A Simple, Lightweight JavaScript Templating Engine

Update – Armin has an alternate implementation based on some fancy regular expressions combined with String’s split method. Its supports most of ERB and avoids all the string mashing I do. Nice!

Templating engines are the most popular way to generate HTML pages and other web content. First popularized by PHP and ASP , templating engines allow you to mix code and content. The templating engine then takes the combined content, extracts the code, runs it, and combines the results with the remaining content to produce the final output.

Since templating engines are generally used to create HTML that is displayed by a browser, they are almost always run on a server. But now that all modern browsers support the DOM, XML and Ajax, it can be helpful to run a templating engine on the client.

Before continuing, remember that JavaScript templates are often not the right solution. Alternatives include generating HTML on a server, or if you are using XML, to use XSL on the client or server to generate HTML.

But if you need something simple and light, perhaps to display a JSON result returned by an Ajax request, then JavaScript templates may fit the bill.

Writing the Templating Engine

A quick search on the Internet found a few existing engines, such as JavaScript Templates, Ajax Pages and the Prototype library. However, I found the first two to be a bit heavyweight while Prototype was a bit to simple (it only supports the replacement of values, not the execution of arbritrary statements such as for loops). So I decide to roll my own.

Creating a template engine in JavaScript is remarkably easy due to the power of String’s replace method. One of its lesser known features is that you specify a function to invoke every time a pattern is matched. The pattern is replaced by the results of the invoked function. Using replace, you can write a template compiler in ten lines of code (and undoubtedly less if you wanted to).

The whole templating engine weighs in at 90 lines, including a helper function copied from the Prototype library. The engine defines two objects – a template object and a parser object. The template object takes a string that includes mixed code and content, invokes the parser to compile the template, and then evaluates and returns the result.

Using the Templating Engine

To see how this works, I’ve created a simple example that is online. If you look at the HTML code, you’ll see:

function replaceContent()
{
  var colorsArray = ['Red', 'Green', 'Blue', 'Orange']
  var source = 
    '<p>Here is a list of <%= this.colors.length %> colors:' + 
    '  <ul>' +
    '    <% for (var i=0; i<this.colors.length; i++) { %>' + 
    '      <li><%= this.colors[i] %></li>' + 
    '    <% } %>' + 
    '  </ul>' +
    '</p>'
 
   var template =  new JsTemplate.Template(source)
   var content = template.run({colors: colorsArray})

   var element = document.getElementById('content')
   element.innerHTML = content
}

The first thing to notice is that the source variable specifies the mixed code and content. The syntax is similar to ERB, which is a Ruby templating engine. The two recognized tags are:

<% %>   Run JavaScript code
<%= %>  Replace JavaScript code with the result

To create your own tags create a new Parser object with an appropriate regular expression.

The second thing to notice is that the data use by the template engine is specified via a parameter to the run method. The parameter should be a JavaScript object. The properties of the object are copied to the template object, thus allowing the template to refer to them via the this keyword. And that is about it (I said it was lightweight!).

To source code of the templating engine is here, while the example is here. Note the code is released under an MIT license, so you can use it however you would like. Enjoy.

  1. Sebastian Good
    June 14, 2007

    Clever. As a minor performance enhancement, might I suggest using a common JavaScript idiom for building large strings. Your compiler turns literals in the output into strings which are added to the “out” variable using +=, meaning an entire new string is allocated. These strings get bigger and bigger, leading not just to wasted memory but also (roughly) quadratic running time. Big templates will suddenly be a lot slower than small ones.

    Might I suggest you use the following pattern.

    var out = [];
    out.push “string1”;
    out.push “string2”;
    out = out.join(“”); // “string1string2”

    Each generated string is simply added to a list and then in one fell swoop the (very fast) compiled function join can make them into your final output.

    Reply
  2. http://abstractfinal.blogspot.com
    June 14, 2007

    Very cool… As you mentioned, most useful when accessing services that return json.

    Reply
  3. Charlie Savage –
    June 14, 2007

    Sebastian – that is an excellent point. I have to admit that I’m a bit embarrassed that it didn’t occur to me – I use the same trick a fair bit. Anyway, I’ll update the code and repost it.

    Reply
  4. Charlie Savage –
    June 14, 2007

    Keyur – Thanks for the comment. I hadn’t seen your blog before, looks great. I’ll have to dig through your REST posts, its a favorite topic of mine.

    Reply
  5. Mark Turansky
    March 5, 2008

    Looks good and I like your use of the familiar < % and %>, but concatenating that string template looks painful to me as a developer.

    I wrote a similar JavaScript Template engine with JSP-like syntax where you can embed the template right in the page itself w/o having to concat a large string.

    JavaScript Templates

    Reply

Leave a Reply

Your email address will not be published.

Top