title: D3 bar chart not working properly with all negative and positive values
body: <p>I need to create bar chart with the help of d3 with positive and negative values. Chart working fine with combination of positive and negative values but if I pass only negative or positive values the X-axis is not coming at proper place. Thanks</p>
  
  <p><a href="http://jsfiddle.net/Mohit_Agrawal/fjuak9bo/7/" rel="nofollow">Jsfiddle</a></p>
  
  <p><a href="http://i.stack.imgur.com/TmEyG.png" rel="nofollow">BarChart Image</a></p>
  
  <pre><code>//var data = [["Since Mar 10, 2015",150], ["1 year",-100], ["3 year",6.9], ["Since Mar 10, 2010",100]];
  
  var data = [["Since Mar 10, 2015",-100], ["1 year",-10]];
  
  d3.select("#example")
  .datum(data)
  .call(columnChart()
    .width(320)
    .height(240)
    .x(function(d, i) { return d[0]; })
    .y(function(d, i) { return d[1]; }));
  
  function columnChart() {
    var margin = {top: 30, right: 10, bottom: 50, left: 50},
    width = 20,
    height = 20,
    xRoundBands = 0.6,
    xValue = function(d) { return d[0]; },
    yValue = function(d) { return d[1]; },
    xScale = d3.scale.ordinal(),
    yScale = d3.scale.linear(),
    yAxis = d3.svg.axis().scale(yScale).orient("left"),
    xAxis = d3.svg.axis().scale(xScale);
    var isNegative = false;    
  
   function chart(selection) {
     selection.each(function(data) {
  
     // Convert data to standard representation greedily;
     // this is needed for nondeterministic accessors.
    for(var i=0; i&lt; data.length; i++){
       if(data[i][1] &lt; 0){
         isNegative = true;
      }
    }  
  
    data = data.map(function(d, i) {
      return [xValue.call(data, d, i), yValue.call(data, d, i)];
    });
  
    // Update the x-scale.
    xScale
        .domain(data.map(function(d) { return d[0];} ))
        .rangeRoundBands([0, width - margin.left - margin.right], xRoundBands);
  
    // Update the y-scale.
    if( data.length &lt; 2 ){
       if( data.map(function(d) { return d[1];} ) &lt; 0){
           yScale
            .domain([data.map(function(d) { return d[1];} ), 0])
            .range([height - margin.top - margin.bottom, 0])
            .nice();         
       }else{
           yScale
            .domain([0, data.map(function(d) { return d[1];} )])
            .range([height - margin.top - margin.bottom, 0])
            .nice();
       }
    }else{
        yScale
            .domain(d3.extent(data.map(function(d) { return d[1];} )))
            .range([height - margin.top - margin.bottom, 0])
            .nice();
    }
  
      // Select the svg element, if it exists.
    var svg = d3.select(this).selectAll("svg").data([data]);
  
    // Otherwise, create the skeletal chart.
    var gEnter = svg.enter().append("svg").append("g");
  
    gEnter.append("g").attr("class", "y axis");
    gEnter.append("g").attr("class", "x axis");
    gEnter.append("g").attr("class", "x axis zero");
  
    // Update the outer dimensions.
    svg .attr("width", width)
        .attr("height", height);
  
    // Update the inner dimensions.
    var g = svg.select("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
  
      // Update the y-axis.
       g.select(".y.axis")
          .call(yAxis.tickSize(0).ticks(5))
          .selectAll("g")
          .selectAll("text")
          .text(function(d){
              return d+"%";
          });
  
      g.append("g")
          .selectAll("line.line")
          .data(yScale.ticks(5))
          .enter()
          .append("line")
           .attr(
              {
                  "class":"line grid tick",
                  "x1" : 0,
                  "x2" : ( width - 60 ),
                  "y1" : function(d){ return yScale(d);},
                  "y2" : function(d){ return yScale(d);},
              });
      gEnter.append("g").attr("class", "bars");
  
      // Update the bars.
      var bar = g.select(".bars")
      .selectAll(".bar")
      .data(data);
  
      bar.enter().append("rect");
      bar.exit().remove();
      bar .attr("class", function(d, i) { return d[1] &lt; 0 ? "bar negative" :   "bar positive"; })
        .attr("x", function(d) { return X(d); })
        .attr("y", function(d, i) { return d[1] &lt; 0 ? Y0() : Y(d); })
        .attr("width", xScale.rangeBand())
        .attr("height", function(d, i) { return Math.abs( Y(d) - Y0() ); });
  
    // x axis at the bottom of the chart
    if( isNegative === true ){
      var xScaleHeight = height - margin.top - margin.bottom+12;
    }else{
      var xScaleHeight = height - margin.top - margin.bottom;
   }        
    g.select(".x.axis")
      .attr("transform", "translate(0," + ( xScaleHeight ) + ")")
      .call(xAxis.orient("bottom"))
      .selectAll("text")
      .call(wrap, xScale.rangeBand());
  
    // zero line
    g.select(".x.axis.zero")
      .attr("transform", "translate(0," + Y0() + ")")
      .attr("class", "zero axis")
      .call(xAxis.tickFormat("").tickSize(0));
  
  
     // Update the text in bars.
     var bar1 = svg.select(".bars").selectAll("text").data(data);
  
     bar1 .data(data)
         .enter()
         .append("text")
         .attr("class", "text")
         .text(function(d) { return d[1]+"%"; })
         .attr("x", function(d) { return X(d); })
         .attr("y", function(d, i) { return d[1] &lt; 0 ? Math.abs(Y(d)+10) : Y(d)-2; });
  });
  </code></pre>
  
  <p>}</p>
  
  <pre><code>  // Custom function for text wrap
     function wrap(text, width) {
       text.each(function() {
       var text = d3.select(this),
       words = text.text().split(/\s+/).reverse(),
       word,
       line = [],
       lineNumber = 0,
       lineHeight = 1, // ems
       y = text.attr("y"),
       dy = parseFloat(text.attr("dy")),
       tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em");
     while (word = words.pop()) {
     line.push(word);
     tspan.text(line.join(" "));
     if (tspan.node().getComputedTextLength() &gt; 55) {
       line.pop();
       tspan.text(line.join(" "));
       line = [word];
       tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
     }
   }
  </code></pre>
  
  <p>});
   }</p>
  
  <pre><code> // The x-accessor for the path generator; xScale ∘ xValue.
    function X(d) {
    return xScale(d[0]);
   }
  
   function Y0() {
    return yScale(0);
   }
  
   // The x-accessor for the path generator; yScale ∘ yValue.
   function Y(d) {
    return yScale(d[1]);
   }
  
   chart.margin = function(_) {
    if (!arguments.length) return margin;
     margin = _;
     return chart;
    };
  
   chart.width = function(_) {
     if (!arguments.length) return width;
      width = _;
      return chart;
    };
  
    chart.height = function(_) {
      if (!arguments.length) return height;
       height = _;
       return chart;
     };
  
    chart.x = function(_) {
     if (!arguments.length) return xValue;
      xValue = _;
      return chart;
     };
  
     chart.y = function(_) {
      if (!arguments.length) return yValue;
        yValue = _;
        return chart;
      };
  
     return chart;
  }
  </code></pre>