All in the <head> – Ponderings and code by Drew McLellan –

Inner Demon

A web developers who have done any level of client-side document manipulation will be familiar with an object’s innerHTML property. Every object in the page (I think I’m right in saying every object) has this property which holds that object’s contents as a string. Take the following markup snippet:

<div id=“myDIV”>What a <em>lovely</em> day!</div>

Using JavaScript, I could create a variable that points to that object, and then get the contents using the innerHTML property:

var obj = document.getElementById(‘myDIV’);
var contents = obj.innerHTML;
// contents == ‘What a <em>lovely</em> day!’

All very straightforward. This is useful by itself, but the really neat part comes in being able to set the property as well as getting it. If we wished to wrap our lovely day statement in a paragraph, that would be very easy indeed:

var obj = document.getElementById(‘myDIV’);
var contents = obj.innerHTML;
obj.innerHTML = ‘<p>’ + contents + ‘</p>’;

This functionality enables a developer to manipulate the document on-the-fly, and is an invaluable technique when building more complex user interfaces. However, useful it may be, but standard it is not. That is to say it’s not part of the W3C Document Object Model. It is, however, actively supported and maintained by just about every browser you’d need to care about – it’s supported because it’s damn useful.

To be honest, I can see why it’s not part of the W3C DOM. The DOM deals with a document as a tree-like nest of objects not as a big string. To grab one of those objects and then start manipulating it as a string is pretty filthy and would require the whole document to be parsed again once complete, so it makes sense that in writing a new specification that this would be left out. It’s impure.

The alternative to innerHTML is far more logical – you create a new node as an object. You then prepare it with whatever attributes and content that you need, and append it as a child of the existing item you wish to use as its parent. That’s pretty consistent with the model and makes perfect sense. It is, however, a royal pain in the arse. It’s long-winded, awkward and bloated and I hate it, hate it, hate it. Instead of quickly manipulating a string and chucking it back at the innerHTML property, you have to painstakingly build it up, tag by tag and attribute by attribute and then append it back to the document. It takes forever and it really hurts.

I was thinking that it should be possible to write a function something like setInnerHTML() to parse a string out and programatically create all the necessary objects. It would be tricky to write, but should be possible. It would also be pretty huge, and for smaller manipulations would be way too expensive to include. Surely there has to be a solution to this. Have I just overlooked something really obvious in the DOM spec?