Evitar que una página web navegue usando JavaScript

Respuestas:

159

El uso le onunloadpermite mostrar mensajes, pero no interrumpirá la navegación (porque es demasiado tarde). Sin embargo, el uso onbeforeunloadinterrumpirá la navegación:

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

Nota: se devuelve una cadena vacía porque los navegadores más nuevos proporcionan un mensaje como "Cualquier cambio no guardado se perderá" que no se puede anular.

En navegadores más antiguos, puede especificar el mensaje que se mostrará en la solicitud:

window.onbeforeunload = function() {
  return "Are you sure you want to navigate away?";
}
Jimmie R. Houts
fuente
11
El navegador mostrará un aviso apropiado. Simplemente usewindow.onbeforeunload = function() { return ""; }
KIM Taegyoon
Pero eso no es suficiente. ¿Qué pasa con los controles dentro del formulario? También desencadenan esto.
Fandango68
1
Los navegadores modernos no le permiten mostrar un mensaje personalizado en la solicitud, ya que esto fue abusado por phishers y similares.
Flimm
Gracias @Flimm, he actualizado la respuesta, por lo que ahora es precisa para los navegadores actuales.
Jimmie R. Houts
@FlimmQuiero actualizar el estado en línea del usuario cuando los usuarios en línea cierran la pestaña o el navegador del navegador. Utilicé el código en la solución pero no funcionó. ¿Hay alguna solución para esto?
Nasimba
23

A diferencia de otros métodos presentados aquí, este bit de código no hará que el navegador muestre una advertencia preguntándole al usuario si quiere irse; en su lugar, explota la naturaleza del DOM para redirigirlo a la página actual (y así cancelar la navegación) antes de que el navegador tenga la oportunidad de descargarlo de la memoria.

Dado que funciona haciendo un cortocircuito en la navegación directamente, no se puede usar para evitar que la página se cierre; sin embargo, se puede usar para deshabilitar el frame-busting.

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

Descargo de responsabilidad: nunca debe hacer esto. Si una página tiene un código que rompe marcos, respete los deseos del autor.

anarcocurioso
fuente
¿Cómo se muestra modal si el usuario desea cerrar el navegador (haga clic en cerrar)? ¿Realmente?
15

Terminé con esta versión ligeramente diferente:

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

En otro lugar, configuro la bandera sucia como verdadera cuando el formulario se ensucia (o de lo contrario quiero evitar navegar). Esto me permite controlar fácilmente si el usuario recibe o no el mensaje Confirmar navegación.

Con el texto en la respuesta seleccionada, verá mensajes redundantes:

ingrese la descripción de la imagen aquí

Peligro
fuente
3
En IE, si dirty es falso, se mostrará una cadena 'nulo'. Simplemente envuélvalo dentro de una declaración if. Ver: stackoverflow.com/questions/11793996/…
Jacob van Lingen el
De acuerdo @JacobvanLingen, esta sería la mejor respuesta aquí y en otras tres preguntas si terminara en lugar de nulo. (1) es condicional (2) menciona "sucio" la razón legítima más común para impedir la navegación y (3) tiene una captura de pantalla. undefined
Bob Stein
¿Funcionaría esto en todos los navegadores si terminara con indefinido en lugar de nulo?
Peligro
9

El equivalente de una manera más moderna y compatible con el navegador, utilizando las modernas API addEventListener.

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

Fuente: https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload

Paul Weber
fuente
1
Recuerde capitalizar correctamenteevent.returnValue
Flimm
7

En el ejemplo de Ayman al devolver falso, evita que la ventana / pestaña del navegador se cierre.

window.onunload = function () {
  alert('You are trying to leave.');
  return false;
}
gabor
fuente
2
A menos que el navegador sea Opera, que omite el evento de descarga si la pestaña / ventana / programa se está cerrando.
Powerlord
5

El equivalente a la respuesta aceptada en jQuery 1.11:

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

JSFiddle ejemplo

La respuesta de altCognito utilizó el unloadevento, que ocurre demasiado tarde para que JavaScript anule la navegación.

BoffinBrain
fuente
3

Use onunload .

Para jQuery, creo que esto funciona así:

$(window).unload(function() { 
  alert("Unloading"); 
  return falseIfYouWantToButBeCareful();
});
cgp
fuente
La devolución de falso no cancelará la descarga desafortunadamente: el unloadevento se dispara cuando el usuario abandona la página, a diferencia de lo beforeunloadque se dispara de antemano (y puede cancelarse)
Jimbo
@altCognito: Me diste una buena idea con falseIfYouWantToButBeCareful () Ahora puedo evitar la ventana emergente predeterminada dada por IE o FF. Pero para Chrome no está funcionando. Buscando dentro.
user367134
3

Ese mensaje de error sugerido puede duplicar el mensaje de error que el navegador ya muestra. En Chrome, los 2 mensajes de error similares se muestran uno tras otro en la misma ventana.

En Chrome, el texto que se muestra después del mensaje personalizado es: "¿Está seguro de que desea abandonar esta página?". En firefox, no muestra nuestro mensaje de error personalizado (pero aún muestra el cuadro de diálogo).

Un mensaje de error más apropiado podría ser:

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

O estilo stackoverflow: "Has comenzado a escribir o editar una publicación".

Curtis Yallop
fuente
2

Si está capturando un botón de retroceso / avance del navegador y no desea navegar, puede 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
    }
});

De lo contrario, puede usar el evento beforeunload , pero el mensaje puede o no funcionar en varios navegadores, y requiere que se devuelva algo que fuerce una solicitud integrada.

un poco menos
fuente