Farenin pencereden ayrıldığını nasıl tespit edebilirim?


103

Farenin pencereden ne zaman ayrıldığını algılayabilmek istiyorum, böylece kullanıcının faresi başka bir yerdeyken olayların tetiklenmesini durdurabilirim.

Bunun nasıl yapılacağına dair bir fikriniz var mı?


1
Bu arıcı çıkış amaçlı github kütüphanesine göz atın. Bu harika. github.com/beeker1121/exit-intent-popup
raksheetbhat

Kullanım mouseLeave tüm gibi öğeler tetiklenmesini önlemek için mouseout : Çok iyi bir açıklama ve destek: does developer.mozilla.org/en-US/docs/Web/API/Element/...

Kaydırma çubuğunda yangını önlemek için belge üzerinde olay ayarlayın - document.body değil. Windows kaydırma çubuğu gövdeyi küçültüyor gibi görünüyor.

Yanıtlar:


100

Lütfen cevabımın çok eskidiğini unutmayın.

Bu tür bir davranış, genellikle bir html sayfasında sürükle bırak davranışı uygulanırken istenir. Aşağıdaki çözüm bir MS Windows XP makinesinde IE 8.0.6, FireFox 3.6.6, Opera 10.53 ve Safari 4 üzerinde test edilmiştir.
Önce Peter-Paul Koch'tan küçük bir fonksiyon; tarayıcılar arası olay işleyicisi:

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

Ve sonra, belge nesneleri mouseout olayına bir olay işleyicisi eklemek için bu yöntemi kullanın:

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

Son olarak, hata ayıklama için katıştırılmış komut dosyası içeren bir html sayfası:

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

Window.event kullanmak bu olayı alma sorunumu çözdü. Teşekkürler!
Jay

fareye krom olarak basılmadığında bu ateşlenmiyor gibi görünüyor. fareye krom olarak basıldığında ateşlenir. tutarsız bir davranış gibi görünüyor.
antony.trupe

5
Pencereyi diğer HTML öğeleri dolduruyorsa bu çalışmaz.
Emmanuel

Bu çözümle ilgili sorun, kullanıcı kaydırıcıyı kullanmaya çalışsa bile sol pencereyi uyarmasıdır. Bu sorunun çözümünü burada yayınladım , ancak hala çözülmesi gereken bir sorun var (bağlantıya bakın).
JohnyFree

1
Kullanım mouseLeave belgede unsurları ateş önlemek için yerine Fare terk ait. Çok iyi bir açıklama ve IE5.5 üzerinde çalışıyor ... developer.mozilla.org/en-US/docs/Web/API/Element/…

43

JQuery kullanıyorsanız, bu kısa ve tatlı koda ne dersiniz?

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

Bu olay, fare istediğiniz gibi sayfanızda olmadığında tetiklenecektir. İstediğinizi yapmak için işlevi değiştirmeniz yeterlidir.

Ayrıca şunları da kullanabilirsiniz:

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

Fare tekrar sayfaya girdiğinde tetiklemek için.

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


mouseleave çalışıyor ama aynı zamanda teftiş elemanı açılırsa ateşleniyor, nasıl önlenir? Fikir?
Pankaj Verma

Bu teknik, Chrome 15 ila 56'da (benim mevcut sürümüm) kararlı değildir. Ancak Firefox'ta çok çalışacak. Bakınız: stackoverflow.com/questions/7448468/…
Tremours

Mouseleave olması gerekenden çok daha fazla ateş ediyor gibi görünüyor.
Alexander

Pencere arka plandaysa (tarayıcı odaklanmamışsa) ve fare pencereye girerse (Chrome 61 / macOS10.11)
CodeBrauer

1
@Skeets (ve gelecekteki okuyucular) Bu sorun 14 Şubat 2019 itibarıyla düzeltildi
Xandor

27

Bu benim için çalışıyor:

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

9
Nedir addEvent?
Yi Jiang


4
ie8'de relatedTarget tanımsız, ie9 + ve firefox'ta toElement tanımsız. Çünkü doğru değerlendirme şudur: if ((evt.relatedTarget === null) || (evt.toElement === null)) {
carlos

1
Öngörü daha kısa olabilirif (!evt.toElement && !evt.relatedTarget)
Pavel Ye

20

Fare çıkışını kaydırma çubuğunu ve eksik alanı hesaba katmadan tespit etmek veya incelemek için:

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

  }
});

Koşul açıklamaları:

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

======================== DÜZENLE ========================= ======

document.addEventListener ("mouseleave") yeni firefox sürümünde çalıştırılmamış gibi görünüyor, mouseleave'in body gibi bir öğeye veya bir alt öğeye eklenmesi gerekiyor.

Onun yerine kullanmayı öneririm

document.body.addEventListener("mouseleave")

Veya

window.addEventListener("mouseout")

zaman zaman ateşlenmedi. İmlecin hareket ettirilmesiyle tetiklenen bir nokta akışı sınırı hedef aldığında ve imleç yeniden boyutlandırıldığında başarısız oluyor gibi görünüyor.
Ivan Borshchov

@ user3479125, benim pasajımda da deneyebilir misiniz ve if-ifadesi eklenmediğinde sorunun devam edip etmediğini görebilir misiniz? Kaydırma çubuğunu hesaba katıyor, ancak otomatik tamamlama veya inceleme ile test etmedim. stackoverflow.com/a/56678357/985399

7

OnMouseLeave olayını kullanmak köpürmeyi önler ve fare tarayıcı penceresinden çıktığında kolayca algılamanıza olanak tanır.

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

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


Fantastik! Destek IE5.5 + ... Ayrıca çalışıyor: document.onmouseleave = function() { alert('You left!') };Gövdeyi küçülten kaydırma çubuklarına ateşleyen document.body kullanmayın! Elemanlarda yangını önlemek için kod gerekli değildir. İyi açıklama: developer.mozilla.org/en-US/docs/Web/API/Element/…

6

Bu cevapların hiçbiri benim için işe yaramadı. Şimdi kullanıyorum:

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

});

Bunu bir sürükle ve bırak dosya yükleme gereci için kullanıyorum. Kesinlikle doğru değil, fare pencerenin kenarından belirli bir mesafeye geldiğinde tetikleniyor.


Fare hareketi "yeterince hızlı" ise bunun bazen tetiklenmeyeceğine inanıyorum.
John Weisz

@JohnWeisz Evet, haklı olduğunu düşünüyorum. Bu senaryoyu bir süredir kullandım ve yine de iyi çalışıyor.
Emmanuel

6

Yukarıdakilerin hepsini denedim, ancak hiçbir şey beklendiği gibi çalışmıyor. Biraz araştırmadan sonra bunu buldum e.relatedTarget olan html sadece fare penceresini çıkar önce .

Yani ... bununla son buldum:


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

Herhangi bir sorun veya gelişme bulursanız lütfen bana bildirin!

2019 Güncellemesi

(user1084282 bulduğu gibi)

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

2
Benim için Chrome'da çalışmıyor. relatedTargetfare pencereden çıktığında boştur. @ User1084282'nin cevabından esinlenerek, bunu şöyle değiştirin: if(!e.relatedTarget && !e.toElement) { ... }ve işe yarıyor

if(!e.relatedTarget && !e.toElement)Gerçek cevaptaki koşul yerine kullanırsanız, bunun Chrome, Firefox ve IE Edge'de iyi çalıştığını onaylıyorum . Farenin belge gövdesini terk ettiğini algılar.
Haijerome

Olayı document.body üzerinde yapmayın çünkü Windows kaydırma çubuğu onu küçültebilir ve kaydırmanın üzerine ateş açabilir. Ve neden 'fare bırakma' varken neden tüm kabarcıklı öğelere ateş eden 'fare' var? developer.mozilla.org/en-US/docs/Web/API/Element/…

2

Dediğimi geri alıyorum. Bu mümkün. Bu kodu yazdım, mükemmel çalışıyor.

window.onload = function() {

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

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

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

}

chrome, firefox, opera alanlarında çalışıyor. IE'de test edilmiyor, ancak çalıştığını varsayın.

Düzenle. IE her zaman olduğu gibi sorun yaratır. IE'de çalışmasını sağlamak için olayları pencereden belgeye değiştirin:

window.onload = function() {

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

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

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

}

onları çapraz tarayıcı kick ass imleç algılaması için birleştirin o0: P


Bunun sayfadaki öğelerle birlikte ne kadar iyi çalıştığını test ettiniz mi? Kendine ait 'fareyle üzerine gelme / dışarıda olma' olaylarına sahip öğelerin köpürmeyi potansiyel olarak iptal edebileceğini ve bu işlevi bozabileceğini düşünürdüm.
Dan Herbert

1
Ozzy, Dan olay yayılmasını durduran bir öğenin olayın belgeye / pencereye ulaşmasını engelleyeceğini ve böylece çözümünüzü etkisiz hale getireceğini açıklamaya çalışıyor.
James

Onu diğer unsurlarla kendi onmousemove ve onmouseout olaylarıyla test ettim ve hala iyi çalışıyor.
Ozzy

2
Evet tamam, ama yine olayların yayılmasından bahsediyoruz. EVENT.stopPropagation () (IE için EVENT.cancelBubble = true) ile olay yayılmasını kasıtlı olarak durdurursanız, belgeye / pencereye kabarmaz ... Buna karşı koymak için, onu destekleyen tarayıcılarda olay yakalamayı kullanabilirsiniz. .
James

JS'de bir değişken bildirmek için 'var' kullanmanız gerektiğini unutmayın. Şimdi $ span değişkeni örtük bir globaldir ve muhtemelen istediğiniz şey bu değildir. Ayrıca kasıtlı olmaması durumunda, bir $ in değişken adlarına ihtiyacınız yoktur.
Jani Hartikainen

2

bu css'yi uygulayın:

html
{
height:100%;
}

Bu, html öğesinin pencerenin tüm yüksekliğini kaplamasını sağlar.

bu jquery'yi uygulayın:

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

Fareyle üzerine gelme ve fareyi çekmeyle ilgili sorun, html'den bir alt öğeye fareyi getirip çıkardığınızda, olayı başlatacak olmasıdır. Verdiğim işlev , bir alt öğeye fareyle giderken çalışmıyor . Yalnızca fareyi pencereden dışarı / içeri doğru çektiğinizde kapanır

sadece kullanıcı pencerede fare gördüğünde yapabileceğinizi bilmeniz için:

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

2
"Javascript'in eşdeğer bir işlevi olduğuna inanmıyorum" derken, jQuery'nin bir javascript işlevleri kitaplığı OLDUĞUNU ve jQuery'nin javascript İLE ve Javascript İÇİN yazıldığını bilmiyor musunuz?
Milche Patern

2
@MilchePatern Bu cevabı neredeyse iki yıl önce yazdım. O zamanlar daha cahildim ve jQuery'de yapılan her şeyin saf JavaScript ile yapılabileceğini fark etmemiştim. Cevabı güncelleyeceğim ...
www139

2

Birbiri ardına denedim ve o sırada en iyi cevabı buldum:

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

Eski tarayıcıları atlıyorum, böylece kodu modern tarayıcılarda çalışması için kısalttım (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>")

Burada tarayıcı desteğini görüyorsunuz

Oldukça kısa olduğunu düşündüm

Ancak , belgedeki tüm öğelerde "fare çekme" tetiklendiği için bir sorun devam ediyor .

Bunun olmasını önlemek için mouseleave kullanın (IE5.5 +) kullanın. Bağlantıdaki iyi açıklamaya bakın.

Aşağıdaki kod, öğenin içindeki öğelerin içinde veya dışında olmasını tetiklemeden çalışır. Belgenin dışına da sürükleyip bırakmayı deneyin.

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

Etkinliği herhangi bir HTML öğesi üzerinde ayarlayabilirsiniz. Olayı document.bodyaçmayın, çünkü Windows kaydırma çubuğu gövdeyi küçültebilir ve kaydırma yapmak istediğinizde ancak üzerinde bir mouseLeave olayını tetiklemek istemediğinizde fare işaretçisi kaydırma çubuğunun altındayken yanabilir. Bunun documentyerine örnekteki gibi ayarlayın .


1

Belki vücut etiketinde OnMouseOver'ı sürekli dinliyorsanız, olay gerçekleşmediğinde geri arama yaparsanız, ancak Zack'in belirttiği gibi, bu çok çirkin olabilir, çünkü tüm tarayıcılar olayları aynı şekilde ele almaz, hatta bazıları vardır Aynı sayfadaki bir div'in üzerinde olsanız bile MouseOver'ı kaybetme olasılığı.


Cevap değil

1

Belki bu, buraya daha sonra gelenlerin bazılarına yardımcı olabilir. window.onblurvedocument.mouseout .

window.onblur şu durumlarda tetiklenir:

  • Sen kullanarak başka bir pencereye geçiş Ctrl+TabveyaCmd+Tab .
  • Belge denetçisine odaklanırsınız (yalnızca fareyle üzerine gelmez).
  • Masaüstünü değiştirirsiniz.

Temelde, bu tarayıcı sekmesi odağı kaybettiğinde.

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

document.mouseout şu durumlarda tetiklenir:

  • İmleci başlık çubuğuna taşırsınız.
  • Sen kullanarak başka bir pencereye geçiş Ctrl+TabveyaCmd+Tab .
  • Açarsınız, imleci belge denetçisinin üzerine getirin.

Temelde her durumda, imleciniz belgeden ayrıldığında.

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

"her zaman O tarayıcı sekmesi odağı kaybettiğinde." .. IE'nin eski sürümlerinde, 'bulanıklaştırma' olayı, başka bir öğe odağı aldığında / sonra DOM derlenir, gooChrome için, öğenin odağı kaybettiği zamandır .. sadece bahsetmek gerekirse.
Milche Patern

Akıllı kullanım window.onblurda. +1
Redwolf Programları

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

Bu biraz karmaşık olabilir, ancak yalnızca fare pencereden çıktığında tetiklenir. Çocuk olaylarını yakalamaya devam ettim ve bu sorunu çözdü



1

Bu benim için çalıştı. Buradaki bazı cevapların bir kombinasyonu. Ve bir modeli gösteren kodu yalnızca bir kez ekledim. Ve model başka bir yere tıklandığında kaybolur.

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


jQuery, modern tarayıcılar IE9 + ve diğerlerinde çalışan cevabıma kıyasla çok fazla kod. Bu cevaba

1

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

Bunu test etmedim, ancak içgüdülerim gövde etiketinde OnMouseOut işlev çağrısı yapmak olurdu.


-2

Bu, Chrome'da çalışacak,

$(document).bind('dragleave', function (e) {
    if (e.originalEvent.clientX == 0){
        alert("left window");
    }
});
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.