Edit in JSFiddle

/*
 * 
 * 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 > 0)?$childrenArray.eq(max):$childrenArray.eq(min);
					var draggable = $tmpEl.data("draggable")||$tmpEl.data("uiDraggable")||$tmpEl.data("ui-draggable"); //compatibility
					draggable.originalPosition = {
						top :  finalEl.position().top,
						left : finalEl.position().left
					 };
				} else {
					this._animate($tmpEl,$moveToEl);
				}
			}
	
			if(dir>0)
				$el.insertAfter($destEl); 
			else				
				$el.insertBefore($destEl);
		},
		
		//called every time, called after _create
		_init: function() {
			//console.log(this.element.attr('id'));		
		},
		
		// var deferals = [];
// 		$.when(deferals).done(function() { 
// 			console.log("animations have completed"); 
// 		}); 
		
		//called only once
		_create: function() {
			
			var self = this,
				o = self.options,
				el = self.element;
				
			$(el).draggable({
				zIndex: o.zIndex,
				revert: true,
				helper: o.helper,
				distance: o.dragDistance,
				scroll: false, 
				refreshPositions: true, //TODO: this causes unnecessary processing, calculate in _shiftElTo method instead
				start: function (event, ui) {
					$(this).data('startEl',true).css('visibility', 'hidden');
					self._trigger("start", event, ui);
				},
				stop: function (event, ui) {
					$(this).removeData('startEl').css('visibility', '');   				
					//TODO: update jquery to at least 1.6 and add promise().done here for when animations are done					
					self._trigger("stop", event, ui); //this should be inside the promise function
				}
			}).droppable({
				tolerance: 'pointer',
				over: function (event, ui) {
					self._shiftElTo(ui.draggable,this); 
					self._trigger("over", event, ui);               
				},
				// out: function (event, ui) {
// 		
// 				},
// 				drop: function (event, ui) {
// 	   
// 				}
			});
			
			self._trigger("added", null, el); //signal to others that the el has been added	
		},
		
		//TODO: set options
// 		_setOption: function(option, value) {
// 		
// 			$.Widget.prototype._setOption.apply( this, arguments ); //for super class, probably not needed
// 
// 			var el = this.element;
// 			
// 			switch (option) {
// 				case "dragDistance":
// 					break;
// 				case "startColor":
// 					break;
// 				case "stopColor":
// 					break;
// 			}
// 		},
		
		destroy: function() {
			var el = this.element;		
			$(el).draggable('destroy').droppable('destroy');
		},
		
	});

})(jQuery);

$('.grid').animatedgridsorter();
$('html').disableSelection();
<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>
.grid{
    border: 1px solid red;
    float: left;
    padding: 5px;
}