Могу ли я заменить или изменить функцию в виджете jQuery UI? Как? (Патч обезьяны)

Если я хочу настроить некоторые возможности объекта пользовательского интерфейса jQuery, заменив одну из функций, как я могу это сделать?

Пример: предположим, я хотел изменить способ отображения предложений виджетом автозаполнения jQuery. Для объекта автозаполнения есть метод, который выглядит следующим образом:

_renderItem: function( ul, item) {
    return $( "<li></li>" )
        .data( "item.autocomplete", item )
        .append( "<a>" + item.label + "</a>" )
        .appendTo( ul );
},

Могу я заменить это?

Я думаю, это можно было бы назвать Monkey Patching.

Как? Какой синтаксис я бы использовал?


person Cheeso    schedule 12.03.2010    source источник


Ответы (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
  }; 
} 
person Philippe Leybaert    schedule 12.03.2010
comment
исправление обезьян или, как объясняет Пол Айриш, удары кулаком :) - paulirish.com/2010 / duck-punching-with-jquery - person Russ Cam; 13.03.2010
comment
Я понимаю эту часть - у меня проблемы с частью jQuery. Как пользовательский интерфейс jQuery определяет виджеты и так далее. - person Cheeso; 13.03.2010
comment
Неа! Я не знал, что такое было. - person Cheeso; 13.03.2010
comment
Итак, как мне получить доступ к переменной this внутри этой новой функции? - person ulu; 10.05.2012
comment
@Philippe Leybaert: Вы знаете, где находится метод позиции jQuery UI? Это не ограничивается одним конкретным виджетом. - person Jinghui Niu; 24.11.2016
comment
@ulu Хотя он не вызывал oldFn в своей замещенной функции, при желании вы можете вызвать oldFn.apply(this, arguments), чтобы сохранить аргумент this. - person Robert; 11.02.2020

Я знаю, что это старый вопрос, но мне просто нужно было исправить некоторые ошибки в старом проекте, и у меня возникла проблема с таким патчем.

Лучше сделайте функцию доступной через объект параметров, а затем поместите туда свою конкретную логику.

Пластырь:

(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);
  }
});
person HaNdTriX    schedule 16.01.2015