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

StackOverflow https://stackoverflow.com/questions/1672142

Вопрос

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

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

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

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

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

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

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

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

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

Это было полезно?

Решение

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

Подробные сведения:

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

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

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

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

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

Дурот отметил в комментариях, что MooTools уже включает в себя нечто подобное.(Спасибо Duroth.) Похоже, что предстоящий выпуск Prototype (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 срабатывает при перемещении входящих / исходящих элементов внутри корпуса.Если это находится в пределах окна, mouseout событие не запускается.
Также введен флаг для текущего состояния мыши "включено" или "выключено" с использованием mouseIsIn.Если это так true, mouseover тоже не сработает.

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

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

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

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

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

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

Ваша проблема связана с событиями наведения курсора мыши, генерируемыми для элементов внутри окно, которое затем всплывает, как описано в Спецификация событий 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 событие в окне вместо этого

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top