February 22, 2008

MooTools template engine (a new approach)

tmpl.jsThis is a template engine I created for MooTools v1.11. I am using this in a recent project or two and it seems to be a rather handy little beast.

What does it do?

It takes a set of template elements, contained in the DOM tree of the current document decorated with marker classes, and expands it with some data.

The data is given as a combination of Javascript objects and arrays. An object’s key selects the DOM Element for which the corresponding value supplies the data.

An array value means the selected elements should be repeated and expanded using the elements of the array.

How does it work?

The data object is processed recursively. If an associative array is found, the first element of the template with the marker class given as the key of the association is selected and both the template and the data are processed deeper from there.

If the value of the association is an array, the elements selected by the key is repeated and filled with the elements of the array recursively.

Whenever a primitive value (ie, a number, or a string) is found, the currently selected element’s text is set accordingly, and recursion stops.

Examine the following example.

<div style="display:none" id="testTemplate">
    <table border="1">
        <tr class="header">
            <th class="columnName" />

        <tr class="data">
            <td class="item" />

        <tr class="data alt">
            <td class="item" />


<div id="testTarget"></div>

Here we have a HTML template described under the div ‘template’. We intend to place an expanded version of it into ‘testTarget’. See how it is done.

        var data = {
            'columnName': ['Name', 'Price', 'Qty'],

            'data': [
                {'item': ['1. Apple', 125, 0.5]},
                {'item': ['2. Banana', 210, 0.4]},
                {'item': ['3. Cat', 300, 0.2]},
                {'item': ['4. Dog', 200, 3]}

        expandTemplate('testTemplate', 'testTarget', data);

Let’s se what we have here.

  • the ‘columnName’ array is there to instruct the engine to repeat the <th class=”columnName” /> three times and set them up so they say ‘Name’, ‘Price’ and ‘Qty’.
  • the ‘data’ array says we need four copies of the <tr class=”data”>…</tr> and everything contained within
  • each of the ‘item’ arrays says we need 3 instances of <td class=”item” /> in each <tr class=”data”> -s, and they should be filled with whatever is in the arrays.

The resulting HTML looks like this:

  <table border="1">
      <tr class="header">
        <th class="columnName">Name</th>
        <th class="columnName">Price</th>
        <th class="columnName">Qty</th>

      <tr class="data">
        <td class="item">1. Apple</td>
        <td class="item">125</td>
        <td class="item">0.5</td>

      <tr class="data alt">
        <td class="item">2. Banana</td>
        <td class="item">210</td>
        <td class="item">0.4</td>

      <tr class="data">
        <td class="item">3. Cat</td>
        <td class="item">300</td>
        <td class="item">0.2</td>

      <tr class="data alt">
        <td class="item">4. Dog</td>
        <td class="item">200</td>
        <td class="item">3</td>

Note that there are multiple trs having the marker class data. These are repeated in alternating succession, and this is the preferred way to expand table templates with that cool zebra look. ;)


Yeah, Ajax is supported in a rather trivial manner. We have the shortcut method tmpl, which performs an Ajax request, interprets the resulting text as the Json representation of a data object, and expands the given template using it. It even fires the onComplete event afterwards!

E.g. the template

<div id="template">
    <div class="title"></div>
        <li class="item" />
        <li class="item alt" />
<div id="target"></div>

And the js:

tmpl('template', 'target', 'primes.php', {
    data: {

Imagine we have a primes.php that returns the primes between ‘from‘ and ‘to‘ as a Json object that looks like this:

    title:"List of some primes",

Then we have the following result:

<div id="template">
    <div class="title">List of some primes</div>
        <li class="item">2</li>
        <li class="item alt">3</li>
        <li class="item">5</li>
        <li class="item alt">7</li>
        <li class="item">11</li>
        <li class="item alt">13</li>
        <li class="item">17</li>
        <li class="item alt">19</li>

There you have it, a zebra colored list of primes. Just as advertised.

Known limitations

Plain old data is processed using Element.setText, and that means no attributes can be set currently. Take the following example.

<div id="template">
    <img class="image" />

It would be nice if the src, alt and title attributes of the img -s could be expanded like this:

<div id="target">
    <img class="image" alt="Me jumping" title="I was jumping happily" src="me_jump.jpg" />
    <img class="image" alt="Me sitting" title="I fell on my a**" src="me_ass.jpg" />
    <img class="image" alt="Me standing up" title="Then I tried to stand up" src="me_fall_again.jpg" />

But there is no way for such a thing right now. I have yet to figure out a solution. Comments are indeed welcome :)


  • as far as I know, the engine described above takes a rather novel approach, and one that meets my needs better than anything I have seen in this field to date
  • first of all, there is no custom language with ifs and fors and whatnot. This also implies there is need for a costly parser for a tiny sublanguage. Besides, in my opinion a template is no place for any control logic. Or any logic for that matter. It is far too late to process the data when it finally comes to template expansion!
  • the ‘language’ describing the template is highly declarative. Again, I don’t think a template language is for them imperative language constructs.
  • I have yet to come up with a way to set attributes in a template. Something like having data objects like {‘src’:’image.jpg’, ‘alt’:’An image…’, ‘styles’: {‘height’:’150px’, ‘border’:’1px solid black’}} and calling Element.setProperties on them might do the trick, dunno… :/
  • There should be events before and after a leaf of the template is expanded, providing some means to prevent further expansion and there should be an event after expansion is complete.
  • Stay tuned for a PHP and an ASP.NET version ;)


Download from here, change extension to js: tmpl.js


February 21, 2008

Update when user is idle

Filed under: AJAX, Javascript, MooTools, OOP — Tags: , , , , — Zeal_ @ 11:44 pm

Recently I had to update a list based on what the user entered into an input field. I thought it should somehow detect that the user finished typing, but that seemed a rather obscure notion at first glance.

But then it occured to me that it simply means that there has not been any input in, say, 1s or any specified amount of time. Even if the user just stopped for a sec or is disturbed, it is nice to have the list updated for her, and indeed, it does not interfere with what we have in mind when thinking about typing. It doesn’t destroy the feeling of “right now I am telling the computer what I want to”, it bears no interrupting quality whatsoever.

It is so simple:

<input type="text" id="typehere" />
<div id="target"></div>

and then,

new IdleUpdate('typehere', {
    onIdleChange:function(el) {
        new Ajax('stuff.php', {

In this example you can see how the class fits nicely in the MooTools style of design, and how expressive a language javascript can be. :)

Options supported are

  • delay: amount of idle time before the event is fired,
  • onIdleChange: the event handler

Needless to say, anything can be done in the event handler, not just Ajax calls but it is also nice for checking password strengts clientside or computing the total of a bill etc.

Check it out yourself, it’s well under 1K ;) You may want to change the extension. idleupdate.js

Introducing overload.js

Filed under: Javascript, MooTools, OOP — Tags: , , , — Zeal_ @ 10:09 pm

Overload.js is a tiny but handy library for MooTools, my attempt at shaping Javascript towards being a more OOP-esque language. It lets you overload methods of a class to do different things based on their actual parameters.

Although it is not production code yet, it works pretty much as expected. Call it 0.1, and maybe spice it with a touch of “beta” too ;)

A class with an overloaded method, setColor, looks like this:

var Color=new Class({
	initialize:function() {
		"string":function(s) {
			var r = parseInt(s.substr(1,2), 16);
			var g = parseInt(s.substr(3,2), 16);
			var b = parseInt(s.substr(5,2), 16);
		"int int int":function(r,g,b) {
			this.r = r;
			this.g = g;
			this.b = b;
	toString:function() {
		return '#' + this.r.toString(16) + this.g.toString(16) + this.b.toString(16);

Here, setColor may be called with either one argument of the type ‘string’, or three arguments of the type ‘int’. It is worth noting that type matching is done via the following function:

function match_type(type_name, arg) {
    switch(type_name) {
        case 'string': return $type(arg) == 'string';
        case 'int': return ($type(arg) == 'number') && (!arg.toString().contains('.'));
        case 'float': return ($type(arg) == 'number') && (arg.toString().contains('.'));
        case 'array': return ($type(arg) == 'array');
        case 'object': return ($type(arg) == 'object');
    return eval('arg instanceof ' + type_name);


  • a string, an array or an object argument is recognized based on their types
  • a float or an integer argument is recognized based on their type being number, and whether if they contain or don’t contain a decimal dot, respectively.
  • an argument of any class (e.g. Element or Ajax) is recognized using eval and instanceof.

I think the most serious problem with the current implementation is that there is no fallback mechanism should formal parameter type matching fail. So,

var c = new Color();

c.setColor("first", "second");

doesn’t call any of the overloaded methods, nor does it notify the user.

Please find attached overload.js in its present form: overload.js.

Comments are welcome! :)

Blog at