I have HTML that looks like this:
<div id="parent">
<div class="child">
Child 1
</div>
<div class="child">
Child 2
</div>
<div class="child">
Child 3
</div>
</div>
I attach mouseenter and mouseout events like so:
$("*").on("mouseenter", function() {
$(this).addClass("mouse_over");
});
$("*").on("mouseout", function() {
$(this).removeClass("mouse_over");
});
Now, imagine the following mouse sequence of events:
The third step is the issue here. I want the mouse_over class to be put back on the parent when reentering the parent from its child element.
I think I understand why this is happening, as technically my mouse is in the parent the whole time so firing the mouseenter event does not make sense.
Here's a fiddle better illustrating what I'm trying to do:
https://jsfiddle.net/tg1wg1xx/
If you hover into the parent and children elements, you'll notice on your way out the pattern overlay is not placed on the parent.
So how can I ensure that the overlay is always placed on whatever element I am currently hovering over?
As Boris explained in his answer, there's 2 different events. To quote him :
mouseenterandmouseleaveare triggered when you enter and leave a hierarchy of nodes, but not when you navigate that hierarchy's descendance.mouseoverandmouseoutare triggered when the mouse respectively enters and leaves a node's "exclusive" space, so you get a "out" when the mouse gets into a child node.
That being said, you need mouseover and mouseout since you need to trigger the mouse out when hovering a child.
$("*").on("mouseover", function(e) {
$(this).addClass("mouse_over");
});
$("*").on("mouseout", function(e) {
$(this).removeClass("mouse_over");
});
Next, you need to know that event bubble in the tree. So when you mouseover on a child, the event is also propagated to the parents. That's why the parent is in hover state even when hovering a child.
To solve that, you need to use .stopPropagation() on the event object.
$("*").on("mouseover", function(e) {
$(this).addClass("mouse_over");
e.stopPropagation();
});
$("*").on("mouseout", function(e) {
$(this).removeClass("mouse_over");
e.stopPropagation();
});
In the spirit of writing less code, you can also use that :
$("*").on("mouseover mouseout", function(e) {
$(this).toggleClass("mouse_over");
e.stopPropagation();
});
mouse events in javascript can be disorienting. Please note that there are two pairs of events that don't mean the same thing :
mouseenter and mouseleave are triggered when you enter and leave a hierarchy of nodes, but not when you navigate that hierarchy's descendance.mouseover and mouseout are triggered when the mouse respectively enters and leaves a node's "exclusive" space, so you get a "out" when the mouse gets into a child node. the behavior you are observing is because you are mixing the two : I updated your fiddle here https://jsfiddle.net/drxrea7e/1/ to use enter and leave.
you can refer to the events' documentation on mozilla's site for detailed info.
Edit after your comment: ah then we need another thing :
the event actually bubbles, so the parent also receives it (but with target = theChild). So you want to add the class only if event.target == this :see my new version of the fiddle : https://jsfiddle.net/drxrea7e/3/.
The children get the image from the class .mouse_over AND the red color from .parent, because background:url() overwrites background-color:white. Is that what you expected?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With