Как захватить событие закрытия окна браузера?

Я хочу захватить событие закрытия окна / вкладки браузера. Я пробовал следующее с jQuery:

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

Но это работает и при отправке форм, а это не то, чего я хочу. Я хочу событие, которое срабатывает только тогда, когда пользователь закрывает окно.

17 ответов

Решение

beforeunload событие запускается всякий раз, когда пользователь покидает вашу страницу по любой причине.

Например, он будет запущен, если пользователь отправит форму, щелкнет ссылку, закроет окно (или вкладку) или перейдет на новую страницу с помощью адресной строки, поля поиска или закладки.

Вы можете исключить отправку формы и гиперссылки (кроме других фреймов) с помощью следующего кода:

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 случается больше чем пара секунд спустя.

Может быть, просто отвязать beforeunload обработчик событий внутри формы submit обработчик события:

jQuery('form').submit(function() {
    jQuery(window).unbind("beforeunload");
    ...
});
window.onbeforeunload = function () {
    return "Do you really want to close?";
};

Для кросс-браузерного решения (протестированного в Chrome 21, IE9, FF15) рассмотрите возможность использования следующего кода, который является слегка подправленной версией кода 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;
}); 

Обратите внимание, что начиная с Firefox 4 появляется сообщение "Вы действительно хотите закрыть?" не отображается FF просто отображает общее сообщение. См. Примечание в https://developer.mozilla.org/en-US/docs/DOM/window.onbeforeunload

Мой ответ нацелен на обеспечение простых ориентиров.

КАК

Смотрите ответ @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?) который будет ждать ответа пользователя.

Хром: 2 секунды.
Firefox: ∞ (или двойной щелчок, или принудительное закрытие)
Край: ∞ (или двойной щелчок)
Проводник 11: 0 секунд.
Сафари: ТОДО

Что мы использовали, чтобы проверить это:

  • Экспресс-сервер 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>

Хромированный выход:

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.

Для решения, которое хорошо работает со сторонними элементами управления, такими как Telerik (например, RadComboBox) и DevExpress, которые используют теги Anchor по разным причинам, рассмотрите возможность использования следующего кода, который является слегка подправленной версией кода desm с лучшим селектором для себя целевые теги привязки:

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

Я использовал ответ Slaks, но он не работал как есть, так как onbeforeunload returnValue анализируется как строка и затем отображается в окне подтверждения браузера. Таким образом, значение true отображалось, как "true".

Просто с помощью возврата сработало. Вот мой код

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

К сожалению, будь то перезагрузка, перенаправление новой страницы или закрытие браузера, событие будет запущено. Альтернативой является перехват идентификатора, инициирующего событие, и если это форма, не запускайте никакую функцию, а если это не идентификатор формы, делайте то, что вы хотите сделать, когда страница закрывается. Я не уверен, что это также возможно напрямую и утомительно.

Вы можете сделать небольшие вещи, прежде чем клиент закроет вкладку. JavaScript обнаруживает, что браузер закрывает вкладку / закрывает браузер, но если ваш список действий большой и вкладка закрывается до его завершения, вы беспомощны. Вы можете попробовать это, но мой опыт не зависит от этого.

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

Возможно, вы могли бы обработать OnSubmit и установить флаг, который вы позже отметите в своем обработчике OnBeforeUnload.

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

Начиная с jQuery 1.7, метод.live() устарел. Используйте.on(), чтобы присоединить обработчики событий. Пользователи старых версий jQuery должны использовать.delegate() вместо.live()

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

по полной или по ссылке

$(window).unbind();

Если ваша форма отправляет их на другую страницу (как я полагаю, это вызывает срабатывание beforeunload), вы можете попытаться изменить отправку формы на вызов ajax. Таким образом, они не покинут вашу страницу при отправке формы, и вы можете использовать beforeunload обязательный код, как вы хотите.

Моя проблема: событие "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');   
}
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`

Просто проверьте...

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

Попробуйте это также

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

Следующее сработало для меня;

 $(window).unload(function(event) {
    if(event.clientY < 0) {
        //do whatever you want when closing the window..
    }
 });
Другие вопросы по тегам