div

Template engine for node.js and browsers

#div()

Javascript template engine for node.js and browsers.

var template = html(
    head(
        title('Page about $subject'),
        script({type: 'text/javascript', src: '/somescript.js'})
    ),
    body(
        ul({$: 'each items'},
            li({$: 'if url'},
                a({href: '$url', class: 'b'}, '$name'),
                span('$name')
            )
        )
    )
);
 
template.print({
    subject: 'some items',
    items: [
        {name: 'chair'},
        {name: 'event', url: '/someevent'},
        {name: 'phone'}
    ]
});
<!-- pretty indented result -->
<html>
    <head>
        <title>Page about some items</title>
        <script type="text/javascript" src="/somescript.js"></script> 
    </head>
    <body>
        <ul data-each="3">
            <li data-if="false"><span>chair</span></li>
            <li data-if="true"><a href="/someevent" class="b">event</a></li>
            <li data-if="false"><span>phone</span></li>
        </ul>
    </body>
</html>
npm install div
var get = require('div').get;
 
//  for comfort using tag functions like tags in html markup define them 
var div = get('div'),
    a = get('a'),
    span = get('span');
 
//  building template 
//  tag({attribute_key: 'attribute value'}, node, node, 'just text', node ...) 
var template = div(
    a({href: '/'}, 'link'),
    span('just text')
);
 
//  reading context with keys 
//  $name - to read context with key 'name' 
//  $this - to read whole context 
var template = div('my name is $name');
 
//  using blocks 
//  tag({$: 'block_name arg1 arg2 ...'}, nodes ...) 
var template = div({$: 'each items'}, div('$title'));
ul({$: 'each numbers'}, li('$n')).print({items: [{n: 1}, {n: 2}, {n: 2}]});
ul({$: 'each'}, li('$this')).print([1, 2]);
<!-- result for both examples -->
<ul data-each="2">
    <li>1</li>
    <li>2</li>
</ul>
var context = {
    a: 1, b: 2,
    c: {a: 111, b: 222}
};
 
div('$a and $b').print(context);
// <div>1 and 2</div> 
 
div({$: 'with c', '$a and $b').print(context);
// <div>111 and 222</div> 
var str = '<a href="/">index</a>';
 
div('$str').print(str);
// <div>&lt;a href=&quot;/&quot;&gt;index&lt;/a&gt;</div> 
 
div({$: 'safe'}, '$str').print(str);
// <div><a href="/">index</a> 
p({$: 'if'}, 'truthy').print();
// <p data-if="false"></p> 
 
p({$: 'if'}, 'truthy').print(true);
// <p data-if="true">truthy</p> 
 
p({$: 'if a'}, 'truthy').print({a: true});
// <p data-if="true">truthy</p> 
 
p({$: 'if a 123'}, 'truthy').print({a: 123});
// <p data-if="true">truthy</p> 
 
p({$: 'if a 123'}, 'truthy', 'falsy').print({a: 124});
// <p data-if="false">falsy</p> 
p({'if a': 'enabled'}).print();
// <p></p> 
 
p({'if a': 'enabled'}).print(true);
// <p a="enabled"></p> 
 
p({'if a class': 'enabled'}).print();
// <p></p> 
 
p({'if a class': 'enabled'}).print({a: true});
// <p class="enabled"></p> 
 
p({'if a 123 class': 'enabled'}).print({a: 123});
// <p class="enabled"></p> 
 
p({'if a 123 class': ['enabled', 'disabled']}).print({a: 122});
// <p class="disabled"></p> 
var content = div({$: 'select'},
    div('index'),
    div('blog'),
    div('post')
);
var context = {};
content.print(context);         // case 1 
content.print(context, [1]);    // case 2 
<!-- case 1 -->
<div>
    <div>index</div>
    <div>blog</div>
    <div>post</div>
</div>
 
<!-- case 2 -->
<div data-select="1">
    <div>blog</div>
</div>
//  small partials 
var products_list = div({class: 'list'}, 'products list content here');
var products_item = div({class: 'item'}, 'detail info about product');
var index = div({class: 'index'}, 'index content');
var contacts = div({class: 'contacts'}, 'contacts content');
 
//  something like layout 
var page = div(
    img({src: '/logo.png', class: 'logo'}),
    div({class: 'content', $: 'select'},
        index,
        div({class: 'products', $: 'select'},
            products_list,
            products_item
        ),
        contacts
    )
);
 
page.add_map('index', index);
page.add_map('products_list', products_list);
page.add_map('product_details', products_item);
 
var context = {};
 
page.print('index', context);           // case 1 
page.print('products_list', context)    // case 2 
<!-- case 1 -->
<div>
    <img src="/logo.png" class="logo">
    <div class="content" data-select="0">
        <div class="index">index content</div>
    </div>
</div>
 
<!-- case 2 -->
<div>
    <img src="/logo.png" class="logo">
    <div class="content" data-select="1">
        <div class="products" data-select="0">
            <div class="list">products list content here</div>
        </div>
    </div>
</div>
var controller = require('div').controller;
 
var click_madness = controller.extend({
    handlers: {
        onclick: 'click',
        onclick_move: 'click span.move'
    },
    initfunction () {
        controller.init.apply(this, arguments);
        this.click_counter = 0;
    },
    onclickfunction (e) {
        this.click_counter += 1;
        this.render({i: this.click_counter});
    },
    onclick_movefunction (e) {
        this.$el.css({marginLeft : '+=10px'});
    }
});
 
var template = div(
    div({ctrl: click_madness},
        span('I have been clicked $i times.'), ' ',
        span({class: 'move'}, 'Move me.')
    ),
    p({ctrl: click_madness}, 'me clicked $i times'),
    div({ctrl: click_madness, $: 'if i 2'},
        'i equals 2',
        'i not equals 2 its $i'
    )
);
 
var el = $(template.print({i: 0})).get(0);
template.set_el(el);

Controller can be included into tags and will be printed as its 'tag' property prints.

var view = controller.extend({
    tag: div('im just template with handlers'),
    handlers: {
        onclick: 'click'
    },
    onclickfunction () {
        this.$el.html('i have been clicked');
    }
});
 
var template = div(
    div('im div and view under me'),
    view
);
 
var el = $(template.print()).get(0);
template.set_el(el);