题
我有一个要求实施一个"未保存的变化"的提示在一个ASP。净的应用程序。如果一个用户修改控制对网络的形式,并试图离开之前挽救,一个提示应出现警告他们,他们有未保存的变化,并得到他们的选择取消和停留在目前的页。提示,不应该显示如果用户没有碰过任何控制。
理想情况下,我想要实现这JavaScript,但是在我走之前的道路滚是我自己的代码,是否有任何现有的构架或建议的设计图案为实现这个吗?理想的是我想的东西,可以很容易被重复利用跨多个网页以最小的变化。
解决方案
使用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和button元素。
其他提示
谜题的一部分:
/**
* 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页面中,您需要一个Javascript函数来判断表单信息是否为“脏”
<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()">
并在代码隐藏中,将触发器添加到输入字段以及重置提交/取消按钮....
btnSubmit.Attributes.Add("onclick", "isDirty = 0;");
btnCancel.Attributes.Add("onclick", "isDirty = 0;");
txtName.Attributes.Add("onchange", "setDirty();");
txtAddress.Attributes.Add("onchange", "setDirty();");
//etc..
以下使用浏览器的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;
谢谢你的回复每一个人。我结束了在执行一个解决方案使用能力和将 保护数据 插件。这让我可以自动适用监控的所有控制在一个页面上。
有几点需要注意但是,尤其是在处理一个ASP。网应用程序:
当一个用户选择取消的选择,doPostBack功能将把一JavaScript错误。我不得不手动把一个试试-抓住周围。提交叫内doPostBack到抑制。
在一些页面上,用户可以执行的行动,执行一个回到同一页,但不是保存。这种结果在任何JavaScript逻辑重置,所以,它认为没有任何改变之后回发时的东西。我不得不实施一个隐藏的文本,得到的回发的网页,并用于举行一个简单的布尔表示值的数据是否是肮脏的。这得到持续的跨回发。
你可能会想要一些回发页面上不引发对话,例如保存按钮。在这种情况下,可以使用JQuery添加一击的功能设置窗口。onbeforeunload为空。
希望这有助于其他任何人已经实施类似的东西。
以下解决方案适用于原型(在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);
这是一个简单的javascript / jquery解决方案。它解释了“撤消”由用户将其封装在一个易于应用的功能中,并且在提交时不会失败。只需调用该函数并传递表单的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');
});
一般的解决方案支持的多种形式在一个特定网页(只是复印,并粘贴在你的项目)
$(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 的开源jQuery插件做出了贡献。
该插件旨在与动态添加的HTML一起使用,支持多种形式,几乎可以支持任何对话框架,在回滚对话框之前回退到浏览器,有一个可插拔的帮助框架,支持从自定义编辑器获取脏状态(tinyMCE插件包含),在iFrames中工作,可以随意设置或重置脏状态。
使用jQuery检测表单更改非常简单:
var formInitVal = $('#formId').serialize(); // detect form init value after form is displayed
// check for form changes
if ($('#formId').serialize() != formInitVal) {
// show confirmation alert
}
我扩展了Slace的上述建议,包括大多数可编辑元素,并且还排除了某些元素(在这里使用称为“srSearch”的CSS样式)导致设置脏标志。
<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.js插件 fleegix.form.diff
( http://js.fleegix.org/plugins/form/diff )是为...创建的。使用 fleegix.form.toObject
( http://js.fleegix.org/ref#fleegix .form.toObject )并将其保存在变量中,然后在卸载时使用 fleegix.form.diff
与当前状态进行比较。很容易就是馅饼。
一种方法,使用数组来保存变量,以便跟踪变化。
这是检测更改的一种非常简单的方法,但其余的并不那么优雅。
另一种相当简单和小巧的方法,来自 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>
在IE document.ready中无法正常工作,它会更新输入值。
所以我们需要在document.ready函数中绑定load事件,该函数也将处理IE浏览器。
下面是你应该放在document.ready函数中的代码。
$(document).ready(function () {
$(window).bind("load", function () {
$("input, select").change(function () {});
});
});