nested selection example

HTML

<script src="http://d3js.org/d3.v3.js"></script>
<div id="container"></div>
<button id="update">Update</button>

CSS

body { font: 10px sans-serif; }
svg { background: white; }

JavaScript

var data = [];

//consts
var boxDim = 10;
var boxMargin = 1;
var span = boxDim + boxMargin;
var margin = { top: 10, right: 10, bottom: 10, left: 50 };
var colorScale = d3.scale.linear().domain([0, 10]).range(["#ccc", "#0f0"]);
var svg = d3.select("body").append("svg");

var redraw = function(){
    var series = svg.selectAll("g.row").data(data, function(d) { return d.key; });

    /*
     * This section handles the "enter" for each row
     */
    // Adding a g element to wrap the svg elements of each row
    var seriesEnter = series.enter().append("g");
    seriesEnter
        .attr("class", "row")
        .attr("transform", function(d, i){ 
            return "translate(" + margin.left + "," + (margin.top + (span*i)) + ")"; 
        })
        .attr("opacity", 0).transition().duration(500).attr("opacity", 1);

    // Adding a text label for each series
    seriesEnter.append("text")
		.style("text-anchor", "end")
		.attr("x", -6)
		.attr("y", boxMargin + (boxDim/2))
		.attr("dy", ".32em")
		.text(function(d){ return d.key; });

    // nested selection for the rects associated with each row    
    var seriesEnterRect = seriesEnter.selectAll("rect").data(function(d){ return d.values; });

    // rect enter. don't need to worry about updates/exit when a row is added
	seriesEnterRect.enter().append("rect")
        .attr("fill", function(d){ return colorScale(d)})
		.attr("x", function(d, i){ return i*span + boxMargin; })
		.attr("y", boxMargin)
		.attr("height", boxDim)
        .attr("width", boxDim);
    
    /*
     * This section handles updates to each row
     */
    var seriesUpdateRect = series.selectAll("rect").data(function(d){ return d.values});

    // rect update    
	seriesUpdateRect.transition().duration(500)
        .attr("fill", function(d){ return colorScale(d)});
    
    // rect enter
	seriesUpdateRect.enter().append("rect")
        .attr("fill", function(d){ return colorScale(d)})
		.attr("x", function(d, i){ return i*span + boxMargin;...