Come mostrare "Sei sicuro di voler uscire da questa pagina?" quando sono state apportate modifiche?


267

Qui in StackOverflow, se hai iniziato ad apportare modifiche, allora tenti di allontanarti dalla pagina, viene visualizzato un pulsante di conferma javascript che chiede: "Sei sicuro di voler uscire da questa pagina?" blee blah bloo ...

Qualcuno lo ha già implementato in precedenza, come posso tenere traccia delle modifiche apportate? Credo di poterlo fare da solo, sto cercando di imparare le buone pratiche da voi esperti.

Ho provato quanto segue ma ancora non funziona:

<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>

Qualcuno può pubblicare un esempio?


3
Per far funzionare il tuo esempio, modifica la funzione in: myFunction () {window.onbeforeunload = "message"; } quindi cambia l'input: <input type = 'text' onchange = 'myFunction ();'> </input>
Keith

Risposte:


367

Aggiornamento (2017)

I browser moderni ora considerano la visualizzazione di un messaggio personalizzato come un pericolo per la sicurezza ed è stato quindi rimosso da tutti. I browser ora visualizzano solo messaggi generici. Dal momento che non dobbiamo più preoccuparci di impostare il messaggio, è semplice come:

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

Leggi di seguito per il supporto del browser legacy.

Aggiornamento (2013)

La risposta originale è adatta per IE6-8 e FX1-3.5 (che è ciò a cui stavamo puntando nel 2009 quando è stata scritta), ma è piuttosto obsoleta ora e non funzionerà nella maggior parte dei browser attuali - Ho lasciato sotto per riferimento.

Non window.onbeforeunloadviene trattato in modo coerente da tutti i browser. Dovrebbe essere un riferimento di funzione e non una stringa (come indicato nella risposta originale), ma funzionerà nei browser più vecchi perché il controllo per la maggior parte di essi sembra essere assegnato a qualcosa onbeforeunload(inclusa una funzione che ritorna null).

Si imposta window.onbeforeunloadsu un riferimento di funzione, ma nei browser più vecchi è necessario impostare returnValuel'evento anziché invece di restituire una stringa:

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

Non è possibile confirmOnPageExitfare questo controllo e restituire null se si desidera che l'utente continui senza il messaggio. Devi ancora rimuovere l'evento per attivarlo e disattivarlo in modo affidabile:

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

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

Risposta originale (ha funzionato nel 2009)

Accenderlo:

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

Per disattivarlo:

window.onbeforeunload = null;

Tieni presente che questo non è un evento normale: non puoi vincolarlo in modo standard.

Per verificare i valori? Dipende dal tuo framework di validazione.

In jQuery potrebbe essere qualcosa del genere (esempio molto semplice):

$('input').change(function() {
    if( $(this).val() != "" )
        window.onbeforeunload = "Are you sure you want to leave?";
});

4
Sarebbe qualcosa del tipo: $ ('input: text'). Change (function () {window.onbeforeunload = $ ('input: text [value! = ""]'). Length> 0? "Warning": null ;});
Keith,

1
Per un semplice controllo, oppure puoi aggiungere una convalida più complessa su ogni modifica
Keith,

1
vale la pena notare che il metodo 'returnValue' è l'unico metodo specificato nello standard, quindi non è solo per IE6-8, è per tutti i browser conformi agli standard (in questo caso non include Chrome, Safari e Opera).
rmcclellan,

3
Per interrompere l'avviso sull'invio del modulo, ho usato $("#submit_button").click(function() { window.onbeforeunload = null; });. Inizialmente ho usato l'evento onclick del pulsante, ma oltre a non essere così bello, non ha funzionato con IE8.
Andy Beverley,

1
@ AlikElzin-kilaka non puoi. Se si desidera modificare il testo a comparsa, è necessario creare il proprio popup personalizzato, ma ciò non può bloccare l' window.onbeforeunloadevento.
Keith

38

La onbeforeunloadMicrosoft-ismo è la cosa più vicina che abbiamo a una soluzione standard, ma essere consapevoli che il supporto del browser non è uniforme; ad esempio per Opera funziona solo nella versione 12 e successive (ancora in versione beta al momento della stesura).

Inoltre, per la massima compatibilità , devi fare di più che semplicemente restituire una stringa, come spiegato nella Rete degli sviluppatori di Mozilla .

Esempio: definire le seguenti due funzioni per abilitare / disabilitare il prompt di navigazione (vedere l'esempio MDN):

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

Quindi definire un modulo come questo:

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

In questo modo, l'utente verrà avvisato di andarsene solo se ha modificato l'area di testo e non verrà richiesto quando sta effettivamente inviando il modulo.


1
Basato sul sito di Mozill, i browser desktop più recenti ora lo supportano: developer.mozilla.org/en/DOM/window.onbeforeunload
Hengjie,

Microsoft-ism è un ottimo termine.
Luke Taylor,


18

Con JQuery questa roba è abbastanza facile da fare. Dal momento che puoi legare ai set.

NON è sufficiente per eseguire il download onbefore, si desidera attivare la navigazione solo se qualcuno ha iniziato a modificare le cose.


2
Non riesco a colpire i post del blog di @jonstjohn. Forse sarà un amico e ci indicherà la giusta direzione? : D
FLGMwt,

14
=> 500 Errore interno. Ecco perché i link sono deprecati su SO. Sottovalutato fino alla correzione
Loïc,

Questa pagina web non è disponibile
Mateusz,

2
Sebbene questo collegamento possa rispondere alla domanda, è meglio includere qui le parti essenziali della risposta e fornire il collegamento come riferimento. Le risposte di solo collegamento possono diventare non valide se la pagina collegata cambia.
bwest,

2
Il link originale di Jon St John era rotto, quindi l'ho aggiornato alla versione di Wayback Machine . Il contenuto del link può essere trovato copiato in molti altri siti, ma credo sia meglio "preservare" quello che Sam ha aggiunto
Alvaro Montoro,

14

"beforeunload" di jquerys ha funzionato benissimo per me

$(window).bind('beforeunload', function(){
    if( $('input').val() !== '' ){
        return "It looks like you have input you haven't submitted."
    }
});

Il bind è stato deprecato e una nuova versione di codice simile a questa può essere vista in questa risposta: stackoverflow.com/a/1889450/908677
Elija Lofgren


11

Questo è un modo semplice per presentare il messaggio se vengono inseriti dati nel modulo e non mostrare il messaggio se il modulo viene inviato:

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

8

Per espandere la già sorprendente risposta di Keith :

Messaggi di avviso personalizzati

Per consentire messaggi di avviso personalizzati, è possibile inserirlo in una funzione come questa:

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

Quindi chiama quella funzione con il tuo messaggio personalizzato:

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

Abilitare nuovamente la navigazione

Per riattivare la navigazione, è sufficiente impostare window.onbeforeunloadsu null. Eccolo, avvolto in una piccola funzione ordinata che può essere chiamata ovunque:

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

Utilizzando jQuery per associare questo per formare elementi

Se si utilizza jQuery, questo può essere facilmente associato a tutti gli elementi di un modulo come questo:

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

Quindi per consentire l'invio del modulo:

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

Moduli modificati dinamicamente:

preventNavigation()e enableNavigation()può essere associato a qualsiasi altra funzione in base alle esigenze, come la modifica dinamica di un modulo o il clic su un pulsante che invia una richiesta AJAX. L'ho fatto aggiungendo un elemento di input nascosto al modulo:

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

Quindi ogni volta che voglio impedire all'utente di spostarsi, innesco la modifica su quell'input per assicurarmi che preventNavigation()venga eseguito:

function somethingThatModifiesAFormDynamically() {

    // Do something that modifies a form

    // ...
    $("#dummy_input").trigger("change");
    // ...
}

3

Qui prova questo funziona al 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>

3

Lo standard afferma che il prompt può essere controllato annullando l' evento beforeunload o impostando il valore restituito su un valore non nullo . Indica inoltre che gli autori dovrebbero utilizzare Event.preventDefault () invece di returnValue e che il messaggio mostrato all'utente non è personalizzabile .

A partire da 69.0.3497.92, Chrome non ha soddisfatto lo standard. Tuttavia, è stata archiviata una segnalazione di bug ed è in corso una revisione . Chrome richiede che returnValue sia impostato facendo riferimento all'oggetto evento, non al valore restituito dal gestore.

È responsabilità dell'autore verificare se sono state apportate modifiche; può essere fatto con una variabile o assicurando che l'evento venga gestito solo quando necessario.

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';


2

Quando l'utente inizia ad apportare modifiche al modulo, verrà impostato un flag booleano. Se l'utente tenta quindi di allontanarsi dalla pagina, controlla quel flag nell'evento window.onunload . Se il flag è impostato, mostri il messaggio restituendolo come stringa. Restituendo il messaggio come stringa verrà visualizzata una finestra di dialogo di conferma contenente il messaggio.

Se si utilizza ajax per eseguire il commit delle modifiche, è possibile impostare il flag su falsedopo che le modifiche sono state eseguite (ovvero nell'evento di successo ajax).


1

È possibile aggiungere un onchangeevento nell'area di testo (o in qualsiasi altro campo) che imposta una variabile in JS. Quando l'utente tenta di chiudere la pagina (window.onunload) controlli il valore di quella variabile e mostri l'avviso di conseguenza.


1
Non puoi farlo - alerte confirmvengono bloccati durante window.onbeforeunloade window.onunload(almeno nella versione di Chrome sul mio PC, ma probabilmente anche in tutti i browser che supportano mai quei gestori).
Mark Amery,

1

Sulla base di tutte le risposte su questo thread, ho scritto il seguente codice e ha funzionato per me.

Se hai solo alcuni tag input / textarea che richiedono la verifica di un evento onunload, puoi assegnare gli attributi di dati HTML5 come data-onunload="true"

per es.

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

e Javascript (jQuery) può apparire così:

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

2
Vedi anche "Per alcuni motivi, i browser basati su Webkit non seguono le specifiche per la finestra di dialogo" nella documentazione di MDN prima dello scaricamento .
Arjan,

1

ecco il mio 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>

E così è così che ho fatto qualcosa di simile in 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!");
}
}

0

Può essere fatto facilmente impostando un ChangeFlag su true, sull'evento onChange di TextArea . Utilizzare JavaScript per mostrare la finestra di dialogo di conferma in base al valore ChangeFlag . Ignora il modulo e vai alla pagina richiesta se conferma restituisce vero, altrimenti non fare nulla .



-1

Esiste un parametro "onunload" per il body tag che puoi chiamare funzioni javascript da lì. Se restituisce false, impedisce la navigazione.


13
Fortunatamente, questo in realtà non funziona. Altrimenti odierei visitare una pagina contenente <body onunload="return false;">.
Søren Løvborg,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.