Empêcher la navigation d'une page Web à l'aide de JavaScript

129

Comment empêcher une page Web de s'éloigner en utilisant JavaScript?

Passionné de logiciels
la source
Qu'est-ce qui fait que cette page s'éloigne?
Niyaz
9
Selon la question, JavaScript le fait naviguer loin ...
Shog9
@ Shog9, il se peut que la fermeture de l'onglet le fasse naviguer. My index finger did tha ...
Bob Stein

Réponses:

159

L'utilisation onunloadvous permet d'afficher des messages, mais n'interrompt pas la navigation (car il est trop tard). Cependant, l'utilisation onbeforeunloadinterrompra la navigation:

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

Remarque: Une chaîne vide est renvoyée car les navigateurs plus récents fournissent un message tel que "Toutes les modifications non enregistrées seront perdues" qui ne peut pas être remplacé.

Dans les anciens navigateurs, vous pouviez spécifier le message à afficher dans l'invite:

window.onbeforeunload = function() {
  return "Are you sure you want to navigate away?";
}
Jimmie R. Houts
la source
11
Le navigateur affichera une invite appropriée. Simplement utiliserwindow.onbeforeunload = function() { return ""; }
KIM Taegyoon
Mais cela ne suffit pas. Qu'en est-il des contrôles à l'intérieur du formulaire? Ils déclenchent cela aussi.
Fandango68
1
Les navigateurs modernes ne vous permettent pas d'afficher un message personnalisé dans l'invite, car cela a été abusé par des hameçonneurs et autres.
Flimm
Merci @Flimm, j'ai mis à jour la réponse afin qu'elle soit maintenant précise pour les navigateurs actuels.
Jimmie R. Houts
@FlimmJe souhaite mettre à jour le statut de l'utilisateur en ligne lorsque les utilisateurs en ligne ferment l'onglet du navigateur ou le navigateur.J'ai utilisé le code dans la solution mais cela n'a pas fonctionné.Y a-t-il une solution pour cela?
Nasimba
23

Contrairement aux autres méthodes présentées ici, ce bit de code ne fera pas afficher au navigateur un avertissement demandant à l'utilisateur s'il veut partir; au lieu de cela, il exploite la nature événementielle du DOM pour rediriger vers la page actuelle (et donc annuler la navigation) avant que le navigateur n'ait une chance de la décharger de la mémoire.

Comme il fonctionne en court-circuitant directement la navigation, il ne peut pas être utilisé pour empêcher la fermeture de la page; cependant, il peut être utilisé pour désactiver le contournement d'images.

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

Avertissement: vous ne devriez jamais faire cela. Si une page contient du code de contournement de cadre, veuillez respecter les souhaits de l'auteur.

anarchocurieux
la source
comment afficher modal si l'utilisateur veut fermer le navigateur (cliquez sur fermer)? vraiment?
15

J'ai fini avec cette version légèrement différente:

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

Ailleurs, je règle le drapeau sale sur true lorsque le formulaire est sali (ou je veux autrement empêcher la navigation). Cela me permet de contrôler facilement si l'utilisateur reçoit ou non l'invite Confirmer la navigation.

Avec le texte de la réponse sélectionnée, vous voyez des invites redondantes:

entrez la description de l'image ici

Danger
la source
3
Dans IE, si dirty est false, une chaîne «null» sera affichée. Enveloppez-le simplement dans une instruction if. Voir: stackoverflow.com/questions/11793996/…
Jacob van Lingen
D'accord @JacobvanLingen, ce serait la meilleure réponse ici et sur trois autres questions si elle se terminait par au undefinedlieu de null. (1) c'est conditionnel (2) il mentionne "sale" la raison légitime la plus courante pour empêcher la navigation et (3) il a une capture d'écran.
Bob Stein
Cela fonctionnerait-il sur tous les navigateurs s'il se terminait par undefined plutôt que null?
Danger
9

L'équivalent d'une manière plus moderne et compatible avec les navigateurs, en utilisant les API addEventListener modernes.

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

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

Paul Weber
la source
1
N'oubliez pas de capitaliser correctementevent.returnValue
Flimm
7

Dans l'exemple d'Ayman, en retournant false, vous empêchez la fenêtre / l'onglet du navigateur de se fermer.

window.onunload = function () {
  alert('You are trying to leave.');
  return false;
}
gabor
la source
2
Sauf si le navigateur est Opera, qui ignore l'événement onunload si l'onglet / la fenêtre / le programme est en cours de fermeture.
Powerlord
5

L'équivalent de la réponse acceptée dans jQuery 1.11:

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

Exemple JSFiddle

La réponse de altCognito a utilisé l' unloadévénement, ce qui arrive trop tard pour que JavaScript abandonne la navigation.

BoffinBrain
la source
3

Utilisez onunload .

Pour jQuery, je pense que cela fonctionne comme ceci:

$(window).unload(function() { 
  alert("Unloading"); 
  return falseIfYouWantToButBeCareful();
});
cgp
la source
Renvoyer false n'annulera malheureusement pas le déchargement - l' unloadévénement se déclenche lorsque l'utilisateur quitte la page, contrairement à beforeunloadce qui se déclenche juste avant (et peut être annulé)
Jimbo
@altCognito: Vous m'avez donné une bonne idée avec falseIfYouWantToButBeCareful () Maintenant, je peux éviter le pop-up par défaut donné par IE ou FF. Mais pour le chrome, cela ne fonctionne pas. Regardant dedans.
user367134
3

Ce message d'erreur suggéré peut dupliquer le message d'erreur que le navigateur affiche déjà. Dans Chrome, les 2 messages d'erreur similaires s'affichent l'un après l'autre dans la même fenêtre.

Dans Chrome, le texte affiché après le message personnalisé est: "Êtes-vous sûr de vouloir quitter cette page?". Dans Firefox, il n'affiche pas du tout notre message d'erreur personnalisé (mais affiche toujours la boîte de dialogue).

Un message d'erreur plus approprié pourrait être:

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

Ou style stackoverflow: "Vous avez commencé à écrire ou modifier un article."

Curtis Yallop
la source
2

Si vous attrapez un bouton Précédent / Suivant du navigateur et que vous ne voulez pas vous en éloigner, vous pouvez utiliser:

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

Sinon, vous pouvez utiliser l' événement beforeunload , mais le message peut ou non fonctionner dans plusieurs navigateurs et nécessite le renvoi de quelque chose qui force une invite intégrée.

un peu moins
la source