Saturday, February 12, 2011

Modified jQuery sortable for horizontal and vertical sorting

Recently I got a requirement to modify jQuery sortable for horizontal and vertical sorting capability. Basically we have to override some functions from jQuery sortable. By default jQuery sortable only provides vertical sorting. But for me requirement was some thing different. See the images below.

Sorting should be something like above. First of all let's see how jQuery sortable does this. If you see the source code there is a function called _rearrange(). This is the function responsible for rearranging the items. This function is called when there is some kind of intersection between items. For example if you want to swap item1 and item2, you have to drag item1 over item2. Code will detect intersection and it will rearrange the items. But in our case there is no intersection as we are dragging item 2 towards right hand side where there are no items.

So how we can do this? First of all we need to give style clear:both and float:left to all the items. When we set this style to any component, it will not allow any floating element on both sides. After setting above styles to all the items we get layout shown in left hand side image. As there is no intersection now we can not use _rearrange() function for changing position. We have to use another function available in jQuery sortable code, that is _mouseStop(). This is the function which is executed when we stop dragging. In this function first of all we need to identify drag direction . Drag direction should be either right top or right bottom. Once the direction is identified we have to set style clear:none for dragged object. Following is the code for it.

var horizontalDistance = Math.abs(this.offset.left - this.currentItem[0].offsetLeft);
var verticalDistance = Math.abs(this.offset.top - this.currentItem[0].offsetTop);
if(horizontalDistance > (this.currentItem[0].clientWidth/2) || verticalDistance > (this.currentItem[0].clientHeight))
{
if(this.offset.left>event.pageX){
this.horizontalDirection = 'left';
}
else{
this.horizontalDirection = 'right';
}
if(this.offset.top>event.pageY){
this.verticalDirection = 'up';
}
else{
this.verticalDirection = 'down';
}
if(this.horizontalDirection == 'right' && this.verticalDirection == 'up'){
this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
this.currentItem[0].style.clear = "none";
this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
}
}

To avoid unnecessary flicker effect, I have removed placeholder.

This is the code which you need to insert in _mouseStop() function at start. I am still working on it and doing some more changes to make it fully functional for all the scenarios so your suggestions are welcome. Please post a comment if you have any suggestion.




4 comments:

  1. great work dude, can u share ur code?

    ReplyDelete
  2. Hi, I'm interested by your code, i like to know what you plan if you drag an element from row1 position 2 to a row 4 position3 (it's an exemple) if you have some code i can help you on because i need a solution to the same problem (you can see here farkess.com/docs/aaa/) i like change this predefined layout to one with horizontal sorting.

    Thank you

    ReplyDelete
  3. Hi, BINGO I MADE IT JUST see it in action here :
    http://www.farkess.com/docs/aaa/

    ReplyDelete