d3 nested data example I

HTML

<script type="text/javascript" src="http://mbostock.github.com/d3/d3.v2.js"></script>

<div id="container"></div>

JavaScript

var data = {
        segments : [
            {x : 20, size : 10, colors : ['#ff0000','#00ff00']},
            {x : 40, size : 20, colors : ['#0000ff','#000000']}
        ]
    };

    function pos(d,i) { return d.x + (i * d.size); } // rect position
    function size(d,i) { return d.size; }            // rect size
    function f(d,i) { return d.color; }              // rect color

    function flatten(data) {
        // converts the .colors to a ._colors list
        data.segments.forEach( function(s,i) {
            var list = s._colors = s._colors || [];
            s.colors.forEach( function(c,j) {
                var obj = list[j] = list[j] || {}
                obj.color = c
                obj.x = s.x
                obj.size = s.size
            });
        });
    }

    function changeRect(chain) {
        return chain
        .transition()
        .attr('x',pos)
        .attr('y',pos)
        .attr('width',size)
        .attr('height',size)
        .attr('fill',f)
        .style('fill-opacity', 0.5)
    }

    vis = d3
    .select('#container')
    .append('svg')
    .attr('width',200)
    .attr('height',200);

    // add the top-level svg element and size it
    function update(){

        flatten(data);

        // add the nested svg elements
        var all = vis.selectAll('g')
        .data(data.segments)

        all.enter().append('g');
        all.exit().remove();

        // Add a rectangle for each color
        var rect = all.selectAll('rect')
        .data(function (d) { return d._colors; }, function(d){return d.color;})

        changeRect( rect.enter().append('rect') )
        changeRect( rect )

        rect.exit().remove()
    }

    update()
    data.segments[0].x = 60;

    function changeLater(time) {
        setTimeout(function(){
            var ds = data.segments
            ds[0].x    = 10 + Math.random() * 100;
            ds[0].size = 10 + Math.random() * 100;
            ds[1].x    = 10 + Math.random() * 100;
           ...