我的申请表里有几页表格。
如何确保表单的安全性,以便在用户导航离开或关闭浏览器选项卡时,提示他们确认是否确实希望保留未保存数据的表单?
我的申请表里有几页表格。
如何确保表单的安全性,以便在用户导航离开或关闭浏览器选项卡时,提示他们确认是否确实希望保留未保存数据的表单?
当前回答
您可以使用serialize()通过序列化表单值来创建URL编码的文本字符串,并检查表单在卸载前是否已更改
$(document).ready(function(){
var form = $('#some-form'),
original = form.serialize()
form.submit(function(){
window.onbeforeunload = null
})
window.onbeforeunload = function(){
if (form.serialize() != original)
return 'Are you sure you want to leave?'
}
})
参考这个链接https://coderwall.com/p/gny70a/alert-when-leaving-page-with-unsaved-form 作者:弗拉基米尔·西多伦科
其他回答
简短的回答:
let pageModified = true
window.addEventListener("beforeunload",
() => pageModified ? 'Close page without saving data?' : null
)
查看JavaScript onbeforeunload事件。它是微软引入的非标准JavaScript,但是它可以在大多数浏览器中运行,他们的onbeforeunload文档有更多的信息和示例。
简短的错误回答:
你可以通过处理beforeunload事件并返回一个非空字符串来做到这一点:
window.addEventListener("beforeunload", function (e) {
var confirmationMessage = 'It looks like you have been editing something. '
+ 'If you leave before saving, your changes will be lost.';
(e || window.event).returnValue = confirmationMessage; //Gecko + IE
return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
});
这种方法的问题是,提交表单也会触发卸载事件。这很容易通过添加一个标志,你提交一个表单:
var formSubmitting = false;
var setFormSubmitting = function() { formSubmitting = true; };
window.onload = function() {
window.addEventListener("beforeunload", function (e) {
if (formSubmitting) {
return undefined;
}
var confirmationMessage = 'It looks like you have been editing something. '
+ 'If you leave before saving, your changes will be lost.';
(e || window.event).returnValue = confirmationMessage; //Gecko + IE
return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
});
};
然后在提交时调用setter:
<form method="post" onsubmit="setFormSubmitting()">
<input type="submit" />
</form>
但是继续读下去……
长而正确的答案:
您也不希望在用户没有更改表单上的任何内容时显示此消息。一种解决方案是将beforeunload事件与“dirty”标志结合使用,该标志仅在确实相关时触发提示。
var isDirty = function() { return false; }
window.onload = function() {
window.addEventListener("beforeunload", function (e) {
if (formSubmitting || !isDirty()) {
return undefined;
}
var confirmationMessage = 'It looks like you have been editing something. '
+ 'If you leave before saving, your changes will be lost.';
(e || window.event).returnValue = confirmationMessage; //Gecko + IE
return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
});
};
现在要实现isDirty方法,有多种方法。
您可以使用jQuery和表单序列化,但是这种方法有一些缺陷。首先,你必须修改代码以适用于任何表单($("form").each()就可以了),但最大的问题是jQuery的serialize()只适用于已命名的、未禁用的元素,因此更改任何禁用或未命名的元素都不会触发脏标志。有一些变通方法,比如使控件为只读,而不是启用、序列化然后再次禁用控件。
因此,事态发展似乎是必然的趋势。你可以试着监听按键。这个事件有几个问题:
不会在复选框、单选按钮或其他通过鼠标输入更改的元素上触发。 将触发不相关的按键,如Ctrl键。 不会触发通过JavaScript代码设置的值。 不会触发剪切或粘贴文本通过上下文菜单。 不适用于虚拟输入,如数据选择器或复选框/单选按钮美化器,它们通过JavaScript将其值保存在隐藏的输入中。
从JavaScript代码中设置的值也不会触发change事件,因此也不适用于虚拟输入。
将输入事件绑定到页面上的所有输入(以及文本区域和选择)在旧的浏览器上不起作用,并且,像上面提到的所有事件处理解决方案一样,不支持撤销。当用户更改文本框然后取消该文本框,或者选中又取消选中复选框时,表单仍然被认为是脏的。
当您想实现更多的行为时,比如忽略某些元素,您将有更多的工作要做。
不要白费力气:
所以,在你考虑实施这些解决方案和所有需要的变通方法之前,要意识到你是在重新发明轮子,你很容易遇到别人已经为你解决了的问题。
如果您的应用程序已经使用了jQuery,那么您最好使用经过测试和维护的代码,而不是自己编写代码,并使用第三方库来完成所有这些工作。
jquery。Dirty(由@troseman在评论中建议)提供了正确检测表单是否被更改的函数,并防止用户在显示提示时离开页面。它还有其他有用的功能,比如重置表单,以及将表单的当前状态设置为“干净”状态。使用示例:
$("#myForm").dirty({preventLeaving: true});
jQuery的Are You Sure?插件,也很好用;查看他们的演示页面。使用示例:
<script src="jquery.are-you-sure.js"></script>
<script>
$(function() {
$('#myForm').areYouSure(
{
message: 'It looks like you have been editing something. '
+ 'If you leave before saving, your changes will be lost.'
}
);
});
</script>
并非所有地方都支持自定义消息
请注意,从2011年开始,Firefox 4就不支持这个对话框中的自定义消息。截至2016年4月,Chrome 51正在推出,自定义消息也将被删除。
在这个网站的其他地方存在一些替代方案,但我认为这样的对话框已经足够清楚了:
你想离开这个网站吗? 您所做的更改可能不会被保存。 离开待
下面的一句话对我很管用。
window.onbeforeunload = s => modified ? "" : null;
根据应用程序的状态将modified设置为true或false。
你可以在这里查看详细的解释: http://techinvestigations.redexp.in/comparison-of-form-values-on-load-and-before-close/
主要代码:
function formCompare(defaultValues, valuesOnClose) {
// Create arrays of property names
var aPropsFormLoad = Object.keys(defaultValues);
var aPropsFormClose = Object.keys(valuesOnClose);
// If number of properties is different,
// objects are not equivalent
if (aPropsFormLoad.length != aPropsFormClose.length) {
return false;
}
for (var i = 0; i < aPropsFormLoad.length; i++) {
var propName = aPropsFormLoad[i];
// If values of same property are not equal,
// objects are not equivalent
if (defaultValues[aPropsFormLoad]+"" !== valuesOnClose[aPropsFormLoad]+"") {
return false;
}
}
// If we made it this far, objects
// are considered equivalent
return true;
}
//add polyfill for older browsers, as explained on the link above
//use the block below on load
for(i=0; i < document.forms[0].elements.length; i++){
console.log("The field name is: " + document.forms[0].elements[i].name +
" and it’s value is: " + document.forms[0].elements[i].value );
aPropsFormLoad[i] = document.forms[0].elements[i].value;
}
//create a similar array on window unload event.
//and call the utility function
if (!formCompare(aPropsOnLoad, aPropsOnClose))
{
//perform action:
//ask user for confirmation or
//display message about changes made
}