当前位置:  开发笔记 > 编程语言 > 正文

检测未保存的更改

如何解决《检测未保存的更改》经验,为你挑选了8个好方法。

我需要在ASP .Net应用程序中实现"未保存的更改"提示.如果用户修改了Web表单上的控件,并尝试在保存之前导航,则会出现一个提示,提示他们有未保存的更改,并为他们提供取消和保留在当前页面的选项.如果用户未触及任何控件,则不应显示提示.

理想情况下,我想在JavaScript中实现它,但在我开始编写自己的代码之前,是否有任何现有的框架或推荐的设计模式来实现这一目标?理想情况下,我希望能够轻松地在多个页面上重复使用,而且变化很小.



1> Aaron Powell..:

使用jQuery:

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

onunload/ 结合onbeforeunload根据需要方法.

从注释中,以下引用所有输入字段,而不重复代码:

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

使用$(":input")是指所有输入,textarea,select和按钮元素.


Upvote,因为我使用了这个解决方案,但有一个稍微简单的方法.如果你使用:$(':input').change(function(){那么它适用于所有输入字段,你不需要复制其他输入类型.$(":input")选择所有输入,textarea ,选择和按钮元素.
只是一个提示.如果表单是脏的,它仍然不意味着它包含真正改变的数据.为了更好的可用性,您必须将旧数据与新数据进行比较;)
我认为这可能在Firefox中存在问题.如果用户修改了表单,然后单击浏览器刷新按钮,页面将被重新加载,Firefox将使用用户以前的条目填充表单 - 而不会触发更改事件.现在表单将变脏,但除非用户进行另一次编辑,否则不会设置该标志.

2> Jonny Buchan..:

一块拼图:

/**
 * 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} true if the form is dirty, false
 *                   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事件注册.



3> Wayne..:

在.aspx页面中,您需要一个Javascript函数来判断表单信息是否"脏"



并在代码隐藏中,将触发器添加到输入字段以及重置提交/取消按钮....

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



4> 小智..:

以下使用浏览器的onbeforeunload函数和jquery来捕获任何onchange事件.它还会查找任何提交或重置按钮以重置指示已发生更改的标志.

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;



5> tbreffni..:

感谢大家的回复.我最终使用JQuery和Protect-Data插件实现了一个解决方案.这允许我自动将监控应用于页面上的所有控件.

但是有一些注意事项,特别是在处理ASP .Net应用程序时:

当用户选择取消选项时,doPostBack函数将抛出JavaScript错误.我不得不手动在doPostBack中的.submit调用周围放置一个try-catch来抑制它.

在某些页面上,用户可以执行执行回发到同一页面的操作,但不是保存.这会导致任何JavaScript逻辑重置,因此它认为在回发之后没有任何内容发生变化.我必须实现一个隐藏的文本框,该文本框与页面一起回发,并用于保存一个简单的布尔值,指示数据是否脏.这会在回发中持续存在.

您可能希望页面上的一些回发不触发对话框,例如"保存"按钮.在这种情况下,您可以使用JQuery添加一个OnClick函数,该函数将window.onbeforeunload设置为null.

希望这对任何必须实现类似功能的人都有帮助.



6> reto..:

以下解决方案适用于原型(在FF,IE 6和Safari中测试).它使用通用表单观察器(触发表单:在修改表单的任何字段时更改),您也可以将其用于其他内容.

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



7> skibulk..:

这是一个简单的javascript/jquery解决方案.它由用户解释"undos",它被封装在一个函数中以便于应用,并且它在提交时不会失败.只需调用该函数并传递表单的ID即可.

此功能在加载页面时将表单序列化一次,并在用户离开页面之前再次序列化表单.如果两个表单状态不同,则会显示提示.

尝试一下: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');
});


我试过你的方法.它适用于Chrome和Firefox,但不能使它适用于Ipad Mini上的Safari.

8> MhdSyrwan..:

常规解决方案支持给定页面中的多个表单(只需复制并粘贴到项目中)

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

注意:此解决方案与其他解决方案相结合,可创建通用集成解决方案.

特征:

只需复制并粘贴到您的应用中即可.

支持多种形式.

你可以设置样式或使动作变脏,因为它们是"形式脏"的类.

您可以通过添加"忽略更改"类来排除某些表单.

推荐阅读
k78283381
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有