Javascript 自定义jQuery插件:事件行为不符合预期
我正在编写一个轻量级jQuery插件来检测脏表单,但在处理事件时遇到了一些问题。正如您在下面的代码中所看到的,该插件将一个事件侦听器附加到“beforeunload”上,该事件侦听器测试表单是否脏,并生成一个弹出窗口,如果是这样的话 还有一个附加到表单“提交”的事件侦听器,理论上应该删除该特定表单的“beforeunload”侦听器(即,我提交的当前表单不应该进行污垢测试,但页面上的其他表单应该进行测试) 我插入了一堆console.log语句来尝试调试它,但没有成功。想法Javascript 自定义jQuery插件:事件行为不符合预期,javascript,events,Javascript,Events,我正在编写一个轻量级jQuery插件来检测脏表单,但在处理事件时遇到了一些问题。正如您在下面的代码中所看到的,该插件将一个事件侦听器附加到“beforeunload”上,该事件侦听器测试表单是否脏,并生成一个弹出窗口,如果是这样的话 还有一个附加到表单“提交”的事件侦听器,理论上应该删除该特定表单的“beforeunload”侦听器(即,我提交的当前表单不应该进行污垢测试,但页面上的其他表单应该进行测试) 我插入了一堆console.log语句来尝试调试它,但没有成功。想法 // Check
// Checks if any forms are dirty if leaving page or submitting another forms
// Usage:
// $(document).ready(function(){
// $("form.dirty").dirtyforms({
// excluded: $('#name, #number'),
// message: "please don't leave dirty forms around"
// });
// });
(function($) {
////// private variables //////
var instances = [];
////// general private functions //////
function _includes(obj, arr) {
return (arr._indexOf(obj) != -1);
}
function _indexOf(obj) {
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (obj, fromIndex) {
if (fromIndex == null) {
fromIndex = 0;
} else if (fromIndex < 0) {
fromIndex = Math.max(0, this.length + fromIndex);
}
for (var i = fromIndex, j = this.length; i < j; i++) {
if (this[i] === obj)
return i;
}
return -1;
};
}
}
////// the meat of the matter //////
// DirtyForm initialization
var DirtyForm = function(form, options) {
// unique name for testing purposes
this.name = "instance_" + instances.length
this.form = form;
this.settings = $.extend({
'excluded' : [],
'message' : 'You will lose all unsaved changes.'
}, options);
// remember intial state of form
this.memorize_current();
// activate dirty tracking, but disable it if this form is submitted
this.enable();
$(this.form).on('submit', $.proxy(this.disable, this));
// remember all trackable forms
instances.push(this);
}
// DirtyForm methods
DirtyForm.prototype = {
memorize_current: function() {
this.originalForm = this.serializeForm();
},
isDirty: function() {
var currentForm = this.serializeForm();
console.log("isDirty called...")
return (currentForm != this.originalForm);
},
enable: function() {
$(window).on('beforeunload', $.proxy(this.beforeUnloadListener, this));
console.log("enable called on " + this.name)
},
disable: function(e) {
$(window).off('beforeunload', $.proxy(this.beforeUnloadListener, this));
console.log("disable called on " + this.name)
},
disableAll: function() {
$.each(instances, function(index, instance) {
$.proxy(instance.disable, instance)
});
},
beforeUnloadListener: function(e) {
console.log("beforeUnloadListener called on " + this.name)
console.log("... and it is " + this.isDirty())
if (this.isDirty()) {
e.returnValue = this.settings.message;
return this.settings.message;
}
},
setExcludedFields: function(excluded) {
this.settings.excluded = excluded;
this.memorize_current();
this.enable();
},
serializeForm: function() {
var blacklist = this.settings.excludes
var filtered = [];
var form_elements = $(this.form).children();
// if element is not in the excluded list
// then let's add it to the list of filtered form elements
if(blacklist) {
$.each(form_elements, function(index, element) {
if(!_includes(element, blacklist)) {
filtered.push(element);
}
});
return $(filtered).serialize();
} else {
return $(this.form).serialize();
}
}
};
////// the jquery plugin part //////
$.fn.dirtyForms = function(options) {
return this.each(function() {
new DirtyForm(this, options);
});
};
})(jQuery);
无论何时调用
$.proxy()
,它都会返回一个新的函数。因此,
$(window).off('beforeunload', $.proxy(this.beforeUnloadListener, this));
不会有任何效果,因为您正在尝试解除未绑定的函数的绑定
您必须存储对使用$.proxy
创建的函数的引用,以便以后可以解除绑定:
enable: function() {
this.beforeUnloadListener = $.proxy(DirtyForm.prototype.beforeUnloadListener, this);
$(window).on('beforeunload', this.beforeUnloadListener);
console.log("enable called on " + this.name)
},
disable: function(e) {
$(window).off('beforeunload', this.beforeUnloadListener);
console.log("disable called on " + this.name)
},
无论何时调用
$.proxy()
,它都会返回一个新的函数。因此,
$(window).off('beforeunload', $.proxy(this.beforeUnloadListener, this));
不会有任何效果,因为您正在尝试解除未绑定的函数的绑定
您必须存储对使用$.proxy
创建的函数的引用,以便以后可以解除绑定:
enable: function() {
this.beforeUnloadListener = $.proxy(DirtyForm.prototype.beforeUnloadListener, this);
$(window).on('beforeunload', this.beforeUnloadListener);
console.log("enable called on " + this.name)
},
disable: function(e) {
$(window).off('beforeunload', this.beforeUnloadListener);
console.log("disable called on " + this.name)
},
我在解决方案上领先了你大约5分钟,但我给你一个重点,因为这确实是正确的答案:D我最终得到了稍微不同的代码,但解决了你提到的问题。请看我在问题中的编辑。我在解决方案上领先了你大约5分钟,但我给你一个重点,因为这确实是正确的答案:D我最终使用了稍微不同的代码,但解决了你提到的问题。请看我在问题中的编辑。嗨,皮埃尔,你能在你的自定义插件上有一个实时演示吗。我真的很感激你发布的解决方案,当然@Roy,我刚刚上传了一个演示给Hi Pierre,你能在自定义插件上有一个实时演示吗。我真的很感激你发布的解决方案,当然@Roy,我刚刚上传了一个演示到