Como capturar o evento de fechamento da janela do navegador?


149

Quero capturar o evento de fechamento da janela / guia do navegador. Eu tentei o seguinte com jQuery:

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

Mas funciona também no envio de formulários, o que não é o que eu quero. Eu quero um evento que dispara apenas quando o usuário fecha a janela.

Respostas:


212

O beforeunloadevento é acionado sempre que o usuário sai da sua página por qualquer motivo.

Por exemplo, ele será acionado se o usuário enviar um formulário, clicar em um link, fechar a janela (ou guia) ou for para uma nova página usando a barra de endereços, a caixa de pesquisa ou um marcador.

Você pode excluir envios de formulários e hiperlinks (exceto de outros quadros) com o seguinte código:

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

Para versões do jQuery anteriores a 1.7, tente o seguinte:

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

O livemétodo não funciona com o submitevento, portanto, se você adicionar um novo formulário, precisará vincular o manipulador a ele também.

Observe que se um manipulador de eventos diferente cancelar o envio ou a navegação, você perderá o prompt de confirmação se a janela for fechada mais tarde. Você pode corrigir isso através da gravação do tempo nos submite clickeventos, e verificar se o beforeunloadacontece mais do que um par de segundos mais tarde.


8
sim, trabalhando muito bem! As versões mais recentes do jquery suportam $ ('form'). Live ('submit, function () {}).
Venkat D.

4
Sua solução é boa, mas como cancelo o evento em caso de atualização? Eu quero o evento apenas se o navegador estiver fechado, sem atualização
Refael 22/10

Parece que o navegador exibe o valor de retorno de beforeunload como uma caixa de diálogo de confirmação. Então eu acho que esta resposta é mais preciso: ligação
tahagh

2
faz esta atualização cabo de uma página usando Ctrl + r, F5, Ctrl + Shift + re alterando a URL do navegador?
Arti

1
@ Jonny: Agora é só .on().
SLaks

45

Talvez apenas desvincule o beforeunloadmanipulador de eventos no manipulador de eventos do formulário submit:

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

3
Não é tão fácil não usar o jQuery especificando isso na definição da tag do formulário? : `<Form onsubmit = "window.onbeforeunload = null;">
temor

4
@we Mas você precisaria incluir isso onsubmit=...em cada formulário. (I ter muitas formas por página, em uma determinada aplicação web)
KajMagnus

16

Para uma solução entre navegadores (testada no Chrome 21, IE9, FF15), considere usar o código a seguir, que é uma versão ligeiramente aprimorada do código de 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;
}); 

Observe que, desde o Firefox 4, a mensagem "Deseja realmente fechar?" não é exibido. FF apenas exibe uma mensagem genérica. Veja a nota em https://developer.mozilla.org/en-US/docs/DOM/window.onbeforeunload


3
Este funciona de forma consistente nos navegadores. Apenas uma nota rápida; Atualizei liveas bindinstruções e para on, o que funciona muito bem com o nível mais recente do jQuery. Obrigado!
Sablefoste 31/01


4

Para uma solução que funcionou bem com controles de terceiros, como Telerik (por exemplo: RadComboBox) e DevExpress que usam as tags Anchor por vários motivos, considere usar o código a seguir, que é uma versão ligeiramente aprimorada do código da desm com um seletor melhor para si próprio segmentação por tags âncora:

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
Esta resposta está correta, mas para aqueles que tiveram problemas com este evento que acontece quando você atualizar a mudança do navegador que seu caso com o seguinte código: if (inFormOrLink == indefinido && inFormOrLink!)
LeonPierre

4

Minha resposta tem como objetivo fornecer referências simples.

COMO

Veja a resposta @SLaks .

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

Quanto tempo o navegador leva para finalmente desligar sua página?

Sempre que um usuário fecha a página ( xbotão ou CTRL+ W), o navegador executa o beforeunloadcódigo fornecido , mas não por tempo indeterminado. A única exceção é a caixa de confirmação (return 'Do you really want to close? ) que aguardará a resposta do usuário.

Chrome : 2 segundos.
Firefox : ∞ (ou clique duas vezes ou force para fechar)
Borda : ∞ (ou clique duas vezes)
Explorer 11 : 0 segundos.
Safari : TODO

O que usamos para testar isso:

  • Um servidor Node.js Express com log de solicitações
  • O seguinte arquivo HTML curto

O que ele faz é enviar o maior número possível de solicitações antes que o navegador encerre sua página (de forma síncrona).

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

Saída do 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

Eu usei a resposta do Slaks, mas isso não estava funcionando como está, pois o onBeforeunload returnValue é analisado como uma sequência e exibido na caixa de confirmações do navegador. Portanto, o valor true foi exibido, como "true".

Apenas usando o retorno funcionou. Aqui está o meu código

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

Talvez você possa manipular o OnSubmit e definir um sinalizador que depois verifique no seu manipulador OnBeforeUnload.


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

Infelizmente, seja um recarregamento, um redirecionamento de nova página ou o fechamento do navegador, o evento será acionado. Uma alternativa é capturar o ID que aciona o evento e, se for o formulário, não aciona nenhuma função e, se não for o ID do formulário, faça o que você deseja fazer quando a página for fechada. Não tenho certeza se isso também é possível diretamente e é tedioso.

Você pode fazer algumas pequenas coisas antes que o cliente feche a guia. O javascript detecta a guia fechar o navegador / fechar o navegador, mas se a sua lista de ações for grande e a guia fechar antes de terminar, você estará desamparado. Você pode experimentá-lo, mas com a minha experiência, não depende disso.

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

Se o envio do formulário os levar para outra página (como suponho que seja, daí o acionamento de beforeunload), você poderá tentar alterar o envio do formulário para uma chamada ajax. Dessa forma, eles não sairão da página quando enviarem o formulário e você poderá usar o beforeunloadcódigo de ligação conforme desejar.


0

Meu problema: o evento 'onbeforeunload' seria acionado apenas se houvesse um número ímpar de envios (cliques). Eu tive uma combinação de soluções de threads semelhantes no SO para que minha solução funcionasse. bem, meu código falará.

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

A partir do jQuery 1.7, o método .live () está obsoleto. Use .on () para anexar manipuladores de eventos. Usuários de versões mais antigas do jQuery devem usar .delegate () em vez de .live ()

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

no link completo ou

$(window).unbind();

0

Tente isso também

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

Basta verificar ...

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

Isso não funciona. No momento em que o evento descarregar é acionado (btw, é acionado a partir do documento), o window.closed === false;
Sergey P. tcp 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

Seguir trabalhou para mim;

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

é uma função jquery.
Maxisam

7
O valor event.clientYé negativo se você clicar no botão Fechar do navegador ou no botão Fechar da guia. No entanto, esse valor é positivo quando você recarrega a página usando atalhos de teclado (F5, Ctrl-R) ou fecha o navegador usando atalhos de teclado (por exemplo, Alt-F4). Portanto, você não pode confiar na posição do evento para diferenciar o evento de fechamento do navegador do evento de recarregamento da página.
Julien Kronegg
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.