Posso sostituire o modificare una funzione su un widget jQuery UI? Come? (Scimmia Patching)
-
19-09-2019 - |
Domanda
Se voglio modificare alcune delle capacità di un oggetto jQuery UI, sostituendo una delle funzioni, come dovrei andare a fare che?
Esempio: supponiamo che io volevo modificare il modo in cui il widget di jQuery autocomplete reso i suggerimenti. C'è un metodo sull'oggetto di completamento automatico che assomiglia a questo:
_renderItem: function( ul, item) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + item.label + "</a>" )
.appendTo( ul );
},
Potrei sostituire questo?
Credo che questo potrebbe essere chiamato Scimmia Patching .
Come? Cosa sintassi dovrei usare?
Soluzione
Non so su jQuery UI, ma in generale, questo è il modo per ridefinire una funzione:
(function() {
var _oldFunc = _renderItem;
_renderItem = function(ul,item) {
// do your thing
// and optionally call the original function:
return _oldFunc(ul,item);
}
})();
Il motivo di questo è avvolto in una funzione anonima è quello di creare una chiusura per memorizzare la funzione originale. In questo modo non può mai interferire con le variabili globali.
Modifica
Per fare questo ad un fn su un widget di jQuery UI, utilizzare la seguente sintassi:
A proposito: il modo per afferrare la funzione è simile a questo:
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
};
}
Altri suggerimenti
Lo so che è una vecchia questione, ma ho dovuto correggere alcuni bug su un vecchio progetto e ha avuto un problema con questo tipo di patch.
Meglio fare la funzione disponibile attraverso le opzioni oggetto, e poi mettere la logica specifica lì.
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');
}($));
Utilizzo-Esempio:
$('.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);
}
});