Programmers Helping Programmers
One of the nicest changes to have happened since I was last an active programmer almost twenty years ago is the help programmers give each other. Programming used to be pretty lonely; it still requires unsocial concentration and lack of distraction; but we programmers aren't alone with our bugs anymore. When we get stuck, we search the forums inevitably setup around the products, tools, and APIs we're using or just google a description of what's happening to us and we usually find that someone else has been in the same place, figured out the problem, and posted a solution.
But the other day I had a problem I couldn't find an answer to. The rest of this post is a pretty nerdy discussion of the problem and a workaround. It's here so that other people with the same problem can find it by googling and as my contribution to helping each other.
I've been testing the code I'm working on with Internet Explorer and Firefox. Before it can be released to production it'll have to be tested with Safari as well and with some mobile phone browsers but for now I'm just using these two. Obviously, this is a web app that runs in a browser although portions are also PHP running on a server. Recently Mozilla released Firefox 3.0. I deliberately didn't upgrade because I figure that most people are still using 2.x and will be for some time so I wanted to test with that.
My colleague Hardeep, however, did upgrade and promptly reported that my code didn't work at all with FF3. He was kind enough to send me console debugging logs and pointers to some known compatibility issues between FF2 and FF3. These issues weren't what was affecting me but the logs he sent pointed me in the right direction. FF2 and FF3 work differently when retrieving objects by tag from an XML structure when the XML is defined in a specific namespace (I'm trying to use as many of the right keywords as possible so that other people with the problem will find this explanation). The javascript method getElementsByTagName(tagName) requires that the prefix be part of tagName in FF2 but does NOT want the prefix as part of tagName in FF3 (or Internet Explorer, for that matter).
I used to have code that looked like this:
if (window.ActiveXObject) { // if IE
var thePrefix="fi:"; // need prefix
} else {
var thePrefix=""; // else no prefix
}
var responseAttributes=xml.getElementsByTagName(thePrefix+"response")[0].attributes;
It wasn't good technique anyway and promptly broke on my bad assumption that IE was the outlier (as it often is) and that all other browsers would work differently. The statement looking for attributes caused a browser error since there were no elements with the tag "response" from FF3's POV. It wanted "fi:response" instead.
New code looks like this:
var thePrefix="";
try {
var responseAttributes=xml.getElementsByTagName("response")[0].attributes;
}
catch (e) {
thePrefix="fi:";
var responseAttributes=xml.getElementsByTagName(thePrefix+"response")[0].attributes;
}
This implementation adjusts itself to whatever the particular browser wants. The reason I bother to set thePrefix is that I have many other invocations of getElementsByTagName() further down in the code. Note that I also could have written:
If (xml.getElementsByTagName("response").length==0) {
thePrefix="fi:";
} else {
thePrefix="";
}
var responseAttributes=xml.getElementsByTagName(thePrefix+"response")[0].attributes;
Also note that both of these examples rely on my certainty that the tag "results" does actually exist in the XML. Once we knew what the problem was. Hardeep did find that someone had blogged about it. Also, when I went to post the bug to bugzilla, I found that it had been reported (several times) but will not be fixed because the FF3 (and IE) behavior is correct and FF2 is not. BTW, the absolute correct way to do this is with getElementsByTagNameNS – but this doesn't work in IE according to W3.
Comments