Animated Grid Sorter Widget

by tcghyit

HTML

<div class='grid'>
click and drag 
</div>
<div class='grid'>
click and drag 
</div>
<div class='grid'>
click and drag 
</div>
<div class='grid'>
click and drag 
</div>
<div class='grid'>
click and drag 
</div>
<div class='grid'>
click and drag 
</div>
<div class='grid'>
click and drag 
</div>
<div class='grid'>
click and drag 
</div><div class='grid'>
click and drag 
</div>
<div class='grid'>
click and drag 
</div>
<div class='grid'>
click and drag 
</div>
<div class='grid'>
click and drag 
</div>
<div class='grid'>
click and drag 
</div>
<div class='grid'>
click and drag 
</div>
<div class='grid'>
click and drag 
</div>
<div class='grid'>
click and drag 
</div>

CSS

.grid{
    border: 1px solid red;
    float: left;
    padding: 5px;
}

JavaScript

/*
 * 
 * Animated Grid Sorter 
 * Version 1.0
 * @requires jQuery v1.5.2
 * @requires jQuery UI 1.8.12
 *
 * Author: Eric Bowden
 */
//TODO: Elements of different sizes doesn't work

(function($) {
	"use strict";

	$.widget("ui.animatedgridsorter", {
	
		options: {
		  dragDistance: 0,
		  startColor: '#f00',
		  stopColor: '#fff',
		  zIndex: 9001,
		  helper: 'clone'
		},
		
		_animate: function($tmpEl,$moveToEl) {

			var oldTop = $tmpEl.position().top;
			var oldLeft = $tmpEl.position().left;
			var newTop = $moveToEl.position().top;
			var newLeft = $moveToEl.position().left;
	
			var $clone;
	
			if($tmpEl.data('cloneExists')) {
				$clone = $tmpEl.data('cloneExists');
				$clone.css({backgroundColor: this.options.startColor});
			} else {
				$clone = $tmpEl.clone().css({
					backgroundColor: this.options.startColor,
					position: 'absolute',
					top: oldTop,
					left: oldLeft
				}).disableSelection();        
				$tmpEl.parent().append($clone);     
				$tmpEl.data('cloneExists',$clone);
				$tmpEl.css('visibility', 'hidden');
			}       

			$clone.stop().animate({
			 	backgroundColor: this.options.stopColor,
				top: newTop,
				left: newLeft
			}, 1000, function () {    
				$clone.remove();
				$tmpEl.css('visibility', '');    
				$tmpEl.data('cloneExists','');
			});
		},
		
		_shiftElTo: function (el,destEl) {
          
			var $el = el.jquery?el:$(el);
			var $destEl = destEl.jquery?destEl:$(destEl);
			var elIndex = $el.index();
			var destElIndex = $destEl.index();
			var dir = destElIndex-elIndex;
			var max = Math.max(elIndex,destElIndex);
			var min = Math.min(elIndex,destElIndex);
			var $childrenArray = $el.parent().children();
 
			for(var i = min;i<=max;i++) {
			
				var $tmpEl = $childrenArray.eq(i);  
				var index = (dir > 0)?$tmpEl.prev().index():$tmpEl.next().index();   
				var $moveToEl = $childrenArray.eq(index);
		  
				if($tmpEl.data('startEl')) { //TODO refactor this section
					var finalEl = (dir >...