Hyperlinks - error "undefined"/ NaN

44 views
Skip to first unread message

cajmcmahon

unread,
May 27, 2015, 8:00:00 AM5/27/15
to d3...@googlegroups.com
Hello,

I'm trying to create a circle pack with hyperlinked circles/nodes. When a reader clicks on one of the circles they will be brought to a webpage giving information about the node.

The format of the hyperlinks are: url + page ID. In reality, http://www.example.com/entityform + entityid.

//Create circles
  node.append("svg:a")
    .attr("xlink:href", function(d) {return "http://www.example.com/entityform/" + d.entityid;})
    .append("circle")
    .attr("r", function(d) { return d.r;
    }) ;

The hover and click works but the ID is not being supplied. I'm getting "undefined", and if I try without the http, I get Localhost/NaN.

I suspect I need an accessor function, but none of the D3 examples I've looked at have anything different from what I'm trying.

I have created a fiddle here: http://jsfiddle.net/cajmcmahon/4fpoqv4n/. I also asked the question on Stackoverflow (with some of the things I've tried), but no solution yet

If anyone can help, I'd be very grateful.

Many thanks,
Colman


Curran

unread,
May 27, 2015, 8:38:51 PM5/27/15
to d3...@googlegroups.com
Hello,

One thing I noticed in your fiddle is that the data array is not in the correct format. You have 

var data = [ 
//Country,Organisation,entity_id
     {EUROPEAN,Org-AA,4},
     {EUROPEAN,Org-BB,5}, ...

This data is not being parsed correctly, and causes the JSFiddle not to work, I get the error "Uncaught SyntaxError: Unexpected token -", due to the dash in Org-AA.

The data objects need to be formatted like this:

var data = [
  {
    Country: "EUROPEAN",
    Organisation: "Org-AA",
    entity_id: 4
  },
  {
    Country: "EUROPEAN",
    Organisation: "Org-BB",
    entity_id: 5
  },...

Also, your fiddle is trying to fetch "data/entityid_test.csv", which doesn't exist on the JSFiddle server.

For debugging, you may want to first check that d.entityid (which is different from d.entity_id) is defined by using console.log, like this:

  node.append("svg:a")
    .attr("xlink:href", function(d) {

      // Print out the value to the JavaScript console for debugging.
      console.log(d.entityid);

      // Try fix by changing d.entityid -> d.entity_id to match the data.
      return "http://www.example.com/entityform/" + d.entity_id;
    })
    .append("circle")
    .attr("r", function(d) { return d.r; }) ;


Here is a working D3 links example that demonstrates dynamically generated href URLs, using the same method that you are using.

Best regards,
Curran

cajmcmahon

unread,
Jun 10, 2015, 3:25:17 PM6/10/15
to d3...@googlegroups.com
I've tried a multitude of things, e.g. for-in loops, but I cannot get the values of "entityid" to pass to "d.entityid". Coming up as "undefined".

In all the other examples I've seen of D3 node hyperlinks, users do not appear to have had to define the d.value in any additional way. I'm completely stumped.

Any insight would be much appreciated.
Updated fiddle at: http://jsfiddle.net/cajmcmahon/4fpoqv4n/67/

Data in form of:
var data = [{
    "Country": "EUROPEAN",
    "entityid": 4,
    "Organisation": "OrgAA"
}, {
    "Country": "EUROPEAN",
    "entityid": 5,
    "Organisation": "OrgBB"
}];


D3 code block:
node.append("svg:a")
        .attr("xlink:href", function (d) {
        return "http://www.example.com/entityform/" + d.entityid;
    })
        .append("circle")
        .attr("r", function (d) {
        return d.r;
    });

Thanks!

Curran Kelleher

unread,
Jun 10, 2015, 5:07:03 PM6/10/15
to d3...@googlegroups.com
Hello,

When your code computes "submissionsByCountry = d3.nest()...", you are losing the entityid property, because it is being aggregated away.

If you inspect the values you have for "d" where you are adding the link, you can see that they look like this

"Object {key: "OrgUU", values: 1, parent: Object, depth: 2, value: 1…}"

because these objects are the result from the circle packing layout, not elements in the original data array.

If there is a 1-1 mapping between Organization and id (which looks to be true in your example data), you can look up the id from the organization. First you can build the lookup table like this:

var idByOrg = {};
data.forEach(function (d) {
    idByOrg[d.Organisation] = d.entityid;
});

Then later access it like this:

//Create nodes/circles
node.append("svg:a")
    .attr("xlink:href", function (d) {
        console.log(d); // Shows {key: "OrgUU", values: 1, parent: Object, depth: 2, value: 1…}
        var entityid = idByOrg[d.key];
        return "http://www.example.com/entityform/" + entityid;
    })
    .append("circle")
    .attr("r", function (d) {
        return d.r;
    });

Now if you inspect the generated URLs, you see things like "http://www.example.com/entityform/10" and "http://www.example.com/entityform/3".


Note that the links only work on leaf nodes in the circle tree. I suppose the next step would be to only include links on the leaf nodes, and not the outer circles.

All the best,
Curran

--
You received this message because you are subscribed to a topic in the Google Groups "d3-js" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/d3-js/ZmbF354QFds/unsubscribe.
To unsubscribe from this group and all its topics, send an email to d3-js+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Colman McMahon

unread,
Jun 11, 2015, 6:25:49 AM6/11/15
to d3...@googlegroups.com
Thank you very much for this! I was on a completely different (and incorrect) track. I'm going to implement now and see how I get on.

Am I right in thinking this is JavaScript programming, rather than specifically D3? And in that vein, where did you get your expertise? I'm coming to D3 from a non-programming background and am wondering how to improve.

Many thanks again!


Colman

Curran Kelleher

unread,
Jun 11, 2015, 2:55:52 PM6/11/15
to d3...@googlegroups.com
Oh yeah I totally understand. These things can be so tricky. I personally went through a university degree program in Computer Science, but I am of the opinion that anyone can learn programming from Web resources and experimentation. I have some screencasts that cover introductory JavaScript and Web programming https://github.com/curran/screencasts .

I still find the nicest way to figure out what's going on is to use console.log() with whatever values you are wondering about. You can put this inside any function. This by itself can be a great learning tool. You can inspect objects and arrays in detail, clicking through arrows to open up their structures. Also you can put "debugger;" on a line by itself, and that will trigger the Chrome debugger to kick in, which is an even more powerful (but perhaps more cumbersome) way to get a view into the program as it is running.

All the best,
Curran

Colman McMahon

unread,
Jun 12, 2015, 7:39:11 AM6/12/15
to d3...@googlegroups.com
Thanks for the information. I've been tinkering with D3 for a while, but it seems to be a two-step- forward, one-step-back process for me. There are so many ways of doing things, it can get a bit confusing at times. The console.log/dir/table is really helpful. It'd be great if it gave JS hints! ;-)

Thanks the link to your screencasts. I'm looking forward to watching them.

I appreciate all your help!


Colman
Reply all
Reply to author
Forward
0 new messages