1

I am currently experimenting with d3-selection. From whatever, literature/material I studied, I understand that it takes a valid CSS selector.

So, for example, if I want to create a data-driven path, I should be using it this way

svg.selectAll('path') /*valid CSS Selector*/
    .data(index1)
    .join('path')    
    .attr('class', (d) => `ln${d}`)
    .attr('d', pathVal)
    .attr('stroke', () => { return `hsla(${Math.random() * 360} , ${((Math.random() + Math.random()/2)*100).toFixed(2)}%, 50%, 1)`; })
    .style('transform', (d, i) => { return `translateY(${d*multiplier}px)` })
    .attr('stroke-width', '2')

const width = 1280;
height = 720;

svg = d3.select('svg')
    .attr('xmlns', 'http://www.w3.org/2000/svg')
    .attr('viewBox', `0 0 ${width} ${height}`)

rect = svg.append('rect')
    .attr('x', '0')
    .attr('y', '0')
    .attr('width', `${width}`)
    .attr('height', `${height}`)
    .attr('fill', `#EFEFEF`)

//create 3 path for testing
dataHorizontal = [
    { x: 0, y: 0 },
    { x: 1280, y: 0 }
];

pathVal = d3.line()
    .x(d => d.x)
    .y(d => d.y)
    (dataHorizontal);

index1 = [1, 2, 3];

multiplier = 60;

//create path

svg.selectAll('path')
    .data(index1)
    .join('path')   
    .attr('class', (d) => `ln${d}`)
    .attr('d', pathVal)
    .attr('stroke', () => { return `hsla(${Math.random() * 360} , ${((Math.random() + Math.random()/2)*100).toFixed(2)}%, 50%, 1)`; })
    .style('transform', (d, i) => { return `translateY(${d*multiplier}px)` })
    .attr('stroke-width', '2')
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<script type="text/javascript" src="https://d3js.org/d3.v7.min.js"></script>


<body>
    <div id="container" class="svg-container"></div>
    <svg>
    </svg>
    <!--d3 script-->
    <script src="prod.js"></script>
</body>

</html>

However, to my surprise, I can see that I can pass on anything there. For example, I can pass on svg.selectAll('foo') and it would still work.

Can someone please explain why/how does it work and what are the side effects of svg.selectAll('foo') compared to svg.selectAll('path')?

const width = 1280;
height = 720;

svg = d3.select('svg')
    .attr('xmlns', 'http://www.w3.org/2000/svg')
    .attr('viewBox', `0 0 ${width} ${height}`)

rect = svg.append('rect')
    .attr('x', '0')
    .attr('y', '0')
    .attr('width', `${width}`)
    .attr('height', `${height}`)
    .attr('fill', `#EFEFEF`)

//create 3 path for testing
dataHorizontal = [
    { x: 0, y: 0 },
    { x: 1280, y: 0 }
];

pathVal = d3.line()
    .x(d => d.x)
    .y(d => d.y)
    (dataHorizontal);

index1 = [1, 2, 3];

multiplier = 60;

//create path

svg.selectAll('foo') /*why it worked?*/
    .data(index1)
    .join('path')   
    .attr('class', (d) => `ln${d}`)
    .attr('d', pathVal)
    .attr('stroke', () => { return `hsla(${Math.random() * 360} , ${((Math.random() + Math.random()/2)*100).toFixed(2)}%, 50%, 1)`; })
    .style('transform', (d, i) => { return `translateY(${d*multiplier}px)` })
    .attr('stroke-width', '2')
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<script type="text/javascript" src="https://d3js.org/d3.v7.min.js"></script>


<body>
    <div id="container" class="svg-container"></div>
    <svg>
    </svg>
    <!--d3 script-->
    <script src="prod.js"></script>
</body>

</html>
smpa01
  • 4,149
  • 2
  • 12
  • 23
  • 1
    It's relevant when your dataset changes. Both examples would be empty selections the first time they are run. But they would have different results if rerun. "foo" would return another empty selection and a new path would be appended. The "path" selection would return the appended path (for removal, transistion, etc) – SmokeyShakers Jul 06 '22 at 19:32
  • 2
    Firstly, you might want to read this: https://stackoverflow.com/questions/46147231/selecting-null-what-is-the-reason-behind-selectallnull-in-d3. Secondly, you can pass anything to it because internally it uses `querySelectorAll`, and you can pass any string to it: `querySelectorAll("foo")` will return a nodeList, but with zero length of course. – Gerardo Furtado Jul 07 '22 at 04:32
  • As a curiosity, some years ago, just for fun, I'd use scientists names, like Charles Darwin or Richard Feynman, because it doesn't matter: https://stackoverflow.com/a/44060963/5768908 and https://stackoverflow.com/a/44080919/5768908 – Gerardo Furtado Jul 07 '22 at 04:37
  • Many thanks @ GerardoFurtado, I will test out the side-effects and post them here. Your post really helps. – smpa01 Jul 07 '22 at 12:48

0 Answers0