Làm cách nào để phát hiện khi chuột rời khỏi cửa sổ?


102

Tôi muốn có thể phát hiện khi con chuột rời khỏi cửa sổ để có thể ngăn các sự kiện kích hoạt trong khi con chuột của người dùng ở nơi khác.

Bất kỳ ý tưởng về cách làm điều này?


1
Kiểm tra thư viện github có mục đích thoát của beeker này. Thật tuyệt vời. github.com/beeker1121/exit-intent-popup
raksheetbhat

Sử dụng MouseLeave để ngăn kích trên tất cả các yếu tố như mouseout làm: giải thích rất tốt và hỗ trợ: developer.mozilla.org/en-US/docs/Web/API/Element/...

Đặt sự kiện trên document - không phải document.body để ngăn chặn thanh cuộn gây cháy. Thanh cuộn của Windows dường như thu nhỏ phần thân.

Câu trả lời:


100

Xin hãy nhớ rằng câu trả lời của tôi đã già đi rất nhiều.

Loại hành vi này thường được mong muốn trong khi thực hiện hành vi kéo-thả trên một trang html. Giải pháp dưới đây đã được thử nghiệm trên IE 8.0.6, FireFox 3.6.6, Opera 10.53 và Safari 4 trên máy MS Windows XP.
Đầu tiên là một chức năng nhỏ của Peter-Paul Koch; trình xử lý sự kiện trình duyệt chéo:

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

Và sau đó sử dụng phương pháp này để đính kèm một trình xử lý sự kiện vào sự kiện mouseout đối tượng tài liệu:

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

Cuối cùng, đây là một trang html với tập lệnh được nhúng để gỡ lỗi:

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

Sử dụng window.event đã khắc phục sự cố của tôi khi nhận được sự kiện này. Cảm ơn!
Jay

có vẻ như điều này không kích hoạt khi chuột không được nhấn trong chrome. nó hoạt động khi con chuột được nhấn trong chrome. có vẻ như là hành vi không nhất quán.
antony.trupe

5
Điều này không hoạt động nếu các phần tử HTML khác đang lấp đầy cửa sổ.
Emmanuel

Vấn đề với giải pháp này là nó cảnh báo cửa sổ bên trái ngay cả khi người dùng chỉ cố gắng sử dụng cuộn. Tôi đã xuất bản giải pháp cho vấn đề này ở đây , nhưng vẫn còn một vấn đề cần được giải quyết (xem liên kết).
JohnyFree

1
Sử dụng mouseleave thay vì mouseout để ngăn cháy các phần tử trong tài liệu. Rất tốt giải thích và nó hoạt động trên IE5.5 ... developer.mozilla.org/en-US/docs/Web/API/Element/...

41

Nếu bạn đang sử dụng jQuery thì làm thế nào về đoạn mã ngắn và hấp dẫn này -

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

Sự kiện này sẽ kích hoạt bất cứ khi nào con chuột không ở trong trang của bạn như bạn muốn. Chỉ cần thay đổi chức năng để làm bất cứ điều gì bạn muốn.

Và bạn cũng có thể sử dụng:

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

Để kích hoạt khi chuột quay lại trang một lần nữa.

Nguồn: https://stackoverflow.com/a/16029966/895724


mouseleave đang hoạt động nhưng nó cũng bắn nếu mở phần tử kiểm tra, làm thế nào để ngăn chặn? Ý tưởng?
Pankaj Verma

Kỹ thuật này không ổn định trong Chrome 15 đến 56 (phiên bản hiện tại của tôi). Nhưng nó hoạt động rất hiệu quả trên Firefox. Xem: stackoverflow.com/questions/7448468/…
Tremours

mouseleave dường như bắn nhiều hơn mức cần thiết.
Alexander

Nó cũng bắn nếu cửa sổ là ở chế độ nền (trình duyệt không tập trung) và chuột vào cửa sổ (Chrome 61 / macOS10.11)
CodeBrauer

1
@Skeets (và những người đọc trong tương lai) Vấn đề này đã được đánh dấu là đã khắc phục kể từ ngày 14 tháng 2 năm 2019
Xandor,

27

Điều này phù hợp với tôi:

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

9
addEventgì?
Yi Jiang

5
đó là một hàm được định nghĩa trong câu trả lời của Joshua Mills
superjos

4
trên ie8, RelatedTarget là không xác định, trên ie9 + và firefox, toElement là không xác định. Bởi vì nó, đánh giá đúng đắn là: if ((evt.relatedTarget === null) || (evt.toElement === null)) {
carlos

1
Các vị có thể ngắn gọn hơn như trongif (!evt.toElement && !evt.relatedTarget)
Pavel Ye

20

Để phát hiện mouseleave mà không tính đến thanh cuộn và trường tự động hoàn thành hoặc kiểm tra:

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

  }
});

Giải thích điều kiện:

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

======================== CHỈNH SỬA ========================= ======

document.addEventListener ("mouseleave") dường như không được kích hoạt trên phiên bản firefox mới, mouseleave cần được đính kèm với một phần tử như body hoặc một phần tử con.

Tôi đề nghị sử dụng thay thế

document.body.addEventListener("mouseleave")

Hoặc là

window.addEventListener("mouseout")

hết lần này đến lần khác không bị sa thải. Các đường nối giống như nó không thành công khi luồng điểm một điểm được kích hoạt bởi con trỏ di chuyển đường viền mục tiêu và con trỏ trở nên thay đổi kích thước.
Ivan Borshchov

@ user3479125, bạn cũng có thể dùng thử trên đoạn mã của tôi và xem vấn đề có còn xảy ra khi câu lệnh if không được thêm không? Nó có tính đến thanh cuộn nhưng tôi chưa thử nghiệm với tính năng tự động hoàn thành hoặc kiểm tra. stackoverflow.com/a/56678357/985399

7

Sử dụng sự kiện onMouseLeave ngăn chặn hiện tượng nổi bọt và cho phép bạn dễ dàng phát hiện khi chuột rời khỏi cửa sổ trình duyệt.

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

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


Tuyệt diệu! Hỗ trợ là IE5.5 + ... Cũng hoạt động: document.onmouseleave = function() { alert('You left!') };Không sử dụng document.body kích hoạt các thanh cuộn abowe thu nhỏ phần thân! Mã ngăn cháy trên các phần tử là không cần thiết. Giải thích hay: developer.mozilla.org/en-US/docs/Web/API/Element/…

6

Không câu trả lời nào trong số này phù hợp với tôi. Tôi hiện đang sử dụng:

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

});

Tôi đang sử dụng cái này cho tiện ích tải lên tệp kéo và thả. Nó không chính xác tuyệt đối, được kích hoạt khi con chuột đến một khoảng cách nhất định từ mép cửa sổ.


Tôi tin rằng điều này đôi khi sẽ không kích hoạt nếu chuyển động của chuột "đủ nhanh".
John Weisz

@JohnWeisz Vâng, tôi nghĩ bạn đúng. Tôi đã sử dụng tập lệnh này trong một thời gian và nó hoạt động tốt.
Emmanuel

6

Tôi đã thử tất cả các cách trên, nhưng dường như không có gì hoạt động như mong đợi. Sau khi nghiên cứu một chút, tôi phát hiện ra rằng e.osystemTargethtml ngay trước khi con chuột thoát khỏi cửa sổ .

Vì vậy ... tôi kết thúc với điều này:


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

Vui lòng cho tôi biết nếu bạn tìm thấy bất kỳ vấn đề hoặc cải tiến nào!

Cập nhật 2019

(như người dùng1084282 đã phát hiện ra)

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

2
Không hoạt động với tôi trên chrome. relatedTargetlà null khi chuột rời khỏi cửa sổ. Lấy cảm hứng từ câu trả lời @ user1084282 của, thay đổi nó như thế này: if(!e.relatedTarget && !e.toElement) { ... }và nó hoạt động

Tôi xác nhận rằng điều này hoạt động tốt trên Chrome, Firefox và IE Edge, nếu bạn sử dụng if(!e.relatedTarget && !e.toElement)thay vì điều kiện trong câu trả lời thực tế. Nó phát hiện con chuột rời khỏi nội dung tài liệu.
Haijerome

Không có sự kiện trên document.body vì thanh cuộn của cửa sổ có thể thu nhỏ nó và kích hoạt cuộn. Và tại sao bạn có 'mouseout' kích hoạt tất cả các phần tử có bọt trong khi bạn có thể có 'mouseleave'? developer.mozilla.org/en-US/docs/Web/API/Element/…

2

Tôi rút lại những gì tôi đã nói. Điều đó là có thể. Tôi đã viết mã này, hoạt động hoàn hảo.

window.onload = function() {

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

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

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

}

hoạt động trong chrome, firefox, opera. Aint đã thử nghiệm trong IE nhưng cho rằng nó hoạt động.

biên tập. IE luôn gây ra rắc rối. Để làm cho nó hoạt động trong IE, hãy thay thế các sự kiện từ cửa sổ sang tài liệu:

window.onload = function() {

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

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

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

}

kết hợp chúng để phát hiện con trỏ đá đít crossbrowser o0: P


Bạn đã kiểm tra xem tính năng này hoạt động tốt như thế nào cùng với các phần tử trên trang chưa? Tôi nghĩ rằng các phần tử có các sự kiện 'onmouseover / out' của riêng chúng có thể có khả năng hủy hiện tượng sôi và phá vỡ chức năng này.
Dan Herbert

1
Ozzy, Dan đang cố gắng giải thích rằng một phần tử ngừng truyền sự kiện sẽ ngăn sự kiện đến được tài liệu / cửa sổ, do đó làm cho giải pháp của bạn không hiệu quả.
James

Tôi vừa thử nghiệm nó với các phần tử khác với các sự kiện onmousemove và onmouseout của riêng họ và nó vẫn hoạt động tốt.
Ozzy

2
Có, không sao, nhưng một lần nữa chúng ta đang nói về truyền bá sự kiện. Nếu bạn cố ý dừng truyền sự kiện bằng EVENT.stopPropagation () (dành cho IE, EVENT.cancelBubble = true) thì nó sẽ không xuất hiện trên tài liệu / cửa sổ ... Để chống lại điều này, bạn có thể sử dụng tính năng chụp sự kiện trong các trình duyệt hỗ trợ nó .
James

Hãy nhớ rằng trong JS để khai báo một biến, bạn phải sử dụng 'var'. Bây giờ biến $ span là một toàn cục ngầm định, có thể không phải là điều bạn muốn. Ngoài ra, trong trường hợp không cố ý, bạn không cần $ trong tên biến.
Jani Hartikainen

2

áp dụng css này:

html
{
height:100%;
}

Điều này đảm bảo rằng phần tử html chiếm toàn bộ chiều cao của cửa sổ.

áp dụng jquery này:

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

Vấn đề với việc di chuột qua và di chuột là nếu bạn di chuột qua / ra khỏi html đến một phần tử con, nó sẽ gây ra sự kiện. Chức năng tôi đã cung cấp không được thiết lập khi di chuyển đến phần tử con. Nó chỉ được thiết lập khi bạn di chuột ra / vào cửa sổ

chỉ để bạn biết rằng bạn có thể làm điều đó khi người dùng di chuột vào cửa sổ:

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

2
Bởi "Tôi không tin rằng javascript có một hàm tương đương", nghĩa là bạn không biết rằng jQuery LÀ một thư viện các hàm javascript và jQuery được viết với và CHO javascript?
Milche Patern

2
@MilchePatern Tôi đã viết câu trả lời này gần hai năm trước. Khi đó tôi còn thiếu hiểu biết hơn và tôi không nhận ra sự thật rằng mọi thứ được thực hiện trong jQuery đều có thể được thực hiện bằng JavaScript thuần túy. Tôi sẽ cập nhật câu trả lời ...
www139

2

Tôi đã thử lần lượt và tìm ra câu trả lời tốt nhất tại thời điểm đó:

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

Tôi bỏ qua các trình duyệt cũ nên đã tạo mã ngắn hơn để hoạt động trên các trình duyệt hiện đại (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>")

Ở đây bạn thấy hỗ trợ của trình duyệt

Đó là khá ngắn tôi nghĩ

Nhưng một vấn đề vẫn còn vì "mouseout" đã kích hoạt tất cả các phần tử trong tài liệu .

Để ngăn điều đó xảy ra, hãy sử dụng mouseleave (IE5.5 +). Xem lời giải thích hay trong liên kết.

Đoạn mã sau hoạt động mà không cần kích hoạt các phần tử bên trong phần tử là bên trong hoặc bên ngoài của. Cũng thử kéo-thả bên ngoài tài liệu.

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

Bạn có thể đặt sự kiện trên bất kỳ phần tử HTML nào. document.bodyMặc dù vậy, không nên bật sự kiện vì thanh cuộn của cửa sổ có thể thu nhỏ phần thân và kích hoạt khi con trỏ chuột ở phía sau thanh cuộn khi bạn muốn cuộn nhưng không muốn nhấn chuột Để lại sự kiện trên đó. documentThay vào đó, hãy đặt nó lên , như trong ví dụ.


1

Có thể nếu bạn liên tục nghe OnMouseOver trong thẻ body, sau đó gọi lại khi sự kiện không xảy ra, nhưng, như Zack nói, điều này có thể rất xấu, bởi vì không phải tất cả các trình duyệt đều xử lý các sự kiện theo cùng một cách, thậm chí có một số khả năng bạn mất MouseOver ngay cả khi vượt qua một div trong cùng một trang.


Nó không phải là một câu trả lời

1

Có lẽ điều này sẽ giúp ích cho một số người đến đây sau này. window.onblurdocument.mouseout.

window.onblur được kích hoạt khi:

  • Bạn chuyển sang cửa sổ khác bằng Ctrl+Tabhoặc Cmd+Tab.
  • Bạn tập trung (không chỉ di chuột qua) vào trình kiểm tra tài liệu.
  • Bạn chuyển đổi máy tính để bàn.

Về cơ bản, bất cứ lúc nào tab trình duyệt đó đều mất tiêu điểm.

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

document.mouseout được kích hoạt khi:

  • Bạn di chuyển con trỏ lên thanh tiêu đề.
  • Bạn chuyển sang cửa sổ khác bằng Ctrl+Tabhoặc Cmd+Tab.
  • Bạn mở, di chuyển con trỏ đến trình kiểm tra tài liệu.

Về cơ bản trong mọi trường hợp khi con trỏ của bạn rời khỏi tài liệu.

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

"thường xuyên bất cứ lúc nào RẰNG tab trình duyệt mất tiêu điểm." .. với các phiên bản IE cũ hơn, sự kiện 'làm mờ' được tạo DOM khi / sau khi một phần tử khác nhận được tiêu điểm, đối với gooChrome, đó là khi chính phần tử đó mất tiêu điểm .. chỉ cần đề cập.
Milche Patern

Sử dụng thông minh window.onblurquá. +1
Chương trình Người sói,

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

Điều này có thể hơi khó nhưng nó sẽ chỉ kích hoạt khi chuột rời khỏi cửa sổ. Tôi tiếp tục bắt các sự kiện con và điều này đã giải quyết nó



1

Điều này đã làm việc cho tôi. Sự kết hợp của một số câu trả lời ở đây. Và tôi đã bao gồm mã hiển thị một mô hình chỉ một lần. Và mô hình sẽ biến mất khi được nhấp vào bất kỳ nơi nào khác.

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

Không có bất kỳ thẻ jQuery nào trong câu hỏi
mrReiha 13/1218

jQuery là rất nhiều mã so với câu trả lời của tôi hoạt động trên trình duyệt hiện đại IE9 + và phần còn lại. Nó là căn cứ vào câu trả lời này nhưng ngắn hơn nhiều: stackoverflow.com/a/3187524/985399

1

Xem mouseovermouseout.

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

Tôi chưa thử nghiệm điều này, nhưng bản năng của tôi là thực hiện lệnh gọi hàm OnMouseOut trên thẻ body.


-2

Điều này sẽ hoạt động trong chrome,

$(document).bind('dragleave', function (e) {
    if (e.originalEvent.clientX == 0){
        alert("left window");
    }
});
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.