Ich habe einige Seiten mit Formularen in meiner Bewerbung.
Wie kann ich das Formular so sichern, dass jemand, wenn er wegnavigiert oder den Browser-Tab schließt, aufgefordert werden sollte, zu bestätigen, dass er das Formular wirklich mit nicht gespeicherten Daten verlassen möchte?
Kurze, falsche Antwort:
Sie können dies tun, indem Sie Umgang mit der beforeunload
Ereignis und Rückgabe einer Nicht-Null-Zeichenfolge:
window.addEventListener("beforeunload", function (e) {
var confirmationMessage="It looks like you have been editing something. "
+ 'If you leave before saving, your changes will be lost.';
(e || window.event).returnValue = confirmationMessage; //Gecko + IE
return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
});
Das Problem bei diesem Ansatz ist das Das Absenden eines Formulars löst auch das Unload-Ereignis aus. Dies lässt sich leicht beheben, indem Sie das a-Flag hinzufügen, dass Sie ein Formular senden:
var formSubmitting = false;
var setFormSubmitting = function() { formSubmitting = true; };
window.onload = function() {
window.addEventListener("beforeunload", function (e) {
if (formSubmitting) {
return undefined;
}
var confirmationMessage="It looks like you have been editing something. "
+ 'If you leave before saving, your changes will be lost.';
(e || window.event).returnValue = confirmationMessage; //Gecko + IE
return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
});
};
Dann Aufruf des Setters beim Absenden:
<form method="post" onsubmit="setFormSubmitting()">
<input type="submit" />
</form>
Aber lies weiter…
Lange, richtige Antwort:
Sie möchten diese Nachricht auch nicht anzeigen wenn der Benutzer nichts an Ihren Formularen geändert hat. Eine Lösung ist die Verwendung von beforeunload
Event in Kombination mit einem “Dirty”-Flag, das den Prompt nur dann auslöst, wenn es wirklich relevant ist.
var isDirty = function() { return false; }
window.onload = function() {
window.addEventListener("beforeunload", function (e) {
if (formSubmitting || !isDirty()) {
return undefined;
}
var confirmationMessage="It looks like you have been editing something. "
+ 'If you leave before saving, your changes will be lost.';
(e || window.event).returnValue = confirmationMessage; //Gecko + IE
return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
});
};
Nun zur Umsetzung der isDirty
Methode gibt es verschiedene Ansätze.
Sie können jQuery und Formularserialisierung verwenden, aber dieser Ansatz hat einige Mängel. Zuerst müssen Sie den Code ändern, um auf jedem Formular zu arbeiten ($("form").each()
tun), aber das größte Problem ist das von jQuery serialize()
funktioniert nur bei benannten, nicht deaktivierten Elementen, sodass das Ändern eines deaktivierten oder unbenannten Elements nicht das Dirty-Flag auslöst. Dafür gibt es Problemumgehungen, z. B. das Festlegen von schreibgeschützten Steuerelementen anstelle des Aktivierens, Serialisierens und erneuten Deaktivierens der Steuerelemente.
Ereignisse scheinen also der richtige Weg zu sein. Sie können versuchen, auf Tastendrücke zu hören. Diese Veranstaltung weist einige Probleme auf:
- Wird nicht bei Kontrollkästchen, Optionsfeldern oder anderen Elementen ausgelöst, die durch Mauseingabe geändert werden.
- Wird für irrelevante Tastendrücke wie die ausgelöst Strg Schlüssel.
- Wird nicht auf Werte ausgelöst, die durch JavaScript-Code festgelegt wurden.
- Wird nicht beim Ausschneiden oder Einfügen von Text über Kontextmenüs ausgelöst.
- Funktioniert nicht für virtuelle Eingaben wie Datumsauswahl oder Verschönerungen von Kontrollkästchen/Radiobuttons, die ihren Wert in einer versteckten Eingabe über JavaScript speichern.
Die change
Das Ereignis wird auch nicht bei Werten ausgelöst, die aus JavaScript-Code festgelegt wurden, und funktioniert daher auch nicht für virtuelle Eingaben.
Bindung der input
Veranstaltung für alle input
s (und textarea
s und select
s) auf Ihrer Seite funktioniert nicht mit älteren Browsern und unterstützt, wie alle oben genannten Lösungen zur Ereignisbehandlung, das Rückgängigmachen nicht. Wenn ein Benutzer ein Textfeld ändert und dies dann rückgängig macht oder ein Kontrollkästchen aktiviert und deaktiviert, wird das Formular immer noch als fehlerhaft betrachtet.
Und wenn Sie weitere Verhaltensweisen implementieren möchten, z. B. das Ignorieren bestimmter Elemente, müssen Sie noch mehr tun.
Das Rad nicht neu erfinden:
Bevor Sie also über die Implementierung dieser Lösungen und aller erforderlichen Problemumgehungen nachdenken, sollten Sie sich darüber im Klaren sein, dass Sie das Rad neu erfinden und dazu neigen, auf Probleme zu stoßen, die andere bereits für Sie gelöst haben.
Wenn Ihre Anwendung bereits jQuery verwendet, können Sie auch getesteten, gepflegten Code verwenden, anstatt Ihren eigenen zu erstellen, und für all dies eine Bibliothek eines Drittanbieters verwenden.
jquery.dirty (empfohlen von @troseman in den Kommentaren) bietet Funktionen, um richtig zu erkennen, ob ein Formular geändert wurde oder nicht, und um zu verhindern, dass der Benutzer die Seite verlässt, während eine Eingabeaufforderung angezeigt wird. Es hat auch andere nützliche Funktionen wie das Zurücksetzen des Formulars und das Festlegen des aktuellen Status des Formulars als “sauberen” Status. Beispielnutzung:
$("#myForm").dirty({preventLeaving: true});
Ein älteres, derzeit aufgegebenes Projekt ist Sind Sie sicher? Plugin, was auch super funktioniert; siehe ihre Demoseite. Beispielnutzung:
<script src="jquery.are-you-sure.js"></script>
<script>
$(function() {
$('#myForm').areYouSure(
{
message: 'It looks like you have been editing something. '
+ 'If you leave before saving, your changes will be lost.'
}
);
});
</script>
Benutzerdefinierte Nachrichten werden nicht überall unterstützt
Beachten Sie, dass Firefox 4 bereits seit 2011 keine benutzerdefinierten Nachrichten in diesem Dialogfeld unterstützt. Ab April 2016 wird Chrome 51 ausgerollt in denen auch benutzerdefinierte Nachrichten entfernt werden.
An anderer Stelle auf dieser Seite gibt es einige Alternativen, aber ich denke, ein Dialog wie dieser ist klar genug:
Möchten Sie diese Seite verlassen?
Von Ihnen vorgenommene Änderungen werden möglicherweise nicht gespeichert.
Verlassen Bleibe
über jquery
$('#form').data('serialize',$('#form').serialize()); // On load save form current state
$(window).bind('beforeunload', function(e){
if($('#form').serialize()!=$('#form').data('serialize'))return true;
else e=null; // i.e; if form state change show warning box, else don't show it.
});
Sie können die Google JQuery Form Serialize-Funktion verwenden, die alle Formulareingaben sammelt und in einem Array speichert. Ich denke diese Erklärung reicht 🙂
Universelle Lösung, die keine Konfiguration erfordert und automatisch alle Eingabeänderungen erkennt, einschließlich inhaltsveränderbarer Elemente:
"use strict";
(() => {
const modified_inputs = new Set;
const defaultValue = "defaultValue";
// store default values
addEventListener("beforeinput", (evt) => {
const target = evt.target;
if (!(defaultValue in target || defaultValue in target.dataset)) {
target.dataset[defaultValue] = ("" + (target.value || target.textContent)).trim();
}
});
// detect input modifications
addEventListener("input", (evt) => {
const target = evt.target;
let original;
if (defaultValue in target) {
original = target[defaultValue];
} else {
original = target.dataset[defaultValue];
}
if (original !== ("" + (target.value || target.textContent)).trim()) {
if (!modified_inputs.has(target)) {
modified_inputs.add(target);
}
} else if (modified_inputs.has(target)) {
modified_inputs.delete(target);
}
});
// clear modified inputs upon form submission
addEventListener("submit", (evt) => {
modified_inputs.clear();
// to prevent the warning from happening, it is advisable
// that you clear your form controls back to their default
// state with evt.target.reset() or form.reset() after submission
});
// warn before closing if any inputs are modified
addEventListener("beforeunload", (evt) => {
if (modified_inputs.size) {
const unsaved_changes_warning = "Changes you made may not be saved.";
evt.returnValue = unsaved_changes_warning;
return unsaved_changes_warning;
}
});
})();
Aufbauend auf der hervorragenden Idee von Wasim A., Serialisierung zu verwenden. Das Problem dabei war, dass die Warnung auch beim Absenden des Formulars angezeigt wurde. Dies wurde hier behoben.
var isSubmitting = false
$(document).ready(function () {
$('form').submit(function(){
isSubmitting = true
})
$('form').data('initial-state', $('form').serialize());
$(window).on('beforeunload', function() {
if (!isSubmitting && $('form').serialize() != $('form').data('initial-state')){
return 'You have unsaved changes which will not be saved.'
}
});
})
Es wurde in Chrome und IE 11 getestet.
Basierend auf den vorherigen Antworten und aus verschiedenen Stellen im Stapelüberlauf zusammengeschustert, habe ich mir hier die Lösung ausgedacht, die den Fall behandelt, wenn Sie Ihre Änderungen tatsächlich einreichen möchten:
window.thisPage = window.thisPage || {};
window.thisPage.isDirty = false;
window.thisPage.closeEditorWarning = function (event) {
if (window.thisPage.isDirty)
return 'It looks like you have been editing something' +
' - if you leave before saving, then your changes will be lost.'
else
return undefined;
};
$("form").on('keyup', 'textarea', // You can use input[type=text] here as well.
function () {
window.thisPage.isDirty = true;
});
$("form").submit(function () {
QC.thisPage.isDirty = false;
});
window.onbeforeunload = window.thisPage.closeEditorWarning;
Es ist erwähnenswert, dass IE11 dies zu erfordern scheint closeEditorWarning
Funktion zurück undefined
damit es keinen Alarm anzeigt.
Der folgende Einzeiler hat für mich funktioniert.
window.onbeforeunload = s => modified ? "" : null;
Einfach einstellen modified
zu wahr oder falsch je nach Stand Ihrer Bewerbung.
Diese Frage hier sollte die Antwort haben, nach der Sie suchen: stackoverflow.com/questions/1244535/…
– Nexeros
6. September 2011 um 8:58 Uhr
siehe stackoverflow.com/questions/140460/…
– Atara
17. Februar 2015 um 8:53 Uhr
Siehe auch: stackoverflow.com/q/821011/435605
– AlikElzin-kilaka
9. Februar 2016 um 6:17 Uhr