Domanda

    

Questa domanda ha già una risposta qui:

         

Vorrei un po di codice JavaScript per funzionare quando il mouse lascia la finestra del browser. Ho solo bisogno di supportare Safari (WebKit).

Ho provato a mettere un gestore mouseout sulla finestra. Questo gestore viene chiamato in modo affidabile quando il mouse lascia la finestra del browser. Ma a causa di ribollimento Si chiama anche quando il mouse si muove tra gli elementi del documento. Io non riesco a capire come determinare quando il mouse ha effettivamente lasciato la finestra e quando si è spostato solo tra gli elementi.

Quando il mouse lascia la finestra, esattamente un evento viene generato, e l'elemento di destinazione sembra essere l'elemento con il mouse era in realtà finita. Quindi il controllo per vedere se l'elemento di destinazione è la finestra o un documento non funziona. E avvolgendo l'intera pagina in un div contenente invisibile non funziona neanche: se il div è invisibile, allora il mouse non sarà mai su di esso, quindi non cambia nulla.

(La stessa cosa accade se metto il gestore sul documento o document.body, salvo che sorprendentemente document.body non ottiene gli eventi mouseover / mouseOut quando il mouse entra o esce una parte vuota della finestra, come ad esempio il vuoto spazio verticale creato da posizionamento assoluto di un elemento con fondo:.. 0 In tale spazio, documento e finestra otterranno eventi mouseover / mouseOut con l'obiettivo di essere , ma document.body non)

Alcune idee che ho avuto:

  • In ogni caso mouseout, ottenere la posizione attuale del mouse e vedere se è in realtà sopra la finestra. Ma io non so se questo sia effettivamente possibile e suona come sarebbe difficile da eliminare tutte le condizioni di gara.
  • registrare anche un gestore di passaggio del mouse e rilevare i casi in cui mouseout non è preceduto da (o seguito a breve da a) un passaggio del mouse. Ma ciò richiederebbe un timer.

Usiamo prototype.js così idealmente vorrei esprimere la soluzione in termini di Event.observe di prototipo, ma posso capire che una parte fuori.

Grazie per eventuali suggerimenti!

È stato utile?

Soluzione

SINTESI: Questo può essere fatto in modo pulito controllando la proprietà relatedTarget durante l'evento mouseout. Se relatedTarget non è un bambino di documento, quindi il mouse appena lasciato la finestra. E 'facile da fare da soli, ma se non si vuole, alcune librerie (Mootools, Prototype futuro ..) hanno sfornato la funzionalità, e altri (prototipo attuale) hanno estensioni disponibili. Su IE, si potrebbe utilizzare invece mouseLeave, che è una versione non spumeggiante di mouseout.

dettagli:

IE ha chiamati eventi MouseEnter e mouseLeave che sono versioni non ribollimento di mouseover e mouseout. Altri browser non lo fanno, ma se lo facessero, la fissazione di un ascoltatore mouseLeave sulla finestra o di un documento farebbe il trucco.

Un signore di nome Ken Snyder viene in soccorso:

  

In un passaggio del mouse, il relatedTarget   Proprietà riferimento al nodo da   che il puntatore è venuto. Su un mouseout,   i riferimenti di proprietà relatedTarget   nodo a cui il puntatore went.On   ogni caso, lo scopo è il nodo   che l'evento è il attached.When   relatedTarget è un non figlio della   currentTarget, un evento mouseover è   equivalente a un evento e di un MouseEnter   evento mouseout è equivalente a un   evento mouseLeave.

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

In questo modo è possibile implementare MouseEnter e mouseLeave in altri browser. In realtà, Ken fornisce stesso codice prototipo di farlo: http://kendsnyder.com/sandbox/enterleave /MouseEnterLeave.js

Duroth sottolineato nei commenti che MooTools include già qualcosa di simile. (Grazie Duroth.) Sembra che l'imminente rilascio Prototype (1.6.2) può includere questa funzionalità, ma non riesco a trovare nulla di preciso.

Altri suggerimenti

Utilizzando solo javascript, nessun 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>

UPDATE:
Aggiunto il controllo per la posizione del mouse su mouseout innescato quando si spostano in / out elementi all'interno del corpo. Se è all'interno della finestra, evento mouseout non viene attivato.
Ha anche introdotto una bandiera per lo stato attuale del topo 'in' o 'fuori' utilizzando mouseIsIn. Se è true, mouseover non si innescherà anche.

Forse si può impostare un listener per mouseover e mouseout document, body o qualche altro elemento che avvolge l'intero documento, e l'uso che (salvando che è successo) come un trigger per determinare se si tratta di un mouseout valida sulla finestra?

In mancanza di ciò, la vostra prima idea (per quanto riguarda controllo di posizione) dovrebbe funzionare abbastanza bene. Ogni evento passa lungo la X / Y dell'evento verificato. Se si tratta di qualcosa di più lontano di altezza / larghezza della finestra, hai lasciato la finestra attuale. Se si tratta di qualcosa di negativo, hai lasciato la finestra. E, forse, se è esattamente l'altezza / larghezza o esattamente top: 0 o sinistra: 0, allora hai lasciato la finestra

.

Quando il mouse lascia ogni elemento, tra cui la finestra, l'oggetto window verrà generato un evento mouseout e passare l'oggetto event con esso.

Uno degli elementi nell'oggetto evento si chiama toElement, che è un puntatore all'elemento il mouse appena entrato quando ha lasciato la vecchia. Ma quando il mouse lascia la finestra, non esiste tale toElement quindi questo articolo sarà null.

testando se questo oggetto è null su un evento mouseout, si può dire se il mouse a destra della finestra. Ecco il codice:

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

Il problema deriva da eventi mouseOut essere generati per gli elementi all'interno la finestra, che poi bolla come descritto nel eventi W3C spec . È possibile controllare quale elemento l'evento è stato effettivamente sparato contro:

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

Ecco la mia soluzione basata su un timer. Il timer qui è fondamentalmente utilizzato per dare una possibilità per altri gestori di eventi (in particolare, onmouseover) per eseguire prima di decidere che il mosue è fuori dalla finestra. Il timeout di 1 ms (in realtà intorno 33ms, v'è una risoluzione minima timer) dà un po 'di tempo per il passaggio del mouse si verifichi se non è già.

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

È possibile utilizzare onmouseout evento su una finestra al posto

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top