innerHTML using a Pythonesque Template Object
innerHTML using a Pythonesque Template Object
There are becoming some increasingly prettier ways to hide away the verbosity of using the W3C's DOM to create anything more complicated than a single element, for example Vivabit's DOM Builder. The other option, generously donated by Microsoft, is to just throw a HTML string at the innerHTML attribute of any Element object.
As part of its standard library Python provides a Template class contained in the string module. This class makes it easy to construct templates which can be used over for several substitution operations, or just one. Recently I've been using a JavaScript implementation to generate HTML strings for use with innerHTML, letting me avoid the DOM.
The object definition is given below. It processes the string in the constructor, providing improved performance for multiple substitutions.
function Template (template) { this.template = template; var idpattern = new RegExp("^({(" + this.idpattern + ")})|(" + this.idpattern + ")"); var parts = []; var i = 0, j = 0; while ((j = this.template.indexOf(this.delimiter, i)) != -1) { if (i != j) { parts.push(this.template.substring(i, j++)); } // check for an escaped delimiter, doubled up if (this.template.charAt(j) == this.delimiter) { if (typeof parts[parts.length - 1] == "string") { parts[parts.length - 1] += this.delimiter; } else { parts.push(this.delimiter); } i = ++j; continue; } var result = this.template.substring(j).match(idpattern); if (result == null) { throw new Error("Invalid placeholder in string: index " + i); } var key = result[2] || result[3]; parts.push(key.split(".")); i = j + (result[1] ? result[1].length : key.length); } if (i != this.template.length) { parts.push(this.template.substring(i)); } this._compiled = parts; } Template.prototype.delimiter = "$"; Template.prototype.idpattern = "[_A-z][._A-z0-9]*"; Template.prototype.substitute = function (keys) { var str = ""; var i = 0, part; while (part = this._compiled[i++]) { if (typeof part == "string") { str += part; } else { for (var j = 0, value = keys; j < part.length; j++) { value = value[part[j]]; } str += value; } } return str; }
This object is great to use with a response from one of Yahoo's API calls, formatting the JSON object. An example implementation of the showUrls from my previous post would like this:
function showUrls (result) { var link = new Template('\ <p><a href="$ClickUrl" target="blank">$Title</a><br>\ <span style="color: gray;">$Note</span>' ); var links = "<div>"; var results = result.ResultSet.Result, i = 0, url; while (url = results[i++]) { links += link.substitute(url); } links += "</div>"; $("url_container").innerHTML = links; }
One thing to be careful about here however is escaping the HTML and attributes correctly. This is a poor man's E4X.
I really need to get around to setting up a code repository so that it's easier for me to maintain my snippets online, rather than just posting them to my blog and letting them stale.

0 Comments:
Post a Comment
<< Home