The previous section discussed general compatibility techniques that are useful for coping with incompatibilities between different versions of browsers from different vendors running on different platforms. This section addresses another compatibility concern: how to use new features of the JavaScript language in a way that does not cause errors on browsers that do not support those features. Our goals are simple: we need to prevent JavaScript code from being interpreted by browsers that don't understand it, and we need to display special messages on those browsers that inform users that their browsers cannot run the scripts.
The first goal is easy. As we saw in Chapter 12, we can prevent a browser from attempting to run code that it cannot understand by setting the language attribute of the <script> tag appropriately. For example, the following <script> tag specifies that the code it contains uses features of JavaScript 1.1 and that browsers that do not support that version of the scripting language should not attempt to run it:
<script language="JavaScript1.1"> // JavaScript 1.1 code goes here </script>
Note that the use of the language attribute is a general technique. When set to the string "JavaScript1.2", the attribute prevents JavaScript 1.0 or 1.1 browsers from attempting to run the code. At the time of this writing, the latest browsers (Netscape 6 and IE 6) support language versions 1.0, 1.1, 1.2, 1.3, 1.4, and 1.5. If you write JavaScript code that includes the try/catch exception-handling statement, for example, you should include it in a <script> tag with language="JavaScript1.5" to prevent browsers that do not understand this statement from trying to run it.
Unfortunately, the language attribute is marred by the fact that specifying language="JavaScript1.2" causes Netscape to behave in ways that are incompatible with the ECMA-262 standard. For example, as we saw in Chapter 5, setting the language attribute to this value causes the == operator to perform equality comparisons without doing any type conversions. And as we saw in Chapter 8, specifying "JavaScript1.2" also causes the toString( ) method to behave quite differently. Unless you explicitly want these new, incompatible behaviors, or unless you can carefully avoid all incompatible features, you should avoid the use of language="JavaScript1.2".
Note that the version numbers used by the language attribute match the version numbers of Netscape's (and now Mozilla's) JavaScript interpreter. Microsoft's interpreter has more or less followed the evolution of Netscape's, but bear in mind that the language attribute is still somewhat vendor-specific: the language features supported by different vendors for a given version number are not guaranteed to be the same. This is particularly so for language="JavaScript1.2", but caution is advisable for other versions as well. Unfortunately, there is no way to specify a specification version with the language attribute. That is, you cannot write:
<script language="ECMAScript3">...</script>
The language attribute provides at least a partial solution to the problem of language version compatibility, but it solves only half of the problem. We also need to be able to fail gracefully for browsers that do not support the desired version of JavaScript. If we require JavaScript 1.1, we'd like to be able to notify users of JavaScript 1.0 browsers that they cannot use the page. Example 20-1 shows how we can do this.
<!-- Set a variable to determine what version of JavaScript we support --> <!-- This technique can be extended to any number of language versions --> <script language="JavaScript"> var _version = 1.0; </script> <script language="JavaScript1.1"> _version = 1.1; </script> <script language="JavaScript1.2"> _version = 1.2; </script> <!-- Run this code on any JavaScript-enabled browser --> <!-- If the version is not high enough, display a message --> <script language="JavaScript"> if (_version < 1.1) { document.write('<hr><h1>This Page Requires JavaScript 1.1</h1>'); document.write('Your JavaScript 1.0 browser cannot run this page.<hr>'); } </script> <!-- Now run the actual program only on JavaScript 1.1 browsers --> <script language="JavaScript1.1"> // The actual JavaScript 1.1 code goes here </script>
Example 20-1 showed how we can write JavaScript 1.1 code that JavaScript 1.0 browsers do not attempt to execute. What if we wanted to write JavaScript 1.2 code that JavaScript 1.1 browsers do not attempt to execute? We could use the language attribute to explicitly specify "JavaScript1.2", but as we discussed earlier, this causes Netscape to behave incompatibly. Unfortunately, JavaScript 1.2 adds a lot of new syntax to the language. If you write code that uses a switch statement, an object initializer, or a function literal and then run that code on a JavaScript 1.1 browser, you'll cause runtime syntax errors.
One way to work around this problem is simply to suppress any errors that occur on JavaScript 1.1 browsers. Example 20-2 shows how this can be done using the onerror error handler of the Window object (which was described in Chapter 13).
<!-- Check whether JavaScript 1.2 is supported --> <script language="JavaScript1.2">var _js12_ = 1.2</script> <!-- Now avoid the problems with JavaScript 1.2 on Netscape by running --> <!-- the following code on any browser that supports JavaScript 1.1. If --> <!-- the browser does not support JavaScript 1.2, however, we'll display --> <!-- an error message and suppress any syntax errors that occur. --> <script language="JavaScript1.1"> // If JavaScript 1.2 is not supported, fail gracefully function supressErrors( ) { return true; } if (!_js12_) { window.onerror = supressErrors; alert("This program requires a browser with JavaScript 1.2 support"); } // Now proceed with the JavaScript 1.2 code </script>
Another approach to version compatibility is to load a web page that requires a specific level of JavaScript support only after determining whether the browser provides that level of support. Example 20-3 shows how this might be done with a short script that tests whether JavaScript 1.2 is supported. If the browser supports this version, the script uses the Location.replace( ) method to load in a new web page that requires JavaScript 1.2. If JavaScript 1.2 is not supported, the script displays a message saying that it is required.
<head> <script language="JavaScript1.2"> // If JavaScript 1.2 is supported, extract a new URL from the portion of // our URL following the question mark, and load in that new URL location.replace(location.search.substring(1)); // Enter a really long, empty loop, so that the body of this document // doesn't get displayed while the new document is loading for(var i = 0; i < 10000000; i++); </script> </head> <body> <hr size="4"> <h1>This Page Requires JavaScript 1.2</h1> Your browser cannot run this page. Please upgrade to a browser that supports JavaScript 1.2, such as Netscape 4 or Internet Explorer 4. <hr size="4"> </body>
The most interesting thing about this example is that it is a generic one -- the name of the JavaScript 1.2 file to be loaded is encoded in the search portion of the original URL; that file is loaded only if JavaScript 1.2 is supported. Thus, if the file in this example has the name testjs12.html, you can use it in URLs like the one shown in this hyperlink:
<a href="http://my.isp.net/~david/utils/testjs12.html?../js/cooljs12.html"> Visit my cool JavaScript 1.2 page! </a>
The other thing to note about Example 20-3 is that calling Location.replace( ) starts a new page loading but does not immediately stop the current page from loading. Therefore, the JavaScript code in this example enters a long, empty loop after it calls replace( ). This prevents the rest of the document from being parsed and displayed, so that users of JavaScript 1.2 browsers do not see the message intended for users of browsers that do not support JavaScript 1.2.
Finally, note that the technique shown in Example 20-3 is useful not only to distinguish one version of JavaScript from another, but also to distinguish between browsers that support JavaScript and those that do not. The next section discusses other compatibility techniques that are useful with non-JavaScript browsers.
Copyright © 2003 O'Reilly & Associates. All rights reserved.