Created
October 26, 2010 05:04
-
-
Save furf/646361 to your computer and use it in GitHub Desktop.
JavaScript Micro Templating
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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; | |
}; | |
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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