If I had to rate my least favorite browser bugs I’d have to put this one near the top. A holdover from the old DOM0 days it’s a practice where elements with a given name or ID are added as an expando property to another DOM node.
Here are my two favorite examples of this bug in action:
The first is a simple form that does a search on a site. Additionally a link is provided that, when clicked, fills in a search value and submits the form.
<form action="" method="POST" id="form"> Search: <input type="text" name="search" id="search"/> <input type="submit" id="submit"/> </form> <a href="#" id="quick">Quick Search 'JavaScript'</a> <script> document.getElementById("quick").onclick = function(){ document.getElementById("search").value = "JavaScript"; document.getElementById("form").submit(); }; </script>
Before running the example you can spot the problem with a quick run to the address bar:
javascript:alert(document.getElementById("form").submit) "[object HTMLInputElement]"
The .submit() method (which is available on all Form elements) is overwritten by the input element of the same name. This ends up being a very common problem – with frameworks using id=”submit” as a default in their code.
Worst of all this fails in all browsers (preventing you from accessing the overwritten method).
The second example is even more devious. In this case we’re going to loop over all the DOM elements in the page and alert out their contents.
<div id="length">12 stories</div> <div id="makeup">radiation</div> <script> var all = document.getElementsByTagName("*"); for ( var i = 0; i < all.length; i++ ) { alert( all[i].innerHTML ); } </script>
This will work in most browsers – but not Internet Explorer. To understand why we return to the address bar.
javascript:alert(document.getElementsByTagName("*").makeup) "[object]" javascript:alert(document.getElementsByTagName("*").length) "[object]"
Oops. All browsers turn elements with specific IDs into expandos of the returned NodeSet. But Internet Explorer goes a step farther and decides to overwrite the built-in .length property as well, breaking current forms of iterating over the DOM elements.
At least within jQuery you’ll see a number of cases where, instead of doing the normal array traversal, we do the following in order to work around the issue:
for ( var i = 0; elems[i]; i++ ) { // Do stuff with elems[i] }
It’s a little more obtuse but at least it’s guaranteed to work against cases of broken NodeSet iteration.
Garrett Smith has a highly technical write-up on the variety of issues that stem from this form of expansion. In short: No browser is immune from these problems. It’s unfortunate that this whole system couldn’t just be done away with (to avoid these types of issues in the first place) but legacy pages will likely necessitate their inclusion for many, many, years to come.
Neal G (November 10, 2008 at 12:53 pm)
Gez John, you are blogging like crazy today! I especially enjoyed the CSS3 one.
James (November 10, 2008 at 1:15 pm)
I am amazed that I’d never noticed that before. That’s a horrific bug, especially the broken iteration thing (id=”length”) … How ridiculous! It’s a massive problem, I’m surprised it’s not talked about more.
nate (November 10, 2008 at 1:36 pm)
Hey John, I checked, and I couldn’t seem to find any record of CakePHP setting the ID for submit buttons. If it was there at one point, I think it would have had to have been over two years ago. Maybe you’re thinking of a different framework? ;-)
John Resig (November 10, 2008 at 1:41 pm)
@Neal: Thanks – glad you’re enjoying it!
@James: Yeah, it really is horrible – and it’s an insane one to track down (since it’s hooked to your markup, not to the actual JavaScript code that you write).
@Nate: Oops, my mistake. I could’ve sworn it was CakePHP – I’ve edited the post to be more generic.
kangax (November 10, 2008 at 2:44 pm)
@James,
it actually is talked about (and not only about this particular bug) http://jibbering.com/faq/names/
Jason Cooper (November 10, 2008 at 4:37 pm)
@Neal: I think John has been sandbagging his posts.
@John: Well played.
Andrew Dupont (November 10, 2008 at 4:57 pm)
Can’t we agree on a standardized way to “opt out” of DOM0 APIs?
John Resig (November 10, 2008 at 5:01 pm)
@Andrew: window.dontDoCrazyShit();
kourge (November 10, 2008 at 9:52 pm)
@Andrew: It’s IE. Expect less, not more.
an0n1 m0us (November 11, 2008 at 3:38 am)
The real issue here is about getting Microsoft to backport bug fixes into the existing IsEvil install base out there.
Why doesn’t anybody in the webbie community up there in west coast Obamaland make that point? There is no justification for MS being allowed to leave broken ware out in the wild for so many years whilst developers suffer. IsEvil is patched monthly. How about patching crap like this, not *just* security holes?
We can demand Microsoft retrofix IE!
Yes We Can!
NOW!
Edwin Martin (November 11, 2008 at 4:02 pm)
Maybe it’s an idea to remove DOM0 from HTML5. I mean, if you use the HTML5 doctype, you can only use the W3C DOM and nothing else.
hax (November 14, 2008 at 3:00 pm)
I submitted a bug (https://bugzilla.mozilla.org/show_bug.cgi?id=322488) on bugzilla three years ago, but no one care about that… Maybe you can add some comments on it.
Steve Clay (November 15, 2008 at 11:52 pm)
I also complained about this. Sun has the oldest spec I could find outlining the behavior: “You can refer to a form’s elements in your code by using the element’s name…” (sigh) No wonder the spec uses names like “submit1” ;)
I like the idea of the HTML5 doctype being a “DOM0” opt-out. I recommended the HTML validator also issue warnings when name attribute values could interfere with DOM interfaces.
Flüge (December 3, 2008 at 7:11 am)
That’s a terrible bug.the SAX parser is much better than DOM.
Vlad (April 29, 2009 at 9:18 am)
I like this blog. And I respect the content of and learn a lot from these pages. With that I would like to respectfully dissent — for now.
Perhaps this is truly a bug. However, Javascript developers know not to use reserved words in their code. I tend to presume that this can carry over markup. Also, just because it’s fashionable to blame MS for a great many things doesn’t mean we should blame it for everything.
So, maybe it’s not a bug — writing code is a discipline. As with all disciplines, certain rules must be observed (in frameworks and home spun code). The easiest way to fix this “bug” (in quotes because I’m not convinced that this is a bug) is to avoid using reserved words for IDs.