วิธีการจับภาพเหตุการณ์ปิดหน้าต่างเบราว์เซอร์?


149

ฉันต้องการจับภาพเหตุการณ์ปิดหน้าต่างแท็บ / เบราว์เซอร์ ฉันได้ลองทำสิ่งต่อไปนี้กับ jQuery:

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

แต่มันใช้ได้กับการส่งแบบฟอร์มด้วยซึ่งไม่ใช่สิ่งที่ฉันต้องการ ฉันต้องการเหตุการณ์ที่ก่อให้เกิดเฉพาะเมื่อผู้ใช้ปิดหน้าต่าง

คำตอบ:


212

beforeunloadเหตุการณ์ fires เมื่อใดก็ตามที่ผู้ใช้ออกจากหน้าเว็บของคุณด้วยเหตุผลใดก็ตาม

ตัวอย่างเช่นมันจะถูกไล่ออกหากผู้ใช้ส่งแบบฟอร์มคลิกที่ลิงค์ปิดหน้าต่าง (หรือแท็บ) หรือไปที่หน้าใหม่โดยใช้แถบที่อยู่ช่องค้นหาหรือที่คั่นหน้า

คุณสามารถยกเว้นการส่งแบบฟอร์มและการเชื่อมโยงหลายมิติ (ยกเว้นจากเฟรมอื่น ๆ ) ด้วยรหัสต่อไปนี้:

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

สำหรับ jQuery เวอร์ชั่นที่เก่ากว่า 1.7 ลองสิ่งนี้:

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

liveวิธีการไม่ได้ทำงานร่วมกับsubmitเหตุการณ์ดังนั้นหากคุณเพิ่มรูปแบบใหม่ที่คุณจะต้องผูกจัดการกับมันได้เป็นอย่างดี

โปรดทราบว่าหากตัวจัดการเหตุการณ์ที่แตกต่างกันยกเลิกการส่งหรือการนำทางคุณจะสูญเสียการแจ้งเตือนหากหน้าต่างปิดจริงในภายหลัง คุณสามารถแก้ไขได้โดยการบันทึกเวลาในsubmitและclickกิจกรรมและตรวจสอบว่าbeforeunloadเกิดขึ้นมากกว่าสองวินาทีในภายหลัง


8
ใช่ทำงานได้ดี! jquery เวอร์ชันใหม่รองรับ $ ('form'). live ('submit, function () {})
Venkat D.

4
ทางออกของคุณดี แต่ฉันจะยกเลิกกิจกรรมในกรณีที่รีเฟรชได้อย่างไร ฉันต้องการเหตุการณ์เฉพาะเมื่อเบราว์เซอร์ปิดไม่มีกรณีรีเฟรช
Refael

ดูเหมือนว่าเบราว์เซอร์จะแสดงค่าส่งคืนก่อนที่จะโหลดเป็นไดอะล็อกยืนยัน ดังนั้นฉันคิดว่าคำตอบนี้ถูกต้องมากขึ้น: link
tahagh

2
ไม่นี้รีเฟรชจับของหน้าโดยใช้Ctrl + r, F5, Ctrl + Shift + rและเปลี่ยน URL เบราว์เซอร์?
Arti

1
@Jonny: .on()ก็ตอนนี้เพียงแค่
SLAK

45

อาจแค่ผูกbeforeunloadตัวจัดการเหตุการณ์ไว้ในsubmitตัวจัดการเหตุการณ์ของฟอร์ม:

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

3
นี่ไม่ใช่เรื่องง่ายเลยที่จะไม่ใช้ jQuery โดยการระบุสิ่งนี้ในการกำหนดแท็กแบบฟอร์มใช่หรือไม่ `<form onsubmit = "window.onbeforeunload = null;">
กลัว

4
@awe แต่คุณต้องรวมมันonsubmit=...ไว้ในแต่ละรูปแบบ (ฉันมีหลายรูปแบบต่อหน้าในเว็บแอปหนึ่ง)
KajMagnus

16

สำหรับโซลูชันข้ามเบราว์เซอร์ (ทดสอบใน Chrome 21, IE9, FF15) ให้ลองใช้รหัสต่อไปนี้ซึ่งเป็นรหัส Slaks 'รุ่น tweaked เล็กน้อย:

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

โปรดทราบว่าตั้งแต่ Firefox 4 ข้อความ "คุณต้องการปิดจริงๆหรือไม่" ไม่ปรากฏ FF แสดงข้อความทั่วไป ดูโน้ตในhttps://developer.mozilla.org/en-US/docs/DOM/window.onbeforeunload


3
อันนี้ใช้ได้กับเบราว์เซอร์อย่างสม่ำเสมอ เพียงแค่บันทึกย่อ ฉันได้อัปเดตทั้งคำสั่งliveและbindคำสั่งเป็นonซึ่งใช้งานได้ดีกับ jQuery ระดับล่าสุด ขอบคุณ!
Sablefoste


4

สำหรับวิธีแก้ปัญหาที่ทำงานได้ดีกับการควบคุมของบุคคลที่สามเช่น Telerik (เช่น: RadComboBox) และ DevExpress ที่ใช้แท็ก Anchor ด้วยเหตุผลหลายประการให้พิจารณาใช้รหัสต่อไปนี้ซึ่งเป็นรหัส desm รุ่นที่ปรับแต่งเล็กน้อยด้วยตัวเลือกที่ดีกว่า กำหนดเป้าหมายแท็ก anchor:

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
คำตอบนี้ถูกต้อง แต่สำหรับผู้ที่มีปัญหากับเหตุการณ์นี้ที่เกิดขึ้นเมื่อคุณรีเฟรชเบราว์เซอร์เปลี่ยนของคุณถ้าเป็นรหัสต่อไปนี้: if (inFormOrLink! == undefined &&! inFormOrLink)
LeonPierre

4

คำตอบของฉันมีวัตถุประสงค์เพื่อให้การวัดผลที่ง่าย

ทำอย่างไร

ดูคำตอบ @SLaks

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

เบราว์เซอร์ใช้เวลานานเท่าใดจึงจะปิดหน้าเว็บในที่สุด

เมื่อใดก็ตามที่ผู้ใช้ปิดหน้า ( xปุ่มหรือCTRL+ W) เบราว์เซอร์รันbeforeunloadรหัสที่กำหนดแต่ไม่สิ้นสุด ข้อยกเว้นเดียวคือกล่องยืนยัน ( return 'Do you really want to close?) ซึ่งจะรอจนกว่าการตอบสนองของผู้ใช้

Chrome : 2 วินาที
Firefox : ∞ (หรือดับเบิลคลิกหรือบังคับปิด)
Edge : ∞ (หรือดับเบิลคลิก)
Explorer 11 : 0 วินาที
Safari : สิ่งที่ต้องทำ

สิ่งที่เราใช้ทดสอบสิ่งนี้:

  • เซิร์ฟเวอร์ Express ของ Node.js พร้อมบันทึกคำขอ
  • ไฟล์ HTML สั้น ๆ ดังต่อไปนี้

สิ่งที่ต้องทำคือส่งคำขอให้ได้มากที่สุดก่อนที่เบราว์เซอร์จะปิดหน้าเว็บ (พร้อมกัน)

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

การแสดงผลของ 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

ฉันใช้คำตอบ Slaks แต่ก็ไม่ได้ผลเหมือนเดิมเนื่องจาก onbeforeunload returnValue มีการแยกวิเคราะห์เป็นสตริงแล้วแสดงในกล่องยืนยันของเบราว์เซอร์ ดังนั้นค่าจริงจึงปรากฏเช่น "จริง"

เพียงแค่ใช้ผลงานคืน นี่คือรหัสของฉัน

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

บางทีคุณสามารถจัดการ OnSubmit และตั้งค่าสถานะที่คุณตรวจสอบในตัวจัดการ OnBeforeUnload ของคุณในภายหลัง



1

น่าเสียดายที่ไม่ว่าจะเป็นการโหลดการเปลี่ยนหน้าใหม่หรือปิดเบราว์เซอร์เหตุการณ์จะถูกเรียกใช้ อีกทางเลือกหนึ่งคือการจับ id ที่ทำให้เกิดเหตุการณ์และถ้ามันเป็นรูปแบบอย่าทริกเกอร์ฟังก์ชั่นใด ๆ และถ้ามันไม่ใช่ id ของแบบฟอร์มให้ทำสิ่งที่คุณต้องการจะทำเมื่อหน้าปิด ฉันไม่แน่ใจว่าเป็นไปได้โดยตรงหรือไม่และน่าเบื่อ

คุณสามารถทำสิ่งเล็ก ๆ น้อย ๆ ก่อนที่ลูกค้าจะปิดแท็บ จาวาสคริปต์ตรวจสอบแท็บปิดเบราว์เซอร์ / ปิดเบราว์เซอร์แต่ถ้ารายการการกระทำของคุณมีขนาดใหญ่และแท็บปิดก่อนที่จะเสร็จสิ้นคุณจะทำอะไรไม่ถูก คุณสามารถลองได้ แต่ด้วยประสบการณ์ของฉัน donot ขึ้นอยู่กับมัน

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/beforeunload?redirectlocale=en-US&redirectslug=DOM/Mozilla_event_reference/beforeunload


0

หากการส่งแบบฟอร์มของคุณนำพวกเขาไปยังอีกหน้าหนึ่ง (อย่างที่ฉันคิดว่ามันเป็นเช่นนั้นเนื่องจากการเรียกใช้beforeunload) คุณสามารถลองเปลี่ยนการส่งแบบฟอร์มของคุณเป็นการโทร ajax ด้วยวิธีนี้พวกเขาจะไม่ออกจากหน้าของคุณเมื่อพวกเขาส่งแบบฟอร์มและคุณสามารถใช้beforeunloadรหัสผูกพันตามที่คุณต้องการ


0

ปัญหาของฉัน: เหตุการณ์ 'onbeforeunload' จะถูกเรียกใช้เฉพาะในกรณีที่มีจำนวนการส่ง (คลิก) จำนวนคี่ ฉันมีการผสมผสานโซลูชันจากเธรดที่คล้ายกันใน SO เพื่อให้โซลูชันทำงานได้ ดีรหัสของฉันจะพูด

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

ตั้งแต่ jQuery 1.7 วิธีการ. live () เลิกใช้แล้ว ใช้. on () เพื่อแนบตัวจัดการเหตุการณ์ ผู้ใช้งาน jQuery เวอร์ชันเก่าควรใช้. delegate () ตามความต้องการของ. live ()

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

ที่สมบูรณ์หรือลิงค์

$(window).unbind();

0

ลองสิ่งนี้ด้วย

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

เพียงยืนยัน ...

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

มันไม่ทำงาน ในขณะที่เหตุการณ์การขนถ่าย (btw มันเกิดจากเอกสาร), window.closed === 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

ทำงานต่อไปสำหรับฉัน;

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

มันเป็นฟังก์ชั่น jquery
maxisam

7
event.clientYเป็นลบถ้าคุณคลิกที่ปุ่มเบราว์เซอร์ปิดหรือปุ่มปิดแท็บ อย่างไรก็ตามค่านี้เป็นค่าบวกเมื่อคุณโหลดหน้าเว็บอีกครั้งโดยใช้แป้นพิมพ์ลัด (F5, Ctrl-R) หรือปิดเบราว์เซอร์โดยใช้แป้นพิมพ์ลัด (เช่น Alt-F4) ดังนั้นคุณจึงไม่สามารถไว้วางใจตำแหน่งของเหตุการณ์ในการแยกแยะเหตุการณ์ปิดเบราว์เซอร์จากเหตุการณ์โหลดหน้าเว็บซ้ำ
Julien Kronegg
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.