Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Third variable in D3 anonymous function

Tags:

d3.js

Let's say you've got a selection with some data bound to it and you use the typical inline anonymous function to access that data:

 d3.select("#whatever").each(function(d,i,q) {console.log(d,i,q)})

We all know the first variable is the data and the second is the array position. But what does the third variable (q in this case) represent? So far it's always come back zero in everything I've tested.

like image 452
Elijah Avatar asked Dec 07 '13 03:12

Elijah


2 Answers

The secret third argument is only of use when you have nested selections. In these cases, it holds the index of the parent data element. Consider for example this code.

var sel = d3.selectAll("foo")
            .data(data)
            .enter()
            .append("foo");
var subsel = sel.selectAll("bar")
                .data(function(d) { return d; })
                .enter()
                .append("bar");

Assuming that data is a nested structure, you can now do this.

subsel.attr("foobar", function(d, i) { console.log(d, i); });

This, unsurprisingly, will log the data item inside the nesting and its index. But you can also do this.

subsel.attr("foobar", function(d, i, j) { console.log(d, i, j); });

Here d and i still refer to the same things, but j refers to the index of the parent data element, i.e. the index of the foo element.

like image 60
Lars Kotthoff Avatar answered Nov 22 '22 15:11

Lars Kotthoff


A note on Lars's reply, which is correct but I found one more feature that is helpful.

The j element gives the index of the element without regard to the nesting of the parent elements. In other words, if you are appending and logging as follows, the final circles are treated as a flat array, not as a group of nested arrays. So your indexes will be scaled from 0 to the number of circle elements you have, without regard to the data structure of your nesting.

var categorygroups = chart.selectAll('g.categorygroups')
      .data(data)
      .enter()
        .append('g').attr('class','categorygroups');

      var valuesgroups = categorygroups.selectAll('g.valuesgroups')
        .data(function(d) {return d.values; }).enter().append('g').attr('class','valuesgroups');

        valuesgroups.append('text').text(function(d) {
          return d.category
        }).attr('y',function(d,i) { return (i + 1) * 100 }).attr('x',0);

      var circlesgroups = valuesgroups.selectAll('g.circlesgroups')
        .data(function(d) {return d.values; }).enter().append('g').attr('class','circlesgroups');

        circlesgroups.append('circle').style('fill','#666')
        .attr('cy',function(d,i,j) { console.log(j); return (j + 1) * 100 })
        .attr('cx',function(d,i) { return (i + 1) * 40 });
like image 36
Union find Avatar answered Nov 22 '22 14:11

Union find