Moh Za
Moh Za

Reputation: 97

Select the children of a node from a tree in d3.js

I am using the following code here to display data (in JSON format) by the means of a tree, which work correctly. The goal is that whenever the user double clicks on a node that the following things should happen:

The first goal (1) works correctly. To do so I used the code snippets below:

var node = svg.selectAll("g.node")
  .data(nodes, function(d) { return d.id || (d.id = ++i); }, function(d) { return d.isSelected || (d.isSelected = false); });

Every node has a isSelected attribute, which is a sort of a flag. And the color of the node is changed thanks to the next code snippet:

var nodeEnter = node.enter().append("g")
  .attr("class", "node")
  //.attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; })
  .on("click", click)
  .each(function(d)
  {
    var sel = d3.select(this);
    //var state = false;
    sel.on("dblclick", function(e)
    {
        //window.alert("state is: " + state);
        //state = !state;

      if (!e.isSelected) {
        e.isSelected = true;
        d3.select(this).select("circle").style("fill", "black");
        //Select all nodes


        selectSubtree(e);

      } else {
        e.isSelected = false;
        d3.select(this).select("circle").style("fill", "#fff");

        //deselect all nodes


        deselectSubtree(e);

      }
    });
  });

The problem occurs when the 'selected' node is sent to the selectSubtree(d) function. I don't know how to exactly change the color of the node. Can someone help me?

function selectSubtree(node){

if(node.children){

node.children.forEach(function(d)
{
    //Select all children
  d.isSelected = true;

        selectSubtree(d);
});}}

My first attempt was to use d3.select("#id").select("circle").style("fill", "#fff"); , since every node has an id, but it wasn't working correctly.

Upvotes: 1

Views: 2938

Answers (1)

Cyril Cherian
Cyril Cherian

Reputation: 32327

You can do it like this:

STEP 1

Give unique id to all the circle in your case i am setting the circle's id as the name

nodeEnter.append("circle")
  .attr("id", function(d){return d.name})//give ids to circle
      .attr("r", 1e-6);

STEP2

In selectsubtree function make the circle dom fill(with black) by using the id we set in step1

function selectSubtree(node)
{
    d3.select("#" + node.name).style("fill", "black");
     //your code of recursively calling  function if it has children.

STEP3

In deselectSubtree function make the circle dom fill(with white) by using the id we set in step1

function deselectSubtree(node)
{
    d3.select("#" + node.name).style("fill", "white");

working code here

Upvotes: 3

Related Questions