Browser Detection versus Object Detection July 2, 2007
Javascript: Things you should know
Use object detection instead of browser detection
Note: This is part I of a "Javascript: Things you should know" series. I assume readers have an understanding of the core language. I try to cover quirks that are important but aren’t covered in text books. The next entry will be quirks with the javascript switch statement.
Use object detection instead of substring detection to determine browser support of your code. Browser detection involves using navigator.userAgent. There are several reasons why you shouldn’t use browser detection.
- Browsers lie about who they are.
- You may filter out browsers that support your code or fail to filter out browsers that don’t support your code..
- Browser detection isn’t future proof: can’t future proof your code against new browsers.
Instead, use object detection: test to see if your browser supports the object you want to manipulate. If the browser supports your objects, yay! You don’t need to know the name of the browser or version number, just whether or not it will support your code.
The most commonly used object detection to check to see if a browser supports the DOM is:
var supportsDOM = document.createElement && document.getElementsByTagName;
This object detection does not mean you can use any object. It simply lets me know whether you should even try implementing your javascript in that particular browser. While the above is a good start, you should still do object detection before assuming browser support.
if(supportsDOM){
var resolution = window.devicePixelRatio;
alert(resolution);
}
At the time of this writing, the only browser that supports the devicePixelRatio property is Safari. See Targeting Safari 3.0 with CSS and Javascript. Safari will return "1", whereas all other browsers will return "undefined". Basically, just because a browser supports the DOM, it does not mean that it supports every object, property and method of the DOM equally, and that it doesn’t have it’s own propietary methods. Once you’ve determined that your browser supports the DOM, you still have to test for method and property support before using it.
if(obj.addEventListener) {
//standards code
}
else if(obj.attachEvent) {
//proprietary code
}
A prime example is IE’s failure to support the WC3 standard addEventListener. Microsoft has it’s own event handling model, supporting attachEvent instead. When performing bject detection, always test for standards compliant methods before proprietary support. IE7 does not support addEventListener. IE8, or whatever the next version is, may support addEventListener and will continue to support attachEvent for backwards compatibility reasons. When IE finally supports the WC3 standard, putting your object detection in this order will ensure that browsers that support standards, whether or not they also support proprietary methods, will use the standard.
Exceptions to the use oject detection not browser detection rule
If you are still supporting IE 5.2 for the Mac, you may want to use browser detection to exclude it. Mac IE 5.2 returns true for if(document.createElement && document.getElementsByTagName), but crashes when it encounters advanced scripts. See Mac IE Hacks.
If you are actually trying to determine which browser is using for some non-javascript reason, such as maintaining statistics on visitors, then it makes sense to use browser detection.
Note: Apple has a good article on object detection versus browser detection.
[…] Note: This is part II of a "Javascript: Things you should know" series. I assume readers have an understanding of the core language. I try to cover quirks that are important, often lead to logic errors but don’t throw an error, and aren’t covered in most books or tutorials. The previous entry was Browser Detection versus Object Detection. […]
You’re quite right to say that IE5 on the Mac supports some functionality tests, but fails when required to perform more advanced tasks.
I found a good way to filter out IE5 on the Mac from other browsers.
If you test for the existance of window.Error, IE5 (Mac) will fail but all the other, more recent, browsers will pass.