I am trying to programmatically open d3.js nodes in a collapsible tree:
I load the data with the following d3.js snippet (which collapses the nodes after the second level),
d3.json("js/ontology.json", function(error, treeData) {
if (error) throw error;
root = d3.hierarchy(treeData, function(d) { return d.children; });
root.x0 = height / 2;
root.y0 = 0;
// Collapse after the second level:
root.children.forEach(collapse);
update(root);
});
I then use the following d3.js code
var nodeEnter = node.enter().append('g')
.attr('class', 'node')
.attr('node-name', d => d.data.name.toLowerCase())
.attr("transform", function(d) {
return "translate(" + source.y0 + "," + source.x0 + ")";
})
.on('click', click);
and this function
function expandNode() {
const node = d3.select('.node[node-name="Nature"]').node();
console.log('NODE: ', node);
node.dispatchEvent(new Event('click'));
}
expandNode();
to programmatically open the "Nature" node.
However, when I substitute "Nature" (visible node) with "Earth" (nested child of "Nature", not visible) this expression
const node = d3.select('.node[node-name="Earth"]').node();
will expand the "Earth" node only if it is visible.
That statement will not expand "Nature" to show "Earth" (and subsequently expand "Earth") if "Earth" is not visible.
Suggestions?
Edit 1. This is closely related to my earlier StackOverflow question,
Programmatically opening d3.js v4 collapsible tree nodes?
If needed, please refer to the JSFiddle referenced there,
https://jsfiddle.net/vstuart/acx5zfgn/62/
The labels are different but otherwise the data and code are similar.
Edit 2. Follow-on question
Accessing promised data in d3.js v6 [programmatically opening nested collapsed nodes]
relating to:
ontology.json
{ "name": "Root",
"children": [
{ "name": "Culture",
"children": [
{ "name": "LGBT" }
]
},
{ "name": "Nature",
"id": "nature",
"children": [
{ "name": "Earth",
"id": "earth",
"children": [
{ "name": "Environment" },
{ "name": "Geography" },
{ "name": "Geology" },
{ "name": "Geopolitical" },
{ "name": "Geopolitical - Countries" },
{ "name": "Geopolitical - Countries - Canada" },
{ "name": "Geopolitical - Countries - United States" },
{ "name": "Nature" },
{ "name": "Regions" }
]
},
{ "name": "Cosmos" },
{ "name": "Outer space" }
]
},
{ "name": "Humanities",
"children": [
{ "name": "History" },
{ "name": "Philosophy" },
{ "name": "Philosophy - Theology" }
]
},
{ "name": "Miscellaneous",
"children": [
{ "name": "Wikipedia",
"url": "https://wikipedia.com" },
{ "name": "Example.com",
"url": "https://example.com" }
]
},
{ "name": "Science",
"children": [
{ "name": "Biology" },
{ "name": "Health" },
{ "name": "Health - Medicine" },
{ "name": "Sociology" }
]
},
{ "name": "Technology",
"children": [
{ "name": "Computers" },
{ "name": "Computers - Hardware" },
{ "name": "Computers - Software" },
{ "name": "Computing" },
{ "name": "Computing - Programming" },
{ "name": "Internet" },
{ "name": "Space" },
{ "name": "Transportation" }
]
},
{ "name": "Society",
"children": [
{ "name": "Business" },
{ "name": "Economics" },
{ "name": "Economics - Business" },
{ "name": "Economics - Capitalism" },
{ "name": "Economics - Commerce" },
{ "name": "Economics - Finance" },
{ "name": "Politics" },
{ "name": "Public services" }
]
}
]
}
You need to discover the node ancestors recursively and then expand them on by one:
const findNodeAncestors = (root, name) => {
if (root.name === name) {
return [name];
}
if (root.children) {
for (let i = 0; i < root.children.length; i++) {
const chain = findNodeAncestors(root.children[i], name);
if (chain) {
chain.push(root.name);
return chain;
}
}
}
return null;
};
const chain = findNodeAncestors(treeData.data, 'Earth');
for (let i = chain.length - 1; i >= 0; i--) {
const node = d3.select(`.node[node-name="${chain[i]}"]`);
const nodeData = node.datum();
if (!nodeData.children && nodeData.data.children) { // Node has children and collapsed
node.node().dispatchEvent(new Event('click')); // Expand the node
}
}
See it's working in a fiddle .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.