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






O'Reilly Book Excerpts: JavaScript & DHTML Cookbook

Cooking with JavaScript & DHTML, Part 3

Related Reading

JavaScript & DHTML Cookbook
Solutions and Example for Web Programmers
By Danny Goodman

by Danny Goodman

Our latest sample recipe from JavaScript & DHTML Cookbook comes from Chapter 5 on "Browser Feature Detection." Learn how to detect object property and method support, thereby ensuring complete support for modern scriptable features. And check back here next week for a sample recipe on importing browser- or operating system-specific style sheets.

Recipe 5.7: Detecting Object Property and Method Support

NN 2, IE 3

Problem

You want scripts to run on all browsers that support the object properties and/or methods that your scripts address, and to degrade gracefully in other browsers.

Solution

Surround the script statements that reference potentially incompatible object properties or methods with if statements that test for the existence of the objects and their properties or methods. The items you test for can belong to core JavaScript language objects, as well as to DOM objects. Testing for the existence of a property or method is a little more complicated than testing for the object alone. If your condition expression references a property of a nonexistent object, a script error results. Therefore, you must precede your property/method test with a test for the object (assuming the object is not one that is fully backward-compatible).

if (objectTest && objectPropertyTest) {
    // OK to work with property
}

This combination works smoothly because if the first condition test fails, JavaScript short-circuits the rest of the expression, bypassing the second condition.

It is not advisable, however, to use the simple existence test for an object's property in an if condition. The main reason is that some legitimate property values are zero or empty strings. A conditional test with these values evaluates the same as false, which gives an incorrect reading about support for the property (see Recipe 4.6 in of JavaScript & DHTML Cookbook). The best way around this problem is to test for the data type of the property being something other than undefined:

if (objectReference && 
   typeof objectReference.propertyName != "undefined") {
    // OK to work with property
}

References to object methods take the same form as references to functions: the name of the method without the parentheses. If the method exists, the reference evaluates to a valid object type and the conditional test succeeds:

if (objectReference && objectReference.methodName) {
    // OK to work with method
}

For example, to protect scripts written with W3C DOM element-referencing from tripping up older browsers, you can wrap function execution inside conditions that test for the existence of the document.getElementById( ) method:

function myFunction( ) {
    if (document.getElementById) {
        // OK to use document.getElementById( ) here
    }
}

To save some bytes on the page and extraneous expression evaluation, you can also set a Boolean global variable as the page loads to use in later condition statements:

var isW3 = (document.getElementById) ? true : false;
...
if (isW3) {
    // OK to use document.getElementById( ) here
}

Discussion

Be careful about the assumptions you make when you qualify a browser for an object and one of its properties or methods. For instance, it would be a mistake to assume that because the browser indicates support for the document.getElementById( ) method that it supports the rest of the W3C DOM Core module objects, properties, and methods. With experience, however, you will gain the knowledge that all browsers that recognize the all-important method also know about the basic element node properties, such as nodeType, nodeName, and nodeValue. Again, a good DOM reference will help you with those kinds of decisions.

Don't be afraid to nest multiple levels of object and property/method detection in a function. You can see examples of this when processing events for the incompatible IE and W3C event models (for more, see Recipe 9.1). But always make sure that your functions are structured in such a way that any one condition failure is handled gracefully so that no script errors accrue in the absence of support for your desired object, property, or method.

The W3C DOM specification includes facilities to help scripts know what level of support is offered by the browser. Every element object has an isSupported( ) method, whose parameters let you test for the browser's support of various W3C standards or DOM modules. The module names available for testing as of DOM Level 2 are Core, XML, HTML, Views, StyleSheets, CSS, CSS2, Events, UIEvents, MouseEvents, MutationEvents, HTMLEvents, Range, and Traversal. In theory, if the browser fully supports the required portions of a module, the isSupported( ) method returns a value of true:

if (myElem.isSupported("CSS", "2.0")) {
    myElem.style.color = "green";
}

But this test is not rigorous enough for most scripters. The standards contain numerous optional features, whose omission still allows a browser maker to claim full conformance with the standard. The only way to assure complete support for modern scriptable features is via the more explicit object, property, and method condition testing.

See Also

Recipe 5.6 for detecting object support; Recipe 4.6 for special condition expressions that evaluate to true and false; Recipe 9.1 for nested object detection in event processing; all in JavaScript & DHTML Cookbook.

Danny Goodman has been writing about technology and computers full-time since 1981 and is the author of Dynamic HTML: The Definitive Reference and "The Complete HyperCard Handbook."


Return to the Web Development DevCenter.