Unless you're developing HTML pages for an intranet environment -- where you know the browser version on virtually every client machine -- you're perhaps painfully aware that not everyone accessing your pages can benefit from your scripting efforts. At one extreme is the client running the latest release version of a browser capable of interpreting JavaScript 1.1, the version delivered with Netscape Navigator 3.0. At the other extreme are those visitors who use text-only browsers, such as Lynx. In between are dozens of browser brands and versions. Some can interpret JavaScript 1.0; others understand only Internet Explorer's version of JavaScript; and still others haven't a clue about the HTML scripting embedded in your documents.
Managing browser-specific features has been a
problem for Web authors and Web masters ever since the first HTML extension
found its way into early browsers. With each new generation of modern browsers,
the universe of visitors to our pages fragments ever more, forcing us to
make difficult decisions about how to treat a variety of browsers. If you're
a scripter, it's only natural to think about using JavaScript as an aid
to sorting out browser versions.
WHOOPS NO JAVASCRIPT
Sometimes I think we scripters get too entwined in our JavaScript-enhanced worlds to distinguish between the forest and its trees. I've lost count of the number of newsgroup requests for a script to help a page detect whether or not the browser is JavaScript-enabled. Perhaps the existence of the javaEnabled() method of the Navigator object leads some scripters to expect a corresponding javaScriptEnabled() method.
What these folks fail to realize is that a non-JavaScript browser cannot run such a script...or any script. Therefore, you cannot script an if...else control structure to document.write() one batch of stuff to a page if JavaScript is enabled and a different batch of stuff if JavaScript isn't there (or if it's turned off).
Another dream tactic is to employ a script to
overwrite HTML that would be displayed in non-JavaScript browsers. This,
too, isn't possible: Any standard HTML in a document will appear in all
browsers from Lynx to Communicator. JavaScript cannot inhibit HTML content
display.
DETERMINING THE REAL NEED
While I can't cover every possible scenario in which you might like to distinguish between JavaScript- and non-JavaScript-aware browsers, I see three basic strategies you could use to accomodate browser with different levels of JavaScript awareness. They are:
I believe you can adapt one of these methods to
fit most script vs. non-script situations -- including those that might
otherwise seem hopeless. Solutions range from the very simple to ones that
take a fair amount of forethought and careful execution. In all cases,
think of JavaScript as a page enhancement tool: When the browser is JavaScript-enabled,
the page does something more than when the page is viewed in a non-JavaScript
browser.
A BRANCHING INDEX PAGE
In keeping with my belief that scripting should work silently in the background, without great fanfare, I avoid deploying index.html pages that rely on the site visitor knowing about his or her browser. While Web page authors are extremely sensitive to browser brands and levels, the increasingly large audience of non-nerds surfing the World Wide Web has little, if any, emotional attachment to the browser being used at any moment. To provide an index.html page with two or more links labeled for specific browsers won't help someone who doesn't know exactly what's inside his or her WebTV box.
(Aside: The height of geek bravado must be a site I visited recently [URL withheld so as not to embarrass the page's author] that provided a link labeled for users who had browsers that were HTML 3.2-compatible and a link for those whose browsers weren't up to that level.)
But you can craft the index.html page to branch to many different tracks through your site. The tactic is based on first displaying a nearly content-less index.html page that isn't the true home or welcoming page to your site. Instead, it displays a lone image of any size (perhaps a logo) in the same page location as that image appears in the true home page for each of your browser-dependent tracks.
Let's look at a typical index.html page that provides branches to two tracks in a site: A scripted track that starts at home1.html and an unscripted track that starts at home2.html. The HTML is shown in Example 1.
<HTML> <HEAD> <TITLE>GiantCo OnLine</TITLE> <SCRIPT LANGUAGE="JavaScript"> <!-- window.location = "home1.html" //--> </SCRIPT> <META HTTP-EQUIV="REFRESH" CONTENT="1; URL=http://www.giantco.com/home2.html"> </HEAD> <BODY> <CENTER> <A HREF=home2.html><IMG SRC=images/giantcoLogo.gif HEIGHT=60 WIDTH=120 BORDER=0 ALT="GiantCo Home Page"></A> </CENTER> </BODY> </HTML>
Let me add the following four points about Example 1:
MULTIFUNCTION LINKS
You can always interlace a script within a page's HTML to document.write() a link (or any other feature for that matter) that you want only JavaScript-enabled browsers to see. But if you want a single link to be able to branch to one of two possible destinations based on the scripting ability of the browser, you can use JavaScript to help out.
For this technique, create the link to the non-JavaScript
destination as follows (as you normally would):
<A HREF="nonJSCatalog.html">Product Catalog</A>
To force this link to navigate to a JavaScript-enabled
page, you need to add a special enhancement to the onClick= event
handler for this link: return false. Just as a form's onSubmit=
event handler cancels the submission of the form if its final statement
evaluates to return false, so, too, does a link ignore the HREF
attribute if the onClick= event handler ends that way. Therefore,
to add the JavaScript destination to the link, use the following code:
<A HREF="nonJSCatalog.html" onClick="location='JSCatalog.html';return false">Product Catalog</A>
Without the return false statement, the
visitor will end up at the HREF attribute's location. You can still add
onMouseOver= and onMouseOut= event handlers to the link to
show friendly status bar descriptions of the link for JavaScript-enabled
browsers.
SCRIPT EXECUTION
Since only a JavaScript-enabled browser can respond to object event handlers, you can be sure that plain button clicking, select object choosing, and any other user action will be ignored by a non-JavaScript browser. But what about the cases in which you have JavaScript 1.1 features that will cause script errors in JavaScript 1.0-only browsers, such as Navigator 2.0x and the current versions of Microsoft Internet Explorer 3.0? For example, many eager newcomers to JavaScript employ an onMouseOver= and onMouseOut= event handler for an image link to swap the art file associated with the Image object during a mouse rollover. But the Image object is found only in JavaScript 1.1 browsers; any attempt at setting the src property of an Image object in JavaScript 1.0 yields an unfriendly script error.
If you want an event handler to operate differently for JavaScript 1.0 and 1.1, you can create two separate <SCRIPT> segments in your document with identically-named functions that are called by the event handler. One <SCRIPT> tag specifies LANGUAGE="JavaScript" while the other specifies LANGUAGE="JavaScript1.1". The key here, however, is to make sure that the JavaScript 1.1 tag set is lower in the document than its corresponding JavaScript 1.0 version, as shown in Example 2.
<HTML> <HEAD> <SCRIPT LANGUAGE="JavaScript"> <!-- function doIt() { // statements for JavaScript 1.0 browsers } //--> </SCRIPT> <SCRIPT LANGUAGE="JavaScript1.1"> <!-- function doIt() { // statements for JavaScript 1.1 browsers } //--> </SCRIPT> </HEAD> <BODY> <FORM> <INPUT TYPE=button VALUE="Click Me" onClick="doIt()"> </FORM> </BODY> </HTML>
Similarly, you can mask JavaScript 1.0-level browsers in the LANGUAGE="JavaScript" segment by leaving the statements in the function blank or by displaying an alert for the user about what extra functionality a JavaScript 1.1-level browser brings to the user experience.
Another possibility is to use the JavaScript 1.1 feature that lets you set the event handler property of an object from a script. If you restrict the action of setting the event handler to a JavaScript 1.1 script, then only JavaScript 1.1 browsers will respond to user action, as shown in Example 3.
<HTML> <HEAD> <SCRIPT LANGUAGE="JavaScript1.1"> <!-- function doIt() { // statements for JavaScript 1.1 browsers
} //--> </SCRIPT> </HEAD> <BODY> <FORM> <INPUT TYPE=button NAME=joeButton VALUE="Click Me"> <SCRIPT LANGUAGE="JavaScript1.1"> <!-- document.forms[0].joeButton.onclick=doIt //--> </SCRIPT> </FORM> </BODY> </HTML>
In Example 3, the button object does not have
an explicit event handler in its tag. Instead, the reference to the
doIt() function defined earlier in the document is assigned to the
onclick property of the button. (The property name for an event handler
is always in lower case). The <SCRIPT> tag for this assignment must
come after the <INPUT> tag that creates the button to make sure the
button object exists before its event handler property can be set. In the
document defined in Example 3, only JavaScript 1.1-level browsers respond
to user action in any way.
ADDITIVE JAVASCRIPT
If you examine the implementations suggested throughout this article, you might see that I tend to treat JavaScript as an additive feature of a page wherever possible -- rather than rushing ahead to make two completely separate tracks through a site. Creating multiple tracks within a Web site makes the maintenance chore all the more difficult.
Perhaps the ideal situation is a page that functions well on its own without JavaScript. By interlacing some <SCRIPT> tags within the basic HTML of the page and some of the event handler techniques described here, you can script added functionality into the page, rather than having to generate an entirely separate track. Visitors who have the latest browsers have a more interactive and enjoyable experience at your site, and people with older browsers will be none the wiser.
This technique won't work all the time, of course.
Some of the areas of my Web site, for example, simply require JavaScript
or the user will see next to nothing on the page. But it means that I can
keep the need for parallel pages at a minimum, simplifying the maintenance
task.
THAT ELUSIVE SCRIPT
While there is no magic property, method, or script that detects JavaScript in a browser, you can indeed use JavaScript to enhance the plain HTML page or navigate to fully scripted pages -- and still accommodate nonscriptable browsers. It may take a little extra thought and planning, but the results will invite a wide audience to your site without your having to "dumb down" your pages to the lowest common denominator.
Author and consultant Danny Goodman's 25th book is the JavaScript Bible, the updated second edition of his bestselling JavaScript Handbook, published by IDG Books. His next title, arriving at the end of February 1997, is The Official Marimba Guide to Bongo, published by Sams.net.