6.3.2. Event Handlers as Object Properties
As of Navigator 3 and Internet
Explorer 4, an event handler can also be assigned to an object as a
property of that object via a script statement. For every event that
an object supports, the object has a property with the event handler
name in all lowercase (although some browsers also recognize the
intercapitalized version, as well). You use the standard assignment
operator (=) to assign a function reference to the
event handler. Because modern DOMs treat each script function as an
object, a function reference is an unquoted name of a function,
without the parentheses normally associated with the function name.
For example, to have a button's
onclick event handler invoke a function named
handleClick( ) defined elsewhere in the document,
the assignment statement is:
document.forms[0].buttonName.onclick = handleClick;
Notice, too, that the reference to the function name is
case-sensitive. Be sure to preserve function name capitalization in
its equivalent reference.
Binding event handlers to
objects as properties has advantages and disadvantages. One advantage
is that you can use scripted branching to simplify the invocation of
event handler functions that require (or must omit) certain browser
versions. For example, if you implement an image-swapping mouse
rollover atop a link surrounding an image, you can weed out old
browsers that don't support image swapping by not
assigning the event handler to those versions:
if (document.images) {
document.links[1].onmouseover = swapImage1;
}
Without an event handler specified in the tag, an older browser is
not tripped up by the invalid object, and the image swapping function
doesn't have to do the version checking.
Moving event handler binding to
script statements also means that you don't have to
worry about HTML and XHTML validators tripping up on event handlers
that are not defined in those standards. This is how you can employ a
nonstandard event handler and still allow the page to pass formal
validation.
A minor disadvantage for the conversion of legacy scripts to the new
format is that this approach does not let you pass parameters to
functions. Netscape 6 or later automatically passes an
event object as the lone parameter to the
function, while IE passes none (because all event information is in
IE's window.event object). It is
up to the called function to derive element object information from
the browser's event object, regardless of how it
exposes itself to the function.
At times more daunting, however, is
the fact that event handler assignment statements must be executed
after the script function and the bound element have loaded into the
browser (and thus into the page's object model).
This means that the assignment statement either must be physically
below the element's tag in the document or it must
run in a function invoked by the window's
onload event handler. If the function or element
object is not yet loaded, the assignment statement causes an error
because the object does not yet exist and the reference to the object
fails.
This
doesn't mean that you can't assign
event handlers by script to run immediately as the page loads. But
you must choose your targets carefully. Assigning events to the
window and document objects is
safe in such statements (after the functions, that is) because those
two objects are valid immediately. Some browsers also assume the
existence of the document.body object while
scripts in the head execute during page loading,
but that behavior is not universal. Your page and script design may
also allow you to define event handlers at the
document level, and let events from elements
bubble up to the document (see Section 6.5 later in this chapter). The
onus is then on the function to examine the event
object and process events from intended targets, while ignoring
events from elsewhere.
Note, too, that event handler assignment allows you to invoke only
one function per event type per element object. Unlike the tag
attribute approach, which lets you chain together a
semicolon-delimited series of script expressions, you get only one
shot at reference assignment. If your page is set up with multiple
assignments of the same element object and event property, the last
one to load is the winner. For example, the DHTML API library from
Chapter 4 contains its own
window.onload event handler assignment to ensure
that the initDHTMLAPI( ) function is called
automatically. But in Examples 4-4 and 4-5, an
onload event handler in the
<body> tag (the tag equivalent of assigning
window object event handlers) invokes both the
initDHTMLAPI( ) function and some other
application-specific function. The tag assignment overrides the
assignment from the external library. Alternatively, these pages
could create one more startup function that invokes both
initDHTMLAPI( ) and the initial action function,
and that startup function reference could be assigned to
window.onload at the bottom of the
head section's scripts.
Tag attribute and object property assignment are the two event
binding techniques that work best across all browsers. The remaining
three techniques are limited to individual DOM implementations and
are not easy to branch
around.