Могу ли я заменить или изменить функцию в виджете jQuery UI? Как? (Обезьяна патчинг) - PullRequest
10 голосов
/ 13 марта 2010

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

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

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

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

Я думаю, что это можно назвать Обезьяна Patching .

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

Ответы [ 2 ]

18 голосов
/ 13 марта 2010

Я не знаю о пользовательском интерфейсе jQuery, но в целом вы переопределяете функцию:

(function() {
   var _oldFunc = _renderItem;

   _renderItem = function(ul,item) {
      // do your thing
      // and optionally call the original function:
      return _oldFunc(ul,item);
   }
})();

Причина, по которой это заключено в анонимную функцию, заключается в создании замыкания для хранения исходной функции. Таким образом, он никогда не будет мешать глобальным переменным.


EDIT
Чтобы сделать это для 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
  }; 
} 
0 голосов
/ 16 января 2015

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

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

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