Comment afficher le message "Êtes-vous sûr de vouloir quitter cette page?" quand des changements sont-ils engagés?

267

Ici, dans stackoverflow, si vous avez commencé à apporter des modifications, vous essayez de quitter la page, un bouton de confirmation javascript apparaît et vous demande: "Êtes-vous sûr de vouloir quitter cette page?" blee blah bloo ...

Quelqu'un a-t-il déjà implémenté cela, comment puis-je suivre que les modifications ont été validées? Je crois que je pourrais le faire moi-même, j'essaie d'apprendre les bonnes pratiques de vous les experts.

J'ai essayé ce qui suit mais ne fonctionne toujours pas:

<html>
<body>
    <p>Close the page to trigger the onunload event.</p>
    <script type="text/javascript">
        var changes = false;        
        window.onbeforeunload = function() {
            if (changes)
            {
                var message = "Are you sure you want to navigate away from this page?\n\nYou have started writing or editing a post.\n\nPress OK to continue or Cancel to stay on the current page.";
                if (confirm(message)) return true;
                else return false;
            }
        }
    </script>

    <input type='text' onchange='changes=true;'> </input>
</body>
</html>

Quelqu'un peut-il poster un exemple?

Shimmy Weitzhandler
la source
3
Pour que votre exemple fonctionne, changez la fonction en: myFunction () {window.onbeforeunload = "message"; } puis modifiez l'entrée: <input type = 'text' onchange = 'myFunction ();'> </input>
Keith
EN RELATION

Réponses:

367

Mise à jour (2017)

Les navigateurs modernes considèrent désormais l'affichage d'un message personnalisé comme un risque pour la sécurité et il a donc été supprimé de tous. Les navigateurs affichent désormais uniquement les messages génériques. Puisque nous n'avons plus à nous soucier de définir le message, c'est aussi simple que:

// Enable navigation prompt
window.onbeforeunload = function() {
    return true;
};
// Remove navigation prompt
window.onbeforeunload = null;

Lisez ci-dessous pour la prise en charge du navigateur existant.

Mise à jour (2013)

La réponse originale convient à IE6-8 et FX1-3.5 (qui était ce que nous visions en 2009 quand elle a été écrite), mais est plutôt obsolète maintenant et ne fonctionnera pas dans la plupart des navigateurs actuels - je suis parti ci-dessous pour référence.

Le window.onbeforeunloadn'est pas traité de manière cohérente par tous les navigateurs. Il devrait s'agir d'une référence de fonction et non d'une chaîne (comme indiqué dans la réponse d'origine), mais cela fonctionnera dans les anciens navigateurs, car la plupart d'entre eux semblent vérifier si quelque chose est attribué onbeforeunload(y compris une fonction qui renvoienull ).

Vous définissez window.onbeforeunloadune référence de fonction, mais dans les navigateurs plus anciens, vous devez définir returnValuel'événement au lieu de simplement renvoyer une chaîne:

var confirmOnPageExit = function (e) 
{
    // If we haven't been passed the event get the window.event
    e = e || window.event;

    var message = 'Any text will block the navigation and display a prompt';

    // For IE6-8 and Firefox prior to version 4
    if (e) 
    {
        e.returnValue = message;
    }

    // For Chrome, Safari, IE8+ and Opera 12+
    return message;
};

Vous ne pouvez pas faire confirmOnPageExiteffectuer la vérification et retourner null si vous voulez que l'utilisateur continue sans le message. Vous devez toujours supprimer l'événement pour l'activer et le désactiver de manière fiable:

// Turn it on - assign the function that returns the string
window.onbeforeunload = confirmOnPageExit;

// Turn it off - remove the function entirely
window.onbeforeunload = null;

Réponse originale (travaillé en 2009)

Pour l'allumer:

window.onbeforeunload = "Are you sure you want to leave?";

Pour le désactiver:

window.onbeforeunload = null;

Gardez à l'esprit que ce n'est pas un événement normal - vous ne pouvez pas vous y lier de manière standard.

Pour vérifier les valeurs? Cela dépend de votre cadre de validation.

Dans jQuery, cela pourrait être quelque chose comme (exemple très basique):

$('input').change(function() {
    if( $(this).val() != "" )
        window.onbeforeunload = "Are you sure you want to leave?";
});
Keith
la source
4
Ce serait quelque chose comme: $ ('input: text'). Change (function () {window.onbeforeunload = $ ('input: text [value! = ""]'). Length> 0? "Warning": null ;});
Keith
1
Pour une vérification simple, ou vous pouvez ajouter une validation plus complexe à chaque changement
Keith
1
il convient de noter que la méthode `` returnValue '' est la seule méthode spécifiée dans la norme, donc ce n'est pas seulement pour IE6-8, c'est pour tous les navigateurs conformes aux normes (dans ce cas, à l'exception de Chrome, Safari et Opera).
rmcclellan
3
Pour arrêter l'alerte lors de la soumission du formulaire, j'ai utilisé $("#submit_button").click(function() { window.onbeforeunload = null; });. À l'origine, j'ai utilisé l'événement onclick du bouton, mais en plus d'être moins agréable, cela ne fonctionnait pas non plus avec IE8.
Andy Beverley du
1
@ AlikElzin-kilaka vous ne pouvez pas. Si vous souhaitez modifier le texte de la fenêtre contextuelle, vous devez créer votre propre fenêtre contextuelle personnalisée, mais cela ne peut pas bloquer l' window.onbeforeunloadévénement.
Keith
38

Le onbeforeunloadMicrosoft-isme est la chose la plus proche que nous ayons d'une solution standard, mais sachez que la prise en charge du navigateur est inégale; Par exemple, pour Opera, cela ne fonctionne que dans la version 12 et les versions ultérieures (toujours en version bêta au moment de la rédaction).

De plus, pour une compatibilité maximale , vous devez faire plus que simplement renvoyer une chaîne, comme expliqué sur le Mozilla Developer Network .

Exemple: Définissez les deux fonctions suivantes pour activer / désactiver l'invite de navigation (cf. l'exemple MDN):

function enableBeforeUnload() {
    window.onbeforeunload = function (e) {
        return "Discard changes?";
    };
}
function disableBeforeUnload() {
    window.onbeforeunload = null;
}

Définissez ensuite un formulaire comme celui-ci:

<form method="POST" action="" onsubmit="disableBeforeUnload();">
    <textarea name="text"
              onchange="enableBeforeUnload();"
              onkeyup="enableBeforeUnload();">
    </textarea>
    <button type="submit">Save</button>
</form>

De cette façon, l'utilisateur ne sera averti de la navigation que s'il a modifié la zone de texte et ne sera pas invité lorsqu'il soumettra le formulaire.

Søren Løvborg
la source
1
Basé sur le site de Mozill, les navigateurs de bureau les plus récents le prennent désormais en charge: developer.mozilla.org/en/DOM/window.onbeforeunload
Hengjie
Microsoft-isme est un excellent terme.
Luke Taylor
18

Avec JQuery ce truc est assez facile à faire. Puisque vous pouvez vous lier à des ensembles.

Ce n'est PAS suffisant pour faire le onbeforeunload, vous voulez seulement déclencher la navigation si quelqu'un a commencé à éditer des trucs.

Sam Saffron
la source
2
Je n'arrive pas à toucher les articles de blog de @jonstjohn. Peut-être qu'il sera un copain et nous orientera dans la bonne direction? : D
FLGMwt
14
=> 500 Erreur interne. C'est pourquoi les liens sont déconseillés sur SO. Voté jusqu'à ce qu'il soit corrigé.
Loïc
Cette page Web n'est pas disponible
Mateusz
2
Bien que ce lien puisse répondre à la question, il est préférable d'inclure les parties essentielles de la réponse ici et de fournir le lien de référence. Les réponses de lien uniquement peuvent devenir invalides si la page liée change.
bwest
2
Le lien d'origine de Jon St John a été rompu, donc je l'ai mis à jour vers la version Wayback Machine de celui-ci. Le contenu du lien peut être trouvé copié sur de nombreux autres sites, mais je suppose qu'il valait mieux "préserver" celui que Sam a ajouté
Alvaro Montoro
14

'beforeunload' de jquerys a très bien fonctionné pour moi

$(window).bind('beforeunload', function(){
    if( $('input').val() !== '' ){
        return "It looks like you have input you haven't submitted."
    }
});
Devon Peticolas
la source
Bind a été déconseillé et une version plus récente du code similaire à celle-ci peut être vue dans cette réponse: stackoverflow.com/a/1889450/908677
Elijah Lofgren
12

pour les nouvelles personnes qui recherchent une solution simple, essayez simplement Areyousure.js

lawphotog
la source
11

C'est un moyen simple de présenter le message si des données sont entrées dans le formulaire, et de ne pas afficher le message si le formulaire est envoyé:

$(function () {
    $("input, textarea, select").on("input change", function() {
        window.onbeforeunload = window.onbeforeunload || function (e) {
            return "You have unsaved changes.  Do you want to leave this page and lose your changes?";
        };
    });
    $("form").on("submit", function() {
        window.onbeforeunload = null;
    });
})
Carl G
la source
8

Pour développer la réponse déjà étonnante de Keith :

Messages d'avertissement personnalisés

Pour autoriser les messages d'avertissement personnalisés, vous pouvez l'encapsuler dans une fonction comme celle-ci:

function preventNavigation(message) {
    var confirmOnPageExit = function (e) {
        // If we haven't been passed the event get the window.event
        e = e || window.event;

        // For IE6-8 and Firefox prior to version 4
        if (e)
        {
            e.returnValue = message;
        }

        // For Chrome, Safari, IE8+ and Opera 12+
        return message;
    };
    window.onbeforeunload = confirmOnPageExit;
}

Appelez ensuite cette fonction avec votre message personnalisé:

preventNavigation("Baby, please don't go!!!");

Réactiver la navigation

Pour réactiver la navigation, il vous suffit de définir window.onbeforeunloadsur null. Le voici, enveloppé dans une petite fonction soignée qui peut être appelée n'importe où:

function enableNavigation() {
    window.onbeforeunload = null;
}

Utilisation de jQuery pour le lier à des éléments de formulaire

Si vous utilisez jQuery, cela peut facilement être lié à tous les éléments d'un formulaire comme celui-ci:

$("#yourForm :input").change(function() {
    preventNavigation("You have not saved the form. Any \
        changes will be lost if you leave this page.");
});

Ensuite, pour permettre la soumission du formulaire:

$("#yourForm").on("submit", function(event) {
    enableNavigation();
});

Formes modifiées dynamiquement:

preventNavigation()et enableNavigation()peut être lié à toutes les autres fonctions selon les besoins, telles que la modification dynamique d'un formulaire, ou en cliquant sur un bouton qui envoie une demande AJAX. Je l'ai fait en ajoutant un élément d'entrée caché au formulaire:

<input id="dummy_input" type="hidden" />

Ensuite, chaque fois que je veux empêcher l'utilisateur de s'éloigner, je déclenche la modification sur cette entrée pour m'assurer qu'elle preventNavigation()est exécutée:

function somethingThatModifiesAFormDynamically() {

    // Do something that modifies a form

    // ...
    $("#dummy_input").trigger("change");
    // ...
}
Mike
la source
3

Ici, essayez cela, cela fonctionne à 100%

<html>
<body>
<script>
var warning = true;
window.onbeforeunload = function() {  
  if (warning) {  
    return "You have made changes on this page that you have not yet confirmed. If you navigate away from this page you will lose your unsaved changes";  
    }  
}

$('form').submit(function() {
   window.onbeforeunload = null;
});
</script>
</body>
</html>
Braydon
la source
3

La norme indique que l'invite peut être contrôlée en annulant l' événement beforeunload ou en définissant la valeur de retour sur une valeur non nulle . Il indique également que les auteurs doivent utiliser Event.preventDefault () au lieu de returnValue, et le message affiché à l'utilisateur n'est pas personnalisable .

Au 69.0.3497.92, Chrome ne satisfaisait pas à la norme. Cependant, un rapport de bogue a été déposé et un examen est en cours. Chrome requiert que returnValue soit défini par référence à l'objet événement, et non à la valeur renvoyée par le gestionnaire.

Il est de la responsabilité de l'auteur de vérifier si des modifications ont été apportées; cela peut être fait avec une variable ou en s'assurant que l'événement n'est géré que lorsque cela est nécessaire.

window.addEventListener('beforeunload', function (e) {
    // Cancel the event as stated by the standard.
    e.preventDefault();
    // Chrome requires returnValue to be set.
    e.returnValue = '';
});
    
window.location = 'about:blank';

Trevor Karjanis
la source
2

Lorsque l'utilisateur commence à apporter des modifications au formulaire, un indicateur booléen est défini. Si l'utilisateur tente ensuite de s'éloigner de la page, vous vérifiez cet indicateur dans l' événement window.onunload . Si l'indicateur est défini, vous affichez le message en le renvoyant sous forme de chaîne. Le retour du message sous forme de chaîne fera apparaître une boîte de dialogue de confirmation contenant votre message.

Si vous utilisez ajax pour valider les modifications, vous pouvez définir l'indicateur falseaprès que les modifications ont été validées (c'est-à-dire dans l'événement de réussite ajax).

Kirtan
la source
1

Vous pouvez ajouter un onchangeévénement sur la zone de texte (ou tout autre champ) qui définit une variable dans JS. Lorsque l'utilisateur tente de fermer la page (window.onunload), vous vérifiez la valeur de cette variable et affichez l'alerte en conséquence.

Makram Saleh
la source
1
Vous ne pouvez pas le faire - alertet confirmêtes bloqué pendant window.onbeforeunloadet window.onunload(au moins dans la version de Chrome sur mon PC, mais probablement aussi dans tous les navigateurs pour prendre en charge ces gestionnaires).
Mark Amery
1

Sur la base de toutes les réponses sur ce fil, j'ai écrit le code suivant et cela a fonctionné pour moi.

Si vous ne disposez que de quelques balises d'entrée / zone de texte qui nécessitent la vérification d'un événement de déchargement, vous pouvez attribuer des attributs de données HTML5 comme data-onunload="true"

par exemple.

<input type="text" data-onunload="true" />
<textarea data-onunload="true"></textarea>

et le Javascript (jQuery) peut ressembler à ceci:

$(document).ready(function(){
    window.onbeforeunload = function(e) {
        var returnFlag = false;
        $('textarea, input').each(function(){
            if($(this).attr('data-onunload') == 'true' && $(this).val() != '')
                returnFlag = true;
        });

        if(returnFlag)
            return "Sure you want to leave?";   
    };
});
Sagar Gala
la source
2
Voir également «Pour certaines raisons, les navigateurs Webkit ne suivent pas les spécifications de la boîte de dialogue» dans la documentation avant téléchargement de MDN .
Arjan
1

voici mon html

<!DOCTYPE HMTL>
<meta charset="UTF-8">
<html>
<head>
<title>Home</title>
<script type="text/javascript" src="script.js"></script>
</head>

 <body onload="myFunction()">
    <h1 id="belong">
        Welcome To My Home
    </h1>
    <p>
        <a id="replaceME" onclick="myFunction2(event)" href="https://www.ccis.edu">I am a student at Columbia College of Missouri.</a>
    </p>
</body>

Et voilà comment j'ai fait quelque chose de similaire en javaScript

var myGlobalNameHolder ="";

function myFunction(){
var myString = prompt("Enter a name", "Name Goes Here");
    myGlobalNameHolder = myString;
    if (myString != null) {
        document.getElementById("replaceME").innerHTML =
        "Hello " + myString + ". Welcome to my site";

        document.getElementById("belong").innerHTML =
        "A place you belong";
    }   
}

// create a function to pass our event too
function myFunction2(event) {   
// variable to make our event short and sweet
var x=window.onbeforeunload;
// logic to make the confirm and alert boxes
if (confirm("Are you sure you want to leave my page?") == true) {
    x = alert("Thank you " + myGlobalNameHolder + " for visiting!");
}
}
Justin Stone
la source
0

Il peut être facilement fait en définissant une ChangeFlag true, le onChange cas de TextArea . Utilisez javascript pour afficher la boîte de dialogue de confirmation basée sur la valeur ChangeFlag . Jetez le formulaire et accédez à la page demandée si la confirmation est vraie, sinon ne faites rien .

Simplyharsh
la source
-1

Il y a un paramètre "onunload" pour la balise body que vous pouvez appeler à partir de là. S'il renvoie faux, il empêche la navigation.

stribika
la source
13
Heureusement, cela ne fonctionne pas vraiment. Sinon, je détesterais visiter une page contenant <body onunload="return false;">.
Søren Løvborg