/* * * 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; }