Browser-detection techniques have been in use ever since the MSIE version 3 browser was launched. Since the features of this browser differed from others, it became necessary to determine what browser was being used to establish the features actually available.
The subject of browser detection is now extremely complex, with a wide variety of browsers. The technique of simply distinguishing between Netscape and MSIE is no longer sufficient. This is even more of an issue now that Netscape version 6.0 is shipping.
This Netscape version 6.0 browser was developed around a completely new source code base. Having started completely afresh, Netscape has not implemented any unnecessary legacy features and instead has pursued a strictly standards-based approach. The most noticeable effect of this is the complete lack of support for layers.
The reason why this is such a big problem is that in the past we might typically have written a short script to determine whether we were running Netscape or MSIE, and coded accordingly. The first example shows how we would have done this using a classical detection technique.
However, now we have millions of web pages using this technique that also use layers. They will detect Netscape 6.0 and return a value saying "OK it's Netscape, so use the Netscape layers code alternative". This is going to break a lot of pages.
We now need something that tells us whether a particular feature is available rather than a particular browser. The second example is a skeleton of how we might do that. It adds a member object called isAvailable to the global object, that can have additional properties added as we need to extend it. In this example, it simply provides access to whether layers are available or not. It provides for three possible cases:
NO - Layers are not available and no alternative simulation is possible
DIV - Layers are not available, use <DIV> blocks and CSS positioning
YES - Layers are available
So now we can build some code to exploit this using a switch statement thus:
isAvailable(); switch(isAvailable.Layers) { case "YES" : // Call the layer programmed version of our page break; case "DIV" : // Call the <DIV> simulated layers version of the page break; case "NO" : // Fall back to the legacy browser, no layers page break; default: // Unexpected condition handled here break; }
Because we need to know what browser and version the code is being run on to determine simulation capabilities, those get set as member properties of the isAvailable object.
Later you could add capabilities to access the DOM feature-detection mechanisms so that all these related feature detection facilities are in a single reusable code block.
Note that the appVersion value picks up the Mozilla/X.YY value and uses that. This means that MSIE 5 reports an appVersion of 4 and Netscape version 6.0 reports an appVersion of 5, which is odd to say the least. You can do a bit more work to parse out the correct version numbers from the remainder of the user agent string or access special values that are platform-dependent within a fragment of code that is selected on a per platform basis.
<SCRIPT> // Classic browser detection returning browser types // and versions function getBrowserType() { var myUserAgent; var myMajor; myUserAgent = navigator.userAgent.toLowerCase(); myMajor = parseInt(.appVersion); if( (myUserAgent.indexOf('mozilla') != -1) && (myUserAgent.indexOf('spoofer') == -1) && (myUserAgent.indexOf('compatible') == -1) && (myUserAgent.indexOf('opera') == -1) && (myUserAgent.indexOf('webtv') == -1)) { if (myMajor > 4) { return "nav6"; } if (myMajor > 3) { return "nav4"; } return "nav"; } if (myUserAgent.indexOf("msie") != -1) { if (myMajor > 4) { return "ie5"; } if (myMajor > 3) { return "ie4"; } return "ie"; } return "other"; } </SCRIPT>
<SCRIPT> isAvailable(); document.write("Browser family : " + isAvailable.Browser + "<BR>"); document.write("Browser version : " + isAvailable.Version + "<BR>"); document.write("Layer support : " + isAvailable.Layers + "<BR>"); // Modern extensible browser feature detection // Becomes a member property of the global object function isAvailable() { // Get user agent stuff var myUserAgent = navigator.userAgent.toLowerCase(); // Set initial conditions isAvailable.Browser = "OTHER"; // Check for navigator if( (myUserAgent.indexOf('mozilla') != -1) && (myUserAgent.indexOf('spoofer') == -1) && (myUserAgent.indexOf('compatible') == -1) && (myUserAgent.indexOf('opera') == -1) && (myUserAgent.indexOf('webtv') == -1)) { isAvailable.Browser = "NAV"; } // Check for MSIE if (myUserAgent.indexOf("msie") != -1) { isAvailable.Browser = "MSIE"; } // Store major version number from leading Moziilla/X.YY // Portion of user agent string isAvailable.Version = parseInt(navigator.appVersion); // Work out if layers available if(document.layers) { isAvailable.Layers = "YES"; } else { if((isAvailable.Browser = "MSIE") && (isAvailable.Version > 3) || (isAvailable.Browser = "NAV") && (isAvailable.Version > 4)) { isAvailable.Layers = "DIV"; } else { isAvailable.Layers = "NO"; } } } // For further investigation look at the MSIE script engine version and build number properties and map them to features. </SCRIPT>
Prev | Home | Next |
Browser | Up | Browser version compatibility |
JavaScript Programmer's Reference, Cliff Wootton Wrox Press (www.wrox.com) Join the Wrox JavaScript forum at p2p.wrox.com Please report problems to support@wrox.com © 2001 Wrox Press. All Rights Reserved. Terms and conditions. |