jQuery UI resizable plugin - relative position issues and external handles

With the jQuery UI resizable plugin, the base functionality is to change the entire body of the resized control to position relative, causing all kind of trouble, only to permit the resize handles to move around the element (like the south handle having a bottom setting of aproximately 0 px). So, after making all kinds of changes to the javascript in order to solve the IE7 relative position bug, I finally submited and started changing the resizable plugin itself.
The idea was simple: remove position relative, make two divs, one inner and one outer, resize them both in the same time, while another div placed in between would act as the south handle. But it didn't work. I couldn't set an element external to the resized element as the handle, as explained here.
The fix above, though, doesn't entirely show the dimension of the problem. The resizable plugin is incredibly buggy! The documentation says that you can specify custom handles either as jQuery strings or as elements or jQuery objects. That is not correct, as the handles passed as objects are stored in a handles field, but then another _handles field is initialized and the first completely ignored! Also, as in the post above, you need to bind the javascript events to every external element as well, since the original mouse capturing events are placed only on the resized element.
Ok, so the fix is this:
- look for a this._handles = $('.ui-resizable-handle', this.element).disableSelection(); line. This is where handles is being ignored. Replace it with:
if (this.handles) {
var handles=$('nothingReally');
for (var i in this.handles)
handles[handles.length++]=this.handles[i][0];
this._handles=handles;
} else {
this._handles = $('.ui-resizable-handle', this.element)
}
$.each(this._handles,function() { $(this).disableSelection(); }); - look for a _mouseInit: function you will see there a line like this.element.bind... you need to add a similar one underneath for all the handles:
// Add mouse events for the handles as well
if (this._handles)
for (var i=0; i<this._handles.length; i++) {
$(this._handles[i]).bind('mousedown.'+this.widgetName, function(event) {
return self._mouseDown(event);
})
.bind('click.'+this.widgetName, function(event) {
if(self._preventClickEvent) {
self._preventClickEvent = false;
event.stopImmediatePropagation();
return false;
}
});
}
The change here allows to pass objects (either elements or jQueries) as handles, thus allowing for external elements to act as handles. Removing 'this.element' from the query is not a good idea in case you want to use more resizable controls on the same page. You want only children of a container to act as handles. It could work to move upwards on the control tree until you can get a child that fits the string jquery, but I think that's overkill.
Hope that helps someone.