Web DevCenter
oreilly.comSafari Books Online.Conferences.
MySQL Conference and Expo April 14-17, 2008, Santa Clara, CA

Sponsored Developer Resources

Web Columns
Adobe GoLive
Essential JavaScript
Megnut

Web Topics
All Articles
Browsers
ColdFusion
CSS
Database
Flash
Graphics
HTML/XHTML/DHTML
Scripting Languages
Tools
Weblogs

Atom 1.0 Feed RSS 1.0 Feed RSS 2.0 Feed

Learning Lab






Supporting Three Event Models at Once
Pages: 1, 2, 3

W3C DOM Node Event Targets

The W3C DOM node architecture allows each node in a document tree to receive events. In browsers that support this architecture, event handlers assigned to text containers are not the targets of events that occur atop the nested text. The text nodes are the target objects. Consider the following:



In the events example, when the mouse pointer rolls atop the text of a SPAN element, the text within that span will be highlighted. Event binding occurs via object properties in the init() function. On the face of it, when a user rolls the mouse atop the SPAN element, the onMouseOver event action assigns the class name (highlight) associated with a style sheet rule that displays the text in bold face and a yellow background; with onMouseOut, the style reverts to its original version (class normal). Notice how one toggleHighlight() function performs both actions with the help of the event object's type property (a property whose name is the same across all event model objects). Try the events example.

Related Reading

Designing with JavaScript, 2nd EditionDesigning with JavaScript, 2nd Edition
By Nick Heinle & Bill Peña
Table of Contents
Index
Sample Chapter
Full Description

But if you load the example into NN6, the true target of the mouse events is the text node inside the SPAN element. Although we don't cover event propagation in this article, take it on faith that the default behavior of the W3C DOM event model causes events to bubble upward through the node containment hierarchy (much like IE4+ events bubble up through element containers). Therefore, in the events example, the mouse events bubble upward from their true targets to the text node's container (that is, the SPAN element). These events trigger the SPAN element's event handlers for those two events.

Even though the event handler belongs to the SPAN element, the event object preserves the reference to the text node as being the event's original target. Modifying the text node's style, however, requires acting on its container. To equalize the operation of the toggleHighlight() function so that it can modify the className property of the SPAN container, the function needs to derive a reference to the text node's container.

One tactic is to use the W3C DOM event object's currentTarget property, which returns a reference to the node that processes the event. The decision tree required to take this property into account lengthens the toggleHighlight() function as follows:

function toggleHighlight(evt) {
  evt = (evt) ? evt : ((window.event) ? window.event : "")
  if (evt) {
    var elem
    if (evt.target) {
      if (evt.currentTarget && (evt.currentTarget != evt.target)) {
        elem = evt.currentTarget
      } else {
        elem = evt.target
      }
    } else {
      elem = evt.srcElement
    }
    elem.className = (evt.type == "mouseover") ? "highlight" : "normal"
  }
}

An alternate approach is to examine the nodeType property of the object returned by the target property. A browser capable of directing events to text nodes would also report the nodeType property of a text node as a value of 3, rather than the value for an element node (a value of 1). If the event target is a text node, then a script can obtain a reference to the surrounding element node via the text node's parentNode property. The decision tree for this approach is somewhat more streamlined:

function toggleHighlight(evt) {
  evt = (evt) ? evt : ((window.event) ? window.event : "")
  if (evt) {
    var elem
    if (evt.target) {
      elem = (evt.target.nodeType == 3) ? evt.target.parentNode : evt.target
    } else {
      elem = evt.srcElement
    }
    elem.className = (evt.type == "mouseover") ? "highlight" : "normal"
  }
}

If you are viewing this article with Netscape 6, try this modified version to see the style change with the mouse rollover.

With this last version of toggleHighlight() embedded into the events example, the page demonstrates how to use JavaScript to add value to the page for browsers capable of the desired effect. At the same time, the basic content, albeit in a less engaging and interactive mode, is still available for users of older or other non-scriptable browsers.

An Event Handler Function Template

Not every event handler function deals with the same properties or behaviors of element objects on the page, but you can start coding such functions with the help of a template derived from the discussions above. The template follows:

function functionName(evt) {
  evt = (evt) ? evt : ((window.event) ? window.event : "")
  if (evt) {
    var elem
    if (evt.target) {
      elem = (evt.target.nodeType == 3) ? evt.target.parentNode : evt.target
    } else {
      elem = evt.srcElement
    }
    if (elem) {
      // process event here
    }
  }
}

Substitute your function's name in the first line and start your event-specific code where indicated. This format should get you started for any cross-browser event binding style you employ. If you use this format a lot within a page, you can condense it further by extracting the target-reading code as a reusable utility function, and invoke it from each of your event handler functions:

// shared function
function getTargetElement(evt) {
  var elem
  if (evt.target) {
    elem = (evt.target.nodeType == 3) ? evt.target.parentNode : evt.target
  } else {
    elem = evt.srcElement
  }
  return elem

}

function functionName(evt) {
  evt = (evt) ? evt : ((window.event) ? window.event : "")
  if (evt) {
    var elem = getTargetElement(evt)
    if (elem) {
      // process event here
    }
  }
}

With this kind of framework in place, you should now be able to focus more closely on the specific actions required for each event handler function.

Danny Goodman has been writing about technology and computers full-time since 1981 and is the author of Dynamic HTML: The Definitive Reference and "The Complete HyperCard Handbook."


Return to the JavaScript and CSS DevCenter.