Jugal Patel
Jugal Patel

Reputation: 43

d3 force nodes toggle

I'm trying to write a click, toggle function on the nodes in a d3 force layout and haven't been anything that helps me figure out how to get this working. The idea is that when you click on a node, an svg appears from the left side of the screen, and when you click again, it disappears. Here is the code that I'm trying on it without any luck:

    var tooltip = svg.append("rect")
            .attr("x", -300)
            .attr("y", 0)
            .attr("width", 300)
            .attr("height", height)
            .attr("color", "black")
            .attr("opacity", 0.8);
    
    var toggleWindow = (function () {
        var currentStatus = -300;
        
        return function () {
            currentStatus = currentStatus === -300 ? 0 : -300;
            d3.select(tooltip).attr("x", currentStatus);
        };
    })();
    
    var node = svg.selectAll(".node")
            .data(json.nodes)
            .enter().append("g")
            .on("mouseover", mouseover)
            .on("mouseout", mouseout)
            .on("click", toggleWindow)
            .call(force.drag);

And here's a link to the full code: http://plnkr.co/edit/nwmUN4RzAwam9dE5bCEj?p=preview

Upvotes: 1

Views: 754

Answers (2)

Cyril Cherian
Cyril Cherian

Reputation: 32327

This is how you do it. First make a tooltip group.

  var tooltip = svg.append("g").attr("transform", "translate(-300,0)");
  //add rectangle to the group
  tooltip.append("rect")
    .attr("x", 0)
    .attr("y", 0)
    .attr("width", 300)
    .attr("height", height)
    .attr("color", "black")
    .attr("opacity", 0.8);

On node click

var node = svg.selectAll(".node")
    .data(json.nodes)
    .enter().append("g")
    .on("mouseover", mouseover)
    .on("mouseout", mouseout)
    .on("click", function(d) {
      if (tooltip.data && d.name == tooltip.data.name) {
        //if clicked on the same node again close
        tooltip.classed("open", false);
        tooltip
          .transition()
          .attr("transform", "translate(-300,0)")//slide via translate
          .duration(1000);
        tooltip.data = undefined;//set the data to be undefined since the tooltip is closed
        return;
      }
      tooltip.data = d;//set the data to the opened node
      tooltip.classed("open", true);//set the class as open since the tooltip is opened
      tooltip
        .transition()
        .attr("transform", "translate(0,0)")
        .duration(1000);
      d3.selectAll(".text-tip").remove();  //remove old text
      tooltip.append("text")//set the value to the text
      .attr("transform", "translate(10,100)")
      .attr("class","text-tip").text(d.name);

    })

Working example here.

Upvotes: 1

Vanshaj Rai
Vanshaj Rai

Reputation: 117

Simply you can add :

Need to define :

var COLLAPSE_LEVEL = 1

And use the below code :

 function toggleAll(d) {
            if (d.children) {
                d.children.forEach(toggleAll);
                if (d.level < COLLAPSE_LEVEL) {
                    return;
                }
                toggle(d);
            }
        }

 function toggle(d) {
        if (d.children) {
            d._children = d.children;
            d.children= null;
        } else {
            d.children= d._children;
            d._children = null;
        }
    }

Upvotes: 0

Related Questions