dynamictemplate
Version:
Δt - async & dynamic templating engine
181 lines (137 loc) • 7.53 kB
Markdown
# [dynamictemplate](http://dodo.github.com/node-dynamictemplate/)
[dynamictemplate](http://dodo.github.com/node-dynamictemplate/) is yet
another template engine, but this time loaded with full async support
and capable of being changed even after the template was rendered.
It works in browsers too.
→ [Check out the demo!](http://dodo.github.com/node-dynamictemplate/example/circles.html)
## Installation
```bash
$ npm install dynamictemplate
```
## Solutions
If any of these problems are familiar to you, you should skip the tl;dr and read the documentation:
* building a real-time user interface
* updating large chunks of DOM
* manipulating nested DOM structures
* working with a designer
* isomorph code
* HTML streaming
## TL;DR
Δt provides convenient DOM manipulation in template style for real-time user interfaces.
* async & dynamic → changeable even after template was rendered
* pure JavaScript with a hugh {{do you mean "huge"?}} event based api → modular & extendable
* runs on server and browser side
* different approach than DOM: don't get your elements out of the black box; keep only those which you need.
* minimalistic (all the other stuff is hidden in modules :P)
## Documentation
Writing and maintaining user interfaces can be hard.
Δt is a new event-based way of writing and maintaining user interfaces in JavaScript.
DOM has grown old. It's one of the legacies from the last millennium that each browser caries with it.
Like nearly every browser API, the DOM has an opinionated {{do you mean "inconsistent"?}}, ugly interface to work with:
the fastest way to fill a DOM is `innerHTML`; the way to get information back once it's parsed is by querying it, but the convenient way to manipulate it is by changing, creating and removing nodes. So, WTF?
These are the reasons why jquery and mootools are still the most used js libraries. But seriously, have you ever tried to write a large {{better word choice: complex}} user interface with it?
So let's try something new:
```JavaScript
var Template = require('dynamictemplate').Template;
var tpl = new Template({schema:'html5'}, function () {
this.div(function () {
this.text("hello world");
this.end();
});
});
```
```CoffeeScript
{ Template } = require 'dynamictemplate'
tpl = new Template schema:'html5', ->
->
"hello world"
()
```
That was easy. We created a new template instance and with it a new `<div>` element with some text and closed it.
Let's try something more complex:
```JavaScript
function template(view) {
return new Template({schema:5}, function () {
this.$div(function () {
view.on('set title', this.text);
});
this.$a(function () {
this.text("back");
view.on('navigate', function (url) {
this.attr('href', url);
}.bind(this));
});
});
}
```
```CoffeeScript
template = (view) ->
new Template schema:'5', ->
@$div ->
view.on('set title', )
@$a href:'/', ->
"back"
view.on('navigate', (url) => (href:url))
```
Ok. Let me explain: we created a div whose text changes on every 'set title' event the view object will emit, and we created an anchor element whose `href` attribute will change on every 'navigate' event. That's it.
Note that the div element will be empty at the beginning.
If you play with it a while {{what is "it"?}}, you might hit some known problems from nodejs: flow control. How convenient that it seems that nearly everybody has written her own library. **Use your own flow control library!** {{I don't understand what you are trying to say here.}}
If you don't know any, [async](https://github.com/caolan/async#readme) might be a good fit.
If you already started playing around with this example, you might have found out that nothing is happing. That is because each `this.div` call doesn't produce a div tag; it only creates a `new` and `add` event with the object representation of the div tag that is its argument. Doesn't sound very useful to you? How about if you use one of the many adapters? An Adapter is a little module that listens for these events and acts accordingly on its domain. This means if you use dt-jquery or dt-dom {{it}} will create a DOM element. In the case of dt-stream, {{it}} will create a nodejs stream instance that emits HTML strings as data.
{{You have a problem with the pronoun "it" -- *you* know what you are referring to, but I don't. I've put double braces around the occurrences of "it" that are hard to understand.}}
```JavaScript
var jqueryify = require('dt-jquery');
tpl = jqueryify(template(view));
// or
var domify = require('dt-dom');
tpl = domify(template(view));
// or
var streamify = require('dt-stream');
tpl = streamify(template(view));
```
{{Make it explicit that "view" refers the previous example. What do I do with variable tpl once I have it?}}
For more information on the events look at [asyncxml](http://dodo.github.com/node-asyncxml/) which generates them.
Let's have another example:
```JavaScript
function template(view) {
return new Template({schema:5}, function () {
this.$div({class:'user'}, function () {
var name = this.a({class:'name'});
var about = this.span({class:'about'});
view.on('set user', function setUser(user) {
name.text(user.name);
name.attr('href', user.url);
about.text(user.description);
});
setUser(view.currentUser);
about.end();
name.end();
});
});
}
```
```CoffeeScript
template = (view) ->
new Template schema:5, ->
@$div class:'user', ->
name = (class:'name')
about = (class:'about')
setUser = (user) ->
name.text(user.name)
name.attr(href:user.url)
about.text(user.description)
view.on('set user', setUser)
setUser(view.currentUser)
about.end()
name.end()
```
All right. Here is the trick: unlike the DOM, where you normally have to query most elements, which feels mostly like grabbing into a black box with spiders and snakes, with Δt you already created the tags, so you can store them in variables, scopes and/or closures when you need them.
For more information, look at the various examples and plugins supporting Δt:
### Plugins
* [Δt compiler](http://dodo.github.com/node-dt-compiler) - this compiles static HTML (like mockup files from a designer) to template masks.
* [Δt stream adapter](http://dodo.github.com/node-dt-stream) - this lets you use node's beloved Stream to get static HTML from the templates.
* [Δt jquery adapter](http://dodo.github.com/node-dt-jquery) - this lets you insert the template into the DOM with the help of [jQuery](http://jquery.com/).
* [Δt list](http://dodo.github.com/node-dt-list) - this gives all you need to handle an ordered list of tags.
* [Δt selector](http://dodo.github.com/node-dt-selector) - this gives you specific selected tags without modifing the template.
[](http://travis-ci.org/dodo/node-dynamictemplate)
{{You've told me what all these parts are, but I'm still not sure how they all fit together.}}