spudly.shuoink.com

the best way to predict the future is to implement it

Entries Comments


Using the XML DOM Without Writing 15,0000 Lines of Code

20 February, 2008 (22:17) | JavaScript

I’m a pretty big fan of using the XML DOM rather than innerHTML, simply because it seems to me to be better programming style. I hate hate hate, however, that it takes 15 lines of code to create one node. Today, I came up with an idea to solve the problem. I created a wrapper function for document.createElement() that takes either a string or an object literal as an argument. Then, based on the data in this argument, I create the needed element(s). Here’s a simple example that creates a text node:

var node = createElements("Hello World!");
document.body.appendChild(node);

Ok, so the above example is pretty useless, but what if you wanted to make that text into a link. the createElements() function allows us to pass an object literal with four items: tag, attributes, style, and children. “Tag” is, of course, the type of HTMLElement you want to create. “Attributes” is another object literal containing the attributes for the html tag (src, href, etc…). “Style” is an object literal containing the style attributes you want applied to the element, and last but certainly not least, “children” allows you to nest elements. It is an array of either strings or object literals, just like the ones you would pass into this function. Each of these children will be recursively created and appended to the main element. Here’s an example that creates a link to google:

var node = createElements({
	 tag: "a",
	 attributes: {
		href: "http://www.google.com"
	 },
	 style {
	    textDecoration: "none"
	 },
	 children: [ "Click Here!" ]
});
document.body.appendChild(node);

And here’s a more complex example that really shows off the nesting power of this javascript function:

var node = createElements({
   tag: "div",
   attributes: {
	  id: "google_link"
   },
   children: [
	  {
		 tag: "a",
		 attributes: {
			href: "http://www.google.com"
		 },
		 style: {
			textDecoration: "none",
			fontWeight: "bold"
		 },
		 children: [
			{
			   tag: "img",
			   attributes: {
				  src: "http://www.google.com/intl/en_ALL/images/logo.gif",
				  alt: "Google!",
				  title: "Google!",
				  border: "0"
			   },
			   style: {
				  width: "200px",
				  height: "200px"
			   }
			},
			{
			   tag: "br"
			},
			"Click here to go to Google!"
		 ]

	  }
   ]
});
document.body.appendChild(node);

The above example creates the following code:

<div id="google_link">
	<a style="text-decoration: none; font-weight: bold;" href="http://www.google.com">
		<img style="width: 200px; height: 200px;" title="Google!" alt="Google!" src="http://www.google.com/intl/en_ALL/images/logo.gif" border="0">
		<br />
		Click here to go to Google!
	</a>
</div>

As you can see, it’s quite a bit easier to use than typing mynode.setAttribute 20 times. Here’s the source code:

function createElements( args ) {
   var el;

   if( typeof(args) == "string" ) {

      el = document.createTextNode(args);

   } else if ( typeof(args) == "object" ) {

      el = document.createElement( args.tag );

      if ( args.attributes ) {
         for ( i in args.attributes ) {
            el.setAttribute(i, args.attributes[i]);
         }
      }
      if ( args.style ) {
         for ( i in args.style ) {
            el.style[i] = args.style[i];
         }
      }
      if ( args.children ) {
         for ( var i = 0; i < args.children.length; i++ ) {
            el.appendChild( createElements( args.children[i] ) );
         }
      }

   }
   return el;
}

« PHP Error Log Parser

 

Comments

Comment from spudly
Time: February 21, 2008, 8:02 am

Just a side note - If you were to write the above example without my method, you would have to write the code below, which is horribly ugly:

var div = document.createElement("div");
node.setAttribute("id", "google_link");
var a = document.createElement("a");
a.setAttribute("href", "http://www.google.com");
a.style.textDecoration = "none";
a.style.fontWeight = "bold";
var img = document.createElement("img");
img.setAttribute("src", "http://www.google.com/intl/en_ALL/images/logo.gif");
img.setAttribute("alt", "Google!");
img.setAttribute("title", "Google!");
img.setAttribute("boder", 0);
img.style.width = "200px";
img.style.height = "200px";
a.appendChild(img);
var br = document.createElement("br");
a.appendChild(br);
var text = document.createTextNode("Click here to go to Google!");
a.appendChild(text);
div.appendChild(a);

… whereas the example I gave could be condensed to:

var node = createElements({
   tag: "div", attributes: { id: "google_link" }, children: [
      {
         tag: "a",
         attributes: {href: "http://www.google.com"},
         style: {textDecoration: "none",fontWeight: "bold"},
         children: [
            {
               tag: "img",
               attributes: {
                  src: "http://www.google.com/intl/en_ALL/images/logo.gif",
                  alt: "Google!", title: "Google!", border: "0"
               },
               style: { width: "200px", height: "200px" }
            },
            { tag: "br" },
            "Click here to go to Google!"
         ]
      }
   ]
});

As you can see, there is a lot less typing involved…

Comment from NelsoN
Time: February 23, 2008, 10:50 pm

Due to several bugs in IE, your (otherwise very nice method) will fail on a bunch of the attributes you pass it..
http://webbugtrack.blogspot.com/2007/08/bug-242-setattribute-doesnt-always-work.html

E.g. if you try to create form elements (with a name) it will fail… setting the style will fail,… setting any event handlers will fail etc.

The good news is that only IE will fail. All other browsers are based on standards. :-)

Comment from spudly
Time: February 24, 2008, 8:51 am

Wow thanks for the info. I’ll have to give this another look, and I’ll post an update soon.

Write a comment