Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

sortable-dnd

Package Overview
Dependencies
Maintainers
1
Versions
75
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sortable-dnd - npm Package Compare versions

Comparing version 0.0.11 to 0.0.12

711

dist/sortable.js
/*!
* sortable-dnd v0.0.11
* sortable-dnd v0.0.12
* open source under the MIT license

@@ -95,227 +95,272 @@ * https://github.com/mfuu/sortable-dnd#readme

var R_SPACE = /\s+/g;
var utils = {
/**
* add specified event listener
* @param {HTMLElement} el
* @param {String} event
* @param {Function} fn
*/
on: function on(el, event, fn) {
if (window.addEventListener) {
el.addEventListener(event, fn, !IE11OrLess && captureMode);
} else if (window.attachEvent) {
el.addEventListener('on' + event, fn);
}
},
/**
* add specified event listener
* @param {HTMLElement} el
* @param {String} event
* @param {Function} fn
*/
/**
* remove specified event listener
* @param {HTMLElement} el
* @param {String} event
* @param {Function} fn
*/
off: function off(el, event, fn) {
if (window.removeEventListener) {
el.removeEventListener(event, fn, !IE11OrLess && captureMode);
} else if (window.detachEvent) {
el.detachEvent('on' + event, fn);
}
},
getWindowScrollingElement: function getWindowScrollingElement() {
var scrollingElement = document.scrollingElement;
function on(el, event, fn) {
if (window.addEventListener) {
el.addEventListener(event, fn, !IE11OrLess && captureMode);
} else if (window.attachEvent) {
el.addEventListener('on' + event, fn);
}
}
/**
* remove specified event listener
* @param {HTMLElement} el
* @param {String} event
* @param {Function} fn
*/
if (scrollingElement) {
return scrollingElement;
} else {
return document.documentElement;
}
},
function off(el, event, fn) {
if (window.removeEventListener) {
el.removeEventListener(event, fn, !IE11OrLess && captureMode);
} else if (window.detachEvent) {
el.detachEvent('on' + event, fn);
}
}
/**
* get element's offetTop
* @param {HTMLElement} el
*/
/**
* get specified element's index in group
* @param {HTMLElement} group
* @param {HTMLElement} el
* @returns {Number} index
*/
index: function index(group, el) {
if (!el || !el.parentNode) return -1;
function getOffset(el) {
var result = {
top: 0,
left: 0,
height: 0,
width: 0
};
result.height = el.offsetHeight;
result.width = el.offsetWidth;
result.top = el.offsetTop;
result.left = el.offsetLeft;
var parent = el.offsetParent;
var children = _toConsumableArray(Array.from(group.children));
while (parent !== null) {
result.top += parent.offsetTop;
result.left += parent.offsetLeft;
parent = parent.offsetParent;
}
return children.indexOf(el);
},
return result;
}
/**
* get scroll element
* @param {HTMLElement} el
* @param {Boolean} includeSelf whether to include the passed element
* @returns {HTMLElement} scroll element
*/
/**
* Returns the "bounding client rect" of given element
* @param {HTMLElement} el The element whose boundingClientRect is wanted
*/
getRect: function getRect(el) {
if (!el.getBoundingClientRect && el !== window) return;
var rect = {
top: 0,
left: 0,
bottom: 0,
right: 0,
height: 0,
width: 0
};
var elRect;
function getParentAutoScrollElement(el, includeSelf) {
// skip to window
if (!el || !el.getBoundingClientRect) return getWindowScrollingElement();
var elem = el;
var gotSelf = false;
if (el !== window && el.parentNode && el !== this.getWindowScrollingElement()) {
elRect = el.getBoundingClientRect();
rect.top = elRect.top;
rect.left = elRect.left;
rect.bottom = elRect.bottom;
rect.right = elRect.right;
rect.height = elRect.height;
rect.width = elRect.width;
} else {
rect.top = 0;
rect.left = 0;
rect.bottom = window.innerHeight;
rect.right = window.innerWidth;
rect.height = window.innerHeight;
rect.width = window.innerWidth;
do {
// we don't need to get elem css if it isn't even overflowing in the first place (performance)
if (elem.clientWidth < elem.scrollWidth || elem.clientHeight < elem.scrollHeight) {
var elemCSS = css(elem);
if (elem.clientWidth < elem.scrollWidth && (elemCSS.overflowX == 'auto' || elemCSS.overflowX == 'scroll') || elem.clientHeight < elem.scrollHeight && (elemCSS.overflowY == 'auto' || elemCSS.overflowY == 'scroll')) {
if (!elem.getBoundingClientRect || elem === document.body) return getWindowScrollingElement();
if (gotSelf || includeSelf) return elem;
gotSelf = true;
}
}
} while (elem = elem.parentNode);
return rect;
},
return getWindowScrollingElement();
}
function getWindowScrollingElement() {
var scrollingElement = document.scrollingElement;
/**
* get target Element in group
* @param {HTMLElement} group
* @param {HTMLElement} el
*/
getElement: function getElement(group, el) {
var result = {
index: -1,
el: null,
rect: {}
};
if (scrollingElement) {
return scrollingElement;
} else {
return document.documentElement;
}
}
/**
* Returns the "bounding client rect" of given element
* @param {HTMLElement} el The element whose boundingClientRect is wanted
*/
var children = _toConsumableArray(Array.from(group.children)); // 如果能直接在子元素中找到,返回对应的index
function getRect(el) {
if (!el.getBoundingClientRect && el !== window) return;
var rect = {
top: 0,
left: 0,
bottom: 0,
right: 0,
height: 0,
width: 0
};
var elRect;
if (el !== window && el.parentNode && el !== getWindowScrollingElement()) {
elRect = el.getBoundingClientRect();
rect.top = elRect.top;
rect.left = elRect.left;
rect.bottom = elRect.bottom;
rect.right = elRect.right;
rect.height = elRect.height;
rect.width = elRect.width;
} else {
rect.top = 0;
rect.left = 0;
rect.bottom = window.innerHeight;
rect.right = window.innerWidth;
rect.height = window.innerHeight;
rect.width = window.innerWidth;
}
var index = children.indexOf(el);
if (index > -1) Object.assign(result, {
index: index,
el: children[index],
rect: this.getRect(children[index])
}); // children 中无法直接找到对应的dom时,需要向下寻找
return rect;
}
/**
* get target Element in group
* @param {HTMLElement} group
* @param {HTMLElement} el
*/
for (var i = 0; i < children.length; i++) {
if (this.isChildOf(el, children[i])) Object.assign(result, {
function getElement(group, el) {
var result = {
index: -1,
el: null,
rect: {},
offset: {}
};
var children = _toConsumableArray(Array.from(group.children)); // 如果能直接在子元素中找到,返回对应的index
var index = children.indexOf(el);
if (index > -1) Object.assign(result, {
index: index,
el: children[index],
rect: getRect(children[index]),
offset: getOffset(children[index])
}); // children 中无法直接找到对应的dom时,需要向下寻找
for (var i = 0; i < children.length; i++) {
if (isChildOf(el, children[i])) {
Object.assign(result, {
index: i,
el: children[i],
rect: this.getRect(children[i])
rect: getRect(children[i]),
offset: getOffset(children[i])
});
break;
}
}
return result;
},
return result;
}
/**
* Check if child element is contained in parent element
* @param {HTMLElement} child
* @param {HTMLElement} parent
* @returns {Boolean} true | false
*/
/**
* Check if child element is contained in parent element
* @param {HTMLElement} child
* @param {HTMLElement} parent
* @returns {Boolean} true | false
*/
isChildOf: function isChildOf(child, parent) {
var parentNode;
function isChildOf(child, parent) {
var parentNode;
if (child && parent) {
parentNode = child.parentNode;
if (child && parent) {
parentNode = child.parentNode;
while (parentNode) {
if (parent === parentNode) return true;
parentNode = parentNode.parentNode;
}
while (parentNode) {
if (parent === parentNode) return true;
parentNode = parentNode.parentNode;
}
}
return false;
},
return false;
}
/**
* add or remove element's class
* @param {HTMLElement} el element
* @param {String} name class name
* @param {Boolean} state true: add, false: remove
*/
/**
* add or remove element's class
* @param {HTMLElement} el element
* @param {String} name class name
* @param {Boolean} state true: add, false: remove
*/
toggleClass: function toggleClass(el, name, state) {
if (el && name) {
if (el.classList) {
el.classList[state ? 'add' : 'remove'](name);
} else {
var className = (' ' + el.className + ' ').replace(R_SPACE, ' ').replace(' ' + name + ' ', ' ');
el.className = (className + (state ? ' ' + name : '')).replace(R_SPACE, ' ');
}
function toggleClass(el, name, state) {
if (el && name) {
if (el.classList) {
el.classList[state ? 'add' : 'remove'](name);
} else {
var className = (' ' + el.className + ' ').replace(R_SPACE, ' ').replace(' ' + name + ' ', ' ');
el.className = (className + (state ? ' ' + name : '')).replace(R_SPACE, ' ');
}
},
}
}
/**
* Check if a DOM element matches a given selector
* @param {HTMLElement} el
* @param {String} selector
* @returns
*/
/**
* Check if a DOM element matches a given selector
* @param {HTMLElement} el
* @param {String} selector
* @returns
*/
matches: function matches(el, selector) {
if (!selector) return;
selector[0] === '>' && (selector = selector.substring(1));
function matches(el, selector) {
if (!selector) return;
selector[0] === '>' && (selector = selector.substring(1));
if (el) {
try {
if (el.matches) {
return el.matches(selector);
} else if (el.msMatchesSelector) {
return el.msMatchesSelector(selector);
} else if (el.webkitMatchesSelector) {
return el.webkitMatchesSelector(selector);
}
} catch (error) {
return false;
if (el) {
try {
if (el.matches) {
return el.matches(selector);
} else if (el.msMatchesSelector) {
return el.msMatchesSelector(selector);
} else if (el.webkitMatchesSelector) {
return el.webkitMatchesSelector(selector);
}
} catch (error) {
return false;
}
}
return false;
},
css: function css(el, prop, val) {
var style = el && el.style;
return false;
}
function css(el, prop, val) {
var style = el && el.style;
if (style) {
if (val === void 0) {
if (document.defaultView && document.defaultView.getComputedStyle) {
val = document.defaultView.getComputedStyle(el, '');
} else if (el.currentStyle) {
val = el.currentStyle;
}
return prop === void 0 ? val : val[prop];
} else {
if (!(prop in style) && prop.indexOf('webkit') === -1) {
prop = '-webkit-' + prop;
}
style[prop] = val + (typeof val === 'string' ? '' : 'px');
if (style) {
if (val === void 0) {
if (document.defaultView && document.defaultView.getComputedStyle) {
val = document.defaultView.getComputedStyle(el, '');
} else if (el.currentStyle) {
val = el.currentStyle;
}
}
},
debounce: function debounce(fn, delay) {
return function () {
var _this = this;
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
return prop === void 0 ? val : val[prop];
} else {
if (!(prop in style) && prop.indexOf('webkit') === -1) {
prop = '-webkit-' + prop;
}
clearTimeout(fn.id);
fn.id = setTimeout(function () {
fn.call.apply(fn, [_this].concat(args));
}, delay);
};
},
_nextTick: function _nextTick(fn) {
return setTimeout(fn, 0);
style[prop] = val + (typeof val === 'string' ? '' : 'px');
}
}
};
}
function debounce(fn, delay) {
return function () {
var _this = this;
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
clearTimeout(fn.id);
fn.id = setTimeout(function () {
fn.call.apply(fn, [_this].concat(args));
}, delay);
};
}
function _nextTick(fn) {
return setTimeout(fn, 0);
}
function Animation() {

@@ -336,3 +381,3 @@ var animationState = [];

target: child,
rect: utils.getRect(child)
rect: getRect(child)
});

@@ -353,15 +398,15 @@ });

var animation = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 150;
var curRect = utils.getRect(el);
var curRect = getRect(el);
var left = preRect.left - curRect.left;
var top = preRect.top - curRect.top;
utils.css(el, 'transition', 'none');
utils.css(el, 'transform', "translate3d(".concat(left, "px, ").concat(top, "px, 0)"));
css(el, 'transition', 'none');
css(el, 'transform', "translate3d(".concat(left, "px, ").concat(top, "px, 0)"));
el.offsetLeft; // 触发重绘
utils.css(el, 'transition', "all ".concat(animation, "ms"));
utils.css(el, 'transform', 'translate3d(0px, 0px, 0px)');
css(el, 'transition', "all ".concat(animation, "ms"));
css(el, 'transform', 'translate3d(0px, 0px, 0px)');
clearTimeout(el.animated);
el.animated = setTimeout(function () {
utils.css(el, 'transition', '');
utils.css(el, 'transform', '');
css(el, 'transition', '');
css(el, 'transform', '');
el.animated = null;

@@ -389,17 +434,19 @@ }, animation);

var Diff = /*#__PURE__*/function () {
function Diff() {
_classCallCheck(this, Diff);
var Differ = /*#__PURE__*/function () {
function Differ() {
_classCallCheck(this, Differ);
this.old = {
this._old_ = {
node: null,
rect: {}
rect: {},
offset: {}
};
this["new"] = {
this._new_ = {
node: null,
rect: {}
rect: {},
offset: {}
};
}
_createClass(Diff, [{
_createClass(Differ, [{
key: "get",

@@ -417,9 +464,11 @@ value: function get(key) {

value: function destroy() {
this.old = {
this._old_ = {
node: null,
rect: {}
rect: {},
offset: {}
};
this["new"] = {
this._new_ = {
node: null,
rect: {}
rect: {},
offset: {}
};

@@ -429,3 +478,3 @@ }

return Diff;
return Differ;
}();

@@ -452,3 +501,2 @@ /**

this.$el = el;
this.rect = rect;
var _this$options = this.options,

@@ -473,3 +521,3 @@ ghostClass = _this$options.ghostClass,

for (var key in ghostStyle) {
utils.css(this.$el, key, ghostStyle[key]);
css(this.$el, key, ghostStyle[key]);
}

@@ -489,2 +537,7 @@ }

}, {
key: "rect",
value: function rect() {
return this.$el.getBoundingClientRect();
}
}, {
key: "move",

@@ -519,2 +572,4 @@ value: function move() {

this.options = options = Object.assign({}, options);
this.scrollEl = getParentAutoScrollElement(this.$el, true); // 获取页面滚动元素
this.dragEl = null; // 拖拽元素

@@ -524,3 +579,3 @@

this.diff = null; // 记录拖拽前后差异
this.differ = null; // 记录拖拽前后差异

@@ -534,3 +589,3 @@ this.ghost = null; // 拖拽时蒙版元素

utils.debounce(this.init(), 50); // 避免重复执行多次
debounce(this.init(), 50); // 避免重复执行多次
}

@@ -568,3 +623,3 @@

this.diff = new Diff();
this.differ = new Differ();
this.ghost = new Ghost(this.options);

@@ -576,41 +631,4 @@ Object.assign(this, Animation());

this._handleDestroy();
}
}, {
key: "_handleDestroy",
value: function _handleDestroy() {
var _this = this;
} // -------------------------------- drag and drop ----------------------------------
var observer = null;
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
if (MutationObserver) {
observer = new MutationObserver(function () {
if (!_this.$el) {
observer.disconnect();
observer = null;
_this._unbindEventListener();
_this._resetState();
}
});
observer.observe(this.$el.parentNode, {
childList: true,
// 观察目标子节点的变化,是否有添加或者删除
attributes: false,
// 观察属性变动
subtree: false // 观察后代节点,默认为 false
});
}
window.onbeforeunload = function () {
if (observer) observer.disconnect();
observer = null;
_this._unbindEventListener();
_this._resetState();
};
}
}, {

@@ -623,8 +641,8 @@ key: "_onStart",

var touch = evt.touches && evt.touches[0] || evt.pointerType && evt.pointerType === 'touch' && evt;
var target = (touch || evt).target;
var e = touch || evt;
if (typeof draggable === 'function') {
if (!draggable(touch || evt)) return true;
if (!draggable(e)) return true;
} else if (typeof draggable === 'string') {
if (!utils.matches(target, draggable)) return true;
if (!matches(e.target, draggable)) return true;
} else if (draggable !== undefined) {

@@ -636,3 +654,3 @@ throw new Error("draggable expected \"function\" or \"string\" but received \"".concat(_typeof(draggable), "\""));

if (target === this.$el) return true;
if (e.target === this.$el) return true;

@@ -642,3 +660,3 @@ try {

// Timeout neccessary for IE9
utils._nextTick(function () {
_nextTick(function () {
document.selection.empty();

@@ -651,3 +669,3 @@ });

var element = dragging && typeof dragging === 'function' ? dragging(touch || evt) : utils.getElement(this.$el, target).el; // 不存在拖拽元素时不允许拖拽
var element = typeof dragging === 'function' ? dragging(e) : getElement(this.$el, e.target).el; // 不存在拖拽元素时不允许拖拽

@@ -663,6 +681,7 @@ if (!element) return true;

var _utils$getElement = utils.getElement(this.$el, this.dragEl),
index = _utils$getElement.index,
el = _utils$getElement.el,
rect = _utils$getElement.rect;
var _getElement = getElement(this.$el, this.dragEl),
index = _getElement.index,
el = _getElement.el,
rect = _getElement.rect,
offset = _getElement.offset;

@@ -675,6 +694,8 @@ if (!el || index < 0) return true; // 将拖拽元素克隆一份作为蒙版

this.ghost.set('y', rect.top);
this.diff.old.rect = rect;
this.differ._old_.rect = rect;
this.differ._old_.offset = offset;
this.differ._old_.node = this.dragEl;
this.calcXY = {
x: (touch || evt).clientX,
y: (touch || evt).clientY
x: e.clientX,
y: e.clientY
};

@@ -696,3 +717,3 @@

var chosenClass = this.options.chosenClass;
utils.toggleClass(this.dragEl, chosenClass, true);
toggleClass(this.dragEl, chosenClass, true);
this.ghost.move();

@@ -711,9 +732,8 @@ if (!window.sortableDndOnDown) return;

this._checkRange(e);
var _getElement2 = getElement(this.$el, target),
index = _getElement2.index,
el = _getElement2.el,
rect = _getElement2.rect,
offset = _getElement2.offset;
var _utils$getElement2 = utils.getElement(this.$el, target),
index = _utils$getElement2.index,
el = _utils$getElement2.el,
rect = _utils$getElement2.rect;
var left = rect.left,

@@ -723,4 +743,20 @@ right = rect.right,

bottom = rect.bottom;
if (!el || index < 0 || top < 0) return;
if (!el || index < 0 || top < 0) return; // 判断边界值
var _rect = getRect(this.$el);
this._checkRange(e, _rect);
var _this$scrollEl = this.scrollEl,
scrollTop = _this$scrollEl.scrollTop,
scrollLeft = _this$scrollEl.scrollLeft; // 如果目标元素超出当前可视区,不允许拖动
if (this.scrollEl !== this.$el && (_rect.left < 0 || _rect.top < 0)) {
if (rect.top < _rect.top + scrollTop && _rect.top < 0) return;
if (rect.left < _rect.left + scrollLeft && _rect.left < 0) return;
} else {
if (rect.top < _rect.top) return;
if (rect.left < _rect.left) return;
}
if (clientX > left && clientX < right && clientY > top && clientY < bottom) {

@@ -733,3 +769,7 @@ this.dropEl = el; // 拖拽前后元素不一致时交换

if (utils.index(this.$el, this.dragEl) < index) {
var _offset = getOffset(this.dragEl); // 获取拖拽元素的 offset 值
// 优先比较 top 值,top 值相同再比较 left
if (_offset.top < offset.top || _offset.left < offset.left) {
this.$el.insertBefore(this.dragEl, this.dropEl.nextElementSibling);

@@ -741,7 +781,5 @@ } else {

this.animateRange();
this.diff.old.node = this.dragEl;
this.diff["new"].node = this.dropEl;
this.differ._new_.node = this.dropEl;
this.differ._new_.rect = getRect(this.dropEl);
}
this.diff["new"].rect = utils.getRect(this.dropEl);
}

@@ -760,8 +798,18 @@ }

chosenClass = _this$options3.chosenClass;
utils.toggleClass(this.dragEl, chosenClass, false);
toggleClass(this.dragEl, chosenClass, false);
if (window.sortableDndOnDown && window.sortableDndOnMove) {
// 拖拽完成触发回调函数
// 重新获取一次拖拽元素的 offset 值作为拖拽完成后的 offset 值
this.differ._new_.offset = getOffset(this.dragEl); // 拖拽完成触发回调函数
var _this$differ = this.differ,
_old_ = _this$differ._old_,
_new_ = _this$differ._new_; // 通过 offset 比较是否进行了元素交换
var changed = _old_.offset.top !== _new_.offset.top || _old_.offset.left !== _new_.offset.left; // 如果拖拽前后没有发生交换,重新赋值一次
if (!changed) this.differ._new_.node = this.differ._old_.node;
if (typeof dragEnd === 'function') {
dragEnd(this.diff.old, this.diff["new"]);
dragEnd(_old_, _new_, changed);
} else {

@@ -772,3 +820,3 @@ throw new Error("Sortable-dnd Error: dragEnd expected \"function\" but received \"".concat(_typeof(dragEnd), "\""));

this.diff.destroy();
this.differ.destroy();
this.ghost.destroy();

@@ -780,8 +828,7 @@

key: "_checkRange",
value: function _checkRange(e) {
var _utils$getRect = utils.getRect(this.$el),
top = _utils$getRect.top,
left = _utils$getRect.left,
right = _utils$getRect.right,
bottom = _utils$getRect.bottom;
value: function _checkRange(e, groupRect) {
var top = groupRect.top,
left = groupRect.left,
right = groupRect.right,
bottom = groupRect.bottom;

@@ -792,4 +839,45 @@ if (e.clientX < left || e.clientX > right || e.clientY < top || e.clientY > bottom) {

}
}
} // -------------------------------- auto destroy ----------------------------------
}, {
key: "_handleDestroy",
value: function _handleDestroy() {
var _this = this;
var observer = null;
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
if (MutationObserver) {
var ownerDocument = this.options.ownerDocument;
observer = new MutationObserver(function () {
if (!ownerDocument.body.contains(_this.$el)) {
observer.disconnect();
observer = null;
_this._unbindEventListener();
_this._resetState();
}
});
observer.observe(this.$el.parentNode, {
childList: true,
// 观察目标子节点的变化,是否有添加或者删除
attributes: false,
// 观察属性变动
subtree: false // 观察后代节点,默认为 false
});
}
window.onbeforeunload = function () {
if (observer) observer.disconnect();
observer = null;
_this._unbindEventListener();
_this._resetState();
};
} // -------------------------------- reset state ----------------------------------
}, {
key: "_resetState",

@@ -800,3 +888,3 @@ value: function _resetState() {

this.ghost.destroy();
this.diff.destroy();
this.differ.destroy();
this.calcXY = {

@@ -816,3 +904,4 @@ x: 0,

delete window.sortableDndOnMove;
}
} // -------------------------------- listener ----------------------------------
}, {

@@ -827,6 +916,6 @@ key: "_bindEventListener",

if (supportPointer) {
utils.on(this.$el, 'pointerdown', this._onStart);
on(this.$el, 'pointerdown', this._onStart);
} else {
utils.on(this.$el, 'mousedown', this._onStart);
utils.on(this.$el, 'touchstart', this._onStart);
on(this.$el, 'mousedown', this._onStart);
on(this.$el, 'touchstart', this._onStart);
}

@@ -837,5 +926,5 @@ }

value: function _unbindEventListener() {
utils.off(this.$el, 'pointerdown', this._onStart);
utils.off(this.$el, 'touchstart', this._onStart);
utils.off(this.$el, 'mousedown', this._onStart);
off(this.$el, 'pointerdown', this._onStart);
off(this.$el, 'touchstart', this._onStart);
off(this.$el, 'mousedown', this._onStart);
}

@@ -850,7 +939,7 @@ }, {

if (supportPointer) {
utils.on(ownerDocument, 'pointermove', this._onMove);
on(ownerDocument, 'pointermove', this._onMove);
} else if (touch) {
utils.on(ownerDocument, 'touchmove', this._onMove);
on(ownerDocument, 'touchmove', this._onMove);
} else {
utils.on(ownerDocument, 'mousemove', this._onMove);
on(ownerDocument, 'mousemove', this._onMove);
}

@@ -862,6 +951,6 @@ }

var ownerDocument = this.options.ownerDocument;
utils.on(ownerDocument, 'pointerup', this._onDrop);
utils.on(ownerDocument, 'touchend', this._onDrop);
utils.on(ownerDocument, 'touchcancel', this._onDrop);
utils.on(ownerDocument, 'mouseup', this._onDrop);
on(ownerDocument, 'pointerup', this._onDrop);
on(ownerDocument, 'touchend', this._onDrop);
on(ownerDocument, 'touchcancel', this._onDrop);
on(ownerDocument, 'mouseup', this._onDrop);
}

@@ -872,5 +961,5 @@ }, {

var ownerDocument = this.options.ownerDocument;
utils.off(ownerDocument, 'pointermove', this._onMove);
utils.off(ownerDocument, 'touchmove', this._onMove);
utils.off(ownerDocument, 'mousemove', this._onMove);
off(ownerDocument, 'pointermove', this._onMove);
off(ownerDocument, 'touchmove', this._onMove);
off(ownerDocument, 'mousemove', this._onMove);
}

@@ -881,6 +970,6 @@ }, {

var ownerDocument = this.options.ownerDocument;
utils.off(ownerDocument, 'mouseup', this._onDrop);
utils.off(ownerDocument, 'touchend', this._onDrop);
utils.off(ownerDocument, 'touchcancel', this._onDrop);
utils.off(ownerDocument, 'pointerup', this._onDrop);
off(ownerDocument, 'mouseup', this._onDrop);
off(ownerDocument, 'touchend', this._onDrop);
off(ownerDocument, 'touchcancel', this._onDrop);
off(ownerDocument, 'pointerup', this._onDrop);
}

@@ -887,0 +976,0 @@ }]);

@@ -1,1 +0,1 @@

!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).Sortable=e()}(this,function(){"use strict";function s(t){return(s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}function r(t,e,n){e&&i(t.prototype,e),n&&i(t,n),Object.defineProperty(t,"prototype",{writable:!1})}function l(t){return function(t){if(Array.isArray(t))return a(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return a(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Map"===(n="Object"===n&&t.constructor?t.constructor.name:n)||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?a(t,e):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function a(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,o=new Array(e);n<e;n++)o[n]=t[n];return o}function t(t){if("undefined"!=typeof window&&window.navigator)return!!navigator.userAgent.match(t)}var h=t(/(?:Trident.*rv[ :]?11\.|msie|iemobile|Windows Phone)/i),c=t(/safari/i)&&!t(/chrome/i)&&!t(/android/i),u={capture:!1,passive:!1},d=/\s+/g,f={on:function(t,e,n){window.addEventListener?t.addEventListener(e,n,!h&&u):window.attachEvent&&t.addEventListener("on"+e,n)},off:function(t,e,n){window.removeEventListener?t.removeEventListener(e,n,!h&&u):window.detachEvent&&t.detachEvent("on"+e,n)},getWindowScrollingElement:function(){var t=document.scrollingElement;return t||document.documentElement},index:function(t,e){return e&&e.parentNode?l(Array.from(t.children)).indexOf(e):-1},getRect:function(t){var e;if(t.getBoundingClientRect||t===window)return e={top:0,left:0,bottom:0,right:0,height:0,width:0},t!==window&&t.parentNode&&t!==this.getWindowScrollingElement()?(t=t.getBoundingClientRect(),e.top=t.top,e.left=t.left,e.bottom=t.bottom,e.right=t.right,e.height=t.height,e.width=t.width):(e.top=0,e.left=0,e.bottom=window.innerHeight,e.right=window.innerWidth,e.height=window.innerHeight,e.width=window.innerWidth),e},getElement:function(t,e){var n={index:-1,el:null,rect:{}},o=l(Array.from(t.children)),t=o.indexOf(e);-1<t&&Object.assign(n,{index:t,el:o[t],rect:this.getRect(o[t])});for(var i=0;i<o.length;i++)this.isChildOf(e,o[i])&&Object.assign(n,{index:i,el:o[i],rect:this.getRect(o[i])});return n},isChildOf:function(t,e){var n;if(t&&e)for(n=t.parentNode;n;){if(e===n)return!0;n=n.parentNode}return!1},toggleClass:function(t,e,n){var o;t&&e&&(t.classList?t.classList[n?"add":"remove"](e):(o=(" "+t.className+" ").replace(d," ").replace(" "+e+" "," "),t.className=(o+(n?" "+e:"")).replace(d," ")))},matches:function(t,e){if(e){if(">"===e[0]&&(e=e.substring(1)),t)try{if(t.matches)return t.matches(e);if(t.msMatchesSelector)return t.msMatchesSelector(e);if(t.webkitMatchesSelector)return t.webkitMatchesSelector(e)}catch(t){return!1}return!1}},css:function(t,e,n){var o=t&&t.style;if(o){if(void 0===n)return document.defaultView&&document.defaultView.getComputedStyle?n=document.defaultView.getComputedStyle(t,""):t.currentStyle&&(n=t.currentStyle),void 0===e?n:n[e];o[e=e in o||-1!==e.indexOf("webkit")?e:"-webkit-"+e]=n+("string"==typeof n?"":"px")}},debounce:function(i,r){return function(){for(var t=this,e=arguments.length,n=new Array(e),o=0;o<e;o++)n[o]=arguments[o];clearTimeout(i.id),i.id=setTimeout(function(){i.call.apply(i,[t].concat(n))},r)}},_nextTick:function(t){return setTimeout(t,0)}};function p(){var o=[];return{captureAnimationState:function(){var t=l(Array.from(this.$el.children)),e=function(t,e,n){e=t.indexOf(e),t=t.indexOf(n);return e<t?{start:e,end:t}:{start:t,end:e}}(t,this.dragEl,this.dropEl),n=e.start,e=e.end;o.length=0,t.slice(n,e+1).forEach(function(t){o.push({target:t,rect:f.getRect(t)})})},animateRange:function(){var n=this;o.forEach(function(t){var e=t.target,t=t.rect;n.animate(e,t,n.animation)})},animate:function(t,e){var n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:150,o=f.getRect(t),i=e.left-o.left,e=e.top-o.top;f.css(t,"transition","none"),f.css(t,"transform","translate3d(".concat(i,"px, ").concat(e,"px, 0)")),t.offsetLeft,f.css(t,"transition","all ".concat(n,"ms")),f.css(t,"transform","translate3d(0px, 0px, 0px)"),clearTimeout(t.animated),t.animated=setTimeout(function(){f.css(t,"transition",""),f.css(t,"transform",""),t.animated=null},n)}}}var v=function(){function t(){o(this,t),this.old={node:null,rect:{}},this.new={node:null,rect:{}}}return r(t,[{key:"get",value:function(t){return this[t]}},{key:"set",value:function(t,e){this[t]=e}},{key:"destroy",value:function(){this.old={node:null,rect:{}},this.new={node:null,rect:{}}}}]),t}(),g=function(){function e(t){o(this,e),this.options=t,this.x=0,this.y=0,this.exist=!1}return r(e,[{key:"init",value:function(t,e){if(t){this.$el=t,this.rect=e;var n,t=this.options,o=t.ghostClass,t=t.ghostStyle,i=void 0===t?{}:t,t=e.width,e=e.height;for(n in this.$el.class=o,this.$el.style.width=t+"px",this.$el.style.height=e+"px",this.$el.style.transform="",this.$el.style.transition="",this.$el.style.position="fixed",this.$el.style.left=0,this.$el.style.top=0,this.$el.style.zIndex=1e5,this.$el.style.opacity=.8,this.$el.style.pointerEvents="none",i)f.css(this.$el,n,i[n])}}},{key:"get",value:function(t){return this[t]}},{key:"set",value:function(t,e){this[t]=e,this[t]=e}},{key:"move",value:function(){this.exist||(document.body.appendChild(this.$el),this.exist=!0),this.$el.style.transform="translate3d(".concat(this.x,"px, ").concat(this.y,"px, 0)")}},{key:"destroy",value:function(){this.$el&&this.$el.remove(),this.exist=!1}}]),e}();return function(){function n(t,e){if(o(this,n),!t)throw new Error("container element is required");this.$el=t,this.options=e=Object.assign({},e),this.dragEl=null,this.dropEl=null,this.diff=null,this.ghost=null,this.calcXY={x:0,y:0},f.debounce(this.init(),50)}return r(n,[{key:"destroy",value:function(){this._unbindEventListener(),this._resetState()}},{key:"init",value:function(){var t,e={animation:150,ghostClass:"",ghostStyle:{},chosenClass:"",draggable:void 0,dragging:null,dragEnd:null,supportPointer:"PointerEvent"in window&&!c,ownerDocument:this.$el.ownerDocument};for(t in e)t in this.options||(this.options[t]=e[t]);this.diff=new v,this.ghost=new g(this.options),Object.assign(this,p()),this._bindEventListener(),this._handleDestroy()}},{key:"_handleDestroy",value:function(){var t=this,e=null,n=window.MutationObserver||window.WebKitMutationObserver;n&&(e=new n(function(){t.$el||(e.disconnect(),e=null,t._unbindEventListener(),t._resetState())})).observe(this.$el.parentNode,{childList:!0,attributes:!1,subtree:!1}),window.onbeforeunload=function(){e&&e.disconnect(),e=null,t._unbindEventListener(),t._resetState()}}},{key:"_onStart",value:function(t){var e=this.options,n=e.dragging,e=e.draggable,o=t.touches&&t.touches[0]||t.pointerType&&"touch"===t.pointerType&&t,i=(o||t).target;if("function"==typeof e){if(!e(o||t))return!0}else if("string"==typeof e){if(!f.matches(i,e))return!0}else if(void 0!==e)throw new Error('draggable expected "function" or "string" but received "'.concat(s(e),'"'));if(!/mousedown|pointerdown/.test(t.type)||0===t.button){if(i===this.$el)return!0;try{document.selection?f._nextTick(function(){document.selection.empty()}):window.getSelection().removeAllRanges();var r=n&&"function"==typeof n?n(o||t):f.getElement(this.$el,i).el;if(!r)return!0;if(r.animated)return;this.dragEl=r}catch(t){throw new Error(t)}window.sortableDndOnDown=!0;e=f.getElement(this.$el,this.dragEl),n=e.index,i=e.el,r=e.rect;if(!i||n<0)return!0;e=this.dragEl.cloneNode(!0);this.ghost.init(e,r),this.ghost.set("x",r.left),this.ghost.set("y",r.top),this.diff.old.rect=r,this.calcXY={x:(o||t).clientX,y:(o||t).clientY},this._onMoveEvents(o),this._onUpEvents(o)}}},{key:"_onMove",value:function(t){t.preventDefault();var e=t.touches&&t.touches[0],t=e||t,n=t.clientX,o=t.clientY,e=e?document.elementFromPoint(n,o):t.target,i=this.options.chosenClass;if(f.toggleClass(this.dragEl,i,!0),this.ghost.move(),window.sortableDndOnDown&&!(n<0||o<0)){document.body.style.cursor="grabbing",window.sortableDndOnMove=!0,this.ghost.set("x",this.ghost.x+n-this.calcXY.x),this.ghost.set("y",this.ghost.y+o-this.calcXY.y),this.calcXY={x:n,y:o},this.ghost.move(),this._checkRange(t);var i=f.getElement(this.$el,e),t=i.index,e=i.el,i=i.rect,r=i.left,s=i.right,l=i.top,i=i.bottom;if(!(!e||t<0||l<0)&&r<n&&n<s&&l<o&&o<i){if(this.dropEl=e,this.dropEl!==this.dragEl){if(this.dropEl.animated)return;this.captureAnimationState(),f.index(this.$el,this.dragEl)<t?this.$el.insertBefore(this.dragEl,this.dropEl.nextElementSibling):this.$el.insertBefore(this.dragEl,this.dropEl),this.animateRange(),this.diff.old.node=this.dragEl,this.diff.new.node=this.dropEl}this.diff.new.rect=f.getRect(this.dropEl)}}}},{key:"_onDrop",value:function(){this._offMoveEvents(),this._offUpEvents(),document.body.style.cursor="";var t=this.options,e=t.dragEnd,t=t.chosenClass;if(f.toggleClass(this.dragEl,t,!1),window.sortableDndOnDown&&window.sortableDndOnMove){if("function"!=typeof e)throw new Error('Sortable-dnd Error: dragEnd expected "function" but received "'.concat(s(e),'"'));e(this.diff.old,this.diff.new)}this.diff.destroy(),this.ghost.destroy(),this._removeWindowState()}},{key:"_checkRange",value:function(t){var e=f.getRect(this.$el),n=e.top,o=e.left,i=e.right,e=e.bottom;(t.clientX<o||t.clientX>i||t.clientY<n||t.clientY>e)&&(document.body.style.cursor="not-allowed")}},{key:"_resetState",value:function(){this.dragEl=null,this.dropEl=null,this.ghost.destroy(),this.diff.destroy(),this.calcXY={x:0,y:0},this._removeWindowState()}},{key:"_removeWindowState",value:function(){window.sortableDndOnDown=null,window.sortableDndOnMove=null,delete window.sortableDndOnDown,delete window.sortableDndOnMove}},{key:"_bindEventListener",value:function(){this._onStart=this._onStart.bind(this),this._onMove=this._onMove.bind(this),this._onDrop=this._onDrop.bind(this),this.options.supportPointer?f.on(this.$el,"pointerdown",this._onStart):(f.on(this.$el,"mousedown",this._onStart),f.on(this.$el,"touchstart",this._onStart))}},{key:"_unbindEventListener",value:function(){f.off(this.$el,"pointerdown",this._onStart),f.off(this.$el,"touchstart",this._onStart),f.off(this.$el,"mousedown",this._onStart)}},{key:"_onMoveEvents",value:function(t){var e=this.options,n=e.supportPointer,e=e.ownerDocument;n?f.on(e,"pointermove",this._onMove):t?f.on(e,"touchmove",this._onMove):f.on(e,"mousemove",this._onMove)}},{key:"_onUpEvents",value:function(){var t=this.options.ownerDocument;f.on(t,"pointerup",this._onDrop),f.on(t,"touchend",this._onDrop),f.on(t,"touchcancel",this._onDrop),f.on(t,"mouseup",this._onDrop)}},{key:"_offMoveEvents",value:function(){var t=this.options.ownerDocument;f.off(t,"pointermove",this._onMove),f.off(t,"touchmove",this._onMove),f.off(t,"mousemove",this._onMove)}},{key:"_offUpEvents",value:function(){var t=this.options.ownerDocument;f.off(t,"mouseup",this._onDrop),f.off(t,"touchend",this._onDrop),f.off(t,"touchcancel",this._onDrop),f.off(t,"pointerup",this._onDrop)}}]),n}()});
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).Sortable=e()}(this,function(){"use strict";function s(t){return(s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}function r(t,e,n){e&&i(t.prototype,e),n&&i(t,n),Object.defineProperty(t,"prototype",{writable:!1})}function l(t){return function(t){if(Array.isArray(t))return a(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return a(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Map"===(n="Object"===n&&t.constructor?t.constructor.name:n)||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?a(t,e):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function a(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,o=new Array(e);n<e;n++)o[n]=t[n];return o}function t(t){if("undefined"!=typeof window&&window.navigator)return!!navigator.userAgent.match(t)}var h=t(/(?:Trident.*rv[ :]?11\.|msie|iemobile|Windows Phone)/i),f=t(/safari/i)&&!t(/chrome/i)&&!t(/android/i),c={capture:!1,passive:!1},u=/\s+/g;function d(t,e,n){window.addEventListener?t.addEventListener(e,n,!h&&c):window.attachEvent&&t.addEventListener("on"+e,n)}function e(t,e,n){window.removeEventListener?t.removeEventListener(e,n,!h&&c):window.detachEvent&&t.detachEvent("on"+e,n)}function p(t){for(var e={top:0,left:0,height:0,width:0},n=(e.height=t.offsetHeight,e.width=t.offsetWidth,e.top=t.offsetTop,e.left=t.offsetLeft,t.offsetParent);null!==n;)e.top+=n.offsetTop,e.left+=n.offsetLeft,n=n.offsetParent;return e}function v(){var t=document.scrollingElement;return t||document.documentElement}function y(t){var e;if(t.getBoundingClientRect||t===window)return e={top:0,left:0,bottom:0,right:0,height:0,width:0},t!==window&&t.parentNode&&t!==v()?(t=t.getBoundingClientRect(),e.top=t.top,e.left=t.left,e.bottom=t.bottom,e.right=t.right,e.height=t.height,e.width=t.width):(e.top=0,e.left=0,e.bottom=window.innerHeight,e.right=window.innerWidth,e.height=window.innerHeight,e.width=window.innerWidth),e}function g(t,e){var n={index:-1,el:null,rect:{},offset:{}},o=l(Array.from(t.children)),t=o.indexOf(e);-1<t&&Object.assign(n,{index:t,el:o[t],rect:y(o[t]),offset:p(o[t])});for(var i=0;i<o.length;i++)if(function(t,e){var n;if(t&&e)for(n=t.parentNode;n;){if(e===n)return 1;n=n.parentNode}return}(e,o[i])){Object.assign(n,{index:i,el:o[i],rect:y(o[i]),offset:p(o[i])});break}return n}function w(t,e,n){var o;t&&e&&(t.classList?t.classList[n?"add":"remove"](e):(o=(" "+t.className+" ").replace(u," ").replace(" "+e+" "," "),t.className=(o+(n?" "+e:"")).replace(u," ")))}function m(t,e,n){var o=t&&t.style;if(o){if(void 0===n)return document.defaultView&&document.defaultView.getComputedStyle?n=document.defaultView.getComputedStyle(t,""):t.currentStyle&&(n=t.currentStyle),void 0===e?n:n[e];o[e=e in o||-1!==e.indexOf("webkit")?e:"-webkit-"+e]=n+("string"==typeof n?"":"px")}}function b(){var o=[];return{captureAnimationState:function(){var t=l(Array.from(this.$el.children)),e=function(t,e,n){e=t.indexOf(e),t=t.indexOf(n);return e<t?{start:e,end:t}:{start:t,end:e}}(t,this.dragEl,this.dropEl),n=e.start,e=e.end;o.length=0,t.slice(n,e+1).forEach(function(t){o.push({target:t,rect:y(t)})})},animateRange:function(){var n=this;o.forEach(function(t){var e=t.target,t=t.rect;n.animate(e,t,n.animation)})},animate:function(t,e){var n=2<arguments.length&&void 0!==arguments[2]?arguments[2]:150,o=y(t),i=e.left-o.left,e=e.top-o.top;m(t,"transition","none"),m(t,"transform","translate3d(".concat(i,"px, ").concat(e,"px, 0)")),t.offsetLeft,m(t,"transition","all ".concat(n,"ms")),m(t,"transform","translate3d(0px, 0px, 0px)"),clearTimeout(t.animated),t.animated=setTimeout(function(){m(t,"transition",""),m(t,"transform",""),t.animated=null},n)}}}var _=function(){function t(){o(this,t),this._old_={node:null,rect:{},offset:{}},this._new_={node:null,rect:{},offset:{}}}return r(t,[{key:"get",value:function(t){return this[t]}},{key:"set",value:function(t,e){this[t]=e}},{key:"destroy",value:function(){this._old_={node:null,rect:{},offset:{}},this._new_={node:null,rect:{},offset:{}}}}]),t}(),E=function(){function e(t){o(this,e),this.options=t,this.x=0,this.y=0,this.exist=!1}return r(e,[{key:"init",value:function(t,e){if(t){this.$el=t;var n,t=this.options,o=t.ghostClass,t=t.ghostStyle,i=void 0===t?{}:t,t=e.width,e=e.height;for(n in this.$el.class=o,this.$el.style.width=t+"px",this.$el.style.height=e+"px",this.$el.style.transform="",this.$el.style.transition="",this.$el.style.position="fixed",this.$el.style.left=0,this.$el.style.top=0,this.$el.style.zIndex=1e5,this.$el.style.opacity=.8,this.$el.style.pointerEvents="none",i)m(this.$el,n,i[n])}}},{key:"get",value:function(t){return this[t]}},{key:"set",value:function(t,e){this[t]=e,this[t]=e}},{key:"rect",value:function(){return this.$el.getBoundingClientRect()}},{key:"move",value:function(){this.exist||(document.body.appendChild(this.$el),this.exist=!0),this.$el.style.transform="translate3d(".concat(this.x,"px, ").concat(this.y,"px, 0)")}},{key:"destroy",value:function(){this.$el&&this.$el.remove(),this.exist=!1}}]),e}();return function(){function n(t,e){if(o(this,n),!t)throw new Error("container element is required");this.$el=t,this.options=e=Object.assign({},e),this.scrollEl=function(t,e){if(!t||!t.getBoundingClientRect)return v();var n=t,o=!1;do{if(n.clientWidth<n.scrollWidth||n.clientHeight<n.scrollHeight){var i=m(n);if(n.clientWidth<n.scrollWidth&&("auto"==i.overflowX||"scroll"==i.overflowX)||n.clientHeight<n.scrollHeight&&("auto"==i.overflowY||"scroll"==i.overflowY)){if(!n.getBoundingClientRect||n===document.body)return v();if(o||e)return n;o=!0}}}while(n=n.parentNode);return v()}(this.$el,!0),this.dragEl=null,this.dropEl=null,this.differ=null,this.ghost=null,this.calcXY={x:0,y:0},this.init()}return r(n,[{key:"destroy",value:function(){this._unbindEventListener(),this._resetState()}},{key:"init",value:function(){var t,e={animation:150,ghostClass:"",ghostStyle:{},chosenClass:"",draggable:void 0,dragging:null,dragEnd:null,supportPointer:"PointerEvent"in window&&!f,ownerDocument:this.$el.ownerDocument};for(t in e)t in this.options||(this.options[t]=e[t]);this.differ=new _,this.ghost=new E(this.options),Object.assign(this,b()),this._bindEventListener(),this._handleDestroy()}},{key:"_onStart",value:function(t){var e=this.options,n=e.dragging,e=e.draggable,o=t.touches&&t.touches[0]||t.pointerType&&"touch"===t.pointerType&&t,i=o||t;if("function"==typeof e){if(!e(i))return!0}else if("string"==typeof e){if(!function(t,e){if(e&&(">"===e[0]&&(e=e.substring(1)),t))try{if(t.matches)return t.matches(e);if(t.msMatchesSelector)return t.msMatchesSelector(e);if(t.webkitMatchesSelector)return t.webkitMatchesSelector(e)}catch(t){return}}(i.target,e))return!0}else if(void 0!==e)throw new Error('draggable expected "function" or "string" but received "'.concat(s(e),'"'));if(!/mousedown|pointerdown/.test(t.type)||0===t.button){if(i.target===this.$el)return!0;try{document.selection?setTimeout(function(){document.selection.empty()},0):window.getSelection().removeAllRanges();var r="function"==typeof n?n(i):g(this.$el,i.target).el;if(!r)return!0;if(r.animated)return;this.dragEl=r}catch(t){throw new Error(t)}window.sortableDndOnDown=!0;e=g(this.$el,this.dragEl),t=e.index,n=e.el,r=e.rect,e=e.offset;if(!n||t<0)return!0;n=this.dragEl.cloneNode(!0);this.ghost.init(n,r),this.ghost.set("x",r.left),this.ghost.set("y",r.top),this.differ._old_.rect=r,this.differ._old_.offset=e,this.differ._old_.node=this.dragEl,this.calcXY={x:i.clientX,y:i.clientY},this._onMoveEvents(o),this._onUpEvents(o)}}},{key:"_onMove",value:function(t){t.preventDefault();var e=t.touches&&t.touches[0],t=e||t,n=t.clientX,o=t.clientY,e=e?document.elementFromPoint(n,o):t.target,i=this.options.chosenClass;if(w(this.dragEl,i,!0),this.ghost.move(),window.sortableDndOnDown&&!(n<0||o<0)){document.body.style.cursor="grabbing",window.sortableDndOnMove=!0,this.ghost.set("x",this.ghost.x+n-this.calcXY.x),this.ghost.set("y",this.ghost.y+o-this.calcXY.y),this.calcXY={x:n,y:o},this.ghost.move();var i=g(this.$el,e),e=i.index,r=i.el,s=i.rect,i=i.offset,l=s.left,a=s.right,h=s.top,f=s.bottom;if(!(!r||e<0||h<0)){var e=y(this.$el),t=(this._checkRange(t,e),this.scrollEl),c=t.scrollTop,t=t.scrollLeft;if(this.scrollEl!==this.$el&&(e.left<0||e.top<0)){if(s.top<e.top+c&&e.top<0)return;if(s.left<e.left+t&&e.left<0)return}else{if(s.top<e.top)return;if(s.left<e.left)return}l<n&&n<a&&h<o&&o<f&&(this.dropEl=r,this.dropEl===this.dragEl||this.dropEl.animated||(this.captureAnimationState(),(c=p(this.dragEl)).top<i.top||c.left<i.left?this.$el.insertBefore(this.dragEl,this.dropEl.nextElementSibling):this.$el.insertBefore(this.dragEl,this.dropEl),this.animateRange(),this.differ._new_.node=this.dropEl,this.differ._new_.rect=y(this.dropEl)))}}}},{key:"_onDrop",value:function(){this._offMoveEvents(),this._offUpEvents(),document.body.style.cursor="";var t=this.options,e=t.dragEnd,t=t.chosenClass;if(w(this.dragEl,t,!1),window.sortableDndOnDown&&window.sortableDndOnMove){this.differ._new_.offset=p(this.dragEl);var t=this.differ,n=t._old_,t=t._new_,o=n.offset.top!==t.offset.top||n.offset.left!==t.offset.left;if(o||(this.differ._new_.node=this.differ._old_.node),"function"!=typeof e)throw new Error('Sortable-dnd Error: dragEnd expected "function" but received "'.concat(s(e),'"'));e(n,t,o)}this.differ.destroy(),this.ghost.destroy(),this._removeWindowState()}},{key:"_checkRange",value:function(t,e){var n=e.top,o=e.left,i=e.right,e=e.bottom;(t.clientX<o||t.clientX>i||t.clientY<n||t.clientY>e)&&(document.body.style.cursor="not-allowed")}},{key:"_handleDestroy",value:function(){var t,e=this,n=null,o=window.MutationObserver||window.WebKitMutationObserver;o&&(t=this.options.ownerDocument,(n=new o(function(){t.body.contains(e.$el)||(n.disconnect(),n=null,e._unbindEventListener(),e._resetState())})).observe(this.$el.parentNode,{childList:!0,attributes:!1,subtree:!1})),window.onbeforeunload=function(){n&&n.disconnect(),n=null,e._unbindEventListener(),e._resetState()}}},{key:"_resetState",value:function(){this.dragEl=null,this.dropEl=null,this.ghost.destroy(),this.differ.destroy(),this.calcXY={x:0,y:0},this._removeWindowState()}},{key:"_removeWindowState",value:function(){window.sortableDndOnDown=null,window.sortableDndOnMove=null,delete window.sortableDndOnDown,delete window.sortableDndOnMove}},{key:"_bindEventListener",value:function(){this._onStart=this._onStart.bind(this),this._onMove=this._onMove.bind(this),this._onDrop=this._onDrop.bind(this),this.options.supportPointer?d(this.$el,"pointerdown",this._onStart):(d(this.$el,"mousedown",this._onStart),d(this.$el,"touchstart",this._onStart))}},{key:"_unbindEventListener",value:function(){e(this.$el,"pointerdown",this._onStart),e(this.$el,"touchstart",this._onStart),e(this.$el,"mousedown",this._onStart)}},{key:"_onMoveEvents",value:function(t){var e=this.options,n=e.supportPointer,e=e.ownerDocument;d(e,n?"pointermove":t?"touchmove":"mousemove",this._onMove)}},{key:"_onUpEvents",value:function(){var t=this.options.ownerDocument;d(t,"pointerup",this._onDrop),d(t,"touchend",this._onDrop),d(t,"touchcancel",this._onDrop),d(t,"mouseup",this._onDrop)}},{key:"_offMoveEvents",value:function(){var t=this.options.ownerDocument;e(t,"pointermove",this._onMove),e(t,"touchmove",this._onMove),e(t,"mousemove",this._onMove)}},{key:"_offUpEvents",value:function(){var t=this.options.ownerDocument;e(t,"mouseup",this._onDrop),e(t,"touchend",this._onDrop),e(t,"touchcancel",this._onDrop),e(t,"pointerup",this._onDrop)}}]),n}()});
{
"name": "sortable-dnd",
"version": "0.0.11",
"version": "0.0.12",
"description": "JS Library for Drag and Drop, supports Sortable and Draggable",

@@ -5,0 +5,0 @@ "main": "dist/sortable.js",

@@ -20,11 +20,11 @@ <p>

<li>
<i>drag me</i>
<i class="drag">drag me</i>
<p>1</p>
</li>
<li>
<i>drag me</i>
<i class="drag">drag me</i>
<p>2</p>
</li>
<li>
<i>drag me</i>
<i class="drag">drag me</i>
<p>3</p>

@@ -43,6 +43,6 @@ </li>

chosenClass: 'chosen',
draggable: (e) => {
return e.target.tagName === 'I' ? true : false
},
// or draggable: 'i'
draggable: (e) => e.target.tagName === 'I' ? true : false, // use function
// draggable: 'i' // use tagName
// draggable: '.drag' // use class
// draggable: '#drag' // use id
dragging: (e) => {

@@ -67,3 +67,3 @@ return e.target

| `dragging` | `Function` | (e) => e.target | Specifies the drag and drop element, which must return an HTMLElement |
| `dragEnd` | `Function` | (pre, cur) => {} | The callback function when the drag is completed |
| `dragEnd` | `Function` | (pre, cur, changed) => {} | The callback function when the drag is completed |
| `ghostStyle` | `Object` | {} | The style of the mask element when dragging |

@@ -70,0 +70,0 @@ | `ghostClass` | `String` | '' | The class of the mask element when dragging |

@@ -1,2 +0,2 @@

import utils from './utils.js'
import { getRect, css } from './utils.js'

@@ -18,3 +18,3 @@ export default function Animation() {

target: child,
rect: utils.getRect(child)
rect: getRect(child)
})

@@ -32,17 +32,17 @@ })

animate(el, preRect, animation = 150) {
const curRect = utils.getRect(el)
const curRect = getRect(el)
const left = preRect.left - curRect.left
const top = preRect.top - curRect.top
utils.css(el, 'transition', 'none')
utils.css(el, 'transform', `translate3d(${left}px, ${top}px, 0)`)
css(el, 'transition', 'none')
css(el, 'transform', `translate3d(${left}px, ${top}px, 0)`)
el.offsetLeft // 触发重绘
utils.css(el, 'transition', `all ${animation}ms`)
utils.css(el, 'transform', 'translate3d(0px, 0px, 0px)')
css(el, 'transition', `all ${animation}ms`)
css(el, 'transform', 'translate3d(0px, 0px, 0px)')
clearTimeout(el.animated)
el.animated = setTimeout(() => {
utils.css(el, 'transition', '')
utils.css(el, 'transform', '')
css(el, 'transition', '')
css(el, 'transform', '')
el.animated = null

@@ -49,0 +49,0 @@ }, animation)

@@ -1,2 +0,14 @@

import utils from './utils.js'
import {
on,
off,
css,
matches,
getRect,
debounce,
getOffset,
_nextTick,
getElement,
toggleClass,
getParentAutoScrollElement
} from './utils.js'
import { Safari } from './Brower.js'

@@ -8,6 +20,6 @@ import Animation from './Animation.js'

*/
class Diff {
class Differ {
constructor() {
this.old = { node: null, rect: {} }
this.new = { node: null, rect: {} }
this._old_ = { node: null, rect: {}, offset: {} }
this._new_ = { node: null, rect: {}, offset: {} }
}

@@ -24,4 +36,4 @@

destroy() {
this.old = { node: null, rect: {} }
this.new = { node: null, rect: {} }
this._old_ = { node: null, rect: {}, offset: {} }
this._new_ = { node: null, rect: {}, offset: {} }
}

@@ -44,3 +56,2 @@ }

this.$el = el
this.rect = rect
const { ghostClass, ghostStyle = {} } = this.options

@@ -62,3 +73,3 @@ const { width, height } = rect

for (const key in ghostStyle) {
utils.css(this.$el, key, ghostStyle[key])
css(this.$el, key, ghostStyle[key])
}

@@ -76,2 +87,6 @@ }

rect() {
return this.$el.getBoundingClientRect()
}
move() {

@@ -98,10 +113,11 @@ // 将初始化放在 move 事件中,避免与鼠标点击事件冲突

this.options = options = Object.assign({}, options)
this.scrollEl = getParentAutoScrollElement(this.$el, true) // 获取页面滚动元素
this.dragEl = null // 拖拽元素
this.dropEl = null // 释放元素
this.diff = null // 记录拖拽前后差异
this.differ = null // 记录拖拽前后差异
this.ghost = null // 拖拽时蒙版元素
this.calcXY = { x: 0, y: 0 } // 记录拖拽移动时坐标
utils.debounce(this.init(), 50) // 避免重复执行多次
debounce(this.init(), 50) // 避免重复执行多次
}

@@ -133,3 +149,3 @@

this.diff = new Diff()
this.differ = new Differ()
this.ghost = new Ghost(this.options)

@@ -143,38 +159,14 @@

_handleDestroy() {
let observer = null
const MutationObserver = window.MutationObserver || window.WebKitMutationObserver
if (MutationObserver) {
observer = new MutationObserver(() => {
if (!this.$el) {
observer.disconnect()
observer = null
this._unbindEventListener()
this._resetState()
}
})
observer.observe(this.$el.parentNode, {
childList: true, // 观察目标子节点的变化,是否有添加或者删除
attributes: false, // 观察属性变动
subtree: false // 观察后代节点,默认为 false
})
}
window.onbeforeunload = () => {
if (observer) observer.disconnect()
observer = null
this._unbindEventListener()
this._resetState()
}
}
// -------------------------------- drag and drop ----------------------------------
_onStart(evt) {
const { dragging, draggable } = this.options
const touch = (evt.touches && evt.touches[0]) || (evt.pointerType && evt.pointerType === 'touch' && evt)
const target = (touch || evt).target
const e = touch || evt
if (typeof draggable === 'function') {
if (!draggable(touch || evt)) return true
if (!draggable(e)) return true
} else if (typeof draggable === 'string') {
if (!utils.matches(target, draggable)) return true
if (!matches(e.target, draggable)) return true
} else if (draggable !== undefined) {

@@ -185,3 +177,3 @@ throw new Error(`draggable expected "function" or "string" but received "${typeof draggable}"`)

if (/mousedown|pointerdown/.test(evt.type) && evt.button !== 0) return // only left button and enabled
if (target === this.$el) return true
if (e.target === this.$el) return true

@@ -191,3 +183,3 @@ try {

// Timeout neccessary for IE9
utils._nextTick(() => { document.selection.empty() })
_nextTick(() => { document.selection.empty() })
} else {

@@ -198,5 +190,3 @@ window.getSelection().removeAllRanges()

// 获取拖拽元素
const element = dragging && typeof dragging === 'function'
? dragging(touch || evt)
: utils.getElement(this.$el, target).el
const element = typeof dragging === 'function' ? dragging(e) : getElement(this.$el, e.target).el

@@ -216,3 +206,3 @@ // 不存在拖拽元素时不允许拖拽

// 获取当前元素在列表中的位置
const { index, el, rect } = utils.getElement(this.$el, this.dragEl)
const { index, el, rect, offset } = getElement(this.$el, this.dragEl)

@@ -227,5 +217,7 @@ if (!el || index < 0) return true

this.diff.old.rect = rect
this.differ._old_.rect = rect
this.differ._old_.offset = offset
this.differ._old_.node = this.dragEl
this.calcXY = { x: (touch || evt).clientX, y: (touch || evt).clientY }
this.calcXY = { x: e.clientX, y: e.clientY }

@@ -245,3 +237,3 @@ this._onMoveEvents(touch)

const { chosenClass } = this.options
utils.toggleClass(this.dragEl, chosenClass, true)
toggleClass(this.dragEl, chosenClass, true)
this.ghost.move()

@@ -260,5 +252,3 @@

this._checkRange(e)
const { index, el, rect } = utils.getElement(this.$el, target)
const { index, el, rect, offset } = getElement(this.$el, target)
const { left, right, top, bottom } = rect

@@ -268,2 +258,18 @@

// 判断边界值
const _rect = getRect(this.$el)
this._checkRange(e, _rect)
const { scrollTop, scrollLeft } = this.scrollEl
// 如果目标元素超出当前可视区,不允许拖动
if (this.scrollEl !== this.$el && (_rect.left < 0 || _rect.top < 0)) {
if (rect.top < (_rect.top + scrollTop) && _rect.top < 0) return
if (rect.left < (_rect.left + scrollLeft) && _rect.left < 0) return
} else {
if (rect.top < _rect.top) return
if (rect.left < _rect.left) return
}
if (clientX > left && clientX < right && clientY > top && clientY < bottom) {

@@ -277,4 +283,7 @@ this.dropEl = el

this.captureAnimationState()
const _offset = getOffset(this.dragEl) // 获取拖拽元素的 offset 值
if (utils.index(this.$el, this.dragEl) < index) {
// 优先比较 top 值,top 值相同再比较 left
if (_offset.top < offset.top || _offset.left < offset.left) {
this.$el.insertBefore(this.dragEl, this.dropEl.nextElementSibling)

@@ -286,7 +295,5 @@ } else {

this.animateRange()
this.diff.old.node = this.dragEl
this.diff.new.node = this.dropEl
this.differ._new_.node = this.dropEl
this.differ._new_.rect = getRect(this.dropEl)
}
this.diff.new.rect = utils.getRect(this.dropEl)
}

@@ -302,8 +309,20 @@ }

utils.toggleClass(this.dragEl, chosenClass, false)
toggleClass(this.dragEl, chosenClass, false)
if (window.sortableDndOnDown && window.sortableDndOnMove) {
// 重新获取一次拖拽元素的 offset 值作为拖拽完成后的 offset 值
this.differ._new_.offset = getOffset(this.dragEl)
// 拖拽完成触发回调函数
const { _old_, _new_ } = this.differ
// 通过 offset 比较是否进行了元素交换
const changed = _old_.offset.top !== _new_.offset.top || _old_.offset.left !== _new_.offset.left
// 如果拖拽前后没有发生交换,重新赋值一次
if (!changed) this.differ._new_.node = this.differ._old_.node
if (typeof dragEnd === 'function') {
dragEnd(this.diff.old, this.diff.new)
dragEnd(_old_, _new_, changed)
} else {

@@ -314,3 +333,3 @@ throw new Error(`Sortable-dnd Error: dragEnd expected "function" but received "${typeof dragEnd}"`)

this.diff.destroy()
this.differ.destroy()
this.ghost.destroy()

@@ -320,4 +339,4 @@ this._removeWindowState()

_checkRange(e) {
const { top, left, right, bottom } = utils.getRect(this.$el)
_checkRange(e, groupRect) {
const { top, left, right, bottom } = groupRect

@@ -330,2 +349,32 @@ if (e.clientX < left || e.clientX > right || e.clientY < top || e.clientY > bottom) {

// -------------------------------- auto destroy ----------------------------------
_handleDestroy() {
let observer = null
const MutationObserver = window.MutationObserver || window.WebKitMutationObserver
if (MutationObserver) {
const { ownerDocument } = this.options
observer = new MutationObserver(() => {
if (!ownerDocument.body.contains(this.$el)) {
observer.disconnect()
observer = null
this._unbindEventListener()
this._resetState()
}
})
observer.observe(this.$el.parentNode, {
childList: true, // 观察目标子节点的变化,是否有添加或者删除
attributes: false, // 观察属性变动
subtree: false // 观察后代节点,默认为 false
})
}
window.onbeforeunload = () => {
if (observer) observer.disconnect()
observer = null
this._unbindEventListener()
this._resetState()
}
}
// -------------------------------- reset state ----------------------------------
_resetState() {

@@ -335,3 +384,3 @@ this.dragEl = null

this.ghost.destroy()
this.diff.destroy()
this.differ.destroy()
this.calcXY = { x: 0, y: 0 }

@@ -348,2 +397,3 @@ this._removeWindowState()

// -------------------------------- listener ----------------------------------
_bindEventListener() {

@@ -356,6 +406,6 @@ this._onStart = this._onStart.bind(this)

if (supportPointer) {
utils.on(this.$el, 'pointerdown', this._onStart)
on(this.$el, 'pointerdown', this._onStart)
} else {
utils.on(this.$el, 'mousedown', this._onStart)
utils.on(this.$el, 'touchstart', this._onStart)
on(this.$el, 'mousedown', this._onStart)
on(this.$el, 'touchstart', this._onStart)
}

@@ -365,5 +415,5 @@ }

_unbindEventListener() {
utils.off(this.$el, 'pointerdown', this._onStart)
utils.off(this.$el, 'touchstart', this._onStart)
utils.off(this.$el, 'mousedown', this._onStart)
off(this.$el, 'pointerdown', this._onStart)
off(this.$el, 'touchstart', this._onStart)
off(this.$el, 'mousedown', this._onStart)
}

@@ -374,7 +424,7 @@

if (supportPointer) {
utils.on(ownerDocument, 'pointermove', this._onMove)
on(ownerDocument, 'pointermove', this._onMove)
} else if (touch) {
utils.on(ownerDocument, 'touchmove', this._onMove)
on(ownerDocument, 'touchmove', this._onMove)
} else {
utils.on(ownerDocument, 'mousemove', this._onMove)
on(ownerDocument, 'mousemove', this._onMove)
}

@@ -385,6 +435,6 @@ }

const { ownerDocument } = this.options
utils.on(ownerDocument, 'pointerup', this._onDrop)
utils.on(ownerDocument, 'touchend', this._onDrop)
utils.on(ownerDocument, 'touchcancel', this._onDrop)
utils.on(ownerDocument, 'mouseup', this._onDrop)
on(ownerDocument, 'pointerup', this._onDrop)
on(ownerDocument, 'touchend', this._onDrop)
on(ownerDocument, 'touchcancel', this._onDrop)
on(ownerDocument, 'mouseup', this._onDrop)
}

@@ -394,5 +444,5 @@

const { ownerDocument } = this.options
utils.off(ownerDocument, 'pointermove', this._onMove)
utils.off(ownerDocument, 'touchmove', this._onMove)
utils.off(ownerDocument, 'mousemove', this._onMove)
off(ownerDocument, 'pointermove', this._onMove)
off(ownerDocument, 'touchmove', this._onMove)
off(ownerDocument, 'mousemove', this._onMove)
}

@@ -402,6 +452,6 @@

const { ownerDocument } = this.options
utils.off(ownerDocument, 'mouseup', this._onDrop)
utils.off(ownerDocument, 'touchend', this._onDrop)
utils.off(ownerDocument, 'touchcancel', this._onDrop)
utils.off(ownerDocument, 'pointerup', this._onDrop)
off(ownerDocument, 'mouseup', this._onDrop)
off(ownerDocument, 'touchend', this._onDrop)
off(ownerDocument, 'touchcancel', this._onDrop)
off(ownerDocument, 'pointerup', this._onDrop)
}

@@ -408,0 +458,0 @@ }

@@ -10,11 +10,9 @@ import { IE11OrLess } from './Brower.js'

export default {
/**
* add specified event listener
* @param {HTMLElement} el
* @param {String} event
* @param {Function} fn
*/
on(el, event, fn) {
/**
* add specified event listener
* @param {HTMLElement} el
* @param {String} event
* @param {Function} fn
*/
export function on(el, event, fn) {
if (window.addEventListener) {

@@ -25,205 +23,281 @@ el.addEventListener(event, fn, !IE11OrLess && captureMode)

}
},
/**
* remove specified event listener
* @param {HTMLElement} el
* @param {String} event
* @param {Function} fn
*/
off(el, event, fn) {
if (window.removeEventListener) {
el.removeEventListener(event, fn, !IE11OrLess && captureMode)
} else if (window.detachEvent) {
el.detachEvent('on' + event, fn)
}
},
}
getWindowScrollingElement() {
let scrollingElement = document.scrollingElement
if (scrollingElement) {
return scrollingElement
} else {
return document.documentElement
}
},
/**
* remove specified event listener
* @param {HTMLElement} el
* @param {String} event
* @param {Function} fn
*/
export function off(el, event, fn) {
if (window.removeEventListener) {
el.removeEventListener(event, fn, !IE11OrLess && captureMode)
} else if (window.detachEvent) {
el.detachEvent('on' + event, fn)
}
}
/**
* get specified element's index in group
* @param {HTMLElement} group
* @param {HTMLElement} el
* @returns {Number} index
*/
index(group, el) {
if (!el || !el.parentNode) return -1
/**
* get element's offetTop
* @param {HTMLElement} el
*/
export function getOffset(el) {
let result = {
top: 0,
left: 0,
height: 0,
width: 0
}
result.height = el.offsetHeight
result.width = el.offsetWidth
result.top = el.offsetTop
result.left = el.offsetLeft
const children = [...Array.from(group.children)]
return children.indexOf(el)
},
let parent = el.offsetParent
/**
* Returns the "bounding client rect" of given element
* @param {HTMLElement} el The element whose boundingClientRect is wanted
*/
getRect(el) {
if (!el.getBoundingClientRect && el !== window) return
while (parent !== null) {
result.top += parent.offsetTop
result.left += parent.offsetLeft
parent = parent.offsetParent
}
const rect = {
top: 0,
left: 0,
bottom: 0,
right: 0,
height: 0,
width: 0,
}
return result
}
let elRect
if (el !== window && el.parentNode && el !== this.getWindowScrollingElement()) {
elRect = el.getBoundingClientRect()
rect.top = elRect.top
rect.left = elRect.left
rect.bottom = elRect.bottom
rect.right = elRect.right
rect.height = elRect.height
rect.width = elRect.width
} else {
rect.top = 0
rect.left = 0
rect.bottom = window.innerHeight
rect.right = window.innerWidth
rect.height = window.innerHeight
rect.width = window.innerWidth
}
/**
* get scroll element
* @param {HTMLElement} el
* @param {Boolean} includeSelf whether to include the passed element
* @returns {HTMLElement} scroll element
*/
export function getParentAutoScrollElement(el, includeSelf) {
// skip to window
if (!el || !el.getBoundingClientRect) return getWindowScrollingElement()
return rect
},
let elem = el
let gotSelf = false
do {
// we don't need to get elem css if it isn't even overflowing in the first place (performance)
if (elem.clientWidth < elem.scrollWidth || elem.clientHeight < elem.scrollHeight) {
let elemCSS = css(elem)
if (
elem.clientWidth < elem.scrollWidth && (elemCSS.overflowX == 'auto' || elemCSS.overflowX == 'scroll') ||
elem.clientHeight < elem.scrollHeight && (elemCSS.overflowY == 'auto' || elemCSS.overflowY == 'scroll')
) {
if (!elem.getBoundingClientRect || elem === document.body) return getWindowScrollingElement()
/**
* get target Element in group
* @param {HTMLElement} group
* @param {HTMLElement} el
*/
getElement(group, el) {
const result = { index: -1, el: null, rect: {} }
const children = [...Array.from(group.children)]
if (gotSelf || includeSelf) return elem
gotSelf = true
}
}
} while (elem = elem.parentNode)
// 如果能直接在子元素中找到,返回对应的index
const index = children.indexOf(el)
if (index > -1)
return getWindowScrollingElement()
}
export function getWindowScrollingElement() {
let scrollingElement = document.scrollingElement
if (scrollingElement) {
return scrollingElement
} else {
return document.documentElement
}
}
/**
* get specified element's index in group
* @param {HTMLElement} group
* @param {HTMLElement} el
* @returns {Number} index
*/
export function getIndex(group, el) {
if (!el || !el.parentNode) return -1
const children = [...Array.from(group.children)]
return children.indexOf(el)
}
/**
* Returns the "bounding client rect" of given element
* @param {HTMLElement} el The element whose boundingClientRect is wanted
*/
export function getRect(el) {
if (!el.getBoundingClientRect && el !== window) return
const rect = {
top: 0,
left: 0,
bottom: 0,
right: 0,
height: 0,
width: 0,
}
let elRect
if (el !== window && el.parentNode && el !== getWindowScrollingElement()) {
elRect = el.getBoundingClientRect()
rect.top = elRect.top
rect.left = elRect.left
rect.bottom = elRect.bottom
rect.right = elRect.right
rect.height = elRect.height
rect.width = elRect.width
} else {
rect.top = 0
rect.left = 0
rect.bottom = window.innerHeight
rect.right = window.innerWidth
rect.height = window.innerHeight
rect.width = window.innerWidth
}
return rect
}
/**
* get target Element in group
* @param {HTMLElement} group
* @param {HTMLElement} el
*/
export function getElement(group, el) {
const result = { index: -1, el: null, rect: {}, offset: {} }
const children = [...Array.from(group.children)]
// 如果能直接在子元素中找到,返回对应的index
const index = children.indexOf(el)
if (index > -1)
Object.assign(result, {
index,
el: children[index],
rect: getRect(children[index]),
offset: getOffset(children[index])
})
// children 中无法直接找到对应的dom时,需要向下寻找
for (let i = 0; i < children.length; i++) {
if (isChildOf(el, children[i])) {
Object.assign(result, {
index,
el: children[index],
rect: this.getRect(children[index])
index: i,
el: children[i],
rect: getRect(children[i]),
offset: getOffset(children[i])
})
// children 中无法直接找到对应的dom时,需要向下寻找
for (let i = 0; i < children.length; i++) {
if (this.isChildOf(el, children[i]))
Object.assign(result, {
index: i,
el: children[i],
rect: this.getRect(children[i])
})
break
}
}
return result
}
return result
},
/**
* Check if child element is contained in parent element
* @param {HTMLElement} child
* @param {HTMLElement} parent
* @returns {Boolean} true | false
*/
isChildOf(child, parent) {
let parentNode
if (child && parent) {
parentNode = child.parentNode
while (parentNode) {
if (parent === parentNode) return true
parentNode = parentNode.parentNode
}
/**
* Check if child element is contained in parent element
* @param {HTMLElement} child
* @param {HTMLElement} parent
* @returns {Boolean} true | false
*/
export function isChildOf(child, parent) {
let parentNode
if (child && parent) {
parentNode = child.parentNode
while (parentNode) {
if (parent === parentNode) return true
parentNode = parentNode.parentNode
}
return false
},
}
return false
}
/**
* add or remove element's class
* @param {HTMLElement} el element
* @param {String} name class name
* @param {Boolean} state true: add, false: remove
*/
toggleClass(el, name, state) {
if (el && name) {
if (el.classList) {
el.classList[state ? 'add' : 'remove'](name)
} else {
const className = (' ' + el.className + ' ').replace(R_SPACE, ' ').replace(' ' + name + ' ', ' ')
el.className = (className + (state ? ' ' + name : '')).replace(R_SPACE, ' ')
}
/**
* add or remove element's class
* @param {HTMLElement} el element
* @param {String} name class name
* @param {Boolean} state true: add, false: remove
*/
export function toggleClass(el, name, state) {
if (el && name) {
if (el.classList) {
el.classList[state ? 'add' : 'remove'](name)
} else {
const className = (' ' + el.className + ' ').replace(R_SPACE, ' ').replace(' ' + name + ' ', ' ')
el.className = (className + (state ? ' ' + name : '')).replace(R_SPACE, ' ')
}
},
}
}
/**
* Check if a DOM element matches a given selector
* @param {HTMLElement} el
* @param {String} selector
* @returns
*/
matches(el, selector) {
if (!selector) return
selector[0] === '>' && (selector = selector.substring(1))
if (el) {
try {
if (el.matches) {
return el.matches(selector)
} else if (el.msMatchesSelector) {
return el.msMatchesSelector(selector)
} else if (el.webkitMatchesSelector) {
return el.webkitMatchesSelector(selector)
}
} catch(error) {
return false
/**
* Check if a DOM element matches a given selector
* @param {HTMLElement} el
* @param {String} selector
* @returns
*/
export function matches(el, selector) {
if (!selector) return
selector[0] === '>' && (selector = selector.substring(1))
if (el) {
try {
if (el.matches) {
return el.matches(selector)
} else if (el.msMatchesSelector) {
return el.msMatchesSelector(selector)
} else if (el.webkitMatchesSelector) {
return el.webkitMatchesSelector(selector)
}
} catch(error) {
return false
}
return false
},
}
css(el, prop, val) {
let style = el && el.style
if (style) {
if (val === void 0) {
if (document.defaultView && document.defaultView.getComputedStyle) {
val = document.defaultView.getComputedStyle(el, '')
} else if (el.currentStyle) {
val = el.currentStyle
}
return prop === void 0 ? val : val[prop]
} else {
if (!(prop in style) && prop.indexOf('webkit') === -1) {
prop = '-webkit-' + prop
}
style[prop] = val + (typeof val === 'string' ? '' : 'px')
return false
}
export function css(el, prop, val) {
let style = el && el.style
if (style) {
if (val === void 0) {
if (document.defaultView && document.defaultView.getComputedStyle) {
val = document.defaultView.getComputedStyle(el, '')
} else if (el.currentStyle) {
val = el.currentStyle
}
return prop === void 0 ? val : val[prop]
} else {
if (!(prop in style) && prop.indexOf('webkit') === -1) {
prop = '-webkit-' + prop
}
style[prop] = val + (typeof val === 'string' ? '' : 'px')
}
},
}
}
debounce(fn, delay) {
return function (...args) {
clearTimeout(fn.id)
fn.id = setTimeout(() => {
fn.call(this, ...args)
}, delay)
}
},
_nextTick(fn) {
return setTimeout(fn, 0)
export function debounce(fn, delay) {
return function (...args) {
clearTimeout(fn.id)
fn.id = setTimeout(() => {
fn.call(this, ...args)
}, delay)
}
}
export function _nextTick(fn) {
return setTimeout(fn, 0)
}
export default {
on,
off,
css,
getRect,
matches,
getIndex,
debounce,
_nextTick,
isChildOf,
getElement,
toggleClass,
getWindowScrollingElement,
getParentAutoScrollElement,
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc