text: /**
   * 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);
  