0

I am pretty new to d3. I am using code below to make a network typology of my portfolio projects based on an example in the d3 website. Now i am looking for a way to add a double click event on the circles that opens a new tab and goes to the corresponding url. I have tried these ones but couldn't make it so far.

double click event on node

open new tab after doubleclick on element

any helps are really appreciated.

var links = [
  {source: "Not Another one", target: "Respond", type: "solid", url:'https://www.wikipedia.org/'},
  {source: "Not Another one", target: "Pause", type: "link", url:'https://facebook.com/'},
  {source: "Who Steals Bikes?", target: "Respond", type: "solid", url:'https://www.yahoo.com/'},
  {source: "Who Steals Bikes?", target:  "Pause", type: "link", url:'https://www.google.com/'},
  {source: "Toward a Moving Structure", target: "Respond", type: "link", url:'https://www.github.com/'},
  {source: "Why Tall?", target: "Respond", type: "link", url:'http://www.mahanmehrvarz.name/'}
  ];

var nodes = {};

// Compute the distinct nodes from the links.
links.forEach(function(link) {
  link.source = nodes[link.source] || (nodes[link.source] = {name: link.source});
  link.target = nodes[link.target] || (nodes[link.target] = {name: link.target});
});

var width = 1000,
    height = 600;

var force = d3.layout.force()
    .nodes(d3.values(nodes))
    .links(links)
    .size([width, height])
    .linkDistance(150)
    .charge(-300)
    .on("tick", tick)
    .start();

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);


// Per-type markers, as they don't inherit styles.
svg.append("defs").selectAll("marker")
    .data(["suit", "solid", "link"])
  .append("path")
     .attr("d", "M0,-5L10,0L0,5");

var path = svg.append("g").selectAll("path")
    .data(force.links())
  .enter().append("path")
    .attr("class", function(d) { return "link " + d.type; })
    .attr("marker-end", function(d) { return "url(#" + d.type + ")"; });

var circle = svg.append("g").selectAll("circle")
    .data(force.nodes())
  .enter().append("circle")

    .attr("r", 6)
    .call(force.drag);

var text = svg.append("g").selectAll("text")
    .data(force.nodes())
  .enter().append("text")
    .attr("x", 26)
    .attr("y", ".31em")
    .text(function(d) { return d.name; });

// Use elliptical arc path segments to doubly-encode directionality.
function tick() {
  path.attr("d", linkArc);
  circle.attr("transform", transform);
  text.attr("transform", transform);
}


function linkArc(d) {
  var dx = dx = d.target.x - d.source.x,
      dy = d.target.y - d.source.y,
      dr = 0
  return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
}

function transform(d) {
  return "translate(" + d.x + "," + d.y + ")";
}
Community
  • 1
  • 1
Mahanmeh
  • 89
  • 2
  • 11
  • Possible duplicate of [D3js: how to open new tab after doubleclick on element?](http://stackoverflow.com/questions/25461578/d3js-how-to-open-new-tab-after-doubleclick-on-element) – thatOneGuy Jun 09 '16 at 13:09
  • this example also didn't work in my code! – Mahanmeh Jun 09 '16 at 19:59

1 Answers1

2

I have found this example like you said : D3js: how to open new tab after doubleclick on element?

But the one that helped was this : JavaScript: location.href to open in new window/tab?

Key bit of code :

window.open(
      htmlLinkHere,
      '_blank' // <- This is what makes it open in a new window.
    );

So onclick just do this :

.on('click', function(d) {
    console.log('open tab')
    window.open(
      'http://en.wikipedia.org',
      '_blank' // <- This is what makes it open in a new window.
    );
  });

I have just put a wiki page but in your example that line would use d.url.

EDIT

In simple terms :

 .on('click', function(d) {
        console.log('open tab')
        window.open(
          d.url,
          '_blank' // <- This is what makes it open in a new window.
        );
      });

Check implemented fiddle (click a node to open in new tab) : http://jsfiddle.net/thatOneGuy/0nv4ck58/5/

EDIT

You say you wan't it to work on the nodes, then you have to pass data to the nodes. I.E the nodes have to have URL data. You can do it like so :

links.forEach(function(link) {
  link.source = nodes[link.source] || (nodes[link.source] = {name: link.source, url:link.url});
  link.target = nodes[link.target] || (nodes[link.target] = {name: link.target, url : link.url});
});

However if the node has more than one link then the url's may conflict. Now you have the data just add the click listener to your nodes :

var circle = svg.append("g").selectAll("circle")
    .data(force.nodes())
  .enter().append("circle")
 .on('click', function(d) {
            console.log('open tab')
            window.open(
              d.url,
              '_blank' // <- This is what makes it open in a new window.
            );
          });
Community
  • 1
  • 1
thatOneGuy
  • 9,977
  • 7
  • 48
  • 90
  • than you so much. it was perfect and very clear to me. now by clicking it is opening another tab. but I want it to look at the 'links' dictionary and open the 'url' assosiated with each circle based on the that. in oder words each circle has a different url they're not the same. (I have also edited the code and put different url to be more clear). thank youfor your help – Mahanmeh Jun 09 '16 at 18:41
  • I have already put that in the answer. Just return d.url in the first parameter of window.open – thatOneGuy Jun 10 '16 at 08:49
  • Ok, I thought I am missing something. d.url simply returns a new blank tab. :( – Mahanmeh Jun 10 '16 at 14:24
  • I thin there is a problem in my data structure which causes a blank when i call url. but i have no idea where and how to resolve it. i appreciate your help. – Mahanmeh Jun 10 '16 at 14:45
  • 'ReferenceError: d is not defined' – Mahanmeh Jun 10 '16 at 14:54
  • then you have no data appended. Add you click function to your question, i.e show me where you append the click listener – thatOneGuy Jun 10 '16 at 14:57
  • yeah, i see. i put the url in the first variable in my code 'links'. if you take a look it's the first line. i don't know the next step. – Mahanmeh Jun 10 '16 at 15:01
  • put the second function i have put in my answer after you create the paths, i.e after this line : .attr("marker-end", function(d) { return "url(#" + d.type + ")"; }); – thatOneGuy Jun 10 '16 at 15:04
  • it's working now but obviously i have to click on the path. is there any way to put this event on the circle instead? BTW thank you so much!!! – Mahanmeh Jun 10 '16 at 15:12
  • just put the click event on the circle, youll need to pass your data to it by the looks of it – thatOneGuy Jun 10 '16 at 15:12
  • i am sorry if i seem stupid. you mean i put the function on the circle too? i didn't get it :( – Mahanmeh Jun 10 '16 at 15:18