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
74
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.2.7 to 0.3.0

867

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

@@ -13,2 +13,28 @@ * https://github.com/mfuu/sortable-dnd#readme

function ownKeys(object, enumerableOnly) {
var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(object);
enumerableOnly && (symbols = symbols.filter(function (sym) {
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
})), keys.push.apply(keys, symbols);
}
return keys;
}
function _objectSpread2(target) {
for (var i = 1; i < arguments.length; i++) {
var source = null != arguments[i] ? arguments[i] : {};
i % 2 ? ownKeys(Object(source), !0).forEach(function (key) {
_defineProperty(target, key, source[key]);
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) {
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
});
}
return target;
}
function _typeof(obj) {

@@ -49,2 +75,17 @@ "@babel/helpers - typeof";

function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _toConsumableArray(arr) {

@@ -104,2 +145,16 @@ return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();

/**
* check if is HTMLElement
*/
function isHTMLElement(obj) {
var d = document.createElement("div");
try {
d.appendChild(obj.cloneNode(true));
return obj.nodeType == 1 ? true : false;
} catch (e) {
return obj == window || obj == document;
}
}
/**
* set transition style

@@ -353,2 +408,18 @@ * @param {HTMLElement} el

/**
* Gets the last child in the el, ignoring ghostEl or invisible elements (clones)
* @param {HTMLElement} el Parent element
* @param {selector} selector Any other elements that should be ignored
* @return {HTMLElement} The last child, ignoring ghostEl
*/
function lastChild(el, selector) {
var last = el.lastElementChild;
while (last && (last === Sortable.ghost || css(last, 'display') === 'none' || selector && !matches(last, selector))) {
last = last.previousElementSibling;
}
return last || null;
}
/**
* add or remove element's class

@@ -397,2 +468,9 @@ * @param {HTMLElement} el element

}
/**
* Check whether the front and rear positions are consistent
*/
function offsetChanged(o1, o2) {
return o1.top !== o2.top || o1.left !== o2.left;
}
function css(el, prop, val) {

@@ -448,3 +526,8 @@ var style = el && el.style;

}
var expando = 'Sortable' + Date.now();
/**
* Sortable states
*/
var State = /*#__PURE__*/_createClass(function State() {

@@ -458,3 +541,3 @@ _classCallCheck(this, State);

/**
* 拖拽前后差异初始化
* Difference before and after dragging
*/

@@ -467,2 +550,4 @@

this.from = {
sortable: null,
group: null,
node: null,

@@ -473,2 +558,4 @@ rect: {},

this.to = {
sortable: null,
group: null,
node: null,

@@ -481,15 +568,7 @@ rect: {},

_createClass(Differ, [{
key: "get",
value: function get(key) {
return this[key];
}
}, {
key: "set",
value: function set(key, value) {
this[key] = value;
}
}, {
key: "destroy",
value: function destroy() {
this.from = {
sortable: null,
group: null,
node: null,

@@ -500,2 +579,4 @@ rect: {},

this.to = {
sortable: null,
group: null,
node: null,

@@ -511,3 +592,3 @@ rect: {},

/**
* 拖拽中的元素
* Elements being dragged
*/

@@ -519,3 +600,3 @@

this.$el = null;
this.el = null;
this.distance = {

@@ -533,3 +614,4 @@ x: 0,

var append = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
this.$el = el;
this.el = el;
if (!append) return;
var _this$options = this.options,

@@ -539,19 +621,20 @@ ghostClass = _this$options.ghostClass,

ghostStyle = _this$options$ghostSt === void 0 ? {} : _this$options$ghostSt;
toggleClass(this.$el, ghostClass, true);
css(this.$el, 'box-sizing', 'border-box');
css(this.$el, 'margin', 0);
css(this.$el, 'top', rect.top);
css(this.$el, 'left', rect.left);
css(this.$el, 'width', rect.width);
css(this.$el, 'height', rect.height);
css(this.$el, 'opacity', '0.8'); // css(this.$el, 'position', IOS ? 'absolute' : 'fixed')
toggleClass(this.el, ghostClass, true);
css(this.el, 'box-sizing', 'border-box');
css(this.el, 'margin', 0);
css(this.el, 'top', rect.top);
css(this.el, 'left', rect.left);
css(this.el, 'width', rect.width);
css(this.el, 'height', rect.height);
css(this.el, 'opacity', '0.8'); // css(this.el, 'position', IOS ? 'absolute' : 'fixed')
css(this.$el, 'position', 'fixed');
css(this.$el, 'zIndex', '100000');
css(this.$el, 'pointerEvents', 'none');
css(this.el, 'position', 'fixed');
css(this.el, 'zIndex', '100000');
css(this.el, 'pointerEvents', 'none');
this.setStyle(ghostStyle);
setTransition(this.$el, 'none');
setTransform(this.$el, 'translate3d(0px, 0px, 0px)');
if (append) this.container.appendChild(this.$el);
css(this.$el, 'transform-origin', this.distance.x / parseInt(this.$el.style.width) * 100 + '% ' + this.distance.y / parseInt(this.$el.style.height) * 100 + '%');
setTransition(this.el, 'none');
setTransform(this.el, 'translate3d(0px, 0px, 0px)');
this.container.appendChild(this.el);
css(this.el, 'transform-origin', this.distance.x / parseInt(this.el.style.width) * 100 + '% ' + this.distance.y / parseInt(this.el.style.height) * 100 + '%');
css(this.el, 'transform', 'translateZ(0)');
}

@@ -562,3 +645,3 @@ }, {

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

@@ -569,3 +652,3 @@ }

value: function rect() {
return getRect(this.$el);
return getRect(this.el);
}

@@ -576,7 +659,17 @@ }, {

var smooth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
if (!this.$el) return;
setTransition(this.$el, smooth ? "".concat(this.options.ghostAnimation, "ms") : 'none');
setTransform(this.$el, "translate3d(".concat(x, "px, ").concat(y, "px, 0)"));
if (!this.el) return;
setTransition(this.el, smooth ? "".concat(this.options.ghostAnimation, "ms") : 'none');
setTransform(this.el, "translate3d(".concat(x, "px, ").concat(y, "px, 0)"));
}
}, {
key: "clear",
value: function clear() {
this.distance = {
x: 0,
y: 0
};
this.el && this.el.remove();
this.el = null;
}
}, {
key: "destroy",

@@ -586,5 +679,5 @@ value: function destroy(rect) {

if (!this.$el) return;
var left = parseInt(this.$el.style.left);
var top = parseInt(this.$el.style.top);
if (!this.el) return;
var left = parseInt(this.el.style.left);
var top = parseInt(this.el.style.top);
this.move(rect.left - left, rect.top - top, true);

@@ -596,12 +689,2 @@ var ghostAnimation = this.options.ghostAnimation;

}
}, {
key: "clear",
value: function clear() {
this.$el && this.$el.remove();
this.distance = {
x: 0,
y: 0
};
this.$el = null;
}
}]);

@@ -620,18 +703,19 @@

return {
_autoScroll: throttle(function (_this) {
// check if is moving now
if (!(_this.state.sortableDown && _this.state.sortableMove)) return;
var _this$state$sortableM = _this.state.sortableMove,
clientX = _this$state$sortableM.clientX,
clientY = _this$state$sortableM.clientY;
_autoScroll: throttle(function (Sortable, state) {
if (!Sortable.scrollEl) return; // check if is moving now
if (!(state.sortableDown && state.sortableMove)) return;
var _state$sortableMove = state.sortableMove,
clientX = _state$sortableMove.clientX,
clientY = _state$sortableMove.clientY;
if (clientX === void 0 || clientY === void 0) return;
if (_this.scrollEl === _this.ownerDocument) ; else {
var _this$scrollEl = _this.scrollEl,
scrollTop = _this$scrollEl.scrollTop,
scrollLeft = _this$scrollEl.scrollLeft,
scrollHeight = _this$scrollEl.scrollHeight,
scrollWidth = _this$scrollEl.scrollWidth;
if (Sortable.scrollEl === Sortable.ownerDocument) ; else {
var _Sortable$scrollEl = Sortable.scrollEl,
scrollTop = _Sortable$scrollEl.scrollTop,
scrollLeft = _Sortable$scrollEl.scrollLeft,
scrollHeight = _Sortable$scrollEl.scrollHeight,
scrollWidth = _Sortable$scrollEl.scrollWidth;
var _getRect = getRect(_this.scrollEl),
var _getRect = getRect(Sortable.scrollEl),
top = _getRect.top,

@@ -644,5 +728,5 @@ right = _getRect.right,

var _this$options = _this.options,
scrollStep = _this$options.scrollStep,
scrollThreshold = _this$options.scrollThreshold; // check direction
var _Sortable$options = Sortable.options,
scrollStep = _Sortable$options.scrollStep,
scrollThreshold = _Sortable$options.scrollThreshold; // check direction

@@ -698,5 +782,5 @@ var totop = scrollTop > 0 && clientY >= top && clientY <= top + scrollThreshold;

requestAnimationFrame(function () {
_this.scrollEl.scrollTo(position.x, position.y);
Sortable.scrollEl.scrollTo(position.x, position.y);
_this._autoScroll(_this);
Sortable._autoScroll(Sortable, state);
});

@@ -725,6 +809,6 @@ }

return {
captureAnimationState: function captureAnimationState() {
var children = _toConsumableArray(Array.from(this.rootEl.children));
_captureAnimationState: function _captureAnimationState(dragEl, dropEl) {
var children = _toConsumableArray(Array.from(this.el.children));
var _getRange = getRange(children, this.dragEl, this.dropEl),
var _getRange = getRange(children, dragEl, dropEl),
start = _getRange.start,

@@ -742,3 +826,3 @@ end = _getRange.end;

},
animateRange: function animateRange() {
_rangeAnimate: function _rangeAnimate() {
var _this = this;

@@ -750,6 +834,6 @@

_this.animate(target, rect, _this.options.animation);
_this._animate(target, rect, _this.options.animation);
});
},
animate: function animate(el, preRect) {
_animate: function _animate(el, preRect) {
var animation = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 150;

@@ -761,3 +845,3 @@ var curRect = getRect(el);

setTransform(el, "translate3d(".concat(left, "px, ").concat(top, "px, 0)"));
el.offsetLeft; // trigger repaint
el.offsetWidth; // trigger repaint

@@ -776,58 +860,108 @@ setTransition(el, "".concat(animation, "ms"));

function DNDEvent() {
return {
_bindEventListener: function _bindEventListener() {
this._onDrag = this._onDrag.bind(this);
this._onMove = this._onMove.bind(this);
this._onDrop = this._onDrop.bind(this);
var _this$options = this.options,
supportPointer = _this$options.supportPointer,
supportTouch = _this$options.supportTouch;
var documentExists = typeof document !== 'undefined';
var supportDraggable = documentExists && !ChromeForAndroid && !IOS && 'draggable' in document.createElement('div');
var sortables = [];
var rootEl,
dragEl,
dropEl,
nextEl,
ghostEl,
activeGroup,
move = {
x: 0,
y: 0
},
state = new State(),
// Status record during drag and drop
differ = new Differ(); // Record the difference before and after dragging
if (supportPointer) {
on(this.rootEl, 'pointerdown', this._onDrag);
} else if (supportTouch) {
on(this.rootEl, 'touchstart', this._onDrag);
} else {
on(this.rootEl, 'mousedown', this._onDrag);
var _prepareGroup = function _prepareGroup(options) {
var group = {};
var originalGroup = options.group;
if (!originalGroup || _typeof(originalGroup) != 'object') {
originalGroup = {
name: originalGroup
};
}
group.name = originalGroup.name;
group.pull = originalGroup.pull;
group.put = originalGroup.put;
options.group = group;
};
/**
* get nearest Sortable
*/
var _nearestSortable = function _nearestSortable(evt) {
_checkPosition(evt);
if (dragEl) {
evt = evt.touches ? evt.touches[0] : evt;
var _evt = evt,
clientX = _evt.clientX,
clientY = _evt.clientY;
var nearest = _detectNearestSortable(clientX, clientY);
if (nearest) {
// Create imitation event
var event = {};
for (var i in evt) {
event[i] = evt[i];
}
},
_clearEvent: function _clearEvent() {
off(this.rootEl, 'pointerdown', this._onDrag);
off(this.rootEl, 'touchstart', this._onDrag);
off(this.rootEl, 'mousedown', this._onDrag);
},
_bindMoveEvents: function _bindMoveEvents(touch) {
if (this.options.supportPointer) {
on(this.ownerDocument, 'pointermove', this._onMove);
} else if (touch) {
on(this.ownerDocument, 'touchmove', this._onMove);
} else {
on(this.ownerDocument, 'mousemove', this._onMove);
}
},
_unbindMoveEvents: function _unbindMoveEvents() {
off(this.ownerDocument, 'pointermove', this._onMove);
off(this.ownerDocument, 'touchmove', this._onMove);
off(this.ownerDocument, 'mousemove', this._onMove);
},
_unbindDropEvents: function _unbindDropEvents() {
off(this.ownerDocument, 'pointerup', this._onDrop);
off(this.ownerDocument, 'pointercancel', this._onDrop);
off(this.ownerDocument, 'touchend', this._onDrop);
off(this.ownerDocument, 'touchcancel', this._onDrop);
off(this.ownerDocument, 'mouseup', this._onDrop);
},
_unbindDragEvents: function _unbindDragEvents() {
if (this.nativeDraggable) {
off(this.rootEl, 'dragstart', this._onDragStart);
off(this.rootEl, 'dragover', this._onDragOver);
off(this.rootEl, 'dragend', this._onDrop);
}
event.target = document.elementFromPoint(clientX, clientY);
event.rootEl = nearest;
event.preventDefault = void 0;
event.stopPropagation = void 0;
nearest[expando]._triggerEvent(event);
}
};
}
}
};
/**
* Detects first nearest empty sortable to X and Y position using emptyInsertThreshold.
* @param {Number} x X position
* @param {Number} y Y position
* @return {HTMLElement} Element of the first found nearest Sortable
*/
var documentExists = typeof document !== 'undefined';
var supportDraggable = documentExists && !ChromeForAndroid && !IOS && 'draggable' in document.createElement('div');
var _detectNearestSortable = function _detectNearestSortable(x, y) {
var result;
sortables.some(function (sortable) {
var threshold = sortable[expando].options.emptyInsertThreshold;
if (!threshold) return;
var rect = getRect(sortable),
insideHorizontally = x >= rect.left - threshold && x <= rect.right + threshold,
insideVertically = y >= rect.top - threshold && y <= rect.bottom + threshold;
if (insideHorizontally && insideVertically) {
return result = sortable;
}
});
return result;
};
var lastPosition = {
x: 0,
y: 0
};
var _checkPosition = function _checkPosition(evt) {
var clientX = evt.clientX,
clientY = evt.clientY;
var distanceX = clientX - lastPosition.x;
var distanceY = clientY - lastPosition.y;
lastPosition.x = clientX;
lastPosition.y = clientY;
if (clientX !== void 0 && Math.abs(distanceX) < 1 && clientY !== void 0 && Math.abs(distanceY) < 1) {
return;
}
};
/**

@@ -839,2 +973,3 @@ * @class Sortable

function Sortable(el, options) {

@@ -845,4 +980,4 @@ if (!(el && el.nodeType && el.nodeType === 1)) {

this.rootEl = el; // root element
el[expando] = this;
this.el = el;
this.scrollEl = getParentAutoScrollElement(el, true); // scroll element

@@ -853,2 +988,16 @@

var defaults = {
group: '',
// string: 'group' or object: { name: 'group', put: true | false, pull: true | false }
animation: 150,
// Define the timing of the sorting animation
draggable: undefined,
// String: css selector, Function: (e) => return true
onDrag: undefined,
// The callback function triggered when dragging starts: () => {}
onMove: undefined,
// The callback function during drag and drop: (from, to) => {}
onDrop: undefined,
// The callback function when the drag is completed: (from, to, changed) => {}
onChange: undefined,
// The callback function when dragging an element to change its position: (from, to) => {}
autoScroll: true,

@@ -866,4 +1015,2 @@ // Auto scrolling when dragging to the edge of the container

// Defines whether the sortable object is available or not. When it is true, the sortable object cannot drag and drop sorting and other functions. When it is false, it can be sorted, which is equivalent to a switch.
animation: 150,
// Define the timing of the sorting animation
ghostAnimation: 0,

@@ -877,14 +1024,2 @@ // Animation when the ghost element is destroyed

// Chosen element style
draggable: undefined,
// String: css selector, Function: (e) => return true
dragging: undefined,
// Set the drag element, must be a function and must return an HTMLElement: (e) => return e.target
onDrag: undefined,
// The callback function triggered when dragging starts: () => {}
onMove: undefined,
// The callback function during drag and drop: (from, to) => {}
onDrop: undefined,
// The callback function when the drag is completed: (from, to, changed) => {}
onChange: undefined,
// The callback function when dragging an element to change its position: (from, to) => {}
fallbackOnBody: false,

@@ -896,3 +1031,4 @@ forceFallback: false,

supportPointer: 'PointerEvent' in window && !Safari,
supportTouch: 'ontouchstart' in window
supportTouch: 'ontouchstart' in window,
emptyInsertThreshold: 5
}; // Set default options

@@ -904,24 +1040,38 @@

this.container = this.options.fallbackOnBody ? document.body : this.rootEl;
this.container = this.options.fallbackOnBody ? document.body : el;
this.nativeDraggable = this.options.forceFallback ? false : supportDraggable;
this.move = {
x: 0,
y: 0
};
this.state = new State(); // Status record during drag and drop
this.ghost = new Ghost(this); // Mask element while dragging
this.differ = new Differ(); // Record the difference before and after dragging
this.dragStartTimer = null; // setTimeout timer
this.ghost = new Ghost(this); // Mask element while dragging
this.autoScrollTimer = null;
this.dragEl = null; // Drag element
_prepareGroup(options); // Bind all private methods
this.dropEl = null; // Drop element
this.dragStartTimer = null; // setTimeout timer
for (var fn in this) {
if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {
this[fn] = this[fn].bind(this);
}
}
this.autoScrollTimer = null;
Object.assign(this, DNDEvent(), Animation(), AutoScroll());
var _this$options = this.options,
supportPointer = _this$options.supportPointer,
supportTouch = _this$options.supportTouch;
this._bindEventListener();
if (supportPointer) {
on(el, 'pointerdown', this._onDrag);
} else if (supportTouch) {
on(el, 'touchstart', this._onDrag);
} else {
on(el, 'mousedown', this._onDrag);
}
if (this.nativeDraggable) {
on(el, 'dragover', this);
on(el, 'dragenter', this);
}
sortables.push(el);
Object.assign(this, Animation(), AutoScroll());
}

@@ -931,2 +1081,3 @@

constructor: Sortable,
// -------------------------------- public methods ----------------------------------

@@ -937,8 +1088,16 @@ /**

destroy: function destroy() {
this._clearState();
this.el[expando] = null;
off(this.el, 'pointerdown', this._onDrag);
off(this.el, 'touchstart', this._onDrag);
off(this.el, 'mousedown', this._onDrag);
this._clearEvent(); // Remove draggable attributes
if (this.nativeDraggable) {
off(this.el, 'dragover', this);
off(this.el, 'dragenter', this);
}
this._clearState(); // Remove draggable attributes
Array.prototype.forEach.call(this.rootEl.querySelectorAll('[draggable]'), function (el) {
Array.prototype.forEach.call(this.el.querySelectorAll('[draggable]'), function (el) {
el.removeAttribute('draggable');

@@ -965,5 +1124,5 @@ });

evt) {
var _this2 = this;
var _this = this;
if (/mousedown|pointerdown/.test(evt.type) && evt.button !== 0 || this.options.disabled) return; // only left button and enabled
if (/mousedown|pointerdown/.test(evt.type) && evt.button !== 0 || this.options.disabled || !this.options.group.pull) return; // only left button and enabled

@@ -977,13 +1136,16 @@ var _getEvent = getEvent(evt),

if (!this.nativeDraggable && Safari && target && target.tagName.toUpperCase() === 'SELECT') return;
if (target === this.rootEl) return true;
if (this.options.stopPropagation) evt.stopPropagation();
var _this$options = this.options,
draggable = _this$options.draggable,
dragging = _this$options.dragging;
if (target === this.el) return true;
if (this.options.stopPropagation) evt.stopPropagation && evt.stopPropagation(); // prevent events from bubbling
var draggable = this.options.draggable;
if (typeof draggable === 'function') {
if (!draggable(e)) return true;
// Function type must return a HTMLElement if used to specifies the drag el
var value = draggable(e);
if (!value) return true;
if (isHTMLElement(value)) dragEl = value; // set drag element
} else if (typeof draggable === 'string') {
// String use as 'tag' or '.class' or '#id'
if (!matches(target, draggable)) return true;
} else if (draggable !== undefined) {
} else if (draggable) {
throw new Error("draggable expected \"function\" or \"string\" but received \"".concat(_typeof(draggable), "\""));

@@ -993,23 +1155,20 @@ } // Get the dragged element

if (dragging) {
if (typeof dragging === 'function') this.dragEl = dragging(e);else throw new Error("dragging expected \"function\" or \"string\" but received \"".concat(_typeof(dragging), "\""));
} else {
this.dragEl = getElement(this.rootEl, target, true);
} // No dragging is allowed when there is no dragging element
if (!dragEl) dragEl = getElement(this.el, target, true); // No dragging is allowed when there is no dragging element
if (!dragEl || dragEl.animated) return true; // solve the problem that the mobile cannot be dragged
if (!this.dragEl || this.dragEl.animated) return true; // solve the problem that the mobile cannot be dragged
if (touch) dragEl.style['touch-action'] = 'none'; // get the position of the dragged element in the list
if (touch) this.dragEl.style['touch-action'] = 'none'; // get the position of the dragged element in the list
var _getElement = getElement(this.rootEl, this.dragEl),
var _getElement = getElement(this.el, dragEl),
rect = _getElement.rect,
offset = _getElement.offset;
this.move = {
move = {
x: e.clientX,
y: e.clientY
};
this.differ.from = {
node: this.dragEl,
differ.from = {
sortable: this,
group: this.el,
node: dragEl,
rect: rect,

@@ -1022,5 +1181,8 @@ offset: offset

};
this.state.sortableDown = e; // sortable state down is active
// Solve the problem that `dragend` does not take effect when the `dragover` event is not triggered
state.sortableDown = e; // sortable state down is active
on(this.ownerDocument, 'dragover', _nearestSortable);
on(this.ownerDocument, 'mousemove', _nearestSortable);
on(this.ownerDocument, 'touchmove', _nearestSortable); // Solve the problem that `dragend` does not take effect when the `dragover` event is not triggered
on(this.ownerDocument, 'pointerup', this._onDrop);

@@ -1037,3 +1199,3 @@ on(this.ownerDocument, 'touchend', this._onDrop);

this.dragStartTimer = setTimeout(function () {
return _this2._onStart(e, touch);
return _this._onStart(e, touch);
}, delay);

@@ -1047,4 +1209,14 @@ } else {

e, touch) {
rootEl = this.el;
nextEl = dragEl.nextSibling;
activeGroup = this.options.group;
if (!this.nativeDraggable || touch) {
this._bindMoveEvents(touch);
if (this.options.supportPointer) {
on(this.ownerDocument, 'pointermove', this._onMove);
} else if (touch) {
on(this.ownerDocument, 'touchmove', this._onMove);
} else {
on(this.ownerDocument, 'mousemove', this._onMove);
}

@@ -1055,6 +1227,5 @@ on(this.ownerDocument, 'pointercancel', this._onDrop);

// allow HTML5 drag event
this.dragEl.draggable = true;
this._onDragStart = this._onDragStart.bind(this);
this._onDragOver = this._onDragOver.bind(this);
on(this.rootEl, 'dragstart', this._onDragStart);
dragEl.draggable = true;
on(dragEl, 'dragend', this);
on(this.el, 'dragstart', this._onDragStart);
} // clear selection

@@ -1075,32 +1246,78 @@

},
// -------------------------------- trigger ----------------------------------
_triggerEvent: function _triggerEvent(evt) {
if (activeGroup.name !== this.options.group.name) return;
rootEl = evt.rootEl;
if (this.nativeDraggable) {
on(this.el, 'dragend', this._onDrop);
this._onDragOver(evt);
} else {
this._onMove(evt);
}
},
// -------------------------------- drag event ----------------------------------
_onDragStart: function _onDragStart(evt) {
// elements can only be dragged after firefox sets setData
evt.dataTransfer.setData('te', evt.target.innerText);
on(this.rootEl, 'dragover', this._onDragOver);
on(this.rootEl, 'dragend', this._onDrop);
if (evt.dataTransfer) {
evt.dataTransfer.setData('draggableEffect', evt.target.innerText);
evt.dataTransfer.effectAllowed = 'move';
}
on(this.el, 'dragover', this._onDragOver);
on(this.el, 'dragend', this._onDrop);
},
_onDragOver: function _onDragOver(evt) {
if (!this.state.sortableDown) return;
var stopPropagation = this.options.stopPropagation;
stopPropagation && evt.stopPropagation && evt.stopPropagation(); // prevent events from bubbling
if (evt.dataTransfer) evt.dataTransfer.dropEffect = 'move';
if (!state.sortableDown || !dragEl) return;
evt.preventDefault !== void 0 && evt.cancelable && evt.preventDefault(); // prevent scrolling
this._preventEvent(evt);
var clientX = evt.clientX,
clientY = evt.clientY;
var distanceX = clientX - this.move.x;
var distanceY = clientY - this.move.y;
_checkPosition(evt); // truly started
if (clientX !== void 0 && Math.abs(distanceX) <= 0 && clientY !== void 0 && Math.abs(distanceY) <= 0) {
return;
} // truly started
this._onStarted(evt, evt); // onMove callback
this._onStarted(evt, evt);
if (evt.target === this.rootEl) return;
this._dispatchEvent('onMove', _objectSpread2(_objectSpread2({}, differ), {}, {
ghostEl: ghostEl,
event: evt,
originalEvent: evt
}));
this._onChange(this, evt.target, evt, evt);
if (this.options.group.put || differ.from.group === this.el) this._onChange(evt.target, evt, evt);
},
// -------------------------------- real started ----------------------------------
_onStarted: function _onStarted(e,
/** originalEvent */
evt) {
state.sortableMove = e; // sortable state move is active
if (!ghostEl) {
// onDrag callback
this._dispatchEvent('onDrag', {
dragEl: dragEl,
event: e,
originalEvent: evt
}); // Init in the move event to prevent conflict with the click event
var rect = differ.from.rect;
ghostEl = dragEl.cloneNode(true);
this.ghost.init(ghostEl, rect, !this.nativeDraggable);
Sortable.ghost = ghostEl; // add class for drag element
toggleClass(dragEl, this.options.chosenClass, true);
dragEl.style['will-change'] = 'transform';
if (this.nativeDraggable) {
this._unbindDropEvents();
on(document, 'drop', this);
}
if (Safari) css(document.body, 'user-select', 'none');
}
},
// -------------------------------- on move ----------------------------------

@@ -1110,8 +1327,9 @@ _onMove: function _onMove(

evt) {
var _this3 = this;
var _this2 = this;
if (!this.state.sortableDown) return;
if (!state.sortableDown || !dragEl) return;
var _getEvent2 = getEvent(evt),
e = _getEvent2.e,
var _getEvent2 = getEvent(evt);
_getEvent2.touch;
var e = _getEvent2.e,
target = _getEvent2.target;

@@ -1121,4 +1339,4 @@

clientY = e.clientY;
var distanceX = clientX - this.move.x;
var distanceY = clientY - this.move.y;
var distanceX = clientX - move.x;
var distanceY = clientY - move.y;

@@ -1129,7 +1347,4 @@ if (clientX !== void 0 && Math.abs(distanceX) <= 0 && clientY !== void 0 && Math.abs(distanceY) <= 0) {

var stopPropagation = this.options.stopPropagation;
stopPropagation && evt.stopPropagation && evt.stopPropagation(); // prevent events from bubbling
this._preventEvent(evt);
evt.preventDefault !== void 0 && evt.cancelable && evt.preventDefault(); // prevent scrolling
this._onStarted(e, evt);

@@ -1139,86 +1354,92 @@

var onMove = this.options.onMove;
if (onMove && typeof onMove === 'function') onMove(this.differ.from, this.ghost.$el, e, evt); // boundary value judgment
this._dispatchEvent('onMove', _objectSpread2(_objectSpread2({}, differ), {}, {
ghostEl: ghostEl,
event: e,
originalEvent: evt
})); // check if element will exchange
if (clientX < 0 || clientY < 0) return;
var _getRect = getRect(this.rootEl),
top = _getRect.top,
right = _getRect.right,
bottom = _getRect.bottom,
left = _getRect.left;
this._onChange(target, e, evt); // auto scroll
if (clientX < left || clientX > right || clientY < top || clientY > bottom) return; // check if element will exchange
this._onChange(this, target, e, evt); // auto scroll
clearTimeout(this.autoScrollTimer);
this.autoScrollTimer && clearTimeout(this.autoScrollTimer);
if (this.options.autoScroll) {
this.autoScrollTimer = setTimeout(function () {
return _this3._autoScroll(_this3);
return _this2._autoScroll(_this2, state);
}, 0);
}
},
_onStarted: function _onStarted(e,
/** originalEvent */
evt) {
this.state.sortableMove = e; // sortable state move is active
// -------------------------------- on change ----------------------------------
_onChange: debounce(function (target, e, evt) {
if (!lastChild(this.el)) {
this.el.appendChild(dragEl);
differ.to = {
sortable: this,
group: this.el,
node: dragEl,
rect: getRect(dragEl),
offset: getOffset(dragEl)
}; // onChange callback
if (!this.ghost.$el) {
// onDrag callback
var onDrag = this.options.onDrag;
if (onDrag && typeof onDrag === 'function') onDrag(this.dragEl, e, evt); // Init in the move event to prevent conflict with the click event
this._dispatchEvent('onChange', _objectSpread2(_objectSpread2({}, differ), {}, {
event: e,
originalEvent: evt
}));
} else {
var _getElement2 = getElement(rootEl, target),
el = _getElement2.el,
rect = _getElement2.rect,
offset = _getElement2.offset;
var rect = this.differ.from.rect;
var ghostEl = this.dragEl.cloneNode(true);
this.ghost.init(ghostEl, rect, !this.nativeDraggable); // add class for drag element
if (!el || !dragEl || el && el.animated) return;
if (el === dragEl) return;
dropEl = el;
differ.to = {
sortable: this,
group: this.el,
node: dropEl,
rect: rect,
offset: offset
};
var clientX = e.clientX,
clientY = e.clientY;
var left = rect.left,
right = rect.right,
top = rect.top,
bottom = rect.bottom; // swap when the elements before and after the drag are inconsistent
toggleClass(this.dragEl, this.options.chosenClass, true);
this.dragEl.style['will-change'] = 'transform';
if (Safari) css(document.body, 'user-select', 'none');
if (this.nativeDraggable) this._unbindDropEvents();
}
},
_onChange: debounce(function (_this, target, e, evt) {
var _getElement2 = getElement(_this.rootEl, target),
el = _getElement2.el,
rect = _getElement2.rect,
offset = _getElement2.offset;
if (clientX > left && clientX < right && clientY > top && clientY < bottom) {
if (rootEl !== this.el) {
if (nextEl) {
this.el.insertBefore(dragEl, nextEl);
} else {
this.el.appendChild(dragEl);
} // onChange callback
if (!el || el && el.animated) return;
_this.dropEl = el;
var clientX = e.clientX,
clientY = e.clientY;
var left = rect.left,
right = rect.right,
top = rect.top,
bottom = rect.bottom;
if (clientX > left && clientX < right && clientY > top && clientY < bottom) {
// swap when the elements before and after the drag are inconsistent
if (el !== _this.dragEl) {
_this.differ.to = {
node: _this.dropEl,
rect: rect,
offset: offset
};
this._dispatchEvent('onChange', _objectSpread2(_objectSpread2({}, differ), {}, {
event: e,
originalEvent: evt
}));
} else {
this._captureAnimationState(dragEl, dropEl); // onChange callback
_this.captureAnimationState();
var onChange = _this.options.onChange;
this._dispatchEvent('onChange', _objectSpread2(_objectSpread2({}, differ), {}, {
event: e,
originalEvent: evt
})); // the top value is compared first, and the left is compared if the top value is the same
var _offset = getOffset(_this.dragEl); // onChange callback
var _offset = getOffset(dragEl);
if (onChange && typeof onChange === 'function') onChange(_this.differ.from, _this.differ.to, e, evt); // the top value is compared first, and the left is compared if the top value is the same
if (_offset.top < offset.top || _offset.left < offset.left) {
this.el.insertBefore(dragEl, el.nextElementSibling);
} else {
this.el.insertBefore(dragEl, el);
}
if (_offset.top < offset.top || _offset.left < offset.left) {
_this.rootEl.insertBefore(_this.dragEl, el.nextElementSibling);
} else {
_this.rootEl.insertBefore(_this.dragEl, el);
this._rangeAnimate();
}
_this.animateRange();
}

@@ -1237,40 +1458,79 @@ }

this._preventEvent(evt);
this.dragStartTimer && clearTimeout(this.dragStartTimer);
var stopPropagation = this.options.stopPropagation;
stopPropagation && evt.stopPropagation();
evt.preventDefault && evt.preventDefault();
var _getEvent3 = getEvent(evt),
touch = _getEvent3.touch; // clear style and class
if (dragEl) {
if (this.nativeDraggable) off(dragEl, 'dragend', this);
var _getEvent3 = getEvent(evt),
touch = _getEvent3.touch; // clear style, attrs and class
toggleClass(this.dragEl, this.options.chosenClass, false);
if (this.nativeDraggable) this.dragEl.draggable = false;
if (touch) this.dragEl.style['touch-action'] = '';
this.dragEl.style['will-change'] = '';
if (this.state.sortableDown && this.state.sortableMove) {
// re-acquire the offset and rect values of the dragged element as the value after the drag is completed
this.differ.to.offset = getOffset(this.dragEl);
this.differ.to.rect = getRect(this.dragEl);
var _this$differ = this.differ,
from = _this$differ.from,
to = _this$differ.to; // compare whether the element is swapped by offset
toggleClass(dragEl, this.options.chosenClass, false);
if (this.nativeDraggable) dragEl.draggable = false;
if (touch) dragEl.style['touch-action'] = '';
dragEl.style['will-change'] = '';
var changed = from.offset.top !== to.offset.top || from.offset.left !== to.offset.left; // onDrop callback
if (state.sortableDown && state.sortableMove) {
// re-acquire the offset and rect values of the dragged element as the value after the drag is completed
differ.to.offset = getOffset(dragEl);
differ.to.rect = getRect(dragEl);
var changed = offsetChanged(differ.from.offset, differ.to.offset);
var onDrop = this.options.onDrop;
if (onDrop && typeof onDrop === 'function') onDrop(changed, evt);
this._dispatchEvent('onDrop', {
changed: changed,
event: evt,
originalEvent: evt
});
}
}
if (Safari) css(document.body, 'user-select', '');
this.ghost.destroy(this.differ.to.rect);
this.state = new State();
this.ghost.destroy(differ.to.rect);
this._clearState();
},
// -------------------------------- event ----------------------------------
_preventEvent: function _preventEvent(evt) {
if (this.options.stopPropagation) evt.stopPropagation && evt.stopPropagation(); // prevent events from bubbling
evt.preventDefault !== void 0 && evt.cancelable && evt.preventDefault();
},
_dispatchEvent: function _dispatchEvent(event, params) {
var callback = this.options[event];
if (typeof callback === 'function') callback(params);
},
// -------------------------------- clear ----------------------------------
_clearState: function _clearState() {
this.state = new State();
this.differ.destroy();
this.dragEl = null;
this.dropEl = null;
state = new State();
differ.destroy();
dragEl = dropEl = nextEl = ghostEl = activeGroup = null;
move = lastPosition = {
x: 0,
y: 0
};
},
_unbindDragEvents: function _unbindDragEvents() {
if (this.nativeDraggable) {
off(this.el, 'dragstart', this._onDragStart);
off(this.el, 'dragover', this._onDragOver);
off(this.el, 'dragend', this._onDrop);
off(document, 'drop', this);
}
},
_unbindMoveEvents: function _unbindMoveEvents() {
off(this.ownerDocument, 'pointermove', this._onMove);
off(this.ownerDocument, 'touchmove', this._onMove);
off(this.ownerDocument, 'mousemove', this._onMove);
off(this.ownerDocument, 'touchmove', _nearestSortable);
off(this.ownerDocument, 'mousemove', _nearestSortable);
off(this.ownerDocument, 'dragover', _nearestSortable);
},
_unbindDropEvents: function _unbindDropEvents() {
off(this.ownerDocument, 'pointerup', this._onDrop);
off(this.ownerDocument, 'pointercancel', this._onDrop);
off(this.ownerDocument, 'touchend', this._onDrop);
off(this.ownerDocument, 'touchcancel', this._onDrop);
off(this.ownerDocument, 'mouseup', this._onDrop);
}

@@ -1282,4 +1542,3 @@ };

debounce: debounce,
throttle: throttle,
getParentAutoScrollElement: getParentAutoScrollElement
throttle: throttle
};

@@ -1286,0 +1545,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 n(t,e){for(var o=0;o<e.length;o++){var n=e[o];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}function i(t,e,o){return e&&n(t.prototype,e),o&&n(t,o),Object.defineProperty(t,"prototype",{writable:!1}),t}function r(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 o=Object.prototype.toString.call(t).slice(8,-1);return"Map"===(o="Object"===o&&t.constructor?t.constructor.name:o)||"Set"===o?Array.from(t):"Arguments"===o||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(o)?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 o=0,n=new Array(e);o<e;o++)n[o]=t[o];return n}function t(t){if("undefined"!=typeof window&&window.navigator)return!!navigator.userAgent.match(t)}var e,l=t(/(?:Trident.*rv[ :]?11\.|msie|iemobile|Windows Phone)/i),h=t(/Edge/i),c=t(/safari/i)&&!t(/chrome/i)&&!t(/android/i),u=t(/iP(ad|od|hone)/i),f=t(/chrome/i)&&t(/android/i),d={capture:!1,passive:!1},p=/\s+/g,g=["-webkit-transition","-moz-transition","-ms-transition","-o-transition","transition"],m=["-webkit-transform","-moz-transform","-ms-transform","-o-transform","transform"],v=(e=!1,document.addEventListener("checkIfSupportPassive",null,{get passive(){return e=!0}}),e);function y(e,o){o?"none"===o?g.forEach(function(t){return P(e,t,"none")}):g.forEach(function(t){return P(e,t,"".concat(t.split("transition")[0],"transform ").concat(o))}):g.forEach(function(t){return P(e,t,"")})}function b(e,o){o?m.forEach(function(t){return P(e,t,"".concat(t.split("transform")[0]).concat(o))}):m.forEach(function(t){return P(e,t,"")})}function w(t){var e=t.touches&&t.touches[0]||t.pointerType&&"touch"===t.pointerType&&t,t=e||t;return{touch:e,e:t,target:e?document.elementFromPoint(t.clientX,t.clientY):t.target}}function E(t,e,o){window.addEventListener?t.addEventListener(e,o,!(!v&&l)&&d):window.attachEvent&&t.attachEvent("on"+e,o)}function D(t,e,o){window.removeEventListener?t.removeEventListener(e,o,!(!v&&l)&&d):window.detachEvent&&t.detachEvent("on"+e,o)}function _(t){for(var e={top:0,left:0,height:0,width:0},o=(e.height=t.offsetHeight,e.width=t.offsetWidth,e.top=t.offsetTop,e.left=t.offsetLeft,t.offsetParent);null!==o;)e.top+=o.offsetTop,e.left+=o.offsetLeft,o=o.offsetParent;return e}function S(t,e){if(!t||!t.getBoundingClientRect)return T();var o=t,n=!1;do{if(o.clientWidth<o.scrollWidth||o.clientHeight<o.scrollHeight){var i=P(o);if(o.clientWidth<o.scrollWidth&&("auto"==i.overflowX||"scroll"==i.overflowX)||o.clientHeight<o.scrollHeight&&("auto"==i.overflowY||"scroll"==i.overflowY)){if(!o.getBoundingClientRect||o===document.body)return T();if(n||e)return o;n=!0}}}while(o=o.parentNode);return T()}function T(){var t=document.scrollingElement;return!t||t.contains(document.body)?document:t}function x(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!==T()?(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 $(t,e,o){var n=r(Array.from(t.children)),t=n.indexOf(e);if(-1<t)return o?n[t]:{index:t,el:n[t],rect:x(n[t]),offset:_(n[t])};for(var i=0;i<n.length;i++)if(function(t,e){var o;if(t&&e)for(o=t.parentNode;o;){if(e===o)return 1;o=o.parentNode}return}(e,n[i]))return o?n[i]:{index:i,el:n[i],rect:x(n[i]),offset:_(n[i])};return o?null:{index:-1,el:null,rect:{},offset:{}}}function M(t,e,o){var n;t&&e&&(t.classList?t.classList[o?"add":"remove"](e):(n=(" "+t.className+" ").replace(p," ").replace(" "+e+" "," "),t.className=(n+(o?" "+e:"")).replace(p," ")))}function P(t,e,o){var n=t&&t.style;if(n){if(void 0===o)return document.defaultView&&document.defaultView.getComputedStyle?o=document.defaultView.getComputedStyle(t,""):t.currentStyle&&(o=t.currentStyle),void 0===e?o:o[e];n[e=e in n||-1!==e.indexOf("webkit")?e:"-webkit-"+e]=o+("string"==typeof o?"":"px")}}function A(o,n,i){var r=null;return function(){var t=this,e=arguments;r&&clearTimeout(r),i&&!r&&o.apply(t,e),r=setTimeout(function(){o.apply(t,e)},n)}}function O(o,n){var i=null;return function(){var t=this,e=arguments;i=i||setTimeout(function(){i=null,o.apply(t,e)},n)}}var k=i(function t(){o(this,t),this.sortableDown=void 0,this.sortableMove=void 0,this.animationEnd=void 0}),C=function(){function t(){o(this,t),this.from={node:null,rect:{},offset:{}},this.to={node:null,rect:{},offset:{}}}return i(t,[{key:"get",value:function(t){return this[t]}},{key:"set",value:function(t,e){this[t]=e}},{key:"destroy",value:function(){this.from={node:null,rect:{},offset:{}},this.to={node:null,rect:{},offset:{}}}}]),t}(),L=function(){function e(t){o(this,e),this.$el=null,this.distance={x:0,y:0},this.options=t.options,this.container=t.container}return i(e,[{key:"init",value:function(t,e){var o=!(2<arguments.length&&void 0!==arguments[2])||arguments[2],t=(this.$el=t,this.options),n=t.ghostClass,t=t.ghostStyle,t=void 0===t?{}:t;M(this.$el,n,!0),P(this.$el,"box-sizing","border-box"),P(this.$el,"margin",0),P(this.$el,"top",e.top),P(this.$el,"left",e.left),P(this.$el,"width",e.width),P(this.$el,"height",e.height),P(this.$el,"opacity","0.8"),P(this.$el,"position","fixed"),P(this.$el,"zIndex","100000"),P(this.$el,"pointerEvents","none"),this.setStyle(t),y(this.$el,"none"),b(this.$el,"translate3d(0px, 0px, 0px)"),o&&this.container.appendChild(this.$el),P(this.$el,"transform-origin",this.distance.x/parseInt(this.$el.style.width)*100+"% "+this.distance.y/parseInt(this.$el.style.height)*100+"%")}},{key:"setStyle",value:function(t){for(var e in t)P(this.$el,e,t[e])}},{key:"rect",value:function(){return x(this.$el)}},{key:"move",value:function(t,e){this.$el&&(y(this.$el,2<arguments.length&&void 0!==arguments[2]&&arguments[2]?"".concat(this.options.ghostAnimation,"ms"):"none"),b(this.$el,"translate3d(".concat(t,"px, ").concat(e,"px, 0)")))}},{key:"destroy",value:function(t){var e,o,n=this;this.$el&&(o=parseInt(this.$el.style.left),e=parseInt(this.$el.style.top),this.move(t.left-o,t.top-e,!0),(o=this.options.ghostAnimation)?setTimeout(function(){return n.clear()},o):this.clear())}},{key:"clear",value:function(){this.$el&&this.$el.remove(),this.distance={x:0,y:0},this.$el=null}}]),e}();function I(){var i=[];return{captureAnimationState:function(){var t=r(Array.from(this.rootEl.children)),e=(o=t,n=this.dragEl,e=this.dropEl,n=o.indexOf(n),o=o.indexOf(e),n<o?{start:n,end:o}:{start:o,end:n}),o=e.start,n=e.end;i.length=0,t.slice(o,n+1).forEach(function(t){i.push({target:t,rect:x(t)})})},animateRange:function(){var o=this;i.forEach(function(t){var e=t.target,t=t.rect;o.animate(e,t,o.options.animation)})},animate:function(t,e){var o=2<arguments.length&&void 0!==arguments[2]?arguments[2]:150,n=x(t),i=e.left-n.left,e=e.top-n.top;y(t,"none"),b(t,"translate3d(".concat(i,"px, ").concat(e,"px, 0)")),t.offsetLeft,y(t,"".concat(o,"ms")),b(t,"translate3d(0px, 0px, 0px)"),clearTimeout(t.animated),t.animated=setTimeout(function(){y(t,""),b(t,""),t.animated=null},o)}}}var W="undefined"!=typeof document&&!f&&!u&&"draggable"in document.createElement("div");function H(t,e){if(!t||!t.nodeType||1!==t.nodeType)throw"Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(t));this.rootEl=t,this.scrollEl=S(t,!0),this.options=e=Object.assign({},e),this.ownerDocument=t.ownerDocument;var o,n={autoScroll:!0,scrollStep:5,scrollThreshold:15,delay:0,delayOnTouchOnly:!1,disabled:!1,animation:150,ghostAnimation:0,ghostClass:"",ghostStyle:{},chosenClass:"",draggable:void 0,dragging:void 0,onDrag:void 0,onMove:void 0,onDrop:void 0,onChange:void 0,fallbackOnBody:!1,forceFallback:!1,stopPropagation:!1,supportPointer:"PointerEvent"in window&&!c,supportTouch:"ontouchstart"in window};for(o in n)o in this.options||(this.options[o]=n[o]);this.container=this.options.fallbackOnBody?document.body:this.rootEl,this.nativeDraggable=!this.options.forceFallback&&W,this.move={x:0,y:0},this.state=new k,this.differ=new C,this.ghost=new L(this),this.dragEl=null,this.dropEl=null,this.dragStartTimer=null,this.autoScrollTimer=null,Object.assign(this,{_bindEventListener:function(){this._onDrag=this._onDrag.bind(this),this._onMove=this._onMove.bind(this),this._onDrop=this._onDrop.bind(this);var t=this.options,e=t.supportPointer,t=t.supportTouch;E(this.rootEl,e?"pointerdown":t?"touchstart":"mousedown",this._onDrag)},_clearEvent:function(){D(this.rootEl,"pointerdown",this._onDrag),D(this.rootEl,"touchstart",this._onDrag),D(this.rootEl,"mousedown",this._onDrag)},_bindMoveEvents:function(t){this.options.supportPointer?E(this.ownerDocument,"pointermove",this._onMove):E(this.ownerDocument,t?"touchmove":"mousemove",this._onMove)},_unbindMoveEvents:function(){D(this.ownerDocument,"pointermove",this._onMove),D(this.ownerDocument,"touchmove",this._onMove),D(this.ownerDocument,"mousemove",this._onMove)},_unbindDropEvents:function(){D(this.ownerDocument,"pointerup",this._onDrop),D(this.ownerDocument,"pointercancel",this._onDrop),D(this.ownerDocument,"touchend",this._onDrop),D(this.ownerDocument,"touchcancel",this._onDrop),D(this.ownerDocument,"mouseup",this._onDrop)},_unbindDragEvents:function(){this.nativeDraggable&&(D(this.rootEl,"dragstart",this._onDragStart),D(this.rootEl,"dragover",this._onDragOver),D(this.rootEl,"dragend",this._onDrop))}},I(),(window.requestAnimationFrame||(window.requestAnimationFrame=function(t){return setTimeout(t,17)}),{_autoScroll:O(function(t){var e,o,n,i,r,s,a,l,h,c,u,f,d,p,g;t.state.sortableDown&&t.state.sortableMove&&(e=(o=t.state.sortableMove).clientX,o=o.clientY,void 0!==e&&void 0!==o&&t.scrollEl!==t.ownerDocument&&(n=(p=t.scrollEl).scrollTop,i=p.scrollLeft,r=p.scrollHeight,p=p.scrollWidth,s=(d=x(t.scrollEl)).top,u=d.right,a=d.bottom,f=d.left,l=d.height,d=d.width,h=(c=t.options).scrollStep,c=c.scrollThreshold,f=0<i&&f<=e&&e<=f+c,d=i+d<p&&e<=u&&u-c<=e,p=n+l<r&&o<=a&&a-c<=o,g={x:i,y:n},(u=0<n&&s<=o&&o<=s+c)?(g.x=f?i-h:d?i+h:i,g.y=n-h):p?(g.x=f?i-h:d?i+h:i,g.y=n+h):f?(g.x=i-h,g.y=n):d&&(g.x=i+h,g.y=n),(u||f||d||p)&&requestAnimationFrame(function(){t.scrollEl.scrollTo(g.x,g.y),t._autoScroll(t)})))},10)})),this._bindEventListener()}return(H.prototype={constructor:H,destroy:function(){this._clearState(),this._clearEvent(),Array.prototype.forEach.call(this.rootEl.querySelectorAll("[draggable]"),function(t){t.removeAttribute("draggable")})},set:function(t,e){this.options[t]=e},get:function(t){return this.options[t]},_onDrag:function(t){var e=this;if(!(/mousedown|pointerdown/.test(t.type)&&0!==t.button||this.options.disabled)){var o=w(t),n=o.touch,i=o.e,o=o.target;if(this.nativeDraggable||!c||!o||"SELECT"!==o.tagName.toUpperCase()){if(o===this.rootEl)return!0;this.options.stopPropagation&&t.stopPropagation();var t=this.options,r=t.draggable,t=t.dragging;if("function"==typeof r){if(!r(i))return!0}else if("string"==typeof r){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}}(o,r))return!0}else if(void 0!==r)throw new Error('draggable expected "function" or "string" but received "'.concat(s(r),'"'));if(t){if("function"!=typeof t)throw new Error('dragging expected "function" or "string" but received "'.concat(s(t),'"'));this.dragEl=t(i)}else this.dragEl=$(this.rootEl,o,!0);if(!this.dragEl||this.dragEl.animated)return!0;n&&(this.dragEl.style["touch-action"]="none");r=$(this.rootEl,this.dragEl),t=r.rect,o=r.offset,r=(this.move={x:i.clientX,y:i.clientY},this.differ.from={node:this.dragEl,rect:t,offset:o},this.ghost.distance={x:i.clientX-t.left,y:i.clientY-t.top},this.state.sortableDown=i,E(this.ownerDocument,"pointerup",this._onDrop),E(this.ownerDocument,"touchend",this._onDrop),E(this.ownerDocument,"mouseup",this._onDrop),this.options),o=r.delay,t=r.delayOnTouchOnly;!o||t&&!n||this.nativeDraggable&&(h||l)?this._onStart(i,n):(clearTimeout(this.dragStartTimer),this.dragStartTimer=setTimeout(function(){return e._onStart(i,n)},o))}}},_onStart:function(t,e){!this.nativeDraggable||e?(this._bindMoveEvents(e),E(this.ownerDocument,"pointercancel",this._onDrop),E(this.ownerDocument,"touchcancel",this._onDrop)):(this.dragEl.draggable=!0,this._onDragStart=this._onDragStart.bind(this),this._onDragOver=this._onDragOver.bind(this),E(this.rootEl,"dragstart",this._onDragStart));try{document.selection?setTimeout(function(){document.selection.empty()},0):window.getSelection().removeAllRanges()}catch(t){}},_onDragStart:function(t){t.dataTransfer.setData("te",t.target.innerText),E(this.rootEl,"dragover",this._onDragOver),E(this.rootEl,"dragend",this._onDrop)},_onDragOver:function(t){var e,o,n,i;this.state.sortableDown&&(this.options.stopPropagation&&t.stopPropagation&&t.stopPropagation(),void 0!==t.preventDefault&&t.cancelable&&t.preventDefault(),e=t.clientX,o=t.clientY,n=e-this.move.x,i=o-this.move.y,void 0!==e&&Math.abs(n)<=0&&void 0!==o&&Math.abs(i)<=0||(this._onStarted(t,t),t.target!==this.rootEl&&this._onChange(this,t.target,t,t)))},_onMove:function(t){var e,o,n,i,r,s,a,l,h=this;this.state.sortableDown&&(e=(o=w(t)).e,o=o.target,n=e.clientX,i=e.clientY,s=n-this.move.x,r=i-this.move.y,void 0!==n&&Math.abs(s)<=0&&void 0!==i&&Math.abs(r)<=0||(this.options.stopPropagation&&t.stopPropagation&&t.stopPropagation(),void 0!==t.preventDefault&&t.cancelable&&t.preventDefault(),this._onStarted(e,t),this.ghost.move(s,r),(s=this.options.onMove)&&"function"==typeof s&&s(this.differ.from,this.ghost.$el,e,t),n<0||i<0||(s=(r=x(this.rootEl)).top,a=r.right,l=r.bottom,n<r.left||a<n||i<s||l<i||(this._onChange(this,o,e,t),this.autoScrollTimer&&clearTimeout(this.autoScrollTimer),this.options.autoScroll&&(this.autoScrollTimer=setTimeout(function(){return h._autoScroll(h)},0))))))},_onStarted:function(t,e){var o;this.state.sortableMove=t,this.ghost.$el||((o=this.options.onDrag)&&"function"==typeof o&&o(this.dragEl,t,e),o=this.differ.from.rect,t=this.dragEl.cloneNode(!0),this.ghost.init(t,o,!this.nativeDraggable),M(this.dragEl,this.options.chosenClass,!0),this.dragEl.style["will-change"]="transform",c&&P(document.body,"user-select","none"),this.nativeDraggable&&this._unbindDropEvents())},_onChange:A(function(t,e,o,n){var i,r,s,a,l,h,e=$(t.rootEl,e),c=e.el,u=e.rect,e=e.offset;c&&!c.animated&&(t.dropEl=c,h=o.clientX,i=o.clientY,l=u.left,r=u.right,s=u.top,a=u.bottom,l<h&&h<r&&s<i&&i<a&&c!==t.dragEl&&(t.differ.to={node:t.dropEl,rect:u,offset:e},t.captureAnimationState(),l=t.options.onChange,h=_(t.dragEl),l&&"function"==typeof l&&l(t.differ.from,t.differ.to,o,n),h.top<e.top||h.left<e.left?t.rootEl.insertBefore(t.dragEl,c.nextElementSibling):t.rootEl.insertBefore(t.dragEl,c),t.animateRange()))},5),_onDrop:function(t){this._unbindDragEvents(),this._unbindMoveEvents(),this._unbindDropEvents(),this.dragStartTimer&&clearTimeout(this.dragStartTimer),this.options.stopPropagation&&t.stopPropagation(),t.preventDefault&&t.preventDefault();var e,o=w(t).touch;M(this.dragEl,this.options.chosenClass,!1),this.nativeDraggable&&(this.dragEl.draggable=!1),o&&(this.dragEl.style["touch-action"]=""),this.dragEl.style["will-change"]="",this.state.sortableDown&&this.state.sortableMove&&(this.differ.to.offset=_(this.dragEl),this.differ.to.rect=x(this.dragEl),e=(o=this.differ).from,o=o.to,e=e.offset.top!==o.offset.top||e.offset.left!==o.offset.left,(o=this.options.onDrop)&&"function"==typeof o&&o(e,t)),c&&P(document.body,"user-select",""),this.ghost.destroy(this.differ.to.rect),this.state=new k},_clearState:function(){this.state=new k,this.differ.destroy(),this.dragEl=null,this.dropEl=null}}).utils={getRect:x,getOffset:_,debounce:A,throttle:O,getParentAutoScrollElement:S},H});
!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 e(e,t){var n,o=Object.keys(e);return Object.getOwnPropertySymbols&&(n=Object.getOwnPropertySymbols(e),t&&(n=n.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),o.push.apply(o,n)),o}function h(o){for(var t=1;t<arguments.length;t++){var i=null!=arguments[t]?arguments[t]:{};t%2?e(Object(i),!0).forEach(function(t){var e,n;e=o,n=i[t=t],t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n}):Object.getOwnPropertyDescriptors?Object.defineProperties(o,Object.getOwnPropertyDescriptors(i)):e(Object(i)).forEach(function(t){Object.defineProperty(o,t,Object.getOwnPropertyDescriptor(i,t))})}return o}function a(t){return(a="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 n(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function o(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 i(t,e,n){return e&&o(t.prototype,e),n&&o(t,n),Object.defineProperty(t,"prototype",{writable:!1}),t}function W(t){return function(t){if(Array.isArray(t))return r(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 r(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)?r(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 r(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 s,l=t(/(?:Trident.*rv[ :]?11\.|msie|iemobile|Windows Phone)/i),X=t(/Edge/i),c=t(/safari/i)&&!t(/chrome/i)&&!t(/android/i),Y=t(/iP(ad|od|hone)/i),B=t(/chrome/i)&&t(/android/i),H={capture:!1,passive:!1},N=/\s+/g,u=["-webkit-transition","-moz-transition","-ms-transition","-o-transition","transition"],F=["-webkit-transform","-moz-transform","-ms-transform","-o-transform","transform"],R=(s=!1,document.addEventListener("checkIfSupportPassive",null,{get passive(){return s=!0}}),s);function f(e,n){n?"none"===n?u.forEach(function(t){return E(e,t,"none")}):u.forEach(function(t){return E(e,t,"".concat(t.split("transition")[0],"transform ").concat(n))}):u.forEach(function(t){return E(e,t,"")})}function d(e,n){n?F.forEach(function(t){return E(e,t,"".concat(t.split("transform")[0]).concat(n))}):F.forEach(function(t){return E(e,t,"")})}function p(t){var e=t.touches&&t.touches[0]||t.pointerType&&"touch"===t.pointerType&&t,t=e||t;return{touch:e,e:t,target:e?document.elementFromPoint(t.clientX,t.clientY):t.target}}function g(t,e,n){window.addEventListener?t.addEventListener(e,n,!(!R&&l)&&H):window.attachEvent&&t.attachEvent("on"+e,n)}function m(t,e,n){window.removeEventListener?t.removeEventListener(e,n,!(!R&&l)&&H):window.detachEvent&&t.detachEvent("on"+e,n)}function v(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 b(){var t=document.scrollingElement;return!t||t.contains(document.body)?document:t}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!==b()?(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 w(t,e,n){var o=W(Array.from(t.children)),t=o.indexOf(e);if(-1<t)return n?o[t]:{index:t,el:o[t],rect:y(o[t]),offset:v(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]))return n?o[i]:{index:i,el:o[i],rect:y(o[i]),offset:v(o[i])};return n?null:{index:-1,el:null,rect:{},offset:{}}}function D(t,e,n){var o;t&&e&&(t.classList?t.classList[n?"add":"remove"](e):(o=(" "+t.className+" ").replace(N," ").replace(" "+e+" "," "),t.className=(o+(n?" "+e:"")).replace(N," ")))}function q(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}}function E(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 z(n,o,i){var r=null;return function(){var t=this,e=arguments;r&&clearTimeout(r),i&&!r&&n.apply(t,e),r=setTimeout(function(){n.apply(t,e)},o)}}function V(n,o){var i=null;return function(){var t=this,e=arguments;i=i||setTimeout(function(){i=null,n.apply(t,e)},o)}}var _="Sortable"+Date.now(),U=i(function t(){n(this,t),this.sortableDown=void 0,this.sortableMove=void 0,this.animationEnd=void 0}),Z=function(){function t(){n(this,t),this.from={sortable:null,group:null,node:null,rect:{},offset:{}},this.to={sortable:null,group:null,node:null,rect:{},offset:{}}}return i(t,[{key:"destroy",value:function(){this.from={sortable:null,group:null,node:null,rect:{},offset:{}},this.to={sortable:null,group:null,node:null,rect:{},offset:{}}}}]),t}(),$=function(){function e(t){n(this,e),this.el=null,this.distance={x:0,y:0},this.options=t.options,this.container=t.container}return i(e,[{key:"init",value:function(t,e){var n=!(2<arguments.length&&void 0!==arguments[2])||arguments[2];this.el=t,n&&(n=(t=this.options).ghostClass,t=void 0===(t=t.ghostStyle)?{}:t,D(this.el,n,!0),E(this.el,"box-sizing","border-box"),E(this.el,"margin",0),E(this.el,"top",e.top),E(this.el,"left",e.left),E(this.el,"width",e.width),E(this.el,"height",e.height),E(this.el,"opacity","0.8"),E(this.el,"position","fixed"),E(this.el,"zIndex","100000"),E(this.el,"pointerEvents","none"),this.setStyle(t),f(this.el,"none"),d(this.el,"translate3d(0px, 0px, 0px)"),this.container.appendChild(this.el),E(this.el,"transform-origin",this.distance.x/parseInt(this.el.style.width)*100+"% "+this.distance.y/parseInt(this.el.style.height)*100+"%"),E(this.el,"transform","translateZ(0)"))}},{key:"setStyle",value:function(t){for(var e in t)E(this.el,e,t[e])}},{key:"rect",value:function(){return y(this.el)}},{key:"move",value:function(t,e){this.el&&(f(this.el,2<arguments.length&&void 0!==arguments[2]&&arguments[2]?"".concat(this.options.ghostAnimation,"ms"):"none"),d(this.el,"translate3d(".concat(t,"px, ").concat(e,"px, 0)")))}},{key:"clear",value:function(){this.distance={x:0,y:0},this.el&&this.el.remove(),this.el=null}},{key:"destroy",value:function(t){var e,n,o=this;this.el&&(n=parseInt(this.el.style.left),e=parseInt(this.el.style.top),this.move(t.left-n,t.top-e,!0),(n=this.options.ghostAnimation)?setTimeout(function(){return o.clear()},n):this.clear())}}]),e}();function G(){var i=[];return{_captureAnimationState:function(t,e){var n=W(Array.from(this.el.children)),e=(t=t,e=e,t=(o=n).indexOf(t),o=o.indexOf(e),t<o?{start:t,end:o}:{start:o,end:t}),o=e.start,t=e.end;i.length=0,n.slice(o,t+1).forEach(function(t){i.push({target:t,rect:y(t)})})},_rangeAnimate:function(){var n=this;i.forEach(function(t){var e=t.target,t=t.rect;n._animate(e,t,n.options.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;f(t,"none"),d(t,"translate3d(".concat(i,"px, ").concat(e,"px, 0)")),t.offsetWidth,f(t,"".concat(n,"ms")),d(t,"translate3d(0px, 0px, 0px)"),clearTimeout(t.animated),t.animated=setTimeout(function(){f(t,""),d(t,""),t.animated=null},n)}}}function S(t){if(K(t),x){var e=t=t.touches?t.touches[0]:t,n=e.clientX,e=e.clientY,o=J(n,e);if(o){var i,r={};for(i in t)r[i]=t[i];r.target=document.elementFromPoint(n,e),r.rootEl=o,r.preventDefault=void 0,r.stopPropagation=void 0,o[_]._triggerEvent(r)}}}function J(i,r){var s;return tt.some(function(t){var e,n,o=t[_].options.emptyInsertThreshold;if(o)return n=y(t),e=i>=n.left-o&&i<=n.right+o,n=r>=n.top-o&&r<=n.bottom+o,e&&n?s=t:void 0}),s}function K(t){var e=t.clientX,t=t.clientY,n=e-L.x,o=t-L.y;L.x=e,L.y=t,void 0!==e&&Math.abs(n)<1&&void 0!==t&&Math.abs(o)}var T,x,O,P,C,M,Q="undefined"!=typeof document&&!B&&!Y&&"draggable"in document.createElement("div"),tt=[],A={x:0,y:0},j=new U,k=new Z,L={x:0,y:0};function I(t,e){if(!t||!t.nodeType||1!==t.nodeType)throw"Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(t));(t[_]=this).el=t,this.scrollEl=function(t,e){if(!t||!t.getBoundingClientRect)return b();var n=t,o=!1;do{if(n.clientWidth<n.scrollWidth||n.clientHeight<n.scrollHeight){var i=E(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 b();if(o||e)return n;o=!0}}}while(n=n.parentNode);return b()}(t,!0),this.options=e=Object.assign({},e),this.ownerDocument=t.ownerDocument;var n,o,i={group:"",animation:150,draggable:void 0,onDrag:void 0,onMove:void 0,onDrop:void 0,onChange:void 0,autoScroll:!0,scrollStep:5,scrollThreshold:15,delay:0,delayOnTouchOnly:!1,disabled:!1,ghostAnimation:0,ghostClass:"",ghostStyle:{},chosenClass:"",fallbackOnBody:!1,forceFallback:!1,stopPropagation:!1,supportPointer:"PointerEvent"in window&&!c,supportTouch:"ontouchstart"in window,emptyInsertThreshold:5};for(n in i)n in this.options||(this.options[n]=i[n]);for(o in this.container=this.options.fallbackOnBody?document.body:t,this.nativeDraggable=!this.options.forceFallback&&Q,this.ghost=new $(this),this.dragStartTimer=null,this.autoScrollTimer=null,s={},(r=(e=e).group)&&"object"==a(r)||(r={name:r}),s.name=r.name,s.pull=r.pull,s.put=r.put,e.group=s,this)"_"===o.charAt(0)&&"function"==typeof this[o]&&(this[o]=this[o].bind(this));var r=this.options,e=r.supportPointer,s=r.supportTouch;g(t,e?"pointerdown":s?"touchstart":"mousedown",this._onDrag),this.nativeDraggable&&(g(t,"dragover",this),g(t,"dragenter",this)),tt.push(t),Object.assign(this,G(),(window.requestAnimationFrame||(window.requestAnimationFrame=function(t){return setTimeout(t,17)}),{_autoScroll:V(function(t,e){var n,o,i,r,s,a,l,c,h,u,f,d,p,g,m;t.scrollEl&&e.sortableDown&&e.sortableMove&&(n=(o=e.sortableMove).clientX,o=o.clientY,void 0!==n&&void 0!==o&&t.scrollEl!==t.ownerDocument&&(i=(g=t.scrollEl).scrollTop,r=g.scrollLeft,s=g.scrollHeight,g=g.scrollWidth,a=(p=y(t.scrollEl)).top,f=p.right,l=p.bottom,d=p.left,c=p.height,p=p.width,h=(u=t.options).scrollStep,u=u.scrollThreshold,d=0<r&&d<=n&&n<=d+u,p=r+p<g&&n<=f&&f-u<=n,g=i+c<s&&o<=l&&l-u<=o,m={x:r,y:i},(f=0<i&&a<=o&&o<=a+u)?(m.x=d?r-h:p?r+h:r,m.y=i-h):g?(m.x=d?r-h:p?r+h:r,m.y=i+h):d?(m.x=r-h,m.y=i):p&&(m.x=r+h,m.y=i),(f||d||p||g)&&requestAnimationFrame(function(){t.scrollEl.scrollTo(m.x,m.y),t._autoScroll(t,e)})))},10)}))}return(I.prototype={constructor:I,destroy:function(){this.el[_]=null,m(this.el,"pointerdown",this._onDrag),m(this.el,"touchstart",this._onDrag),m(this.el,"mousedown",this._onDrag),this.nativeDraggable&&(m(this.el,"dragover",this),m(this.el,"dragenter",this)),this._clearState(),Array.prototype.forEach.call(this.el.querySelectorAll("[draggable]"),function(t){t.removeAttribute("draggable")})},set:function(t,e){this.options[t]=e},get:function(t){return this.options[t]},_onDrag:function(t){var e=this;if(!(/mousedown|pointerdown/.test(t.type)&&0!==t.button||this.options.disabled)&&this.options.group.pull){var n=p(t),o=n.touch,i=n.e,n=n.target;if(this.nativeDraggable||!c||!n||"SELECT"!==n.tagName.toUpperCase()){if(n===this.el)return!0;this.options.stopPropagation&&t.stopPropagation&&t.stopPropagation();t=this.options.draggable;if("function"==typeof t){var r=t(i);if(!r)return!0;!function(e){var t=document.createElement("div");try{return t.appendChild(e.cloneNode(!0)),1==e.nodeType}catch(t){return e==window||e==document}}(r)||(x=r)}else if("string"==typeof t){if(!q(n,t))return!0}else if(t)throw new Error('draggable expected "function" or "string" but received "'.concat(a(t),'"'));if(!(x=x||w(this.el,n,!0))||x.animated)return!0;o&&(x.style["touch-action"]="none");r=w(this.el,x),t=r.rect,n=r.offset,r=(A={x:i.clientX,y:i.clientY},k.from={sortable:this,group:this.el,node:x,rect:t,offset:n},this.ghost.distance={x:i.clientX-t.left,y:i.clientY-t.top},j.sortableDown=i,g(this.ownerDocument,"dragover",S),g(this.ownerDocument,"mousemove",S),g(this.ownerDocument,"touchmove",S),g(this.ownerDocument,"pointerup",this._onDrop),g(this.ownerDocument,"touchend",this._onDrop),g(this.ownerDocument,"mouseup",this._onDrop),this.options),n=r.delay,t=r.delayOnTouchOnly;!n||t&&!o||this.nativeDraggable&&(X||l)?this._onStart(i,o):(clearTimeout(this.dragStartTimer),this.dragStartTimer=setTimeout(function(){return e._onStart(i,o)},n))}}},_onStart:function(t,e){T=this.el,P=x.nextSibling,M=this.options.group,!this.nativeDraggable||e?(this.options.supportPointer?g(this.ownerDocument,"pointermove",this._onMove):g(this.ownerDocument,e?"touchmove":"mousemove",this._onMove),g(this.ownerDocument,"pointercancel",this._onDrop),g(this.ownerDocument,"touchcancel",this._onDrop)):(x.draggable=!0,g(x,"dragend",this),g(this.el,"dragstart",this._onDragStart));try{document.selection?setTimeout(function(){document.selection.empty()},0):window.getSelection().removeAllRanges()}catch(t){}},_triggerEvent:function(t){M.name===this.options.group.name&&(T=t.rootEl,this.nativeDraggable?(g(this.el,"dragend",this._onDrop),this._onDragOver(t)):this._onMove(t))},_onDragStart:function(t){t.dataTransfer&&(t.dataTransfer.setData("draggableEffect",t.target.innerText),t.dataTransfer.effectAllowed="move"),g(this.el,"dragover",this._onDragOver),g(this.el,"dragend",this._onDrop)},_onDragOver:function(t){t.dataTransfer&&(t.dataTransfer.dropEffect="move"),j.sortableDown&&x&&(this._preventEvent(t),K(t),this._onStarted(t,t),this._dispatchEvent("onMove",h(h({},k),{},{ghostEl:C,event:t,originalEvent:t})),!this.options.group.put&&k.from.group!==this.el||this._onChange(t.target,t,t))},_onStarted:function(t,e){j.sortableMove=t,C||(this._dispatchEvent("onDrag",{dragEl:x,event:t,originalEvent:e}),t=k.from.rect,C=x.cloneNode(!0),this.ghost.init(C,t,!this.nativeDraggable),I.ghost=C,D(x,this.options.chosenClass,!0),x.style["will-change"]="transform",this.nativeDraggable&&(this._unbindDropEvents(),g(document,"drop",this)),c&&E(document.body,"user-select","none"))},_onMove:function(t){var e,n,o,i,r,s,a=this;j.sortableDown&&x&&((n=p(t)).touch,e=n.e,n=n.target,o=e.clientX,i=e.clientY,r=o-A.x,s=i-A.y,void 0!==o&&Math.abs(r)<=0&&void 0!==i&&Math.abs(s)<=0||(this._preventEvent(t),this._onStarted(e,t),this.ghost.move(r,s),this._dispatchEvent("onMove",h(h({},k),{},{ghostEl:C,event:e,originalEvent:t})),this._onChange(n,e,t),clearTimeout(this.autoScrollTimer),this.options.autoScroll&&(this.autoScrollTimer=setTimeout(function(){return a._autoScroll(a,j)},0))))},_onChange:z(function(t,e,n){var o,i,r,s,a,l,c;!function(t,e){for(var n=t.lastElementChild;n&&(n===I.ghost||"none"===E(n,"display")||e&&!q(n,e));)n=n.previousElementSibling;return n}(this.el)?(this.el.appendChild(x),k.to={sortable:this,group:this.el,node:x,rect:y(x),offset:v(x)},this._dispatchEvent("onChange",h(h({},k),{},{event:e,originalEvent:n}))):(o=(t=w(T,t)).el,l=t.rect,t=t.offset,!o||!x||o&&o.animated||o!==x&&(O=o,k.to={sortable:this,group:this.el,node:O,rect:l,offset:t},i=e.clientX,r=e.clientY,c=l.left,s=l.right,a=l.top,l=l.bottom,c<i&&i<s&&a<r&&r<l&&(T!==this.el?(P?this.el.insertBefore(x,P):this.el.appendChild(x),this._dispatchEvent("onChange",h(h({},k),{},{event:e,originalEvent:n}))):(this._captureAnimationState(x,O),this._dispatchEvent("onChange",h(h({},k),{},{event:e,originalEvent:n})),(c=v(x)).top<t.top||c.left<t.left?this.el.insertBefore(x,o.nextElementSibling):this.el.insertBefore(x,o),this._rangeAnimate()))))},5),_onDrop:function(t){var e,n;this._unbindDragEvents(),this._unbindMoveEvents(),this._unbindDropEvents(),this._preventEvent(t),this.dragStartTimer&&clearTimeout(this.dragStartTimer),x&&(this.nativeDraggable&&m(x,"dragend",this),e=p(t).touch,D(x,this.options.chosenClass,!1),this.nativeDraggable&&(x.draggable=!1),e&&(x.style["touch-action"]=""),x.style["will-change"]="",j.sortableDown&&j.sortableMove&&(k.to.offset=v(x),k.to.rect=y(x),e=k.from.offset,n=k.to.offset,e=e.top!==n.top||e.left!==n.left,this._dispatchEvent("onDrop",{changed:e,event:t,originalEvent:t}))),c&&E(document.body,"user-select",""),this.ghost.destroy(k.to.rect),this._clearState()},_preventEvent:function(t){this.options.stopPropagation&&t.stopPropagation&&t.stopPropagation(),void 0!==t.preventDefault&&t.cancelable&&t.preventDefault()},_dispatchEvent:function(t,e){t=this.options[t];"function"==typeof t&&t(e)},_clearState:function(){j=new U,k.destroy(),x=O=P=C=M=null,A=L={x:0,y:0}},_unbindDragEvents:function(){this.nativeDraggable&&(m(this.el,"dragstart",this._onDragStart),m(this.el,"dragover",this._onDragOver),m(this.el,"dragend",this._onDrop),m(document,"drop",this))},_unbindMoveEvents:function(){m(this.ownerDocument,"pointermove",this._onMove),m(this.ownerDocument,"touchmove",this._onMove),m(this.ownerDocument,"mousemove",this._onMove),m(this.ownerDocument,"touchmove",S),m(this.ownerDocument,"mousemove",S),m(this.ownerDocument,"dragover",S)},_unbindDropEvents:function(){m(this.ownerDocument,"pointerup",this._onDrop),m(this.ownerDocument,"pointercancel",this._onDrop),m(this.ownerDocument,"touchend",this._onDrop),m(this.ownerDocument,"touchcancel",this._onDrop),m(this.ownerDocument,"mouseup",this._onDrop)}}).utils={getRect:y,getOffset:v,debounce:z,throttle:V},I});
{
"name": "sortable-dnd",
"version": "0.2.7",
"description": "JS Library for Drag and Drop, supports Sortable and Draggable",
"main": "dist/sortable.js",
"version": "0.3.0",
"description": "JS library for drag-and-drop lists, supports sortable and draggable",
"main": "dist/sortable.min.js",
"files": [

@@ -29,3 +29,3 @@ "src",

"author": "mfuu",
"license": "ISC",
"license": "MIT",
"bugs": {

@@ -32,0 +32,0 @@ "url": "https://github.com/mfuu/sortable-dnd/issues"

@@ -48,13 +48,13 @@ <p>

// draggable: '#drag' // use id
// dragging: (e) => e.target.parentNode // set dragging HTMLElement
onDrag: (dragEl, event, originalEvent) => {
// draggable: (e) => e.target.parentNode // use fundtion to set drag Element
onDrag: ({ dragEl, event, originalEvent }) => {
// code
},
onMove: (from, ghostEl, event, originalEvent) => {
onMove: ({ from, ghostEl, event, originalEvent }) => {
// code
},
onDrop: (changed, /* originalEvent */event) => {
onDrop: ({ changed, event, originalEvent }) => {
// code
},
onChange: (from, to, event, originalEvent) => {
onChange: ({ from, to, event, originalEvent }) => {
// code

@@ -79,4 +79,4 @@ }

|-------------------|-------------------|-------------|--------------|
| `animation` | `Number` | `150` | Animation speed moving items when sorting |
| `draggable` | `String/Function` | `undefined` | Specifies which items inside the element should be draggable, the function type must return a boolean |
| `draggable` | `String/Function` | `undefined` | Specifies which items inside the element should be draggable |
| `group` | `String/Object` | `-` | string: 'name' or object: `{ name: 'group', put: true/false, pull: true/false }` |
| `onDrag` | `Function` | `undefined` | The callback function when the drag is started |

@@ -86,5 +86,4 @@ | `onMove` | `Function` | `undefined` | The callback function when the dragged element is moving |

| `onChange` | `Function` | `undefined` | The callback function when the dragged element changes position |
| `autoScroll` | `Boolean` | `true` | Automatic scrolling when moving to the edge of the container, **for browsers that do not support HTML5 drag events** |
| `scrollStep` | `Number` | `5` | The distance to scroll each frame when autoscrolling |
| `scrollThreshold` | `Number` | `15` | Threshold to trigger autoscroll |
| `animation` | `Number` | `150` | Animation speed moving items when sorting |
| `disabled` | `Boolean` | `false` | Disables the sortable if set to true |

@@ -96,12 +95,15 @@

|-------------------|-------------------|-------------|--------------|
| `disabled` | `Boolean` | `false` | Disables the sortable if set to true |
| `dragging` | `Function` | `undefined` | Specifies the element witch you want to drag |
| `autoScroll` | `Boolean` | `true` | Automatic scrolling when moving to the edge of the container, **for browsers that do not support HTML5 drag events** |
| `scrollStep` | `Number` | `5` | The distance to scroll each frame when autoscrolling |
| `scrollThreshold` | `Number` | `15` | Threshold to trigger autoscroll |
| `delay` | `Number` | `0` | time in milliseconds to define when the sorting should start |
| `delayOnTouchOnly`| `Boolean` | `false` | only delay if user is using touch |
| `ghostAnimation` | `Number` | `0` | Ghost element animation delay before destroyed |
| `chosenClass` | `String` | `{}` | The class of the selected element when dragging |
| `ghostStyle` | `Object` | `{}` | The style of the mask element when dragging |
| `ghostClass` | `String` | `''` | The class of the mask element when dragging |
| `chosenClass` | `String` | `{}` | The class of the selected element when dragging |
| `forceFallback` | `Boolean` | `false` | true: ignore the HTML5 DnD behaviour and force the fallback to kick in |
| `stopPropagation` | `Boolean` | `false` | The `stopPropagation()` method of the Event interface prevents further propagation of the current event in the capturing and bubbling phases |
# LICENSE
[MIT](https://github.com/mfuu/sortable-dnd/blob/main/LICENSE)

@@ -15,5 +15,5 @@ import { getRect, setTransition, setTransform } from './utils.js'

captureAnimationState() {
const children = [...Array.from(this.rootEl.children)]
const { start, end } = getRange(children, this.dragEl, this.dropEl)
_captureAnimationState(dragEl, dropEl) {
const children = [...Array.from(this.el.children)]
const { start, end } = getRange(children, dragEl, dropEl)

@@ -30,10 +30,10 @@ animationState.length = 0 // reset

animateRange() {
_rangeAnimate() {
animationState.forEach(state => {
const { target, rect } = state
this.animate(target, rect, this.options.animation)
this._animate(target, rect, this.options.animation)
})
},
animate(el, preRect, animation = 150) {
_animate(el, preRect, animation = 150) {
const curRect = getRect(el)

@@ -46,3 +46,3 @@ const left = preRect.left - curRect.left

el.offsetLeft // trigger repaint
el.offsetWidth // trigger repaint

@@ -49,0 +49,0 @@ setTransition(el, `${animation}ms`)

@@ -10,14 +10,15 @@ import { throttle, getRect } from './utils.js'

return {
_autoScroll: throttle(function(_this) {
_autoScroll: throttle(function(Sortable, state) {
if (!Sortable.scrollEl) return
// check if is moving now
if (!(_this.state.sortableDown && _this.state.sortableMove)) return
const { clientX, clientY } = _this.state.sortableMove
if (!(state.sortableDown && state.sortableMove)) return
const { clientX, clientY } = state.sortableMove
if (clientX === void 0 || clientY === void 0) return
if (_this.scrollEl === _this.ownerDocument) {
if (Sortable.scrollEl === Sortable.ownerDocument) {
// does not support now
} else {
const { scrollTop, scrollLeft, scrollHeight, scrollWidth } = _this.scrollEl
const { top, right, bottom, left, height, width } = getRect(_this.scrollEl)
const { scrollStep, scrollThreshold } = _this.options
const { scrollTop, scrollLeft, scrollHeight, scrollWidth } = Sortable.scrollEl
const { top, right, bottom, left, height, width } = getRect(Sortable.scrollEl)
const { scrollStep, scrollThreshold } = Sortable.options
// check direction

@@ -67,4 +68,4 @@ const totop = scrollTop > 0 && clientY >= top && clientY <= (top + scrollThreshold)

requestAnimationFrame(() => {
_this.scrollEl.scrollTo(position.x, position.y)
_this._autoScroll(_this)
Sortable.scrollEl.scrollTo(position.x, position.y)
Sortable._autoScroll(Sortable, state)
})

@@ -71,0 +72,0 @@ }

import { css, getRect, toggleClass, setTransition, setTransform } from './utils.js'
import { IOS } from './Brower.js'
/**
* Sortable states
*/
export class State {

@@ -13,18 +15,12 @@ constructor() {

/**
* 拖拽前后差异初始化
* Difference before and after dragging
*/
export class Differ {
constructor() {
this.from = { node: null, rect: {}, offset: {} }
this.to = { node: null, rect: {}, offset: {} }
this.from = { sortable: null, group: null, node: null, rect: {}, offset: {} }
this.to = { sortable: null, group: null, node: null, rect: {}, offset: {} }
}
get(key) {
return this[key]
}
set(key, value) {
this[key] = value
}
destroy() {
this.from = { node: null, rect: {}, offset: {} }
this.to = { node: null, rect: {}, offset: {} }
this.from = { sortable: null, group: null, node: null, rect: {}, offset: {} }
this.to = { sortable: null, group: null, node: null, rect: {}, offset: {} }
}

@@ -34,7 +30,7 @@ }

/**
* 拖拽中的元素
* Elements being dragged
*/
export class Ghost {
constructor(sortable) {
this.$el = null
this.el = null
this.distance = { x: 0, y: 0 }

@@ -46,27 +42,29 @@ this.options = sortable.options

init(el, rect, append = true) {
this.$el = el
this.el = el
if (!append) return
const { ghostClass, ghostStyle = {} } = this.options
toggleClass(this.$el, ghostClass, true)
toggleClass(this.el, ghostClass, true)
css(this.$el, 'box-sizing', 'border-box')
css(this.$el, 'margin', 0)
css(this.$el, 'top', rect.top)
css(this.$el, 'left', rect.left)
css(this.$el, 'width', rect.width)
css(this.$el, 'height', rect.height)
css(this.$el, 'opacity', '0.8')
// css(this.$el, 'position', IOS ? 'absolute' : 'fixed')
css(this.$el, 'position', 'fixed')
css(this.$el, 'zIndex', '100000')
css(this.$el, 'pointerEvents', 'none')
css(this.el, 'box-sizing', 'border-box')
css(this.el, 'margin', 0)
css(this.el, 'top', rect.top)
css(this.el, 'left', rect.left)
css(this.el, 'width', rect.width)
css(this.el, 'height', rect.height)
css(this.el, 'opacity', '0.8')
// css(this.el, 'position', IOS ? 'absolute' : 'fixed')
css(this.el, 'position', 'fixed')
css(this.el, 'zIndex', '100000')
css(this.el, 'pointerEvents', 'none')
this.setStyle(ghostStyle)
setTransition(this.$el, 'none')
setTransform(this.$el, 'translate3d(0px, 0px, 0px)')
setTransition(this.el, 'none')
setTransform(this.el, 'translate3d(0px, 0px, 0px)')
if (append) this.container.appendChild(this.$el)
this.container.appendChild(this.el)
css(this.$el, 'transform-origin', (this.distance.x / parseInt(this.$el.style.width) * 100) + '% ' + (this.distance.y / parseInt(this.$el.style.height) * 100) + '%')
css(this.el, 'transform-origin', (this.distance.x / parseInt(this.el.style.width) * 100) + '% ' + (this.distance.y / parseInt(this.el.style.height) * 100) + '%')
css(this.el, 'transform', 'translateZ(0)')
}

@@ -76,3 +74,3 @@

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

@@ -82,15 +80,21 @@ }

rect() {
return getRect(this.$el)
return getRect(this.el)
}
move(x, y, smooth = false) {
if (!this.$el) return
setTransition(this.$el, smooth ? `${this.options.ghostAnimation}ms` : 'none')
setTransform(this.$el, `translate3d(${x}px, ${y}px, 0)`)
if (!this.el) return
setTransition(this.el, smooth ? `${this.options.ghostAnimation}ms` : 'none')
setTransform(this.el, `translate3d(${x}px, ${y}px, 0)`)
}
clear() {
this.distance = { x: 0, y: 0 }
this.el && this.el.remove()
this.el = null
}
destroy(rect) {
if (!this.$el) return
const left = parseInt(this.$el.style.left)
const top = parseInt(this.$el.style.top)
if (!this.el) return
const left = parseInt(this.el.style.left)
const top = parseInt(this.el.style.top)
this.move(rect.left - left, rect.top - top, true)

@@ -100,8 +104,2 @@ const { ghostAnimation } = this.options

}
clear() {
this.$el && this.$el.remove()
this.distance = { x: 0, y: 0 }
this.$el = null
}
}

@@ -5,2 +5,3 @@ import {

css,
expando,
matches,

@@ -11,2 +12,3 @@ getRect,

debounce,
lastChild,
getOffset,

@@ -16,2 +18,4 @@ _nextTick,

toggleClass,
isHTMLElement,
offsetChanged,
getParentAutoScrollElement

@@ -23,3 +27,2 @@ } from './utils.js'

import Animation from './Animation.js'
import Events from './Events.js'

@@ -30,3 +33,92 @@ // -------------------------------- Sortable ----------------------------------

const sortables = []
let rootEl,
dragEl,
dropEl,
nextEl,
ghostEl,
activeGroup,
move = { x: 0, y: 0 },
state = new State, // Status record during drag and drop
differ = new Differ() // Record the difference before and after dragging
const _prepareGroup = function (options) {
let group = {}
let originalGroup = options.group
if (!originalGroup || typeof originalGroup != 'object') {
originalGroup = { name: originalGroup }
}
group.name = originalGroup.name
group.pull = originalGroup.pull
group.put = originalGroup.put
options.group = group
}
/**
* get nearest Sortable
*/
const _nearestSortable = function(evt) {
_checkPosition(evt)
if (dragEl) {
evt = evt.touches ? evt.touches[0] : evt
const { clientX, clientY } = evt
const nearest = _detectNearestSortable(clientX, clientY)
if (nearest) {
// Create imitation event
let event = {}
for (let i in evt) {
event[i] = evt[i]
}
event.target = document.elementFromPoint(clientX, clientY)
event.rootEl = nearest
event.preventDefault = void 0
event.stopPropagation = void 0
nearest[expando]._triggerEvent(event)
}
}
}
/**
* Detects first nearest empty sortable to X and Y position using emptyInsertThreshold.
* @param {Number} x X position
* @param {Number} y Y position
* @return {HTMLElement} Element of the first found nearest Sortable
*/
const _detectNearestSortable = function(x, y) {
let result
sortables.some((sortable) => {
const threshold = sortable[expando].options.emptyInsertThreshold
if (!threshold) return
const rect = getRect(sortable),
insideHorizontally = x >= (rect.left - threshold) && x <= (rect.right + threshold),
insideVertically = y >= (rect.top - threshold) && y <= (rect.bottom + threshold)
if (insideHorizontally && insideVertically) {
return (result = sortable)
}
})
return result
}
let lastPosition = { x: 0, y: 0 }
const _checkPosition = function(evt) {
const { clientX, clientY } = evt
const distanceX = clientX - lastPosition.x
const distanceY = clientY - lastPosition.y
lastPosition.x = clientX
lastPosition.y = clientY
if ((clientX !== void 0 && Math.abs(distanceX) < 1) && (clientY !== void 0 && Math.abs(distanceY) < 1)) {
return
}
}
/**
* @class Sortable

@@ -41,3 +133,5 @@ * @param {HTMLElement} el group element

this.rootEl = el // root element
el[expando] = this
this.el = el
this.scrollEl = getParentAutoScrollElement(el, true) // scroll element

@@ -48,2 +142,11 @@ this.options = options = Object.assign({}, options)

const defaults = {
group: '', // string: 'group' or object: { name: 'group', put: true | false, pull: true | false }
animation: 150, // Define the timing of the sorting animation
draggable: undefined, // String: css selector, Function: (e) => return true
onDrag: undefined, // The callback function triggered when dragging starts: () => {}
onMove: undefined, // The callback function during drag and drop: (from, to) => {}
onDrop: undefined, // The callback function when the drag is completed: (from, to, changed) => {}
onChange: undefined, // The callback function when dragging an element to change its position: (from, to) => {}
autoScroll: true, // Auto scrolling when dragging to the edge of the container

@@ -56,3 +159,2 @@ scrollStep: 5, // The distance to scroll each frame

disabled: false, // Defines whether the sortable object is available or not. When it is true, the sortable object cannot drag and drop sorting and other functions. When it is false, it can be sorted, which is equivalent to a switch.
animation: 150, // Define the timing of the sorting animation

@@ -63,9 +165,2 @@ ghostAnimation: 0, // Animation when the ghost element is destroyed

chosenClass: '', // Chosen element style
draggable: undefined, // String: css selector, Function: (e) => return true
dragging: undefined, // Set the drag element, must be a function and must return an HTMLElement: (e) => return e.target
onDrag: undefined, // The callback function triggered when dragging starts: () => {}
onMove: undefined, // The callback function during drag and drop: (from, to) => {}
onDrop: undefined, // The callback function when the drag is completed: (from, to, changed) => {}
onChange: undefined, // The callback function when dragging an element to change its position: (from, to) => {}

@@ -78,2 +173,3 @@ fallbackOnBody: false,

supportTouch: 'ontouchstart' in window,
emptyInsertThreshold: 5
}

@@ -86,21 +182,35 @@

this.container = this.options.fallbackOnBody ? document.body : this.rootEl
this.container = this.options.fallbackOnBody ? document.body : el
this.nativeDraggable = this.options.forceFallback ? false : supportDraggable
this.move = { x: 0, y: 0 }
this.state = new State // Status record during drag and drop
this.differ = new Differ() // Record the difference before and after dragging
this.ghost = new Ghost(this) // Mask element while dragging
this.dragEl = null // Drag element
this.dropEl = null // Drop element
this.dragStartTimer = null // setTimeout timer
this.autoScrollTimer = null
Object.assign(
this,
Events(),
Animation(),
AutoScroll(),
)
this._bindEventListener()
_prepareGroup(options)
// Bind all private methods
for (let fn in this) {
if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {
this[fn] = this[fn].bind(this)
}
}
const { supportPointer, supportTouch } = this.options
if (supportPointer) {
on(el, 'pointerdown', this._onDrag)
} else if (supportTouch) {
on(el, 'touchstart', this._onDrag)
} else {
on(el, 'mousedown', this._onDrag)
}
if (this.nativeDraggable) {
on(el, 'dragover', this)
on(el, 'dragenter', this)
}
sortables.push(el)
Object.assign(this, Animation(), AutoScroll())
}

@@ -111,2 +221,3 @@

// -------------------------------- public methods ----------------------------------
/**

@@ -116,6 +227,16 @@ * Destroy

destroy: function() {
this.el[expando] = null
off(this.el, 'pointerdown', this._onDrag)
off(this.el, 'touchstart', this._onDrag)
off(this.el, 'mousedown', this._onDrag)
if (this.nativeDraggable) {
off(this.el, 'dragover', this)
off(this.el, 'dragenter', this)
}
this._clearState()
this._clearEvent()
// Remove draggable attributes
Array.prototype.forEach.call(this.rootEl.querySelectorAll('[draggable]'), function (el) {
Array.prototype.forEach.call(this.el.querySelectorAll('[draggable]'), function (el) {
el.removeAttribute('draggable')

@@ -141,3 +262,3 @@ })

_onDrag: function(/** Event|TouchEvent */evt) {
if (/mousedown|pointerdown/.test(evt.type) && evt.button !== 0 || this.options.disabled) return // only left button and enabled
if (/mousedown|pointerdown/.test(evt.type) && evt.button !== 0 || this.options.disabled || !this.options.group.pull) return // only left button and enabled

@@ -148,15 +269,16 @@ const { touch, e, target } = getEvent(evt)

if (!this.nativeDraggable && Safari && target && target.tagName.toUpperCase() === 'SELECT') return
if (target === this.rootEl) return true
if (target === this.el) return true
if (this.options.stopPropagation) evt.stopPropagation()
if (this.options.stopPropagation) evt.stopPropagation && evt.stopPropagation() // prevent events from bubbling
const { draggable, dragging } = this.options
const { draggable } = this.options
if (typeof draggable === 'function') {
if (!draggable(e)) return true
// Function type must return a HTMLElement if used to specifies the drag el
const value = draggable(e)
if (!value) return true
if (isHTMLElement(value)) dragEl = value // set drag element
} else if (typeof draggable === 'string') {
// String use as 'tag' or '.class' or '#id'
if (!matches(target, draggable)) return true
} else if (draggable !== undefined) {
} else if (draggable) {
throw new Error(`draggable expected "function" or "string" but received "${typeof draggable}"`)

@@ -166,22 +288,20 @@ }

// Get the dragged element
if (dragging) {
if (typeof dragging === 'function') this.dragEl = dragging(e)
else throw new Error(`dragging expected "function" or "string" but received "${typeof dragging}"`)
} else {
this.dragEl = getElement(this.rootEl, target, true)
}
if (!dragEl) dragEl = getElement(this.el, target, true)
// No dragging is allowed when there is no dragging element
if (!this.dragEl || this.dragEl.animated) return true
if (!dragEl || dragEl.animated) return true
// solve the problem that the mobile cannot be dragged
if (touch) this.dragEl.style['touch-action'] = 'none'
if (touch) dragEl.style['touch-action'] = 'none'
// get the position of the dragged element in the list
const { rect, offset } = getElement(this.rootEl, this.dragEl)
this.move = { x: e.clientX, y: e.clientY }
this.differ.from = { node: this.dragEl, rect, offset}
const { rect, offset } = getElement(this.el, dragEl)
move = { x: e.clientX, y: e.clientY }
differ.from = { sortable: this, group: this.el, node: dragEl, rect, offset}
this.ghost.distance = { x: e.clientX - rect.left, y: e.clientY - rect.top }
this.state.sortableDown = e // sortable state down is active
state.sortableDown = e // sortable state down is active
on(this.ownerDocument, 'dragover', _nearestSortable)
on(this.ownerDocument, 'mousemove', _nearestSortable)
on(this.ownerDocument, 'touchmove', _nearestSortable)
// Solve the problem that `dragend` does not take effect when the `dragover` event is not triggered

@@ -201,5 +321,18 @@ on(this.ownerDocument, 'pointerup', this._onDrop)

},
_onStart: function(/** Event|TouchEvent */e, touch) {
rootEl = this.el
nextEl = dragEl.nextSibling
activeGroup = this.options.group
if (!this.nativeDraggable || touch) {
this._bindMoveEvents(touch)
if (this.options.supportPointer) {
on(this.ownerDocument, 'pointermove', this._onMove)
} else if (touch) {
on(this.ownerDocument, 'touchmove', this._onMove)
} else {
on(this.ownerDocument, 'mousemove', this._onMove)
}
on(this.ownerDocument, 'pointercancel', this._onDrop)

@@ -209,7 +342,6 @@ on(this.ownerDocument, 'touchcancel', this._onDrop)

// allow HTML5 drag event
this.dragEl.draggable = true
dragEl.draggable = true
this._onDragStart = this._onDragStart.bind(this)
this._onDragOver = this._onDragOver.bind(this)
on(this.rootEl, 'dragstart', this._onDragStart)
on(dragEl, 'dragend', this)
on(this.el, 'dragstart', this._onDragStart)
}

@@ -230,38 +362,77 @@

// -------------------------------- trigger ----------------------------------
_triggerEvent(evt) {
if (activeGroup.name !== this.options.group.name) return
rootEl = evt.rootEl
if (this.nativeDraggable) {
on(this.el, 'dragend', this._onDrop)
this._onDragOver(evt)
} else {
this._onMove(evt)
}
},
// -------------------------------- drag event ----------------------------------
_onDragStart: function(evt) {
// elements can only be dragged after firefox sets setData
evt.dataTransfer.setData('te', evt.target.innerText)
if (evt.dataTransfer) {
evt.dataTransfer.setData('draggableEffect', evt.target.innerText)
evt.dataTransfer.effectAllowed = 'move'
}
on(this.rootEl, 'dragover', this._onDragOver)
on(this.rootEl, 'dragend', this._onDrop)
on(this.el, 'dragover', this._onDragOver)
on(this.el, 'dragend', this._onDrop)
},
_onDragOver: function(evt) {
if (!this.state.sortableDown) return
const { stopPropagation } = this.options
stopPropagation && evt.stopPropagation && evt.stopPropagation() // prevent events from bubbling
evt.preventDefault !== void 0 && evt.cancelable && evt.preventDefault() // prevent scrolling
if (evt.dataTransfer) evt.dataTransfer.dropEffect = 'move'
if (!state.sortableDown || !dragEl) return
this._preventEvent(evt)
_checkPosition(evt)
const { clientX, clientY } = evt
const distanceX = clientX - this.move.x
const distanceY = clientY - this.move.y
if ((clientX !== void 0 && Math.abs(distanceX) <= 0) && (clientY !== void 0 && Math.abs(distanceY) <= 0)) {
return
}
// truly started
this._onStarted(evt, evt)
if (evt.target === this.rootEl) return
this._onChange(this, evt.target, evt, evt)
// onMove callback
this._dispatchEvent('onMove', { ...differ, ghostEl, event: evt, originalEvent: evt })
if (this.options.group.put || differ.from.group === this.el) this._onChange(evt.target, evt, evt)
},
// -------------------------------- real started ----------------------------------
_onStarted: function(e, /** originalEvent */evt) {
state.sortableMove = e // sortable state move is active
if (!ghostEl) {
// onDrag callback
this._dispatchEvent('onDrag', { dragEl, event: e, originalEvent: evt })
// Init in the move event to prevent conflict with the click event
const { rect } = differ.from
ghostEl = dragEl.cloneNode(true)
this.ghost.init(ghostEl, rect, !this.nativeDraggable)
Sortable.ghost = ghostEl
// add class for drag element
toggleClass(dragEl, this.options.chosenClass, true)
dragEl.style['will-change'] = 'transform'
if (this.nativeDraggable) {
this._unbindDropEvents()
on(document, 'drop', this)
}
if (Safari) css(document.body, 'user-select', 'none')
}
},
// -------------------------------- on move ----------------------------------
_onMove: function(/** Event|TouchEvent */evt) {
if (!this.state.sortableDown) return
if (!state.sortableDown || !dragEl) return
const { touch, e, target } = getEvent(evt)
const { clientX, clientY } = e
const distanceX = clientX - this.move.x
const distanceY = clientY - this.move.y
const distanceX = clientX - move.x
const distanceY = clientY - move.y

@@ -272,5 +443,3 @@ if ((clientX !== void 0 && Math.abs(distanceX) <= 0) && (clientY !== void 0 && Math.abs(distanceY) <= 0)) {

const { stopPropagation } = this.options
stopPropagation && evt.stopPropagation && evt.stopPropagation() // prevent events from bubbling
evt.preventDefault !== void 0 && evt.cancelable && evt.preventDefault() // prevent scrolling
this._preventEvent(evt)

@@ -281,70 +450,63 @@ this._onStarted(e, evt)

// onMove callback
const { onMove } = this.options
if (onMove && typeof onMove === 'function') onMove(this.differ.from, this.ghost.$el, e, evt)
this._dispatchEvent('onMove', { ...differ, ghostEl, event: e, originalEvent: evt })
// boundary value judgment
if (clientX < 0 || clientY < 0) return
const { top, right, bottom, left } = getRect(this.rootEl)
if (clientX < left || clientX > right || clientY < top || clientY > bottom) return
// check if element will exchange
this._onChange(this, target, e, evt)
this._onChange(target, e, evt)
// auto scroll
this.autoScrollTimer && clearTimeout(this.autoScrollTimer)
clearTimeout(this.autoScrollTimer)
if (this.options.autoScroll) {
this.autoScrollTimer = setTimeout(() => this._autoScroll(this), 0)
this.autoScrollTimer = setTimeout(() => this._autoScroll(this, state), 0)
}
},
_onStarted: function(e, /** originalEvent */evt) {
this.state.sortableMove = e // sortable state move is active
if (!this.ghost.$el) {
// onDrag callback
const { onDrag } = this.options
if (onDrag && typeof onDrag === 'function') onDrag(this.dragEl, e, evt)
// Init in the move event to prevent conflict with the click event
const { rect } = this.differ.from
const ghostEl = this.dragEl.cloneNode(true)
this.ghost.init(ghostEl, rect, !this.nativeDraggable)
// -------------------------------- on change ----------------------------------
_onChange: debounce(function(target, e, evt) {
if (!lastChild(this.el)) {
this.el.appendChild(dragEl)
// add class for drag element
toggleClass(this.dragEl, this.options.chosenClass, true)
this.dragEl.style['will-change'] = 'transform'
differ.to = { sortable: this, group: this.el, node: dragEl, rect: getRect(dragEl), offset: getOffset(dragEl) }
// onChange callback
this._dispatchEvent('onChange', { ...differ, event: e, originalEvent: evt })
} else {
const { el, rect, offset } = getElement(rootEl, target)
if (!el || !dragEl || (el && el.animated)) return
if (el === dragEl) return
if (Safari) css(document.body, 'user-select', 'none')
if (this.nativeDraggable) this._unbindDropEvents()
}
},
_onChange: debounce(function(_this, target, e, evt) {
const { el, rect, offset } = getElement(_this.rootEl, target)
if (!el || (el && el.animated)) return
_this.dropEl = el
const { clientX, clientY } = e
const { left, right, top, bottom } = rect
dropEl = el
differ.to = { sortable: this, group: this.el, node: dropEl, rect, offset }
if (clientX > left && clientX < right && clientY > top && clientY < bottom) {
const { clientX, clientY } = e
const { left, right, top, bottom } = rect
// swap when the elements before and after the drag are inconsistent
if (el !== _this.dragEl) {
_this.differ.to = { node: _this.dropEl, rect, offset }
if (clientX > left && clientX < right && clientY > top && clientY < bottom) {
if (rootEl !== this.el) {
if (nextEl) {
this.el.insertBefore(dragEl, nextEl)
} else {
this.el.appendChild(dragEl)
}
_this.captureAnimationState()
// onChange callback
this._dispatchEvent('onChange', { ...differ, event: e, originalEvent: evt })
} else {
this._captureAnimationState(dragEl, dropEl)
const { onChange } = _this.options
const _offset = getOffset(_this.dragEl)
// onChange callback
this._dispatchEvent('onChange', { ...differ, event: e, originalEvent: evt })
// the top value is compared first, and the left is compared if the top value is the same
const _offset = getOffset(dragEl)
if (_offset.top < offset.top || _offset.left < offset.left) {
this.el.insertBefore(dragEl, el.nextElementSibling)
} else {
this.el.insertBefore(dragEl, el)
}
// onChange callback
if (onChange && typeof onChange === 'function') onChange(_this.differ.from, _this.differ.to, e, evt)
// the top value is compared first, and the left is compared if the top value is the same
if (_offset.top < offset.top || _offset.left < offset.left) {
_this.rootEl.insertBefore(_this.dragEl, el.nextElementSibling)
} else {
_this.rootEl.insertBefore(_this.dragEl, el)
this._rangeAnimate()
}
_this.animateRange()
}
}
}, 5),

@@ -357,38 +519,81 @@

this._unbindDropEvents()
this._preventEvent(evt)
this.dragStartTimer && clearTimeout(this.dragStartTimer)
const { stopPropagation } = this.options
stopPropagation && evt.stopPropagation()
evt.preventDefault && evt.preventDefault()
if (dragEl) {
if (this.nativeDraggable) off(dragEl, 'dragend', this)
const { touch } = getEvent(evt)
// clear style and class
toggleClass(this.dragEl, this.options.chosenClass, false)
if (this.nativeDraggable) this.dragEl.draggable = false
if (touch) this.dragEl.style['touch-action'] = ''
this.dragEl.style['will-change'] = ''
const { touch } = getEvent(evt)
// clear style, attrs and class
toggleClass(dragEl, this.options.chosenClass, false)
if (this.nativeDraggable) dragEl.draggable = false
if (touch) dragEl.style['touch-action'] = ''
dragEl.style['will-change'] = ''
if (this.state.sortableDown && this.state.sortableMove) {
// re-acquire the offset and rect values of the dragged element as the value after the drag is completed
this.differ.to.offset = getOffset(this.dragEl)
this.differ.to.rect = getRect(this.dragEl)
if (state.sortableDown && state.sortableMove) {
// re-acquire the offset and rect values of the dragged element as the value after the drag is completed
differ.to.offset = getOffset(dragEl)
differ.to.rect = getRect(dragEl)
const changed = offsetChanged(differ.from.offset, differ.to.offset)
this._dispatchEvent('onDrop', { changed, event: evt, originalEvent: evt })
}
}
const { from, to } = this.differ
// compare whether the element is swapped by offset
const changed = from.offset.top !== to.offset.top || from.offset.left !== to.offset.left
// onDrop callback
const { onDrop } = this.options
if (onDrop && typeof onDrop === 'function') onDrop(changed, evt)
}
if (Safari) css(document.body, 'user-select', '')
this.ghost.destroy(this.differ.to.rect)
this.state = new State
this.ghost.destroy(differ.to.rect)
this._clearState()
},
// -------------------------------- event ----------------------------------
_preventEvent: function(evt) {
if (this.options.stopPropagation) evt.stopPropagation && evt.stopPropagation() // prevent events from bubbling
evt.preventDefault !== void 0 && evt.cancelable && evt.preventDefault()
},
_dispatchEvent: function(event, params) {
const callback = this.options[event]
if (typeof callback === 'function') callback(params)
},
// -------------------------------- clear ----------------------------------
_clearState: function() {
this.state = new State
this.differ.destroy()
this.dragEl = null
this.dropEl = null
state = new State
differ.destroy()
dragEl =
dropEl =
nextEl =
ghostEl =
activeGroup = null
move =
lastPosition = { x: 0, y: 0 }
},
_unbindDragEvents: function() {
if (this.nativeDraggable) {
off(this.el, 'dragstart', this._onDragStart)
off(this.el, 'dragover', this._onDragOver)
off(this.el, 'dragend', this._onDrop)
off(document, 'drop', this)
}
},
_unbindMoveEvents: function() {
off(this.ownerDocument, 'pointermove', this._onMove)
off(this.ownerDocument, 'touchmove', this._onMove)
off(this.ownerDocument, 'mousemove', this._onMove)
off(this.ownerDocument, 'touchmove', _nearestSortable)
off(this.ownerDocument, 'mousemove', _nearestSortable)
off(this.ownerDocument, 'dragover', _nearestSortable)
},
_unbindDropEvents: function() {
off(this.ownerDocument, 'pointerup', this._onDrop)
off(this.ownerDocument, 'pointercancel', this._onDrop)
off(this.ownerDocument, 'touchend', this._onDrop)
off(this.ownerDocument, 'touchcancel', this._onDrop)
off(this.ownerDocument, 'mouseup', this._onDrop)
}

@@ -402,5 +607,4 @@ }

throttle,
getParentAutoScrollElement
}
export default Sortable
import { IE11OrLess } from './Brower.js'
import Sortable from './Sortable.js'

@@ -15,2 +16,16 @@ const captureMode = {

/**
* check if is HTMLElement
*/
export function isHTMLElement(obj) {
let d = document.createElement("div")
try {
d.appendChild(obj.cloneNode(true))
return obj.nodeType == 1 ? true : false
} catch(e) {
return obj == window || obj == document
}
}
/**
* set transition style

@@ -266,2 +281,25 @@ * @param {HTMLElement} el

/**
* Gets the last child in the el, ignoring ghostEl or invisible elements (clones)
* @param {HTMLElement} el Parent element
* @param {selector} selector Any other elements that should be ignored
* @return {HTMLElement} The last child, ignoring ghostEl
*/
export function lastChild(el, selector) {
let last = el.lastElementChild
while (
last &&
(
last === Sortable.ghost ||
css(last, 'display') === 'none' ||
selector && !matches(last, selector)
)
) {
last = last.previousElementSibling
}
return last || null
}
/**
* add or remove element's class

@@ -311,2 +349,9 @@ * @param {HTMLElement} el element

/**
* Check whether the front and rear positions are consistent
*/
export function offsetChanged(o1, o2) {
return o1.top !== o2.top || o1.left !== o2.left
}
export function css(el, prop, val) {

@@ -360,20 +405,2 @@ let style = el && el.style

export default {
on,
off,
css,
getRect,
matches,
throttle,
debounce,
getIndex,
_nextTick,
isChildOf,
getElement,
toggleClass,
setTransform,
setTransition,
supportPassive,
getWindowScrollingElement,
getParentAutoScrollElement,
}
export const expando = 'Sortable' + Date.now()
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