start page | rating of books | rating of authors | reviews | copyrights

JavaScript: The Definitive Guide

Previous Chapter 18
Compatibility Techniques
Next
 

18.2 Compatibility with Non-JavaScript Browsers

When a user without a JavaScript-capable browser visits your web pages, they obviously won't be able run your JavaScript programs. Therefore, your JavaScript scripts should fail gracefully when read into browsers that do not understand JavaScript. There are two components to this. First, they must not simply format and display your entire JavaScript program as if it was HTML text. And second, they should display a message informing the visitor that their browser cannot correctly handle the page. You can do both of these things with some carefully placed comments.

Hiding Scripts from Old Browsers

Web browsers that support JavaScript will execute the JavaScript statements that appear between the <SCRIPT> and </SCRIPT> tags. Browsers that don't support JavaScript, but that recognize the <SCRIPT> tag, will simply ignore everything between <SCRIPT> and </SCRIPT>. This is as it should be. Other, older browsers, however (and there are a lot of them), do not recognize the <SCRIPT> and </SCRIPT> tags, and so they ignore the tags themselves, and treat all the JavaScript between them as text to be displayed. Users of old browsers cannot run your JavaScript programs, and this should be punishment enough--they should not also have to look at your code!

In order to prevent this, you enclose the body of your scripts within an HTML comment, using the format shown in Example 18.1.

Example 18.1: A Script Hidden from Old Browsers

1  <SCRIPT LANGUAGE="JavaScript">
2  <!-- begin HTML comment that hides the script
3          .
4          . JavaScript statements go here
5          .
6  // end HTML comment that hides the script -->
7  </SCRIPT>

Browsers that do not understand the <SCRIPT> and </SCRIPT> tags simply ignore them. Thus, lines 1 and 7 in Example 18.1 have no effect on these browsers. They'll ignore lines 2 through 6 as well, because the first four characters on line 2 begin an HTML comment, and the last three characters on line 6 end that comment--everything between is ignored by the HTML parser.

This script-hiding technique also works for browsers that do support JavaScript. Lines 1 and 7 indicate the beginning and ending of a script. As noted in Chapter 2, Lexical Structure, JavaScript-enabled web browsers recognize the HTML comment opening string <!--, but treat it as a single-line comment. Thus, a browser with JavaScript support treats line 2 as a single-line comment. Similarly, line 6 begins with the // single-line comment string, so that line is ignored by JavaScript-enabled browsers as well. This leaves lines 3 through 5, which are executed as JavaScript statements.

While it takes a little getting used to, this simple and elegant mix of HTML and JavaScript comments do exactly what we need--prevent JavaScript code from being displayed by browsers that do not support JavaScript. You should get in the habit of using these comments with all your scripts. The comments need not be as verbose as this, of course. It is common to see scripts that look like this:

<SCRIPT LANGUAGE="JavaScript">
<!-- begin hiding
  document.write(new Date());
// end hiding -->
</SCRIPT>
It is also common to strip the English text out of the comments:

<SCRIPT LANGUAGE="JavaScript"> 
<!-- 
  document.write(new Date());
// -->
</SCRIPT>
When writing very short scripts, you can even compress them by removing some of the line breaks:

<SCRIPT LANGUAGE="JavaScript"> <!--
  document.write(new Date());
// --> </SCRIPT>
And even the following is legal:

<SCRIPT LANGUAGE="JavaScript"> <!--
  document.write(new Date()); // --> </SCRIPT>
The only rule to hiding JavaScript code with an HTML comment is that there must be a line break after the <!-- that opens the comment. Remember that this functions as a JavaScript comment, and comments out the remainder of the line. So the JavaScript interpreter won't run any code that follows it.

This commenting technique has solved the problem of hiding our JavaScript code from browsers that can't run it. The next step in failing gracefully is to display a message to the user letting them know that the page cannot run. The next sub-section shows how to accomplish this.

Notifying Users of Old Browsers

In order to inform users of old browsers that their browser cannot successfully run the JavaScript programs on a web page we need some technique for displaying a message on an old browser but not displaying it on a JavaScript-capable browser. This would be easy if we could use a JavaScript if statement and the document.write() method to display the message, but of course we can't do this if the browser doesn't understand JavaScript in the first place. So instead we again rely on HTML comments and take advantage of the fact that JavaScript treats HTML comments differently than HTML does.

JavaScript treats the <!-- sequence that begins an HTML comment as a single-line comment like //. This means that the following text is commented out in both HTML and in JavaScript:

<!-- This text is commented out in HTML and JavaScript -->
JavaScript doesn't recognize the --> closing comment and doesn't care where it occurs, however, so the following text is commented out in JavaScript but not in HTML:

<!-- --> This text is commented out in JavaScript, but not in HTML.
Herein lies the secret to displaying messages on non-JavaScript browsers but not on JavaScript-enabled browsers. Example 18.2 shows what our JavaScript scripts might look like with our JavaScript code hidden from the HTML parser, as above, and with our HTML messages hidden from the JavaScript interpreter.

Example 18.2: Displaying a Message on Non-JavaScript Browsers

<SCRIPT LANGUAGE="JavaScript">
<!-- The message below will only display on non-JavaScript browsers -->
<!-- --> <HR><H1>This Page Requires JavaScript</H1>
<!-- --> Your web browser is not capable of running JavaScript programs,
<!-- --> so you will not be able to use this page. Please consider
<!-- --> upgrading to the latest version of either Netscape Navigator
<!-- --> or Microsoft Internet Explorer.
<!-- --> <HR>
<!-- This HTML comment hides the script from non-JavaScript browsers
        .
        . JavaScript code goes here
        .
// This JavaScript comment is also the end of the HTML comment above. -->
</SCRIPT>

Hiding Scripts from Really Old Browsers

One flaw in the script-hiding scheme described above is that some older web browsers recognize the <!-- string to begin a comment, but then end the comment with a > character alone, instead of looking for a complete --> string. This means that if the > character appears anywhere within your JavaScript code, either in a string, or as one of the >, >=, >> or >>> operators, then the HTML parser for these older browsers will close the comment, and will treat the rest of your script as HTML text to be formatted and displayed.

There are two possible solutions to this problem. The first is to ignore it. Maybe being forced to look at your JavaScript code will encourage users of these really old browsers to upgrade to one that supports the correct HTML comment syntax! Unfortunately, the Lynx browser, prior to version 2.6, is one of the ones that has the problem. This browser for text only terminals fills an important niche, and there are quite a few copies in use. In version 2.6, comment syntax is no longer an issue for Lynx, because it now correctly recognizes the <SCRIPT> tag and ignores anything between it and </SCRIPT>.

The only other solution to this problem is somewhat tedious and not entirely satisfactory. Since the problem is with the ">" character appearing in your JavaScript code, the solution is to make sure that that character does not appear, at least not in its unescaped form. You can do this with the following rules:

Falling Back to a Non-JavaScript Page

Sometimes, if a browser cannot run the scripts in one web page, you'd like to have it load some other page that does not use JavaScript. This page might be a CGI-based version of your program, for example, or it might simply contain static HTML content, formatted in a way that does not rely on embedded JavaScript.

Loading an alternate page would be easy if we could use JavaScript, but obviously, we can't. What we can do, however, instead of "falling back" on a non-JavaScript page is turn things around and "skip ahead" to a JavaScript page if JavaScript is supported. That is, we load the non-JavaScript page by default. This page will actually contain a short script. If the script runs, then JavaScript is supported, and the script uses the Location object to read in the JavaScript version of the page. Example 18.3 shows an example HTML document using this technique.

Example 18.3: Loading a JavaScript-Based Page Only if JavaScript Is Supported

<HEAD>
<SCRIPT LANGUAGE="JavaScript">    <!-- hide script
location = "my_js_home_page.html";      // stop hiding -->
</SCRIPT>
<TITLE>My Home Page (Non-JavaScript Version)</TITLE>
</HEAD>
<BODY>  
        .
        . Arbitrary, non-JavaScript HTML goes here 
        .
</BODY>

You can even automate this process. If every non-JavaScript web page in a directory has a JavaScript equivalent with a filename prefix of "js_", then you might use code like this at the top of a non-JavaScript page to load in the equivalent when JavaScript is supported:

<SCRIPT>                        <!-- hide script
  var pathname = location.path;
  var filename = path.substring(path.lastIndexOf("/")+1, path.length);
  location = "js_" + filename;  // stop hiding -->
</SCRIPT>

There is one shortcoming to the technique shown here. If the user loads a non-JavaScript page in a JavaScript-capable browser, the short initial script will take them to the full JavaScript page. This is what we want. But when they click on the browser's Back, they'll move to the non-JavaScript page, and the script there will send them forward again! In effect, this technique breaks the Back button. With Navigator 3.0, the workaround is to use the replace() method of the Location object rather than assigning directly to the location property. So you should replace the code above with this:

<SCRIPT>                        <!-- hide script
  var path = location.path;
  var filename = "js/" + path.substring(path.lastIndexOf("/")+1, path.length);
  if (location.replace) location.replace(filename)
  else location = filename;     // stop hiding -->
</SCRIPT>


Previous Home Next
Platform, Browser, and Version- Specific Compatibility Book Index Compatibility with JavaScript 1.0 Browsers

HTML: The Definitive Guide CGI Programming JavaScript: The Definitive Guide Programming Perl WebMaster in a Nutshell