DOM template

Templating engine which manipulates directly with DOM.

Template HTML

<div id="tpl">
    <p class="project-name"></p>
</div>

Create template instance

var tpl = Meta.Template(document.getElementById('tpl'), {
    ".project_name":    "name"
});

Render template

tpl({
    name: "My project"
});

Result

<div id="tpl">
    <p class="project-name">My project</p>
</div>

Overview

MetaJS templating engine provides data-binding, conditions and loops. It is dom-based which means that it manipulates directly with DOM without text-based re-rendering and re-parsing which provides high performance and flexibility.

Usability & compatibility

MetaJS Template library can be used standalone and not depends on WebComponents specification so it works in most modern browsers. See working demo.

Just include dist/template.min.js.

Concept

Template engine processes DOM nodes by definition rules. Engine goes throught selectors and executes processing function for every node returned by selector.

Definition rules are specified by and object in format "selector": processing_function.

Purpose of each processing function is to modify DOM element.

Usage

Create template instance:

var tpl = Meta.Template(document.getElementById('tpl'), {
    ".project_name":    "name",
    ".budget":          $__string("$ #{budget}"),
    ".created":         $__date("d. m. Y", "created"),
    ".active":          $__if("active"),
    ".status":          $__fn(function(data){
        switch(data.status){
            case 0: return "Concept";
            case 1: return "In progress";
            case 2: return "Closed";
        }
    }),
    ".manager"          $__with("manager", {
        ".first-name":      "first_name",
        ".last-name":       "last_name"
    }),
    "ul.tasks":         $__repeat("tasks", {
        ".task":            "task",
        ".due-date":        $__date("d. m. Y", "due_date"),
        "@":                $__attrIf("completed", "complete")
    }),
    ".note":            $__html("note")
});

Render template:

tpl({
    name:       "My project",
    budget:     1000,
    created:    new Date(2015, 3, 20, 0, 0, 0, 0),
    active:     true,
    status:     1,
    manager:    {
        first_name: "John",
        last_name:  "Doe"
    },
    tasks:      [
        {
            task: "Write concept",
            due_date: new Date(2015, 3, 22, 0, 0, 0, 0),
            complete: true
        }, {
            task: "Consult with customer",
            due_date: new Date(2015, 3, 25, 0, 0, 0, 0),
            complete: false
        }
    ],
    note: '<p>This will be fun!</p>'
});

Results in:

<div id="tpl">
    <p class="project-name">My project</p>
    <p class="budget">$ 1000</p>
    <p class="created">20. 3. 2015</p>
    <p class="active">ACTIVE</p>
    <p class="status">In progress</p>
    <p class="manager">
        <span class="first-name">John</span>
        <span class="last-name">Doe</span>
    </p>

    <ul class="tasks">
        <li>
            <span class="task" completed>Write concept</span>
            <span class="due-date">22. 3. 2015</span>
        </li>
        <li>
            <span class="task">Consult with customer</span>
            <span class="due-date">25. 3. 2015</span>
        </li>
    </ul>

    <div class="note">
        <p>This will be fun!</p>
    </div>
</div>

Template reference

Meta.Template(targetElement, binding)

var tpl = Meta.Template(element, {
    "selector": "model_property"
});

Parameter targetElement specifies root element on which bindings will be processed.

Parameter binding specifies definition rules in format "selector": processingFunction.

var instance = Meta.Template(targetElement, binding);

instance(data)

instance({
    model: "property"
});

Parameter data specifies data values which will be passed to processing functions.

instance(data);

Data binding

Data-binding processing functions reference.

$__html

Example usage

var tpl = Meta.Template(target, {
    "p.first_name": $__html("first_name"),
});

$__html(key)

Sets element innerHTML to raw context value.

$__text

Example usage

var tpl = Meta.Template(target, {
    "p.first_name": $__text("first_name"),
});

$__text(key)

Sets element innerHTML to sanitized context value.

By default if string is provided instead of processing function then $__text is used.

$__string

Example usage

var tpl = Meta.Template(target, {
    "p.full_name": $__string("#{first_name} #{last_name}"),
});

$__string(stringPattern)

Sets element innerHTML to string defined by stringPattern.

Pattern is string where #{key} is replaced by context value.

$__fn

Example usage

var tpl = Meta.Template(target, {
    "p.date": $__fn(function(data, context){
        return data.date.toString()
    }),
});

$__fn(fn)

Sets element innerHTML to value returned by user-function.

User-function accepts data as first parameter, context as second and this is set to current element.

$__filter

Example usage

var tpl = Meta.Template(target, {
    "p.last_name": $__filter("uppercase", "last_name"),
});

$__filter(filterName, key)

Sets element innerHTML to context value filtered by global filter - see filters reference.

$__date

Example usage

var tpl = Meta.Template(target, {
    "p.published": $__date("d. m. Y H:i", "published", "-"),
});

$__date(format, key, emptyValue = "NaN")

Sets element innerHTML to date-formated context value.

Context value must be a timestamp or Date object.

Parameter format is same as in PHP - see PHP's date function reference.

$__attr

Example usage

var tpl = Meta.Template(target, {
    "#menu": $__attr("opened", "ui.menu.opened"),
});

$__attr(attributeName, key)

Sets element attribute specified by attributeName to context value.

$__attrIf

Example usage

var tpl = Meta.Template(target, {
    "#menu": $__attrIf("opened", "ui.menu.opened", true),
});

$__attrIf(attributeName, key, empty)

Sets element attribute specified by attribtueName to context value only if value is positive.

If empty is set to true, attribute will be added without content, eg.: <li completed>...</li>.

$__classIf

Example usage

var tpl = Meta.Template(target, {
    "#menu": $__classIf("opened", "ui.menu.opened"),
});

$__classIf(className, key)

Adds or removes element's css class specified by className if context key is positive or negative.

$__prop

Example usage

var tpl = Meta.Template(target, {
    "meta-fragment#todo-list": $__prop("model", "todos"),
});

$__prop(propertyName, key)

Sets element node object property to context value.

Conditions

Condition processing functions reference.

Behaviour

If condition is satisfied then DOM node is added back to it's parent node if were removed.

If condition is not satisfied then DOM node is stored as is and removed from it's parent.

Parameter binding specifies definition rules which will be processed on child node if condition is satisfied.

Parameter key can also be a function returning a value which will be evaluated instead of context value. See Key, context & scope.

Parameter value can also be a function returning a value which will be used for comparision.

$__if

var tpl = Meta.Template(target, {
    ".supplier": $__if("supplier", {
        ".name": "name"
    }),
});

$__if(key, binding)

Conditions is satisfied if context value is positive, eg.: true / >0 / non empty.

$__ifNot

var tpl = Meta.Template(target, {
    "#actions": $__ifNot("disabled")
});

$__ifNot(key, binding)

Conditions is satisfied if context value is negative, eg.: false / undefined / null / NaN.

$__ifLt

var tpl = Meta.Template(target, {
    ".success": $__ifLt("errors.length", 1)
});

$__ifLt(key, value, binding)

Condition is satisfied if context value is lower then reference value.

$__ifLte

var tpl = Meta.Template(target, {
    ".success": $__ifLte("errors.length", 1)
});

$__ifLte(key, value, binding)

Condition is satisfied if context value is lower then or equal to reference value.

$__ifGt

var tpl = Meta.Template(target, {
    ".issues": $__ifGt("issues.length", 0)
});

$__ifGt(key, value, binding)

Condition is satisfied if context value is greater then reference value.

$__ifGte

var tpl = Meta.Template(target, {
    ".issues": $__ifGt("issues.length", 1)
});

$__ifGte(key, value, binding)

Condition is satisfied if context value is greater then or equal to reference value.

Loops

Loops processing functions reference.

$__repeat

var tpl = Meta.Tempate(target, {
    ".customers li": $__repeat("customers", {
        "@":            $__attr("index", "@key"),
        ".first_name":  "first_name",
        ".last_name":   "last_name",
    }),
});

$__repeat(key, binding)

Repeats nodes specified by selector for each item in context value.

Parameter binding defines definition rules which will be processed for every repeated element.

Context value can be both object or an array.

Each repeated node is bound to it's context data so when element position changes then node is just moved in DOM and thus not re-created.

Iteration key is available for child definition rules as key context meta-value so it is accessible by key @key.

Filters

Custom filters reference.

Meta.Template.registerFilter(name, func)

Meta.Template.registerFilter("uppercase", function(value, params){
    return value.substr(params.start, params.length);
});

Register custom filter globaly so every template instance can use it.

User-function accepts value as first parameter and params object as second.

Default filters

Filter name Description Params
uppercase Converts string to upperacse. -
lowercase Converts string to lowercase. -
trim Trims string. -
substr Return substring of given string. offset: integer, length: integer
replace Replaces substring of given string. find: string/regexp, replace: string, global: boolean (true)

Context, scope & key

Almost every processing function accepts key parameter.

String key

Key specifies path to context's value and accepts dot notation.

Example context:

{
    data: {
        customer: {
            first_name: "John",
            last_name:  "Doe"
        }
    },
    parent: ...parent context...
}

Context data-values

By default data properties are accessed by string key.

To access customer's first name we can use key customer.first_name.

var tpl = Meta.Template(target, {
    "p.first_name": $__text("customer.first_name"),
});

Context meta-values

If we want to access context's meta-data, eg. 'parent' we must prefix key with '@' sign.

var tpl = Meta.Template(target, {
    "ul li": $__repeat("customers", {
        ".info": $__with("contact", {
            "@":            $__prop("index", "@parent.key"),
            ".custmer-id":  "@parent.data.customer_id",
            ".first-name":  "first_name",
            ".last-name":   "last_name"
        })
    }
});

Function key

Parameter key also can be a function returning a value.

User-function accepts context's data property as first parameter and entire context as second parameter.

Variable this is set to current element.

var tpl = Meta.Template(target, {
    "p.name": $__text(function(data, ctx){
        return data.name;
    }),
});

Context

Each processing function accepts only one parameter - context.

Context is object containing data-values and meta-values.

Data values are received when rendering template and are set to data meta-value.

Meta values are used for internal workflow and to provide usefull scope variables such as index when iterating over an array.

Processing function which work with scopes ($__repeat, $__with, etc...) creates new context and provides child data and reference to parent context.

Root context example

Example of first-level context which is available for root selectors.

{
    data: {
        customer: {
            first_name: "John",
            last_name:  "Doe"
        }
    }
}

$__with context example

Example of second-level context provided for $__with child definitions.

{
    data: {
        first_name: "John",
        last_name:  "Doe"
    },
    parent: <reference to previous (first-level) context>
}

$__repeat context example

Example of second-level context provided for $__repeat child definitions.

{
    data: {
        first_name: "John",
        last_name:  "Doe"
    },
    key: 6,
    parent: <reference to previous (first-level) context>
}

Scope

To change scope lower for nicer code you can use $__with function.

$__with

var tpl = Meta.Tempate(target, {
    ".customer": $__with("customer", {
        ".first-name": "first_name",
        ".last-name": "last_name",
    }),
});

tpl({
    customer: {
        first_name: "John",
        last_name:  "Doe"
    }
})

$__with(key, binding=

Processes definition rules defined by binding where context data is set to specified value.