I’m a big fan of using D3.js for building content from structured data. You can write expressive JavaScript using the D3.js API to convert your data to structured markup.

A real quick example might be:

[cc lang=”html” line_numbers=”0″]

[/cc]

[cc lang=”javascript” line_numbers=”0″]
var d = d3.selectAll(“.content ul”).data([
“one”,
“two”,
“three”,
“four”
]);
d.enter()
.append(“li”)
.classed(“number”, true)
.text(String);
[/cc]

Which really just says take the elements at .content ul selector and bind them to the data [“one”, “two, …]. The d.enter() starts expressing what happens when a new data element is found in the bound dataset. In this case we create a new li element (.append(“li”)), set the CSS class, then apply the content of the data element as the text of this element. So this is pretty reasonable, but a common activity I see is applying a couple classes or maybe an ID to this and it would be great if I could express that in a new way. I’d like to be able to do like:

[cc lang=”javascript” line_numbers=”0″]
d.enter()
.appendSelector(“li.number.second-class#num-id”)
.text(String);
[/cc]

To generate <li class=”number second-class” id=”num-id”> much easier. Well, D3.js does provide a couple extension points, the easiest one to interact with is just expand the API with additional calls.

[cc lang=”javascript” line_numbers=”0″]
d3.selection.enter.prototype.appendSelector =
d3.selection.prototype.appendSelector = function(selector) {
var self = this;
var selectorParts = selector.split(/([\.\#])/);
if (selectorParts.length == 0) return self;
self = self.append(selectorParts.shift());

while (selectorParts.length > 1) {
var selectorModifier = selectorParts.shift();
var selectorItem = selectorParts.shift();
if (selectorModifier === “.”) {
self = self.classed(selectorItem, true);
} else if (selectorModifier === “#”) {
self = self.attr(‘id’, selectorItem);
}
}
return self;
};
[/cc]

So the prototypes for d3.selection and d3.selection.enter are the primary things that you’ll interact with via the API. This allows d.enter().appendSelector(…) to work brilliantly. For those who don’t want to extend the D3.js prototypes, call and each can be used to apply a function to a selector. Using these tools you can make repeatable and reusable expressions of intent when building things with D3.js.

Extending D3.js