سؤال

لدي متطلبات لتنفيذ المطالبة "التغييرات غير المحفوظة" في تطبيق ASP .Net.إذا قام مستخدم بتعديل عناصر التحكم في نموذج ويب، وحاول التنقل بعيدًا قبل الحفظ، فيجب أن تظهر مطالبة تحذره من أن لديه تغييرات غير محفوظة، وتمنحه خيار الإلغاء والبقاء في الصفحة الحالية.يجب ألا يتم عرض المطالبة إذا لم يلمس المستخدم أيًا من عناصر التحكم.

من الناحية المثالية، أود تنفيذ ذلك في JavaScript، ولكن قبل أن أبدأ في تنفيذ التعليمات البرمجية الخاصة بي، هل هناك أي أطر عمل حالية أو أنماط تصميم موصى بها لتحقيق ذلك؟من الناحية المثالية، أريد شيئًا يمكن إعادة استخدامه بسهولة عبر صفحات متعددة مع الحد الأدنى من التغييرات.

هل كانت مفيدة؟

المحلول

وعن طريق مسج:

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

ومع الجمع بين أساليب onunload / onbeforeunload على النحو المطلوب.

ومن التعليقات، المراجع التالية كل حقول الإدخال، دون رمز تكرار:

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

وعن طريق $(":input") يشير إلى جميع المدخلات، وجزء النص، حدد، وعناصر زر.

نصائح أخرى

وقطعة واحدة من اللغز:

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

و آخر:

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

والتفاف كل شيء، وماذا يحصل؟

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.");

وأنت ربما تريد أيضا لتغيير تسجيل معالج الأحداث beforeunload لاستخدام تسجيل الحدث LIBRARY_OF_CHOICE ل.

في صفحة .aspx، كنت في حاجة الى وظيفة جافا سكريبت لمعرفة ما إذا كان أو لم يكن من المعلومات النموذج هو "القذرة"

<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()">

ووفي codebehind، إضافة إلى مشغلات حقول الإدخال، وكذلك إعادة تعيين على تقديم / إلغاء أزرار ....

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

وفيما يلي يستخدم ظيفة onbeforeunload المتصفح ومسج للقبض على أي حال عند_التغيير. ويبدو أيضا عن أي تقدم أو إعادة تعيين أزرار لإعادة العلم حدثت تغيرات مبينا.

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;

شكرا لكم جميعا على الردود.انتهى بي الأمر بتنفيذ حل باستخدام JQuery و حماية البيانات توصيل في.يتيح لي هذا تطبيق المراقبة تلقائيًا على كافة عناصر التحكم الموجودة على الصفحة.

ومع ذلك، هناك بعض التحذيرات، خاصة عند التعامل مع تطبيق ASP .Net:

  • عندما يختار المستخدم خيار الإلغاء، ستؤدي وظيفة doPostBack إلى ظهور خطأ JavaScript.اضطررت إلى إجراء محاولة التقاط يدويًا حول مكالمة .submit داخل doPostBack لمنعها.

  • في بعض الصفحات، يمكن للمستخدم تنفيذ إجراء يؤدي إلى إعادة النشر إلى نفس الصفحة، ولكنه ليس حفظًا.يؤدي هذا إلى إعادة تعيين أي منطق لجافا سكريبت، لذلك يعتقد أنه لم يتغير شيء بعد إعادة النشر عندما يكون هناك شيء ما قد تغير.اضطررت إلى تنفيذ مربع نص مخفي يتم نشره مرة أخرى مع الصفحة، ويستخدم للاحتفاظ بقيمة منطقية بسيطة تشير إلى ما إذا كانت البيانات متسخة.يستمر هذا عبر عمليات إعادة النشر.

  • قد ترغب في ألا تؤدي بعض عمليات الإبلاغ عن النشر على الصفحة إلى تشغيل مربع الحوار، مثل زر "حفظ".في هذه الحالة، يمكنك استخدام JQuery لإضافة دالة OnClick التي تقوم بتعيين window.onbeforeunload على القيمة null.

نأمل أن يكون هذا مفيدًا لأي شخص آخر يتعين عليه تنفيذ شيء مماثل.

والحل التالي يعمل لنموذج (اختبار في FF، IE 6 و سفاري). ويستخدم شكل مراقب عام (التي تطلق النموذج: تغيرت عندما تم تعديل أية حقول النموذج)، والتي يمكنك استخدامها لأشياء أخرى كذلك

/* 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);

إليك حل جافا سكريبت/مسج بسيط.إنه يمثل "التراجع" من قبل المستخدم، ويتم تضمينه داخل وظيفة لسهولة التطبيق، ولا يخطئ عند الإرسال.ما عليك سوى استدعاء الوظيفة وتمرير معرف النموذج الخاص بك.

تقوم هذه الوظيفة بإجراء تسلسل للنموذج مرة واحدة عند تحميل الصفحة، ومرة ​​أخرى قبل أن يغادر المستخدم الصفحة.إذا كانت حالتا النموذج مختلفتين، فسيتم عرض المطالبة.

حاول: 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');
});

الحل العام دعم نماذج متعددة في صفحة معينة (فقط قم بالنسخ واللصق في مشروعك)

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

ملحوظة:يتم دمج هذا الحل من حلول الآخرين لإنشاء حل عام متكامل.

سمات:

  • ما عليك سوى النسخ واللصق في تطبيقك.
  • يدعم نماذج متعددة.
  • يمكنك تصميم أو تنفيذ إجراءات بأشكال قذرة، نظرًا لأنها تنتمي إلى فئة "الشكل القذر".
  • يمكنك استبعاد بعض النماذج عن طريق إضافة فئة "تجاهل التغييرات".

وأنا ساهمت مؤخرا إلى مصدر مسج المساعد مفتوحة تسمى dirtyForms .

تم تصميم البرنامج المساعد للعمل مع HTML إضافتها بشكل حيوي، ويدعم أشكال متعددة، يمكن أن تدعم عمليا أي إطار الحوار، يرتد إلى متصفح beforeunload الحوار، لديها إطار المساعد للتوصيل لدعم الحصول على وضع القذرة من المحررين مخصصة (المساعد محرر TinyMCE يتم تضمين)، يعمل ضمن إطارات iFrames، وحالة القذرة يمكن تعيين أو إعادة تعيين في الإرادة.

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

والكشف عن التغيرات النموذج باستخدام مسج بسيط جدا:

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

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

وأنا موسعة على اقتراح Slace في أعلاه، لتشمل أكثر العناصر قابلة للتحرير وباستثناء أيضا بعض العناصر (مع نمط CSS يسمى "srSearch" هنا) من التسبب في علامة سيئ إلى أن تعيين.

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

وهذا هو بالضبط ما البرنامج المساعد fleegix.form.diff Fleegix.js ( <أ href = ل تم إنشاء "http://js.fleegix.org/plugins/form/diff" يختلط = "نوفولو noreferrer"> http://js.fleegix.org/plugins/form/diff ) ل. تسلسل الحالة الأولية من النموذج على الحمل باستخدام fleegix.form.toObject ( <أ href = ل "http://js.fleegix.org/ref#fleegix.form.toObject" يختلط = "noreferrer نوفولو"> http://js.fleegix.org/ref#fleegix.form.toObject ) وحفظ في متغير، ثم قارن مع الوضع الحالي باستخدام fleegix.form.diff على تفريغ. سهلا كما فطيرة.

أسلوب واحد ، وذلك باستخدام صفائف لعقد المتغيرات بحيث يمكن تتبع التغيرات.

وهنا طريقة بسيطة جدا ل كشف عن تغيرات ، ولكن بقية ليست أنيقة كما.

وهناك طريقة أخرى وهي بسيطة الى حد كبير وصغير، من <لأ href = "http://farfetched.blogspot.com/2005/03/warn-of-unsaved-changes-javascript.html" يختلط = "نوفولو noreferrer" > المستبعد مدونة :

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

في IE سوف document.ready لا تعمل بشكل صحيح فإنه سيتم تحديث قيم الإدخال.

لذلك نحن بحاجة إلى ربط الحدث تحميل داخل وظيفة document.ready الذي سيقوم بمعالجة لمتصفح IE أيضا.

وأدناه هو رمز يجب عليك ان تضع داخل وظيفة document.ready.

 $(document).ready(function () {
   $(window).bind("load", function () { 
    $("input, select").change(function () {});
   });
});
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top