Theory:
Last few days I’ve been looking a template engines and came across some really fine and sleek solutions including PURE, EJS, Jhon Resig’s Micro Templates, jsTemplates, YAJET and a list of on going ones. I was constantly in pursuit of simplicity, minimality! To sum up engines claiming micro were just and overkill for my scenario. Templating at times is pretty trivial a simple case might be display set of links fetched from JSON in anchor tags, displaying list of emails with DIV elements, replacing items in a template URL etc. Having such a full fledged template engine on such puny never makes sense to me (yes I did this in some of my recent projects). I used String.prototype.replace at a lot of places and did some boilerplate work for saving extra lives at times (Yep I know there are loads of template engines out there doing this; but I required a precisely fine tuned engine). So in my labs I did another experiment and came up with my own version of really bare-bones yet flexible template engine. Checkout demo here.
Practical:
Well here is what I came up with (not meant for good readability but for experts it won’t be a problem). But full-fills the purpose its under almost 350 bytes and when YUI compressed goes under 330 bytes:
function fitb(tar, data, opt) {
var reg = /(:\w+)/g,
iht = tar.innerHTML,
tpl = ((tar._$$f = tar._$$f || iht)) || tar;
opt = opt || {};
return (
iht &&
(tar.innerHTML = ((opt.append && tar.innerHTML) || "") + (opt.pre||"")+fitb(tpl, data, opt)+(opt.post||""))
) || (
data.length &&
data.map(function(el) { return fitb(tpl, el, opt); }).join(opt.glue || "")
) || (
tpl.replace(reg, function(match) { return (data[match.substr(1)] || opt.none || "");})
);
};
Now what about usage
// :name is replaced by Looping and :type is replaced by array
fitb('hello :name this was a simple :type. ', {'name': 'Looping', 'type': 'array'});
// outputs "hello A this was a simple array. hello Looping this was a simple array.
fitb('hello :name this was a simple :type. ', [{'name': 'Again', 'type': 'array'}, {'name': 'Looping', 'type': 'array'}]);
Wait that’s not it! It can do more once you use third parameter:
// outputs "hello A this was a simple array.
hello Looping this was a simple array. fitb('hello :name this was a simple :type. ', [{'name': 'Again', 'type': 'array'}, {'name': 'Looping', 'type': 'array'}], {glue: '
'});
That’s still not enough, you can even do direct operations on a DOM node:
// innerHTML of DOM node is used as template string and cached
fitb(document.getElementById('myNode'), [{'name': 'Again', 'type': 'array'}, {'name': 'Looping', 'type': 'array'}]);
// Calling multiple times is not effected by innerHTML of DOM node (it cache's original template string).
firtb(document.getElementById('myNode'), [{'name': 'Some other data', 'type': 'array'}, {'name': 'More data', 'type': 'array'}]);
// Append the templated results in myNode excellent for adding new data
firtb(document.getElementById('myNode'), [{'name': 'Again', 'type': 'array'}, {'name': 'Looping', 'type': 'array'}], {append: true});
It’s pretty minimal yet usable; you can checkout demo here.
Design by Simon Fletcher. Powered by Tumblr.
© Copyright 2010