DHTML Templates Tutorial

I've been playing around recently with storing small DHTML templates into my page, that I can then grab from JavaScript, do string substitution of variables in the template, and then add to the page.

The essential technique is you store your template into an HTML comment:
<div id="template">
<!--
<html>
<head>
<script language="JavaScript">
function sayHello() { alert("%message%"); }
</script>
</head>
<body onload="sayHello()">
<p>%message%</p>
</body>
</html>
-->
</div>
We surround our magic variables in the template with %; in the example above we only have one, %message%.

Once the page is finished loading, you can then grab the template and replace its values with your own; in the code below we have a method initialize that is called when the page is finished loading with a message that will be written into the template, "Hello Template World!":
<script language="JavaScript">
function initialize(message) {
// get our template that we will write into the iframe
var templateDiv = document.getElementById("template");
var currentElement = templateDiv.firstChild;
// loop until we get a COMMENT_NODE
while (currentElement && currentElement.nodeType != 8) {
currentElement = currentElement.nextSibling;
}
var template = currentElement.nodeValue;

// replace the templated value in the constants with
// our new value
var newContent = template.replace(/\%message\%/g, message);

// get our iframe
var testFrame = document.getElementById("testFrame");

// now write out the new contents
var doc = testFrame.contentDocument;
if (doc == undefined || doc == null)
doc = testFrame.contentWindow.document;
doc.open();
doc.write(newContent);
doc.close();
}
</script>
The first thing we do is grab our template:
// get our template that we will write into the iframe
var templateDiv = document.getElementById("template");
var currentElement = templateDiv.firstChild;
// loop until we get a COMMENT_NODE
while (currentElement && currentElement.nodeType != 8) {
currentElement = currentElement.nextSibling;
}
var template = currentElement.nodeValue;
We get the div that holds the template, get its first child, and then loop until we encounter a COMMENT_NODE in the DOM (node type 8). Once we do, we then extract the value in the comment (currentElement.nodeValue).

Next, we then do a string substitution using JavaScript regular expressions:
// replace the templated value in the constants with our
// new value
var newContent = template.replace(/\%message\%/g, message);
Then, we grab our iframe and write out the templated contents:
// get our iframe
var testFrame = document.getElementById("testFrame");

// now write out the new contents
var doc = testFrame.contentDocument;
if (doc == undefined || doc == null)
doc = testFrame.contentWindow.document;
doc.open();
doc.write(newContent);
doc.close();

Try out the demo and see the full source code. You should see a popup that says "Hello Template World!" and should see the same value written into the iframe that is visible with a box around it.

This has been tested in IE 6+ and FireFox.

What's good about this technique:
  • You can store all sorts of gnarly code that would be a pain to have in JavaScript strings or that would cause issues if you had it in a hidden div.
  • No encoding issues! You can have greater and lesser signs and tags in your code without sitting there converting them to entities, such as < and >
  • If you are solving DHTML history issues, you don't need a blank.html type document to load into your iframe. Just write the contents of blank.html into the hidden iframe....
  • You can have small reusable templates that you just change, for each row of a dynamic table, for example.
What's bad about this technique:
  • Should we really be using comments to hold application state and presentation information?

Comments