admin/public/static/ext/diyview/js/ddsort.js

248 lines
6.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;(function ($) {
/**
* Author: https://github.com/Barrior
*
* DDSort: drag and drop sorting.
* @param {Object} options
* target[string]: 可选jQuery事件委托选择器字符串默认'li'
* cloneStyle[object]: 可选,设置占位符元素的样式
* floatStyle[object]: 可选,设置拖动元素的样式
* down[function]: 可选,鼠标按下时执行的函数
* move[function]: 可选,鼠标移动时执行的函数
* up[function]: 可选,鼠标抬起时执行的函数
* draggableArea[string]:可选,设置可拖拽的区域
*/
$.fn.DDSort = function (options) {
var $doc = $(document),
fnEmpty = function () {
},
settings = $.extend(true, {
down: fnEmpty,
move: fnEmpty,
up: fnEmpty,
target: 'li',
cloneStyle: {
'background-color': '#f7f8fa'
},
floatStyle: {
//用固定定位可以防止定位父级不是Body的情况的兼容处理表示不兼容IE6无妨
'position': 'fixed',
'box-shadow': '10px 10px 20px 0 #eee',
/*'webkitTransform': 'rotate(4deg)',
'mozTransform': 'rotate(4deg)',
'msTransform': 'rotate(4deg)',
'transform': 'rotate(4deg)'*/
},
draggableArea: ''
}, options);
return this.each(function () {
var that = $(this),
height = 'height',
width = 'width';
if (that.css('box-sizing') == 'border-box') {
height = 'outerHeight';
width = 'outerWidth';
}
let time; // 监听长按时间
let progress = 0; // 记录长按时长
that.on('mousedown.DDSort', settings.target, function (e) {
//只允许鼠标左键拖动
if (e.which != 1) {
return;
}
//防止表单元素失效
var tagName = e.target.tagName.toLowerCase();
if (tagName == 'input' || tagName == 'textarea' || tagName == 'select' || $(e.target).attr('stop-ddsort')) {
return;
}
// 记录长按时长
time = setInterval(() => {
progress++
}, 125);
var THIS = this,
$this = $(THIS),
offset = $this.offset(),
disX = e.pageX - offset.left,
disY = e.pageY - offset.top,
clone = $this.clone()
.css(settings.cloneStyle)
.css('height', $this[height]())
.empty(),
hasClone = 1,
//缓存计算
thisOuterHeight = $this.outerHeight(),
thatOuterHeight = that.outerHeight(),
//滚动速度
upSpeed = thisOuterHeight,
downSpeed = thisOuterHeight,
maxSpeed = thisOuterHeight * 3;
if (settings.draggableArea != "") {
//判断当前点击的DOM是否允许拖拽
var isDraggable = recursiveQuery($(e.target), settings.draggableArea);
// 特殊处理:带有该属性的禁用
if ($(e.target).parent().attr("data-disabled") || $(e.target).attr("data-disabled")) {
return;
}
if (!isDraggable) {
return;
}
}
var downIndex = $(THIS).index();
settings.down.call(THIS, downIndex);
$doc.on('mousemove.DDSort', function (e) {
if (progress === 0) return; // 如果没有长按则不能拖拽
if (hasClone) {
$this.before(clone)
.css('width', $this[width]())
.css(settings.floatStyle)
.appendTo($this.parent());
hasClone = 0;
}
var left = e.pageX - disX,
top = e.pageY - disY,
prev = clone.prev(),
next = clone.next().not($this);
var gap = $(window).scrollTop();
var calculate = top - gap;
//检测是否滚动了
top = ((top - $(window).scrollTop()) != top) ? calculate : top;
$this.css({
left: left,
top: top,
zIndex: 999
});
//向上排序
if (prev.length && top < (prev.offset().top - gap) + prev.outerHeight() / 2) {
clone.after(prev);
//向下排序
} else if (next.length && top + thisOuterHeight > (next.offset().top - gap) + next.outerHeight() / 2) {
clone.before(next);
}
/**
* 处理滚动条
* that是带着滚动条的元素这里默认以为that元素是这样的元素正常情况就是这样如果使用者事件委托的元素不是这样的元素那么需要提供接口出来
*/
var thatScrollTop = that.scrollTop(),
thatOffsetTop = that.offset().top,
scrollVal;
//向上滚动
if (top < thatOffsetTop) {
downSpeed = thisOuterHeight;
upSpeed = ++upSpeed > maxSpeed ? maxSpeed : upSpeed;
scrollVal = thatScrollTop - upSpeed;
//向下滚动
} else if (top + thisOuterHeight - thatOffsetTop > thatOuterHeight) {
upSpeed = thisOuterHeight;
downSpeed = ++downSpeed > maxSpeed ? maxSpeed : downSpeed;
scrollVal = thatScrollTop + downSpeed;
}
that.scrollTop(scrollVal);
var index = recursiveQueryIndex($(THIS));
settings.currentIndex = index; // 当前拖拽元素
settings.move.call(THIS, index);
})
.on('mouseup.DDSort', function () {
clearInterval(time);
progress = 0;
$doc.off('mousemove.DDSort mouseup.DDSort');
//click的时候也会触发mouseup事件加上判断阻止这种情况
if (!hasClone) {
clone.before($this.removeAttr('style')).remove();
settings.up.call(THIS, settings.currentIndex);
}
});
return false;
});
});
};
//当前递归次数
var currentRecursiveCount = 0;
//最大递归次数
var recursiveMaxCount = 20;
/**
* 递归查询当前区域是否允许拖拽
* 创建时间2018年7月3日18:18:01
*/
function recursiveQuery(o, draggableArea) {
if (o.hasClass(draggableArea)) {
//允许拖拽,清空递归次数
currentRecursiveCount = 0;
// console.log($(o));
return true;
} else {
if (currentRecursiveCount <= recursiveMaxCount) {
currentRecursiveCount++;
return recursiveQuery(o.parent(), draggableArea);
} else {
//清空递归次数
// console.log("清空递归次数");
currentRecursiveCount = 0;
return false;
}
}
}
/**
* 递归查询当前拖拽的下标
* 创建时间2018年7月3日18:18:01
*/
function recursiveQueryIndex(o) {
if (o.hasClass("draggable-element")) {
//允许拖拽,清空递归次数
currentRecursiveCount = 0;
return $(o).attr("data-index");
} else {
if (currentRecursiveCount <= recursiveMaxCount) {
currentRecursiveCount++;
return recursiveQueryIndex(o.parent());
} else {
//清空递归次数
// console.log("清空递归次数");
currentRecursiveCount = 0;
return -1;
}
}
}
})(jQuery);