Impedir que uma página da Web navegue para longe usando JavaScript

129

Como impedir que uma página da Web navegue para longe usando JavaScript?

Entusiasta de software
fonte
O que faz com que esta página navegue?
Niyaz 04/05/09
9
De acordo com a questão, JavaScript torna navegar longe ...
Shog9
@ Shog9, pode estar fechando a aba, fazendo com que ela se afaste. Meu dedo indicador ...
Bob Stein

Respostas:

159

O uso onunloadpermite exibir mensagens, mas não interrompe a navegação (porque é tarde demais). No entanto, o uso onbeforeunloadinterromperá a navegação:

window.onbeforeunload = function() {
  return "";
}

Nota: Uma cadeia vazia é retornada porque os navegadores mais recentes fornecem uma mensagem como "Quaisquer alterações não salvas serão perdidas" que não podem ser substituídas.

Em navegadores mais antigos, você pode especificar a mensagem a ser exibida no prompt:

window.onbeforeunload = function() {
  return "Are you sure you want to navigate away?";
}
Jimmie R. Houts
fonte
11
O navegador exibirá um prompt apropriado. Simplesmente usewindow.onbeforeunload = function() { return ""; }
KIM Taegyoon
Mas isso não basta. E quanto aos controles dentro do formulário? Eles também desencadeiam isso.
Fandango68
1
Navegadores modernos não permitem que você exiba uma mensagem personalizada no prompt, pois isso foi abusado por phishers e similares.
Flimm
Obrigado @Flimm, atualizei a resposta para que agora seja precisa nos navegadores atuais.
Jimmie R. Houts
@FlimmEu quero atualizar o status online do usuário quando os usuários online fecham a guia ou o navegador. Usei o código na solução, mas ele não funcionou. Existe uma solução para isso?
Nasimba 29/03
23

Ao contrário de outros métodos apresentados aqui, esse trecho de código não fará com que o navegador exiba um aviso perguntando ao usuário se ele deseja sair; em vez disso, explora a natureza do evento do DOM para redirecionar de volta à página atual (e, assim, cancelar a navegação) antes que o navegador possa descarregá-lo da memória.

Como ele funciona com um curto-circuito direto na navegação, não pode ser usado para impedir que a página seja fechada; no entanto, ele pode ser usado para desativar o bloqueio de quadros.

(function () {
    var location = window.document.location;

    var preventNavigation = function () {
        var originalHashValue = location.hash;

        window.setTimeout(function () {
            location.hash = 'preventNavigation' + ~~ (9999 * Math.random());
            location.hash = originalHashValue;
        }, 0);
    };

    window.addEventListener('beforeunload', preventNavigation, false);
    window.addEventListener('unload', preventNavigation, false);
})();

Isenção de responsabilidade: você nunca deve fazer isso. Se uma página tiver um código de quebra de quadros, respeite os desejos do autor.

anarquista
fonte
como show modal se o usuário quiser fechar o navegador (clique em fechar)? é mesmo?
15

Acabei com esta versão um pouco diferente:

var dirty = false;
window.onbeforeunload = function() {
    return dirty ? "If you leave this page you will lose your unsaved changes." : null;
}

Em outros lugares, defino o sinalizador sujo como verdadeiro quando o formulário fica sujo (ou, caso contrário, desejo impedir a navegação). Isso me permite controlar facilmente se o usuário recebe ou não o prompt Confirmar Navegação.

Com o texto na resposta selecionada, você verá avisos redundantes:

insira a descrição da imagem aqui

Perigo
fonte
3
No IE, se sujo for falso, uma string 'null' será mostrada. Apenas envolva-o dentro de uma instrução if. Veja: stackoverflow.com/questions/11793996/…
Jacob van Lingen
Concordou em @JacobvanLingen, essa seria a melhor resposta aqui e em outras três perguntas se terminasse em vez de nulo. (1) é condicional (2) menciona "sujo" o motivo legítimo mais comum para impedir a navegação e (3) possui uma captura de tela. undefined
Bob Stein
Isso funcionaria em todos os navegadores se terminasse com indefinido em vez de nulo?
Danger
9

O equivalente de uma maneira mais moderna e compatível com o navegador, usando as modernas APIs addEventListener.

window.addEventListener('beforeunload', (event) => {
  // Cancel the event as stated by the standard.
  event.preventDefault();
  // Chrome requires returnValue to be set.
  event.returnValue = '';
});

Fonte: https://developer.mozilla.org/pt-BR/docs/Web/Events/beforeunload

Paul Weber
fonte
1
Lembre-se de event.returnValue
usar letras
7

No exemplo de Ayman, retornando false, você impede que a janela / guia do navegador se feche.

window.onunload = function () {
  alert('You are trying to leave.');
  return false;
}
gabor
fonte
2
A menos que o navegador seja o Opera, que ignora o evento onunload se a guia / janela / programa estiver sendo fechada.
Powerlord
5

O equivalente à resposta aceita no jQuery 1.11:

$(window).on("beforeunload", function () {
    return "Please don't leave me!";
});

Exemplo JSFiddle

A resposta de altCognito usou o unloadevento, que acontece muito tarde para o JavaScript abortar a navegação.

BoffinBrain
fonte
3

Use onunload .

Para jQuery, acho que funciona assim:

$(window).unload(function() { 
  alert("Unloading"); 
  return falseIfYouWantToButBeCareful();
});
cgp
fonte
Retornando falsa não vai cancelar o descarregamento infelizmente - os unloadincêndios de evento quando o usuário é sair da página, ao contrário do beforeunloadque dispara apenas de antemão (e pode ser cancelada)
Jimbo
@altCognito: Você me deu uma boa idéia com falseIfYouWantToButBeCareful () Agora, posso evitar o pop-up padrão fornecido pelo IE ou FF. Mas, para o chrome, não está funcionando. Olhando para isso.
user367134
3

Essa mensagem de erro sugerida pode duplicar a mensagem de erro que o navegador já exibe. No chrome, as duas mensagens de erro semelhantes são exibidas uma após a outra na mesma janela.

No chrome, o texto exibido após a mensagem personalizada é: "Tem certeza de que deseja sair desta página?". No firefox, ele não exibe nossa mensagem de erro personalizada (mas ainda exibe a caixa de diálogo).

Uma mensagem de erro mais apropriada pode ser:

window.onbeforeunload = function() {
    return "If you leave this page, you will lose any unsaved changes.";
}

Ou no estilo stackoverflow: "Você começou a escrever ou editar uma postagem."

Curtis Yallop
fonte
2

Se você estiver pegando o botão voltar / avançar do navegador e não quiser sair, pode usar:

window.addEventListener('popstate', function() {
    if (window.location.origin !== 'http://example.com') {
        // Do something if not your domain
    } else if (window.location.href === 'http://example.com/sign-in/step-1') {
        window.history.go(2); // Skip the already-signed-in pages if the forward button was clicked
    } else if (window.location.href === 'http://example.com/sign-in/step-2') {
        window.history.go(-2); // Skip the already-signed-in pages if the back button was clicked
    } else {
        // Let it do its thing
    }
});

Caso contrário, você pode usar o evento beforeunload , mas a mensagem pode ou não funcionar em vários navegadores e requer a devolução de algo que força um prompt interno.

um pouco menos
fonte