2009-11-04 28 views
11

Me gustaría que se ejecute algún código de JavaScript cuando el mouse sale de la ventana del navegador. Solo necesito admitir Safari (WebKit).Evento de Javascript cuando el mouse sale de la ventana del navegador

Intenté poner un manejador de mouseout en la ventana. Ese controlador se llama confiablemente cuando el mouse sale de la ventana del navegador. Pero debido al burbujeo, también se llama cuando el mouse se mueve entre los elementos del documento. No puedo encontrar la manera de determinar cuándo el mouse realmente salió de la ventana y cuándo solo se movió entre los elementos.

Cuando el mouse sale de la ventana, se genera exactamente un evento, y el elemento de destino parece ser el elemento en el que el mouse realmente se había terminado. Entonces, verificar si el elemento objetivo es ventana o documento no funciona. Y envolver toda la página en un div que contiene invisible tampoco funciona: si el div es invisible, entonces el mouse nunca lo superará, por lo que nada cambia.

(Lo mismo sucede si pongo el controlador en document o document.body, excepto que document.body no obtiene los eventos mouseover/mouseout cuando el mouse entra o deja una parte vacía de la ventana, como espacio vertical vacío creado por la colocación de un elemento absolutamente con la parte inferior:.. 0 Para ese espacio, y la ventana de documento obtendrán eventos mouseover/mouseout con el objetivo de ser <html>, pero no lo hará document.body)

Algunas ideas que tenía:

  • En cada evento mouseout, obtenga la posición real del mouse y ver si de hecho está sobre la ventana. Pero no sé si esto es realmente posible y parece que sería complicado eliminar todas las condiciones de carrera.
  • También registre un manejador de mouseover y detecte los casos en que mouseout no es procesado por (o seguido de a) un mouseover. Pero eso requeriría un temporizador.

Utilizamos prototype.js, así que idealmente me gustaría expresar la solución en términos de Event.observe del prototipo, pero puedo descifrar esa parte.

¡Gracias por cualquier sugerencia!

+0

MooTools ofrece los eventos personalizados MouseEnter/MouseLeave (http://demos.mootools.net/Mouseenter). No conozco Prototype, pero ¿no ofrece algo similar? – Duroth

+0

@Duroth Gracias por el puntero. El prototipo 1.6.1 no parece, pero parece 1.6.2 mayo. – Geoff

Respuesta

12

RESUMEN: Esto puede hacerse limpiamente comprobando la propiedad relatedTarget durante el evento mouseout. Si relatedTarget no es un elemento secundario del documento, entonces el mouse acaba de salir de la ventana. Es fácil hacerlo usted mismo, pero si no lo desea, algunas bibliotecas (Mootools, future Prototype ..) tienen funcionalidad integrada, y otras (Prototype actual) tienen extensiones disponibles. En IE, podría usar mouseleave, que es una versión no burbujeante de mouseout.

Detalles:

IE tiene eventos llamados MouseEnter y mouseleave que son versiones que no son burbujeantes de pasar el ratón y mouseout. Otros navegadores no lo hacen, pero si lo hicieran, configurar un mouse para dejar de escuchar en la ventana o en el documento haría el truco.

Un caballero llamado Ken Snyder llega al rescate:

En un mouseover, los relatedTarget referencias de propiedades del nodo desde el que llegaron el puntero. En un mouseout, las referencias de propiedades relatedTarget el nodo al que el puntero went.On cualquier caso, el ámbito es el nodo a cual el evento se attached.When la relatedTarget es un niño, no del currentTarget, una el evento mouseover es equivalente a un evento mouseenter y un evento mouseout es equivalente a un evento mouseleave .

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

Esto hace que sea posible implementar MouseEnter y MouseLeave en otros navegadores. De hecho, Ken proporciona el mismo código de prototipo para hacerlo: http://kendsnyder.com/sandbox/enterleave/MouseEnterLeave.js

Duroth señaló en comentarios que MooTools ya incluye algo similar. (Gracias Duroth). Parece que el próximo lanzamiento de Prototype (1.6.2) puede incluir esta funcionalidad, pero no puedo encontrar nada definitivo.

+1

Actualización: parece que ahora está presente en FF 10+, Chrome 30+ y Opera, junto con IE - https://developer.mozilla.org/en-US/docs/Web/Events/mouseleave – snappieT

-1

Puede utilizar onmouseout evento en una ventana en lugar

+0

Esto es en realidad lo que probé (lo siento, no estaba claro. He editado la pregunta para aclarar). ¿Cómo puedo distinguir el caso donde el mouse ha salido de la ventana del caso donde el mouse solo se movió entre los elementos, y el controlador se llama debido a burbujeo? – Geoff

9

El uso de JavaScript, ningún prototipo o jQuery etc.

<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> 

ACTUALIZACIÓN:
cheque Agregado para la posición del ratón en mouseout desencadenado cuando se mueve elementos de entrada/salida dentro del cuerpo. Si está dentro de la ventana, el evento mouseout no se desencadena.
También se introdujo un indicador para el estado actual del mouse 'in' o 'out' usando mouseIsIn. Si es true, mouseover tampoco se disparará.

+0

Esto parece funcionar, pero en realidad no es así. Ambos manejadores son llamados cada vez que el mouse se mueve sobre el recuadro rojo ("Dummy element"). Es solo que el mouseout (¿le pasa?) Se llama en último lugar, por lo que no se da cuenta. Puede ver esto manteniendo un contador de la cantidad total de veces que se ha llamado al controlador e imprimiéndolo además de 'in' o 'out'. O mediante el uso de console.log(). – Geoff

+0

@Geoff: Ya ​​veo, gracias por señalar. Déjame ver qué más puedo hacer ... –

+0

@Geoff: Implementé una lógica adicional para la posición del mouse en 'mouseout'. Si está dentro de la ventana, ignóralo. Esto evitará el disparo no deseado. Lo probé en Safari, parece funcionar. –

1

Quizás pueda configurar un detector para mouseover y mouseout document, body o algún otro elemento que envuelva todo el documento, y use eso (guardándolo como desencadenante) para determinar si es un mouseout válido en la ventana ?

De lo contrario, su primera idea (con respecto al control de posición) debería funcionar bastante bien. Cualquier evento pasa a lo largo de la X/Y el evento ocurrió. Si es algo más que el alto/ancho de la ventana, saliste de la ventana real.Si es algo negativo, dejaste la ventana. Y, posiblemente, si es exactamente el alto/ancho o exactamente superior: 0 o izquierda: 0, entonces salió de la ventana.

0

Su problema proviene de los eventos de mouseout que se generan para los elementos dentro de la ventana, que luego brotan como se describe en el W3C events spec. Puede comprobar qué elemento del evento fue realmente disparó en:

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

Ese código encontrará el remitente del evento, pero ¿cómo puedo usar esa información para determinar si el mouse ha salido de la ventana? Incluso cuando el mouse sale de la ventana, el remitente no es una ventana o documento: es el elemento que contiene el más bajo, algunos < > o < > al azar según el lugar donde estaba el mouse antes de salir de la ventana. – Geoff

0

Aquí está mi solución basada en un temporizador. El temporizador aquí se utiliza básicamente para dar la oportunidad a otros manejadores de eventos (específicamente, onmouseover) de ejecutar antes de decidir que el servidor está fuera de la ventana. El tiempo de espera de 1 ms (en realidad alrededor de 33 ms, hay una resolución de temporizador mínima) da un poco de tiempo para que ocurra el mouseover si ya no lo tiene.

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) 
    } 
} 
1

Cuando el ratón sale de cualquier elemento, incluyendo la ventana, el objeto de la ventana se disparará un evento mouseout y pasar el objeto event junto con él.

Uno de los elementos en el objeto de evento se llama toElement, que es un puntero al elemento que el mouse acaba de ingresar cuando salió del anterior.Pero cuando el mouse sale de la ventana, no hay tal toElement por lo que este elemento se convierte en null.

Al probar si este elemento es null en un evento mouseout, puede ver si el mouse salió de la ventana. Aquí está el código:

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