Impedir qualquer forma de atualização de página usando jQuery / Javascript

92

Depois que o usuário está em minha página, não quero que ele atualize a página.

  1. A qualquer momento, o usuário F5pressiona ou atualiza o botão na parte superior. Ele deve receber um alerta dizendo

    Você não pode atualizar a página.

  2. Além disso, se o usuário abrir uma nova guia e tentar acessar a mesma url na guia anterior, ele deverá receber um alerta

    Você não pode abrir a mesma página em 2 guias

De qualquer forma, posso fazer isso usando JavaScript ou jQuery? O ponto um é muito importante.

pankaj
fonte
Você pode detectar usando Broadcast Channel API ( developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API ) e enviar msg para se comunicar entre as guias. ASSIM, usando isso, você pode detectar várias guias com o mesmo url e bloquear outras guias.
aXuser264

Respostas:

191

# 1 pode ser implementado via window.onbeforeunload.

Por exemplo:

<script type="text/javascript">
    window.onbeforeunload = function() {
        return "Dude, are you sure you want to leave? Think of the kittens!";
    }
</script>

O usuário receberá a mensagem e terá a opção de permanecer na página ou continuar seu caminho. Isso está se tornando mais comum. Stack Overflow faz isso se você tentar navegar para fora de uma página enquanto estiver digitando uma postagem. Você não pode impedir completamente o usuário de recarregar, mas pode fazer com que pareça muito assustador se o fizerem.

# 2 é mais ou menos impossível. Mesmo se você rastreasse sessões e logins de usuários, ainda não seria capaz de garantir que detectou uma segunda guia corretamente. Por exemplo, talvez eu tenha uma janela aberta e, em seguida, feche-a. Agora abro uma nova janela. Você provavelmente detectaria isso como uma segunda guia, embora eu já tenha fechado a primeira. Agora o seu usuário não pode acessar a primeira janela porque a fechou, e não pode acessar a segunda janela porque você está negando.

Na verdade, o sistema online do meu banco se esforça muito para fazer o nº 2, e a situação descrita acima acontece o tempo todo. Normalmente, tenho que esperar até que a sessão do lado do servidor expire para poder usar o sistema bancário novamente.

Seth
fonte
1
Apenas uma observação de que o evento onbeforeunload não está disponível nas versões do navegador Opera.
WillyCornbread de
1
Existe uma maneira de fazer algo se o usuário optar por permanecer na página.
riship89
5
Fez o truque para mim, embora você deva usar window.addEventListener (consulte developer.mozilla.org/en-US/docs/Web/Events/beforeunload ) em vez disso, para compatibilidade entre navegadores e para evitar problemas de biblioteca.
Julien Bérubé
Sei que essa pergunta é antiga, mas se eles realmente quisessem evitar várias sessões, poderiam usar WebSockets?
Meghan
1
@Sean - Sim ... se você realmente quiser evitar várias sessões. Um WebSocket pode fazer comunicação bidirecional com estado. O cliente (provavelmente) não se tornará outra pessoa repentinamente enquanto o WebSocket estiver conectado, então você deve ser capaz de atribuir um token a esse usuário e apagá-lo assim que o soquete for fechado. Mas, ele está hackeando o comportamento esperado do agente do usuário, então provavelmente é uma UX ruim. Posso pensar em pouquíssimos casos em que algo assim seria apropriado (talvez um jogo online - para evitar que alguém se logue como duas garras mortais de nível 37 ...).
Seth
35

Você não pode impedir que o usuário atualize, nem deveria realmente tentar. Você deve voltar para porque você precisa dessa solução, qual é a raiz do problema aqui ?. Comece por aí e encontre uma maneira diferente de resolver o problema. Talvez você explicasse por que acha que precisa fazer isso, isso ajudaria a encontrar essa solução.

Quebrar recursos fundamentais do navegador nunca é uma boa ideia, mais de 99,999999999% da Internet funciona e se atualiza com F5, essa é uma expectativa do usuário, que você não deve quebrar.

Nick Craver
fonte
O problema é que a página é um aplicativo Siebel. e quando um usuário está em uma sessão e clica em atualizar, uma nova sessão é criada e o aplicativo trava. então preciso que o usuário não consiga atualizar.
pankaj
20
@pankaj - Isso deve ser corrigido no site do aplicativo e nos cookies, por exemplo, para que o usuário compartilhe a sessão nas guias.
Nick Craver
9
Não tenho certeza de onde você está vindo aqui. Inúmeros sites na internet impedem a atualização do navegador se você tiver um formulário sujo, alertando-o para o fato de que você pode perder suas alterações. Não sei por que isso está "quebrando os recursos fundamentais do navegador".
Siraris
1
@Siraris: Exatamente. Além disso, estou criando um aplicativo privado que o usuário deve poder usar mesmo quando não está em sua rede privada. Então, eu guardo tudo no armazenamento do navegador para uso offline, mas se ele recarregar a página, todo o aplicativo desaparecerá. Pode não ser muito "normal", mas neste mundo de TI moderno será cada vez mais.
cslotty
16

Embora não seja uma boa ideia desabilitar a tecla F5, você pode fazer isso em JQuery como abaixo.

<script type="text/javascript">
function disableF5(e) { if ((e.which || e.keyCode) == 116 || (e.which || e.keyCode) == 82) e.preventDefault(); };

$(document).ready(function(){
     $(document).on("keydown", disableF5);
});
</script>

Espero que isso ajude!

Nilesh
fonte
27
E quanto ao OSX, onde está CMD + R? Ou celular onde há um botão para pressionar? Não vejo isso como uma solução
ItáliaPaleAle
14

Nos velhos tempos do CGI, tínhamos muitos formulários que acionavam várias ações de back-end. Como notificações de texto para grupos, trabalhos de impressão, coleta de dados, etc.

Se o usuário estava em uma página que dizia "Aguarde ... Executando um trabalho ENORME que pode levar algum tempo.". Era mais provável que acertassem em REFRESH e isso seria RUIM!

PORQUE? Porque isso desencadearia mais trabalhos lentos e, eventualmente, paralisaria a coisa toda.

A solução? Permita que eles façam sua forma. Quando eles enviarem o formulário ... Comece seu trabalho e direcione-os para outra página que os diga para esperar.

Onde a página do meio realmente continha os dados do formulário necessários para iniciar o trabalho. A página WAIT, entretanto, contém uma destruição do histórico do javascript. Assim, eles podem RECARREGAR aquela página de espera o quanto quiserem e nunca acionará o job original para iniciar em segundo plano, pois essa página ESPERA contém apenas os dados do formulário necessários para a ESPERA em si.

Espero que isso faça sentido.

A função de destruição do histórico também os impedia de clicar em VOLTAR e depois atualizar também.

Foi muito perfeito e funcionou muito bem por MUITOS MUITOS anos até que a organização sem fins lucrativos foi encerrada.

Exemplo: ENTRADA DE FORMULÁRIO - Colete todas as informações e, quando enviado, aciona seu trabalho de back-end.

RESPOSTA da entrada do formulário - Retorna HTML que executa um redirecionamento para sua página de espera estática e / ou POST / GET para outro formulário (a página ESPERA).

PÁGINA DE ESPERA - Contém apenas dados de FORMULÁRIO relacionados à página de espera, bem como javascript para destruir o histórico mais recente. Como (-1 OU -2) para destruir apenas as páginas mais recentes, mas ainda permite que elas voltem para a página de entrada do FORM original.

Assim que estiverem em sua página ESPERA, eles podem clicar em ATUALIZAR o quanto quiserem e isso nunca gerará o trabalho FORM original no backend. Em vez disso, sua página WAIT deve incluir uma atualização cronometrada META para que possa sempre verificar o status de seu trabalho. Quando o trabalho é concluído, eles são redirecionados da página de espera para onde você desejar.

Se eles atualizarem manualmente ... Eles estão simplesmente adicionando mais uma verificação do status do trabalho lá.

Espero que ajude. Boa sorte.

Todd
fonte
2
Você não recebeu crédito suficiente por esta resposta surpreendente e informativa. Obrigado!!
ShiningLight
2

O número (2) é possível usando uma implementação de soquete (como websocket, socket.io, etc.) com uma pulsação personalizada para cada sessão em que o usuário está envolvido. Se um usuário tentar abrir outra janela, você terá que verificar o gerenciador de javascript com o servidor se estiver ok e responder com uma mensagem de erro.

No entanto, uma solução melhor é sincronizar as duas sessões, se possível, como no Google Docs.

seo
fonte
2

O problema nº 2 agora pode ser resolvido usando BroadcastAPI .

No momento, ele está disponível apenas no Chrome, Firefox e Opera.

var bc = new BroadcastChannel('test_channel');

bc.onmessage = function (ev) { 
    if(ev.data && ev.data.url===window.location.href){
       alert('You cannot open the same page in 2 tabs');
    }
}

bc.postMessage(window.location.href);
RockLegend
fonte