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

149

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

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

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

khelll
источник

Ответы:

212

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

SLaks
источник
8
да, отлично работает! Более новые версии jquery поддерживают $ ('form'). Live ('submit, function () {}).
Венкат Д.
4
Ваше решение хорошо, но как мне отменить мероприятие в случае обновления? Я хочу, чтобы это событие происходило только в том случае, если браузер закрыт, обновления не было
Refael
Похоже, что браузер отображает возвращаемое значение beforeunload в качестве диалогового окна подтверждения. Поэтому я думаю, что этот ответ является более точным: ссылка
Tahagh
2
делает это ручка обновления страницы с помощью Ctrl + r, F5, Ctrl + Shift + rи изменение URL браузера?
Арти
1
@Jonny: теперь просто .on().
SLaks
45

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

jQuery('form').submit(function() {
    jQuery(window).unbind("beforeunload");
    ...
});
karim79
источник
3
Разве не так просто не использовать jQuery, указав это в определении тега формы? : `<Форма onsubmit = "window.onbeforeunload = NULL;">
благоговение
4
@awe Но вы должны включить это onsubmit=...в каждую форму. (У меня есть много форм на странице, в определенном веб-приложении)
KajMagnus
16

Для кросс-браузерного решения (протестированного в 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

ДЧС
источник
3
Этот работает последовательно через браузеры. Просто быстрая заметка; Я обновил liveи bindоператоры on, и операторы , что прекрасно работает с последним уровнем jQuery. Спасибо!
Саблефост
16
window.onbeforeunload = function () {
    return "Do you really want to close?";
};
Бехнам Мохаммади
источник
4

Для решения, которое хорошо работает со сторонними элементами управления, такими как 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;
});
PLT
источник
1
Этот ответ правильный, но для тех, у кого возникли проблемы с этим событием при обновлении браузера, измените свой if на следующий код: 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?), которое будет ждать ответа пользователя.

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

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

  • Сервер Node.js Express с журналом запросов
  • Следующий короткий 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.
zurfyx
источник
3

Я использовал ответ 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;
})
kapad
источник
1

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

i_am_jorf
источник
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

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

Вы можете сделать небольшие вещи, прежде чем клиент закроет вкладку. 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

Gary
источник
0

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

idrumgood
источник
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");
    }
  }
}
Brunno
источник
Не работает В данный момент происходит событие unload (кстати, оно запускается из документа), window.closed === false;
Сергей Павлович ака лазурное
-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). Таким образом, нельзя полагаться на положение события, чтобы отличать событие закрытия браузера от события перезагрузки страницы.
Жюльен Кронегг