Reusable Bar Charts

Here's a sweet ass example of bar charts in a really reusable form.

HTML

<div id="svg_canvas"></div>

CSS

/* Styles go here */
.bar
{
  fill : steelblue;
}

.bar-text
{
  text-anchor: middle;
}

JavaScript

function BarChart(config)
{
  var margins  = {top : 20, right : 10, bottom : 10, left : 25};
  var xScale, yScale;
  
  function chart(selection)
  {
    createSVGCanvas(selection)// <----  Works
    //selection.call(createSVGCanvas) // <----  Doesn't Work
      .call(calculateScales) 
      .call(dataLayer)
    
    return this;
  }
  
  function createSVGCanvas(selection)
  {
    //This properly returns an svg element, but in the broken version
    // the next .call'd function, has a selection of the
    // div#svg_canvas.
    return selection.append("svg")
            .attr("width", config.width)
            .attr("height", config.height);
  }
  
  function calculateScales(selection)
  {
    // in the broken version, the selection
    // is of the div#svg_canvas NOT the svg.
    var data = selection[0][0].__data__;
    
    var xDomain = d3.range(0, data.length);
    var yDomain = [d3.max(data) + 1, d3.min(data) - 1];
    
    var xRange  = [margins.left, config.width  - margins.right];
    
    var yRange  = [margins.top,  config.height - margins.bottom];
    
    xScale = d3.scale.ordinal().domain(xDomain).rangeRoundBands(xRange, .3, .3);
    yScale = d3.scale.linear().domain(yDomain).range(yRange);
    
    return selection;
  }
  
  function dataLayer(selection)
  {
    var barGrouping = selection.append("g").attr("id", "data_layer");
    
    var bars = barGrouping.selectAll("rect")
      .data(function(datum){return datum})
      .enter()
      .append("rect")
        .attr("class", "bar")
        .attr("id", function(datum, index) { return "bar-" + index;})
        .attr("width", xScale.rangeBand()) 
        .attr("height", function(datum){return yScale.range()[1] - yScale(datum);})
        .attr("x",      function(datum, index){return xScale(index);})
        .attr("y",      function(datum){return  yScale(datum) ;});
    
    return selection;
  }

  return chart;...