I have an element with some child elements. When the mouse leaves the parent element I want to hide the parent and it's children. Problem I'm having is that when I hover over any of the children, the mouseout event is being fired. What's the best way to prevent this? I really only want the event to fire when the mouse is not within the parent or any of it's children.
The event is bubbling up from the child to the parent (where it is being caught)
You should catch the event on the children by adding a listener and making the propagation stop there.
This code will stop the event from bubbling up to the parents handler
function onMouseLeave(e)
{
if (!e) var e = window.event;
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
}
question: The mouse off event is fired by the parent, when it should not. Mouseing over the child should not trigger a mouse off from the parent. How can we stop this?
You only need a mouseout handler attached to the parent element. But...
You need to check that the parent is actually the target of the mouseout event, as opposed to the event bubbling up from one of the children. Check event.target (W3C) and event.srcElement (IE).
You also need to check that the element that the mouse will be entering is not a descendant of the parent. Check event.relatedTarget (W3C) and event.toElement (IE).
From http://api.jquery.com/mouseover/:
mouseover fires when the pointer moves into the child element as well, while mouseenter fires only when the pointer moves into the bound element.
and the same goes for mouseout vs mouseleave
Related
Question:
I have a container with a bound (wheel) event listener containing some headings and paragraphs just for demo purposes. When I use the mouse wheel to scroll, the scroll event is occurring on one of the inner elements rather than on the container having the bound event.
Why is an event firing on a child element of a container rather than on the bound element itself?
Background:
I am playing around with angular on StackBlitz and wanted to implement an event listener on a <div> container to handle the scroll event:
<div class="inner no-scroll" (wheel)="blockScroll($event)">
In my app.component.ts I created the event handler to be called:
blockScroll(e) {
console.log(e);
if (e.target !== e.currentTarget) {
return;
}
let eO = e; // e.originalEvent;
var delta = eO.deltaY || -eO.detail;
e.target.scrollTop += delta * 30;
e.stopPropagation();
e.preventDefault();
}
In Firefox Developer Tools I see that the event is properly bound to the <div>:
Now when I use the mouse wheel over the container I see that in nearly all cases the event target is not the bound <div> but rather a <h3> or <p> element inside of the container. I wonder why the wrong element is triggering the scroll event?
This is the expected behavior.
target - element that triggered event (element directly under the mouse pointer at the beginning of the scroll)
currentTarget - element that listens to event (the div element in this case)
So if you were to point at the top of the container and begin scrolling, both target and currentTarget would point to the same div element. But once it's scrolled past the top of the container, the elements directly beneath the mouse pointer would be the <p> or <h3> elements.
I am using BS4 accordion with nesting each other.
I have faced event bubbling with parent to child and child to parent both I have solved one that is from child to parent using the event.stopPropagation() but event bubbling from parent to child is not stopped why?
Here is the code
$('.card > .collapse').on('shown.bs.collapse', function(e){
e.preventDefault();
e.stopPropagation();
$(this).parent().find(".flaticon-down-arrow").removeClass("flaticon-down-arrow").addClass("flaticon-right-arrow");
}).on('hidden.bs.collapse', function(e){
e.preventDefault();
e.stopPropagation();
$(this).parent().find(".flaticon-right-arrow").removeClass("flaticon-right-arrow").addClass("flaticon-down-arrow");
})
Here is my codepen link
Note: - Inspect to the changes of classes
Event bubbling only goes up the DOM tree (from child to parent, to grandparent, etc). It does not go down the DOM tree. Thus, any event on the parent will never bubble to its children.
The documentation states that during event bubbling (for a click event):
The browser checks to see if the element that was actually clicked on has an onclick event handler registered on it in the bubbling phase, and runs it if so.
Then it moves on to the next immediate ancestor element and does the same thing, then the next one, and so on until it reaches the element.
I added a transitionend event listener to a div. This div has children who have transition on some elements. I want the transitionend event to only fire for the element I added it for, is this a bug? or expected behavior? How to make it fire only if its the one i added the listener to?
Events are bubbling by default,
meaning that they will be "transmitted" to the parent element until they hit the body or a handler that will stop them.
You can either :
Filter by the event's target being sure it's the element you're targetting.
Listening to the event on children and event.stopPropagation() on them. That way, they won't bubble through the parent anymore.
If you'd show us some code, it would be easier to help you, depending on your current implementation.
This process is called as Event Bubbling.The thing you can do is either detect the bubbling using the event handler or prevent the bubbling by stopping the propogation. You can do this by
event.stopPropagation()
In IE beofore 9.
You can do it as
window.event.cancelBubble = true;
Please have a detailed look here
Structure:
.parent (has if/else to toggle on click) -> .child (has nothing)
<div class="parent">Parent
<div class="child">Child</div>
</div>
The parent element is styled to hide overflowing content and toggle its height on click. When the user clicks, the parent element will expand to show the child element. I want users to be able to click on the child element without the parent element toggling back to its original size and hiding the child element. I want the toggle to only happen on the parent.
I realize the child element is still contained within the parent element's clickable area, but is there a way to exclude it?
Solution 1: Compare target with currentTarget:
$("#parentEle").click( function(e) {
if(e.target == e.currentTarget) {
alert('parent ele clicked');
} else {
//you could exclude this else block to have it do nothing within this listener
alert('child ele clicked');
}
});
Fiddle
e.target will be the element that started the event.
e.currentTarget will be where it currently is (bubbling up) which will be parentEle in this click event as that's what this is listening for.
If they are the same, you know the click was directly on the parent.
Solution 2: Stop the propagation before the event hits the parentEle:
The other option is to prevent the event from bubbling up in the first place if there is a click on a child element. That can be done like this:
$("#parentEle").click( function(e) {
alert('parent ele clicked');
});
$("#parentEle").children().click( function(e) {
//this prevent the event from bubbling to any event higher than the direct children
e.stopPropagation();
});
Fiddle
The main difference between the two is that the first solution will just ignore the event in this listener and allow it to keep bubbling up. This may be necessary if you have a parent of this parentEle that needs to get the event.
The second solution stops any click events from bubbling past parentEle's direct children. So if there was a click event on a parent of parentEle, they would never see these events either.
Use event.stopPropagation();:
$('#a').add('#b').click(fun1);
function handler(event) {
event.stopPropagation();
// now do your stuff
}
If i perform mouse down on element A and release the mouse when i am on element B, neither of the elements receive the mouseUp event.
Is it possible that one of them will receive the event (it does not matter to me which of the two)?
Neither of the elements receive the mouseup event in the case of what you described because you attached an event listener of event type mouseup to element A. I would conclude that particular mouseup event listener will not fire if you release the mouse button while hovering over anything not contained within element A.