Подтвердить что ты не робот

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

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

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

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

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

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

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

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

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

4b9b3361

Ответ 1

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

Подробнее:

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

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

При наведении курсора мыши связанный с ним объект свойство ссылается на node из который указатель пришел. В режиме мыши, связанные ссылки свойств собственности node, на который указатель поместил. любое событие, область действия - nodeкоторое событие присоединено. relatedTarget не является дочерним currentTarget, событие mouseover эквивалентно событию mouseenter и событие mouseout эквивалентно событие mouseleave.

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

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

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

Ответ 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>

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

Ответ 3

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

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

Ответ 4

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

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

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

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

Ответ 5

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

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

Ответ 6

Вот мое решение, основанное на таймере. Таймер здесь в основном используется, чтобы дать возможность другим обработчикам событий (в частности, 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)
   }
}

Ответ 7

Вы можете использовать onmouseout событие вместо этого