Haiku makes DOM trees
so simple to generate,
I think you'll like it.
There are plenty of libraries for making it easier to create arbitrary DOM nodes,
but I couldn't find one that used Zen Coding
syntax, which I've kinda fallen in love with lately. It can generate single
element nodes, DOM Fragments, or even a raw string of HTML, suitable for
insertion via innerHTML
.
It's intended to be a lightweight replacement for the standard DOM method of creating new HTML structures, without the overhead of a full-blown templating system like Mustache or Dust.js or the like.
Haiku is packaged as an AMD module, but it's dependency-free, so it's simple to
install: just drop it in your root JavaScript folder, and require
away:
require(["haiku"], function(haiku) {
document.body.appendChild( haiku.expand("section#main+aside#related") );
});
Specifies the ID for an element (ignores multiple operands; an element can only have one ID):
div#main |
produces ⇒ | <div id="main"></div> |
Specifies the CSS class for an element (multiple operands allowed):
blockquote.fancy.gothic |
⇒ | <blockquote class="fancy gothic"></blockquote> |
Provides simple Supplant-style templating based on a caller-provided data object (just basic parameter substitution right now):
a[href=http://me.com?id=$link;]>{$label;} |
⇒ |
<a href="http://me.com?id=9001">Goku's power level</a>
|
{ "link":9001, "label":"Goku's power level } |
Makes the following element a child of the preceding one:
ul>li |
⇒ | <ul> <li></li> </ul> |
Makes the following element a sibling of the preceding one:
div>p#intro+p#main |
⇒ | <div> <p id="intro"></p> <p id="main"></p> </div> |
Makes the following element a sibling of the preceding one's parent (i.e goes up one level in the tree):
header>h1<section.main |
⇒ | <header><h1></h1></header> <section class="main"></section> |
Specifies the contents of a text node:
p>{A }+em{simple}+{ example} |
⇒ | <p>A <em>simple</em> example</p> |
Specifies attributes other than class and id (comma-separated if more than one):
a#myId.myClass[href=http://foo.com,data-type=permalink] |
⇒ | <a href="foo.com" data-type="permalink" id="myId" class="myClass" /> |
Let's say you've got a piece of code that needs to create a handful of new DOM nodes and apply a bunch of atributes to them. You could do this the Vanilla JavaScript way, like so:
function createPerson(dataObject) {
var item, link;
item = document.createElement('li');
item.className = 'person';
item.setAttribute('data-item-key', dataObject.id);
link = document.createElement('a');
link.href = 'http://foo.com?personid=' + dataObject.id;
link.className = 'external';
link.innerText = dataObject.name
item.appendChild(link);
return item;
}
Or you can use Haiku's expand
method. By default, Haiku appends
all of the nodes it interprets from your provided string to a new DOM document
fragment, which it hands back to you for placement in your document tree:
function createPerson(dataObject) {
var tmpl = "li.person[data-item-key=$id;]>a.external[href=http://foo.com?personid=$id;>{$name;}";
return haiku.expand(tmpl, dataObject);
// returns a DOM document fragment
}
Maybe you prefer to hand-jam HTML and use something like jQuery to inject it via
innerHTML
:
function createPerson(dataObject) {
var html;
html = "<li class='person' data-item-key='" + dataObject.id + "'>";
html += "<a class='external' href='http://foo.com?personid='" + dataObject.id + "'>" + dataObject.name + "</a>";
html += "</li>";
return html;
}
Haiku supports this as well, if you pass a truthy value as the optional third
argument to expand
:
function createPerson(dataObject) {
var tmpl = "li.person[data-item-key=$id;]>a.external[href=http://foo.com?personid=$id;>{$name;}";
return haiku.expand(tmpl, dataObject, true);
// returns a string of serialized HTML
}
In the above case, where your created DOM tree has a single root node, you could
instead use Haiku's create
method to get back an actual reference to
the root DOM Element node instead. This is helpful if you need to do any further
manipulation of the node (say, add an event handler or two) prior to insertion
into the tree:
function createPerson(dataObject) {
var tmpl = "li.person[data-item-key=$id;]>a.external[href=http://foo.com?personid=$id;>{$name;}";
return haiku.create(tmpl, dataObject);
// returns the DOM Element for the <li>
}
Minified version generated via UglifyJS, using Marijn Haverbeke's online tool.
So far, this is more or less a subset of Zen Coding's power — I haven't
yet added support for abbreviation groups
(body>(header>h1)+(div#main)+(footer>span)
), element multiplication
(li*5>a
), or item numbering (li#item$*3
).
I expect if this project proves useful, I'll probably add those features (and maybe expand the templating capability a bit more) at some point in the future.