Событие Javascript, когда мышь покидает окно браузера [дубликат]

этот вопрос уже есть ответ здесь:

Я хотел бы, чтобы некоторый код Javascript запускался, когда мышь покидает окно браузера. Мне нужно только поддерживать Safari (WebKit.)

Я попытался поместить обработчик mouseout в окно. Этот обработчик надежно вызывается, когда мышь покидает окно браузера. Но из-за пузырьков он также вызывается, когда мышь перемещается между элементами в документе. Я не могу понять, как определить, когда мышь действительно покинула окно и когда она только перемещалась между элементами.

когда мышь покидает окно, генерируется ровно одно событие, и целевой элемент кажется элементом, над которым мышь была на самом деле. Поэтому проверьте, является ли целевой элемент window или документ не работает. И обертывание всей страницы невидимым содержимым div тоже не работает: если div невидим, то мышь никогда не будет над ним, поэтому ничего не меняется.

(то же самое происходит, если я ставлю обработчик на документ или документ.тело, за исключением этого удивительного документа.body не получает события mouseover / mouseout, когда мышь входит или выходит из пустой части окна, например, пустое вертикальное пространство, созданное абсолютным позиционированием элемента с нижними:0. Для этого пространства документ и окно получат события mouseover/mouseout с целью , но документ.тело-нет.)

некоторые идеи у меня было:

  • на каждом событии mouseout, получить фактическое положение мыши и посмотреть, если это на самом деле над окном. Но я не знаю, возможно ли это на самом деле, и похоже, что было бы сложно устранить все условия гонки.
  • также зарегистрируйте обработчик наведения мыши и обнаружьте случаи, когда mouseout не продолжается (или вскоре следует) наведением мыши. Но для этого потребуется таймер.

мы используем прототип.js так идеально, что я хотел бы выразить решение с точки зрения события прототипа.наблюдать, но я могу понять эту часть.

Спасибо за любые предложения!

7 ответов


резюме: Это можно сделать чисто, проверив свойство relatedTarget во время события mouseout. Если relatedTarget не является дочерним документом, то мышь просто покинула окно. Это легко сделать самостоятельно, но если вы этого не хотите, некоторые библиотеки (Mootools, future Prototype..) имеют запеченную функциональность, а другие (текущий прототип) имеют доступные расширения. На IE, можно использовать mouseleave, которое не булькает версия mouseout.

детали:

IE имеет события, называемые mouseenter и mouseleave, которые являются не пузырящимися версиями mouseover и mouseout. Другие браузеры этого не делают, но если бы они это сделали, установка прослушивателя mouseleave в окне или документе сделала бы трюк.

джентльмен по имени Кен Снайдер приходит на помощь:

на мыши, на relatedTarget свойство ссылается на узел из на что указка и пришла. На mouseout, в relatedTarget собственность ссылок узел, на который указывал указатель.На любое событие, область является узлом для какие мероприятия прилагается.Когда relatedTarget не является ребенком currentTarget, событие mouseover эквивалентно событию mouseenter и событие mouseout эквивалентно событие mouseleave.

-- http://kendsnyder.com/archives/6-MouseEnter-and-MouseLeave.html

Это позволяет реализовать mouseenter и mouseleave в других браузерах. Фактически, Кен предоставляет тот же код прототипа для этого:http://kendsnyder.com/sandbox/enterleave/MouseEnterLeave.js

Duroth указал в комментариях, что MooTools уже включает что-то подобное. (Спасибо Duroth.) Похоже, что предстоящий выпуск прототипа (1.6.2) может включать эту функциональность, но я не могу найти ничего определенного.


используя только javascript, без прототипа или jquery и т. д.

<html>
<head>
<script type="text/javascript">
  var mouseX = 0;
  var mouseY = 0;
  var counter = 0;
var mouseIsIn = true;
function wireEvent() {
window.addEventListener("mouseout",
    function(e){
        mouseX = e.pageX;
        mouseY = e.pageY;
        if ((mouseY >= 0 && mouseY <= window.innerHeight)
        && (mouseX >= 0 && mouseX <= window.innerWidth))
            return;
        //do something for mouse out
        counter++;
        mouseIsIn = false;
        document.getElementById('in_out').innerHTML='out' + counter;
    },
    false);
window.addEventListener("mouseover",
    function(e){
        if(mouseIsIn)
            return;
        //do something for mouse over
        counter++;
        mouseIsIn = true;
        document.getElementById('in_out').innerHTML='in' + counter;
    },
    false);
}
</script> 
</head>
<body onload="wireEvent();">
<div id="in_out">&nbsp;</div>
<div style="width:300px; height: 200px; background: red;">Dummy element</div>
</body>
</html>

обновление:
Добавлена проверка положения мыши на mouseout срабатывает при перемещении элементов in/out внутри тела. Если он в окне,mouseout событие не срабатывает.
Также введен флаг для текущего состояния мыши " in " или " out " с помощью mouseIsIn. Если это true, mouseover не будет срабатывать тоже.


возможно, вы можете установить прослушиватель для события mouseover и mouseout document, body или какой-то другой элемент, который обертывает весь документ, и использует это (сохраняя, что это произошло) в качестве триггера, чтобы определить, является ли это допустимым mouseout в окне?

в противном случае ваша первая идея (относительно проверки позиции) должна работать довольно хорошо. Любое событие проходит по X / Y событие произошло. Если это что-то дальше высоты/ширины окна, вы оставили фактическое окно. Если это что-нибудь отрицательное, ты оставил окно. И, возможно, если это точно высота / ширина или точно top: 0 или left: 0, то вы покинули окно.


когда мышь покидает любой элемент, включая окно, объект window будет запускать mouseout событие и передать event объект вместе с ней.

один из элементов в объекте события называется toElement, который является указателем на элемент, который мышь только что ввела, когда она покинула Старый. Но когда мышь покидает окно, такого нет toElement таким образом, этот элемент становится null.

проверяя, является ли этот элемент null на mouseout событие, вы можно сказать, если мышь покинула окно. Вот код:

window.onmouseout=function(event){ 
  if(event.toElement===null) console.log('the mouse left the window'); 
}

ваша проблема возникает из событий mouseout, генерируемых для элементов внутри окно, которое затем пузырь вверх, как описано в спецификации событий W3C. Вы можете проверить, на каком элементе событие было фактически запущено:

function mouseoutFunction(event) {
  event = event || window.event;
  var sender = event.srcElement || event.target;
}

вот мое решение, основанное на таймере. Таймер здесь в основном используется, чтобы дать возможность другим обработчикам событий (в частности, onmouseover) выполнить, прежде чем решить, что mosue находится вне окна. Тайм-аут 1 мс (на самом деле около 33 мс, есть минимальное разрешение таймера) дает немного времени для наведения мыши, если это уже не произошло.

var inWin=0;
window.onmouseout = function(e)
{
   inWin--;
   setTimeout(checkIfOut, 1);
}
window.onmouseover = function(e)
{
   inWin++;
}

function checkIfOut()
{
   if(!inWin)
   {
     //Yay! Mouse is out of the window (probably)
   }
}

можно использовать onmouseout событие в окне вместо