Wie kann ich erkennen, wann die Maus das Fenster verlässt?


102

Ich möchte erkennen können, wann die Maus das Fenster verlässt, damit ich verhindern kann, dass Ereignisse ausgelöst werden, während sich die Maus des Benutzers an einer anderen Stelle befindet.

Irgendwelche Ideen, wie das geht?


1
Schauen Sie sich diese Github-Bibliothek mit Beeker-Exit-Intent an. Es ist toll. github.com/beeker1121/exit-intent-popup
raksheetbhat

Verwenden Sie Mouseleave , um zu verhindern, dass alle Elemente ausgelöst werden, wie dies beim Mouseout der Fall ist: Sehr gute Erklärung und Unterstützung: developer.mozilla.org/en-US/docs/Web/API/Element/…

Setzen Sie das Ereignis auf das Dokument - nicht auf document.body, um einen Brand über der Bildlaufleiste zu verhindern. Die Windows-Bildlaufleiste scheint den Körper zu verkleinern.

Antworten:


100

Bitte denken Sie daran, dass meine Antwort sehr gealtert ist.

Diese Art von Verhalten ist normalerweise erwünscht, wenn Drag-Drop-Verhalten auf einer HTML-Seite implementiert wird. Die folgende Lösung wurde unter IE 8.0.6, FireFox 3.6.6, Opera 10.53 und Safari 4 auf einem MS Windows XP-Computer getestet.
Zuerst eine kleine Funktion von Peter-Paul Koch; Browserübergreifender Ereignishandler:

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

Verwenden Sie dann diese Methode, um einen Ereignishandler an das Mouseout-Ereignis für Dokumentobjekte anzuhängen:

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

Schließlich ist hier eine HTML-Seite mit dem Skript zum Debuggen eingebettet:

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

Die Verwendung von window.event hat mein Problem beim Abrufen dieses Ereignisses behoben. Vielen Dank!
Jay

Es sieht so aus, als würde dies nicht ausgelöst, wenn die Maus nicht in Chrom gedrückt wird. Es wird ausgelöst, wenn die Maus in Chrom gedrückt wird. scheint inkonsistentes Verhalten.
antony.trupe

5
Dies funktioniert nicht, wenn andere HTML-Elemente das Fenster füllen.
Emmanuel

Das Problem bei dieser Lösung ist, dass das linke Fenster auch dann angezeigt wird, wenn der Benutzer nur versucht, den Scroller zu verwenden. Ich veröffentlichte Lösung für dieses Problem hier , aber es gibt noch ein Problem braucht (siehe Link) gelöst werden.
JohnyFree

1
Verwenden Mouseleave anstelle von Mouseout, um einen Brand auf Elemente im Dokument zu verhindern. Sehr gute Erklärung und es funktioniert auf IE5.5 ... developer.mozilla.org/en-US/docs/Web/API/Element/…

41

Wenn Sie jQuery verwenden, wie wäre es dann mit diesem kurzen und süßen Code -

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

Dieses Ereignis wird immer dann ausgelöst, wenn sich die Maus nicht wie gewünscht auf Ihrer Seite befindet. Ändern Sie einfach die Funktion, um zu tun, was Sie wollen.

Und Sie könnten auch verwenden:

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

Auslösen, wenn die Maus wieder zur Seite zurückkehrt.

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


mouseleave funktioniert, aber es wird auch ausgelöst, wenn das Inspektionselement geöffnet wird. Wie kann dies verhindert werden? Idee?
Pankaj Verma

Diese Technik ist in Chrome 15 bis 56 (meine aktuelle Version) nicht stabil. Aber es funktioniert sehr gut in Firefox. Siehe: stackoverflow.com/questions/7448468/…
Tremours

Mouseleave scheint viel mehr zu feuern, als es sollte.
Alexander

Es wird auch ausgelöst, wenn sich das Fenster im Hintergrund befindet (Browser nicht fokussiert) und die Maus das Fenster betritt (Chrome 61 / macOS10.11)
CodeBrauer

1
@Skeets (und zukünftige Leser) Dieses Problem wurde als behoben am 14. Februar 2019
Xandor

27

Das funktioniert bei mir:

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

9
Was ist addEvent?
Yi Jiang

5
Es ist eine Funktion, die in Joshua Mills Antwort definiert ist
Superjos

4
auf ie8 ist relatedTarget undefiniert, auf ie9 + und Firefox ist toElement undefiniert. Die korrekte Bewertung lautet daher: if ((evt.relatedTarget === null) || (evt.toElement === null)) {
Carlos

1
Das Prädikat könnte prägnanter sein als inif (!evt.toElement && !evt.relatedTarget)
Pavel Ye

20

Um Mausblätter zu erkennen, ohne die Bildlaufleiste und das Feld für die automatische Vervollständigung zu berücksichtigen, oder um Folgendes zu überprüfen:

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");

  }
});

Bedingungen Erklärungen:

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

======================= BEARBEITEN ========================== ======

document.addEventListener ("mouseleave") scheint bei einer neuen Firefox-Version nicht ausgelöst zu werden. Mouseleave muss an ein Element wie body oder ein untergeordnetes Element angehängt werden.

Ich schlage vor, stattdessen zu verwenden

document.body.addEventListener("mouseleave")

Oder

window.addEventListener("mouseout")

von Zeit zu Zeit nicht gefeuert. Nähte, wie sie fehlschlagen, wenn ein Punkt des Punktstroms, der durch das Bewegen des Cursors ausgelöst wird, den Rand des Ziels und die Größe des Cursors ändert.
Ivan Borshchov

@ user3479125, könntest du es auch auf meinem Snippet ausprobieren und sehen, ob das Problem weiterhin besteht, wenn die if-Anweisung nicht hinzugefügt wird? Es berücksichtigt die Bildlaufleiste, aber ich habe nicht mit Autocomplete oder Inspect getestet. stackoverflow.com/a/56678357/985399

7

Die Verwendung des Ereignisses onMouseLeave verhindert das Sprudeln und ermöglicht es Ihnen, leicht zu erkennen, wann die Maus das Browserfenster verlässt.

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

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


Fantastisch! Unterstützung ist IE5.5 + ... Funktioniert auch: document.onmouseleave = function() { alert('You left!') };Verwenden Sie nicht document.body, das über Bildlaufleisten ausgelöst wird, die den Körper verkleinern! Code zur Verhinderung eines Brandes auf Elementen wird nicht benötigt. Gute Erklärung: developer.mozilla.org/en-US/docs/Web/API/Element/…

6

Keine dieser Antworten hat bei mir funktioniert. Ich benutze jetzt:

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

});

Ich verwende dies für ein Widget zum Hochladen von Dateien per Drag & Drop. Es ist nicht absolut genau und wird ausgelöst, wenn die Maus einen bestimmten Abstand vom Fensterrand erreicht.


Ich glaube, dass dies manchmal nicht ausgelöst wird, wenn die Mausbewegung "schnell genug" ist.
John Weisz

@ JohnWeisz Ja, ich denke du hast recht. Ich habe dieses Skript jetzt schon eine Weile benutzt und es funktioniert trotzdem gut.
Emmanuel

6

Ich habe alles oben versucht, aber nichts scheint wie erwartet zu funktionieren. Nach ein wenig Recherche fand ich heraus, dass e.relatedTarget das HTML ist, kurz bevor die Maus das Fenster verlässt .

Also ... ich habe am Ende folgendes:


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

Bitte lassen Sie mich wissen, wenn Sie Probleme oder Verbesserungen finden!

Update 2019

(wie user1084282 herausgefunden hat)

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

2
Ich arbeite nicht für mich auf Chrom. relatedTargetist null, wenn die Maus das Fenster verlässt. Inspiriert von der Antwort von @ user1084282, ändern Sie sie in diese: if(!e.relatedTarget && !e.toElement) { ... }und es funktioniert

Ich bestätige, dass dies unter Chrome, Firefox und IE Edge einwandfrei funktioniert, wenn Sie if(!e.relatedTarget && !e.toElement)anstelle der Bedingung in der tatsächlichen Antwort verwenden. Es erkennt, dass die Maus den Dokumentkörper verlässt.
Haijerome

Haben Sie das Ereignis nicht in document.body, da die Windows-Bildlaufleiste es möglicherweise verkleinert und über dem Bildlauf ausgelöst wird. Und warum haben Sie ein "Mouseout", das auf alle sprudelnden Elemente feuert, wenn Sie "Mouseleave" haben können? developer.mozilla.org/en-US/docs/Web/API/Element/…

2

Ich nehme zurück, was ich gesagt habe. Es ist möglich. Ich habe diesen Code geschrieben, funktioniert perfekt.

window.onload = function() {

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

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

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

}

arbeitet in Chrom, Firefox, Oper. Aint im IE getestet, aber davon ausgehen, dass es funktioniert.

bearbeiten. IE verursacht wie immer Probleme. Ersetzen Sie die Ereignisse vom Fenster zum Dokument, damit es im IE funktioniert:

window.onload = function() {

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

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

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

}

Kombiniere sie für die Crossbrowser Kick Ass Cursor Erkennung o0: P.


Haben Sie getestet, wie gut dies mit Elementen auf der Seite zusammenarbeitet? Ich würde denken, dass Elemente, die ihre eigenen "Onmouseover / Out" -Ereignisse haben, möglicherweise das Sprudeln aufheben und diese Funktionalität beeinträchtigen könnten.
Dan Herbert

1
Ozzy, Dan versucht zu erklären, dass ein Element, das die Ereignisausbreitung stoppt, verhindert, dass das Ereignis das Dokument / Fenster erreicht, wodurch Ihre Lösung unwirksam wird.
James

Ich habe es gerade mit anderen Elementen mit eigenen Onmousemove- und Onmouseout-Ereignissen getestet und es funktioniert immer noch einwandfrei.
Ozzy

2
Ja, okay, aber wir sprechen wieder über die Weitergabe von Ereignissen. Wenn Sie die Ereignisverbreitung absichtlich mit EVENT.stopPropagation () stoppen (für IE EVENT.cancelBubble = true), sprudelt sie nicht in das Dokument / Fenster ... Um dem entgegenzuwirken, können Sie die Ereigniserfassung in Browsern verwenden, die dies unterstützen .
James

Denken Sie daran, dass Sie in JS zum Deklarieren einer Variablen 'var' verwenden müssen. Jetzt ist die Variable $ span eine implizite globale Variable, die wahrscheinlich nicht Ihren Wünschen entspricht. Auch für den Fall, dass dies nicht beabsichtigt ist, benötigen Sie kein $ in Variablennamen.
Jani Hartikainen

2

wende dieses CSS an:

html
{
height:100%;
}

Dadurch wird sichergestellt, dass das HTML-Element die gesamte Höhe des Fensters einnimmt.

Wenden Sie diese Abfrage an:

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

Das Problem bei Mouseover und Mouseout besteht darin, dass das Ereignis ausgelöst wird, wenn Sie mit der Maus über HTML auf ein untergeordnetes Element fahren. Die Funktion, die ich gegeben habe, wird beim Bewegen eines untergeordneten Elements nicht ausgelöst. Es wird nur ausgelöst, wenn Sie mit der Maus aus dem Fenster fahren

Nur damit Sie wissen, dass Sie dies tun können, wenn der Benutzer im Fenster mauset:

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

2
Mit "Ich glaube nicht, dass Javascript eine äquivalente Funktion hat" meinen Sie, Sie wissen nicht, dass jQuery eine Javascript-Funktionsbibliothek ist und dass jQuery MIT und FÜR Javascript geschrieben ist?
Milche Patern

2
@MilchePatern Ich habe diese Antwort vor fast zwei Jahren geschrieben. Ich war damals ignoranter und wusste nicht, dass alles, was in jQuery gemacht wird, in reinem JavaScript gemacht werden kann. Ich werde die Antwort aktualisieren ...
www139

2

Ich versuchte es nacheinander und fand damals die beste Antwort:

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

Ich überspringe alte Browser, um den Code für moderne Browser (IE9 +) zu verkürzen.

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

Hier sehen Sie die Browserunterstützung

Das war ziemlich kurz, dachte ich

Es blieb jedoch ein Problem bestehen, da "Mouseout" für alle Elemente im Dokument ausgelöst wurde .

Verwenden Sie Mouseleave , um dies zu verhindern (IE5.5 +) . Siehe die gute Erklärung im Link.

Der folgende Code funktioniert ohne Auslösen von Elementen innerhalb des Elements, die sich innerhalb oder außerhalb befinden. Versuchen Sie auch, die Datei außerhalb des Dokuments zu ziehen.

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

Sie können das Ereignis für jedes HTML-Element festlegen. Das Ereignis document.bodyist jedoch nicht aktiviert, da die Windows-Bildlaufleiste möglicherweise den Körper verkleinert und ausgelöst wird, wenn sich der Mauszeiger über der Bildlaufleiste befindet, wenn Sie einen Bildlauf durchführen möchten, aber kein mouseLeave-Ereignis darüber auslösen möchten. Aktivieren Sie es documentstattdessen wie im Beispiel.


1

Wenn Sie OnMouseOver ständig im Body-Tag anhören, wird es möglicherweise zurückgerufen, wenn das Ereignis nicht auftritt. Wie Zack feststellt, kann dies jedoch sehr hässlich sein, da nicht alle Browser Ereignisse auf die gleiche Weise behandeln, es gibt sogar einige Möglichkeit, dass Sie den MouseOver verlieren, selbst wenn Sie sich über einem Div auf derselben Seite befinden.


Es ist keine Antwort

1

Vielleicht würde dies einigen von denen helfen, die später hierher kommen. window.onblurund document.mouseout.

window.onblur wird ausgelöst, wenn:

  • Sie wechseln mit Ctrl+Taboder zu einem anderen FensterCmd+Tab .
  • Sie konzentrieren sich (nicht nur mit der Maus) auf den Dokumenteninspektor.
  • Sie wechseln die Desktops.

Grundsätzlich verliert DIESER Browser-Tab jedes Mal den Fokus.

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

document.mouseout wird ausgelöst, wenn:

  • Sie bewegen den Cursor auf die Titelleiste.
  • Sie wechseln mit Ctrl+Taboder zu einem anderen FensterCmd+Tab .
  • Sie öffnen den Mauszeiger zum Dokumenteninspektor.

Grundsätzlich in jedem Fall, wenn Ihr Cursor das Dokument verlässt.

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

"Asical immer dann, wenn DIESE Browser-Registerkarte den Fokus verliert." .. Bei älteren IE-Versionen wird das Ereignis 'Unschärfe' DOM-kompiliert, wenn / nachdem ein anderes Element den Fokus erhalten hat. Bei gooChrome verliert das Element selbst den Fokus .. nur um es zu erwähnen.
Milche Patern

Auch klug window.onblur. +1
Redwolf Programme

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

Dies mag etwas hackig sein, wird aber nur ausgelöst, wenn die Maus das Fenster verlässt. Ich fing immer wieder Kinderereignisse auf und das löste es



1

Das hat bei mir funktioniert. Eine Kombination einiger Antworten hier. Und ich habe den Code, der ein Modell zeigt, nur einmal eingefügt. Und das Modell verschwindet, wenn es irgendwo anders angeklickt wird.

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

Es gab kein jQuery-Tag auf der Frage
mrReiha

jQuery ist eine Menge Code im Vergleich zu meiner Antwort, die auf modernen Browsern IE9 + und dem Rest funktioniert. Es basiert auf dieser Antwort, ist aber viel kürzer: stackoverflow.com/a/3187524/985399

1

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

Ich habe dies nicht getestet, aber mein Instinkt wäre, einen OnMouseOut-Funktionsaufruf für das Body-Tag durchzuführen.


-2

Dies wird in Chrom funktionieren,

$(document).bind('dragleave', function (e) {
    if (e.originalEvent.clientX == 0){
        alert("left window");
    }
});
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.