I would like to create a custom version of the sortable widget. I have been searching for documentation, but could not find something really accurate. The best information I found was : http://jqueryui.pbworks.com/Widget-factory.
I开发者_如何学运维 tried :
$.widget("ui.customsortable", $.extend($.ui.sortable, {
_init: function() {
$.widget.prototype._init.apply(this, arguments);
}
}));
But $.widget.prototype._init is not the function I want to call I guess since it is the $.widget prototype.
Then, I tried something I read here and there :
var _init = $.ui.sortable.prototype._init;
$.widget("ui.customsortable", $.extend($.ui.sortable, {
_init: function() {
_init.apply(this, arguments);
},
}));
But :
- I can't believe I have to store all methods I want to override like this, it is so ugly.
- It throws an error ("this.refresh is not a function"), which means the refresh method does not exist. Does that mean I would have to recreate all methods I want to override ? What's the point of extending in that case ?
Am I missing something here ?
Thanks for your help !
These are kinda strange answers. There is an optional second parameter - basewidget to inherit from. It's easy. No need to work with prototype and so on.
$.widget( "ui.customsortable", $.ui.sortable, {
_init: function() {
this.element.data('sortable', this.element.data('customsortable'));
// or whatever you want
}
} );
The second parameter is $.ui.sortable. I think it's all you need.
After several tries, I finally found out how to do this easily :
$.widget("ui.customsortable", $.extend({}, $.ui.sortable.prototype, {
_init: function(){
this.element.data('sortable', this.element.data('customsortable'));
return $.ui.sortable.prototype._init.apply(this, arguments);
}
// Override other methods here.
}));
$.ui.customsortable.defaults = $.extend({}, $.ui.sortable.defaults);
The key is to copy data from your custom widget to the original one. Don't forget to use $.ui.sortable.prototype.[overriden method].apply(this, arguments); in each overriden method.
Holly crap !
Regarding the selected solution above:
$.widget("ui.customsortable", $.extend(true, {}, $.ui.sortable.prototype, {
If you are extending one objects options into another, the [deep] flag of true will give you the desired results.
I'm using this in order to predefine start, stop and update functions:
$.widget('ui.custom_sortable_or_any_other_name', $.ui.sortable, {
_init: function() {
this.element.children().css('position', 'relative'); //for example
},
options : {
start: function (event, ui) {
ui.item.addClass('noclick'); //ui.item get's the item, that's my point
},
stop: function (event, ui) {
},
update: function (event, ui) {
$.ajax(); //some ajax you might want to do
}
}
});
I don't know just what you're after, when you say "extend a widget". In my case I wanted to change how the widget rendered itself, and fiddling with the CSS classes didn't satisfy. It was not a case of extending the behavior of a widget, but rather modifying the behavior of a widget.
So I over-rode the render method. The widget in question was the jQueryUI autocomplete, and the over-ride looked like this:
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
};
}
I just called that in $(document).ready()
.
related:
- Can I replace or modify a function on a jQuery UI widget? How?
- jQueryUI: how can I custom-format the Autocomplete plug-in results?
I used this one time:
$.ui.buttonset.prototype.value = function() {
return this.element.find('#' + this.element.find('label[aria-pressed="true"]').attr('for')).val();
}
精彩评论