UPDATE: Here I created a JSFiddle . Send the updated script with your answer.
I have dynamic filters that the user can apply to the data, but they change the opacity of the nodes to indicate what is filtered in and out (the elements filtered "out" are still partially visible, and the actual function d3 filter() not used (intentionally) ) I also set a property for each node that is being filtered out (for example, node = {"name": "test", "isFilteredOut": true}; ). So, for the purposes of this question, although I use the word “filter”, this is really just a conditional style change (and I will try to put the word “filter” in quotation marks in this post as a reminder of this).
All this works fine, but now I want to recursively "filter out" all the child nodes and edges of the "filtered" nodes, as well as the edge connecting the original "filtered" node to the filtered parent node.
All the examples that I can find start with a click event and thus allow this to be used to get the data for the starting node. I do not have this luxury , because the filter is applied using a user interface element that is not inside the graph itself.
I am now filtering such nodes:
node.style("opacity", function(n) { if (my_filter_conditions) { return 1; } else { n.isFilteredOut = true; return 0.1; } });
I need to do the following:
Recursively select all the child nodes of the currently “filtered” nodes and “filter” them as well (ie, change their opacity to 0.1 and set n.isFilteredOut = true; ).
Change the opacity of all the edges to 0.1, where the source node or target node is “filtered” (ie n.isFilteredOut = true; at each end of the edge)
What i tried
I do not know how to access the data of the source and target nodes, considering only the index of each of the edges (remember that I do not have this node to start with a click event). I tried passing the node index obtained from the edge to get the node data with:
var node_data = d3.select(current_edge.source.index).datum();
However, this led to the d3 library errors related to this.node() being empty (therefore, index transfer did not work here).
I also tried to process the edges by nesting the function to handle the links inside the function passed to the node.style() function, but then it tries to figure out all the edges on each node, and I cannot get it to provide the desired result.
link.style("opacity", function (e) { return ( (n.isFilteredOut) && (n.index==e.source.index | n.index==e.target.index) ) ? 0.1 : 1; });
It was my attempt to “filter” the edges on both sides of the “filtered” nodes, but none of the edges ever filtered out when I used this for some reason (it seemed like nothing happened at all).
UPDATE: Here I created a JSFiddle .
Script Notes:
- I know that it is simplified (it should be a minimal working example)
- The actual application contains filters that are applied within the types (even if you are just looking for a specific device / part / etc.), so it is important that the logic can conditionally follow the "chain" only for those nodes,
node.isFilteredOut = true; - In this example, the correct answer will lead to a situation where the filtering devices will also filter out all parts
- Solutions that do some sort of filtering using a
dataSet will not work, because most of my data is dynamically populated from different JSON sources. Feel free to work with nodes , edges , links , node and / or link . - Please do not rewrite my filtering methodology. Yes, I know that
eval() expressions are small. But this is not a question of how to best apply infinite conjunctive filters, but also of a recursive change in the opacity of nodes and edges based on the applied filters.