jQuery event handling / propagation / bubbling? - javascript

I'm trying to create a menu for a website, I'm using jQuery for this and I've run into a little problem.
I have this structure
<div class="menuTitle menuDiv menuNode" id="menuNode_<?=$row_menu["id"]?>">
<a href="<?=$rt?>" class="menuAnchor" onclick="return registerMenuClick($(this).parent())">
<span><?=$nodeName?></span>
</a>
</div>
<div class="menuSelect" id="menuSelect_<?=$row_menu["id"]?>" align="center"><?=$nodeName?></div>
And in jQuery, I have
$(document).ready(function(){
$(".menuNode, .menuSelect").live("mouseover",function(event){
MenuBar.selectedID = $(this).attr("id").replace("menuNode_","").replace("menuSelect_","");
MenuBar.showThisBranch();
}).live("mouseout",function(event){
MenuBar.selectedID = $(this).attr("id").replace("menuNode_","").replace("menuSelect_","");
MenuBar.hideThisBranch();
});
})
When the user hovers over menuNode, the menuSelect should be shown (that, it does), but if I hover over menuAnchor, or the span, it fires the mouseout event, and then the mouseover event.
So, if say, I had the mouse over menuNode, and the move over to the span and then out to menuNode again, it would fire the mouseover event 3 times. I've had this behavior before on a click event, but it seems the method used to resolve this does not work on this problem.
Any suggestions?

As #Beetroot-Beetroot suggested, mouseenter/mouseleave helped, coupled with a TimeOut to change from the menuNode to the menuSelect (300 miliseconds on enter, 500 on leave).

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

onClick event doesn't fire if you move mouse

I have a simple button like this:
<a class="button" href="javascript:void(0);" onclick="submitActivity();">Add</a>
I also tried with:
<a class="button" href="javascript:submitActivity();">Add</a>
In both cases, it doesn't register the click if the mouse has moved a certain amount of pixels between mousedown and mouseup. This can lead users to believe they have submitted the info when they didn't
This is happening in Chrome. Haven't tested other browsers.
I want the event to fire regardless of where in the button you click and release.
Edit: The same thing is happening in Firefox, but visually it looks like I'm dragging the link. This way it at least makes sense to the user that it doesn't submit, but in Chrome there are no such visual indicator of what is happening.
A click is defined as "holding down the mouse button, and then letting go of the mouse button." It is a combination of a mouse down and mouse up event executed on the same element. If the user moves away from the element, they are no longer executing a click, simply a mousedown (and also a mouseout, and then a mouseup on a different element).
This is standard, intuitive behavior. Users don't expect their click to "matter" unless they let go of the mouse without moving.
If for your application it is really important than ANY click result in this submit happening for you, then don't go with an onclick, go with onmousedown.
<a class="button" href="javascript:void(0);" onmousedown="submitActivity();">Add</a>
EDIT: Misunderstood your problem. Perhaps this syntax that I am used to will work for you will work for you:
<INPUT type="button" value="Add" name="add_button" onClick="submitActivity()">
Solution was to do a preventDefault() on onmousedown.
$(".button").mousedown(function(event){
event.preventDefault();
return false;
});
Demo fiddle
<a class="button" href="javascript:void(0);" onMouseDown="submitActivity();">Add</a>
I stumbled upon the same problem but in another context. I created custom buttons using divs with onclick="..." and placing child divs into them for the button text and icon. When moving the cursor even one pixel over a child div between mousedown and mouseup, the parent div generated a mouseout event which prevented the click event to be fired. I could not find a way to disable the mouseout event, but found a simple CSS-solution to this problem. Just disable pointer-events for all children:
.buttondiv * {
pointer-events: none; /* prevent click problems in buttons containing child divs */
}

How can I create an exception for a jquery mouseout event only if another mouseover event hasn't been triggered?

Basically my client wants hidden navigation to appear when mouseover an image. I've solved the problem of the navigation not hiding when you mouseover the navigation and then hiding when you leave the navigation. There are two problems I'm running into and I've tried a variety of different combinations that I thought would work, but of course didn't. The two problems are:
When you mouseout the image without mouseover the navigation then the navigation needs to hide, as of right now it stays open until you either mouseover the image again or mouseleave the navigation.
Second problem is when you mouseleave the navigation directly to mouseover the image it loops the function and hides the nav then opens the nav again, I've tried changing slideToggle to show, but that causes a whole bunch of other issues.
Right now the code is behaving as close to how I want it and could be considered acceptable, but I'd love to know how to solve the problems above. I thought about using the hoverIntent plugin to sense the mouse movements and only trigger the functions once the mouse has slowed, but couldn't get it working properly. Clearly, I am a novice when it comes to javascript and jquery so please forgive me, but I'd really appreciate any help.
Here is my code
$(document).ready(function(){
$(".nav-body").hide();
$(".nav-head").mouseover(function(){
$(this).next(".nav-body").slideToggle(600);
$(".nav-body").mouseleave(function(){
$(this).hide(700);
});
});
});
Here is my html:
<p class="nav-head"><img src="/images/face-btn.jpg" /></p>
<div class="nav-body">
<ul><?php wp_list_pages('title_li=&child_of=12&depth=1'); ?></ul>
</div>
Markup change
<div class="nav-container">
<p class="nav-head"></p>
<div class="nav-body"></div>
</div>
Javascript
var eventHandler;
eventHandler = function(){$(".nav-head").one("mouseover",function(){
$(this).next(".nav-body").slideToggle(600);
$(".nav-container").one("mouseleave", function(){
$(this).find(".nav-body").hide(700, eventHandler);
});
});};
eventHandler();
The first change is from mouseleave to mouseout. Inside the navigation, there are likely to be descendent elements that cover the actual nav-body. With mouse leave, the handler only triggers when the mouse leaves the bound element. If it goes over descend it elements, it is considered leaving. Mouseout only triggers if it is outside the bounds of the bound object.
The second thing I did was assign a delegate to the handler binding operation so that I could use it as a callback function for hide(). This way, the event handler won't be restored to the nav-head until the hide is completely done.
The last was to assign the mouseout handler to the containing div. This way, the so long as it leaves the nav-head (or the nav-body) since its contained, the body will hide.

jQuery trigger mouseout event

Is it possible to trigger a mouseout event on a link element using jQuery ?
I.e. Something of the sort
$(linkEle).mouseout()
I want this to work on an iPad, which even though does not have any mouse cursor, does actually have the event...
Yes, jquery has a mouseout event handler - http://api.jquery.com/mouseout/
$('some_selector_here').mouseout(function() {
// Do some stuff
}
$('some_selector_here').trigger('mouseout');
You might be able to use:
.trigger('mouseleave');
In the form of:
$('#elementToTriggerMouseLeaveOn').trigger('mouseleave');
References:
trigger().
I don't know about the ipad, but it works as you posted. http://jsfiddle.net/tESUc/
$(linkEle).mouseout();
or
$(linkEle).trigger('mouseout');
or
$(linkEle).trigger($.Event('mouseout'));
Try with tap event
tap - triggered after a tapping an pnscreen element.
http://www.roccles.com/?p=134
$('.link').live('tap',function(event) {
//TODO
});
mouse hover state does not exist on touchscreens
Mouse over/out events do not work as required on ipad. Take a look at touchstart/touchmove and touchend events which are specially for touch devices.
Something like this http://jsfiddle.net/hTYKQ/ Will work in ipad but in this fashion:
1st click to the element triggers the mouseenter function.
2nd click triggers stuff.. if it has stuff... like a link (
http://jsfiddle.net/qxM33/1/ i screwed the <a> href but you get
the point.)
Click outside the element triggers the mouseleave function.
What this story teaches is: jquery mouse over and mouse out functions work much like click functions in ipad.

How to stop toggle event from being fired multiple times on mouseenter/mouseleave?

I'm using jQuery to toggle the visibility of a <div> using the jQuery toggle method. The toggle is fired on the mouseenter and mouseleave event, thus creating the effect of the div to fold out on mouseenter and fold in on mouseleave. Problem is, if the user drags the mouse over the <div> a few times and then leaves the <div>, the div will toggle in and out several times. This can happen if the user accidentally moves around the mouse pointer in the <div> are. Do anyone have any idea on how I can avoid this behavior?
Thanx!
Two things:
If you're going to use both mouseenter and mouseleave I'd suggest using the hover() function; and
When using triggered animations it's a good habit to get into to use the stop() method.
So:
$("div.someclass").hover(function() {
$("...").stop().fadeIn("slow");
}, function() {
$("...").stop().fadeOut("slow");
});
Note: replace "..." with the appropriate selector for what you're toggling and use the appropriate effect (I'm using fade here). Also, this in an event handler refers to the source of the event.
You can use the more common mouseover/mouseout events to get a hover event that doesn't fire on internal mouse movements.
But don't use toggle on a mouse event, it can easily go wrong if eg. the mouse is over the element at page load time, or the mouse leaves the browser (which can allow the mouse to leave the bounds of the element without firing a mouseout). Have separate function for over which shows the content, and out which hides it.
Better: just use the hover() method which is meant for exactly this purpose.
Aside from the correct answer by Cletus, i'd like to point out that using mouseenter and mouseleave events is not wrong. The trick only resides into the stop() method, in fact we could still do:
$("div.someclass").on("mouseenter", function() {
$("...").stop().fadeIn("slow");
});
$("div.someclass").on("mouseleave", function() {
$("...").stop().fadeOut("slow");
});
Here is a jsFiddle example :)

Categories