Monday, July 13, 2009

jQuery UI resizable plugin - relative position issues and external handles

Well, I have been trying to build this control and from day one I had weird issues with the display on Internet Explorer 7. Apparently, because of a bug Rick Strahl reported in his blog, elements that have the position relative escape their containers when the containers themselves are not relative. You will see there a comment from me when I hadn't really understood the problem :(

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


Anonymous said...

your site contains a lot of bugs.. hehe :)

Siderite said...

Why is everybody fixating on the bugs? There are cute cats there as well :(

Anonymous said...

you saved my lot of time... from last night i was trying to solve it but unable to do as im not javascript expert but want to use jquery....

continue ur good work....
thanks a lot.!!!!!!!!

Dipak C.

Anonymous said...

I am getting error pane. disableSelection() is not defined function in following code... If i comment that line code is working but is there is proper solution for it.
its a jquery.sheet plugin

if (s.editable) {
var formula = jS.obj.formula();
.mousedown(function(e) {
if (jS.isTd( {
return false;
//Dipak .disableSelection()


Siderite said...

The code you posted is not really related to the jQuery UI resizable plugin. To me is seems there is an object or a namespace called Dipak that should contain the disableSelection function. And it doesn't. Since you are Dipak, I presume the error is in your code...

Anonymous said...

You're a fucking idiot for putting flies on your site. Dick.

Siderite said...

I hereby apologize to people who have a deep phobia of flies and/or cats. I have never intended to hurt your feelings. I am sorry.