Hide unrelated parent nodes but child node in D3.js
I am trying to do this in D3.js but cannot find a way to do it.
What I want to do is when a person clicks on the root node (level 0), it should show the children (level 1). When a person clicks on one of the child nodes (level 1), they should show their children (level 2) and parent and parent (level 1, this is what the user clicked on), but hide all unrelated parents (from level 1).
Let me explain it to you with pictures.
source to share
You can do something like http://bl.ocks.org/benlyall/4fea200ebebb273aa4df
I forked http://bl.ocks.org/mbostock/4339083 and made a few changes:
-
Added a new property for each node
.all_children
that keeps track of all children. We need this or something similar since it.children
contains the currently rendered child nodes and is._children
used by existing code to determine if a node contains children or not (and sets the style accordingly).Also added a property
.hidden
to help determine if node should be rendered.They are added after loading the data:
d3.json("flare.json", function(error, flare) { root = flare; root.x0 = height / 2; root.y0 = 0; function collapse(d) { if (d.children) { d.all_children = d.children; d._children = d.children; d._children.forEach(collapse); d.children = null; d.hidden = true; } } root.all_children = root.children; root.children.forEach(collapse); root.children.forEach(function(d) { d.hidden = false; }); root.hidden = false; update(root); });
-
Updated the function
update
to reflect the new changes and only draw the nodes to be drawn:function update(source) { // Compute the new tree layout. var nodes = tree.nodes(root).filter(function(d) { return !d.hidden; }).reverse(), links = tree.links(nodes);
nodes
Only those nodes that are NOT hidden are set in the variable . -
Updated handler
click
to correctly set the state of the nodes on the display:// Toggle children on click. function click(d) { if (d.children) { d._children = d.children; d.children = null; if (d._children) { d._children.forEach(function(n) { n.hidden = true; }); if (d.parent) { d.parent.children = d.parent.all_children; d.parent.children.forEach(function(n) { n.hidden = false; }); } } } else { d.children = d._children; d._children = null; if (d.children) { d.children.forEach(function(n) { n.hidden = false; }); if (d.parent) { d.parent.children = [d,]; d.parent.children.filter(function(n) { return n !== d; }).forEach(function(n) { n.hidden = true; }); } } } update(d); }
The first part of the statement
if
is called when we collapse a node, in which case we need to display all the siblings of the clicked node by settingd.parent.children
tod.parent.all_children
and setting each of those nodes to.hidden = false
. And we need to hide all children of the clicked node by settingd.children = null
and then hiding all the node ind._children
.The second part of the statement
if
is called when we expand the node, in which case we need to hide our siblings (set.hidden
totrue
) and update the.children
property of the clicked node.parent
node so that only the clicked node is listed as a child.
source to share