Переопределить основные функции jQuery на уровне элемента
Можно ли переопределить основные функции jQuery на уровне элемента, поэтому, например, я хочу переопределить функцию val() только на одном элементе <select> .
если я сделаю что-то вроде этого
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);
он работает так, как ожидалось, но как только я адресую одно и то же поле с новым экземпляром jQuery
var element = $('select');
element.val(19);
он перестает работать, потому что у нас есть новый экземпляр объекта jQuery. если я играю с функцией $. fn.val, я изменяю это поведение для всех объектов, которые поддерживают функцию val, что для меня немного.
Любая помощь будет оценена.
Спасибо.
Ответы
Ответ 1
Я сделал это расширение jquery для того, чтобы делать то, о чем вы говорите:
// 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);
}
};
};
Бонус за ответ Дэйва - вам не нужно загрязнять пространство имен данных jquery или беспокоиться о том, что кто-то переписывает этот ключ
Ответ 2
Исходя из ответа sdleihssirhc, но измененного только для применения к ранее сопоставленному элементу (элементам), поскольку вы сказали "только на одном <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
Каждый объект jQuery включает свойство selector
, которое содержит (duh) исходный селектор, который использовался для получения элементов (я на самом деле не работал с ним вообще, поэтому я не уверен, что с ним происходит когда вы проходите цепочку методов).
Итак, вы можете обернуть метод val
в функцию, которая проверяет свойство selector
, а затем решает, использовать ли вашу функцию или оригинал. Он будет выглядеть примерно так:
$.fn.old_val = $.fn.val;
$.fn.val = function () {
if (this.selector === 'select') {
console.log('The new val');
}
return this.old_val.apply(this, arguments);
};
У вас в основном было это раньше, я просто настраиваю его, чтобы оно применимо ко всем новым экземплярам jQuery.
(Кроме того, это довольно упрощенно, поэтому вы должны соответствующим образом изменить/улучшить его.)
Ответ 4
Да, это отличный вопрос. Я никогда не пробую эту вещь.
Отпустите:
Прежде чем начать, мы должны скопировать значение val-функции по умолчанию в другое место:
jQuery.fn.oldval = jQuery.fn.val;
Я бы написал функцию global, чтобы поймать функцию val():
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);
};
После этого вы можете установить функцию в свои Element-Data с помощью:
var element = jQuery(...);
jQuery.data(element.get(0), 'val-function', function(value){
/* Your Function here */
});
Я не знаю, работает ли это. Попробуй. Это только из моего мозга.
Ответ 5
Этот небольшой фрагмент позволяет переопределить методы jQuery.
Я нахожу @BT ответ довольно плохим, поскольку он создает дополнительный обратный вызов каждый раз, когда используется функция. Поэтому, если вы примените его к 1000 элементам, вызывается 1000 функций для КАЖДОГО val()
!
My overrideNodeMethod
может применяться к как можно большему количеству элементов. Он в основном проверяет данные hasOverriddenMethod
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);
};
};