Case-sensitivity with IE getAttribute
I ran across an interesting behavior in IE the other day. Some of my script code was misbehaving, and it took me a while to track down the exact problem. In one part of my code I had an onfocusout event that would update an expando property to a certain value. However, when the object got focus again, I’d read the value and would find it was still set to the original value. When I moved focus away, I’d update the value again and same thing.
After much debugging, I stepped into the code that set the original value. It looked something like:
item.setAttribute("index", 0);
When I lost focus, I would update the value like so:
item.setAttribute("Index", 5);
Then, when I read the value back, I’d do:
value = item.getAttribute("Index");
However, the last line of code would return “0”, the original value I had set. So, why wasn’t my value being updated? Those of you intricately familiar with the IE DOM will already have seen the answer, it took me quite a while (mostly because of the thousands of lines of script code involved and the fact that in this modern era of technology, we still have yet to have a script debugger that really works well.)
So, let’s simplify the code down so you can run it in your own test web page:
<div id="foo"></div>
<script>
function window::onload()
{
foo.setAttribute("index", 0);
foo.setAttribute("Index", 5);
window.alert(foo.getAttribute("Index"));
}
</script>
Upon first glance, you would expect to see a value of “5” on the screen. However, upon running the code we see 0. Why?
Well, this has to do with the default behavior of setAttribute and getAttribute. When setAttribute is called, the <div> will look something like:
<div id=”foo” index=”0”>
This is because setAttribute is case-sensitive and creates an expando property of the exact name specified. The second setAttribute will do the same, and the <div> will look like:
<div id=”foo” index=”0” Index=”5”>
Since “index” and “Index” are different, two keys are created. Now, when the value is read, IE looks for the first attribute matching the name “Index”. Since getAttribute is not case-sensitive by default, it finds “index” with a lower case “i”.
The best way to fix this behavior is to use the same casing for expando attributes, my original code was simply due to a typo on my part years ago that didn’t surface until now. The other way around is to call getAttribute as such:
window.alert(foo.getAttribute("Index", true));
This will cause IE to be case-sensitive when searching for the value. I’d disagree with the IE team (though it was probably some ECMA decision) on this point, I think names of expando properties should be case-sensitive like most syntax in Jscript. Interesting lesson though, I learned to check with MSDN before assuming something was the case.
Mike - Web Dev Guy
Comments
- Anonymous
June 23, 2006
Interesting finding :] A few additions: setAttribute/getAttibure are DOM, not JSCore and hence not a subject to the ECMA but the W3C and because of this the attribute is a custom (X)HTML attribute and not an expando (if my memory serves me well [it did not in the past...] expandos are set via obj.thisIsAnExpando = 123). According to [1] neither getAttribute nor setAttribute do feature IEs iFlags [2, 3] parameter; Speaking of that parameter: it is pretty questionable to have different default values for set- and getAttribute: setAttribute is case-sensitive by default while getAttribute is case-insensitive (being part of the HTML DOM makes this behaviour and the flag even more questionable - after all HTML is case-insensitive for its tags and attributes).
[1] http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-666EE0F9
[2] http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/reference/methods/getattribute.asp?frame=true
[3] http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/reference/methods/setattribute.asp?frame=true