Section C. Object detection


C. Object detection

Your best friend for avoiding browser problems is object detection. If your script uses an object, first check if the browser supports that object. If it doesn't, your script ends.

In contrast to browser detection (which we'll look at in 3D), object detection always works. Since it doesn't depend on browser identity but on browser capabilities, object detection is inherently superior to browser detection.

Once you know that your visitor's browser supports certain objects, you can safely start up your script. You don't need to know exactly which browser it is; you found the objects you need, so you know your script is going to work.

How object detection works

Let's continue with an example from the previous section: Opera doesn't support document.styleSheets. Therefore Edit Style Sheet, which relies on this object, should first check if a visitor's browser supports it. If not, the script should end.

That's why Edit Style Sheet starts out by detecting the presence of this object:

[Edit Style Sheet, lines 5-6]

function initStyleChange() {    if (!document.styleSheets) return; 


You can even pronounce this line: "if NOT document.styleSheets, return". The line checks if the object document.styleSheets is present, and if it isn't, it ends the function (return).

In fact, this is the general syntax of all object detections: you take the object(s) you want to use and check if they're there. If they aren't (if (!chosen.object)), you end the function.

Technically, object detection hinges on the conversion of an object to a boolean value. We'll get back to this in 5G.

W3C DOM check

By far the most common object detect is this one:

[Site Survey/survey.js, line 27. Most other scripts also use this line, or a variation on it.]

var W3CDOM = document.createElement && document.getElementsByTagName; 


Often I want to check W3C DOM support before proceeding with a script. This line does so. It checks for the existence of document.createElement and document.getElementsByTagName, which, as we'll see in Chapter 8, are two vital DOM methods. Both have to be present (&&) for the browser to survive the check.

There are historical reasons why I use exactly this check and no other. Explorer 4, which doesn't support the W3C DOM, nonetheless supports document.createElement, though it has a different meaning. So merely checking for this object would allow Explorer 4 to pass. On the other hand, an old version of Opera supported getElementsByTagName but not createElement. That's why I check for both methods.

Event-handling test

In 7C we'll encounter my addEventSimple() function, which adds event handlers according to the W3C and Microsoft models (just nod wisely for the moment). This area of JavaScript contains a major browser incompatibility: the W3C model doesn't work in Explorer, and the Microsoft model doesn't work in Mozilla.

A bit of object detection is obviously in order:

[Usable Forms, lines 151-156. This function is also used in Site Survey, Dropdown Menu, and Edit Style Sheet.]

function addEventSimple(obj,evt,fn) {     if (obj.addEventListener) // W3C             obj.addEventListener(evt,fn,false);     else if (obj.attachEvent) // Microsoft             obj.attachEvent('on'+evt,fn); } 


The function checks for support of addEventListener() (W3C), and then for support of attachEvent() (Microsoft). If a browser supports one of these methods, the event handler is set and the function ends.

This object detection contains two interesting points:

  • It checks for the W3C-compliant method first because the standard should precede any proprietary method. (Once Explorer supports the W3C standard, it's likely to retain support for the Microsoft model, too, in order to remain backward-compatible. Nonetheless I want this future version to use the standard, so the standards support check should come first.)

  • If a browser supports neither method, no event handler is set. Thus this function also serves as a filter that allows most modern browsers to pass through, but excludes, for instance, Explorer on Mac.

Site Survey

A quick peek at Site Survey concludes the object-detection examples. Remember that this example script consists of two script files. Survey.js contains a few object detectionsa standard W3C DOM check (line 27) and the addEventSimple() function (lines 86-91). Popup.js contains no object detection at all, even though it uses the W3C DOM to create new form fields.

A browser will only download popup.js if the popup opens. In turn, the popup opens only when the browser supports the W3C DOM and either advanced event-registration model, because that's what survey.js specifies.

Thus, popup.js "hides" behind the object detections in survey.js; if the browser doesn't survive those detects, it never downloads popup.js. It's safe to use the W3C DOM event in the popup because without W3C DOM support the popup never opens.

This kind of object detection-once-removed is occasionally useful, but you should make sure that there's no way the user can directly open the "hidden" JavaScript file when you use it.

In the case of Site Survey, it's theoretically possible that the user could directly open the page popup.html. However, it's unlikely, since the file is not a regular part of the host site, and in any case the popup won't function correctly without a main window from which to extract data. Therefore I judged it safe to "hide" popup.js behind the detects in survey.js.

How far should you go?

Sandwich Picker starts like this:

[Sandwich Picker, lines 1-12, condensed]

var IEMAC = (navigator.userAgent.indexOf('Mac') != -1 && navigator.userAgent.indexOf('MSIE') != -1); var W3CDOM = (document.createElement && document.getElementsByTagName && !IEMAC); if (W3CDOM) {     var extraTD = document.createElement('td');     // more stuff     var extraButton = document.createElement('button');     extraButton.appendChild(document.createTextNode('Collect all orders')); } 


It first uses object detection similar to the one we just saw (except for the browser detectsee 3D). If the browser survives the check (if (W3CDOM)) it executes some extra code.

This code uses createElement twice, but since we just checked for its existence those lines are safe. However, the code also includes appendChild, and our object detect hasn't checked if this method is supported. To be really finicky and precise we'd have to check for it first:

if (extraButton.appendChild)     extraButton.appendChild([etc.])); 


It's not wrongtheoretically, this is even safer than the actual Sandwich Picker code. Nonetheless, nobody does it, because all browsers that support createElement and getElementsByTagName also support appendChild. I experimentally confirmed this conclusion by testing it in all available browsers. (Besides, it wouldn't make sense for a W3C DOM-compliant browser not to support something as vital as appendChild.)

Of course, this reasoning is not 100% watertight. Theoretically a browser could be created that supports createElement and getElementsByTagName but not appendChild, but it would be laughed out of business. Therefore, my scripts use one general object detection right at the start, and from then on they assume that the browser also supports related functionality, including other vital W3C DOM methods.

When I need another area of functionality, such as XMLHttpRequest, I add a second object detection to remove browsers that don't support it. After all, the fact that a browser supports the W3C DOM doesn't necessarily mean it also supports XMLHttpRequest. (See 10A for more on detecting XMLHttpRequest.)



ppk on JavaScript. Modern, Accessible, Unobtrusive JavaScript Explained by Means of Eight Real-World Example Scripts2006
ppk on JavaScript. Modern, Accessible, Unobtrusive JavaScript Explained by Means of Eight Real-World Example Scripts2006
ISBN: N/A
EAN: N/A
Year: 2005
Pages: 116

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net