Closed RaphCodec closed 7 months ago
That's not as easy as it sounds
if you want to hide, but they still take the space, then you can just check if it's highlighted, set zero opacity or something, otherwise don't do anything
If you want them to be completelly removed, you have to manipulate the data, pass new data and rerender graph
Ok. I will try that. Thanks for the help, the library is great.
I found a way to do it. I have the fololowing functions that find the children and ancestors in the data and remove them. I tried getNodeChildren but kept running into an error saying "Uncaught TypeError: Cannot read properties of undefined (reading 'push')". Not sure if I was doing something wrong. Anyay the way I did it was using the following.
function findChildren(parent, selected) {
for (const item of data) {
if (item.parentId === parent) {
selected.push(item.name);
findChildren(item.id, selected);
}
}
}
function findAncestorsLineage(nodeId, selected) {
for (const item of data) {
if (item.id === nodeId) {
// Found the current node, add its parent to selected
const parentId = item.parentId;
if (parentId) {
selected.push(parentId);
// Recursively find ancestors of the parent
findAncestorsLineage(parentId, selected);
}
break; // Stop searching once we reach the root node (parent ID is null or undefined)
}
}
}
function findChildrenLineage(parentId, selected) {
for (const item of data) {
if (item.parentId === parentId) {
// Found a child node, add its ID to selected
selected.push(item.id);
// Recursively find children of the current child
findChildrenLineage(item.id, selected);
}
}
}
//Removes all currenlty selected nodes
function removeNodes() {
currentlySelected = [...new Set(currentlySelected)]
for ( id in currentlySelected) {
chart.removeNode(currentlySelected[id])
}
to_pop = [];
for (const id of currentlySelected) {
to_pop.push(data.filter(item => item.id === id)[0].name)
findChildren(id, to_pop)
}
for (person in to_pop) {
names.pop(person)
}
to_pop = []
currentlySelected = []
}
function showLineage() {
currentlySelected = [...new Set(currentlySelected)]; //making sure all values in array are unique
// Check if the array is empty or has more than one element
if (currentlySelected.length === 0 || currentlySelected.length > 1) {
// Display an alert if the array is empty or has more than one element
alert("Please select one person. There may only be one person selected at a time.");
} else {
to_keep = []
for (const id of currentlySelected) {
to_keep.push(data.filter(item => item.id === id)[0].id)
findChildrenLineage(id, to_keep)
}
for (const id of currentlySelected) {
to_keep.push(data.filter(item => item.id === id)[0].id)
findAncestorsLineage(id, to_keep)
}
to_keep = [...new Set(to_keep)];
currentlySelected = data
.filter(obj => !to_keep.includes(obj.id)) // Filter out IDs present in to_keep
.map(obj => obj.id);
removeNodes()
to_keep = []
}
}
Those delete all nodes not in the lineage so that the tree looks more clean. I ended up not needing to add nodes back so didn't solve that part. Only issue is that the console logs ids that are not in the tree since their parent is removed but the id is still in the loop. other than that it works as I want it to, in case anyone else wants to do something similiar. Thanks again.
Looking at the futuristic example I see that the mark root botton hides all unhiglighted nodes. Is there a way to easily modify this function to temporarily remove all unhighlighed nodes? My goal is to make a straigt line of the people highlighted, whereas that fucntion currently leaves people in their current postition. I kow an important part of the functionality has to do with the code below. Please let me know if any clarification is needed.