JavaScript innerHTML v. outerHTML / DOM Engine Epic Fails
I was messing around with javascript today and I recognized one major issue when updating the innerHTML of an object versus the outerHTML. Namely, that objects updated with HTML content via outerHTML do not allow subsequent access to interior objects within that HTML content. The DOM engine (at least in Firefox) will not recognize the interior elements when outerHTML is used, but WILL if innerHTML is used.
The Scenario
Suppose you have just created a div object dynamically in javascript. In other words, you’ve created a div object in code versus its existence in the actual HTML document. For example, this code:
var o = document.createElement(“div”);
Would create this type of HTML:
<div></div>
Next, imagine that you have a string of HTML that you would like to make up this <div> element. For the sake of argument, pretend you have a variable ‘html’ and this contains the HTML you would like to make up everything of your new dynamically created <div> object including the tag itself:
var html = “<div id=’mydiv’ a=’1′ b=’2′><img src=’foo.jpg border=’0′ width=’5′ height=’5′ /></div>”;
At this point one may be tempted to make a call such as this:
o.innerHTML = html; // do not actually do this
This would be wrong to do, however, since that would result in the following HTML being created for o:
<div><div id=’mydiv’ a=’1′ b=’2′><img id=’myimg’ src=’foo.jpg border=’0′ width=’5′ height=’5′ /></div></div>
The better option (at least logically) would be to update the outerHTML of o which is supposed to replace the entire HTML contents of o including the tag itself:
o.outerHTML = html; // this should work… but
This does actually work, and and the DOM engine actually updates the entire o object with the appropriate content. If that’s all you need, then you’re set.
But, there is a problem if you need to do more… If you need to access your <img> object programmatically a few lines after you’ve created o (note the <img> object is now part of the <div>’s content) then you’re shit out of luck. Any attempts to do the following will return a null object:
var i = document.getElementById(“myimg”); // if you’ve used outerHTML the DOM engine won’t know ‘myimg’ exists yet
If you try to do this, after using outerHTML, the DOM engine will not recognize ‘myimg’ as having been created yet. The DOM engine WILL, however, recognize ‘myimg’ as having been created if you use innerHTML! So what gives!?
Whatever the problem is, my solution was to create my <div> object programmatically, have my HTML content just be the <img> tag itself, and then to update the innerHTML as the image. THEN you need to programmatically update the attributes of the <div> object. It’s a pain, I know, especially if you’ve streamed HTML content from an AJAX call, etc. Anyway, a final solution would be something like this:
var html = “<img src=’foo.jpg border=’0′ width=’5′ height=’5′ />”;
var o = document.createElement(“div”);
o.innerHTML = html;
o.setAttribute(“a”, “1″);
o.setAttribute(“b”, “2″);
o.id = “mydiv”;
document.getElementById(“myimg”).src=”bar.jpg”;
I spent a good two hours dissecting the innards of Firefox’s DOM and just came up with, “Why?” Anyway, I hope this helps people.