Skip to content

Instantly share code, notes, and snippets.

@furf
Created October 26, 2010 05:04
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save furf/646361 to your computer and use it in GitHub Desktop.
Save furf/646361 to your computer and use it in GitHub Desktop.
JavaScript Micro Templating
// Simple JavaScript Templating
// John Resig - http://ejohn.org/ - MIT Licensed
// @see http://ejohn.org/blog/javascript-micro-templating/
(function(){
var cache = {};
this.tmpl = function tmpl(str, data){
// Figure out if we're getting a template, or if we need to
// load the template - and be sure to cache the result.
var fn = !/\W/.test(str) ?
cache[str] = cache[str] ||
tmpl(document.getElementById(str).innerHTML) :
// Generate a reusable function that will serve as a template
// generator (and which will be cached).
new Function("obj",
"var p=[],print=function(){p.push.apply(p,arguments);};" +
// Introduce the data as local variables using with(){}
"with(obj){p.push('" +
// Convert the template into pure JavaScript
str
.replace(/[\r\t\n]/g, " ")
.split("<%").join("\t")
.replace(/((^|%>)[^\t]*)'/g, "$1\r")
.replace(/\t=(.*?)%>/g, "',$1,'")
.split("\t").join("');")
.split("%>").join("p.push('")
.split("\r").join("\\'")
+ "');}return p.join('');");
// Provide some basic currying to the user
return data ? fn( data ) : fn;
};
})();
<script type="text/html" id="helloTmpl">
<%
/*
We'll be nice and safe inside our template and use var to create
some pretty display values.
*/
var name = name.toUpperCase();
var age = age + 1;
%>
HELLO, <%= name %>. YOU WILL BE <%= age %> NEXT YEAR.
</script>
// Grab the template data from our <script> tag.
var template = document.getElementById('helloTmpl').innerHTML;
// Convert the template data a renderer function.
var renderer = tmpl(template);
// Objectify me.
var furf = {
name: 'furf',
age: 37
};
// Let's inspect furf.
console.dir(furf);
// {
// age: 37
// name: 'furf',
// }
// Looks good so far. Now let's render our template to the console.
console.log(renderer(furf));
// HELLO, FURF. YOU WILL BE 38 NEXT YEAR.
// Awesome! Looks like our template is rendering just fine. Now, let's
// check in on me and see how I'm doing.
console.dir(furf)
// {
// age: 38
// name: 'FURF',
// }
// GAK! Another year older and louder!
// It seems inside a with statement, even "var" will not protect your
// object when declaring a variable with a name that matches one of its
// properties.
// The fix? DON'T USE WITH(){}!
// Instead, wrap the renderer function with one that calls it in the
// context of the data object and use the this keyword to access its
// values.
// Minor inconvenience? Sure. The benefit of clarity, worth it.
this.tmpl = function tmpl(str, data){
// Figure out if we're getting a template, or if we need to
// load the template - and be sure to cache the result.
var fn = !/\W/.test(str) ?
cache[str] = cache[str] ||
tmpl(document.getElementById(str).innerHTML) :
// Generate a reusable function that will serve as a template
// generator (and which will be cached).
new Function("obj",
"var p=[],print=function(){p.push.apply(p,arguments);};" +
// Introduce the data as local variables using with(){}
"p.push('" +
// Convert the template into pure JavaScript
str
.replace(/[\r\t\n]/g, " ")
.split("<%").join("\t")
.replace(/((^|%>)[^\t]*)'/g, "$1\r")
.replace(/\t=(.*?)%>/g, "',$1,'")
.split("\t").join("');")
.split("%>").join("p.push('")
.split("\r").join("\\'")
+ "');return p.join('');");
function wrap (data) {
return fn.call(data);
}
// Provide some basic currying to the user
return data ? wrap( data ) : wrap;
};
<script type="text/html" id="helloTmpl">
<%
/*
Now we can safely declare new variables inside our template.
(Though this is probably still bad form and a view of the
object should be passed in instead rather than the object
itself.)
*/
var name = this.name.toUpperCase();
var age = this.age + 1;
%>
HELLO, <%= name %>. YOU WILL BE <%= age %> NEXT YEAR.
</script>
console.dir(furf);
// {
// age: 37
// name: 'furf',
// }
console.log(renderer(furf));
// HELLO, FURF. YOU WILL BE 38 NEXT YEAR.
console.dir(furf)
// {
// age: 37
// name: 'furf',
// }
// Yay! I made it out unscathed! Still young and pretty.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment