Bagaimana cara mendeteksi saat mouse meninggalkan jendela?

102

Saya ingin dapat mendeteksi saat mouse meninggalkan jendela sehingga saya dapat menghentikan pengaktifan peristiwa saat mouse pengguna berada di tempat lain.

Ada ide bagaimana melakukan ini?


sumber
1
Lihat pustaka github maksud keluar dari beeker ini. Itu bagus. github.com/beeker1121/exit-intent-popup
raksheetbhat
Gunakan mouseleave untuk mencegah penembakan pada semua elemen seperti yang dilakukan mouseout : Penjelasan dan dukungan yang sangat bagus: developer.mozilla.org/en-US/docs/Web/API/Element/…
Tetapkan acara pada dokumen - bukan document.body untuk mencegah kebakaran di atas bilah gulir. Scrollbar Windows tampak mengecilkan badan.

Jawaban:

100

Harap diingat bahwa jawaban saya sudah sangat tua.

Jenis perilaku ini biasanya diinginkan saat menerapkan perilaku seret-lepas di halaman html. Solusi di bawah ini telah diuji pada IE 8.0.6, FireFox 3.6.6, Opera 10.53, dan Safari 4 pada mesin MS Windows XP.
Pertama, fungsi kecil dari Peter-Paul Koch; penangan acara lintas browser:

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

Dan kemudian gunakan metode ini untuk melampirkan event handler ke objek dokumen mouseout event:

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

Terakhir, berikut adalah halaman html dengan skrip yang disematkan untuk debugging:

<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>
J Mills
sumber
Menggunakan window.event memperbaiki masalah saya mendapatkan acara ini. Terima kasih!
Jay
Sepertinya ini tidak menyala saat mouse tidak ditekan dengan krom. itu menyala saat mouse ditekan dengan krom. Sepertinya perilaku tidak konsisten.
antony.trupe
5
Ini tidak berfungsi jika elemen HTML lain mengisi jendela.
Emmanuel
Masalah dengan solusi ini adalah jendela kiri memperingatkan meskipun pengguna hanya mencoba menggunakan penggulung. Saya menerbitkan solusi untuk masalah ini di sini , tetapi masih ada satu masalah yang perlu diselesaikan (lihat tautannya).
JohnyFree
1
Gunakan mouseleave sebagai pengganti mouseout untuk mencegah kebakaran pada elemen dalam dokumen. Penjelasan yang sangat bagus dan berfungsi di IE5.5 ... developer.mozilla.org/en-US/docs/Web/API/Element/…
42

Jika Anda menggunakan jQuery, bagaimana dengan kode pendek dan manis ini -

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

Peristiwa ini akan terpicu setiap kali mouse tidak ada di halaman Anda seperti yang Anda inginkan. Ubah saja fungsinya untuk melakukan apa pun yang Anda inginkan.

Dan Anda juga bisa menggunakan:

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

Untuk memicu ketika mouse masuk kembali ke halaman itu lagi.

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

Mandeep Janjua
sumber
mouseleave berfungsi tetapi juga menembak jika elemen inspeksi dibuka, bagaimana mencegahnya? Ide?
Pankaj Verma
Teknik ini tidak stabil di Chrome 15 hingga 56 (versi saya saat ini). Tapi itu bekerja sangat baik di Firefox. Lihat: stackoverflow.com/questions/7448468/…
Tremours
mouseleave tampaknya menembak lebih banyak dari yang seharusnya.
Alexander
Ini juga menyala jika jendela berada di latar belakang (browser tidak fokus) dan mouse memasuki jendela (Chrome 61 / macOS10.11)
CodeBrauer
1
@Skeets (dan pembaca mendatang) Masalah ini telah ditandai diperbaiki pada Feb 14, 2019
Xandor
27

Ini bekerja untuk saya:

addEvent(document, 'mouseout', function(evt) {
  if (evt.toElement == null && evt.relatedTarget == null) {
    alert("left window");
  }
});
pengguna1084282
sumber
9
Apa addEvent?
Yi Jiang
5
itu adalah fungsi yang didefinisikan dalam jawaban Joshua Mills
superjos
4
di ie8, relatedTarget tidak ditentukan, di ie9 + dan firefox, toElement tidak ditentukan. Karena itu, evaluasi yang benar adalah: if ((evt.relatedTarget === null) || (evt.toElement === null)) {
carlos
1
Predikatnya bisa lebih ringkas seperti padaif (!evt.toElement && !evt.relatedTarget)
Pavel Ye
20

Untuk mendeteksi mouseleave tanpa memperhitungkan scroll bar dan kolom lengkapi otomatis atau periksa:

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

  }
});

Penjelasan kondisi:

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") tampaknya tidak diaktifkan pada versi firefox baru, mouseleave perlu dilampirkan ke elemen seperti body, atau elemen turunan.

Saya menyarankan untuk menggunakan sebagai gantinya

document.body.addEventListener("mouseleave")

Atau

window.addEventListener("mouseout")
Daphoque
sumber
dari waktu ke waktu tidak dipecat. Jahitan seperti itu gagal ketika salah satu titik aliran dipicu oleh kursor bergerak batas tujuan dan kursor berubah ukuran.
Ivan Borshchov
@ user3479125, dapatkah Anda mencobanya juga di cuplikan saya dan melihat apakah masalahnya tetap ada saat pernyataan-if tidak ditambahkan? Ini memperhitungkan bilah gulir tetapi saya belum menguji dengan pelengkapan otomatis atau inspeksi. stackoverflow.com/a/56678357/985399
7

Menggunakan acara onMouseLeave mencegah gelembung menggelembung dan memungkinkan Anda mendeteksi dengan mudah saat mouse meninggalkan jendela browser.

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

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

Samy Bencherif
sumber
Fantastis! Dukungan adalah IE5.5 + ... Bekerja juga: document.onmouseleave = function() { alert('You left!') };Gunakan bukan document.body yang menembakkan di atas scroll bar yang mengecilkan tubuh! Kode untuk mencegah kebakaran pada elemen tidak diperlukan. Penjelasan yang bagus: developer.mozilla.org/en-US/docs/Web/API/Element/…
6

Tak satu pun dari jawaban ini berhasil untuk saya. Saya sekarang menggunakan:

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

});

Saya menggunakan ini untuk widget pengunggahan file seret dan lepas. Ini tidak sepenuhnya akurat, dipicu saat mouse mencapai jarak tertentu dari tepi jendela.

Emmanuel
sumber
Saya yakin ini terkadang tidak akan terpicu jika gerakan mouse "cukup cepat".
John Weisz
@JohnWeisz Ya, saya pikir Anda benar. Saya telah menggunakan skrip ini untuk sementara waktu sekarang dan itu berfungsi dengan baik.
Emmanuel
6

Saya sudah mencoba semua hal di atas, tetapi tidak ada yang berfungsi seperti yang diharapkan. Setelah sedikit riset, saya menemukan bahwa e.relatedTarget adalah html tepat sebelum mouse keluar dari jendela .

Jadi ... saya berakhir dengan ini:


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

Beri tahu saya jika Anda menemukan masalah atau peningkatan!

Pembaruan 2019

(seperti yang ditemukan pengguna1084282)

document.body.addEventListener('mouseout', function(e) {
    if (!e.relatedTarget && !e.toElement) {
        console.log('We\'re OUT !');
    }
});
Claudiu
sumber
2
Tidak berhasil untuk saya di chrome. relatedTargetadalah null saat mouse meninggalkan jendela. Terinspirasi oleh jawaban @ user1084282, ubah menjadi ini: if(!e.relatedTarget && !e.toElement) { ... }dan berfungsi
Saya mengonfirmasi bahwa ini berfungsi dengan baik di Chrome, Firefox dan IE Edge, jika Anda menggunakan if(!e.relatedTarget && !e.toElement)alih-alih kondisi di jawaban yang sebenarnya. Ini mendeteksi mouse meninggalkan badan dokumen.
Haijerome
Jangan memiliki acara di document.body karena bilah gulir windows dapat mengecilkannya dan menyala di atas gulir. Dan mengapa Anda memiliki 'mouseout' yang menyala pada semua elemen yang menggelembung ketika Anda dapat memiliki 'mouseleave'? developer.mozilla.org/en-US/docs/Web/API/Element/…
2

Saya menarik kembali apa yang saya katakan. Itu mungkin. Saya menulis kode ini, bekerja dengan sempurna.

window.onload = function() {

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

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

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

}

bekerja di chrome, firefox, opera. Tidak diuji di IE, tetapi asumsikan berhasil.

edit. IE selalu menyebabkan masalah. Untuk membuatnya berfungsi di IE, ganti acara dari jendela ke dokumen:

window.onload = function() {

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

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

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

}

menggabungkannya untuk deteksi kursor crossbrowser kick ass o0: P

Ozzy
sumber
Sudahkah Anda menguji seberapa baik ini bekerja bersama dengan elemen pada halaman? Saya akan berpikir bahwa elemen yang memiliki acara 'onmouseover / out' mereka sendiri berpotensi membatalkan gelembung dan merusak fungsi ini.
Dan Herbert
1
Ozzy, Dan mencoba menjelaskan bahwa elemen yang menghentikan propagasi kejadian akan mencegah kejadian mencapai dokumen / jendela, sehingga membuat solusi Anda tidak efektif.
Yakobus
Saya baru saja mengujinya dengan elemen lain dengan acara onmousemove dan onmouseout mereka sendiri dan masih berfungsi dengan baik.
Ozzy
2
Ya oke, tapi sekali lagi kita berbicara tentang propagasi acara. Jika Anda dengan sengaja menghentikan penyebaran peristiwa dengan EVENT.stopPropagation () (untuk IE, EVENT.cancelBubble = true) maka itu tidak akan menggelembung ke dokumen / jendela ... Untuk mengatasi ini, Anda dapat menggunakan penangkapan peristiwa di browser yang mendukungnya .
Yakobus
Ingatlah bahwa di JS untuk mendeklarasikan variabel, Anda harus menggunakan 'var'. Sekarang variabel $ span adalah global implisit, yang mungkin bukan yang Anda inginkan. Juga jika tidak disengaja, Anda tidak memerlukan $ dalam nama variabel.
Jani Hartikainen
2

terapkan css ini:

html
{
height:100%;
}

Ini memastikan bahwa elemen html memenuhi seluruh tinggi jendela.

terapkan jquery ini:

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

Masalah dengan gerakan mouse dan gerakan mouse adalah bahwa jika Anda mengarahkan mouse ke atas / keluar dari html ke elemen anak itu akan memicu acara. Fungsi yang saya berikan tidak diaktifkan saat mengarahkan mouse ke elemen anak. Ini hanya menyala ketika Anda mengarahkan mouse ke luar / masuk jendela

hanya untuk Anda ketahui, Anda dapat melakukannya saat pengguna mengarahkan mouse di jendela:

$("html").mouseenter(function(){
  alert('mouse enter');
});
www139
sumber
2
Dengan "Saya tidak percaya javascript memiliki fungsi yang setara", maksud Anda, Anda tidak tahu bahwa jQuery ADALAH pustaka fungsi javascript dan jQuery IS ditulis DENGAN dan UNTUK javascript?
Milche Patern
2
@MilchePatern Saya menulis jawaban ini hampir dua tahun lalu. Saya lebih bodoh saat itu dan saya tidak menyadari fakta bahwa apa pun yang dilakukan di jQuery dapat dilakukan dalam JavaScript murni. Saya akan memperbarui jawabannya ...
www139
2

Saya mencoba satu demi satu dan menemukan jawaban terbaik pada saat itu:

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

Saya melewati peramban lama jadi saya mempersingkat kodenya untuk bekerja di peramban modern (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>")

Di sini Anda melihat dukungan browser

Itu cukup singkat, pikirku

Namun masalah tetap ada karena "mouseout" memicu semua elemen dalam dokumen .

Untuk mencegahnya, gunakan mouseleave (IE5.5 +). Lihat penjelasan bagusnya di link.

Kode berikut bekerja tanpa memicu elemen di dalam elemen berada di dalam atau di luar. Coba juga drag-release di luar dokumen.

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

Anda dapat mengatur acara di elemen HTML apa pun. document.bodyNamun, jangan biarkan acara tersebut aktif , karena bilah gulir jendela dapat mengecilkan isi dan menyala saat penunjuk mouse berada di atas bilah gulir saat Anda ingin menggulir tetapi tidak ingin memicu peristiwa mouseLeave di atasnya. Nyalakan saja document, seperti pada contoh.


sumber
1

Mungkin jika Anda terus-menerus mendengarkan OnMouseOver di tag body, maka callback saat acara tidak terjadi, tetapi, seperti yang dikatakan Zack, ini bisa sangat buruk, karena tidak semua browser menangani acara dengan cara yang sama, bahkan ada beberapa kemungkinan bahwa Anda kehilangan MouseOver bahkan dengan berada di atas div di halaman yang sama.

Pablo Albornoz
sumber
Ini bukan jawaban
1

Mungkin ini akan membantu beberapa dari mereka yang datang ke sini nanti. window.onblurdandocument.mouseout .

window.onblur dipicu ketika:

  • Anda beralih ke jendela lain menggunakan Ctrl+TabatauCmd+Tab.
  • Anda fokus (bukan hanya gerakan mouse) pada pemeriksa dokumen.
  • Anda beralih desktop.

Pada dasarnya setiap kali tab browser kehilangan fokus.

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

document.mouseout dipicu ketika:

  • Anda memindahkan kursor ke bilah judul.
  • Anda beralih ke jendela lain menggunakan Ctrl+Tabatau Cmd+Tab.
  • Anda membuka memindahkan kursor ke pemeriksa dokumen.

Pada dasarnya kapan pun kursor Anda meninggalkan dokumen.

document.onmouseleave = function(){
    console.log("Mouse Out!")
}
Jayant Bhawal
sumber
"Pada dasarnya setiap kali tab browser itu kehilangan fokus." .. dengan IE versi yang lebih lama, acara 'blur' adalah DOM dikompilasi ketika / setelah elemen lain menerima fokus, untuk gooChrome, itu adalah ketika elemen itu sendiri kehilangan fokus .. hanya untuk menyebutkan.
Milche Patern
Pintar menggunakan window.onblurjuga. +1
Program Redwolf
1
$(window).mouseleave(function(event) {
  if (event.toElement == null) {
    //Do something
  }
})

Ini mungkin sedikit hacky tetapi hanya akan terpicu ketika mouse meninggalkan jendela. Saya terus menonton acara anak-anak dan ini menyelesaikannya

Cekaleek
sumber
1
$(window).mouseleave(function() {
 alert('mouse leave');
});
sandeep kumar
sumber
1

Ini berhasil untuk saya. Kombinasi dari beberapa jawaban di sini. Dan saya memasukkan kode yang menunjukkan model hanya sekali. Dan model tersebut akan hilang saat diklik di tempat lain.

<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>
Morgan Hayes
sumber
Tidak ada tag jQuery pada pertanyaan
mrReiha
jQuery adalah banyak kode dibandingkan dengan jawaban saya yang berfungsi di browser modern IE9 + dan yang lainnya. Ini berdasarkan jawaban ini tetapi jauh lebih pendek: stackoverflow.com/a/3187524/985399
1

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

ashleedawg.dll
sumber
0

Saya belum menguji ini, tetapi naluri saya adalah melakukan panggilan fungsi OnMouseOut pada tag body.

Ender
sumber
-2

Ini akan bekerja di chrome,

$(document).bind('dragleave', function (e) {
    if (e.originalEvent.clientX == 0){
        alert("left window");
    }
});
anupraj
sumber