我的申请表里有几页表格。
如何确保表单的安全性,以便在用户导航离开或关闭浏览器选项卡时,提示他们确认是否确实希望保留未保存数据的表单?
我的申请表里有几页表格。
如何确保表单的安全性,以便在用户导航离开或关闭浏览器选项卡时,提示他们确认是否确实希望保留未保存数据的表单?
当前回答
您可以使用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 作者:弗拉基米尔·西多伦科
其他回答
通过jquery
$('#form').data('serialize',$('#form').serialize()); // On load save form current state
$(window).bind('beforeunload', function(e){
if($('#form').serialize()!=$('#form').data('serialize'))return true;
else e=null; // i.e; if form state change show warning box, else don't show it.
});
你可以谷歌JQuery表单序列化函数,这将收集所有表单输入并保存在数组中。我想这个解释就足够了:)
Eerik Sven Puudist的解决方案…
var isSubmitting = false;
$(document).ready(function () {
$('form').submit(function(){
isSubmitting = true
})
$('form').data('initial-state', $('form').serialize());
$(window).on('beforeunload', function() {
if (!isSubmitting && $('form').serialize() != $('form').data('initial-state')){
return 'You have unsaved changes which will not be saved.'
}
});
})
…在复杂的面向对象设置中,自发地为我完成了这项工作,而不需要任何更改。
我应用的唯一更改是引用具体的表单(每个文件只有一个表单),称为“formForm”('form' -> '#formForm'):
<form ... id="formForm" name="formForm" ...>
特别出色的是,提交按钮被“单独保留”了。
此外,它也适用于最新版本的Firefox(截至2019年2月7日)。
我做了下面的代码。它可以比较所有字段的变化(除了那些用. ignoredirty类标记的字段),也可以只比较当前可见的字段。它可以为Javascript添加的新字段重新初始化。因此,我保存的不是表单状态,而是每个控件的状态。
/* Dirty warning for forms */
dirty = (skipHiddenOrNullToInit) => {
/* will return True if there are changes in form(s)
for first initialization you can use both: .dirty(null) or .dirty() (ignore its result)
.dirty(null) will (re)initialize all controls - in addititon use it after Save if you stay on same page
.dirty() will initialize new controls - in addititon use it if you add new fields with JavaScript
then
.dirty() (or: .dirty(false)) says if data are changed without regard to hidden fields
.dirty(true) says if data are changed with regard to hidden fields (ie. fields with .d-none or .hidden class)
controls with .ignoreDirty class will be skipped always
previous about .d-none, .hidden, .ignoreDirty applies to the control itself and all its ancestors
*/
let isDirty = false;
let skipSelectors = '.ignoreDirty';
if (skipHiddenOrNullToInit) {
skipSelectors += ', .d-none, .hidden'
} else if (skipHiddenOrNullToInit === undefined) {
skipHiddenOrNullToInit = false;
}
$('input, select').each(
function(_idx, el) {
if ($(el).prop('type') !== 'hidden') {
let dirtyInit = $(el).data('dirty-init');
if (skipHiddenOrNullToInit === null || dirtyInit === undefined) {
try {
isChromeAutofillEl = $(el).is(":-webkit-autofill");
} catch (error) {
isChromeAutofillEl = false;
}
if (isChromeAutofillEl && $(el).data('dirty-init') === undefined) {
setTimeout(function() { // otherwise problem with Chrome autofilled controls
$(el).data('dirty-init', $(el).val());
}, 200)
} else {
$(el).data('dirty-init', $(el).val());
}
} else if ($(el).closest(skipSelectors).length === 0 && dirtyInit !== $(el).val()) {
isDirty = true;
return false; // breaks jQuery .each
}
}
}
);
return isDirty;
}
我有额外的Chrome自动填充值的麻烦,因为它很难初始化和已经加载它们。所以我不初始化页面加载,但在任何focusin事件。(但是:也许JavaScript更改控件值仍然存在问题。)我使用下面的代码,我在页面加载调用:
let init_dirty = (ifStayFunc) => {
/* ifStayFunc: optional callback when user decides to stay on page
use .clearDirty class to avoid warning on some button, however:
if the button fires JavaScript do't use .clearDirty class and instead
use directly dirty(null) in code - to be sure it will run before window.location */
$('input, select').on('focusin', function(evt) {
if (!$('body').data('dirty_initialized')) {
dirty();
$('body').data('dirty_initialized', true);
}
});
window.addEventListener('beforeunload', (evt) => {
if (dirty(true)) {
if (ifStayFunc) {
ifStayFunc();
}
evt.preventDefault();
evt.returnValue = ''; // at least Google Chrome requires this
}
});
$('.clearDirty').on('click', function(evt) {
dirty(null);
});
};
因此,我将. cleardirty类添加到提供Save的按钮中,这样就可以防止在这种情况下出现警告。 回调ifStayFunc允许我做一些事情,如果用户将停留在页面上,而他是警告。通常我可以显示额外的保存按钮(如果我仍然只看到一些默认/主按钮,这使得安全+SomethingMore -我想允许保存没有这个“SomethingMore”)。
根据之前的回答,并从堆栈溢出的不同地方拼凑在一起,这里是我提出的解决方案,当你实际上想要提交你的更改时,它可以处理这种情况:
window.thisPage = window.thisPage || {};
window.thisPage.isDirty = false;
window.thisPage.closeEditorWarning = function (event) {
if (window.thisPage.isDirty)
return 'It looks like you have been editing something' +
' - if you leave before saving, then your changes will be lost.'
else
return undefined;
};
$("form").on('keyup', 'textarea', // You can use input[type=text] here as well.
function () {
window.thisPage.isDirty = true;
});
$("form").submit(function () {
QC.thisPage.isDirty = false;
});
window.onbeforeunload = window.thisPage.closeEditorWarning;
值得注意的是,IE11似乎要求closeEditorWarning函数返回undefined才能不显示警报。
你可以在这里查看详细的解释: 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
}