2008-09-26 2 views
18

Wir haben eine typische Webanwendung, die im Wesentlichen eine Dateneingabeanwendung mit vielen Bildschirmen ist, von denen einige einen gewissen Grad an Komplexität aufweisen. Wir müssen diese Standardfunktionalität bereitstellen, um sicherzustellen, dass der Benutzer vergisst, auf die Schaltfläche "Speichern" zu klicken, bevor er weg navigiert oder seinen Browser schließt, eine Warnung erhält und abbrechen kann (aber nur wenn ungespeicherte oder schmutzige Daten vorhanden sind).Client/JS Framework für den Schutz "nicht gespeicherter Daten"?

Ich kenne die Grundlagen von dem, was ich tun muss - in der Tat bin ich mir sicher, dass ich alles schon über die Jahre gemacht habe (knüpfen an onbeforeunload, verfolgen den "schmutzigen" Zustand der Seite, etc ...) aber bevor ich wieder mit der Programmierung anfange, hat jemand irgendwelche Vorschläge für Bibliotheken, die schon da sind (kostenlos oder anders), die helfen werden?

Antwort

18

Ein Stück des Puzzles:

/** 
* Determines if a form is dirty by comparing the current value of each element 
* with its default value. 
* 
* @param {Form} form the form to be checked. 
* @return {Boolean} <code>true</code> if the form is dirty, <code>false</code> 
*     otherwise. 
*/ 
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; 
} 

And another:

window.onbeforeunload = function(e) 
{ 
    e = e || window.event; 
    if (formIsDirty(document.forms["someFormOfInterest"])) 
    { 
     // For IE and Firefox 
     if (e) 
     { 
      e.returnValue = "You have unsaved changes."; 
     } 
     // For Safari 
     return "You have unsaved changes."; 
    } 
}; 

es Wickeln Sie alle auf, und was tun Sie?

var confirmExitIfModified = (function() 
{ 
    function formIsDirty(form) 
    { 
     // ...as above 
    } 

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

confirmExitIfModified("someForm", "You have unsaved changes."); 

Sie werden wahrscheinlich wollen auch die Registrierung der beforeunload Event-Handler ändern LIBRARY_OF_CHOICE ‚s Event-Registrierung zu verwenden.

+1

Danke für all die Samples ... hier gibt es sicher genug, um mit mir zu arbeiten, obwohl ich immer noch damit zu kämpfen habe, Postbacks nicht zu fangen und mit einigen Ajax-Panels umzugehen. –

13

Wenn Sie jQuery verwenden, hier ist ein einfacher Trick:

$('input:text,input:checkbox,input:radio,textarea,select').one('change',function() { 
    $('BODY').attr('onbeforeunload',"return 'Leaving this page will cause any unsaved data to be lost.';"); 
}); 

Aber denken Sie daran, wenn Sie eine Bedingung, wo Sie auf dieser Seite umleiten oder Sie wollen eine erfolgreiche Form Post zu ermöglichen, müssen Sie Ereignis tun dies vor dieser Umleitung oder Bestaetigung etwa so:

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

... oder befinden Sie sich in einer Schleife, wo es hält die Aufforderung zu fragen.

In meinem Fall hatte ich eine große App und ich machte location.href Weiterleitungen in Javascript, sowie Formular Posting, und dann einige AJAX submits, die dann kommen mit einer Erfolgsreaktion inline auf der Seite zurück. In jeder dieser Bedingungen musste ich dieses Ereignis erfassen und den Aufruf removeAttr() verwenden.

+0

Für jetzt, bessere Lösung fand ich zu diesem Thema, in nur drei Zeilen. –

7

Wollte leicht auf Volomike ausgezeichnete jQuery-Code zu erweitern.

Mit diesem haben wir einen sehr sehr coolen und eleganten Mechanismus, um das Ziel zu erreichen, unbeabsichtigten Datenverlust zu verhindern, indem man von aktualisierten Daten vor dem Speichern weg navigiert - dh. aktualisiertes Feld auf einer Seite, klicken Sie dann auf eine Schaltfläche, einen Link oder sogar auf die Schaltfläche Zurück im Browser, bevor Sie auf die Schaltfläche Speichern klicken.

Das einzige, was Sie tun müssen, ist ein "noWarn" -Klasse-Tag zu allen Steuerelementen (insbesondere Speichern Schaltflächen) hinzufügen, die eine Post zurück auf die Website, die entweder speichern oder keine aktualisierten Daten entfernen.

Wenn das Steuerelement Datenverlust der Seite verursacht, z. navigiert zur nächsten Seite oder löscht die Daten - Sie müssen nichts tun, da die Skripte automatisch die Warnmeldung anzeigen.

Super! Gut gemacht Volomike!

haben einfach die jQuery-Code wie folgt:

$(document).ready(function() { 

    //---------------------------------------------------------------------- 
    // Don't allow us to navigate away from a page on which we're changed 
    // values on any control without a warning message. Need to class our 
    // save buttons, links, etc so they can do a save without the message - 
    // ie. CssClass="noWarn" 
    //---------------------------------------------------------------------- 
    $('input:text,input:checkbox,input:radio,textarea,select').one('change', function() { 
     $('BODY').attr('onbeforeunload', 
     "return 'Leaving this page will cause any unsaved data to be lost.';"); 
    }); 

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

}); 
7

Zusätzlich zu Lance Antwort, ich habe gerade einen Nachmittag versuchen, laufen diese Schnipsel zu bekommen. Erstens scheint jquery 1.4 Fehler beim Binden des Änderungsereignisses zu haben (Stand Februar '10). jQuery 1.3 ist in Ordnung. Zweitens kann ich nicht jquery, um die onbeforeunload/beforeunload zu binden (ich vermute, IE7, die ich verwende). Ich habe verschiedene Selektoren ("Körper"), (Fenster) ausprobiert. Ich habe '.bind', '.attr' ausprobiert. zu reinen js Zurückkehren gearbeitet (ich sah auch ein paar ähnlichen Beiträge auf SO über dieses Problem):

$(document).ready(function() { 
    $(":input").one("change", function() { 
     window.onbeforeunload = function() { return 'You will lose data changes.'; } 
    }); 
    $('.noWarn').click(function() { window.onbeforeunload = null; }); 
}); 

Hinweis ich auch benutzt habe ‚: Eingabe‘ Selektor anstatt alle Eingangstypen aufzählt. Streng übertrieben, aber ich fand es cool :-)

+0

+1 für nicht in IE arbeiten, es sei denn, Sie verwenden Vanille js für die Bindung. –

+0

+1 für "window.onbeforeunload = null;" –

1

Ich habe eine weitere kleine Verbesserung der jQuery-Implementierungen auf dieser Seite vorgenommen. Meine Implementierung wird behandelt, wenn Sie clientseitige ASP.NET-Seitenüberprüfung aktiviert haben und auf einer Seite verwendet werden.

Es vermeidet den "Fehler" beim Löschen der onBeforeLeave-Funktion, wenn die Seite aufgrund eines Validierungsfehlers nicht wirklich auf Klick posten kann. Verwenden Sie einfach die no-warn-validate Klasse für Schaltflächen/Links, die eine Validierung verursachen. Es hat immer noch die Klasse no-warn für Steuerelemente mit CausesValidation=false (z. B. eine Schaltfläche "Speichern als Entwurf"). Dieses Muster könnte wahrscheinlich für andere Validierungs-Frameworks als ASP.NET verwendet werden, daher poste ich hier als Referenz.

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

$(document).ready(function() { 
    //----------------------------------------------------------------------------------------- 
    // Don't allow navigating away from page if changes to form are made. Save buttons, links, 
    // etc, can be given "no-warn" or "no-warn-validate" css class to prevent warning on submit. 
    // "no-warn-validate" inputs/links will only remove warning after successful validation 
    //----------------------------------------------------------------------------------------- 
    $(':input').one('change', function() { 
     window.onbeforeunload = function() { 
      return 'Leaving this page will cause edits to be lost.'; 
     } 
    }); 

    $('.no-warn-validate').click(function() { 
     if (Page_ClientValidate == null || Page_ClientValidate()) { removeCheck(); } 
    }); 

    $('.no-warn').click(function() { removeCheck() }); 
}); 
2

Ich habe ein jQuery plug-in erstellt, die verwendet werden können, ein warn-on-Ungespeicherte-Änderungen für Web-Anwendungen bieten zu implementieren. Es unterstützt Postbacks. Es enthält außerdem einen Link zu Informationen zum Normalisieren des Verhaltens des Internet Explorer-Ereignisses onbeforeunload.