Reputation: 4526
In jQueryUI, the Widget factory can be use to extend the functionality of existing widgets. This is be useful to tweak private methods (like _renderItem
) for example.
$.widget( "ui.autocomplete", $.ui.autocomplete, {
_renderItem: function( ul, item ) {
}
});
Another way (which AFAIK give similar results) is to use jQuery.extend() method :
$.extend( $.ui.autocomplete, {
_renderItem: function( ul, item ) {
},
});
jQueryUI implementation seems to use both in some places (line 3335, or search for "live region extension" in the js file )
My question is : is there any difference between these two ways of extending a widget and which one should I better use, as good practice ?
Upvotes: 1
Views: 382
Reputation: 7073
Using $.extend
as you have there won't work because you're adding methods directly to the constructor function, you'd need to add the methods to either the constructor's prototype or directly on an instance.
The following would work however:
$.extend($.ui.autocomplete.prototype, {
foo: true
});
This will mutate the original autocomplete class so as a side effect of this any instances instantiated before the extend will also be mutated, i.e.
var instance = $('input').autocomplete().data('uiAutocomplete');
console.log(instance.foo); // undefined
$.extend($.ui.autocomplete.prototype, { foo: true });
console.log(instance.foo); // true
On the other hand the widget factory will create a new 'class' which inherits from the existing $.ui.autocomplete
(which just happens to override the reference to the original autocomplete constructor):
var instance = $('input').autocomplete().data('uiAutocomplete');
console.log(instance.foo); // undefined
$.widget('ui.autocomplete', $.ui.autocomplete, { foo: true });
console.log(instance.foo); // undefined (still)
The widget factory will also let you store the constructor in a separate namespace so you could use both the original and the extended constructor at once:
$.widget('foo.autocomplete', $.ui.autocomplete, { foo: true });
console.log($.foo.autocomplete !== $.ui.autocomplete); // true
You would need to manually re-bridge the original constructor to a jQuery plugin to be able to instantiate it in a 'jQuery way':
$.widget.bridge('originalAutocomplete', $.ui.autocomplete);
$('input').autocomplete(); // instanceof $.foo.autocomplete && instanceof $.ui.autocomplete
$('input').originalAutocomplete(); // instance of $.ui.autocomplete only
In short... $.widget
would more commonly be recommended as a best practice vs $.extend
, but it depends on your use case.
Upvotes: 1