我的申请表里有几页表格。
如何确保表单的安全性,以便在用户导航离开或关闭浏览器选项卡时,提示他们确认是否确实希望保留未保存数据的表单?
我的申请表里有几页表格。
如何确保表单的安全性,以便在用户导航离开或关闭浏览器选项卡时,提示他们确认是否确实希望保留未保存数据的表单?
当前回答
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;
其他回答
测试了伊莱·格雷的通用解决方案,只有在我把代码简化到
'use strict';
(() => {
const modified_inputs = new Set();
const defaultValue = 'defaultValue';
// store default values
addEventListener('beforeinput', evt => {
const target = evt.target;
if (!(defaultValue in target.dataset)) {
target.dataset[defaultValue] = ('' + (target.value || target.textContent)).trim();
}
});
// detect input modifications
addEventListener('input', evt => {
const target = evt.target;
let original = target.dataset[defaultValue];
let current = ('' + (target.value || target.textContent)).trim();
if (original !== current) {
if (!modified_inputs.has(target)) {
modified_inputs.add(target);
}
} else if (modified_inputs.has(target)) {
modified_inputs.delete(target);
}
});
addEventListener(
'saved',
function(e) {
modified_inputs.clear()
},
false
);
addEventListener('beforeunload', evt => {
if (modified_inputs.size) {
const unsaved_changes_warning = 'Changes you made may not be saved.';
evt.returnValue = unsaved_changes_warning;
return unsaved_changes_warning;
}
});
})();
对his的修改删除了target[defaultValue]的使用,只使用target。dataset[defaultValue]来存储真实的默认值。
我添加了一个'saved'事件监听器,'saved'事件将由您自己在保存操作成功时触发。
但是这个“通用”的解决方案只适用于浏览器,而不适用于应用程序的webview,例如微信浏览器。
为了使它在微信浏览器(部分)也工作,另一个改进再次:
'use strict';
(() => {
const modified_inputs = new Set();
const defaultValue = 'defaultValue';
// store default values
addEventListener('beforeinput', evt => {
const target = evt.target;
if (!(defaultValue in target.dataset)) {
target.dataset[defaultValue] = ('' + (target.value || target.textContent)).trim();
}
});
// detect input modifications
addEventListener('input', evt => {
const target = evt.target;
let original = target.dataset[defaultValue];
let current = ('' + (target.value || target.textContent)).trim();
if (original !== current) {
if (!modified_inputs.has(target)) {
modified_inputs.add(target);
}
} else if (modified_inputs.has(target)) {
modified_inputs.delete(target);
}
if(modified_inputs.size){
const event = new Event('needSave')
window.dispatchEvent(event);
}
});
addEventListener(
'saved',
function(e) {
modified_inputs.clear()
},
false
);
addEventListener('beforeunload', evt => {
if (modified_inputs.size) {
const unsaved_changes_warning = 'Changes you made may not be saved.';
evt.returnValue = unsaved_changes_warning;
return unsaved_changes_warning;
}
});
const ua = navigator.userAgent.toLowerCase();
if(/MicroMessenger/i.test(ua)) {
let pushed = false
addEventListener('needSave', evt => {
if(!pushed) {
pushHistory();
window.addEventListener("popstate", function(e) {
if(modified_inputs.size) {
var cfi = confirm('确定要离开当前页面嘛?' + JSON.stringify(e));
if (cfi) {
modified_inputs.clear()
history.go(-1)
}else{
e.preventDefault();
e.stopPropagation();
}
}
}, false);
}
pushed = true
});
}
function pushHistory() {
var state = {
title: document.title,
url: "#flag"
};
window.history.pushState(state, document.title, "#flag");
}
})();
查看JavaScript onbeforeunload事件。它是微软引入的非标准JavaScript,但是它可以在大多数浏览器中运行,他们的onbeforeunload文档有更多的信息和示例。
增加@codecaster的想法 您可以将此添加到表单的每个页面(在我的情况下,我以全局方式使用它,因此只有在表单上才会有此警告)将其函数更改为
if ( formSubmitting || document.getElementsByTagName('form').length == 0)
同时在表单提交上添加包括登录和取消按钮的链接,这样当人们按下取消或提交表单时,就不会在没有表单的每一页中触发警告…
<a class="btn btn-danger btn-md" href="back/url" onclick="setFormSubmitting()">Cancel</a>
你可以在这里查看详细的解释: 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
}
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;