- From: Bjoern Hoehrmann <derhoermi@gmx.net>
- Date: Sun, 11 May 2008 04:23:25 +0200
* Magnus Kristiansen wrote: >Mouseover/out events will trigger when elements contained inside the >EventTarget are hovered, and then bubble up. This is contrary to the most >obvious interpretation, as you are still inside (over) the targeted >element. IE supports two events, mouseenter[1] and mouseleave[2], which >solve this problem by not bubbling. This actually has little to do with the bubbling behavior but with the fact that the mouse events are always targeted at the most deeply nested element, while mouseenter and mouseleave are targeted at all ancestors not shared by the two relevant event targets. So moving the cursor from $a to $b you get (in this order): mouseleave to `$a/ancestor-or-self::* except $b/ancestor-or-self::*` mouseenter to `$b/ancestor-or-self::* except $a/ancestor-or-self::*` in, respectively, reverse document order and document order. This means for example that you get no mouseleave event when moving from an element to one of its descendants, and no mouseenter event when moving from an element to one of its ancestors. Calling them mouse-joins-descendant-or- self-axis and mouse-leaves-descendant-or-self-axis would be clearer. >It is possible to work around the problem by using target/relatedTarget >and walking up the DOM tree. However, this requires extra code for every >event handler. Besides, these events were often not meant to be generated >in the first place, by the intent of the author. You can simply generate your own events, using document.createEvent(), and thereby avoid writing code for each handler. You can also use a general purpose wrapper for your handlers that is registered instead and decides whether to call the wrapped handler to a similar effect. For the former you could simply register this brevity-optimized handler on the document for the capture phase for both mouseover and mouseout: function (evt) { var t = [], n = 'mouseenter', b = evt.relatedTarget; for (var x = evt.target; x; x = x.parentNode) if (!b || !((x.compareDocumentPosition(b) || 0x10) & 0x10)) t.push(x); if (evt.type == 'mouseout') { n = 'mouseleave'; t = t.reverse(); } while (t.length) { var ne = document.createEvent("MouseEvents"); ne.initMouseEvent(n, false, evt.cancelable, evt.view, evt.detail, evt.screenX, evt.screenY, evt.clientX, evt.clientY, evt.ctrlKey, evt.altKey, evt.shiftKey, evt.metaKey, evt.button, evt.relatedTarget); t.pop().dispatchEvent(ne); } } In browsers that support the features used above the effect would be as if they support the two additional events. The code for the other method would be simpler, as you can see in several script libraries that support these events in some way. >I have no statistics for how often mouseover/out are used with and without >intent of bubbling, but the anecdotal evidence from my own experience has >never found me wanting it. Not caring about bubbled up event objects is quite different from the mouseenter and mouseleave events, you can simply check the .eventPhase to ignore the former and that you have to do so is a limitation of the registration system. The mouseenter and mouseleave events have their own pseudo-bubbling behavior which might let you forget the benefits. -- Bj?rn H?hrmann ? mailto:bjoern at hoehrmann.de ? http://bjoern.hoehrmann.de Weinh. Str. 22 ? Telefon: +49(0)621/4309674 ? http://www.bjoernsworld.de 68309 Mannheim ? PGP Pub. KeyID: 0xA4357E78 ? http://www.websitedev.de/
Received on Saturday, 10 May 2008 19:23:25 UTC