views:

1046

answers:

7

Hi,

I want to be able to detect when the mouse leaves the window so I can stop events from firing while the user's mouse is elsewhere.

Any ideas of how to do this?

A: 

I haven't tested this, but my instinct would be to do an OnMouseOut function call on the body tag.

Ender
A: 

This could be very ugly due to event bubbling.

Zack
A: 

Maybe if you're constantly listening to OnMouseOver in the body tag, then callback when the event is not ocurring, but, as Zack states, this could be very ugly, because not all the browsers handle events the same way, there is even some possibility that you lose the MouseOver even by being over a div in the same page.

ONi
A: 

You cant find out when the mouse leaves the window for one simple reason. The mouse coordinates in javascript record the last known coordinates of the cursor. So lets say the cursor is at 0,0 and you move it out of the window. The coordinates dont change to -42,-12 or something It still stays at 0,0 because its the last recorded coordinate

Ozzy
A: 

I take back what i said. It is possible. I wrote this code, works perfectly.

window.onload = function() {

    $span = document.getElementById('text');

    window.onmouseout = function() {
     $span.innerHTML = "mouse out"; 
    }

    window.onmousemove = function() {
     $span.innerHTML = "mouse in"; 
    }

}

works in chrome, firefox, opera. Aint tested in IE but assume it works.

edit. IE as always causes trouble. To make it work in IE, replace the events from window to document:

window.onload = function() {

    $span = document.getElementById('text');

    document.onmousemove = function() {
     $span.innerHTML = "mouse move";
    }

    document.onmouseout = function() {
     $span.innerHTML = "mouse out";
    }

}

combine them for crossbrowser kick ass cursor detection o0 :P

Ozzy
Have you tested how well this works together with elements on the page? I would think that elements that have their own 'onmouseover/out' events could potentially cancel bubbling and break this functionality.
Dan Herbert
Yes, it works fine with and without elements on the page.
Ozzy
Ozzy, Dan is trying to explain that an element that stops event propagation will prevent the event from reaching the document/window, thereby rendering your solution ineffective.
J-P
I just tested it with other elements with their own onmousemove and onmouseout events and it still works fine.
Ozzy
Yes okay, but again we're talking about event propagation. If you purposefully stop event propagation with EVENT.stopPropagation() (for IE, EVENT.cancelBubble=true) then it won't bubble up to the document/window... To counteract this you could use event capturing in browsers that support it.
J-P
Remember that in JS to declare a variable, you must use 'var'. Now the variable $span is an implicit global, which is probably not what you want. Also in case it isn't intentional, you don't need a $ in variable names.
Jani Hartikainen
A: 

Have been trying to accomplish the same thing myself... so far the most logical (to me) idea was to try window.addEventListener('mouseout', mylistenerfn, false). According to DOM specs you should be able to attach a mouseout listener to the window object. This negates the need to check coordinates from mousemove events. This partially works. The event does fire if you leave the window. However it also fires every time you mouseover an image or iframe, or move from one img to another, if they are layered. Perhaps I don't understand capturing and bubbling enough? Need to move event to capture phase? I tried that, same results... any ideas?

+3  A: 

Greetings, I'm not sure if anyone is still interested in a solution to this problem. This type of behavior is usually desired while implementing drag-drop behavior on an html page. The solution below was tested on IE 8.0.6, FireFox 3.6.6, Opera 10.53, and Safari 4 on an MS Windows XP machine.
First a little function from Peter-Paul Koch; cross browser event handler:

function addEvent(obj, evt, fn) {
    if (obj.addEventListener) {
        obj.addEventListener(evt, fn, false);
    }
    else if (obj.attachEvent) {
        obj.attachEvent("on" + evt, fn);
    }
}

And then use this method to attach an event handler to the document objects mouseout event:

addEvent(document, "mouseout", function(e) {
    e = e ? e : window.event;
    var from = e.relatedTarget || e.toElement;
    if (!from || from.nodeName == "HTML") {
        // stop your drag event here
        // for now we can just use an alert
        alert("left window");
    }
});

Finally, here is an html page with the script embedded for debugging:

<html>
<head>
<script type="text/javascript">
function addEvent(obj, evt, fn) {
    if (obj.addEventListener) {
        obj.addEventListener(evt, fn, false);
    }
    else if (obj.attachEvent) {
        obj.attachEvent("on" + evt, fn);
    }
}
addEvent(window,"load",function(e) {
    addEvent(document, "mouseout", function(e) {
        e = e ? e : window.event;
        var from = e.relatedTarget || e.toElement;
        if (!from || from.nodeName == "HTML") {
            // stop your drag event here
            // for now we can just use an alert
            alert("left window");
        }
    });
});
</script>
</head>
<body></body>
</html>

Enjoy!

chickenSandwich

chickenSandwich
Using window.event fixed my problem getting this event. Thanks!
Jay