123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- /**
- * DDSort: drag and drop sorting.
- * Documentation: https://github.com/Barrior/DDSort
- */
- +function ($) {
- var defaultOptions = {
- down: $.noop,
- move: $.noop,
- up: $.noop,
- target: 'li',
- delay: 100,
- cloneStyle: {
- 'background-color': '#eee'
- },
- floatStyle: {
- // 用固定定位可以防止定位父级不是Body的情况的兼容处理,表示不兼容IE6,无妨
- 'position': 'fixed',
- 'box-shadow': '10px 10px 20px 0 #eee',
- 'webkitTransform': 'rotate(4deg)',
- 'mozTransform': 'rotate(4deg)',
- 'msTransform': 'rotate(4deg)',
- 'transform': 'rotate(4deg)'
- }
- };
- $.fn.DDSort = function (options) {
- var $doc = $(document);
- var settings = $.extend(true, {}, defaultOptions, options);
- return this.each(function () {
- var that = $(this);
- var height = 'height';
- var width = 'width';
- if (that.css('box-sizing') == 'border-box') {
- height = 'outerHeight';
- width = 'outerWidth';
- }
- that.on('mousedown.DDSort touchstart.DDSort', settings.target, function (e) {
- var startTime = new Date().getTime();
- // 桌面端只允许鼠标左键拖动
- if (e.type == 'mousedown' && e.which != 1) return;
- // 防止表单元素,a 链接,可编辑元素失效
- var tagName = e.target.tagName.toLowerCase();
- if (tagName == 'input' || tagName == 'textarea' || tagName == 'select' ||
- tagName == 'a' || $(e.target).prop('contenteditable') == 'true') {
- return;
- }
- var self = this;
- var $this = $(self);
- // 鼠标按下时的元素偏移
- var offset = $this.offset();
- // 鼠标按下时的光标坐标
- // 桌面端
- var pageX = e.pageX;
- var pageY = e.pageY;
- // 移动端
- var targetTouches = e.originalEvent.targetTouches;
- if (e.type == 'touchstart' && targetTouches) {
- pageX = targetTouches[0].pageX;
- pageY = targetTouches[0].pageY;
- }
- var clone = $this.clone()
- .css(settings.cloneStyle)
- .css('height', $this[height]())
- .empty();
- var hasClone = 1;
- // 缓存计算
- var thisOuterHeight = $this.outerHeight(),
- thisOuterWidth = $this.outerWidth(),
- thatOuterHeight = that.outerHeight(),
- thatOuterWidth = that.outerWidth();
- // 滚动速度
- var upSpeed = thisOuterHeight,
- downSpeed = thisOuterHeight,
- leftSpeed = thisOuterWidth,
- rightSpeed = thisOuterWidth,
- maxSpeed = thisOuterHeight * 3;
- settings.down.call(self);
- $doc.on('mousemove.DDSort touchmove.DDSort', function (e) {
- // 鼠标移动时的光标坐标
- // 桌面端
- var _pageX = e.pageX;
- var _pageY = e.pageY;
- // 移动端
- var targetTouches = e.originalEvent.targetTouches;
- if (e.type == 'touchmove' && targetTouches) {
- _pageX = targetTouches[0].pageX;
- _pageY = targetTouches[0].pageY;
- }
- if (new Date().getTime() - startTime < settings.delay) {
- return;
- }
- if (hasClone) {
- $this.before(clone)
- .css('width', $this[width]())
- .css(settings.floatStyle)
- .appendTo($this.parent());
- hasClone = 0;
- }
- var disX = pageX - _pageX;
- var disY = pageY - _pageY;
- var left = offset.left - disX;
- var top = offset.top - disY;
-
- $this.offset({
- left: left,
- top: top
- });
- var $left = getLeft(clone),
- $right = getRight(clone, $this),
- $top = getTop(clone),
- $under = getUnder(clone, $this);
- if ($top && $top.length && top < $top.offset().top + $top.outerHeight(true) / 2) {
- // 向上排序
- $top.before(clone);
-
- } else if ($under && $under.length && top + thisOuterHeight > $under.offset().top + $under.outerHeight(true) / 2) {
- // 向下排序
- $under.after(clone);
- } else if($left && $left.length && left < $left.offset().left + $left.outerWidth(true) / 2) {
- //向左排序
- $left.before(clone);
-
- } else if($right && $right.length && left + thisOuterWidth > $right.offset().left + $right.outerWidth(true) / 2) {
- //向右排序
- $right.after(clone);
-
- }
- // 处理滚动条,that 是带着滚动条的元素,这里默认以为 that 元素是这样的元素(正常情况就是这样),
- // 如果使用者事件委托的元素不是这样的元素,那么需要提供接口出来
- var thatScrollTop = that.scrollTop();
- var thatOffsetTop = that.offset().top;
- if (top < thatOffsetTop) {
- // 向上滚动
- downSpeed = thisOuterHeight;
- upSpeed = ++upSpeed > maxSpeed ? maxSpeed : upSpeed;
- var scrollVal = thatScrollTop - upSpeed;
- that.scrollTop(scrollVal);
- } else if (top + thisOuterHeight - thatOffsetTop > thatOuterHeight) {
- // 向下滚动
- upSpeed = thisOuterHeight;
- downSpeed = ++downSpeed > maxSpeed ? maxSpeed : downSpeed;
- var scrollVal = thatScrollTop + downSpeed;
- that.scrollTop(scrollVal);
- }
- var thatScrollLeft = that.scrollLeft();
- var thatOffsetLeft = that.offset().left;
- if (left < that.offset().left) {
- // 向左滚动
- rightSpeed = thisOuterWidth;
- leftSpeed = ++leftSpeed > maxSpeed ? maxSpeed : leftSpeed;
- var scrollVal = thatScrollLeft - leftSpeed;
- that.scrollLeft(scrollVal);
- } else if (left + thisOuterWidth - thatOffsetLeft > thatOuterWidth) {
- // 向右滚动
- leftSpeed = thisOuterWidth;
- rightSpeed = ++rightSpeed > maxSpeed ? maxSpeed : rightSpeed;
- var scrollVal = thatScrollLeft + rightSpeed;
- that.scrollLeft(scrollVal);
- }
- settings.move.call(self, left, top);
- })
- .on('mouseup.DDSort touchend.DDSort', function () {
- $doc.off('mousemove.DDSort mouseup.DDSort touchmove.DDSort touchend.DDSort');
- // click 的时候也会触发 mouseup 事件,加上判断阻止这种情况
- if (!hasClone) {
- clone.before($this.removeAttr('style')).remove();
- settings.up.call(self);
- }
- });
- return false;
- });
- });
- };
-
-
- //允许计算误差
- var deviation = 5;
-
- var getLeft = function (clone) {
- var left = clone.prev();
- if(left.length && clone.offset().top==left.offset().top) {
- var _dev = Math.abs(clone.offset().left - (left.offset().left + left.outerWidth(true)));
- if(_dev <= deviation) {
- return left;
- }
- }
- return undefined;
- }
- var getTop = function (clone, prev) {
- if(!prev){
- prev = clone.prev();
- }
- if(!prev.length) {
- return undefined;
- }
- if(clone.offset().left==prev.offset().left) {
- var _dev = Math.abs(clone.offset().top - (prev.offset().top+prev.outerHeight(true)));
- if(_dev <= deviation) {
- return prev;
- }
- }
- return getTop(clone, prev.prev());
- }
- var getRight = function (clone, $this) {
- var rigth = clone.next().not($this);
- if(rigth.length && clone.offset().top==rigth.offset().top) {
- var _dev = Math.abs(clone.offset().left - (rigth.offset().left-clone.outerWidth(true)));
- if(_dev <= deviation) {
- return rigth;
- }
- }
- return undefined;
- }
- var getUnder = function (clone, $this, next) {
- if(!next){
- next = clone.next().not($this);
- }
- if(!next.length) {
- return undefined;
- }
- if(clone.offset().left==next.offset().left) {
- var _dev = Math.abs(clone.offset().top - (next.offset().top-clone.outerHeight(true)));
- if(_dev <= deviation) {
- return next;
- }
- }
- return getUnder(clone, $this, next.next().not($this));
- }
- }(jQuery);
|