可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Is it possible to override core jQuery functions on Element level, so for an example, i want to override val() function only on one <select> element.
if i do something like this
var element = $('select');
var old_val = element.val;
element.val = function () {
console.log('The new val');
return old_val.apply(this, arguments);
}
element.val(19);
it works as expected, but as soon as i address the same field with new jQuery instance
var element = $('select');
element.val(19);
it stops working because we have new instance of jQuery object. if i fiddle with $.fn.val function i change that behavior for all objects who support val function, which is a bit to much for me.
Any help will be appreciated.
Thank you.
回答1:
I made this jquery extension for doing just what you're talking about:
// overrides a method thats supposed to be called on a single node (a method like val)
$.fn.overrideNodeMethod = function(methodName, action) {
var originalVal = $.fn[methodName];
var thisNode = this;
$.fn[methodName] = function() {
if (this[0]==thisNode[0]) {
return action.apply(this, arguments);
} else {
return originalVal.apply(this, arguments);
}
};
};
Bonus over Dave's answer - you don't have to pollute the jquery data namespace or worry about someone overwriting that key
回答2:
Based on answer by sdleihssirhc but modified to only apply to the previously matched element(s), since you said "only on one <select> element".
element.data('custom_val', function() {
console.log('The new val');
});
$.fn.old_val = $.fn.val;
$.fn.val = function () {
var custom_val = this.data('custom_val');
if (custom_val) {
return custom_val.apply(this, arguments);
} else {
return this.old_val.apply(this, arguments);
}
};
回答3:
This little snippet allows to override jQuery methods.
I find @BT answer quite bad as it creates extra callback every time function is used. So if you'll apply it to 1000 elements, 1000 functions for EVERY val()
are called!
My overrideNodeMethod
can be applied to as many elements as many times as you want. It basically checks hasOverriddenMethod
data
var originaljQueryMethods = {};
for(var method in $.fn){
originaljQueryMethods[method] = $.fn[method];
};
$.fn.callOriginalMethod = function(method, args) {
return originaljQueryMethods[method].apply(this, args);
};
$.fn.overrideNodeMethod = function(method, callback) {
var dataKey = "hasOverriddenMethod." + method;
$(this).callOriginalMethod("data", [dataKey, callback]);
$.fn[method] = function() {
var callback = $(this).callOriginalMethod("data", [dataKey])
if (callback) {
return callback.apply(this, arguments);
}
return $(this).callOriginalMethod(method, arguments);
};
};
回答4:
Every jQuery object includes a selector
property, which contains (duh) the original selector that was used to get the elements (I haven't really worked with it at all, so I'm not sure what happens to it as you go through a chain of methods).
So you could wrap the val
method in a function that checks the selector
property, and then decides whether to use your function or the original. It would look something like this:
$.fn.old_val = $.fn.val;
$.fn.val = function () {
if (this.selector === 'select') {
console.log('The new val');
}
return this.old_val.apply(this, arguments);
};
You basically had this before, I'm just tweaking it so it will apply to all new jQuery instances.
(Also, this is pretty simplistic on it's own; you'll want to modify/enhance it accordingly.)
回答5:
Yeah this a great question. I'd never try this thing.
Let's go:
Before we start we should copy the default val-function to another place:
jQuery.fn.oldval = jQuery.fn.val;
I would write a function global to catch the val() function:
jQuery.fn.val = function(value) {
var t = jQuery(this);
if(t.get(0)) {
//Check for overwritten function
var func = jQuery.data(t.get(0), 'val-function');
if(jQuery.isFunction(func)) {
return func(value);
}
}
//Use old function
return jQuery(this).oldval(value);
};
After that you can set a function to your Element-Data with:
var element = jQuery(...);
jQuery.data(element.get(0), 'val-function', function(value){
/* Your Function here */
});
I don't know if this works. Try it. It's only from my brain.