Simple JavaScript Templating
During a recent spurt of intensive JavaScripting the major revelation for me has been that you can use a function as the second parameter of the humble replace() method of a String.
We all know you can do this:
"Today is Tuesday".replace("Tues", "Wednes");
The result being the string "Today is Wednesday".
We probably all know you can get fancy and use Regular Expressions too. That's all old news though.
Adding Functionality To Replace
We can make the String's .replace() method even more powerful by using a function to work out what to replace any given string with. For example:
"Today is Wednesday".replace(/(\S+)day/g, function(matched, group){ switch ( group.toLowerCase() ){ case "to": return "Tomorrow"; case "wednes": return "Thursday"; case "thurs": return "Friday"; //etc default: return matched; } } );
Again, the result of this would be the string "Tomorrow is Thursday". It's probably a poor example but it proves a point -- that you can get clever about what string is used as the replacement.
It works by looking for all words that end in "day". It then looks at the bit of the string before "day" to see what the day after it will be. Or, if the bit before "day" is "To" then it returns "Tomorrow". If it's a word ending in "day" that doesn't match a know day name then we just return the matched string unchanged.
Templating With Replace
Where this becomes useful is when you want to allow your applications to be configurable by the administrator/owner. If you have a string stored in JavaScript and want to replace a part of the string with another JavaScript variable then this has just become a whole lot easier.
Imagine the following JavaScript "application":
var myApp = { version: "1.3", name: "My App", config: { messages_welcome: "Welcome to version <%= version %> " + " of <%= name %>" } } myApp.init = function(){ alert( myApp.config.messages_welcome.build() ); }
When the application's init() method is called it builds then displays a message like "Welcome to version 1.3 of My App".
String.Build() ?
To transform the string using the template I added a method called "build" to the String class' Prototype, like so:
String.prototype.build = function(){ var re=/<%=?(.*?)%>/g; return this.replace(re, function (matched, group) { return myApp[ group ] || matched; } ); };
What does this do? Well, it looks at the string you asked it to "build" for anything inside the delimiters <%= %>. When it finds one it looks to see if the MyApp object has a property with a matching name. If so then the value of that property is replaced in to the string. If the property doesn't exist that part of the string remains unchanged.
It's hard to get across just how useful this can be but I've knocked up a little demo which might help. In the demo the init() method of the app takes a set of extra configuration setting which are applied (my username in this case) to the MyApp.config object and then, in turn, applied to the welcome message.
The code is really easy to read (hence easy to support). Thumbs up!
Hi Jake,
We use opensource library trimpath for JS templating. (url: http://code.google.com/p/trimpath/wiki/JavaScriptTemplates).
We also use jquery in our recent projects and planning to use this http://ejohn.org/blog/javascript-micro-templating/ .
Thanks, I can see where this could be used in several applications.
Jake, I don't do a lot (any) of javascripting but have looked at a lot of code and never really realized what prototype was used for. I see now that you use it to add functions to existing objects. Thanks for the example!
Thumbs up indeed. Good clean use of a time tested technique. I can see you've gotten your head around OOP quite well. Most people would write a function and never consider extending the base class.