开发者

Override core jQuery functions on Element level

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.


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


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);
    }
};


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);            
    };
};


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.)


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜