Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist

JavaScript Micro Templating

View 1-tmpl.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
// 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;
};
})();
View 1-tmpl.js
1 2 3 4 5 6 7 8 9 10 11
<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>
View 1-tmpl.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
// 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.
View 1-tmpl.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
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;
};
View 1-tmpl.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14
<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>
View 1-tmpl.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
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
Something went wrong with that request. Please try again.