Frage

Ich habe eine Anforderung, eine „ungesicherte Änderungen“ prompt in einer ASP .NET-Anwendung zu implementieren. Wenn ein Benutzer Steuerelemente in einem Webformular modifiziert und versucht weg zu navigieren vor dem Speichern soll eine Aufforderung erscheint sie warnt, dass sie nicht gespeicherte Änderungen, und gibt ihnen die Möglichkeit zu stornieren und auf der aktuellen Seite zu bleiben. Die Eingabeaufforderung sollte nicht angezeigt werden, wenn der Benutzer eine der Kontrollen nicht berührt hat.

Im Idealfall würde Ich mag diese in JavaScript implementieren, aber bevor ich auf dem Weg gehen, um meinen eigenen Code des Rollens, gibt es irgendwelche bestehenden Rahmen oder empfohlenen Entwurfsmuster für dieses Ziel zu erreichen? Im Idealfall würde ich etwas, das leicht über mehrere Seiten mit minimalen Änderungen wiederverwendet werden kann.

War es hilfreich?

Lösung

Mit jQuery:

var _isDirty = false;
$("input[type='text']").change(function(){
  _isDirty = true;
});
// replicate for other input types and selects

In Kombination mit onunload / onbeforeunload Methoden je nach Bedarf.

Aus den Kommentaren, die folgenden Referenzen alle Eingabefelder, ohne Duplizieren Code:

$(':input').change(function () {

$(":input") Verwendung bezieht sich auf alle Eingabe, Textfeld, auswählen und Schaltfläche Elemente.

Andere Tipps

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

Und ein anderer :

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

Wickeln Sie es allen oben, und was bekommen 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 Ereignishandler ändern LIBRARY_OF_CHOICE die Event-Registrierung verwenden.

In der ASPX-Seite, benötigen Sie einen JavaScript-Funktion zu sagen, ob die Form info ist „dirty“

<script language="javascript">
    var isDirty = false;

    function setDirty() {
        isDirty = true;
    }

    function checkSave() {
        var sSave;
        if (isDirty == true) {
            sSave = window.confirm("You have some changes that have not been saved. Click OK to save now or CANCEL to continue without saving.");
            if (sSave == true) {
                document.getElementById('__EVENTTARGET').value = 'btnSubmit';
                document.getElementById('__EVENTARGUMENT').value = 'Click';  
                window.document.formName.submit();
            } else {
                 return true;
            }
        }
    }
</script>
<body class="StandardBody" onunload="checkSave()">

und in dem Code-Behind, die Auslöser in die Eingabefelder sowie Resets über die Vorlage hinzufügen / Abbrechen Tasten ....

btnSubmit.Attributes.Add("onclick", "isDirty = 0;");
btnCancel.Attributes.Add("onclick", "isDirty = 0;");
txtName.Attributes.Add("onchange", "setDirty();");
txtAddress.Attributes.Add("onchange", "setDirty();");
//etc..

Im Folgenden verwendet den onbeforeunload Funktion und jquery Browser jedes Onchange Ereignis zu erfassen. Es sieht auch für jede einreichen oder Reset-Tasten der Flagge, die Änderungen aufgetreten sind, zurückgesetzt werden.

dataChanged = 0;     // global variable flags unsaved changes      

function bindForChange(){    
     $('input,checkbox,textarea,radio,select').bind('change',function(event) { dataChanged = 1})
     $(':reset,:submit').bind('click',function(event) { dataChanged = 0 })
}


function askConfirm(){  
    if (dataChanged){ 
        return "You have some unsaved changes.  Press OK to continue without saving." 
    }
}

window.onbeforeunload = askConfirm;
window.onload = bindForChange;

Danke für die Antworten jeder. Ich beendete eine Lösung mit JQuery und die Protect-Data Plug-in. Dies ermöglicht es mir automatisch die Überwachung auf einer Seite alle Steuerelemente.

Es gibt ein paar Einschränkungen jedoch, vor allem, wenn sie mit einer ASP-Net-Anwendung zu tun:

  • Wenn ein Benutzer die Option Abbrechen wählt, wird die doPostBack Funktion eines JavaScript-Fehler werfen. Ich hatte manuell innerhalb doPostBack einen try-catch um den .submit Anruf um es zu unterdrücken.

  • Auf einigen Seiten könnte ein Benutzer eine Aktion ausführen, die eine Postbacks auf die gleiche Seite führt, ist aber keine speichern. Dies führt in jeder Logik Zurücksetzen JavaScript, so dass er denkt, dass nichts nach dem Postback geändert hat, wenn etwas haben kann. Ich hatte eine versteckte Textbox zu implementieren, die mit der Seite zurückgesendet wird, und verwendet wird, einen einfachen Booleschen Wert zu halten, der angibt, ob die Daten verschmutzt ist. Dies wird über Postbacks beibehalten.

  • Sie können einige Postbacks auf der Seite wollen nicht den Dialog auslösen, wie zum Beispiel eine Schaltfläche Speichern. In diesem Fall können Sie JQuery verwenden, um eine OnClick-Funktion, die window.onbeforeunload auf null setzt hinzuzufügen.

Hoffentlich ist das hilfreich für alle anderen, die etwas ähnliches zu implementieren hat.

Die folgende Lösung funktioniert für Prototypen (getestet in FF, IE 6 und Safari). Es verwendet eine generische Form Beobachter (die Form abfeuert: geändert, wenn alle Felder des Formulars geändert wurden)., Die Sie auch für andere Dinge verwenden können

/* use this function to announce changes from your own scripts/event handlers.
 * Example: onClick="makeDirty($(this).up('form'));"
 */
function makeDirty(form) {
    form.fire("form:changed");
}

function handleChange(form, event) {
    makeDirty(form);
}

/* generic form observer, ensure that form:changed is being fired whenever
 * a field is being changed in that particular for
 */
function setupFormChangeObserver(form) {
    var handler = handleChange.curry(form);

    form.getElements().each(function (element) {
        element.observe("change", handler);
    });
}

/* installs a form protector to a form marked with class 'protectForm' */
function setupProtectForm() {
    var form = $$("form.protectForm").first();

    /* abort if no form */
    if (!form) return;

    setupFormChangeObserver(form);

    var dirty = false;
    form.observe("form:changed", function(event) {
        dirty = true;
    });

    /* submitting the form makes the form clean again */
    form.observe("submit", function(event) {
        dirty = false;
    });

    /* unfortunatly a propper event handler doesn't appear to work with IE and Safari */
    window.onbeforeunload = function(event) {
        if (dirty) {
            return "There are unsaved changes, they will be lost if you leave now.";
        }
    };
}

document.observe("dom:loaded", setupProtectForm);

Hier ist ein Javascript / jquery-Lösung, die einfach ist. Auf sie entfallen „undos“ durch den Benutzer wird in einer Funktion für eine einfache Anwendung gekapselt, und es Fehlzündungen nicht auf vorlegen. Nur die Funktion aufrufen und die ID des Formulars übergeben.

Diese Funktion serialisiert die Form einmal, wenn die Seite geladen wird, und wieder, bevor der Benutzer verlässt die Seite. Wenn die beiden Formzustände unterschiedlich sind, wird die Eingabeaufforderung angezeigt.

Probieren Sie es aus: http://jsfiddle.net/skibulk/Ydt7Y/

function formUnloadPrompt(formSelector) {
    var formA = $(formSelector).serialize(), formB, formSubmit = false;

    // Detect Form Submit
    $(formSelector).submit( function(){
        formSubmit = true;
    });

    // Handle Form Unload    
    window.onbeforeunload = function(){
        if (formSubmit) return;
        formB = $(formSelector).serialize();
        if (formA != formB) return "Your changes have not been saved.";
    };
}

$(function(){
    formUnloadPrompt('form');
});

Allgemeine Lösung mehrere Formulare in einer bestimmten Seite Unterstützung ( Kopieren Sie einfach und fügen Sie ihn in Ihrem Projekt )

$(document).ready(function() {
    $('form :input').change(function() {
        $(this).closest('form').addClass('form-dirty');
    });

    $(window).bind('beforeunload', function() {
        if($('form:not(.ignore-changes).form-dirty').length > 0) {
            return 'You have unsaved changes, are you sure you want to discard them?';
        }
    });

    $('form').bind('submit',function() {
        $(this).closest('form').removeClass('form-dirty');
        return true;
    });
});

. Hinweis: Diese Lösung von anderen Lösungen kombiniert, um eine allgemeine integrierte Lösung zu schaffen

Features:

  • Kopieren Sie einfach und fügen Sie ihn in Ihre App.
  • Unterstützung mehrerer Formulare.
  • Sie können Aktionen schmutzige Formen Stil oder machen, da sie die Klasse "Form-dirty" haben.
  • Sie können einige Formen ausschließen, indem die Klasse Hinzufügen ‚ignore-Änderungen‘.

Ich trug vor kurzem zu einer Open-Source-jQuery-Plugin namens dirtyForms .

Das Plugin entwickelt, um mit dynamisch hinzugefügt HTML zu arbeiten, unterstützt mehrere Formen, kann praktisch jeden Dialograhmen unterstützen, an den Browser zurückfällt beforeunload Dialogs, hat einen steckbaren Helfer Rahmen schmutzig Status von benutzerdefinierten Editoren zur Unterstützung bekommen (eine TinyMCE-Plugin im Lieferumfang enthalten), arbeitet in iFrames, und kann der schmutzigen Status gesetzt oder zurückgesetzt.

https://github.com/snikch/jquery.dirtyforms

Detect Form ändert sich mit jQuery ist sehr einfach:

var formInitVal = $('#formId').serialize(); // detect form init value after form is displayed

// check for form changes
if ($('#formId').serialize() != formInitVal) {
    // show confirmation alert
}

erweiterte ich auf Slace Vorschlag oben, die meisten bearbeitbaren Elemente enthalten und auch ohne bestimmte Elemente (mit einem CSS-Stil namens „srSearch“ hier) von verursacht die Dirty-Flag gesetzt werden.

<script type="text/javascript">
        var _isDirty = false;
        $(document).ready(function () {            

            // Set exclude CSS class on radio-button list elements
            $('table.srSearch input:radio').addClass("srSearch");

            $("input[type='text'],input[type='radio'],select,textarea").not(".srSearch").change(function () {
                _isDirty = true;
            });
        });

        $(window).bind('beforeunload', function () {
            if (_isDirty) {
                return 'You have unsaved changes.';
            }
        });        

      var unsaved = false;
    $(":input").change(function () {         
        unsaved = true;
    });

    function unloadPage() {         
        if (unsaved) {             
          alert("You have unsaved changes on this page. Do you want to leave this page and discard your changes or stay on this page?");
        }
    } 

window.onbeforeunload = unloadPage;

Das ist genau das, was die Fleegix.js Plugin fleegix.form.diff ( http://js.fleegix.org/plugins/form/diff ) wurde erstellt. Serialisieren den Anfangszustand der Form von Last unter Verwendung fleegix.form.toObject ( http://js.fleegix.org/ref#fleegix.form.toObject ) und speichern in einer variablen, zu vergleichen, dann mit dem aktuellen Status auf fleegix.form.diff unload verwenden. Einfach als Torte.

Eine Methode , Arrays mit den Variablen zu halten, so können Änderungen verfolgt werden.

Hier ist eine sehr einfache Methode, um zu erkennen , aber der Rest ist nicht so elegant.

Eine andere Methode, die recht einfach und klein ist, von farfetched Blog :

<body onLoad="lookForChanges()" onBeforeUnload="return warnOfUnsavedChanges()">
<form>
<select name=a multiple>
 <option value=1>1
 <option value=2>2
 <option value=3>3
</select>
<input name=b value=123>
<input type=submit>
</form>

<script>
var changed = 0;
function recordChange() {
 changed = 1;
}
function recordChangeIfChangeKey(myevent) {
 if (myevent.which && !myevent.ctrlKey && !myevent.ctrlKey)
  recordChange(myevent);
}
function ignoreChange() {
 changed = 0;
}
function lookForChanges() {
 var origfunc;
 for (i = 0; i < document.forms.length; i++) {
  for (j = 0; j < document.forms[i].elements.length; j++) {
   var formField=document.forms[i].elements[j];
   var formFieldType=formField.type.toLowerCase();
   if (formFieldType == 'checkbox' || formFieldType == 'radio') {
    addHandler(formField, 'click', recordChange);
   } else if (formFieldType == 'text' || formFieldType == 'textarea') {
    if (formField.attachEvent) {
     addHandler(formField, 'keypress', recordChange);
    } else {
     addHandler(formField, 'keypress', recordChangeIfChangeKey);
    }
   } else if (formFieldType == 'select-multiple' || formFieldType == 'select-one') {
    addHandler(formField, 'change', recordChange);
   }
  }
  addHandler(document.forms[i], 'submit', ignoreChange);
 }
}
function warnOfUnsavedChanges() {
 if (changed) {
  if ("event" in window) //ie
   event.returnValue = 'You have unsaved changes on this page, which will be discarded if you leave now. Click "Cancel" in order to save them first.';
  else //netscape
   return false;
 }
}
function addHandler(target, eventName, handler) {
 if (target.attachEvent) {
  target.attachEvent('on'+eventName, handler);
 } else {
  target.addEventListener(eventName, handler, false);
 }
}
</script>

Im IE document.ready nicht richtig funktionieren wird es die Werte des Eingangs aktualisieren.

so müssen wir Ladeereignis innerhalb der document.ready Funktion binden, die auch für die IE-Browser behandelt.

unten ist der Code, den Sie in der document.ready Funktion setzen sollten.

 $(document).ready(function () {
   $(window).bind("load", function () { 
    $("input, select").change(function () {});
   });
});
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top