Reputation: 77
I am having difficulties with the filter that I am trying to use on my force directed graph. I can filter out nodes, but cannot make associated links disappear. My knowledge of JavaScript is pretty limited, but I guess the logic should be: if node is hidden, then hide associated links. Am I on the right path? If someone could help me with it, it would be much appreciated!
Data format:
{
"nodes": [
{"name":"AA1","group":"Group1","type":"a"},
{"name":"AA2","group":"Group2","type":"b"},
{"name":"AA3","group":"Group3","type":"c"},
{"name":"AA4","group":"Group4","type":"a"},
{"name":"AA5","group":"Group2","type":"b"},
{"name":"AA6","group":"Group4","type":"c"},...
],
"links": [
{"source":1,"target":59,"value":1},
{"source":1,"target":88,"value":1},
{"source":3,"target":12,"value":1},
{"source":3,"target":16,"value":1},
{"source":3,"target":87,"value":1},
{"source":5,"target":3,"value":1},
{"source":5,"target":16,"value":1},
{"source":5,"target":114,"value":1},... ]
FILTER CODE:
// call method to create filter
createFilter();
// method to create filter
function createFilter()
{
d3.select(".filterContainer").selectAll("div")
.data(["a", "b", "c"])
.enter()
.append("div")
.attr("class", "checkbox-container")
.append("label")
.each(function(d) {
// create checkbox for each data
d3.select(this).append("input")
.attr("type", "checkbox")
.attr("id", function(d) {return "chk_" + d;})
.attr("checked", true)
.on("click", function(d, i) {
// register on click event
var lVisibility = this.checked? "visible":"hidden";
filterGraph(d, lVisibility);
})
d3.select(this).append("span")
.text(function(d){return d;});
});
$("#sidebar").show(); // show sidebar
}
// Method to filter graph
function filterGraph(aType, aVisibility)
{
// change the visibility of the node
node.style("visibility", function(o) {
var lOriginalVisibility = $(this).css("visibility");
return o.type === aType ? aVisibility : lOriginalVisibility;
});
/////////////////////////////////////// NEEDED CODE TO HIDE LINKS //////////////////////////////////////
}
Upvotes: 1
Views: 1748
Reputation: 1447
You need to hide the link by checking if either its source or target is not selected. So in your filterGraph part, add something like (suppose your links have class="link"):
positive = ["Dahlia", "Tholomyes"];
link.attr("display", function (o) {
////Here the structure of the the link can vary, sometimes it is o["source"]["name"], sometimes it is o["source"]["name"], check it out before you fill in.
var source_name = o["source"]["id"];
var target_name = o["target"]["id"];
var result = positive.indexOf(source_name) != -1 && positive.indexOf(target_name) != -1 ? "auto" : "none"
return result;
});
Take Mike Bostock's miserable for instance, I have used the code above to filter out all the others except the one that connects "Dahlia" and "Tholomyes".
Here is the snippet for your jsfiddle example:
var hidden_nodes =[];
// Method to filter graph
function filterGraph(aType, aVisibility)
{
// change the visibility of the node
// if all the links with that node are invisibile, the node should also be invisible
// otherwise if any link related to that node is visibile, the node should be visible
// change the visibility of the connection link
node.style("visibility", function(o) {
var lOriginalVisibility = $(this).css("visibility");
if (o.type == aType) {
if (aVisibility == "hidden")
{
hidden_nodes.push(o.name);
}
else
{
index = hidden_nodes.indexOf(o.name);
if (index > -1)
{
hidden_nodes.splice(index, 1);
}
}
}
return o.type === aType ? aVisibility : lOriginalVisibility;
});
link.attr("display", function (o) {
////Here the structure of the the link can vary, sometimes it is o["source"]["name"], sometimes it is o["source"]["name"], check it out before you fill in.
var source_name = o["source"]["name"];
var target_name = o["target"]["name"];
var result = hidden_nodes.indexOf(source_name) != -1 || hidden_nodes.indexOf(target_name) != -1 ? "none" : "auto"
return result;
});
}
Upvotes: 2