Oct 17 2010

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.


Jun 15 2010

HTML5 Geolocation on iPhone

The iPhone’s latest version of Safari supports HTML5 Geolocation Services.  To the average mobile phone user this might not seem like a big deal, but for web developers it’s huge.

In the past, web developers who needed to get latitude/longitude coordinates in Javascript were required to make server-side AJAX calls and base coordinates off of IP addresses and shaky algorithms.  The process was time-consuming (even using asynchronous calls) and burdensome to the server.  If constant updates were required, an ill-equipped server would overload.  Simply put, web browsers lacked the ability to support  robust real-time geolocation updates.

HTML5, the newest standards outlined by W3C, sought to change that with Geolocation Services.  Now, major website browsers (such as Safari and Firefox) come with the ability to retrieve latitude and longitude coordinates within Javascript as an integrated part of the browser itself.  This means that a programmer can now ask an HTML5 enabled browser to return coordinates without ever making an AJAX call.  The process follows this pattern: programmer makes request to the browser, browser pings its geolocation service provider, the geolocation service provider responds to the browser, the browser updates its Javascript coords object with the relevant information including latitude and longitude for the programmer to then work with.  The speed is incredibly fast compared to the old method, and is also incredibly accurate down to a few 100 meters.

Even more important, the programmer can register a callback function to constantly be executed asynchronously with updated positions.  This allows a lot of exciting things to be done.  For instance, I developed a very basic speedometer website (calculating MPH) at http://www.geigel.com/html5/speed.php that can be used on my iPhone.  To test this, open your mobile Safari browser to the website URL and then start driving down the road in your car.  Although the updated speed appearing on the website is not as precise or responsive as the MPH the car shows, the experiment illustrates what is now possible using HTML5.

What I find interesting beyond the mere technical/programming doors that HTML5 has opened is the behind-the-scenes battle from search-engine companies to be the exclusive provider of geolocation data for the major browsers.  After all, geolocation data doesn’t just magically come into existence simply because HTML5 says it should.  A company needs to process a request from the browser and respond quickly.  Obviously, Internet Explorer will rely on Microsoft as its sole provider of information (when, and if, IE decides to support geolocation).  Similarly, Chrome will use Google, however it is unclear if a Gears plugin will be required versus being natively built into the browser.  The real competition occurs when you begin looking at who will supply information for Firefox and Opera.  At present, Firefox relies on Google (http://www.mozilla.com/en-US/firefox/geolocation/).  Opera, on the other hand, seems to currently be going with a third-party geolocation service provider named Skyhook (http://labs.opera.com/news/2009/03/26/).  Whether these browsers will stick with these providers remains to be seen.

Whatever all of this means for the future of websites, the W3C, and major players is unclear.  What is clear is that users of the technology are going to experience a richer  browsing session with location aware websites.  Equally clear is that geolocation providers will gain significant amounts of anonymous technical data about user positions, trends, etc. which can be scary for privacy-minded individuals.  Thankfully, the W3C cared enough to require in their specification that browsers should warn users when their position is being tracked, and ask that these services be activated.