jQuery triggers out event even though it should be still in - javascript

I am facing a rather awkward problem. I register two event handlers, one for mouseenter and one for mouseout for the li elements on the page. It has multiple div areas inside it. When I leave the li element it calls the out handler, which is ok. What is not ok is that the out handler is also triggered when I leave a div inside that li.
Below is an image that illustrates it. The blue area is the li element which I register an enter and out event for.
I tried to register handlers on the inner divs that would stop the propagation but it only results in the triggering of the out handler when I enter those inner divs.
Any idea what is going wrong here?

Use mouseleave instead of mouseout. Mouseout triggers everytime your mouse is going off from exactly atop of the target. So when you enter the divs, your mouse goes out of the li and on the div. But it is still inside the LI of course, using mouseleave will make it work.
From JQuery doc:
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.

Related

Is it possible for an element to only listen to click events and ignore events like mouse movement?

My problem is the following: I have a div, which has some crucial mouse events I need to fetch. These are onMouseOver to be more precise.
However, when the mouse hover over this div, I am creating a few buttons on this div, which are then leading to misbehavious of my onMouseOver event, as they are overlaying the div, and as soon as the mouse is being moved onto those buttons, it "leaves" the div and the event stops triggering.
So, I want to be able to ignore mouse movement on these buttons, but I still want to grab the click event when someone clicks the buttons, of course.
The closest I've found so far was
pointer-event: none
, but that also disables click events.
Is there something else I could use to achieve this?
Thanks in advance
You should use mouseenter and mouseleave events if using jQuery. mouseover and mouseout functions do not bubble from child to parent, so you end up triggering a mouseout event when you hover the child elements.
You can always attach onmouseover event to these buttons and put in the same function as for div.
Even if You ignores onmouseover on this buttons You will lost onmouseover on the div.
You can use preventdefault(). after that you can write your own code
$("a").click(function(e){
e.preventDefault();
//You can write other code what you want to write
});
This code may help you to get override the other code
or you may use e.stopPropagation() in stead of e.preventDefault(); it will stop all other active events

React mouse events fired on components not listening for them

Not sure if it's my profound misunderstanding of React events or an actual bug, but mouse events registered on the parents sometimes fire on the children.
In the bin below, mousing around the two divs will eventually result in the inner div getting highlighted red, even though it doesn't have an event trigger for attaching the ui-hover class (though its parent does).
http://jsbin.com/vemopo/1/edit?css,js,output
It seems to depend on how fast the mouse is moving. My guess is, event.target becomes whatever is under the mouse when the event is triggered. So it fires when entering the parent div, but if the mouse is moving quickly then it may already be hovering the child div when the event handler is processed.
(Updated answer)
As #Stan commented, replacing event.target with event.currentTarget is the simplest fix, it will target the element whose listener triggered the event rather than the element under the mouse.
(Original answer / other options)
You can also set ref="target" on the parent div and then use the ref rather than the event target.
_mouseEnter: function(event) {
this.refs.target.getDOMNode().classList.add('ui-hover');
},
However, it may be preferable to avoid touching the DOM like this. In that case you could use setState in the event handlers and use conditionals to give a different result depending on this.state.
_mouseEnter: function(event) {
this.setState({
hovering: true
});
}

jquery - perform effect on any event

i have 5 elements in a page.
i have selected them using class names $('.class')
i am trying to perform a function for those selected elements irrespective of event (click or hover or watever).
eg:
$('.class').hover(function(){definition1});
$('.class').click(function(){definition1});
i dont want to have 2 seperate event as above 2, instead i want the function to be executed irrespective of whether its hover or click event.
$('.class').bind('click mouseenter', function() {
// Go nuts.
});
(if using jQuery >= 1.7, swap bind() with on().)
Keep in mind that hover()'s second argument is for mouseleave event, which you haven't written anything for here.
If you want to cover most events, pass in 'blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error' as the first argument.
You could also try to detect them with code by iterating over properties that start with on, but it sounds too flaky to me.
To bind multiple events to one element in jQuery 1.7 and later you can do the following by separating event names by spaces:
jQuery('.class').on('click hover mousenter mouseleave', function(event){
// do what you need to do
});
which you can see in jsfiddle.
But: be careful, because you can easily fire the event too much times (more than necessary and more than enough). By binding so many events some may be called unnecessarily (as in the example above the code will be fired twice when the mouse cursor will leave the element it hovered over).
If you do not want to exec a function without any event put it in
$(function(){
function test(){definition1}
});
then in html
<body onload="test();">

jquery callback specificity

Is there any specificity associated with event callback with jQuery. Say, I register a mousedown event callback on a div element, and also on the document. Which one would trigger if I click on the div? Does the order of registration matters? or the specificity (like css) matters?
thanks.
It will bubble up the DOM tree and call all other events of that type.
You can stop this with event.stopPropagation().
Your example
If you assigned the events like so...
$(document).mousedown(function() { alert('document'); });
$('div').mousedown(function() { alert('div'); });
Mouse down anywhere will trigger document's handler, and get one alert dialog with document.
Mouse down on any div will trigger the div's handler, and then bubble up the DOM all the way to document where it will trigger its event handler. You will get two alert dialogs; first the div one and then the document one.
Both events will be triggered, first the div, and then the document click.
It will execute both, from inside out. Clicking in the div will fire the div event then the document. Example on jsFiddle
$(window.document).click(function(e){
alert("doc");
});
$("div").click(function(e){
alert("div");
});
You can avoid it firing other events with e.stopImmediatePropagation(). See this example
$(window.document).click(function(e){
alert("doc");
});
$("div").click(function(e){
alert("div");
e.stopImmediatePropagation(); // prevents $(doc) from rising
});

Javascript: Multiple mouseout events triggered

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 accomplished without complex mouse-tracking functions. In the future, I plan to reimplement 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.
The 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.

Categories