HTML Namespace Attributes and IE document.namespaces

A few posts ago I promised to elaborate on a little gotcha that bit us in the butt while prepping the "blocks" to enable Popfly apps to use the Windows Live Contacts web control and Windows Live Spaces web control

Here it is:   IE has a handy document.namespaces object that reflects the namespaces defined in attributes of the HTML element of the page. 

The gotcha:   document.namespaces does not track with attributes that are dynamically added to the HTML element after page load.

The situation: "blocks" in Popfly can emit HTML code to set up shop in the application host page, but they do not have control over the host page's HTML tag.  Since our web controls pretty much requires namespaces (that's a bug - they should work with or without namespaces), we tossed in a quick fix in the Popfly block:  look up the html element and use setAttribute to set the namespace attributes we would have set on the html tag if we had access to it.

Result:   worked great in Firefox, but that was only because Firefox doesn't provide any support for namespaces in HTML docs.  I ranted on this awhile back.  You have to serve up content type text/xml in order to get Firefox's namespace support to kick in, but doing that kills all the JavaScript on your page, among other things, and in general one should not take lightly renaming HTML as XML or visa-versa.  It'll sneak up and bite you when you least have time to deal with it.

Result2: Didn't work in IE.  Our bootstrap code in the contacts control takes advantage of document.namespaces in IE, and falls back to savage spelunking to find the namespace attributes the hard way in Firefox and other browsers.  document.namespaces is populated when the html document is being loaded and is not updated after it has loaded.  Our quick fix of adding the namespace attributes to the html element in our Popfly code block had no effect because they were added after document.namespaces was locked down.

Solution:   Change the Popfly code block to call document.namespaces.add() if document.namespaces exists, otherwise add the namespace attributes to the html element.  Do it. Test it. Ship it. Whew!