Ive got the following html setup:
<div id="div1">
<div id="content1">blaat</div>
<div id="content1">blaat2</div>
</div>
it is styled so you can NOT hover div1 without hovering one of the other 2 divs.
Now i've got a mouseout on div1.
The problem is that my div1.mouseout gets triggered when i move from content1 to content2, because their mouseouts are bubbling.
and the event's target, currentTarget or relatedTarget properties are never div1, since it is never hovered directly...
I've been searching mad for this, but I can only find articles and solutions for problems who are the reverse of what I need. It seems trivial but I can't get it to work...
The mouseout of div1 should ONLY get triggered when the mouse leaves div1.
One of the possibilities would be to set some data on mouse enter and mouseleave, but I'm convinced this should work out of the box, since it is just a mouseout...
EDIT:
bar.mouseleave(function(e) {
if ($(e.currentTarget).attr('id') == bar.attr('id')) {
bar.css('top', '-'+contentOuterHeight+'px');
$('#floatable-bar #floatable-bar-tabs span').removeClass('active');
}
});
changed the mouseout to mouseleave and the code worked...
Use the mouseleave event instead or mouseout for this, it handles your specific issue. See here for details
From the docs on the difference:
The mouseleave event differs from mouseout in the way it handles event bubbling. If mouseout were used in this example, then when the mouse pointer moved out of the Inner element, the handler would be triggered. This is usually undesirable behavior. The mouseleave event, on the other hand, only triggers its handler when the mouse leaves the element it is bound to, not a descendant. So in this example, the handler is triggered when the mouse leaves the Outer element, but not the Inner element.
Example markup:
<div id="outer">
Outer
<div id="inner">
Inner
</div>
</div>
The hover method has two parameters, first for mouse in and second for mouse out.
$('your_div').hover(function(){
// your code here.
}, function(){// any mouse out code here})
Related
I've got a DOM structure like the one below. These to elements are overlaping. On hover, video start to play. Unfortunately, when I hover over .showsOnHover, mouseover and mouseout repeatedly fire one after another making .showsOnHover blink and video stutter.
What should I do to instruct browser to treat hovering over .showsOnHover as one continuous hover?
.html
<video (mouseover)="mouseover()" (mouseout)="mouseout()"></video>
<div [hidden]="!hovering" class="showsOnHover"></div>
.ts
mouseover(e){
this.hovering = true;
this.video.play();
}
mouseout(e){
this.hovering = false;
this.video.stop();
}
The issue is that when showsOnHover is shown, it covers up the video, which makes it mouseout, so it hides the div, then the hover event triggers again, and it shows the div, and it just loops over and over very rapidly.
You essentially will want to do one of the following:
Put the mouseover and mouseout events on both the video and the showsOnHover elements, perhaps do it on a containing parent div element. This way the mouseout event won't be triggered when it's shown; instead it will only trigger when you leave the larger containing element.
Add pointer-events: none; to your .showsOnHover class in the CSS. This makes that div transparent to mouse events. However, this could cause issues if you wanted to run any click events off that button.
Change mouseover to mouseenter as mentioned in Ram's answer
create a parent div and fire the same event on that,
<div class="parentDiv" (mouseenter)="mouseover()" (mouseleave)="mouseout()">
<video></video>
<div [hidden]="!hovering" class="showsOnHover"></div>
</div>
Use mouseenter instead of mouseover
mouseenter(e){
this.hovering = true;
this.video.play();
}
[.mouseover()] can cause many headaches due to event bubbling. For
instance, when the mouse pointer moves over the Inner element in this
example, a mouseover event will be sent to that, then trickle up to
Outer. This can trigger our bound mouseover handler at inopportune
times. See the discussion for .mouseenter() for a useful alternative.
Please see What is the difference between the mouseover and mouseenter events?
Use (mouseenter) and (mouseleave) instead of (mouseover) and (mouseout)
When my overlay comes up, everything works well, but I added some code to close out the overlay, but this code gets triggered even when I'm just clicking my arrows. The following is the code that's being triggered, which is fine when I'm not clicking the arrows to change the image. But when I click the arrows, the background which is the overlay is also being trigger, so the image is changing but the overlay is also hiding.
$('#overlay').click(function() {
$(this).fadeOut('slow');
});
How can I be able to use the arrows without it also clicking on the background overlay? If you open up the project, you will see what I'm saying.
To open the project:
https://htmlpreview.github.io/?https://github.com/rodriguesandrewb/photo_gallery_v1/blob/master/index.html
To open the repository:
https://github.com/rodriguesandrewb/photo_gallery_v1
You want to use event.stopPropagation(): https://api.jquery.com/event.stoppropagation/
This prevents the event from bubbling (being triggered by other elements)
Your outter most element is #overlay. It means that no matter where you click you'll be always clicking on your #overlay element. That is way your callback is being always triggered and closing your image.
To fix your problem and make your image close only when clicking on it you could use:
$('#changeImage').click(function() {
$(this).closest('#overlay').fadeOut('slow');
});
Ok, there's a ton of code to sort out, so I'm guessing your overlay is
<div id="overlay" style="display: block;"></div>
and your event.target is deep down inside this:
<div class="mainCenter">
<div class="container">
<div id="topFixed">
<input type="text" id="search" placeholder="Search">
</div>
<ul id="gallery">
.......
I'm not 100% sure where your event.target is, (the element you want to click and not everything else). But it's safe to assume that after you click your intended button, the event continues to bubble up the event chain. The event chain is basically your event.target's ancestors which includes#overlay` which is at the very top of the event chain.
To prevent event bubbling (btw bubbling is the default behavior but in instances such as your's it's not desired.) try placing stopPropagation() after or inside at the end of your event handler.
I wish I could be more specific as to where and how to apply this code as it pertains to your source, but you didn't provide the specific areas that concern your eventListeners, eventHandlers, etc...
The #overlay is used in this example but I suggest you use the event.target parent instead. The purpose of this code is to accept an event like 'click' on an element (i.e. button) or multiple elements (i.e. buttons) through their mutually shared parent. That's one place to click for potentially several different buttons. At first you'd think that's non-sense and you'd say, "Sure that button is clicked because the parent was clicked, but now everything the parent is chained to will trigger everything else."
That would be correct except we have stopPropagation(); at the very end of your eventHandler. That will stop propagation of the event bubbling back up the event chain, so there's no more rogue triggers lighting up everywhere. Rogue Triggers® sounds like a great band name. :P
For details and a much better explanation: http://www.kirupa.com/html5/handling_events_for_many_elements.htm
var overlay = document.querySelector("#overlay");
theParent.addEventListener("click", doSomething, false);
function doSomething(e) {
if (e.target !== e.currentTarget) {
var clickedItem = e.target.id;
alert("Hello " + clickedItem);
}
e.stopPropagation();
}
As JQuery document says, I have converted many lines mouseover to mouseenter because it does not fire more than once.
http://api.jquery.com/mouseover/
mouseover fires when the pointer moves into the child element as well
mouseenter fires only when the pointer moves into the bound element.
Even hover event works as mouseenter and mouseleave, not as mouseover and mouseout.
It makes me wonder why there is mouseover event if mouseenter can do it all.
For me, mouseover gets fired unpredictably when you move mouse around on an element. It seems really dependent on the depth of child elements.
Is there a good use-case of mouseover and mouseout, which needs to fire multiple times?
That I know of, there is no use case for mouseover/mouseout at all. The only reason they exist is because these events are triggered by browsers because they are in the standard DOM event list. mouseenter and mouseleave are not standard events, but they are jQuery-specific constructs.
I suppose a use case would be if you wanted the event to trigger when moving the mouse over and out of the children of the element that the events are bound to. I can't think of anything specific, but at least this functionality is available. If only mouseenter/mouseleave existed, you wouldn't have a choice in the matter.
From http://code.jquery.com/jquery-1.9.1.js:
jQuery.each({
mouseenter: "mouseover",
mouseleave: "mouseout"
}, function( orig, fix ) {
/* content snipped */
Speculation: the reason why the creators of jQuery created the mouseenter and mouseleave non-standard events is because their behavior works as you would expect the mouseover/mouseout events to work (i.e. without regard for descendants).
Because the event contains coordinates of cursor.
So if you need to track mouse coordinates under the target, you have to use 'mouseover'
When the mouse hovers into the inner element, the mouseOut event for the outer element is fired first, then the mouseOver element for inner element is fired, then the mouseOver element for the inner element is fired last.
Why does this happen? Because the inner element technically is still inside of the outer element, so the mouse doesn't leave the outer element when it moves into the inner element. Is there a way to prevent that?
Full example here: http://jsfiddle.net/pMCeu/4/
To avoid this you should use mouseenter and mouseleave instead of mouseover and mouseout.
It is due to event bubbling. take a look at this post for a little more info.
Hi the solution above is correct and complete.
but you can also use mousemove event
Hi:
when I add a mouseout event to a parent element,it seems that all of its child are added this event also,it works well if the event is a mouse click and etc.
However for the mouseout event,this will cause some unexpected result.
Take a look at this example:
<html>
<head>
<script type="text/javascript">
function init(){
document.getElementById('par').onmouseout=function(){alert('mouse out')};
}
</script>
</head>
<body onload='init()'>
<div id="par" style="width:400px;height:300px">
<div style="background-color:red;width:100%;height:150px"></div>
<div style="background-color:black;width:100%;height:150px"></div>
</div>
</body>
</html>
please Move from the red div to the black div,then move out of the black div,then you will get two alert window,I just want one.
So how to fix it?
That's not possible using plain javascript without the mouseleave event, which, to my knowledge, is only supported by Internet Explorer.
Javascript toolkits may provide a solution, jQuery for instance emulates that event:
The mouseleave event differs from
mouseout in the way it handles event
bubbling. If mouseout were used in
this example, then when the mouse
pointer moved out of the Inner
element, the handler would be
triggered. This is usually undesirable
behavior. The mouseleave event, on
the other hand, only triggers its
handler when the mouse leaves the
element it is bound to, not a
descendant. So in this example, the
handler is triggered when the mouse
leaves the Outer element, but not the
Inner element.