Thursday 22 October 2009

Why feature-sniffing? Sample from an IE8-bug in Dojo

I am going to give a real-world example of when browser-sniffing fails, and that browser-sniffing is not the same as user-agent sniffing.

Some weeks ago I made a note to myself. Never use native DOM-methods if you have a library at hand. I had discovered an Internet Explorer bug, and noticed that if I had used the dojo.attr code instead of setAttribute it would never have been a problem. But today I discovered that the exact same code that I praised some weeks ago now totally broke on Internet Explorer 8. And it was Dojos fault not Microsofts. I repeat it was not a Microsoft bug. Microsoft actually had fixed a bug.

The reason was browser-sniffing instead of feature-sniffing. The Dojo code checks whether the browser is Internet Explorer, and assumes that it behaves in a certain way if it is. But just because it is is a bug in todays Internet Explorer, it does not need to be in Internet Explorer 9 or 10. The brand name will probably stay. There are two solutions to the problem, one not so good and one good.

Browser-detection

The not very good one is to check on a certain version of the browser that you know about. If you know the bug is in IE6 or IE7 or IE8 you can test for that particular version. But wait, what if they fix the bug? This could be the case for IE8. It is not unthinkable. Then your code would break.

User-agents

An additional question, but less important, is how you detect the browser version. If it is based on an user-agent string you might have additional problems, this string could be set by another browser in some sort of compatiblity-mode, or even changed by the user. When you read about browser sniffing it usually sounds like it is detection based on user-agents that is the main problem. And people respond that only 0.025 percent fakes user-agents anyway so it is no problem. In a way I agree, the main problem is not using user-agents. It is assuming a bug exists without testing for the exact bug, but assuming it exists because we are on a certain browser. Testing for the presence of certain objects (like document.all) and then assuming a certain behaviour can be just as unreliable. What if the bug is fixed in the next service-pack but document.all remains?

Feature-detection

The best way to do it I can think of is to test if the bug exists, not if we are on a certain browser. You can call it feature-detection, or bug-detection. Sure, it might take some extra milliseconds and some coding effort. But I think it is worth it, especially in a general purpose library. And I was just visually inspecting jQuerys support.js, it seems it can be done in a fast way.

Unobtrusive websites

Of course you can use the same way to do accessible website with graceful degradation. Test for features, not browser versions.

Details on the bug

This might not be very interesting, but if you really want to know. Dojo 1.2.3 has a function dojo.attr that fixes some issues with the native setAttribute method. One thing is that when setting the (css) class the attibute is named className for Internet Explorer 6 and 7. But that was fixed in Internet Explorer 8. However, line 1085 in html.js checks for isIE rather than ieLT8 (which would have worked). Here is my bug-report.

Sample bug sniffing

This is the feature sniffing I have used for this bug.

var featureSniffClassNameAttributeIsClass = function () {
var d = dojo.doc.createElement("div");
try {
d.setAttribute("className", "c");
var h = d.outerHTML;
// if setting className on a node alters the class, we are on IE6 or 7
var convertClassToClassName = ! /classname/.exec(h.toLowerCase());
return convertClassToClassName;
} catch (e) {
//probably we are on a non IE browser because an error occurred
return false;
}
};

Why don't you upgrade to the latest dojo?

Now that is a good question. I don't know if this bug is fixed yet, maybe it is. But sometimes you don't have an option. We are doing a chat-widget for Lotus Connections. Lotus Connections is a commercial social software for intranets made by IBM. And it does not have a chat. Almost unbelievable. If you are running Lotus Connections and want a chat, of course you do, contact me for more information. Or if you are a systems-integrator and want one to sell. Anyway, widgets for Lotus Connections do not sit in isolated iframes, so your Javascript runs on the actual page. And IBM has decided on the Dojo version, not me. So I don't think I can persuade them to patch it.

No comments:

Post a Comment