Come posso rilevare quando il mouse esce dalla finestra?


102

Voglio essere in grado di rilevare quando il mouse lascia la finestra in modo da poter interrompere l'attivazione degli eventi mentre il mouse dell'utente è altrove.

Qualche idea su come farlo?


1
Dai un'occhiata a questa libreria github per l'intento di uscita di beeker. È ottimo. github.com/beeker1121/exit-intent-popup
raksheetbhat

Usa mouseleave per impedire l' attivazione su tutti gli elementi come fa il mouseout : Spiegazione e supporto molto validi: developer.mozilla.org/en-US/docs/Web/API/Element/…

Imposta l'evento sul documento - non document.body per evitare il fuoco sopra la barra di scorrimento. La barra di scorrimento di Windows sembra restringere il corpo.

Risposte:


100

Tieni presente che la mia risposta è invecchiata molto.

Questo tipo di comportamento è solitamente desiderato durante l'implementazione del comportamento di trascinamento su una pagina html. La soluzione seguente è stata testata su IE 8.0.6, FireFox 3.6.6, Opera 10.53 e Safari 4 su una macchina MS Windows XP.
Prima una piccola funzione di Peter-Paul Koch; gestore di eventi cross browser:

function addEvent(obj, evt, fn) {
    if (obj.addEventListener) {
        obj.addEventListener(evt, fn, false);
    }
    else if (obj.attachEvent) {
        obj.attachEvent("on" + evt, fn);
    }
}

Quindi utilizzare questo metodo per collegare un gestore di eventi all'evento mouseout degli oggetti del documento:

addEvent(document, "mouseout", function(e) {
    e = e ? e : window.event;
    var from = e.relatedTarget || e.toElement;
    if (!from || from.nodeName == "HTML") {
        // stop your drag event here
        // for now we can just use an alert
        alert("left window");
    }
});

Infine, ecco una pagina html con lo script incorporato per il debug:

<html>
<head>
<script type="text/javascript">
function addEvent(obj, evt, fn) {
    if (obj.addEventListener) {
        obj.addEventListener(evt, fn, false);
    }
    else if (obj.attachEvent) {
        obj.attachEvent("on" + evt, fn);
    }
}
addEvent(window,"load",function(e) {
    addEvent(document, "mouseout", function(e) {
        e = e ? e : window.event;
        var from = e.relatedTarget || e.toElement;
        if (!from || from.nodeName == "HTML") {
            // stop your drag event here
            // for now we can just use an alert
            alert("left window");
        }
    });
});
</script>
</head>
<body></body>
</html>

L'utilizzo di window.event ha risolto il mio problema nel ricevere questo evento. Grazie!
Jay

sembra che questo non si attivi quando il mouse non viene premuto in Chrome. si attiva quando il mouse viene premuto in chrome. sembra un comportamento incoerente.
antony.trupe

5
Questo non funziona se altri elementi HTML stanno riempiendo la finestra.
Emmanuel

Il problema con questa soluzione è che avvisa la finestra sinistra anche se l'utente prova a usare lo scroller. Ho pubblicato la soluzione a questo problema qui , ma c'è ancora un problema da risolvere (vedere il collegamento).
JohnyFree

1
Usa mouseleave invece di mouseout per evitare il fuoco sugli elementi nel documento. Spiegazione molto buona e funziona su IE5.5 ... developer.mozilla.org/en-US/docs/Web/API/Element/…

42

Se stai usando jQuery, allora che ne dici di questo codice breve e dolce -

$(document).mouseleave(function () {
    console.log('out');
});

Questo evento si attiverà ogni volta che il mouse non si trova nella tua pagina come desideri. Basta cambiare la funzione per fare quello che vuoi.

E potresti anche usare:

$(document).mouseenter(function () {
    console.log('in');
});

Si attiva quando il mouse torna nuovamente alla pagina.

Fonte: https://stackoverflow.com/a/16029966/895724


il mouseleave funziona ma si attiva anche se l'elemento di ispezione è aperto, come impedire? Idea?
Pankaj Verma

Questa tecnica non è stabile in Chrome da 15 a 56 (la mia versione attuale). Ma funziona molto bene in Firefox. Vedi: stackoverflow.com/questions/7448468/...
Tremours

Mouseleave sembra sparare molto più di quanto dovrebbe.
Alexander

Si attiva anche se la finestra è in background (browser non focalizzato) e il mouse entra nella finestra (Chrome 61 / macOS10.11)
CodeBrauer

1
@Skeets (e futuri lettori) Questo problema è stato contrassegnato come risolto il 14 febbraio 2019
Xandor

27

Questo funziona per me:

addEvent(document, 'mouseout', function(evt) {
  if (evt.toElement == null && evt.relatedTarget == null) {
    alert("left window");
  }
});

9
Che cos'è addEvent?
Yi Jiang

5
è una funzione definita nella risposta di Joshua Mills
superjos

4
su ie8, relatedTarget è undefined, su ie9 + e firefox, toElement è undefined. Perché esso, la valutazione corretta è: if ((evt.relatedTarget === null) || (evt.toElement === null)) {
carlos

1
Il predicato potrebbe essere più conciso come inif (!evt.toElement && !evt.relatedTarget)
Pavel Ye

20

Per rilevare l'uscita del mouse senza tenere conto della barra di scorrimento e del campo di completamento automatico o ispezionare:

document.addEventListener("mouseleave", function(event){

  if(event.clientY <= 0 || event.clientX <= 0 || (event.clientX >= window.innerWidth || event.clientY >= window.innerHeight))
  {

     console.log("I'm out");

  }
});

Spiegazione delle condizioni:

event.clientY <= 0  is when the mouse leave from the top
event.clientX <= 0  is when the mouse leave from the left
event.clientX >= window.innerWidth is when the mouse leave from the right
event.clientY >= window.innerHeight is when the mouse leave from the bottom

======================== EDIT ========================= ======

document.addEventListener ("mouseleave") sembra non essere attivato sulla nuova versione di firefox, mouseleave deve essere associato a un elemento come body o un elemento figlio.

Suggerisco di usare invece

document.body.addEventListener("mouseleave")

O

window.addEventListener("mouseout")

di tanto in tanto non sparato. Seams come se fallisse quando un punto del flusso di punti innescato dallo spostamento del cursore mira al bordo e il cursore viene ridimensionato.
Ivan Borshchov

@ user3479125, potresti provarlo anche sul mio frammento e vedere se il problema persiste quando l'istruzione if non viene aggiunta? Prende in considerazione la barra di scorrimento ma non l'ho testata con autocompletamento o ispezione. stackoverflow.com/a/56678357/985399

7

L'utilizzo dell'evento onMouseLeave previene il bubbling e consente di rilevare facilmente quando il mouse esce dalla finestra del browser.

<html onmouseleave="alert('You left!')"></html>

http://www.w3schools.com/jsref/event_onmouseleave.asp


Fantastico! Il supporto è IE5.5 + ... Funziona anche: document.onmouseleave = function() { alert('You left!') };usa not document.body che spara oltre le barre di scorrimento che riducono il corpo! Il codice per prevenire il fuoco sugli elementi non è necessario. Buona spiegazione: developer.mozilla.org/en-US/docs/Web/API/Element/…

6

Nessuna di queste risposte ha funzionato per me. Ora sto usando:

document.addEventListener('dragleave', function(e){

    var top = e.pageY;
    var right = document.body.clientWidth - e.pageX;
    var bottom = document.body.clientHeight - e.pageY;
    var left = e.pageX;

    if(top < 10 || right < 20 || bottom < 10 || left < 10){
        console.log('Mouse has moved out of window');
    }

});

Lo sto usando per un widget per il caricamento di file drag and drop. Non è assolutamente preciso, viene attivato quando il mouse arriva a una certa distanza dal bordo della finestra.


Credo che questo a volte non si attivi se il movimento del mouse è "abbastanza veloce".
John Weisz

@JohnWeisz Sì, penso che tu abbia ragione. Ho usato questo script per un po 'di tempo e funziona bene.
Emmanuel

6

Ho provato tutto quanto sopra, ma niente sembra funzionare come previsto. Dopo una piccola ricerca ho scoperto che e.relatedTarget è l' html appena prima che il mouse esca dalla finestra .

Quindi ... ho finito con questo:


document.body.addEventListener('mouseout', function(e) {
    if (e.relatedTarget === document.querySelector('html')) {
        console.log('We\'re OUT !');
    }
});

Per favore fatemi sapere se trovate problemi o miglioramenti!

Aggiornamento 2019

(come user1084282 scoperto)

document.body.addEventListener('mouseout', function(e) {
    if (!e.relatedTarget && !e.toElement) {
        console.log('We\'re OUT !');
    }
});

2
Non funziona per me su Chrome. relatedTargetè nullo quando il mouse lascia la finestra. Ispirato dalla risposta di @ user1084282, cambialo in questo: if(!e.relatedTarget && !e.toElement) { ... }e funziona

Confermo che funziona bene su Chrome, Firefox e IE Edge, se utilizzi al if(!e.relatedTarget && !e.toElement)posto della condizione nella risposta effettiva. Rileva che il mouse esce dal corpo del documento.
Haijerome

Non avere l'evento su document.body perché la barra di scorrimento di Windows potrebbe rimpicciolirlo e sparare sopra lo scorrimento. E perché hai "mouseout" che si attiva su tutti gli elementi con bolle quando puoi avere "mouseleave"? developer.mozilla.org/en-US/docs/Web/API/Element/…

2

Riprendo quello che ho detto. È possibile. Ho scritto questo codice, funziona perfettamente.

window.onload = function() {

    $span = document.getElementById('text');

    window.onmouseout = function() {
        $span.innerHTML = "mouse out";  
    }

    window.onmousemove = function() {
        $span.innerHTML = "mouse in";   
    }

}

funziona in chrome, firefox, opera. Non è stato testato in IE ma presumo che funzioni.

modificare. IE come sempre causa problemi. Per farlo funzionare in IE, sostituisci gli eventi dalla finestra al documento:

window.onload = function() {

    $span = document.getElementById('text');

    document.onmousemove = function() {
        $span.innerHTML = "mouse move";
    }

    document.onmouseout = function() {
        $span.innerHTML = "mouse out";
    }

}

combinali per il rilevamento del cursore kick ass crossbrowser o0: P


Hai testato quanto bene funzioni insieme agli elementi sulla pagina? Penso che gli elementi che hanno i propri eventi "onmouseover / out" potrebbero potenzialmente annullare il bubbling e interrompere questa funzionalità.
Dan Herbert

1
Ozzy, Dan sta cercando di spiegare che un elemento che arresta la propagazione dell'evento impedirà all'evento di raggiungere il documento / finestra, rendendo in tal modo inefficace la tua soluzione.
James,

L'ho appena testato con altri elementi con i propri eventi onmousemove e onmouseout e funziona ancora bene.
Ozzy

2
Sì, va bene, ma ancora una volta stiamo parlando di propagazione degli eventi. Se interrompi intenzionalmente la propagazione degli eventi con EVENT.stopPropagation () (per IE, EVENT.cancelBubble = true), allora non si diffonderà nel documento / finestra ... Per contrastare questo potresti usare la cattura degli eventi nei browser che lo supportano .
James,

Ricorda che in JS per dichiarare una variabile, devi usare 'var'. Ora la variabile $ span è un globale implicito, che probabilmente non è quello che vuoi. Inoltre, nel caso non sia intenzionale, non è necessario un $ nei nomi delle variabili.
Jani Hartikainen

2

applica questo css:

html
{
height:100%;
}

Ciò garantisce che l'elemento html occupi l'intera altezza della finestra.

applica questo jquery:

$("html").mouseleave(function(){
 alert('mouse out');
});

Il problema con mouseover e mouseout è che se passi il mouse sopra / fuori da html a un elemento figlio, l'evento innescherà. La funzione che ho fornito non viene attivata quando si passa con il mouse su un elemento figlio. Viene attivato solo quando si sposta il mouse fuori / dentro dalla finestra

solo per farti sapere che puoi farlo quando l'utente posiziona il mouse nella finestra:

$("html").mouseenter(function(){
  alert('mouse enter');
});

2
Con "Non credo che javascript abbia una funzione equivalente", intendi che non sai che jQuery È una libreria di funzioni javascript e che jQuery È scritto CON e PER javascript?
Milche Patern

2
@MilchePatern Ho scritto questa risposta quasi due anni fa. Allora ero più ignorante e non mi rendevo conto del fatto che qualsiasi cosa fatta in jQuery può essere fatta in JavaScript puro. Aggiornerò la risposta ...
www139

2

Ho provato uno dopo l'altro e ho trovato una risposta migliore al momento:

https://stackoverflow.com/a/3187524/985399

Salto i vecchi browser, quindi ho reso il codice più breve per funzionare sui browser moderni (IE9 +)

    document.addEventListener("mouseout", function(e) {
        let t = e.relatedTarget || e.toElement;
        if (!t || t.nodeName == "HTML") {
          console.log("left window");
        }
    });

document.write("<br><br>PROBLEM<br><br><div>Mouseout trigg on HTML elements</div>")

Qui vedi il supporto del browser

È stato piuttosto breve, ho pensato

Ma rimaneva ancora un problema perché "mouseout" si attiva su tutti gli elementi del documento .

Per evitare che ciò accada, usa mouseleave ( IE5.5 +). Vedi la buona spiegazione nel link.

Il codice seguente funziona senza attivare gli elementi all'interno dell'elemento che devono essere all'interno o all'esterno di. Prova anche a rilasciare il trascinamento all'esterno del documento.

var x = 0

document.addEventListener("mouseleave", function(e) { console.log(x++) 
})

document.write("<br><br>SOLUTION<br><br><div>Mouseleave do not trigg on HTML elements</div>")

Puoi impostare l'evento su qualsiasi elemento HTML. document.bodyTuttavia, non attivare l'evento , poiché la barra di scorrimento di Windows potrebbe ridurre il corpo e attivarsi quando il puntatore del mouse si trova sopra la barra di scorrimento quando si desidera scorrere ma non si desidera attivare un evento mouseLeave su di essa. Impostalo documentinvece su , come nell'esempio.


1

Forse se ascolti costantemente OnMouseOver nel tag body, richiama quando l'evento non si verifica, ma, come afferma Zack, potrebbe essere molto brutto, perché non tutti i browser gestiscono gli eventi allo stesso modo, ce ne sono anche alcuni possibilità che tu perda il MouseOver anche trovandoti sopra un div nella stessa pagina.


Non è una risposta

1

Forse questo aiuterebbe alcuni di quelli che verranno qui più tardi. window.onblure document.mouseout.

window.onblur viene attivato quando:

  • Si passa a un'altra finestra utilizzando Ctrl+Tabo Cmd+Tab.
  • Ti concentri (non solo il passaggio del mouse) sull'ispettore documenti.
  • Cambia desktop.

Fondamentalmente ogni volta che la scheda del browser perde il focus.

window.onblur = function(){
    console.log("Focus Out!")
}

document.mouseout viene attivato quando:

  • Spostare il cursore sulla barra del titolo.
  • Si passa a un'altra finestra utilizzando Ctrl+Tabo Cmd+Tab.
  • Apri e sposta il cursore sull'ispettore documenti.

Fondamentalmente in ogni caso quando il cursore lascia il documento.

document.onmouseleave = function(){
    console.log("Mouse Out!")
}

"asically ogni volta che la scheda del browser perde il focus." .. con le versioni precedenti di IE, l'evento 'sfocatura' è controllato dal DOM quando / dopo che un altro elemento riceve il focus, per gooChrome, è quando l'elemento stesso perde il focus .. solo per menzionare.
Milche Patern

window.onblurAnche l' utilizzo intelligente . +1
Programmi Redwolf

1
$(window).mouseleave(function(event) {
  if (event.toElement == null) {
    //Do something
  }
})

Potrebbe essere un po 'complicato ma si attiverà solo quando il mouse lascia la finestra. Continuavo a catturare eventi bambini e questo lo ha risolto



1

Questo ha funzionato per me. Una combinazione di alcune delle risposte qui. E ho incluso il codice che mostra un modello solo una volta. E il modello scompare quando viene cliccato altrove.

<script>
    var leave = 0
    //show modal when mouse off of page
    $("html").mouseleave(function() {
       //check for first time
       if (leave < 1) {
          modal.style.display = "block";
          leave = leave + 1;
       }
    });

    // Get the modal with id="id01"
       var modal = document.getElementById('id01');

    // When the user clicks anywhere outside of the modal, close it
       window.onclick = function(event) {
          if (event.target == modal) {
             modal.style.display = "none";
          }
       }
</script>

Non c'era alcun tag jQuery sulla domanda
mrReiha

jQuery è un sacco di codice rispetto alla mia risposta che funziona sui browser moderni IE9 + e il resto. E 'di base su questa risposta, ma molto più breve: stackoverflow.com/a/3187524/985399

1

Vedi mouseovere mouseout.

var demo = document.getElementById('demo');
document.addEventListener("mouseout", function(e){demo.innerHTML="😞";});
document.addEventListener("mouseover", function(e){demo.innerHTML="😊";});
div { font-size:80vmin; position:absolute;
      left:50%; top:50%; transform:translate(-50%,-50%); }
<div id='demo'>😐</div>


0

Non l'ho testato, ma il mio istinto sarebbe quello di eseguire una chiamata alla funzione OnMouseOut sul tag body.


-2

Funzionerà in Chrome,

$(document).bind('dragleave', function (e) {
    if (e.originalEvent.clientX == 0){
        alert("left window");
    }
});
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.