Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

D3JS Selection and class

Tags:

d3.js

Is there a simple way to expand the following piece of code so that div.someclass be automatically created if it does not exist?

d3.select("body").select("div.someclass").selectAll("p")
    .data([ 1, 2, 3 ])
    .enter()
        .append("p")
        .text(function (d, i) {
            return "index: " + i + ", value: " + d;
        });

I'm still at the early stages of learning D3JS. My understanding of it so far is that "instead of telling D3 how to do something, you tell D3 what you want". So I was surprised to see that the above piece of code requires <div class="someclass"></div> to be declared in the HTML.

An alternative is to insert the div programmatically:

/** Append HTML placeholder programmatically **/
placeholder = d3.select("body").append("div").attr("class", "someclass");

/** Bind the data to the DOM **/
/** instead of telling D3 how to do something, tell D3 what you want: in the absence of <p>, this will return a virtual selection **/
placeholder.selectAll("p")
    .data([ 1, 2, 3 ])
    .enter()
        .append("p")
        .text(function (d, i) {
            return "index: " + i + ", value: " + d;
        });

Is there a shorter/better way?

like image 818
Fabien Snauwaert Avatar asked Dec 15 '22 04:12

Fabien Snauwaert


1 Answers

If I understand correctly, you're asking how to append div.someClass IFF it doesn't exist. There's a D3 pattern for this, though it's a bit odd:

// create a selection for the container with a static 1-element array
var container = d3.select("body").selectAll("div.someclass")
    .data([0]); 

// now add it if it doesn't exist
container.enter().append('div').attr('class', 'someclass');

// now use it for the subselection
container.selectAll("p")
    .data([1, 2, 3]);

// etc

The odd part here is .data([0]) - the 0 is conventional, not required; this could be any static single-element array. The first time this is called, a new element will be created (unless something else created div.someclass first). The second time, the element is already there, so there's no .enter() selection and nothing more will be appended.

This is a fairly common pattern in reusable components that are meant to be called repeatedly on update - see the d3.svg.axis code for an example.

like image 85
nrabinowitz Avatar answered Apr 06 '23 20:04

nrabinowitz