JavaScript: Windows and Frames
Pages: 1, 2, 3, 4, 5, 6, 7
Timeouts and Intervals
The setTimeout( ) method of the
Window object schedules a piece of JavaScript code to be run at some specified
time in the future. The clearTimeout( ) method can
be used to cancel the execution of that code. setTimeout(
) is commonly used to perform animations or other kinds of repetitive
actions. If a function runs and then uses setTimeout(
) to schedule itself to be called again, we get a process that repeats
without any user intervention. JavaScript 1.2 has added the setInterval( ) and clearInterval(
) methods, which are like setTimeout( ) and
clearTimeout( ), except that they automatically
reschedule the code to run repeatedly; there is no need for the code to
reschedule itself.
The setTimeout( ) method is commonly
used in conjunction with the status or defaultStatus properties to animate some kind of message
in the status bar of the browser. In general, animations involving the status
bar are gaudy, and you should shun them! There are, however, a few status-bar
animation techniques that can be useful and in good taste. Example
13-2 shows such a tasteful status-bar animation. It displays the current
time in the status bar and updates that time once a minute. Because the update
occurs only once a minute, this animation does not produce a constant
flickering distraction at the bottom of the browser window, like so many
others do.
Note the use of the onload event
handler of the <body> tag to perform the
first call to the display_time_in_status_line( )
method. This event handler is invoked once when the HTML document is fully
loaded into the browser. After this first call, the method uses setTimeout( ) to schedule itself to be called every 60
seconds so that it can update the displayed time.
<html>
<head>
<script>
// This function displays the time in the status line
// Invoke it once to activate the clock; it will call itself from then on
function display_time_in_status_line( )
{
var d = new Date( );
// Get the current time
var h = d.getHours( );
// Extract hours: 0 to 23
var m = d.getMinutes( );
// Extract minutes: 0 to 59
var ampm = (h >= 12)?"PM":"AM";
// Is it a.m. or p.m.?
if (h > 12) h -= 12;
// Convert 24-hour format to 12-hour
if (h == 0) h = 12;
// Convert 0 o'clock to midnight
if (m < 10) m = "0" + m;
// Convert 0 minutes to 00 minutes, etc.
var t = h + ':' + m + ' ' + ampm;
// Put it all together
defaultStatus = t;
// Display it in the status line
// Arrange to do it all again in one minute
setTimeout("display_time_in_status_line( )", 60000);
// 60000 ms is one minute
}
</script>
</head>
<!-- Don't bother starting the clock till everything
is loaded. The status line will be busy with other
messages during loading, anyway. -->
<body onload="display_time_in_status_line( );">
<!-- The HTML document contents go here -->
</body>
</html>
In JavaScript 1.2, Example
13-2 could be written using setInterval( )
instead of setTimeout( ). In this case, the
setTimeout( ) call would be removed from the
display_time_in_status_line( ) method, and we'd remove
the onload event handler. Instead, after defining
display_time_in_status_line( ), our script would
call setInterval( ) to schedule an invocation of
the function that automatically repeats once every 60,000 milliseconds.
Error Handling
The onerror property of a Window
object is special. If you assign a function to this property, the function
will be invoked whenever a JavaScript error occurs in that window: the
function you assign becomes an error handler for the window.
Three arguments are passed to an error handler. The first is a
message describing the error that occurred. This may be something like
"missing operator in expression", "self is read-only", or "myname is not
defined". The second argument is a string that contains the URL of the
document containing the JavaScript code that caused the error. The third
argument is the line number within the document where the error occurred. An
error handler can use these arguments for any purpose it desires. A typical
error handler might display the error message to the user, log it somewhere,
or force the error to be ignored.
In addition to those three arguments, the return value of the
onerror handler is significant. Browsers typically
display an error message in a dialog box or in the status line when an error
occurs. If the onerror handler returns
true, it tells the system that the handler has handled
the error and that no further action is necessary--in other words, the system
should not display its own error message. For example, if you do not want your
users to be pestered by error messages, no matter how buggy the code you write
is, you could use a line of code like this at the start of all your JavaScript
programs:
self.onerror = function( ) { return true; }
Of course, doing this will make it very difficult for users to
give you feedback when your programs fail silently without producing error
messages.
We'll see a sample use of an onerror
handler in Example 14-1. That example uses the
onerror handler to display the error details to the user
and allow the user to submit a bug report containing those details.
Note that the onerror error handler
is buggy in Netscape 6. Although the function you specify is triggered when an
error occurs, the three arguments that are passed are incorrect and unusable.
Netscape 6 and other browsers that support JavaScript 1.5 have an alternative
means of catching and handling errors, however: they can use the
try/catch statement. (See Chapter 6 for details.)
The Navigator Object
The Window.navigator property refers
to a Navigator object that contains information about the web browser as a
whole, such as the version and a list of the data formats it can display. The
Navigator object is named after Netscape Navigator, but it is also supported
by Internet Explorer. IE also supports
clientInformation as a vendor-neutral synonym for
navigator. Unfortunately, Netscape and Mozilla do not
support this property.
The Navigator object has five main properties that provide
version information about the browser that is running:
appName
The simple name of the web browser.
appVersion
The version number and/or other version information
for the browser. Note that this should be considered an "internal" version
number, since it does not always correspond to the version number displayed
to the user. For example, Netscape 6 reports a version number of 5.0, since
there never was a Netscape 5 release. Also, IE Versions 4 through 6 all
report a version number of 4.0, to indicate compatibility with the baseline
functionality of fourth-generation browsers.
userAgent
The string that the browser sends in its USER-AGENT HTTP header. This property typically
contains all the information in both appName and
appVersion.
appCodeName
The code name of the browser. Netscape uses the code
name "Mozilla" as the value of this property. For compatibility, IE does the
same thing.
platform
The hardware platform on which the browser is
running. This property was added in JavaScript 1.2.
The following lines of JavaScript code display each of these
Navigator object properties in a dialog box:
Figure
13-2 shows the dialog box displayed when the code is run on IE 6.
Figure 13-2. Navigator object properties
As you can see from Figure
13-2, the properties of the Navigator object have values that are
sometimes more complex than we are interested in. We are often interested in
only the first digit of the appVersion property,
for example. When using the Navigator object to test browser information, we
often use methods such as parseInt( ) and
String.indexOf( ) to extract only the information we
want. Example
13-3 shows some code that does this: it processes the properties of the
Navigator object and stores them in an object named
browser. These properties, in their processed form, are
easier to use than the raw navigator properties.
The general term for code like this is a "client sniffer," and you can find
more complex and general-purpose sniffer code on the Internet.
(See, for example, The Ultimate JavaScript Client Sniffer.)
For many purposes, however, something as simple as that shown in Example
13-3 works just fine.
Example 13-3: Determining browser vendor and version
/*
* File: browser.js
* Include with: <script SRC="browser.js"></script>
*
* A simple "sniffer" that determines browser version and vendor.
* It creates an object named "browser" that is easier to use than
* the "navigator" object.
*/
// Create the browser object
var browser = new Object( );
// Figure out the browser's major version
browser.version = parseInt(navigator.appVersion);
// Now figure out if the browser is from one of the two
// major browser vendors. Start by assuming it is not.
browser.isNetscape = false;
browser.isMicrosoft = false;
if (navigator.appName.indexOf("Netscape") != -1)
browser.isNetscape = true;
else if (navigator.appName.indexOf("Microsoft") != -1)
browser.isMicrosoft = true;