1

How does one go about displaying the 1st degree neighbors of a selected (and by that i mean hovering over the node) via d3,tip?

Here's my d3.tip portion

var tip = d3.tip()
    .attr('class', 'd3-tip')
    .html(function(d) {return [name of neighbors];});

How would I change the follow to help me return text via my tip rather than changing the opacity?

var linkedByIndex = {};
var toggle = 0;
for (i = 0; i < nodes.length; i++) {
    linkedByIndex[i + "," + i] = 1;
};
links.forEach(function (d) {
    linkedByIndex[d.source.index + "," + d.target.index] = 1;
});

//This function looks up whether a pair are neighbours  
function neighboring(a, b) {
    return linkedByIndex[a.index + "," + b.index];
}

function connectedNodes() {

    if (toggle == 0) {
        //Reduce the opacity of all but the neighbouring nodes
        d = d3.select(this).node().__data__;
        circle.style("opacity", function (o) {
            return neighboring(d, o) | neighboring(o, d) ? 1 : 0.1;
        });

        path.style("opacity", function (o) {
            return d.index==o.source.index | d.index==o.target.index ? 1 : 0.1;
        });

        //Reduce the op

        toggle = 1;
    } else {
        //Put them back to opacity=1
        circle.style("opacity", 1);
        path.style("opacity", 1);
        toggle = 0;
    }}
OmicronAlpha
  • 167
  • 1
  • 2
  • 7

1 Answers1

1

Here's how I would do it with a different force directed graph (should be simple to implement into yours).

I'd run the connectedNodes function when you first run the script, but instead of changing the opacity, I would add neighbours to an array which then gets appended to the data on each node.

Here's a fiddle with the tooltips (on hover) showing all the nodes (node.name) it's connected to : http://jsfiddle.net/reko91/jz2AU/125/

Run the function after you create the nodes :

node.each(function(d) {
  //console.log(d)
  connectedNodes1(this)
})

Here's the changed function :

function connectedNodes1(thisNode) {

  d = d3.select(thisNode).node().__data__;

  var neighbours = [];
  node.each(function(o) {

    // console.log(o)
    if (neighboring(d, o) | neighboring(o, d)) {
      neighbours.push(o.name) //push into array
    }

  });
  d3.select(thisNode).node().__data__.neighboursString =""; //set the attribute to nothing

  for (i = 0; i < neighbours.length; i++) { //go through each element in the array to create one string
    var thisString = neighbours[i] + ' | '; //add a split so it can be easily read
    d3.select(thisNode).node().__data__.neighboursString += (thisString); //concat to attribute
  }
  d3.select(thisNode).node().__data__.neighbours = neighbours; //set neighbours to neighbours array above if you want to use any of the nodes later
}

Notice I made two attributes : neighboursString and neighbours.

-neighboursString : concatenation of all neighbours to create tooltip

-neighbours : array of all neighbour nodes if needed later

Now to create the tooltips (with the help from the second answer here : Show data on mouseover of circle). Obviously, in your case you wont need this so just pass currentNode.neighboursString to d3.tip, should be simple :

var tooltip = d3.select("body")
  .append("div")
  .style("position", "absolute")
  .style("z-index", "10")
  .style("visibility", "hidden")
  .text("a simple tooltip");

Now to show and edit tooltip on hover :

node.on("mouseover", function(d) {
    tooltip.text(d.neighboursString); //set text to neighboursString attr
    return tooltip.style("visibility", "visible");
  })
  .on("mousemove", function(d) {
  tooltip.text(d.neighboursString);
    return tooltip.style("top",
      (d3.event.pageY - 10) + "px").style("left", (d3.event.pageX + 10) + "px");
  })
  .on("mouseout", function() {
    return tooltip.style("visibility", "hidden");
  });

Hope that solves your problem, you can still use the neighbours on double click in the example I have shown :)

Community
  • 1
  • 1
thatOneGuy
  • 9,977
  • 7
  • 48
  • 90