Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Selections in D3, Jquery

In the answer Mike posted here, he overviews three different ways to apply a change to a matched element based on a index or custom filter. I'm trying to clarify, hopefully for more people than just myself, the actual selections in these solutions.

So given a document with 6 SVG rects with class .bar, we have these different selections and what they return:

d3.select(".bar"):

[Array[1]  
0: rect.[object SVGAnimatedString]  
length: 1  
parentNode: html  
__proto__: Array[0]  

d3.selectAll(".bar"):

[Array[6]  
0: rect.[object SVGAnimatedString]  
1: rect.[object SVGAnimatedString]  
2: rect.[object SVGAnimatedString]  
3: rect.[object SVGAnimatedString]  
4: rect.[object SVGAnimatedString]  
5: rect.[object SVGAnimatedString]  
length: 6  
parentNode: html  
__proto__: Array[0]  

$(".bar"):

[
<rect class=​"dataBars" x=​"53.191489361702125" width=​"212.7659574468085" y="4.761904761904762" height=​"11.11111111111111">​</rect>​,  
<rect class=​"dataBars" x=​"74.46808510638297" width=​"372.3404255319149" y=​"20.634920634920636" height=​"11.11111111111111">​</rect>​, 
<rect class=​"dataBars" x=​"127.6595744680851" width=​"212.7659574468085" y=​"36.507936507936506" height=​"11.11111111111111">​</rect>,​  
<rect class=​"dataBars" x=​"31.914893617021274" width=​"212.7659574468085" y=​"52.38095238095238" height=​"11.11111111111111">​</rect>​,  
<rect class=​"dataBars" x=​"159.5744680851064" width=​"265.9574468085106" y=​"68.25396825396825" height=​"11.11111111111111">​</rect>​,  
<rect class=​"dataBars" x=​"234.04255319148936" width=​"138.29787234042553" y=​"84.12698412698413" height=​"11.11111111111111">​</rect>​,
]  

Now here's where it get's more tricky (for me at least), say I want to apply a style to the 3rd rectangle, this rectangle can be found using

d3.selectAll(".bar")[0][2]  

But if we want to then use the d3.selection.attr(), that returns

TypeError: Property 'style' of object #<SVGRectElement> is not a function

But we can then wrap this selection

d3.select(d3.selectAll(".bars rect")[0][2]).style("fill", "red")

and this will work as expected.

Then, if we want to apply a filter, such as

filter(function (d) { return d === 5 || d === 15;}

the d3.selectAll(".bar") must be used, and d3.select(d3.selectAll(".bar")) will not work correctly.

I've read Mike's excellent tutorials and documentation on selections, but just when I think I have it figured out, something pops up and surprises me. So what is the difference between these selections, and how do I know which one to use when? Thank you very much, and sorry for the long post!

like image 724
user4815162342 Avatar asked Feb 15 '23 19:02

user4815162342


1 Answers

I've tried to do this in the past and run into similar errors. Then I realized that I was not really following the intended API. The second that you start accessing selection elements by index, you're way off the beaten path.

See nested selections

So, if you wanted to style your third bar, you would do

d3.selectAll(".bar").style("color", function(d,i) { return i === 2 ? "red" : null; } )

And if your selection is one level more nested than that, make it function(d,i,j) and similarly go from there. Etc.

like image 157
roippi Avatar answered Feb 18 '23 10:02

roippi