I'm aware of the different event models in JavaScript (the WC3 model versus the Microsoft model), as well as the difference between bubbling and capturing. However, after a few hours reading various articles about this issue, I'm still unsure how to properly code the following seemingly simple behavior:
If I have an outer div
and an inner div
element, I want a single mouse-out event to be triggered when the mouse leaves the outer-div. When the mouse crosses from the inner-div to the outer-div, nothing should happen, and when the mouse crosses from the outer-div to the inner-div nothing should happen. The event should only fire if the mouse moves from the outer-div to the surrounding page.
<div id="outer" style = "width:20em; height:20em; border:1px solid #F00" align = "center" onmouseout="alert('mouseout event!')" >
<div id="inner" style = "width:18em; height:18em; border:1px solid #000"></div>
</div>
Now, if I place the mouseout
event on the outer-div, two mouse-out events are fired when the mouse moves from the inner-div to the surrounding page, because the event fires once when the mouse moves from inner to outer, and then again when it moves from outer to the surrounding page.
I know I can cancel the event using ev.stopPropagation()
, so I tried registering an event handler with the inner-div to cancel the event propagation. However, this won't prevent the event from firing when the mouse moves from the outer-div to the inner-div.
So, unless I'm overlooking something, it seems to me this behavior can't be acplished without plex mouse-tracking functions. In the future, I plan to re-implement a lot of this code using a more advanced framework, like jQuery, but for now, I'm wondering if there is a simple way to implement the above behavior in regular JavaScript.
I'm aware of the different event models in JavaScript (the WC3 model versus the Microsoft model), as well as the difference between bubbling and capturing. However, after a few hours reading various articles about this issue, I'm still unsure how to properly code the following seemingly simple behavior:
If I have an outer div
and an inner div
element, I want a single mouse-out event to be triggered when the mouse leaves the outer-div. When the mouse crosses from the inner-div to the outer-div, nothing should happen, and when the mouse crosses from the outer-div to the inner-div nothing should happen. The event should only fire if the mouse moves from the outer-div to the surrounding page.
<div id="outer" style = "width:20em; height:20em; border:1px solid #F00" align = "center" onmouseout="alert('mouseout event!')" >
<div id="inner" style = "width:18em; height:18em; border:1px solid #000"></div>
</div>
Now, if I place the mouseout
event on the outer-div, two mouse-out events are fired when the mouse moves from the inner-div to the surrounding page, because the event fires once when the mouse moves from inner to outer, and then again when it moves from outer to the surrounding page.
I know I can cancel the event using ev.stopPropagation()
, so I tried registering an event handler with the inner-div to cancel the event propagation. However, this won't prevent the event from firing when the mouse moves from the outer-div to the inner-div.
So, unless I'm overlooking something, it seems to me this behavior can't be acplished without plex mouse-tracking functions. In the future, I plan to re-implement a lot of this code using a more advanced framework, like jQuery, but for now, I'm wondering if there is a simple way to implement the above behavior in regular JavaScript.
Share Improve this question edited Apr 14, 2023 at 16:10 Brian Tompsett - 汤莱恩 5,89372 gold badges61 silver badges133 bronze badges asked Apr 24, 2010 at 16:16 Channel72Channel72 851 silver badge4 bronze badges 1- Does the page perhaps treat elements as bined? Like the outer-div itself would just be "outer-div" and then the inner-div inside of it would be "outer-div+inner-div", so if you cross between them it treats them as two separate ones, both with an onmouseout event attached to both of them? Seems kind of odd but that seems to be how the pages are working here. – animuson ♦ Commented Apr 24, 2010 at 16:22
1 Answer
Reset to default 7The mouseout
event on the inner div ‘bubbles’ to the outer div. To detect that this has happened from the outer div, check the target
property of the event
:
<div id="outer">
<div id="inner">x</div>
</div>
document.getElementById('outer').onmouseout= function(event) {
// deal with IE nonsense
if (event===undefined) event= window.event;
var target= 'target' in event? event.target : event.srcElement;
if (target!==this) return;
...
};
The usual problem with mouseout
is you get it when the pointer moves “out” of the parent even if it's only moving “in” to the child. You can detect this case manually by looking up the ancestor list of the element the mouse is moving into:
var other= 'relatedTarget' in event? event.relatedTarget : event.toElement;
while ((other= other.parentNode).nodeType===1)
if (other===this) return;
This is the mousein
/mouseout
model: it is only interested about which element is the mouse's immediate parent. What you more often want is the mouseenter
/mouseleave
model, which considers element trees as a whole, so you'd only get mouseleave
when the pointer was leaving the element-or-its-descendants and not moving directly into the element-or-its-descendants.
Unfortunately mouseenter
/mouseleave
is currently an IE-only event pair. Hopefully other browsers will pick it up as it is expected to be part of DOM Level 3 Events.