Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are d3's select() and selectAll() behaving differently here?

I am playing around with the drag multiples example, and I noticed something I can't explain.

In this snippet:

var svg = d3.select("body").selectAll("svg")
    .data(d3.range(16).map(function() { return {x: width / 2, y: height / 2}; }))
    .enter().append("svg")
    .attr("width", width)
    .attr("height", height);

I changed selectAll to select. It still works, but now the svg elements are added after the </body> tag. The original code, with selectAll, adds them after the <body> tag as you would expect.

Since the original html contains no hardcoded <svg> element, I would think that both select and selectAll just return the empty selection. So I cannot figure out why they result in different behavior.

I'm just looking for an explanation. Thanks!

like image 335
Jonah Avatar asked Jan 06 '13 23:01

Jonah


People also ask

What do the select () and selectAll () functions in D3 do?

d3. select selects the first matching element whilst d3. selectAll selects all matching elements. Both functions take a string as its only argument.

What does D3 selectAll return?

selectAll() function in D3. js is used to select all the element that matches the specified selector string. Parameters: This function accepts single parameter HTML tag as a parameter. Return Value: This function returns the selected elements.

What is .attr in D3?

D3 provides the ability to set attributes of a selected element using the attr() function. This function takes two parameters: Attribute Name - For example, "r" to set an SVG circle's radius.

What is D in D3 JS?

Generally in d3 documentation and tutorials, you'll see d used for the current data element and i used for the index of the current data element. The index is passed in as the second element to the function calls like so: function setY(d, i) { return percent_scale(d.


3 Answers

The basic difference between select and selectAll is that select squashes the hierarchy of the existing selections, while selectAll preserves it.

Therefore, when you use one selectAll after the other, the result will be a lot like a list of nested for loops.

http://bost.ocks.org/mike/nest/

like image 54
Avi Dubey Avatar answered Oct 17 '22 13:10

Avi Dubey


Check Mike Bostock's post about select/selectAll: Nested Selections

To quote:

There is an important difference between select and selectAll: select preserves the existing grouping, whereas selectAll creates a new grouping. Calling select thus preserves the data, index and even the parent node of the original selection!

like image 45
Dave Foster Avatar answered Oct 17 '22 11:10

Dave Foster


Other answers here are a bit off, and don't cite the correct source; this is only tangentially related to nesting. D3's author explains it in his join concept. I review that here for completeness:

You have two sets (arrays):

  1. the dataset that drives the visualisation;
  2. the HTML elements that represent each data item in that dataset.

These sets may not be exactly the same at any given time during the application's run. So we do a little management to ensure they do match, at all times (every processing frame). Imagine a real-time data set (stream) - maybe last time we only got 98 elements, now instead we've got 100. The page still has 98 <div>s, but now we need to create 2 more. That's exactly what happens, automagically, in your code:

  1. By calling .selectAll("svg") you are saying, "Create a set of <svg> elements even if they don't exist." Another way to put this is, "Let's imagine we can select a set of <svg>s that matches the dataset we've given. Now, go ahead and create that set."
  2. ...Which is exactly what .enter().append(...) then does. Conversely, if there had been too many elements for our new dataset (because we previously had more in elements in the dataset than we do now), .exit().remove(...) would deal with that.

enter is the set of elements we need to create; exit is those we need to remove.

Your .selectAll("svg") would return nothing, but as it is more of a proposal than an imperative, it then creates what it needs in .enter().append("svg"), in order to match the dataset given.

like image 3
Engineer Avatar answered Oct 17 '22 11:10

Engineer