Web DevCenter
oreilly.comSafari Books Online.Conferences.
MySQL Conference and Expo April 14-17, 2008, Santa Clara, CA

Sponsored Developer Resources

Web Columns
Adobe GoLive
Essential JavaScript
Megnut

Web Topics
All Articles
Browsers
ColdFusion
CSS
Database
Flash
Graphics
HTML/XHTML/DHTML
Scripting Languages
Tools
Weblogs

Atom 1.0 Feed RSS 1.0 Feed RSS 2.0 Feed

Learning Lab






Object Detection
Pages: 1, 2

Evaluating Your Needs

It is difficult to formulate a template to use for object detection. Each page's compatibility goals and object detection needs are somewhat different.



Perhaps the most important step in implementing object detection is identifying your needs. For example, if your scripts interact only with dynamic style attributes of elements, the primary object detection task is identifying the applicable syntax for referencing elements: using document.all to pick up stragglers still using IE4 vs. document.getElementById() for IE5+ and NN6 users. A function that receives an element's ID as an argument can accommodate both syntaxes, while protecting even older browsers from triggering errors:

function myFunc(elemID) {
  var elem = (document.getElementById) ? 
    document.getElementById(elemID) : ((document.all) ? 
    document.all[elemID] : null);
  if (elem) {
    // act on element
  }
}

If you don't want to repeat so much code in your functions, you can alternatively establish global variable flags for element reference categories at the top of your scripts:

var isW3C = (document.getElementById) ? true : false
var isAll = (document.all) ? true : false

Then use these global variables in your conditional expressions for execution branching, as follows:

function myFunc(elemID) {
  var elem = (isW3C) ? document.getElementById(elemID) : ((isAll) ?
    document.all[elemID] : null);
  if (elem) {
    // act on element
    }
}

Mold your decision branches so that the most likely true condition tests first. For example, with so many users now visiting with at least basic W3C DOM browsers, test for W3C DOM support first. Yes, it's true that IE5 supports both element reference styles, but the W3C DOM version will include NN6 users and future standards-compatible browsers, as well.

For functions that act as event handlers, multiple object detection routines are needed to handle both the diversity of event models and element reference syntaxes, as shown in the following example borrowed from the article Supporting Three Event Models at Once:

function functionName(evt) {
  evt = (evt) ? evt : ((window.event) ? window.event : "")
  if (evt) {
    var elem
    if (evt.target) {
      elem = (evt.target.nodeType == 3) ? evt.target.parentNode : evt.target
    } else {
      elem = evt.srcElement
    }
    if (elem) {
      // process event here
    }
  }
}

Planning

Designing your scripts around object detection frequently takes more planning than the browser sniffing approach. For one thing, it requires that you have a good grasp of what objects, properties, and methods are supported by your target browsers. The immense size of today's Microsoft and W3C object models, plus the various levels of support in different operating systems and browser versions complicates the matter. Unless you have a photographic memory, you'll want to have a reference handy, either in the form of up-to-date JavaScript-related books or a compatibility chart. These references provide the information you need about which objects, properties, and methods to test for.

The more you work with the object models, the more you discover ways to use clues about one feature as an indicator of support for other features. For example, every browser that supports the document.getElementById() method is essentially guaranteed to support the style property of any HTML element. After that, however, support for individual style sheet properties can vary widely. Thus, an execution branch following support for document.getElementById() can assume support for the style property and go right into testing for the presence of an uncommon or non-standard style sheet property (such as the IE-only style.pixelWidth property). But use this "support by association" tactic judiciously and only with sufficient familiarity with current browser features. Otherwise you'll fall into the same bad habits that plague version sniffers. If you're unsure about associated support, perform explicit, nested object detection to provide error-free execution paths.

As a result, some of your branching may need to be many levels deep. Fear not. Except in huge scripts that must process tons of data in numerous iterative loops, the performance impact of nested if constructions is negligible.

As you work on the code, you need to visualize execution paths that encounter your detection branches. Be sure to visualize not only how execution flows when browsers support your cool features, but also what happens when detection finds no support for your features. Will your scripts degrade gracefully in older browsers?

Testing

While the chief benefits of using object detection are freedom from browser version concerns and a hedge against the unknown (alternative browsers and future browser versions), you are not liberated from the job of testing your code on as many browsers as you can. Just because a browser indicates that it supports a particular object or property doesn't mean that the support is identical across all supporting browsers.

As intimated in the article Scripting for IE 5 Macintosh Edition, implementations of even the most modern browser standards can present differences in rendered results. Or, as occurred frequently in Netscape Navigator 6.0, object model features were present but inactive, until version 6.1. Test, test, test!

When Browser Sniffing is OK

You may occasionally encounter problems whose solution requires the old-fashioned browser version sniffing. In general these problems are limited to known bugs or "alternative behavior" of an object in a browser version. For example, if MegaBrowser 3.05 for Windows always reports that an otherwise well-supported object property has a value of zero no matter what the rendering shows and generates an error if you try to set the property value, you'll have to code a detour for that browser version. You'll be back to the old navigator.userAgent property parsing to protect users of that browser from its foibles. You can't hope to anticipate every browser bug, but object detection won't help you there either.

Some page designers also prefer to use OS-specific style sheets or content, rather than trust one size to fit all. In such cases, it's perfectly normal and appropriate to branch according to OS version. The following script statements would be in the HEAD portion of a document to link a Mac-specific style sheet definition file for Macintosh clients (and hope for the best on Windows, Unix, and other OSes):

var isMac = navigator.userAgent.indexOf("Mac") != -1
if (isMac) {
  document.write("<link rel='stylesheet' type='text/css' HREF='/css/mac.css'>")
} else {
  document.write("<link rel='stylesheet' type='text/css' HREF='/css/generic.css'>")
}

Worth the Effort?

Related Reading

JavaScript: The Definitive Guide, 4th EditionJavaScript: The Definitive Guide, 4th Edition
By David Flanagan
Table of Contents
Index
Sample Chapter
Full Description

Until you get comfortable with the planning and thought processes needed to implement object detection, you may wonder if so much extra up-front work will pay off. If you have been through revision cycles in the past as new browsers disrupt your existing scripts, you can begin to appreciate how one of the goals of this technique -- less maintenance going forward -- will ease your load. Of course, you probably won't know that your hard work early on saved you from headaches down the road. That makes it a thankless job in a way, but one that, rather than making you look good in the future, can prevent you from looking bad.

Using object detection also leads to good programming practice. You'll need to know the resources at your disposal and visualize execution paths for when things work and when they don't. You also grow to appreciate the importance of developing code that anticipates errors and handles them gracefully. Once you grow comfortable with object detection, you'll wonder why you bothered with convoluted sniffing matrices in the past.

Apple Developer Connection is a resource for web developers, authors, and hobbyists who enjoy crafting clean, effective web pages.


Return to the JavaScript and CSS DevCenter.