2.2 Cross-Browser XMLHttpRequest
One of the attributes that have made XMLHttpRequest such a popular transport for AJAX requests is that it is easy to use in a way that is compatible across multiple browsers. The big two browsers, IE and Firefox, provide the same basic API. This consistency makes for a similar development experience. Opera and Safari also support the same basic API, but only in their more recent versions.
When you are writing cross-browser, the first problem you need to overcome is that XMLHttpRequest is an ActiveX object in IE, and it's a normal JavaScript object in Mozilla and the other browsers. There are a number of approaches to overcoming this problem, including optional JScript code for IE, but I find that the simplest solution is just to use exceptions. Listing 2-1 shows an example that tries every version of the XMLHTTP ActiveX object, if needed. This helps make our implementation as robust as possible. The function also throws an exception if it's not possible to create an XMLHttpRequest object. This gives us a way to give error messages or to fall back to IFrame requests, if needed.
Listing 2-1. Cross-Browser XMLHttpRequest Creation
1 // function to create an XMLHttpClient in a cross-browser manner 2 function initXMLHttpClient() { 3 var xmlhttp; 4 try { 5 // Mozilla / Safari / IE7 6 xmlhttp = new XMLHttpRequest(); 7 } catch (e) { 8 // IE 9 var XMLHTTP_IDS = new Array('MSXML2.XMLHTTP.5.0', 10 'MSXML2.XMLHTTP.4.0', 11 'MSXML2.XMLHTTP.3.0', 12 'MSXML2.XMLHTTP', 13 'Microsoft.XMLHTTP' ); 14 var success = false; 15 for (var i=0;i < XMLHTTP_IDS.length && !success; i++) { 16 try { 17 xmlhttp = new ActiveXObject(XMLHTTP_IDS[i]); 18 success = true; 19 } catch (e) {} 20 } 21 if (!success) { 22 throw new Error('Unable to create XMLHttpRequest.'); 23 } 24 } 25 return xmlhttp; 26 }
The overall pattern of this code is simple: Create an XMLHttpRequest instance in the most optimal way possible, as shown in line 6. This creation should always succeed on Mozilla-based browsers, such as Firefox, on Opera, and on the upcoming IE 7.
If XMLHttpRequest doesn't exist, catch the exception that is thrown, as shown in line 7. Getting an exception means you're on IE or an old browser. To test for IE, attempt to create an ActiveX version of XMLHttpRequest, which is accomplished by the following:
- Looping over all possible ActiveX identifiers. This action will create an ActiveX instance for each identifier until the creation succeeds, setting the success flag to true, as shown in lines 9–20.
- If creation is successful, returning an XMLHttpRequest instance, as shown in line 25. Otherwise, throwing a JavaScript exception, as shown in line 22.
This approach allows for minimal overhead if the browser supports a native XMLHttpRequest object while fully supporting IE. It also gives us an error if XMLHttpRequest isn't supported at all. This error could be displayed to the user at this point, or you could insert another communication approach, such as hidden IFrames.