b++ Why browser detection with JavaScript is a bad habit?
What’s wrong with this JavaScript function?
var xmlHttp = function(){
var r = null;
var browser = navigator.appName;
if(browser == 'Microsoft Internet Explorer'){
r = new ActiveXObject('Microsoft.XMLHTTP');
} else {
r = new XMLHttpRequest();
};
return r;
};
You don’t have a clue? Then this is the right article for you… (well except you don’t know why are you reading this in the first place)
Let’s say you run this script in Opera. Opera is by default declaring its’ navigator.appName as Microsoft Internet Explorer (open the W3schools TryIt Editor in your default Opera installation).
In case of Opera, the first condition would match, but the trouble is – Opera doesn’t support ActiveXObject object and it will throw you an error. Furthermore, if a browser is not Microsoft Internet Explorer and it doesn’t support XMLHttpRequest, the browser will also hang.
In the above example the function detects browser version, instead of its’ support for a method at hand. On the other hand, if you test for a method and the browser fails, it will simply skip to a next check. The correct approach for the above example would be:
var xmlHttp = function() {
var r = null;
if (window.XMLHttpRequest) {
r = new XMLHttpRequest();
} else if(window.ActiveXObject) {
var msp = new Array('Msxml2.XMLHTTP','Microsoft.XMLHTTP');
for (var i = 0; i < msp.length; i = i + 1) {
try { r = new ActiveXObject(msp[i]); } catch (e){};
};
};
return r;
};
Right?
001—2006.02.02.16:36
Perfect.
There’s a good chance that people who write browser sniffing Javascript have no idea what that code above is though (object literal notation). The first time I saw it, it looked a little cryptic and was taken aback.
002—2006.03.03.12:54
A little off-topic, but we use this method at work to create an “Ajax” object:
function AJAX() {var o = false;
/*@cc_on @*/
/*@if (@_jscript_version >= 5)
try {
o = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
o = new ActiveXObject("Microsoft.XMLHTTP");
} catch (E) {
o = false;
}
}
@end @*/
if (!o && typeof XMLHttpRequest!='undefined') {
o = new XMLHttpRequest();
}
return o;
}
Sorry for the rough formatting.
Anyway, explanation is that it uses conditional compilation (all that
@cc_onstuff) to do some serious browser/object forking. Hope that helps. If the function returnsfalse, then the browser doesn’t support Ajax. Otherwise the return value is an Ajax object.