All in the <head>

– Ponderings & code by Drew McLellan –

– Live from The Internets since 2003 –

About

Inner Demon

29 January 2004

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?

- Drew McLellan

Comments

  1. § Danilo: Haven’t played with it, but I think you may be able to use a combo of document.createDocumentFragment() with document.createTextNode(), at least according to this page:
    http://www.mozilla.org/docs/dom/domref/dom_doc_ref45.html
  2. § Drew: Danilo - I’m a little confused by the example they give on that Mozilla doc page. createTextNode() does exactly that - creates text. The DIV tags in the example code would get written to the document as text, not as a new DIV element.
  3. § Chris Vincent: It would be pretty difficult to create a function that parsed a string and manually created every element. It might be possible though.

    What I would do is take all of those DOM functions for adding attributes and whatnot and wrap them into one function. It would take, for example, an array of attributes as key-value pairs and put them into the object. This function would return the object for appending (or do appending in the function itself).
  4. § Drew: Yes, I think you’d have to do it that way. Otherwise it’s a bunch of regexps and a recursive function, I think. You’d look through the string to find the first tag, process it, then pass the remaining string to another instance of the function, and return the resulting object. Something I’d rather do on the server, given the chance.
  5. § Eric TF Bat: The compromise would be to write a function that takes a semi-structured piece of data and converts either to a string (if innerHTML exists) or to a full tree of nodes. So something like this (pardon my typos; I’m rusty with JavaScript):

    ['div',{'class': 'indented'},'This is a ',['em', {}, 'lovely'], ' paragraph, don't you think?]

    would turn into this if you had innerHTML support:

    <div class="indented">This is a <em>lovely</em> paragraph, don’t you think?</div>

    or be processed by lots of tree-building code otherwise. Building strings like that is MUCH easier than having to parse the string in the tree-building case. Granted it slows down the common case at the expense of the uncommon one, but it makes your code more maintainable: arrays are easier to play with than strings with lots of concatenated variables.
  6. § Danilo: Drew,

    Damn, that’ll teach me for only looking at the example and expecting it to do what it appears what it is going to do. Sorry for the side track.

    FWIW: Going the direction of the suggestion by Eric would be harder to construct and maintain that doing it the ”DOM” way in the first place.
  7. § AttackMonkey: Yeah, wrapping all the DOM stuff into a function could be an unwieldy beast indeed...........

    Speaking of DOM stuff, does anyone know of a DOM equivalent to the MS code that allows ytou to get the selected part of a bit of text, as used in all the html editor code?
  8. § Danilo: Don’t know of it’s support, but there is document.getSelection()

    I found a page that has a NN and IE compatible version, but lists others that don’t support it (don’t know the current accuracy of the support, though). Get Selection
  9. § Morgan Roderick: Maybe it is just because I am rather tired today, but I cannot see what is so difficult in doing it with DOM.

    Or perhaps, I am doing it wrong?

    http://roderick.dk/xperiments/innerHTML.html

    Seems to work just fine in IE6 and Moz
  10. § Morgan Roderick: ... or perhaps I am just too tired to read properly...

    From msdn

    Standards Information

    There is no public standard that applies to this property.
  11. § Nishi: I have a table tag under which there is a div tag. This div tag has tr and td tags under it. How do I access the td and tr tags wrt the div tags.

Photographs

CSS Training Course: 18th July

We're running another CSS course aimed at beginners (or those wanting to freshen up!) on 18th July. Places are limited, so book soon to be sure of a place.

Work With Me

edgeofmyseat.com logo

At edgeofmyseat.com we build custom content management systems, ecommerce solutions and develop web apps.

Recent Links

Affiliation

  • Web Standards Project
  • Britpack
  • 24 ways

About Drew McLellan

Photo of Drew McLellan

Drew McLellan has been hacking on the web since around 1996 following an unfortunate incident with a margarine tub. Since then he’s spread himself between both front- and back-end development projects, and now is Director and Senior Web Developer at edgeofmyseat.com in Maidenhead, UK (GEO: 51.5217, -0.7177). Prior to this, Drew was a Web Developer for Yahoo!, and before that primarily worked as a technical lead within design and branding agencies for clients such as Nissan, Goodyear Dunlop, Siemens/Bosch, Caburys, ICI Dulux and Virgin.net. Somewhere along the way, Drew managed to get himself embroiled with Dreamweaver and was made an early Macromedia Evangelist for that product. This lead to book deals, public appearances, fame, glory, and his eventual downfall.

Picking himself up again, Drew is now a strong advocate for best practises, and stood as Group Lead for The Web Standards Project 2006-08. He has had articles published by A List Apart, Adobe, and O’Reilly Media’s XML.com, mostly due to mistaken identity. Drew is a proponent of the lower-case semantic web, and is currently expending energies in the direction of the microformats movement, with particular interests in making parsers an off-the-shelf commodity and developing simple UI conventions. He writes here at all in the head and, with a little help from his friends, at 24 ways.