21 Stimmen

Client/JS Framework für den Schutz von "ungespeicherten Daten"?

Wir haben eine typische Webanwendung, die im Wesentlichen eine Dateneingabe-Anwendung mit vielen Bildschirmen ist, von denen einige einen gewissen Grad an Komplexität aufweisen. Wir müssen diese Standardfunktion bereitstellen, um sicherzustellen, dass der Benutzer gewarnt wird und abbrechen kann, wenn er vergisst, auf die Schaltfläche "Speichern" zu klicken, bevor er die Navigation abbricht oder seinen Browser schließt (nur wenn Daten ungespeichert oder nicht gespeichert sind).

Ich kenne die Grundlagen dessen, was ich tun muss - ich bin mir sogar ziemlich sicher, dass ich das alles im Laufe der Jahre bereits gemacht habe (Anknüpfung an onbeforeunload, Verfolgung des "dirty" Zustands der Seite usw...) aber bevor ich mich auf das Codieren dieses VORERST NOCHMAL begebe, hat jemand Vorschläge für bereits vorhandene Bibliotheken (kostenlos oder anderweitig), die helfen könnten?

0 Stimmen

19voto

Jonny Buchanan Punkte 60128

Ein Puzzlestück:

/**
 * Bestimmt, ob ein Formular geändert wurde, indem der aktuelle Wert jedes Elements
 * mit seinem Standardwert verglichen wird.
 *
 * @param {Form} form das zu überprüfende Formular.
 * @return {Boolean} true, wenn das Formular geändert wurde, false
 *                   sonst.
 */
function formIsDirty(form)
{
    for (var i = 0; i < form.elements.length; i++)
    {
        var element = form.elements[i];
        var type = element.type;
        if (type == "checkbox" || type == "radio")
        {
            if (element.checked != element.defaultChecked)
            {
                return true;
            }
        }
        else if (type == "hidden" || type == "password" || type == "text" ||
                 type == "textarea")
        {
            if (element.value != element.defaultValue)
            {
                return true;
            }
        }
        else if (type == "select-one" || type == "select-multiple")
        {
            for (var j = 0; j < element.options.length; j++)
            {
                if (element.options[j].selected !=
                    element.options[j].defaultSelected)
                {
                    return true;
                }
            }
        }
    }
    return false;
}

Und noch eins:

window.onbeforeunload = function(e)
{
    e = e || window.event;  
    if (formIsDirty(document.forms["someFormOfInterest"]))
    {
        // Für IE und Firefox
        if (e)
        {
            e.returnValue = "Es gibt ungespeicherte Änderungen.";
        }
        // Für Safari
        return "Es gibt ungespeicherte Änderungen.";
    }
};

Alles zusammengefasst, was bekommst du?

var confirmExitIfModified = (function()
{
    function formIsDirty(form)
    {
        // ...wie oben
    }

    return function(form, message)
    {
        window.onbeforeunload = function(e)
        {
            e = e || window.event;
            if (formIsDirty(document.forms[form]))
            {
                // Für IE und Firefox
                if (e)
                {
                    e.returnValue = message;
                }
                // Für Safari
                return message;
            }
        };
    };
})();

confirmExitIfModified("someForm", "Es gibt ungespeicherte Änderungen.");

Du wirst wahrscheinlich auch die Registrierung des beforeunload-Event-Handlers ändern wollen, um die Ereignisregistrierung von LIBRARY_OF_CHOICE zu verwenden.

13voto

Wenn Sie jQuery verwenden, hier ist ein einfacher Trick:

$('input:text,input:checkbox,input:radio,textarea,select').one('change',function() {
  $('BODY').attr('onbeforeunload',"return 'Das Verlassen dieser Seite führt dazu, dass alle nicht gespeicherten Daten verloren gehen.';");
});

Aber denken Sie daran, wenn Sie eine Bedingung haben, bei der Sie von dieser Seite umleiten oder einen erfolgreichen Formularbeitrag zulassen möchten, müssen Sie dies vor der Umleitung oder dem Absendeereignis wie folgt tun:

$('BODY').removeAttr('onbeforeunload');

...sonst geraten Sie in eine Schleife, in der Sie immer wieder die Aufforderung erhalten.

In meinem Fall hatte ich eine große App und habe location.href-Umleitungen in JavaScript durchgeführt, sowie Formularbeiträge und dann einige AJAX-Übermittlungen, die dann mit einer Erfolgsantwort inline auf der Seite zurückkommen. In all diesen Bedingungen musste ich dieses Ereignis erfassen und den removeAttr()-Aufruf verwenden.

8voto

Möchte etwas über Volomikes ausgezeichneten jQuery-Code etwas ausführlicher erläutern.

Also haben wir hier einen sehr coolen und eleganten Mechanismus, um das Ziel zu erreichen, unbeabsichtigten Datenverlust beim Navigieren von aktualisierten Daten vor dem Speichern zu verhindern - z.B. aktualisiertes Feld auf einer Seite, dann auf einen Knopf, Link oder sogar auf die Zurück-Taste im Browser klicken, bevor man auf den Speichern-Knopf klickt.

Das Einzige, was Sie tun müssen, ist allen Steuerelementen (insbesondere Speichern-Schaltflächen) eine "noWarn" -Klasse hinzuzufügen, die einen Post-Back zur Website durchführen, die entweder aktualisierte Daten speichern oder nicht entfernen.

Wenn das Steuerelement dazu führt, dass die Seite Daten verliert, d.h. zur nächsten Seite navigiert oder die Daten löscht - müssen Sie nichts tun, da die Skripte automatisch die Warnmeldung anzeigen.

Genial! Gut gemacht Volomike!

Einfach den jQuery-Code wie folgt haben:

$(document).ready(function() {

    //----------------------------------------------------------------------
    // Es ist nicht erlaubt, von einer Seite zu navigieren, auf der wir Werte in einem Steuerelement geändert haben, ohne eine Warnmeldung. Unsere Speichern-Schaltflächen, Links usw. müssen klassifiziert werden, damit sie einen Speichern ohne die Meldung durchführen können - d.h. CssClass="noWarn"
    //----------------------------------------------------------------------
    $('input:text,input:checkbox,input:radio,textarea,select').one('change', function() {
        $('BODY').attr('onbeforeunload',
        "return 'Wenn Sie diese Seite verlassen, gehen alle ungespeicherten Daten verloren.';");
    });

    $('.noWarn').click(function() { $('BODY').removeAttr('onbeforeunload'); });

});

7voto

Ben McIntyre Punkte 1874

Zusätzlich zu Lances Antwort habe ich einen Nachmittag damit verbracht, diesen Codeabschnitt zum Laufen zu bringen. Erstens scheint jquery 1.4 Probleme mit dem Binden des Änderungsereignisses zu haben (Stand Feb 10). jQuery 1.3 ist okay. Zweitens kann ich jquery nicht dazu bringen, das Ereignis onbeforeunload/beforeunload zu binden (ich vermute IE7, den ich verwende). Ich habe verschiedene Selektoren ausprobiert ("body"), (window). Ich habe '.bind', '.attr' ausprobiert. Die Rückkehr zu reinem JS hat funktioniert (ich habe auch einige ähnliche Beiträge auf SO zu diesem Problem gesehen):

$(document).ready(function() {
    $(":input").one("change", function() {
        window.onbeforeunload = function() { return 'Du wirst Datenänderungen verlieren.'; }
    });
    $('.noWarn').click(function() { window.onbeforeunload = null; });
});

Beachten Sie, dass ich den Selektor ':input' verwendet habe, anstatt alle Eingabetypen aufzulisten. Streng genommen unnötig, aber ich fand es cool :-)

2voto

Ken Browning Punkte 27913

Ich habe ein jQuery Plug-in erstellt, das verwendet werden kann, um eine Warnung vor ungespeicherten Änderungen für Webanwendungen zu implementieren. Es unterstützt Postbacks. Es enthält auch einen Link zu Informationen darüber, wie das Verhalten des onbeforeunload-Ereignisses des Internet Explorers normalisiert werden kann.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X