13

Let's suppose I have two spearate divs, A and B, which overlap at a corner:

+-----+
|     |
|  A  |
|   +-----+
+---|     |
    |  B  |
    |     |
    +-----+

I want to trigger an event when the mouse leaves both A and B.

I tried this

$("#a, #b").mouseleave(function() { ... });

But this triggers the event if the mouse leaves either node. I want the event to be triggered once the mouse is not over either node.

Is there an easy way to do this? I had an idea that involved global variables keeping track of the mouse state over each div, but I was hoping for something more elegant.

beatnik
  • 226
  • 1
  • 14
Peter Olson
  • 139,199
  • 49
  • 202
  • 242
  • 1
    I've seen this before. I think you can calculate the *combined* coordinates using `.offset()` for each `#a, #b`, and when the mouse position is no longer over the combined coordinates, [`$('#a, #b').trigger('mouseleave'); `](http://api.jquery.com/trigger/). – Jared Farrish Dec 19 '11 at 05:41
  • @JarredFarrish That sounds even worse that the solution I had in mind. Keeping track of the offset of the cursor can be pretty unwieldy. – Peter Olson Dec 19 '11 at 06:12

3 Answers3

20

I encounter this problem all the time, and my 'quick fix' if it fits what I'm doing is the following;

var timer;

$("#a, #b").mouseleave(function() {
    timer = setTimeout(doSomething, 10);
}).mouseenter(function() {
    clearTimeout(timer);
});


function doSomething() {
    alert('mouse left');
}

Fiddle : http://jsfiddle.net/adeneo/LdDBn/

adeneo
  • 312,895
  • 29
  • 395
  • 388
  • +2.5 That's pretty slick! I like how you only need one global variable and the process doesn't require as much finagling as the more obvious solutions. – Peter Olson Dec 19 '11 at 06:00
  • If you can position one of the elements absolutely, there is no need for a hack like this. See [here](http://stackoverflow.com/a/17604616/446921). – Muhd Jul 11 '13 at 22:31
  • @muhd - position absolute has nothing to do with it, that's event propagation, which happens when you nest elements like that, but the answer was meant as an alternative to nesting, as that's not always possible. – adeneo Jul 11 '13 at 23:02
  • Your quick fix seems to much quick solutions for me :) – Just code Jun 02 '14 at 10:22
3

If you nest the second container inside the first there is no need for a complex jQuery solution:

http://jsfiddle.net/5cKSf/3/

HTML

<div class="a">
    This is the A div
    <div class="b">
        This is the B div
    </div>
</div>

CSS

.a {
    background-color: red;
    width: 100px;
    height: 100px;
    position: relative;
}

.b {
    background-color: blue;
    width: 100px;
    height: 100px;
    position:absolute;
    top: 50px;
    left: 50px;
}

JS

$('.a').hover(function() {
   alert('mouseenter'); 
}, function() {
   alert('mouseleave');
});
Muhd
  • 24,305
  • 22
  • 61
  • 78
0

I guess you can achieve this using something like:

var mouseLeftD1 = false;
var mouseLeftD2 = false;

$('#d1').mouseleave(function() {
  mouseLeftD1 = true;
  if(mouseLeftD2 == true) setTimeout(mouseLeftBoth, 10);
}).mouseenter(function() {
  mouseLeftD1 = false;
});

$('#d2').mouseleave(function() {
  mouseLeftD2 = true;
  if(mouseLeftD1 == true) setTimeout(mouseLeftBoth, 10);
}).mouseenter(function() {
  mouseLeftD2 = false;
});

function mouseLeftBoth() {
  if(mouseLeftD1 && mouseLeftD2) {
    // .. your code here ..
  }
}
techfoobar
  • 65,616
  • 14
  • 114
  • 135