blueprint.js provides a versatile function for easily creating DOM elements and element templates with highly readable code. It tiny, fast, and it doesn't try to create it's own Turing-complete language just to make DOM elements. That's what JavaScript is for.
To see an example of how blueprint.js works, check out this page. The code that creates all the visible elements in the demo is here.
Blueprint requires one .js
file that's less than 15 KB, raw. (A future release will include a smaller, minified version.)
To use blueprint.js, you simply need to load one script in your page. This can be accomplished by adding the following line to your <head>
element:
<script src='https://wits.github.io/blueprint.js/blueprint.js'></script>
The code above will ensure that you always get the latest version of blueprint.js. (You can also host the file yourself.)
blueprint.js is a tiny library that is almost exclusively designed for creating DOM elements. Creating elements with blueprint.js always starts with the $new
function, which creates blank elements. This function can do a lot directly, as in the cases below:
The simplest usage of the $new
method is to create an empty div. To do this, you can simply call:
$new().element(); // HTMLDivElement
This will return an HTMLDivElement (<div>
) with no children, text, or classes.
$new
can create elements with other tags, like so:
$new('h1').element(); // HTMLHeadingElement
This will return an HTMLHeadingElement (<h1>
, specifically) with no children, text, or classes.
$new
can also be used to easily create elements with a specific id. For instance:
$new('#foo').element();
This will return an HTMLDivElement (<div>
) with the id foo
. (Equivalent to <div id="foo"></div>
.)
$new
can also be used to easily create elements with specific classes. For instance:
$new('.foo.bar').element();
This will return an HTMLDivElement (<div>
) with the classes foo
and bar
. (Equivalent to <div class="foo bar"></div>
.)
$new
can also be used to easily create elements with specific attributes. For instance:
$new('[title="Hello!"]').element();
This will return an HTMLDivElement equivalent to <div title="Hello!"></div>
.
The methods above can all be combined to create complex elements in a very short, simple, readable way:
$new('h1.foo#bar[title="baz"]').element();
This will return an element equivalent to: <h1 class="foo" id="bar" title="baz"></h1>
.
You can add text to elements before creating them using the .text
method, like so:
$new().text('Lorem ipsum ...').element();
This will return an HTMLDivElement (<div>
) with the text "Lorem ipsum ...", but no children or classes.
You can add child elements to elements before creating them, using the .children
method, like so:
$new('ul').children(
$new('li').text('Item 1'),
$new('li').text('Item 2'),
$new('li').text('Item 3')
).element();
This will return an HTMLUListElement (<ul>
) with three (<li>
) children, each with distinct text.
There are several other methods that can be chained together when creating elements (in addition to .text
and .children
).
Although attributes can be added in the $new
function, they can also be added using the attr
method. This method can be used in two ways.
// $new
$new('a[href=http://example.com]').element();
// .attr(name, value)
$new('a').attr('href', 'http://example.com').element();
// .attr(JSON)
$new('a').attr({
href: 'http://example.com'
}).element();
CSS styling can be added using the style
method. This method can be used in two ways.
// .style(name, value)
$new().style('background-color', 'red').element();
// .style(JSON)
$new().style({
backgroundColor: 'red'
}).element();
Although classes can be added in the $new
function, they can also be added using the class
method.
// $new
$new('.foo').element();
// .class
$new().class('foo').element();
Although the id can be set in the $new
function, it can also be set using the id
method.
// $new
$new('#foo').element();
// .id
$new().id('foo').element();
If you need to add multiple elements to an existing element directly, you can do so with the $frag
method. (For instance, if you're filling in a list ul
element that is already in the page.)
// $frag
list.appendChild($frag(
$new('li').text('Item #1'),
$new('li').text('Item #2'),
$new('li').text('Item #3')
));
// Without $frag
list.appendChild($new('li').text('Item #1').element());
list.appendChild($new('li').text('Item #2').element());
list.appendChild($new('li').text('Item #3').element());
The
$frag
method returns a document fragment. It can take any number of parameters (including zero) and will automatically call.element()
on its parameters if needed.
Every blueprint you make returns an object that can be reused. This means you can make multiple DOM elements from the same blueprint!
// Create a blueprint
var cardBlueprint = $new('.card').text('This is a card');
document.body.appendChild(cardBlueprint.element());
document.body.appendChild(cardBlueprint.element());
document.body.appendChild(cardBlueprint.element());
If you want to allow each generated element to be different, you might be tempted to do the following:
// This is dangerous and could introduce bugs to your code! Try out this example to see what strange side-effects you get
var cardBlueprint = $new('.card');
cardBlueprint.text('This is a card.');
document.body.appendChild(cardBlueprint.element());
cardBlueprint.text('This is a second card!');
document.body.appendChild(cardBlueprint.element());
cardBlueprint.text('Three cards?!');
document.body.appendChild(cardBlueprint.element());
The issue with the above is that each call to text()
modifies the actual blueprint object. In this case, text()
appends an additional text DOM child each time it's called, with the third and final card having the text "This is a card.This is a second card!Three cards?!" contained within it.
What we can do instead is create a slightly different version of this code, using prepare()
. This method takes a callback function as its sole argument, which then allows you to modify each "instance" of the blueprint without introducing side-effects to the other elements. You can even add multiple prepare()
calls to a blueprint!
Here's how we could rewrite the above snippet using prepare:
var cardBlueprint = $new('.card').prepare(function($this, props) {
$this.text(props.cardText);
});
document.body.appendChild(cardBlueprint.element({
cardText: 'This is a card.'
}));
document.body.appendChild(cardBlueprint.element({
cardText: 'This is a second card!'
}));
document.body.appendChild(cardBlueprint.element({
cardText: 'Three cards?!'
}));
When using this advanced feature, the basic rule of thumb is to directly modify your blueprint if you want that change to apply to all of the elements you plan on creating, and to use prepare()
for anything that is dynamic between elements.