element. Still, there’s nothing wrong with using it for simple scripts, as shown throughout the
book so far.
The DOM 0 event model includes several events that multiple Hypertext Markup Language
(HTML) tags raise in response to various user actions or state changes. Table 11-1 describes
each event.
Table 11-1 DOM
0 Events
Event Name
Description
onblur()
The element lost focus (that is, it is not selected by the user).
onchange()
The element has either changed (for example, a user typed into a text field)
or lost focus.
onclick()
The mouse clicked an element.
ondblclick()
The mouse double-clicked an element.
onfocus()
The element got focus.
onkeydown()
A keyboard key is pressed (as opposed to released) while the element
has focus.
onkeypress()
A keyboard key is pressed while the element has focus.
onkeyup()
A keyboard key is released while the element has focus.
onload()
The element is loaded (a document, a frameset, or an image).
onmousedown()
A mouse button is pressed.
onmousemove()
The mouse is moved.
onmouseout()
The mouse is moved off of or away from an element.
onmouseover()
The mouse is over an element.
onmouseup()
A mouse button is released.
onreset()
The form element is reset, such as when a user presses a form reset button.
onresize()
The window’s size is changed.
onselect()
The text of a form element is selected.
onsubmit()
The form is submitted.
onunload()
The document or frameset is unloaded.
Newer Event Models: W3C and Internet Explorer
The W3C codified an event model that allows powerful event handling, and almost all later
versions of major browsers support it with the notable exception of Internet Explorer prior
to version 9, which uses a different model. Because the standard W3C event model and the
earlier Internet Explorer event model differ, you must account for each in any JavaScript that
uses either event handling approach rather than only the approach provided by the DOM 0
event model.
Conceptually, the process of event handling is similar in the W3C model and Internet Explorer
models. In both models, you register the event first, associating a function with the event.
Chapter 11 JavaScript Events and the Browser
225
When a registered event gets triggered, the event’s function gets called. However, the location at which the event occurs is one important difference between them.
To understand this difference, imagine a document with a
element and another
element in the body, for example, an . If a visitor moves the mouse over the image,
should the onmouseover() event be handled first within the , or within the ?
The two models diverge in determining where the event should be processed.
The W3C model supports two forms for locating where the event should be handled: Event
Capture and Event Bubbling. With Event Capture, the search for a handler begins at the top
level (the document level) and proceeds downward through the DOM tree to more specific
elements. If you used Event Capture in the example from the last paragraph, an event would
be processed first by the element and then by the element. Processing occurs
in exactly the reverse order for Event Bubbling; the element in which the event occurred gets
searched for a handler first, and the search proceeds upward from there.
As previously stated, the W3C model—and therefore all browsers that adhere to it (in other
words, all browsers except older versions of Internet Explorer)—can use both forms of event
handling (you learn about this soon), whereas older versions of Internet Explorer use only
Event Bubbling. With the W3C model, you register an event using the addEventListener()
method. With the earlier Internet Explorer model, you use attachEvent()for the same purpose. In practical terms, this means that you need to use both methods in every script you
write that handles events, choosing at runtime the one appropriate for the browser in which
the script is running. The basic structure of the addEventListener() method is this:
addEventListener(event,function,capture/bubble);
The capture/bubble parameter is a Boolean value, where true indicates that the event should
use top-down capturing and false indicates that the event should use bubbling. Here’s a typical call to the addEventListener() method for a Submit button. The call registers the submit
event, specifying a function named myFunction() (which would be defined elsewhere in the
The attachEvent() method used in the earlier Internet Explorer model doesn’t require the
third argument, because you don’t have to decide whether to use capturing or bubbling;
the earlier Internet Explorer model offers only bubbling.
Here’s an example of registering the submit event in earlier versions of Internet Explorer,
associating it with myFunction() by calling attachEvent():
226
Part III Integrating JavaScript into Design
window.attachEvent("onsubmit",myFunction());
You might have noticed a subtle difference in the name of the event to which the event
handlers were added—submit, as opposed to onsubmit in the DOM Level 0 model. Many of
the events in the DOM Level 2 changed names. Table 11-2 shows the names of several DOM
Level 0 events and their W3C DOM Level 2 counterparts. Note that the DOM 2 events simply
remove the word “on” from the event name. (The earlier Internet Explorer model uses the
DOM 0 names.)
Table 11-2 DOM
0 and DOM Level 2 Events
DOM 0 Event
DOM 2 Event
onblur()
blur
onfocus()
focus
onchange()
change
onmouseover()
mouseover
onmouseout()
mouseout
onmousemove()
mousemove
onmousedown()
mousedown
onmouseup()
mouseup
onclick()
click
ondblclick()
dblclick
onkeydown()
keydown
onkeyup()
keyup
onkeypress()
keypress
onsubmit()
submit
onload()
load
onunload()
unload
Both the W3C and earlier Internet Explorer models include methods to remove event listeners. In the W3C model, the method is called removeEventListener() and takes the same three
This generic event handler creates an object called EHandler (which stands for event handler),
which then has two methods added to it, add()and remove(), both available in the W3C and
the earlier Internet Explorer models. The add method in each model determines whether the
event type is a load event, meaning that the function needs to be executed on page load. If
the function does, the add handler needs to determine whether any existing onload functions
are already defined. If they are, the handler must set the onload functions to run with the
newly defined function.
For the purposes of this chapter and the remainder of the book, I expect you to save this file
to an external JavaScript file called ehandler.js, and add the file into any JavaScript files in
need of an event handler. As a reminder, you can add an external JavaScript file like this:
Luckily, Windows Internet Explorer 9 uses the W3C compatible model; as that new browser
version becomes more popular in the market, attachEvent will slowly be replaced. However,
sites that support earlier browsers will still need to use the older Microsoft model for years to
come.
You can improve on this event handler script so that it is more suitable for situations you
might encounter when building more powerful JavaScript applications. (You can find more
information about this topic at John Resig’s website: http://ejohn.org/blog/flexible-javascriptevents/.) However, a better solution is to use a JavaScript framework or library, such as jQuery,
to abstract the event model even more.
More Information I discuss in more depth jQuery and other JavaScript frameworks beginning with Chapter 19, “A Touch of AJAX.” For now, the simple event handler script presented in
this section suffices as an example in this book. For more advanced JavaScript programming using events, I recommend you use a library such as jQuery rather than the simple event handler
shown here.
The remainder of this chapter applies knowledge you gained about events as well as about
the Browser Object Model from Chapter 9, “The Browser Object Model”; the Document
Object Model from Chapter 10, “The Document Object Model”; and the syntax from the Part
I of the book, “JavaWhat? The Where, Why, and How of JavaScript.”
Detecting Visitor Information
JavaScript programming often requires browser detection—that is, the detection of which
browser a visitor to a website is using. For several years, browser detection was accomplished
largely by using the userAgent property of the navigator object. The userAgent property
is available through the navigator object and shows information about the user’s browser.
However, relying on the userAgent property is no longer recommended, because visitors can
Chapter 11 JavaScript Events and the Browser
229
so easily forge it. In addition, maintaining accurate userAgent information for every version of
every browser is incredibly difficult.
I personally use five different browsers of various versions. Maintaining an up-to-date list
of which browser supports which feature for just my handful of browsers is even too cumbersome. Imagine what it would be like trying to maintain JavaScript code that accounted for
every browser and every version of that browser! It would be virtually impossible. And that
doesn’t even take fake (either for malicious or other purposes) userAgent strings into account!
So I discuss the userAgent property only briefly and then move on to show the newer (and
much better) methods for determining whether the JavaScript that you’re using will work in
the visitor’s browser. This section also examines other properties of the navigator object that
are helpful, if not 100 percent reliable.
A Brief Look at the userAgent Property
As mentioned, the userAgent string is a property of the navigator object. It contains information about the user’s browser. To show the userAgent information, just type this in your
browser:
javascript:alert(navigator.userAgent);
If you’re using Windows Internet Explorer 7, you might see an alert like the one in Figure
11-1.
Figure 11-1 The userAgent property of the navigator object.
Other browsers report different information. For example, one version of Firefox reports itself
as this:
Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
This string usually changes as each new version of a browser is released. If you tried to track
each released version of each browser, and then tried to track which version of each browser
supported which feature of JavaScript, you’d be spending a lot of time (and possibly a lot of
your employer’s or client’s time as well) maintaining that list.
230
Part III Integrating JavaScript into Design
A much better way to track what is and is not supported in the visitor’s browser is a technique known as feature testing, discussed in the next section.
Feature Testing
Using feature testing, sometimes referred to as object detection, a JavaScript program attempts
to detect whether the browser that is visiting the webpage supports a given feature.
Fortunately, you don’t have to test whether every function and method you want to use are
supported in the visitor’s browser. The DOM Level 0 model and other earlier functions of
JavaScript are so widely supported, and their cross-browser implementations are so close,
that testing for particular features isn’t necessary. However, you must still test whether
JavaScript is available, because not all browsers support JavaScript, and not all visitors have
the JavaScript support option turned on.
The typeof operator is the primary mechanism used to implement feature testing. In general
terms, you use the operator as follows:
if (typeof featureName != "undefined") {
// Do Something Fun With That Feature
}
Try an example. To test for the existence of the getElementById() method, which indicates
that the browser supports the more advanced DOM interface, you might use this code:
if (typeof document.getElementById != "undefined") {
alert("getelembyid is supported");
} else {
alert("no getelembyid support");
}
You may be tempted to skip the use of typeof within the test, and you may see examples on
the web where a feature test looks like this:
if (document.getElementById) { ... }
Unfortunately, this method of feature testing isn’t as reliable as the typeof test. The problem
is that the shorter syntax runs the method. When you omit typeof, the method or property
being tested might return 0 or false by default, which makes the test fail; in other words, it
appears that the browser doesn’t support that method or property—when it actually does.
Therefore, testing using typeof is safer and more reliable.
Chapter 11 JavaScript Events and the Browser
231
Another way to accomplish this task that looks a bit cleaner is to use the ternary operator to
set a flag early in the code. Script that runs later on can use a standard if conditional to check
the flag, as shown here:
// test for getElmementById, set getElem to the result
One of the most discouraging problems you face as a web programmer is dealing with the
presence of older browsers. Writing webpages that have any sort of current look and feel
and still display reasonably well in older browsers is becoming increasingly difficult. What
defines an older browser? Ask three different web designers and you’ll probably get three
different answers. To me, an older browser is one that is more than three years old, though
I lean toward saying two years rather than three.
By this definition, then, Firefox 1.0 is an older browser, even though most webpages display
fine, and almost all the JavaScript code you write will probably work perfectly in that version
of Firefox. A more general rule is that any version of Internet Explorer or Netscape earlier
than version 5 tends to have many, many quirks that web designers must take into account.
Given the depressing fact that browsers even older than Microsoft Internet Explorer 5.0 are
sometimes still in use, accepting that your code might fail in these browsers is a good idea.
You can try to make your code fail gracefully; however, doing even that may not always be
possible. I recently installed a copy of Netscape 3 (which, if I remember correctly, was released
in 1997). The browser had trouble with most JavaScript, and also had problems displaying
HTML and CSS (Cascading Style Sheets) on basic websites. This was to be expected, because
that version of Netscape was released well before many of the standards in use today were
codified. The point is that no matter how hard you try, your website is probably never going
to fail gracefully in really old versions of browsers. I recommend that you choose a minimum
browser level to support—and design for that target, keeping in mind that the later the minimum level, the more visitors you shut out of the site. The goal is to strike a balance between
being a welcoming site and being a cutting-edge site.
There are two primary techniques for keeping JavaScript away from older browsers: inserting
HTML-style comments into the JavaScript, and using the tags.
To use HTML comments in your JavaScript, you surround them within marks, as
shown in this example:
Download from Wow! eBook
232
Part III Integrating JavaScript into Design
Unfortunately, not every browser obeys these HTML comments, so you still encounter errors
sometimes. This style of commenting, or protection, is becoming less and less common. As
the old browsers slowly get cycled out, this type of workaround isn’t really necessary.
Whatever falls between the tag pairs is displayed only when the page
detects no JavaScript support in the browser. Here’s an example of