Javascript Browser Detection Revisited
You’ve all seen them before. Javascript browser detection scripts. There are extremely large and ugly ones out there, ignoring the fact that browser detection in itself is an ugly thing having to resolve to. Our suggestion is based on not trusting the user agent string delivered by the browser. Instead we use a combination of object detection and bad voodoo to be 100% sure what browser and what version is served. Updated for IE7!
Do we really need this?
Hopefully not. In most circumstances you can secure yourself from doing stuff to a browser that it doesnt support, simply by checking if method X or object Y is available before you use it. However, the better you get at scripting, and the more crossbrowser compatibility you have to have, the more boundaries get touched or crossed. You will end up with some stupid differences, like IE’s different implementation of what mousebutton was pressed, or Gecko firing a mouseover event when the mouse wasn’t actually moved, but the position of the element below it was.
So we agree that browser detection is only for far-out stuff, and it’s still ugly. But sometimes you have do to what you can to get the job done. Now, especially when writing stuff that pushes the limits of browser capability, you will encounter people that think they are clever with their browser setup. People writing all sorts of wierd stuff in their user agent string, or just browsers like Opera 8, that had to fake being Internet Explorer because MS was deliberately sending out wrong styles for non-IE browsers on MSN.
If the user agent string can’t be trusted, we need to go deeper. So we decided to use object detection, and for IE a little spicy technique called Conditional Compilation, something only available in JScript.
The Code
function detectBrowser() {
var BO = new Object();
BO["ie"] = false /*@cc_on || true @*/;
BO["ie4"] = BO["ie"] && (document.getElementById == null);
BO["ie5"] = BO["ie"] && (document.namespaces == null) && (!BO["ie4"]);
BO["ie6"] = BO["ie"] && (document.implementation != null) && (document.implementation.hasFeature != null);
BO["ie55"] = BO["ie"] && (document.namespaces != null) && (!BO["ie6"]);
/*@cc_on
BO["ie7"] = @_jscript_version == '5.7';
@*/
BO["ns4"] = !BO["ie"] && (document.layers != null) && (window.confirm != null) && (document.createElement == null);
BO["opera"] = (self.opera != null);
BO["gecko"] = (document.getBoxObjectFor != null);
BO["khtml"] = (navigator.vendor == "KDE");
BO["konq"] = ((navigator.vendor == 'KDE') || (document.childNodes) && (!document.all) && (!navigator.taintEnabled));
BO["safari"] = (document.childNodes) && (!document.all) && (!navigator.taintEnabled) && (!navigator.accentColorName);
BO["safari1.2"] = (parseInt(0).toFixed == null) && (BO["safari"] && (window.XMLHttpRequest != null));
BO["safari2.0"] = (parseInt(0).toFixed != null) && BO["safari"] && !BO["safari1.2"];
BO["safari1.1"] = BO["safari"] && !BO["safari1.2"] && !BO["safari2.0"];
return BO;
}
var BO = new detectBrowser();
The Explanation
There isn’t much to explain really. The function returns an object with boolean properties like BO.ie, BO.gecko etc. We suggest doing this check only once and storing the object where ever you might need it for later reference.
To check for IE we use a JScript only construct called Conditional Compilation, which sets BO.ie to true, but only for IE of course.
The other stuff does various object and method detections based on our knowledge of different implementations in different versions. This list is of course not complete, so if you have any additions that follow the same detection method please comment on this article. This is just what we have been needing so far.
on July 23rd, 2006 at 4:18 pm
Very nice, only thing one could comment about is the lag of IE3 support. But as many of our readers would agree there is close to no users using IE3 anymore.
on January 31st, 2007 at 1:43 pm
Just added IE7 support, since that was lacking.
That work by checking the JScript engine version, since that was updated for IE7.
I am not sure if this will work on machines with multiple Ie versions installed. If someone can check that it would be nice.
on August 16th, 2007 at 1:59 pm
Great articel!
I use another way to identify IE 7 by checking the window.XMLHttpRequest - just in case anybody is interested:
BO[”ie7″] = (BO[”ie”] && document.implementation != null && document.compatMode != null && window.XMLHttpRequest != null)
on September 7th, 2007 at 3:55 pm
IE3 support? what?! are you serious?
Most web apps today won’t support less than IE6, and even then, only grudgingly.
on January 8th, 2008 at 8:17 am
Using the code above, I was getting a false positive for ie6 on ie7 until I added a && window.XMLHttpRequest == null to the check for ie6.