Evite cualquier forma de actualización de la página usando jQuery / Javascript

93

Una vez que el usuario está en mi página, no quiero que actualice la página.

  1. En cualquier momento, el usuario F5presiona o actualiza el botón en la parte superior. Debería recibir una alerta diciendo

    No puede actualizar la página.

  2. Además, si el usuario abre una nueva pestaña e intenta acceder a la misma URL en la pestaña anterior, debería recibir una alerta.

    No puede abrir la misma página en 2 pestañas

De todos modos, ¿puedo hacer esto usando JavaScript o jQuery? El punto uno es realmente importante.

pankaj
fuente
Puede detectar usando la API de Broadcast Channel ( developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API ) y enviar mensajes para comunicarse entre pestañas. ASÍ, al usar esto, puede detectar múltiples pestañas con la misma URL y bloquear otras pestañas.
aeXuser264

Respuestas:

195

# 1 se puede implementar a través de window.onbeforeunload.

Por ejemplo:

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

Se le pedirá al usuario el mensaje y se le dará la opción de permanecer en la página o continuar su camino. Esto es cada vez más común. Stack Overflow hace esto si intenta navegar fuera de una página mientras escribe una publicación. No puede evitar por completo que el usuario vuelva a cargar, pero puede hacer que suene realmente aterrador si lo hace.

# 2 es más o menos imposible. Incluso si realizó un seguimiento de las sesiones y los inicios de sesión de los usuarios, aún no podría garantizar que detectaba una segunda pestaña correctamente. Por ejemplo, tal vez tenga una ventana abierta y luego la cierre. Ahora abro una nueva ventana. Es probable que lo detecte como una segunda pestaña, aunque ya cerré la primera. Ahora su usuario no puede acceder a la primera ventana porque la cerró y no puede acceder a la segunda ventana porque usted se lo niega.

De hecho, el sistema en línea de mi banco se esfuerza mucho por hacer el n. ° 2, y la situación descrita anteriormente ocurre todo el tiempo. Por lo general, tengo que esperar hasta que expire la sesión del lado del servidor antes de poder usar el sistema bancario nuevamente.

Seth
fuente
1
Solo una nota que el evento onbeforeunload no está disponible en las versiones del navegador Opera.
WillyCornbread
1
¿Hay alguna forma de hacer algo si el usuario elige permanecer en la página?
riship89
5
Me hizo el truco, aunque debería usar window.addEventListener (consulte developer.mozilla.org/en-US/docs/Web/Events/beforeunload ) en su lugar, para la compatibilidad entre navegadores y para evitar problemas de biblioteca.
Julien Bérubé
Sé que esta pregunta es antigua pero, si realmente quisieran evitar múltiples sesiones, ¿podrían usar WebSockets?
Meghan
1
@Sean - Sí ... si realmente quisieras evitar múltiples sesiones. Un WebSocket puede realizar una comunicación bidireccional con estado. El cliente (probablemente) no se convertirá repentinamente en otra persona mientras WebSocket esté conectado, por lo que debería poder asignar un token a ese usuario y borrarlo una vez que se cierre el socket. Pero está pirateando el comportamiento esperado del agente de usuario, por lo que probablemente sea una mala experiencia de usuario. Puedo pensar en muy pocos casos en los que algo como esto sería apropiado (tal vez un juego en línea, para evitar que alguien inicie sesión como dos garras mortales de nivel 37 ...).
Seth
34

No puede evitar que el usuario se actualice, ni debería intentarlo. Debería volver a por qué necesita esta solución, ¿cuál es la raíz del problema aquí? Empiece por ahí y encuentre una forma diferente de resolver el problema. Tal vez, si explicó por qué cree que necesita hacer esto, podría ayudar a encontrar una solución de este tipo.

Romper las características fundamentales del navegador nunca es una buena idea, más del 99.999999999% de Internet funciona y se actualiza con F5, esta es una expectativa del usuario, una que no debes romper.

Nick Craver
fuente
El problema es que la página es una aplicación siebel. y cuando un usuario está en una sesión y pulsa actualizar, se crea una nueva sesión y la aplicación se bloquea. así que necesito que el usuario no pueda actualizar.
Pankaj
20
@pankaj: eso debe arreglarse en el sitio de la aplicación y las cookies, por ejemplo, para que el usuario comparta la sesión entre pestañas.
Nick Craver
9
No estoy seguro de dónde vienes de aquí. Innumerables sitios en Internet impiden la actualización del navegador si tiene un formulario sucio, lo que le advierte del hecho de que puede perder los cambios. No estoy seguro de por qué esto está "rompiendo las funciones fundamentales del navegador".
Siraris
1
@Siraris: Exactamente. Además, estoy creando una aplicación privada que se supone que el usuario puede usar incluso cuando no está en su red privada. Así que guardo todo en el almacenamiento del navegador para usarlo sin conexión, pero si vuelve a cargar la página, toda la aplicación desaparecerá. Puede que no sea muy "habitual", pero en este mundo moderno de TI lo será cada vez más.
cslotty
16

Aunque no es una buena idea deshabilitar la tecla F5, puede hacerlo en JQuery como se muestra a continuación.

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

Nilesh
fuente
28
¿Qué pasa con OSX, donde es CMD + R? ¿O móvil donde hay que presionar un botón? No veo esto como una solución
ItalyPaleAle
14

En los viejos tiempos de CGI teníamos muchas formas que desencadenarían varias acciones de backend. Como notificaciones de texto a grupos, trabajos de impresión, cultivo de datos, etc.

Si el usuario estaba en una página que decía "Por favor espere ... Realizando un trabajo ENORME que podría llevar algún tiempo" ¡Era más probable que pulsaran ACTUALIZAR y esto sería MALO!

¿POR QUÉ? Porque desencadenaría trabajos más lentos y eventualmente empantanaría todo.

¿La solución? Permítales hacer su forma. Cuando envíen su formulario ... Comience su trabajo y luego diríjalos a otra página que les diga que esperen.

Donde la página en el medio realmente contenía los datos del formulario que se necesitaban para comenzar el trabajo. Sin embargo, la página WAIT contiene una destrucción del historial de JavaScript. Para que puedan RECARGAR esa página de espera todo lo que quieran y nunca activará el trabajo original para que comience en segundo plano, ya que esa página de ESPERA solo contiene los datos del formulario necesarios para la ESPERA en sí.

Espero que tenga sentido.

La función de destrucción del historial también les impidió hacer clic en ATRÁS y luego actualizar también.

Fue muy fluido y funcionó muy bien durante MUCHOS MUCHOS años hasta que la organización sin fines de lucro se cerró.

Ejemplo: ENTRADA DE FORMULARIO: recopile toda su información y, cuando se envíe, esto activará su trabajo de backend.

RESPONSE from form entry - Devuelve HTML que realiza una redirección a su página de espera estática y / o POST / GET a otro formulario (la página WAIT).

PÁGINA DE ESPERA: solo contiene datos de FORMULARIO relacionados con la página de espera, así como javascript para destruir el historial más reciente. Me gusta (-1 O -2) para destruir solo las páginas más recientes, pero aún les permite volver a su página de entrada FORM original.

Una vez que estén en su página de ESPERA, pueden hacer clic en ACTUALIZAR tanto como quieran y nunca generará el trabajo de FORMULARIO original en el backend. En cambio, su página WAIT debe incluir una actualización programada META para que siempre pueda verificar el estado de su trabajo. Cuando se completa su trabajo, se les redirige fuera de la página de espera a donde desee.

Si lo hacen ACTUALIZAR manualmente ... Simplemente están agregando una verificación más del estado de su trabajo allí.

Espero que ayude. Buena suerte.

Todd
fuente
2
No obtuviste suficiente crédito por esta asombrosa e informativa respuesta. ¡¡Gracias!!
ShiningLight
3

El problema # 2 ahora se puede resolver usando BroadcastAPI .

Por el momento, solo está disponible en Chrome, Firefox y 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
fuente
2

El número (2) es posible mediante el uso de una implementación de socket (como websocket, socket.io, etc.) con un latido personalizado para cada sesión en la que participa el usuario. Si un usuario intenta abrir otra ventana, tiene una verificación del controlador de JavaScript con el servidor si está bien, y luego responda con un mensaje de error.

Sin embargo, una mejor solución es sincronizar las dos sesiones, si es posible, como en los documentos de Google.

seo
fuente