Tuesday, April 10th, 2007
Capabilities vs. Quirks: When sniffing is OK
Andrew Dupont has written a detailed report on Capabilities vs. Quirks: a look at browser sniffing.
The purists go on a rant if they ever see you touch navigator.userAgent, but Andrew gives reasons why Prototype has items such as:
IE: !!(window.attachEvent && !window.opera),
Opera: !!window.opera,
WebKit: navigator.userAgent.indexOf('AppleWebKit/')> -1,
Gecko: navigator.userAgent.indexOf('Gecko')> -1 &&
navigator.userAgent.indexOf('KHTML') == -1
};
An example of a quirk that requires sniffing:
* around a bug where XMLHttpRequest sends an incorrect
* Content-length header. See Mozilla Bugzilla #246651.
*/
if (this.transport.overrideMimeType &&
(navigator.userAgent.match(/Gecko/(d{4})/) ||
[0,2005])[1] <2005)
headers['Connection'] = 'close';
This makes my eyes water whenever I look at it: we’re parsing out a year from a user agent string. But what else is there to do? Even if it’s possible to detect this quirk on the client side (and I’m not sure it is), it’d involve sending a dummy Ajax request on page load. Checking navigator.userAgent doesn’t look so ridiculous after all.







ëï
Anyone using a Gecko-based browser from 2005 is prone to worse bugs than that, i see it ridiculous to support these kind of quirks.
The reason I don’t ever check the user agent string is because it can be spoofed by most browsers. While it’s a lofty ideal to use the same code for every browser, it’s not really realistic if you want your web application to work or look right. But object detection is far superior to user agent detection. You can effectively detect a lot of popular browsers with object detection:
if(document.all && !window.opera) var isIE = true;if(document.all && !document.fireEvent && !window.opera) var isIE5 = true;
if(document.all && document.fireEvent && !document.createComment) var isIE55 = true;
if(document.compatMode && document.all) var isIE6 = true;
if(document.documentElement && typeof document.documentElement.style.maxHeight!="undefined" && !isSafari && !isGecko && !isOpera) var isIE7 = true;
if(!document.doctype && !isIE) var isSafari = true;
if(window.Iterator) var isGecko181 = true;
elseif(Array.every) var isGecko18 = true;
elseif(window.getComputedStyle && !window.opera) isGecko17 = true;
if(window.opera) var isOpera = true;
very nice Trevor, just the piece of code i was looking for :)
Daniel,
Most of the credit belongs to http://www.javascriptkit.com/javatutors/objdetect3.shtml