Могу ли я заменить или изменить функцию в виджете jQuery UI? Как? (Обезьяна патчинг)
Если я захочу настроить некоторые возможности объекта пользовательского интерфейса jQuery, заменив одну из функций, как мне это сделать?
Пример: предположим, я хотел изменить способ, которым виджет автозаполнения jQuery отображал предложения. У объекта автозаполнения есть метод, который выглядит следующим образом:
_renderItem: function( ul, item) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + item.label + "</a>" )
.appendTo( ul );
},
Могу ли я заменить это?
Я думаю, это можно назвать " Обезьяньим патчем".
Как? Какой синтаксис я бы использовал?
2 ответа
Я не знаю о пользовательском интерфейсе jQuery, но в целом вы переопределяете функцию так:
(function() {
var _oldFunc = _renderItem;
_renderItem = function(ul,item) {
// do your thing
// and optionally call the original function:
return _oldFunc(ul,item);
}
})();
Причина, по которой это заключено в анонимную функцию, заключается в создании замыкания для хранения исходной функции. Таким образом, он никогда не сможет помешать глобальным переменным.
РЕДАКТИРОВАТЬ
Чтобы сделать это для fn на виджете пользовательского интерфейса jQuery, используйте этот синтаксис:
К вашему сведению: способ получить функцию выглядит следующим образом:
function monkeyPatchAutocomplete() {
// don't really need this, but in case I did, I could store it and chain
var oldFn = $.ui.autocomplete.prototype._renderItem;
$.ui.autocomplete.prototype._renderItem = function( ul, item) {
// whatever
};
}
Я знаю, что это старый вопрос, но мне просто нужно было исправить некоторые ошибки в старом проекте, и у меня была проблема с этим патчем.
Лучше сделайте функцию доступной через объект параметров, а затем поместите туда свою конкретную логику.
Patch:
(function monkeyPatchJQueryAutocomplete($) {
/**
* Proxies a private
* prototype method to the
* options Object
*
* @param {Object} obj
* @param {String} funcName
*/
function proxyPrivateMethodToOptions(obj, funcName) {
var __super = obj.prototype[funcName];
obj.prototype[funcName] = function() {
if (this.options[funcName]) {
return this.options[funcName].apply(this, arguments);
}
return __super.apply(this, arguments);
};
}
// Make the private _renderItem
// method available through the options Object
proxyPrivateMethodToOptions($.ui.autocomplete, '_renderItem');
// We can do this for other methods as well:
proxyPrivateMethodToOptions($.ui.autocomplete, '_renderMenu');
}($));
Использование-Пример:
$('.some-input').autocomplete({
_renderItem: function(ul, item) {
console.log('here we can reference the old func via: ', __super);
return $("<li>")
.append($("<a>").text(item.label))
.appendTo(ul);
}
});