HTML Nested Elements & OnMouseOut Event
If you are trying to track the mouse-out event, for example to hide the sub menu when user leave that area, then there are good chances there are good chances that you may stuck into a problem, where the parent element mouse-out event fires, when you move the cursor to the child.
Here is a quick demo of this:
You will notice that as soon as you move the mouse over to the child DIV, the mouse out event of the parent is fired. This is problem in most of the cases, where you want to detect the true mouse out (where the mouse is still over main Div or any of its child Div areas).
There are two possible solutions for this. First is that if you are using the JQuery, then you are good. There is already a special event in JQuery called mouseleave which does exactly what you want. All you have to do is to bind to this event instead of HTML element onmouseout event, and you are good.
However, if you are not using the JQuery, and for some reason don’t want to use it just for this fix. Then there is simple JavaScript only fix for this too (somewhat same rule is used by JQuery too). Here is the JavaScript for such mouse leave event:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | // JQuery style getElementByID wrapper $ = function(id) { return document.getElementById(id); } // Our generic code to handle the on mouse event isMouseLeave = function(event, parent) { // Get the reference to the event object if (!event) var e = window.event; // Get the target parent (extra code for cross browser compatability) e = event.toElement || event.relatedTarget; // Now keep traversing all the parents of the current target object to detect if the // object on which the mouse is being moved is child of the main parent element we are looking // for or not while (e && e.nodeName && e.nodeName != 'BODY') { // if this is a child element, ignore this on mouse out event if (e == parent) return false; // check the next parent e = e.parentNode; }; // If we are here, then this is actually the mouse out leave event, so do what you want to do return true; } // Generic event binder bindMouseOut = function(object, handler) { object.onmouseout = function(event) { // Call handler if this is mouse leave even if (isMouseLeave(event, object)) handler(); }; } |
// JQuery style getElementByID wrapper $ = function(id) { return document.getElementById(id); } // Our generic code to handle the on mouse event isMouseLeave = function(event, parent) { // Get the reference to the event object if (!event) var e = window.event; // Get the target parent (extra code for cross browser compatability) e = event.toElement || event.relatedTarget; // Now keep traversing all the parents of the current target object to detect if the // object on which the mouse is being moved is child of the main parent element we are looking // for or not while (e && e.nodeName && e.nodeName != 'BODY') { // if this is a child element, ignore this on mouse out event if (e == parent) return false; // check the next parent e = e.parentNode; }; // If we are here, then this is actually the mouse out leave event, so do what you want to do return true; } // Generic event binder bindMouseOut = function(object, handler) { object.onmouseout = function(event) { // Call handler if this is mouse leave even if (isMouseLeave(event, object)) handler(); }; }
And you can bind this mouse leave function with any HTML element using the following simple script:
1 2 3 4 5 | bindMouseOut ($('outerDiv'), function(){ showMsg('messageLog', 'Out Div Mouse Out'); }) |
bindMouseOut ($('outerDiv'), function(){ showMsg('messageLog', 'Out Div Mouse Out'); })
You can view this in action on Jfiddle:
JQuery magic revealed.
Tags: Event, JavaScript, Nested, OnMouseOut
This entry was posted
on Sunday, August 19th, 2012 at 4:18 pm and is filed under HTML & CSS, JavaScript.
You can follow any responses to this entry through the RSS 2.0 feed.
You can leave a response, or trackback from your own site.
Excellent, the one from many out there that actually works smoothly.
Thanks a lot.
Nevermind – too much trouble to post code here.
Dan,
Sorry, but can’t allow HTML in the comments mainly due to spam and security. Anyway, I got the idea you were trying to share. Good job.
This works for me:
function mouseOut(e){
var child;
var target;
var target=(e.currentTarget) ? e.currentTarget: e.srcElement;
var child=e.relatedTarget ? e.relatedTarget : e.toElement
while(child.parentElement){
if(target==child){
return false;
}
child=child.parentElement;
}
return true;
}
DIV 1
Nested DIV 2
Nested Nested DIV 3