I have some pretty standard code that creates a bunch of SVG:circles based on node
data and SVG:lines based on link
data.
I want to put some rollover code on the circles and lines such that rolling over a circle highlights that circle, the lines that connect to it, and any other circles at the end of those lines.
The challenge I'm having is getting a reference to the link
data when I'm handling an event triggered by the circle, which only has node
datum attached.
d3nodes = d3svg.selectAll( ".node" )
.data( nodes )
.enter().append( "circle" )
.attr( "class", "node" )
.attr( "r", NODE_RADIUS )
.attr( "cx", function( d ){ return d.x; } )
.attr( "cy", function( d ){ return d.y; } )
.on( "mouseover", function( d ){ console.log( d ); } ); // Node datum
d3links = d3svg.selectAll( ".link" )
.data( links )
.enter().append( "line" )
.attr( "class", "link" )
.attr( "x1", function( d ){ return nodes[d.source].x; } )
.attr( "y1", function( d ){ return nodes[d.source].y; } )
.attr( "x2", function( d ){ return nodes[d.target].x; } )
.attr( "y2", function( d ){ return nodes[d.target].y; } )
.on( "mouseover", function( d ){ console.log( d ); } ); // Link datum
Once I have a reference to links
, I can use the following function to get a list of links where that node is either a source or a target:
/**
* Gets up to 4 nodes, that represent all the nodes linked to this node
* (either as targets or source).
*
* @param {Object} node Object from the "nodes" array (so, the data, not the d3nodes)
* @param {Object[]} links Array of links (again, the data that was passed to the force layout)
* @returns {Array} Matching node objects (again, not DOM elements)
*/
function getLinks( node, links ){
var nodes = [],
i = 0, l = links.length,
link;
for ( ; i < l; ++i ){
link = links[i];
if ( link.target === node ){
nodes.push( link.source );
continue;
}
if ( link.source === node ){
nodes.push( link.target );
}
}
return nodes;
}
But my function really needs a reference to the links
array, and I'm not sure how to get it from within an event handler that only seems to get the node
datum.
I'd like to avoid any kind of global variables, or a global lookup table, since I'm going to have any number of these graphs on a page, and they all need to stay separate.
In the past I've stored a reference to the nodes
, links
and force
objects on the DOM element itself (using jQuery.data()), but is that really a best practice?
I feel like I'm missing an important conceptual point, and hope someone can shed some light.