Como mostrar a mensagem "Tem certeza de que deseja sair desta página?" quando as alterações foram confirmadas?

267

Aqui no stackoverflow, se você começou a fazer alterações e tenta sair da página, um botão de confirmação de javascript é exibido e pergunta: "Tem certeza de que deseja sair desta página?" blee blá bloo ...

Alguém já implementou isso antes, como faço para rastrear que as alterações foram confirmadas? Acredito que eu poderia fazer isso sozinho, estou tentando aprender as boas práticas de vocês, especialistas.

Eu tentei o seguinte, mas ainda não funciona:

<html>
<body>
    <p>Close the page to trigger the onunload event.</p>
    <script type="text/javascript">
        var changes = false;        
        window.onbeforeunload = function() {
            if (changes)
            {
                var message = "Are you sure you want to navigate away from this page?\n\nYou have started writing or editing a post.\n\nPress OK to continue or Cancel to stay on the current page.";
                if (confirm(message)) return true;
                else return false;
            }
        }
    </script>

    <input type='text' onchange='changes=true;'> </input>
</body>
</html>

Alguém pode postar um exemplo?

Shimmy Weitzhandler
fonte
3
Para fazer o seu exemplo funcionar, altere a função para: myFunction () {window.onbeforeunload = "message"; } altere a entrada: <input type = 'text' onchange = 'myFunction ();'> </input>
Keith
Relacionados: stackoverflow.com/q/821011/435605
AlikElzin-Kilaka

Respostas:

367

Atualização (2017)

Agora, os navegadores modernos consideram a exibição de uma mensagem personalizada um risco à segurança e, portanto, foi removida de todos eles. Os navegadores agora exibem apenas mensagens genéricas. Como não precisamos mais nos preocupar em definir a mensagem, é tão simples quanto:

// Enable navigation prompt
window.onbeforeunload = function() {
    return true;
};
// Remove navigation prompt
window.onbeforeunload = null;

Leia abaixo para obter suporte ao navegador herdado.

Atualização (2013)

A resposta original é adequada para IE6-8 e FX1-3.5 (que é o nosso objetivo em 2009 quando foi escrita), mas está desatualizada agora e não funcionará nos navegadores mais atuais - deixei abaixo para referência.

O window.onbeforeunloadnão é tratado de forma consistente por todos os navegadores. Deve ser uma referência de função e não uma string (como a resposta original afirmou), mas funcionará em navegadores mais antigos, porque a verificação para a maioria deles parece ser se alguma coisa está atribuída onbeforeunload(incluindo uma função que retorna null).

Você define window.onbeforeunloaduma referência de função, mas em navegadores antigos, você deve definir returnValueo evento em vez de retornar uma string:

var confirmOnPageExit = function (e) 
{
    // If we haven't been passed the event get the window.event
    e = e || window.event;

    var message = 'Any text will block the navigation and display a prompt';

    // For IE6-8 and Firefox prior to version 4
    if (e) 
    {
        e.returnValue = message;
    }

    // For Chrome, Safari, IE8+ and Opera 12+
    return message;
};

Você não pode confirmOnPageExitfazer isso , verifique e retorne nulo se desejar que o usuário continue sem a mensagem. Você ainda precisa remover o evento para ativá-lo e desativá-lo com segurança:

// Turn it on - assign the function that returns the string
window.onbeforeunload = confirmOnPageExit;

// Turn it off - remove the function entirely
window.onbeforeunload = null;

Resposta original (trabalhada em 2009)

Para ligar:

window.onbeforeunload = "Are you sure you want to leave?";

Para desativá-lo:

window.onbeforeunload = null;

Lembre-se de que este não é um evento normal - você não pode se vincular a ele da maneira padrão.

Para verificar valores? Isso depende da sua estrutura de validação.

No jQuery, isso pode ser algo como (exemplo muito básico):

$('input').change(function() {
    if( $(this).val() != "" )
        window.onbeforeunload = "Are you sure you want to leave?";
});
Keith
fonte
4
Isso seria algo como: $ ('input: text'). Change (function () {window.onbeforeunload = $ ('input: text [value! = ""]'). Length> 0? "Warning": null ;});
217 Keith
1
Para uma verificação simples, ou você pode adicionar validação mais complexo a cada mudança
Keith
1
vale a pena notar que o método 'returnValue' é o único método especificado no padrão; portanto, não é apenas para o IE6-8, é para todos os navegadores compatíveis com os padrões (neste caso, não incluindo Chrome, Safari e Opera).
rmcclellan
3
Para interromper o alerta no envio do formulário, eu usei $("#submit_button").click(function() { window.onbeforeunload = null; });. Originalmente, usei o evento onclick do botão, mas, além de não ser tão bom, também não funcionou com o IE8.
Andy Beverley
1
@ AlikElzin-kilaka você não pode. Se você deseja alterar o texto pop-up, é necessário criar seu próprio pop-up personalizado, mas isso não pode bloquear o window.onbeforeunloadevento.
Keith
38

O onbeforeunloadMicrosoft-ism é a coisa mais próxima que temos de uma solução padrão, mas esteja ciente de que o suporte ao navegador é desigual; por exemplo, para o Opera, ele funciona apenas na versão 12 e posterior (ainda em beta no momento em que este artigo foi escrito).

Além disso, para obter compatibilidade máxima , você precisa fazer mais do que simplesmente retornar uma string, conforme explicado na Mozilla Developer Network .

Exemplo: Defina as duas funções a seguir para ativar / desativar o prompt de navegação (veja o exemplo MDN):

function enableBeforeUnload() {
    window.onbeforeunload = function (e) {
        return "Discard changes?";
    };
}
function disableBeforeUnload() {
    window.onbeforeunload = null;
}

Em seguida, defina um formulário como este:

<form method="POST" action="" onsubmit="disableBeforeUnload();">
    <textarea name="text"
              onchange="enableBeforeUnload();"
              onkeyup="enableBeforeUnload();">
    </textarea>
    <button type="submit">Save</button>
</form>

Dessa forma, o usuário só será avisado sobre a navegação se tiver alterado a área de texto e não será avisado quando estiver enviando o formulário.

Søren Løvborg
fonte
1
Baseado no site da Mozill, a maioria dos browsers recentes agora apoiá-lo: developer.mozilla.org/en/DOM/window.onbeforeunload
Hengjie
Microsoft-ism é um ótimo termo.
Luke Taylor
18

Com o JQuery, essas coisas são muito fáceis de fazer. Desde que você pode ligar a conjuntos.

NÃO é suficiente para executar o onbeforeunload, você deseja acionar a navegação apenas se alguém começar a editar as coisas.

Sam Saffron
fonte
2
Não consigo acessar as postagens do @jonstjohn. Talvez ele seja um amigo e nos aponte na direção certa? : D
FLGMwt
14
=> 500 Erro interno. É por isso que os links são descontinuados no SO. Votou até ser consertado.
Loïc
Esta página não está disponível
Mateusz
2
Embora esse link possa responder à pergunta, é melhor incluir aqui as partes essenciais da resposta e fornecer o link para referência. As respostas somente para links podem se tornar inválidas se a página vinculada for alterada.
bwest
2
O link original de Jon St John foi quebrado, então eu o atualizei para a versão do Wayback Machine . O conteúdo do link pode ser encontrado copiada em muitos outros sites, mas eu acho que foi melhor para "preservar" o que Sam acrescentou
Alvaro Montoro
14

jquerys 'beforeunload' funcionou muito bem para mim

$(window).bind('beforeunload', function(){
    if( $('input').val() !== '' ){
        return "It looks like you have input you haven't submitted."
    }
});
Devon Peticolas
fonte
Bind foi preterido e uma nova versão do código semelhante a este pode ser visto nesta resposta: stackoverflow.com/a/1889450/908677
Elias Lofgren
12

para novas pessoas que procuram uma solução simples, tente o Areyousure.js

lawphotog
fonte
11

Essa é uma maneira fácil de apresentar a mensagem se houver dados inseridos no formulário e não mostrar a mensagem se o formulário for enviado:

$(function () {
    $("input, textarea, select").on("input change", function() {
        window.onbeforeunload = window.onbeforeunload || function (e) {
            return "You have unsaved changes.  Do you want to leave this page and lose your changes?";
        };
    });
    $("form").on("submit", function() {
        window.onbeforeunload = null;
    });
})
Carl G
fonte
8

Para expandir a resposta já surpreendente de Keith :

Mensagens de aviso personalizadas

Para permitir mensagens de aviso personalizadas, você pode agrupá-lo em uma função como esta:

function preventNavigation(message) {
    var confirmOnPageExit = function (e) {
        // If we haven't been passed the event get the window.event
        e = e || window.event;

        // For IE6-8 and Firefox prior to version 4
        if (e)
        {
            e.returnValue = message;
        }

        // For Chrome, Safari, IE8+ and Opera 12+
        return message;
    };
    window.onbeforeunload = confirmOnPageExit;
}

Em seguida, basta chamar essa função com sua mensagem personalizada:

preventNavigation("Baby, please don't go!!!");

Ativando a navegação novamente

Para reativar a navegação, tudo que você precisa fazer é definir window.onbeforeunloadcomo null. Aqui está, envolto em uma pequena função elegante que pode ser chamada em qualquer lugar:

function enableNavigation() {
    window.onbeforeunload = null;
}

Usando jQuery para vincular isso para formar elementos

Se estiver usando jQuery, isso pode ser facilmente vinculado a todos os elementos de um formulário como este:

$("#yourForm :input").change(function() {
    preventNavigation("You have not saved the form. Any \
        changes will be lost if you leave this page.");
});

Em seguida, para permitir o envio do formulário:

$("#yourForm").on("submit", function(event) {
    enableNavigation();
});

Formulários modificados dinamicamente:

preventNavigation()e enableNavigation()pode ser vinculado a quaisquer outras funções, conforme necessário, como modificar dinamicamente um formulário ou clicar em um botão que envia uma solicitação AJAX. Eu fiz isso adicionando um elemento de entrada oculto ao formulário:

<input id="dummy_input" type="hidden" />

Então, sempre que eu quiser impedir que o usuário navegue para longe, aciono a alteração nessa entrada para garantir que ela preventNavigation()seja executada:

function somethingThatModifiesAFormDynamically() {

    // Do something that modifies a form

    // ...
    $("#dummy_input").trigger("change");
    // ...
}
Mike
fonte
3

Aqui tente isso, funciona 100%

<html>
<body>
<script>
var warning = true;
window.onbeforeunload = function() {  
  if (warning) {  
    return "You have made changes on this page that you have not yet confirmed. If you navigate away from this page you will lose your unsaved changes";  
    }  
}

$('form').submit(function() {
   window.onbeforeunload = null;
});
</script>
</body>
</html>
Braydon
fonte
3

O padrão afirma que a solicitação pode ser controlada cancelando o evento beforeunload ou configurando o valor de retorno para um valor não nulo . Ele também afirma que os autores devem usar Event.preventDefault () em vez de returnValue, e a mensagem mostrada ao usuário não é personalizável .

A partir de 69.0.3497.92, o Chrome não atendia ao padrão. No entanto, há um relatório de bug arquivado e uma revisão está em andamento. O Chrome exige que returnValue seja definido por referência ao objeto de evento, não ao valor retornado pelo manipulador.

É de responsabilidade do autor acompanhar se foram feitas alterações; isso pode ser feito com uma variável ou garantindo que o evento seja tratado apenas quando necessário.

window.addEventListener('beforeunload', function (e) {
    // Cancel the event as stated by the standard.
    e.preventDefault();
    // Chrome requires returnValue to be set.
    e.returnValue = '';
});
    
window.location = 'about:blank';

Trevor Karjanis
fonte
2

Quando o usuário começa a fazer alterações no formulário, um sinalizador booleano será definido. Se o usuário tentar navegar para fora da página, verifique esse sinalizador no evento window.onunload . Se o sinalizador estiver definido, você mostra a mensagem retornando-a como uma sequência. Retornar a mensagem como uma string exibirá uma caixa de diálogo de confirmação contendo sua mensagem.

Se você estiver usando o ajax para confirmar as alterações, poderá definir o sinalizador para falsedepois que as alterações forem confirmadas (ou seja, no evento de sucesso do ajax).

Kirtan
fonte
1

Você pode adicionar um onchangeevento na área de texto (ou em qualquer outro campo) que defina uma variável em JS. Quando o usuário tenta fechar a página (window.onunload), você verifica o valor dessa variável e mostra o alerta de acordo.

Makram Saleh
fonte
1
Você não pode fazer isso - alerte confirmestá bloqueado durante window.onbeforeunloade window.onunload(pelo menos na versão do Chrome no meu PC, mas provavelmente também em todos os navegadores que suportam esses manipuladores).
Mark Amery
1

Com base em todas as respostas neste tópico, escrevi o seguinte código e funcionou para mim.

Se você tiver apenas algumas tags de entrada / área de texto que exijam a verificação de um evento onunload, poderá atribuir atributos de dados HTML5 como data-onunload="true"

por exemplo.

<input type="text" data-onunload="true" />
<textarea data-onunload="true"></textarea>

e o Javascript (jQuery) pode ficar assim:

$(document).ready(function(){
    window.onbeforeunload = function(e) {
        var returnFlag = false;
        $('textarea, input').each(function(){
            if($(this).attr('data-onunload') == 'true' && $(this).val() != '')
                returnFlag = true;
        });

        if(returnFlag)
            return "Sure you want to leave?";   
    };
});
Sagar Gala
fonte
2
Consulte também "Por alguns motivos, os navegadores baseados no Webkit não seguem as especificações da caixa de diálogo" na documentação de pré-descarregamento do MDN .
Arjan
1

aqui está o meu html

<!DOCTYPE HMTL>
<meta charset="UTF-8">
<html>
<head>
<title>Home</title>
<script type="text/javascript" src="script.js"></script>
</head>

 <body onload="myFunction()">
    <h1 id="belong">
        Welcome To My Home
    </h1>
    <p>
        <a id="replaceME" onclick="myFunction2(event)" href="https://www.ccis.edu">I am a student at Columbia College of Missouri.</a>
    </p>
</body>

E foi assim que fiz algo semelhante em javaScript

var myGlobalNameHolder ="";

function myFunction(){
var myString = prompt("Enter a name", "Name Goes Here");
    myGlobalNameHolder = myString;
    if (myString != null) {
        document.getElementById("replaceME").innerHTML =
        "Hello " + myString + ". Welcome to my site";

        document.getElementById("belong").innerHTML =
        "A place you belong";
    }   
}

// create a function to pass our event too
function myFunction2(event) {   
// variable to make our event short and sweet
var x=window.onbeforeunload;
// logic to make the confirm and alert boxes
if (confirm("Are you sure you want to leave my page?") == true) {
    x = alert("Thank you " + myGlobalNameHolder + " for visiting!");
}
}
Justin Stone
fonte
0

Isso pode ser feito facilmente, definindo um ChangeFlag como true, no evento onChange de TextArea . Use javascript para mostrar a caixa de diálogo de confirmação com base no valor ChangeFlag . Descarte o formulário e navegue para a página solicitada se a confirmação retornar verdadeira, caso contrário, não faça nada .

simplyharsh
fonte
-1

Existe um parâmetro "onunload" para a tag body, que você pode chamar de funções javascript a partir daí. Se retornar falso, impede a navegação.

stribika
fonte
13
Felizmente, isso realmente não funciona. Caso contrário, eu odiaria visitar uma página que contenha <body onunload="return false;">.
Søren Løvborg 13/07/2009