Team LiB
Previous Section Next Section

Internet Explorer 4+ Event Model

The event model of Internet Explorer 4 and later is more advanced than that of Netscape 4. Because every element in the page is represented as an object under IE4+, a richer, more robust set of elements are capable of generating events. In addition, Microsoft has implemented a wider variety of events that apply to each object. One major downside is that event propagation occurs in the opposite manner as with Netscape 4, complicating cross-browser programming in environments where backwards compatibility is important.

Binding Handlers to Objects

No matter what browser the user has, you can always attach event handlers to objects using (X)HTML attributes specified directly in the element or with JavaScript. But Internet Explorer provides an additional mechanism for doing so: the attachEvent() method. This method was added to all document objects in Internet Explorer 5 to support DHTML Behaviors (Chapter 21), and probably in anticipation of the DOM2 standard as well (though the semantics of its DOM2 cousin are much different).

The attachEvent() method has the following syntax,

object.attachEvent(“event to handle“, eventHandler);

where the first parameter is a string like “onclick” and eventHandler is the function that should be invoked when the event occurs. The return value is a Boolean indicating whether attachment was successful.

To remove a handler bound this way, use detachEvent() with the exact same arguments. The following simple example illustrates the syntax:

<<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">>
<<html xmlns="http://www.w3.org/1999/xhtml">>
<<head>>
<<title>>IE Attach/Detach Event Test<</title>>
<<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />>
<<script type="text/javascript">>
<<!--
function showAuthor() 
{
  alert("Oscar Wilde");
}
function enableEvent() 
{
  someText.attachEvent("onmouseover", showAuthor);
}
function disableEvent() 
{
 someText.detachEvent("onmouseover", showAuthor);
}
//-->>
<</script>>
<</head>>
<<body onload="enableEvent();">>
<<em id="someText">>We may be in the gutter, but some of us are looking at the
 stars<</em>>
<<form action="#" method="get">>
 <<input type="button" value="Attach Event" onclick="enableEvent();" />>
 <<input type="button" value="Detach Event" onclick="disableEvent();" />>
<</form>>
<</body>>
<</html>>
Note 

You can bind multiple handlers for the same event to a single object using attachEvent(). However, there is no guarantee on the order in which the handlers will be called.

Event Objects

Similar to Netscape 4, when an event occurs in Internet Explorer, the browser creates a transient Event object and makes it available to the appropriate handler. Unlike Netscape 4, it is implicitly made available as the global variable event. Some properties of the object are listed in Table 11-8.

Table 11-8: Some Useful Properties of the IE4+ Event Object

Property

Description

>srcElement

Reference to the object for which the event is intended (i.e., the event's target).

>Type

String containing the type of event, e.g., "click".

>clientX

Numeric value indicating the horizontal coordinate of the event.

>clientY

Numeric value indicating the vertical coordinate of the event.

>screenX

Numeric value indicating the horizontal coordinate of the event relative to the whole screen.

>screenY

Numeric value indicating the vertical coordinate of the event relative to the whole screen.

>button

Numeric value indicating the mouse button pressed (primary is 0, but varies from system to system).

>keyCode

Numeric value indicating the Unicode value of the key depressed.

>altKey

Boolean indicating if the Alt key was depressed.

>ctrlKey

Boolean indicating if the Ctrl key was depressed.

>shiftKey

Boolean indicating if the Shift key was depressed.

>cancelBubble

Boolean indicating whether the event should not bubble up the hierarchy.

>returnValue

Boolean indicating the return value from the event handler. Other handlers
in the bubbling chain have the opportunity to change this value unless event bubbling has been canceled.

>fromElement

Reference to the element the mouse is moving away from in a mouseover
or mouseout.

>toElement

Reference to the element the mouse is moving to during mouseover or mouseout.

Since the Event object is implicitly available everywhere, there’s no need to pass it to a handler bound with JavaScript. However, there’s no harm in doing so, and the practice means that your scripts will work with both Netscape 4 and IE4+.

Event Bubbling

The flow of events in Internet Explorer is the opposite of Netscape 4. Most events begin at the object at which they occur and bubble up the hierarchy. Bubbling events give the appropriate handler at each level in the hierarchy the opportunity to handle, redirect, or pass the event along up the tree. Bubbling events proceed up to the Document, but there they stop (i.e., they don’t propagate up to the Window).

Some events that have specific, well-defined meanings, such as form submission and receiving focus, do not bubble. Whereas bubbling events work their way up the tree, causing the appropriate handler to be invoked at each level in the hierarchy until they reach the top or are canceled, non-bubbling events invoke the handler only of the object at which they occur. The rationale is that such events do not have well-defined semantics at a higher level in the hierarchy, so they should not be propagated up the tree. The list of Internet Explorer events and their bubbling behavior is given in Table 11-9.

Table 11-9: Behavior of Internet Explorer Events

Event Handler

Bubbles?

Cancelable?

onabort

No

Yes

onactivate

Yes

No

onafterprint

No

No

onafterupdate

Yes

No

onbeforeactivate

Yes

Yes

onbeforecopy

Yes

Yes

onbeforecut

Yes

Yes

onbeforedeactivate

Yes

Yes

onbeforeeditfocus

Yes

Yes

onbeforepaste

Yes

Yes

onbeforeprint

No

No

onbeforeunload

No

Yes

onbeforeupdate

Yes

Yes

onblur

No

No

onbounce

No

Yes

oncellchange

Yes

No

onchange

No

Yes

onclick

Yes

Yes

oncontextmenu

Yes

Yes

oncontrolselect

Yes

Yes

oncopy

Yes

Yes

oncut

Yes

Yes

ondataavailable

Yes

No

ondatasetchanged

Yes

No

ondatasetcomplete

Yes

No

ondblclick

Yes

Yes

ondeactivate

Yes

No

ondrag

Yes

Yes

ondragend

Yes

Yes

ondragenter

Yes

Yes

ondragleave

Yes

Yes

ondragover

Yes

Yes

ondragstart

Yes

Yes

ondrop

Yes

Yes

onerror

No

Yes

onerrorupdate

Yes

No

onfilterchange

No

No

onfinish

No

Yes

onfocus

No

No

onfocusin

Yes

No

onfocusout

Yes

No

onhelp

Yes

Yes

onkeydown

Yes

Yes

onkeypress

Yes

Yes

onkeyup

Yes

No

onlayoutcomplete

Yes

Yes

onload

No

No

onlosecapture

No

No

onmousedown

Yes

Yes

onmouseenter

No

No

onmouseleave

No

No

onmouesmove

Yes

No

onmouseout

Yes

No

onmouseover

Yes

Yes

onmouseup

Yes

Yes

onmousewheel

Yes

Yes

onmove

Yes

No

onmoveend

Yes

No

onmovestart

Yes

Yes

onpaste

Yes

Yes

onpropertychange

No

No

onreadystatechange

No

No

onreset

No

Yes

onresize

No

No

onresizeend

Yes

No

onresizestart

Yes

Yes

onrowenter

Yes

No

onrowexit

No

Yes

onrowsdelete

Yes

No

onrowsinserted

Yes

No

onscroll

No

No

onselect

No

Yes

onselectionchange

No

No

onselectstart

Yes

Yes

onstart

No

No

onstop

No

No

onsubmit

No

Yes

onunload

No

No

You might wonder about the cancelable column in Table 11-9. The idea here is that an event that is cancelable can have its upward progress halted in script. We’ll see how to do this in a moment, but for now to illustrate event bubbling in action, consider the following example. Handlers for clicks are defined for many objects in the hierarchy, and each writes the name of the element to which it is attached into the paragraph with id of “results”:

 <<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">>
<<html xmlns="http://www.w3.org/1999/xhtml">>
<<head>>
<<title>>Event Bubbling Example<</title>>
<<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />>
<<script type="text/javascript">>
<<!--
function gotClick(who) 
{
  document.all.results.innerHTML += who + " got the click <<br />>";
}
//-->>
<</script>>
<</head>>
<<body onclick="gotClick('body');">>
<<table onclick="gotClick('table');">>
 <<tr onclick="gotClick('tr');">>
   <<td onclick="gotClick('td');">>
     <<p onclick="gotClick('p');">>
Click on the <<b onclick="gotClick('b');">>BOLD TEXT<</b>> to
watch bubbling in action!
     <</p>> 
   <</td>> 
 <</tr>> 
<</table>>
<<hr />> <<br />>
<<p id="results">> <</p>>
<</body>>
<</html>>

Clicking the bold text causes a click event to occur at the <<b>> tag. The event then bubbles up, invoking the onclick handlers off objects above it in the containment hierarchy. The result is shown in Figure 11-1.

Click To expand
Figure 11-1: A click on the bold text causes a click event, which bubbles up the hierarchy.

Preventing Bubbling

You can stop events from propagating up the hierarchy by setting the cancelBubble property of the Event object. This property is false by default, meaning that after a handler is finished with the event, it will continue on its way up to the next enclosing object in the hierarchy. Setting the cancelBubble property to true prevents further bubbling after the current handler has finished. For example, you could prevent the event from getting beyond the <<b>> tag in the last example by making this small modification:

...<<b onclick="gotClick('b');event.cancelBubble=true;">>BOLD TEXT<</b>>...

The result of clicking on the bold text after this change is made is shown in Figure 11-2.

Click To expand
Figure 11-2: If an event is cancelable, setting event.cancelBubble prevents the event from propagating.

Not all events are cancelable; Table 11-9 indicates whether each event can be canceled in this way.

It is important to keep in mind that returning false from a handler (or setting event.returnValue to false) prevents the default action for the event, but does not cancel bubbling. Later handlers invoked by the bubbling behavior will still have a chance to handle the event, and any value they return (or set event.returnValue to) will “overwrite” the value set or returned by a previous handler.

Conversely, canceling bubbling does not affect the event’s return value. Because the default returnValue of an event is true, you need to be sure to return false or set returnValue to false if you wish to prevent the event’s default action.

Imitating Netscape’s Event Capture

Because all parts of the page are scriptable in IE4+, performing event captures as in Netscape 4 is very easy. Simply set the handler at the appropriate level in the hierarchy, for example, to capture clicks at the Document level with the function myHandler:

document.onclick = myHandler;

and omit Click handlers from lower objects. To unset event capture, simply set the appropriate handler to null, for example, to turn off click capturing at the Document level:

document.onclick = null;

Event Routing

Events bubble up strictly through objects in the hierarchy that contain them. There is, however, a primitive way to redirect to another object in Internet Explorer 5.5+. Each object has a fireEvent() method that transfers the event to the object on which it is invoked:

object.fireEvent(“event to fire“ [, eventObject])

The first argument is a string denoting the handler to fire, for example, "onclick". The optional eventObject parameter is the Event object from which the new Event object will be created. If eventObject is not given, a brand new Event is created and initialized as if the event had really occurred on the target object. If eventObject is specified, its properties are copied into the new Event object, except for cancelBubble, returnValue, srcElement, and type. These values are always initialized (respectively) to false, true, the element on which the event is firing, and the type of event given by the first argument to fireEvent().

One major downside of this method is that its invocation causes a new Event to be created, so the reference to the original target (event.srcElement) is lost during the handoff.

The following example illustrates the method:

function handleClick() 
{
   event.cancelBubble = true;
   // Redirect event to the first image on the page
   document.images[0].fireEvent("onclick", event);
}

When set as a click handler, the prceding function redirects the event to the first image in the page.

Remember to cancel the original event before redirecting to another object; failing to do so “forks” the event by allowing it to continue on its way up the hierarchy while adding the new event created by fireEvent() to the event queue. The new event will be fired only after the original event has finished bubbling.

Event Creation

In the basic event model, you can simulate events by invoking event handlers directly as well as implicitly create a few “real” events by invoking methods like submit() and focus(). Netscape 4 provided more flexibility with its routeEvent() method. Internet Explorer 5.5+ goes well beyond these capabilities by providing a way to create actual Event objects. The syntax is

var myEvent = document.createEventObject([eventObjectToClone]);

This createEventObject() method of the Document object returns an Event object, cloning the eventObjectToClone argument if one exists. You can set the properties of the newly created Event and cause the event to occur on an object of your choice by passing it as an argument to fireEvent().

While most programmers won’t really have cause to use this feature, the ability to create arbitrary events and cause them to occur on any element in the document hierarchy can be quite handy if you’re writing JavaScript-based applications. For example, they’re a useful base on top of which to build a generic JavaScript message-passing system, and can also be used to create user interface tests of complex sequences of user actions that would be laborious to trigger by hand.

Other Proprietary Features

Internet Explorer—especially versions 5.5 and later—provides more event-related features than we’ve covered here. Most of these features involve the proprietary event handlers IE supports for special user actions like dragging and dropping, printing, and so forth. To learn more, visit http://msdn.micrsosoft.com.


Team LiB
Previous Section Next Section