Thursday, November 30th, 2006

DOMTool: Given HTML generate DOM methods

Category: JavaScript, Library, Utility

<p>Stuart Colville has developed a tool for generating DOM methods from an HTML snippet called DOMTool:

The idea is that you drop a snippet of HTML in the input and the tool puts it into the document with innerHTML and then loops through that structure to generate the DOM methods needed to append that piece of HTML into a document from a script. There’s a kind of beautiful irony in using innerHTML to generate DOM methods.

I’ve added a basic compat function to handle the problem with name attributes in IE so this would need to be included in the end-user’s script should they be trying to create any elements with name attributes. This function only appears when name attributes are present in the input.

Users should also bear in mind that the ouput will not necessarily be optimal but it should be fairly easy to take the output and use it as a basis for production code.

Example

Say you hand the tool:

  1. <p>test1</p>
  2. <p>test2</p>
  3. <p>test3</p>

You will get back:

javascript
< view plain text >
  1. var p1=document.createElement('P');
  2. var txt1=document.createTextNode(’test1′);
  3. p1.appendChild(txt1);
  4. var p2=document.createElement(’P');
  5. var txt1=document.createTextNode(’test2′);
  6. p2.appendChild(txt1);
  7. var p3=document.createElement(’P');
  8. var txt1=document.createTextNode(’test3′);
  9. p3.appendChild(txt1);

If you want to give it a whirl, visit the tool here: DOMTool 1.01

Related Content:

10 Comments »

Comments feed TrackBack URI

I like the idea. Some will say, “Well, what about innerHTML?” This isnt for replacing the simple innerHTML (i use innerHTML whenever possible). Lets say you have a complex dynamically made chunk of DOM goodness and you just dont want to have to spend all the time crating the dom. You drop it in, then pick out the peaces you need.

Comment by Mario — November 30, 2006

I was actually thinking of writing something like this myself. Guess that I don’t have to now.

Comment by Andy — November 30, 2006

Very interesting! That is quite something. ;)

I’m personally a fan of cloning HTML templates, (grabbing a collection of nodes and using cloneNode(true),) which would also work with the HTML-based approach given here. (This was used extensively for Yahoo! Photos and worked quite well.)

You may still have to modify each instance slightly for your uses, but the structure would be left intact – and that saves you a lot of time. It’s also very simple if someone wants to modify your template structure, since it’s HTML! I’ve learned over the years that it seems best to leave HTML where it works best (as HTML), and not to create big complex structures of it using Javascript (but cloning and extending/customising with JS where appropriate.)

Comment by Scott Schiller — November 30, 2006

Really cool. This is going to save me some time, thanks!

Comment by Mark Holton — November 30, 2006

Sounds a lot like Jack yui-ext DOMHelper object (www.jackslocum.com) which does this and supports templated building of repeating elements. He also has a blog post about performance of innerHTML vs this type of approach.

Comment by Tim — November 30, 2006

This is neat. I was thinking of writing something like this myself. Ideally, one should be able to do dojo like attachpoints inside the html via annotations, and have the code create equivalent variables that are visible externallly. This will then be a simpler static version of dojoj widgets..

Comment by Vijay Chakravarthy — November 30, 2006

One drawback is not being able to assign JS vars to elements as they are created. I much prefer the approach published by Michael Geary and inspired by MochiKit.DOM:

http://mg.to/topics/programming/javascript/jquery

It really makes creating DOM fragments much, much simpler.

Comment by James Cook — December 1, 2006

Thanks, James.

To compare the different techniques, let’s try a more interesting bit of HTML code:


<div id="test" class="outer">
<span class="inner">
<a href="example.html" title="Howdy">
Click me
</a>
</span>
</div>

Here’s the output from DOMTool:


var div1=document.createElement('DIV');
div1.className='outer';
div1.setAttribute('id','test');
var span1=document.createElement('SPAN');
span1.className='inner';
div1.appendChild(span1);
var a1=document.createElement('A');
a1.setAttribute('title','Howdy');
a1.setAttribute('href','example.html');
span1.appendChild(a1);
var txt1=document.createTextNode('Click me\n ');
a1.appendChild(txt1);

Here’s how you would code it with my DOM creation functions:


$.DIV({ id:'test', 'class':'outer' },
$.SPAN({ 'class':'inner' },
$.A({ href:'example.html', title:'Howdy' },
'Click me'
)
)
);

And here is how it be using Olsow’s DOM creation function (posted in the comments to my page that James referenced):


$.create(
'div', { id:'test', 'class':'outer' }, [
'span', { 'class':'inner' }, [
'a', { href:'example.html', title:'Howdy' }, [
'Click me'
]
]
]
);

Comment by Michael Geary — December 1, 2006

Hmm… A comment system on a blog frequented by coders should allow indentation! Assume proper indentation in the code above… :-)

Comment by Michael Geary — December 1, 2006

Actually, James, with DOMTool you can save references to the objects as they are created. In fact, it looks like the generated code creates a unique variable name for each DOM element, so you are all set.

Mine also allows you to save references to inner objects. If you wanted the inner A element from my example, you’d do this:


var a;
$.DIV({ id:'test', 'class':'outer' },
$.SPAN({ 'class':'inner' },
a = $.A({ href:'example.html', title:'Howdy' },
'Click me' ) ) );

Olsow’s function doesn’t let you save references to inner elements – it just gives you a jQuery object for the topmost element(s).

Comment by Michael Geary — December 1, 2006

Leave a comment

You must be logged in to post a comment.