codeonthebeach
codeonthebeach

Reputation: 9

Understanding D3 with an example - Mouseover, Mouseup with multiple arguments

I am reading the code from http://bl.ocks.org/diethardsteiner/3287802

But I dont understand why and how the mouse-up piece of code works:

   var arcs = vis.selectAll("g.slice")
     .data(pie)
     .enter()
     .append("svg:g")
     .attr("class", "slice")
     .on("mouseover", mouseover)
     .on("mouseout", mouseout)
     .on("click", up)
     ;

    ...

    function up(d, i) {
       updateBarChart(d.data.category, color(i));
       updateLineChart(d.data.category, color(i));   
    }

I can see that "up" is a mouse-event handler, but what are the "d" and "i" here?

I mean, how does it know what variable it need to pass on as the function Argument when we are calling "on("click", up)? It seems that "d" and "i" are refering to the data associated with "g.slice" and its index, but istn't a mouse-up Event handle supposed to take an Event object as Default Argument?

Moreover, regarding the "d.data.category", I dont see any data of such structure in the code, although there is a dataset variable declared. But how come that "d.data" would refer to the data of a Person in the dataset?

Thank you guys!!!

Upvotes: 0

Views: 1188

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102218

For someone that has knowledge of JavaScript but is not familiar with D3, this seems strange indeed, but these arguments (or parameters) are already expected by D3:

When a specified event is dispatched on a selected node, the specified listener will be evaluated for each selected element, being passed the current datum (d), the current index (i), and the current group (nodes), with this as the current DOM element.

These are the famous 3 arguments when you use a function in a D3 selection:

the function is evaluated for each selected element, in order, being passed the current datum (d), the current index (i), and the current group (nodes), with this as the current DOM element.

So, when you do something like this in a D3 selection:

function(d,i,n){

You have the 3 arguments:

  1. d, named like this for "datum", is the datum of the element.
  2. i, for "index", is the index of the element;
  3. n is the group of the element.

Of course, you can name them anything you want ("foo", "bar", "a", "r2d2" etc...), the important here is just the order of the arguments.

Here is a demo to show you this, click the circles:

var width = 400,
    height = 150;
var data = [3,19,6,12,23];

var scale = d3.scaleLinear()
    .range([10, width - 10])
    .domain([0,30]);

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

var circles = svg.selectAll("circle").data(data)
    .enter()
    .append("circle")
    .attr("r", 8)
    .attr("fill", "teal")
    .attr("cy", 50)
    .attr("cx", function(d) {
        return scale(d)
    })
    .on("click", up);

var axis = d3.axisBottom(scale);

var gX = svg.append("g")
    .attr("transform", "translate(0,100)")
    .call(axis);

function up(d,i){
  alert("datum is " + d + "; index is " + i);
  }
<script src="https://d3js.org/d3.v4.min.js"></script>

Regarding the d.data.category, it's all well commented in the code: dataset has both "category" and "measure", and it's bound to the SVG. When you use d3.layout.pie() on dataset, it returns an array of objects like this:

{"data":  42, "value":  42, "startAngle": 42, "endAngle": 42, "padAngle": 42}

That's where the d.data comes from.

Upvotes: 2

Related Questions