D3 - Collapsible Force Layout modification


First of all, I'm new to d3.js and I'm amazed with this and what it is possible to do. Saying that, sorry by my "noobish".

I'm struggling with the d3 Collapsible Force Layout scheme to do something a little bit different. Here is the original one: http://mbostock.github.com/d3/talk/20111116/force-collapsible.html:

enter image description here

  1. Get the size of the elements, before collapse them, based on its childnodes. So the idea is increase the size of the element based on the size of its children nodes. In the original example, the size is based directly from the fields inside each childnode.
  2. Get the layout fixed, as it is on final of its translation mode (not show that fuzzy action until become static).
  3. Show ONLY the nodes that have some "alert":1 (like {"name": "AgglomerativeCluster", "size": 3938, "alert":1}), information in the childnode field. Like the whole graph becomes uncollapsed after reload the info, and only if some child have the alert="1" info added, shows its path from the root to the leaf, and all others become closed, making possible to click and open the other leafes as well.

----SOLVED 4. Open a window in a fixed area (like on top right of the schema), to show aditional information that will be available inside of each node field, after click on them. -----SOLVED

Here is the code so far:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
    <link type="text/css" rel="stylesheet" href="css/style.css"/>
    <script type="text/javascript" src="d3/d3.js"></script>
    <script type="text/javascript" src="d3/d3.geom.js"></script>
    <script type="text/javascript" src="d3/d3.layout.js"></script>
    <style type="text/css">

        circle.node {
            cursor: pointer;
            stroke: #000;
            stroke-width: .5px;

        }
        .node text {
            font: 12px sans-serif;
            pointer-events: none;
            font-weight: bold;
        }
        line.link {
            fill: none;
            stroke: #9ecae1;
            stroke-width: 1.5px;
        }

    </style>
</head>
<body>



<script type="text/javascript">

    var w = 1280,
        h = 800,
        root;

    var force = d3.layout.force()
            .linkDistance(80)
            .charge(-270)
            .gravity(.01)
            .size([w, h]);

    var vis = d3.select("body")
            .append("svg:svg")
            .attr("width", w)
            .attr("height", h)
            .attr("pointer-events", "all")
            .append('svg:g')
            .call(d3.behavior.zoom().on("zoom", redraw))
            .append('svg:g');

    vis.append('svg:rect')
            .attr('width', w)
            .attr('height', h)
            .attr('fill', 'rgba(255,255,255,255)')




    //setInterval(function(){
    d3.json("mbostock.github.io/d3/talk/20111116/flare.json", function(json) {
        root = json;
        root.fixed=true;
        root.x = w / 2;
        root.y = h / 2 - 50;
        update();
    });
  //  },10000);
    function redraw() {
        console.log("here", d3.event.translate, d3.event.scale);
        vis.attr("transform","translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")");

    }
    function update() {
        var nodes = flatten(root),
                links = d3.layout.tree().links(nodes);


        // Restart the force layout.
        force
                .nodes(nodes)
                .links(links)
                .start();


        // Update the links…
        var link = vis.selectAll("line.link")
                .data(links, function(d) { return d.target.id; });

        // Enter any new links.
        link.enter().insert("svg:line", ".node")
                .attr("class", "link")
                .attr("x1", function(d) { return d.source.x; })
                .attr("y1", function(d) { return d.source.y; })
                .attr("x2", function(d) { return d.target.x; })
                .attr("y2", function(d) { return d.target.y; });

        // Exit any old links.
        link.exit().remove();

        // Update the nodes…
        var node = vis.selectAll("g.node")
                .data(nodes, function(d) { return d.id; })


        node.select("circle")
                .style("fill", color);




        // Enter any new nodes.
        var nodeEnter = node.enter().append("svg:g")
                .attr("class", "node")
                .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
                .on("click", click)
                .call(force.drag);

        nodeEnter.append("svg:circle")
             //   .attr("r", function(d) {if(d.weight <3){return 20}else{return d.children .weight*1.5 || 20; }})
               // .attr("r", function(d) { return  d.weight>1 ? d.weight :  d.weight; })
                .attr("r", function(d) { return 20|| 20; })

        //.attr("r", function(d) { return  d.name.length || 20; })
                //.attr("r", function(d) { return  node.selectAll(this.children).length; })
                //.attr("r", function(d) { return  node.index*10; })

                .style("stroke","#c0c0c0")
                .style("fill", color);

        nodeEnter.append("svg:text")
                .attr("text-anchor", "middle")
                .attr("dy", ".35em")
                .text(function(d) { return d.name; });
                //.text(function(d) { return d.distance(); });

        // Exit any old nodes.
        node.exit().remove();


        // Re-select for update.
        link = vis.selectAll("line.link");
        node = vis.selectAll("g.node");

        force.on("tick", function() {
            link.attr("x1", function(d) { return d.source.x; })
                    .attr("y1", function(d) { return d.source.y; })
                    .attr("x2", function(d) { return d.target.x; })
                    .attr("y2", function(d) { return d.target.y; });
            node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });

        });
        //force.stop();

    }

    // Color leaf nodes orange, and packages white or blue.
    function color(d) {
        if(d.alert==1){
            return "red";
        }
        return d._children ? "#3182bd" : d.children ? "#c6dbef" : "#fd8d3c";
    }

    // Toggle children on click.
    function click(d) {
        if (d.children) {
            d._children = d.children;
            d.children = null;
        } else {
            d.children = d._children;
            d._children = null;
        }
        update();
    }

    // Returns a list of all nodes under the root.
    function flatten(root) {
        var nodes = [], i = 0;

        function recurse(node) {
            if (node.children) node.children.forEach(recurse);
            if (!node.id) node.id = ++i;
            nodes.push(node);
        }

        recurse(root);
        return nodes;

    }

</script>
</body>
</html>

Can anyone please help me?


Answers: