Làm thế nào để chụp sự kiện đóng cửa sổ trình duyệt?


149

Tôi muốn chụp sự kiện đóng cửa sổ / tab trình duyệt. Tôi đã thử như sau với jQuery:

jQuery(window).bind(
    "beforeunload", 
    function() { 
        return confirm("Do you really want to close?") 
    }
)

Nhưng nó cũng hoạt động trên biểu mẫu, đó không phải là điều tôi muốn. Tôi muốn một sự kiện chỉ kích hoạt khi người dùng đóng cửa sổ.

Câu trả lời:


212

Sự beforeunloadkiện này kích hoạt bất cứ khi nào người dùng rời khỏi trang của bạn vì bất kỳ lý do gì.

Ví dụ: nó sẽ được kích hoạt nếu người dùng gửi biểu mẫu, nhấp vào liên kết, đóng cửa sổ (hoặc tab) hoặc đi đến một trang mới bằng thanh địa chỉ, hộp tìm kiếm hoặc dấu trang.

Bạn có thể loại trừ việc gửi biểu mẫu và siêu liên kết (ngoại trừ các khung khác) với mã sau:

var inFormOrLink;
$('a').on('click', function() { inFormOrLink = true; });
$('form').on('submit', function() { inFormOrLink = true; });

$(window).on("beforeunload", function() { 
    return inFormOrLink ? "Do you really want to close?" : null; 
})

Đối với các phiên bản jQuery cũ hơn 1.7, hãy thử điều này:

var inFormOrLink;
$('a').live('click', function() { inFormOrLink = true; });
$('form').bind('submit', function() { inFormOrLink = true; });

$(window).bind("beforeunload", function() { 
    return inFormOrLink ? "Do you really want to close?" : null; 
})

Các livephương pháp không làm việc với các submitsự kiện, vì vậy nếu bạn thêm một hình thức mới, bạn sẽ cần phải ràng buộc xử lý với nó là tốt.

Lưu ý rằng nếu một trình xử lý sự kiện khác hủy bỏ việc gửi hoặc điều hướng, bạn sẽ mất dấu nhắc xác nhận nếu cửa sổ thực sự bị đóng sau đó. Bạn có thể khắc phục điều đó bằng cách ghi lại thời gian trong submitclickcác sự kiện và kiểm tra xem điều đó có beforeunloadxảy ra sau vài giây không.


8
yup, làm việc tuyệt vời Các phiên bản mới hơn của jquery hỗ trợ $ ('form'). Live ('submit, function () {}).
Venkat D.

4
Giải pháp của bạn là tốt nhưng làm cách nào để hủy sự kiện trong trường hợp làm mới? Tôi chỉ muốn sự kiện nếu trình duyệt bị đóng, không có trường hợp làm mới
Refael

Có vẻ như trình duyệt hiển thị giá trị trả về của tải trước dưới dạng hộp thoại xác nhận. Vì vậy, tôi nghĩ rằng câu trả lời này chính xác hơn: link
tahagh

2
thực hiện xử lý này làm mới của một trang sử dụng Ctrl + r, F5, Ctrl + Shift + rvà thay đổi URL của trình duyệt?
Arti

1
@Jonny: Bây giờ chỉ là .on().
SLaks

45

Có thể chỉ hủy liên kết beforeunloadtrình xử lý sự kiện trong trình xử lý sự kiện của biểu mẫu submit:

jQuery('form').submit(function() {
    jQuery(window).unbind("beforeunload");
    ...
});

3
Đây không phải là dễ dàng khi không sử dụng jQuery bằng cách chỉ định điều này trong định nghĩa thẻ biểu mẫu? : `<form onsubmit =" window.onb Beforeunload = null; ">
awe

4
@awe Nhưng bạn cần bao gồm nó onsubmit=...trong mỗi hình thức. (Tôi có nhiều mẫu trên mỗi trang, trong một ứng dụng web nhất định)
KajMagnus

16

Đối với giải pháp trình duyệt chéo (đã được thử nghiệm trong Chrome 21, IE9, FF15), hãy xem xét sử dụng mã sau đây, đây là phiên bản được điều chỉnh một chút về mã của Slaks:

var inFormOrLink;
$('a').live('click', function() { inFormOrLink = true; });
$('form').bind('submit', function() { inFormOrLink = true; });

$(window).bind('beforeunload', function(eventObject) {
    var returnValue = undefined;
    if (! inFormOrLink) {
        returnValue = "Do you really want to close?";
    }
    eventObject.returnValue = returnValue;
    return returnValue;
}); 

Lưu ý rằng kể từ Firefox 4, thông báo "Bạn có thực sự muốn đóng không?" không được hiển thị. FF chỉ hiển thị một thông điệp chung chung. Xem ghi chú trong https://developer.mozilla.org/en-US/docs/DOM/window.onb Beforeunload


3
Điều này hoạt động nhất quán trên các trình duyệt. Chỉ cần một ghi chú nhanh; Tôi đã cập nhật cả câu lệnh livebindcâu lệnh on, hoạt động tuyệt vời với mức độ mới nhất của jQuery. Cảm ơn!
Sablefoste


4

Để giải pháp hoạt động tốt với các điều khiển của bên thứ ba như Telerik (ví dụ: RadComboBox) và DevExpress sử dụng các thẻ Anchor vì nhiều lý do, hãy xem xét sử dụng mã sau đây, đây là phiên bản được điều chỉnh một chút của mã desm với bộ chọn tốt hơn cho chính bạn thẻ neo nhắm mục tiêu:

var inFormOrLink;
$('a[href]:not([target]), a[href][target=_self]').live('click', function() { inFormOrLink = true; });
$('form').bind('submit', function() { inFormOrLink = true; });

$(window).bind('beforeunload', function(eventObject) {
    var returnValue = undefined;
    if (! inFormOrLink) {
        returnValue = "Do you really want to close?";
    }
    eventObject.returnValue = returnValue;
    return returnValue;
});

1
Câu trả lời này là đúng nhưng đối với những người gặp sự cố với sự kiện này xảy ra khi bạn làm mới trình duyệt, hãy thay đổi mã của bạn thành mã sau: if (inFormOrLink! == không xác định &&! InFormOrLink)
LeonPierre

4

Câu trả lời của tôi là nhằm cung cấp điểm chuẩn đơn giản.

LÀM THẾ NÀO ĐỂ

Xem câu trả lời @SLaks .

$(window).on("beforeunload", function() { 
    return inFormOrLink ? "Do you really want to close?" : null; 
})

Trình duyệt mất bao lâu để cuối cùng đóng trang của bạn?

Bất cứ khi nào người dùng đóng trang ( xnút hoặc CTRL+ W), trình duyệt sẽ thực thi beforeunloadmã đã cho , nhưng không phải là vô thời hạn. Ngoại lệ duy nhất là hộp xác nhận ( return 'Do you really want to close?) sẽ đợi cho đến khi có phản hồi của người dùng.

Chrome : 2 giây.
Firefox : (hoặc nhấp đúp chuột hoặc buộc đóng)
Cạnh : ∞ (hoặc nhấp đúp)
Explorer 11 : 0 giây.
Safari : HÔM NAY

Những gì chúng tôi sử dụng để kiểm tra điều này:

  • Máy chủ Node.js Express có nhật ký yêu cầu
  • Tệp HTML ngắn sau đây

Những gì nó làm là gửi càng nhiều yêu cầu càng tốt trước khi trình duyệt đóng trang của nó (đồng bộ).

<html>
<body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script>
    function request() {
        return $.ajax({
            type: "GET",
            url: "http://localhost:3030/" + Date.now(),
            async: true
        }).responseText;
    }
    window.onbeforeunload = () => {
        while (true) {
            request();
        }
        return null;
    }
    </script>
</body>
</html>

Đầu ra Chrome:

GET /1480451321041 404 0.389 ms - 32  
GET /1480451321052 404 0.219 ms - 32  
...  
GET /hello/1480451322998 404 0.328 ms - 32

1957ms  2 seconds // we assume it's 2 seconds since requests can take few milliseconds to be sent.

3

Tôi đã sử dụng câu trả lời Slaks nhưng nó không hoạt động như vậy, vì onb Beforeunload returnValue được phân tích cú pháp dưới dạng chuỗi và sau đó được hiển thị trong hộp xác nhận của trình duyệt. Vì vậy, giá trị true đã được hiển thị, như "true".

Chỉ cần sử dụng trở lại làm việc. Đây là mã của tôi

var preventUnloadPrompt;
var messageBeforeUnload = "my message here - Are you sure you want to leave this page?";
//var redirectAfterPrompt = "http://www.google.co.in";
$('a').live('click', function() { preventUnloadPrompt = true; });
$('form').live('submit', function() { preventUnloadPrompt = true; });
$(window).bind("beforeunload", function(e) { 
    var rval;
    if(preventUnloadPrompt) {
        return;
    } else {
        //location.replace(redirectAfterPrompt);
        return messageBeforeUnload;
    }
    return rval;
})

1

Có lẽ bạn có thể xử lý OnSubmit và đặt cờ mà sau này bạn kiểm tra trong trình xử lý OnB BeforeUnload của bạn.


1
jQuery(window).bind(
                    "beforeunload",
                      function (e) {
                          var activeElementTagName = e.target.activeElement.tagName;
                          if (activeElementTagName != "A" && activeElementTagName != "INPUT") {
                              return "Do you really want to close?";
                          }
                      })

1

Thật không may, cho dù đó là tải lại, chuyển hướng trang mới hoặc trình duyệt đóng sự kiện sẽ được kích hoạt. Một cách khác là bắt id kích hoạt sự kiện và nếu nó là biểu mẫu thì không kích hoạt bất kỳ chức năng nào và nếu đó không phải là id của biểu mẫu thì hãy làm những gì bạn muốn làm khi đóng trang. Tôi không chắc nếu điều đó cũng có thể trực tiếp và tẻ nhạt.

Bạn có thể làm một số việc nhỏ trước khi khách hàng đóng tab. javascript phát hiện trình duyệt đóng tab / đóng trình duyệt nhưng nếu danh sách hành động của bạn lớn và tab đóng trước khi kết thúc, bạn sẽ bất lực. Bạn có thể thử nó nhưng với kinh nghiệm của tôi donot phụ thuộc vào nó.

window.addEventListener("beforeunload", function (e) {
  var confirmationMessage = "\o/";
  /* Do you small action code here */
  (e || window.event).returnValue = confirmationMessage; //Gecko + IE
  return confirmationMessage;                            //Webkit, Safari, Chrome
});

https://developer.mozilla.org/en-US/docs/Web/Reference/Events/b Beforeunload? redirectlocale = en-US & redects-pug


0

Nếu việc gửi biểu mẫu của bạn đưa họ đến một trang khác (như tôi giả sử, do đó kích hoạt beforeunload), bạn có thể thử thay đổi biểu mẫu của mình thành một cuộc gọi ajax. Bằng cách này, họ sẽ không rời khỏi trang của bạn khi họ gửi biểu mẫu và bạn có thể sử dụng beforeunloadmã ràng buộc của mình theo ý muốn.


0

Vấn đề của tôi: Sự kiện 'onb Beforeunload' sẽ chỉ được kích hoạt nếu có số lần gửi (số lần nhấp) lẻ. Tôi đã có sự kết hợp các giải pháp từ các luồng tương tự trong SO để giải pháp của tôi hoạt động. Vâng, mã của tôi sẽ nói.

<!--The definition of event and initializing the trigger flag--->


$(document).ready(function() {
updatefgallowPrompt(true);
window.onbeforeunload = WarnUser;   
}

function WarnUser() {
var allowPrompt = getfgallowPrompt();
    if(allowPrompt) {
    saveIndexedDataAlert();
    return null;
    } else {
        updatefgallowPrompt(true);
        event.stopPropagation
    }
}

<!--The method responsible for deciding weather the unload event is triggered from submit or not--->
function saveIndexedDataAlert() {
    var allowPrompt = getfgallowPrompt();
    var lenIndexedDocs = parseInt($('#sortable3 > li').size()) + parseInt($('#sortable3 > ul').size());

    if(allowPrompt && $.trim(lenIndexedDocs) > 0) {
        event.returnValue = "Your message";
    } else {
        event.returnValue = "   ";
        updatefgallowPrompt(true);
    }
}

<!---Function responsible to reset the trigger flag---->
$(document).click(function(event) {  
$('a').live('click', function() { updatefgallowPrompt(false); });
 });

<!--getter and setter for the flag---->
function updatefgallowPrompt (allowPrompt){ //exit msg dfds
    $('body').data('allowPrompt', allowPrompt); 
}   

function getfgallowPrompt(){        
    return $('body').data('allowPrompt');   
}

0

Kể từ jQuery 1.7, phương thức .live () không được dùng nữa. Sử dụng .on () để đính kèm các trình xử lý sự kiện. Người dùng các phiên bản cũ hơn của jQuery nên sử dụng .delegate () để ưu tiên cho .live ()

$(window).bind("beforeunload", function() {
    return true || confirm("Do you really want to close?"); 
}); 

hoàn thành hoặc liên kết

$(window).unbind();

0

Cũng thử cái này

window.onbeforeunload = function ()
{       
    if (pasteEditorChange) {
        var btn = confirm('Do You Want to Save the Changess?');
           if(btn === true ){
               SavetoEdit();//your function call
           }
           else{
                windowClose();//your function call
           }
    }  else { 
        windowClose();//your function call
    }
};

-1

Chỉ cần xác minh ...

function wopen_close(){
  var w = window.open($url, '_blank', 'width=600, height=400, scrollbars=no, status=no, resizable=no, screenx=0, screeny=0');
  w.onunload = function(){
    if (window.closed) {
       alert("window closed");
    }else{ 
       alert("just refreshed");
    }
  }
}

Nó không hoạt động. Tại thời điểm sự kiện unload kích hoạt (btw, nó kích hoạt từ tài liệu), window.closes === false;
Sergey P. aka azure

-1
var validNavigation = false;
            jQuery(document).ready(function () {

                wireUpEvents();
            });

            function endSession() {
                // Browser or broswer tab is closed
                // Do sth here ...
                alert("bye");
            }

            function wireUpEvents() {
                /*
                * For a list of events that triggers onbeforeunload on IE
                * check http://msdn.microsoft.com/en-us/library/ms536907(VS.85).aspx
                */
                window.onbeforeunload = function () {
                    debugger
                    if (!validNavigation) {
                        endSession();
                    }
                }

                // Attach the event keypress to exclude the F5 refresh
                $(document).bind('keypress', function (e) {
                    debugger
                    if (e.keyCode == 116) {
                        validNavigation = true;
                    }
                });

                // Attach the event click for all links in the page
                $("a").bind("click", function () {
                    debugger
                    validNavigation = true;
                });

                // Attach the event submit for all forms in the page
                $("form").bind("submit", function () {
                    debugger
                    validNavigation = true;
                });

                // Attach the event click for all inputs in the page
                $("input[type=submit]").bind("click", function () {
                    debugger
                    validNavigation = true;
                });

            }`enter code here`

-7

Sau đây làm việc cho tôi;

 $(window).unload(function(event) {
    if(event.clientY < 0) {
        //do whatever you want when closing the window..
    }
 });

nó là một hàm jquery.
maxisam

7
Điều event.clientYnày là tiêu cực nếu bạn nhấp vào nút đóng trình duyệt hoặc nút đóng tab. Tuy nhiên, giá trị này là dương khi bạn tải lại trang bằng phím tắt (F5, Ctrl-R) hoặc đóng trình duyệt bằng cách sử dụng phím tắt bàn phím (ví dụ: Alt-F4). Do đó, bạn không thể dựa vào vị trí sự kiện để phân biệt sự kiện đóng trình duyệt với sự kiện tải lại trang.
Julien Kronegg
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.