· 6 years ago · May 31, 2019, 10:56 PM
1/**!
2 * Sortable 1.9.0
3 * @author RubaXa <trash@rubaxa.org>
4 * @author owenm <owen23355@gmail.com>
5 * @license MIT
6 */
7(function (global, factory) {
8 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
9 typeof define === 'function' && define.amd ? define(factory) :
10 (global = global || self, global.Sortable = factory());
11}(this, function () { 'use strict';
12
13 function _typeof(obj) {
14 if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
15 _typeof = function (obj) {
16 return typeof obj;
17 };
18 } else {
19 _typeof = function (obj) {
20 return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
21 };
22 }
23
24 return _typeof(obj);
25 }
26
27 function _defineProperty(obj, key, value) {
28 if (key in obj) {
29 Object.defineProperty(obj, key, {
30 value: value,
31 enumerable: true,
32 configurable: true,
33 writable: true
34 });
35 } else {
36 obj[key] = value;
37 }
38
39 return obj;
40 }
41
42 function _extends() {
43 _extends = Object.assign || function (target) {
44 for (var i = 1; i < arguments.length; i++) {
45 var source = arguments[i];
46
47 for (var key in source) {
48 if (Object.prototype.hasOwnProperty.call(source, key)) {
49 target[key] = source[key];
50 }
51 }
52 }
53
54 return target;
55 };
56
57 return _extends.apply(this, arguments);
58 }
59
60 function _objectSpread(target) {
61 for (var i = 1; i < arguments.length; i++) {
62 var source = arguments[i] != null ? arguments[i] : {};
63 var ownKeys = Object.keys(source);
64
65 if (typeof Object.getOwnPropertySymbols === 'function') {
66 ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {
67 return Object.getOwnPropertyDescriptor(source, sym).enumerable;
68 }));
69 }
70
71 ownKeys.forEach(function (key) {
72 _defineProperty(target, key, source[key]);
73 });
74 }
75
76 return target;
77 }
78
79 function _objectWithoutPropertiesLoose(source, excluded) {
80 if (source == null) return {};
81 var target = {};
82 var sourceKeys = Object.keys(source);
83 var key, i;
84
85 for (i = 0; i < sourceKeys.length; i++) {
86 key = sourceKeys[i];
87 if (excluded.indexOf(key) >= 0) continue;
88 target[key] = source[key];
89 }
90
91 return target;
92 }
93
94 function _objectWithoutProperties(source, excluded) {
95 if (source == null) return {};
96
97 var target = _objectWithoutPropertiesLoose(source, excluded);
98
99 var key, i;
100
101 if (Object.getOwnPropertySymbols) {
102 var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
103
104 for (i = 0; i < sourceSymbolKeys.length; i++) {
105 key = sourceSymbolKeys[i];
106 if (excluded.indexOf(key) >= 0) continue;
107 if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
108 target[key] = source[key];
109 }
110 }
111
112 return target;
113 }
114
115 function _toConsumableArray(arr) {
116 return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread();
117 }
118
119 function _arrayWithoutHoles(arr) {
120 if (Array.isArray(arr)) {
121 for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
122
123 return arr2;
124 }
125 }
126
127 function _iterableToArray(iter) {
128 if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter);
129 }
130
131 function _nonIterableSpread() {
132 throw new TypeError("Invalid attempt to spread non-iterable instance");
133 }
134
135 var version = "1.9.0";
136
137 function userAgent(pattern) {
138 return !!navigator.userAgent.match(pattern);
139 }
140
141 var IE11OrLess =
142 /*@__PURE__*/
143 userAgent(/(?:Trident.*rv[ :]?11\.|msie|iemobile)/i);
144 var Edge =
145 /*@__PURE__*/
146 userAgent(/Edge/i);
147 var FireFox =
148 /*@__PURE__*/
149 userAgent(/firefox/i);
150 var Safari =
151 /*@__PURE__*/
152 userAgent(/safari/i) && !userAgent(/chrome/i) && !userAgent(/android/i);
153 var IOS =
154 /*@__PURE__*/
155 userAgent(/iP(ad|od|hone)/i);
156
157 var captureMode = {
158 capture: false,
159 passive: false
160 };
161
162 function on(el, event, fn) {
163 el.addEventListener(event, fn, IE11OrLess ? false : captureMode);
164 }
165
166 function off(el, event, fn) {
167 el.removeEventListener(event, fn, IE11OrLess ? false : captureMode);
168 }
169
170 function matches(
171 /**HTMLElement*/
172 el,
173 /**String*/
174 selector) {
175 if (!selector) return;
176 selector[0] === '>' && (selector = selector.substring(1));
177
178 if (el) {
179 try {
180 if (el.matches) {
181 return el.matches(selector);
182 } else if (el.msMatchesSelector) {
183 return el.msMatchesSelector(selector);
184 } else if (el.webkitMatchesSelector) {
185 return el.webkitMatchesSelector(selector);
186 }
187 } catch (_) {
188 return false;
189 }
190 }
191
192 return false;
193 }
194
195 function getParentOrHost(el) {
196 return el.host && el !== document && el.host.nodeType ? el.host : el.parentNode;
197 }
198
199 function closest(
200 /**HTMLElement*/
201 el,
202 /**String*/
203 selector,
204 /**HTMLElement*/
205 ctx, includeCTX) {
206 if (el) {
207 ctx = ctx || document;
208
209 do {
210 if (selector != null && (selector[0] === '>' ? el.parentNode === ctx && matches(el, selector) : matches(el, selector)) || includeCTX && el === ctx) {
211 return el;
212 }
213
214 if (el === ctx) break;
215 /* jshint boss:true */
216 } while (el = getParentOrHost(el));
217 }
218
219 return null;
220 }
221
222 var R_SPACE = /\s+/g;
223
224 function toggleClass(el, name, state) {
225 if (el && name) {
226 if (el.classList) {
227 el.classList[state ? 'add' : 'remove'](name);
228 } else {
229 var className = (' ' + el.className + ' ').replace(R_SPACE, ' ').replace(' ' + name + ' ', ' ');
230 el.className = (className + (state ? ' ' + name : '')).replace(R_SPACE, ' ');
231 }
232 }
233 }
234
235 function css(el, prop, val) {
236 var style = el && el.style;
237
238 if (style) {
239 if (val === void 0) {
240 if (document.defaultView && document.defaultView.getComputedStyle) {
241 val = document.defaultView.getComputedStyle(el, '');
242 } else if (el.currentStyle) {
243 val = el.currentStyle;
244 }
245
246 return prop === void 0 ? val : val[prop];
247 } else {
248 if (!(prop in style) && prop.indexOf('webkit') === -1) {
249 prop = '-webkit-' + prop;
250 }
251
252 style[prop] = val + (typeof val === 'string' ? '' : 'px');
253 }
254 }
255 }
256
257 function matrix(el, selfOnly) {
258 var appliedTransforms = '';
259
260 do {
261 var transform = css(el, 'transform');
262
263 if (transform && transform !== 'none') {
264 appliedTransforms = transform + ' ' + appliedTransforms;
265 }
266 /* jshint boss:true */
267
268 } while (!selfOnly && (el = el.parentNode));
269
270 if (window.DOMMatrix) {
271 return new DOMMatrix(appliedTransforms);
272 } else if (window.WebKitCSSMatrix) {
273 return new WebKitCSSMatrix(appliedTransforms);
274 } else if (window.CSSMatrix) {
275 return new CSSMatrix(appliedTransforms);
276 }
277 }
278
279 function find(ctx, tagName, iterator) {
280 if (ctx) {
281 var list = ctx.getElementsByTagName(tagName),
282 i = 0,
283 n = list.length;
284
285 if (iterator) {
286 for (; i < n; i++) {
287 iterator(list[i], i);
288 }
289 }
290
291 return list;
292 }
293
294 return [];
295 }
296
297 function getWindowScrollingElement() {
298 if (IE11OrLess) {
299 return document.documentElement;
300 } else {
301 return document.scrollingElement;
302 }
303 }
304 /**
305 * Returns the "bounding client rect" of given element
306 * @param {HTMLElement} el The element whose boundingClientRect is wanted
307 * @param {[Boolean]} relativeToContainingBlock Whether the rect should be relative to the containing block of (including) the container
308 * @param {[Boolean]} relativeToNonStaticParent Whether the rect should be relative to the relative parent of (including) the contaienr
309 * @param {[Boolean]} undoScale Whether the container's scale() should be undone
310 * @param {[HTMLElement]} container The parent the element will be placed in
311 * @return {Object} The boundingClientRect of el, with specified adjustments
312 */
313
314
315 function getRect(el, relativeToContainingBlock, relativeToNonStaticParent, undoScale, container) {
316 if (!el.getBoundingClientRect && el !== window) return;
317 var elRect, top, left, bottom, right, height, width;
318
319 if (el !== window && el !== getWindowScrollingElement()) {
320 elRect = el.getBoundingClientRect();
321 top = elRect.top;
322 left = elRect.left;
323 bottom = elRect.bottom;
324 right = elRect.right;
325 height = elRect.height;
326 width = elRect.width;
327 } else {
328 top = 0;
329 left = 0;
330 bottom = window.innerHeight;
331 right = window.innerWidth;
332 height = window.innerHeight;
333 width = window.innerWidth;
334 }
335
336 if ((relativeToContainingBlock || relativeToNonStaticParent) && el !== window) {
337 // Adjust for translate()
338 container = container || el.parentNode; // solves #1123 (see: https://stackoverflow.com/a/37953806/6088312)
339 // Not needed on <= IE11
340
341 if (!IE11OrLess) {
342 do {
343 if (container && container.getBoundingClientRect && (css(container, 'transform') !== 'none' || relativeToNonStaticParent && css(container, 'position') !== 'static')) {
344 var containerRect = container.getBoundingClientRect(); // Set relative to edges of padding box of container
345
346 top -= containerRect.top + parseInt(css(container, 'border-top-width'));
347 left -= containerRect.left + parseInt(css(container, 'border-left-width'));
348 bottom = top + elRect.height;
349 right = left + elRect.width;
350 break;
351 }
352 /* jshint boss:true */
353
354 } while (container = container.parentNode);
355 }
356 }
357
358 if (undoScale && el !== window) {
359 // Adjust for scale()
360 var elMatrix = matrix(container || el),
361 scaleX = elMatrix && elMatrix.a,
362 scaleY = elMatrix && elMatrix.d;
363
364 if (elMatrix) {
365 top /= scaleY;
366 left /= scaleX;
367 width /= scaleX;
368 height /= scaleY;
369 bottom = top + height;
370 right = left + width;
371 }
372 }
373
374 return {
375 top: top,
376 left: left,
377 bottom: bottom,
378 right: right,
379 width: width,
380 height: height
381 };
382 }
383 /**
384 * Checks if a side of an element is scrolled past a side of its parents
385 * @param {HTMLElement} el The element who's side being scrolled out of view is in question
386 * @param {[DOMRect]} rect Optional rect of `el` to use
387 * @param {String} elSide Side of the element in question ('top', 'left', 'right', 'bottom')
388 * @param {String} parentSide Side of the parent in question ('top', 'left', 'right', 'bottom')
389 * @return {HTMLElement} The parent scroll element that the el's side is scrolled past, or null if there is no such element
390 */
391
392
393 function isScrolledPast(el, rect, elSide, parentSide) {
394 var parent = getParentAutoScrollElement(el, true),
395 elSideVal = (rect ? rect : getRect(el))[elSide];
396 /* jshint boss:true */
397
398 while (parent) {
399 var parentSideVal = getRect(parent)[parentSide],
400 visible = void 0;
401
402 if (parentSide === 'top' || parentSide === 'left') {
403 visible = elSideVal >= parentSideVal;
404 } else {
405 visible = elSideVal <= parentSideVal;
406 }
407
408 if (!visible) return parent;
409 if (parent === getWindowScrollingElement()) break;
410 parent = getParentAutoScrollElement(parent, false);
411 }
412
413 return false;
414 }
415 /**
416 * Gets nth child of el, ignoring hidden children, sortable's elements (does not ignore clone if it's visible)
417 * and non-draggable elements
418 * @param {HTMLElement} el The parent element
419 * @param {Number} childNum The index of the child
420 * @param {Object} options Parent Sortable's options
421 * @return {HTMLElement} The child at index childNum, or null if not found
422 */
423
424
425 function getChild(el, childNum, options) {
426 var currentChild = 0,
427 i = 0,
428 children = el.children;
429
430 while (i < children.length) {
431 if (children[i].style.display !== 'none' && children[i] !== Sortable$1.ghost && children[i] !== Sortable$1.dragged && closest(children[i], options.draggable, el, false)) {
432 if (currentChild === childNum) {
433 return children[i];
434 }
435
436 currentChild++;
437 }
438
439 i++;
440 }
441
442 return null;
443 }
444 /**
445 * Gets the last child in the el, ignoring ghostEl or invisible elements (clones)
446 * @param {HTMLElement} el Parent element
447 * @param {selector} selector Any other elements that should be ignored
448 * @return {HTMLElement} The last child, ignoring ghostEl
449 */
450
451
452 function lastChild(el, selector) {
453 var last = el.lastElementChild;
454
455 while (last && (last === Sortable$1.ghost || css(last, 'display') === 'none' || selector && !matches(last, selector))) {
456 last = last.previousElementSibling;
457 }
458
459 return last || null;
460 }
461 /**
462 * Returns the index of an element within its parent for a selected set of
463 * elements
464 * @param {HTMLElement} el
465 * @param {selector} selector
466 * @return {number}
467 */
468
469
470 function index(el, selector) {
471 var index = 0;
472
473 if (!el || !el.parentNode) {
474 return -1;
475 }
476 /* jshint boss:true */
477
478
479 while (el = el.previousElementSibling) {
480 if (el.nodeName.toUpperCase() !== 'TEMPLATE' && el !== Sortable$1.clone && (!selector || matches(el, selector))) {
481 index++;
482 }
483 }
484
485 return index;
486 }
487 /**
488 * Returns the scroll offset of the given element, added with all the scroll offsets of parent elements.
489 * The value is returned in real pixels.
490 * @param {HTMLElement} el
491 * @return {Array} Offsets in the format of [left, top]
492 */
493
494
495 function getRelativeScrollOffset(el) {
496 var offsetLeft = 0,
497 offsetTop = 0,
498 winScroller = getWindowScrollingElement();
499
500 if (el) {
501 do {
502 var elMatrix = matrix(el),
503 scaleX = elMatrix.a,
504 scaleY = elMatrix.d;
505 offsetLeft += el.scrollLeft * scaleX;
506 offsetTop += el.scrollTop * scaleY;
507 } while (el !== winScroller && (el = el.parentNode));
508 }
509
510 return [offsetLeft, offsetTop];
511 }
512 /**
513 * Returns the index of the object within the given array
514 * @param {Array} arr Array that may or may not hold the object
515 * @param {Object} obj An object that has a key-value pair unique to and identical to a key-value pair in the object you want to find
516 * @return {Number} The index of the object in the array, or -1
517 */
518
519
520 function indexOfObject(arr, obj) {
521 for (var i in arr) {
522 for (var key in obj) {
523 if (obj[key] === arr[i][key]) return Number(i);
524 }
525 }
526
527 return -1;
528 }
529
530 function getParentAutoScrollElement(el, includeSelf) {
531 // skip to window
532 if (!el || !el.getBoundingClientRect) return getWindowScrollingElement();
533 var elem = el;
534 var gotSelf = false;
535
536 do {
537 // we don't need to get elem css if it isn't even overflowing in the first place (performance)
538 if (elem.clientWidth < elem.scrollWidth || elem.clientHeight < elem.scrollHeight) {
539 var elemCSS = css(elem);
540
541 if (elem.clientWidth < elem.scrollWidth && (elemCSS.overflowX == 'auto' || elemCSS.overflowX == 'scroll') || elem.clientHeight < elem.scrollHeight && (elemCSS.overflowY == 'auto' || elemCSS.overflowY == 'scroll')) {
542 if (!elem.getBoundingClientRect || elem === document.body) return getWindowScrollingElement();
543 if (gotSelf || includeSelf) return elem;
544 gotSelf = true;
545 }
546 }
547 /* jshint boss:true */
548
549 } while (elem = elem.parentNode);
550
551 return getWindowScrollingElement();
552 }
553
554 function extend(dst, src) {
555 if (dst && src) {
556 for (var key in src) {
557 if (src.hasOwnProperty(key)) {
558 dst[key] = src[key];
559 }
560 }
561 }
562
563 return dst;
564 }
565
566 function isRectEqual(rect1, rect2) {
567 return Math.round(rect1.top) === Math.round(rect2.top) && Math.round(rect1.left) === Math.round(rect2.left) && Math.round(rect1.height) === Math.round(rect2.height) && Math.round(rect1.width) === Math.round(rect2.width);
568 }
569
570 var _throttleTimeout;
571
572 function throttle(callback, ms) {
573 return function () {
574 if (!_throttleTimeout) {
575 var args = arguments,
576 _this = this;
577
578 if (args.length === 1) {
579 callback.call(_this, args[0]);
580 } else {
581 callback.apply(_this, args);
582 }
583
584 _throttleTimeout = setTimeout(function () {
585 _throttleTimeout = void 0;
586 }, ms);
587 }
588 };
589 }
590
591 function cancelThrottle() {
592 clearTimeout(_throttleTimeout);
593 _throttleTimeout = void 0;
594 }
595
596 function scrollBy(el, x, y) {
597 el.scrollLeft += x;
598 el.scrollTop += y;
599 }
600
601 function clone(el) {
602 var Polymer = window.Polymer;
603 var $ = window.jQuery || window.Zepto;
604
605 if (Polymer && Polymer.dom) {
606 return Polymer.dom(el).cloneNode(true);
607 } else if ($) {
608 return $(el).clone(true)[0];
609 } else {
610 return el.cloneNode(true);
611 }
612 }
613
614 function setRect(el, rect) {
615 css(el, 'position', 'absolute');
616 css(el, 'top', rect.top);
617 css(el, 'left', rect.left);
618 css(el, 'width', rect.width);
619 css(el, 'height', rect.height);
620 }
621
622 function unsetRect(el) {
623 css(el, 'position', '');
624 css(el, 'top', '');
625 css(el, 'left', '');
626 css(el, 'width', '');
627 css(el, 'height', '');
628 }
629
630 var expando = 'Sortable' + new Date().getTime();
631
632 function AnimationStateManager() {
633 var animationStates = [],
634 animationCallbackId;
635 return {
636 captureAnimationState: function captureAnimationState() {
637 animationStates = [];
638 if (!this.options.animation) return;
639 var children = [].slice.call(this.el.children);
640
641 for (var i in children) {
642 if (css(children[i], 'display') === 'none' || children[i] === Sortable$1.ghost) continue;
643 animationStates.push({
644 target: children[i],
645 rect: getRect(children[i])
646 });
647 var fromRect = getRect(children[i]); // If animating: compensate for current animation
648
649 if (children[i].thisAnimationDuration) {
650 var childMatrix = matrix(children[i], true);
651 fromRect.top -= childMatrix.f;
652 fromRect.left -= childMatrix.e;
653 }
654
655 children[i].fromRect = fromRect;
656 }
657 },
658 addAnimationState: function addAnimationState(state) {
659 animationStates.push(state);
660 },
661 removeAnimationState: function removeAnimationState(target) {
662 animationStates.splice(indexOfObject(animationStates, {
663 target: target
664 }), 1);
665 },
666 animateAll: function animateAll(callback) {
667 if (!this.options.animation) {
668 clearTimeout(animationCallbackId);
669 if (typeof callback === 'function') callback();
670 return;
671 }
672
673 var animating = false,
674 animationTime = 0;
675
676 for (var i in animationStates) {
677 var time = 0,
678 target = animationStates[i].target,
679 fromRect = target.fromRect,
680 toRect = getRect(target),
681 prevFromRect = target.prevFromRect,
682 prevToRect = target.prevToRect,
683 animatingRect = animationStates[i].rect,
684 targetMatrix = matrix(target, true); // Compensate for current animation
685
686 toRect.top -= targetMatrix.f;
687 toRect.left -= targetMatrix.e;
688 target.toRect = toRect; // If element is scrolled out of view: Do not animate
689
690 if ((isScrolledPast(target, toRect, 'bottom', 'top') || isScrolledPast(target, toRect, 'top', 'bottom') || isScrolledPast(target, toRect, 'right', 'left') || isScrolledPast(target, toRect, 'left', 'right')) && (isScrolledPast(target, animatingRect, 'bottom', 'top') || isScrolledPast(target, animatingRect, 'top', 'bottom') || isScrolledPast(target, animatingRect, 'right', 'left') || isScrolledPast(target, animatingRect, 'left', 'right')) && (isScrolledPast(target, fromRect, 'bottom', 'top') || isScrolledPast(target, fromRect, 'top', 'bottom') || isScrolledPast(target, fromRect, 'right', 'left') || isScrolledPast(target, fromRect, 'left', 'right'))) continue;
691
692 if (target.thisAnimationDuration) {
693 // Could also check if animatingRect is between fromRect and toRect
694 if (isRectEqual(prevFromRect, toRect) && !isRectEqual(fromRect, toRect) && // Make sure animatingRect is on line between toRect & fromRect
695 (animatingRect.top - toRect.top) / (animatingRect.left - toRect.left) === (fromRect.top - toRect.top) / (fromRect.left - toRect.left)) {
696 // If returning to same place as started from animation and on same axis
697 time = calculateRealTime(animatingRect, prevFromRect, prevToRect, this.options);
698 }
699 } // if fromRect != toRect and not animating to same position as already animating: animate
700
701
702 if (!isRectEqual(toRect, fromRect)) {
703 target.prevFromRect = fromRect;
704 target.prevToRect = toRect;
705
706 if (!time) {
707 time = this.options.animation;
708 }
709
710 this.animate(target, animatingRect, time);
711 }
712
713 if (time) {
714 animating = true;
715 animationTime = Math.max(animationTime, time);
716 clearTimeout(target.animationResetTimer);
717 target.animationResetTimer = setTimeout(function () {
718 this.animationStates[this.i].target.animationTime = 0;
719 this.animationStates[this.i].target.prevFromRect = null;
720 this.animationStates[this.i].target.fromRect = null;
721 this.animationStates[this.i].target.prevToRect = null;
722 this.animationStates[this.i].target.thisAnimationDuration = null;
723 }.bind({
724 animationStates: animationStates,
725 i: Number(i)
726 }), time);
727 target.thisAnimationDuration = time;
728 }
729 }
730
731 clearTimeout(animationCallbackId);
732
733 if (!animating) {
734 if (typeof callback === 'function') callback();
735 } else {
736 animationCallbackId = setTimeout(function () {
737 if (typeof callback === 'function') callback();
738 }, animationTime);
739 }
740
741 animationStates = [];
742 },
743 animate: function animate(target, prev, duration) {
744 if (duration) {
745 css(target, 'transition', '');
746 css(target, 'transform', '');
747 var currentRect = getRect(target),
748 elMatrix = matrix(this.el),
749 scaleX = elMatrix && elMatrix.a,
750 scaleY = elMatrix && elMatrix.d,
751 translateX = (prev.left - currentRect.left) / (scaleX || 1),
752 translateY = (prev.top - currentRect.top) / (scaleY || 1);
753 target.animatingX = !!translateX;
754 target.animatingY = !!translateY;
755 css(target, 'transform', 'translate3d(' + translateX + 'px,' + translateY + 'px,0)');
756 repaint(target); // repaint
757
758 css(target, 'transition', 'transform ' + duration + 'ms' + (this.options.easing ? ' ' + this.options.easing : ''));
759 css(target, 'transform', 'translate3d(0,0,0)');
760 typeof target.animated === 'number' && clearTimeout(target.animated);
761 target.animated = setTimeout(function () {
762 css(target, 'transition', '');
763 css(target, 'transform', '');
764 target.animated = false;
765 target.animatingX = false;
766 target.animatingY = false;
767 }, duration);
768 }
769 }
770 };
771 }
772
773 function repaint(target) {
774 return target.offsetWidth;
775 }
776
777 function calculateRealTime(animatingRect, fromRect, toRect, options) {
778 return Math.sqrt(Math.pow(fromRect.top - animatingRect.top, 2) + Math.pow(fromRect.left - animatingRect.left, 2)) / Math.sqrt(Math.pow(fromRect.top - toRect.top, 2) + Math.pow(fromRect.left - toRect.left, 2)) * options.animation;
779 }
780
781 var plugins = [];
782 var defaults = {
783 initializeByDefault: true
784 };
785 var PluginManager = {
786 mount: function mount(plugin) {
787 // Set default static properties
788 for (var option in defaults) {
789 !(option in plugin) && (plugin[option] = defaults[option]);
790 }
791
792 plugins.push(plugin);
793 },
794 pluginEvent: function pluginEvent(eventName, sortable, evt) {
795 this.eventCanceled = false;
796 var eventNameGlobal = eventName + 'Global';
797
798 for (var i in plugins) {
799 if (!sortable[plugins[i].pluginName]) continue; // Fire global events if it exists in this sortable
800
801 if (sortable[plugins[i].pluginName][eventNameGlobal]) {
802 this.eventCanceled = !!sortable[plugins[i].pluginName][eventNameGlobal](_objectSpread({
803 sortable: sortable
804 }, evt));
805 } // Only fire plugin event if plugin is enabled in this sortable,
806 // and plugin has event defined
807
808
809 if (sortable.options[plugins[i].pluginName] && sortable[plugins[i].pluginName][eventName]) {
810 this.eventCanceled = this.eventCanceled || !!sortable[plugins[i].pluginName][eventName](_objectSpread({
811 sortable: sortable
812 }, evt));
813 }
814 }
815 },
816 initializePlugins: function initializePlugins(sortable, el, defaults) {
817 for (var i in plugins) {
818 var pluginName = plugins[i].pluginName;
819 if (!sortable.options[pluginName] && !plugins[i].initializeByDefault) continue;
820 var initialized = new plugins[i](sortable, el);
821 initialized.sortable = sortable;
822 sortable[pluginName] = initialized; // Add default options from plugin
823
824 _extends(defaults, initialized.options);
825 }
826
827 for (var option in sortable.options) {
828 var modified = this.modifyOption(sortable, option, sortable.options[option]);
829
830 if (typeof modified !== 'undefined') {
831 sortable.options[option] = modified;
832 }
833 }
834 },
835 getEventOptions: function getEventOptions(name, sortable) {
836 var eventOptions = {};
837
838 for (var i in plugins) {
839 if (typeof plugins[i].eventOptions !== 'function') continue;
840 eventOptions = _objectSpread({}, eventOptions, plugins[i].eventOptions(name, sortable));
841 }
842
843 return eventOptions;
844 },
845 modifyOption: function modifyOption(sortable, name, value) {
846 var modifiedValue;
847
848 for (var i in plugins) {
849 // Plugin must exist on the Sortable
850 if (!sortable[plugins[i].pluginName]) continue; // If static option listener exists for this option, call in the context of the Sortable's instance of this plugin
851
852 if (plugins[i].optionListeners && typeof plugins[i].optionListeners[name] === 'function') {
853 modifiedValue = plugins[i].optionListeners[name].call(sortable[plugins[i].pluginName], value);
854 }
855 }
856
857 return modifiedValue;
858 }
859 };
860
861 function dispatchEvent(_ref) {
862 var sortable = _ref.sortable,
863 rootEl = _ref.rootEl,
864 name = _ref.name,
865 targetEl = _ref.targetEl,
866 cloneEl = _ref.cloneEl,
867 toEl = _ref.toEl,
868 fromEl = _ref.fromEl,
869 oldIndex = _ref.oldIndex,
870 newIndex = _ref.newIndex,
871 oldDraggableIndex = _ref.oldDraggableIndex,
872 newDraggableIndex = _ref.newDraggableIndex,
873 originalEvent = _ref.originalEvent,
874 putSortable = _ref.putSortable,
875 eventOptions = _ref.eventOptions;
876 sortable = sortable || rootEl[expando];
877 var evt,
878 options = sortable.options,
879 onName = 'on' + name.charAt(0).toUpperCase() + name.substr(1); // Support for new CustomEvent feature
880
881 if (window.CustomEvent && !IE11OrLess && !Edge) {
882 evt = new CustomEvent(name, {
883 bubbles: true,
884 cancelable: true
885 });
886 } else {
887 evt = document.createEvent('Event');
888 evt.initEvent(name, true, true);
889 }
890
891 evt.to = toEl || rootEl;
892 evt.from = fromEl || rootEl;
893 evt.item = targetEl || rootEl;
894 evt.clone = cloneEl;
895 evt.oldIndex = oldIndex;
896 evt.newIndex = newIndex;
897 evt.oldDraggableIndex = oldDraggableIndex;
898 evt.newDraggableIndex = newDraggableIndex;
899 evt.originalEvent = originalEvent;
900 evt.pullMode = putSortable ? putSortable.lastPutMode : undefined;
901
902 var allEventOptions = _objectSpread({}, eventOptions, PluginManager.getEventOptions(name, sortable));
903
904 for (var option in allEventOptions) {
905 evt[option] = allEventOptions[option];
906 }
907
908 if (rootEl) {
909 rootEl.dispatchEvent(evt);
910 }
911
912 if (options[onName]) {
913 options[onName].call(sortable, evt);
914 }
915 }
916
917 var pluginEvent = function pluginEvent(eventName, sortable) {
918 var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
919 originalEvent = _ref.evt,
920 data = _objectWithoutProperties(_ref, ["evt"]);
921
922 PluginManager.pluginEvent.bind(Sortable$1)(eventName, sortable, _objectSpread({
923 dragEl: dragEl,
924 parentEl: parentEl,
925 ghostEl: ghostEl,
926 rootEl: rootEl,
927 nextEl: nextEl,
928 lastDownEl: lastDownEl,
929 cloneEl: cloneEl,
930 cloneHidden: cloneHidden,
931 dragStarted: moved,
932 putSortable: putSortable,
933 activeSortable: Sortable$1.active,
934 originalEvent: originalEvent,
935 oldIndex: oldIndex,
936 oldDraggableIndex: oldDraggableIndex,
937 newIndex: newIndex,
938 newDraggableIndex: newDraggableIndex,
939 hideGhostForTarget: _hideGhostForTarget,
940 unhideGhostForTarget: _unhideGhostForTarget,
941 cloneNowHidden: function cloneNowHidden() {
942 cloneHidden = true;
943 },
944 cloneNowShown: function cloneNowShown() {
945 cloneHidden = false;
946 },
947 dispatchSortableEvent: function dispatchSortableEvent(name) {
948 _dispatchEvent({
949 sortable: sortable,
950 name: name,
951 originalEvent: originalEvent
952 });
953 }
954 }, data));
955 };
956
957 function _dispatchEvent(info) {
958 dispatchEvent(_objectSpread({
959 putSortable: putSortable,
960 cloneEl: cloneEl,
961 targetEl: dragEl,
962 rootEl: rootEl,
963 oldIndex: oldIndex,
964 oldDraggableIndex: oldDraggableIndex,
965 newIndex: newIndex,
966 newDraggableIndex: newDraggableIndex
967 }, info));
968 }
969
970 if (typeof window === "undefined" || !window.document) {
971 throw new Error("Sortable.js requires a window with a document");
972 }
973
974 var dragEl,
975 parentEl,
976 ghostEl,
977 rootEl,
978 nextEl,
979 lastDownEl,
980 cloneEl,
981 cloneHidden,
982 oldIndex,
983 newIndex,
984 oldDraggableIndex,
985 newDraggableIndex,
986 activeGroup,
987 putSortable,
988 awaitingDragStarted = false,
989 ignoreNextClick = false,
990 sortables = [],
991 tapEvt,
992 touchEvt,
993 moved,
994 lastTarget,
995 lastDirection,
996 pastFirstInvertThresh = false,
997 isCircumstantialInvert = false,
998 targetMoveDistance,
999 // For positioning ghost absolutely
1000 ghostRelativeParent,
1001 ghostRelativeParentInitialScroll = [],
1002 // (left, top)
1003 _silent = false,
1004 savedInputChecked = [];
1005 /** @const */
1006
1007 var PositionGhostAbsolutely = IOS,
1008 CSSFloatProperty = Edge || IE11OrLess ? 'cssFloat' : 'float',
1009 // This will not pass for IE9, because IE9 DnD only works on anchors
1010 supportDraggable = 'draggable' in document.createElement('div'),
1011 supportCssPointerEvents = function () {
1012 // false when <= IE11
1013 if (IE11OrLess) {
1014 return false;
1015 }
1016
1017 var el = document.createElement('x');
1018 el.style.cssText = 'pointer-events:auto';
1019 return el.style.pointerEvents === 'auto';
1020 }(),
1021 _detectDirection = function _detectDirection(el, options) {
1022 var elCSS = css(el),
1023 elWidth = parseInt(elCSS.width) - parseInt(elCSS.paddingLeft) - parseInt(elCSS.paddingRight) - parseInt(elCSS.borderLeftWidth) - parseInt(elCSS.borderRightWidth),
1024 child1 = getChild(el, 0, options),
1025 child2 = getChild(el, 1, options),
1026 firstChildCSS = child1 && css(child1),
1027 secondChildCSS = child2 && css(child2),
1028 firstChildWidth = firstChildCSS && parseInt(firstChildCSS.marginLeft) + parseInt(firstChildCSS.marginRight) + getRect(child1).width,
1029 secondChildWidth = secondChildCSS && parseInt(secondChildCSS.marginLeft) + parseInt(secondChildCSS.marginRight) + getRect(child2).width;
1030
1031 if (elCSS.display === 'flex') {
1032 return elCSS.flexDirection === 'column' || elCSS.flexDirection === 'column-reverse' ? 'vertical' : 'horizontal';
1033 }
1034
1035 if (elCSS.display === 'grid') {
1036 return elCSS.gridTemplateColumns.split(' ').length <= 1 ? 'vertical' : 'horizontal';
1037 }
1038
1039 if (child1 && firstChildCSS["float"] !== 'none') {
1040 var touchingSideChild2 = firstChildCSS["float"] === 'left' ? 'left' : 'right';
1041 return child2 && (secondChildCSS.clear === 'both' || secondChildCSS.clear === touchingSideChild2) ? 'vertical' : 'horizontal';
1042 }
1043
1044 return child1 && (firstChildCSS.display === 'block' || firstChildCSS.display === 'flex' || firstChildCSS.display === 'table' || firstChildCSS.display === 'grid' || firstChildWidth >= elWidth && elCSS[CSSFloatProperty] === 'none' || child2 && elCSS[CSSFloatProperty] === 'none' && firstChildWidth + secondChildWidth > elWidth) ? 'vertical' : 'horizontal';
1045 },
1046
1047 /**
1048 * Detects first nearest empty sortable to X and Y position using emptyInsertThreshold.
1049 * @param {Number} x X position
1050 * @param {Number} y Y position
1051 * @return {HTMLElement} Element of the first found nearest Sortable
1052 */
1053 _detectNearestEmptySortable = function _detectNearestEmptySortable(x, y) {
1054 for (var i in sortables) {
1055 if (lastChild(sortables[i])) continue;
1056 var rect = getRect(sortables[i]),
1057 threshold = sortables[i][expando].options.emptyInsertThreshold,
1058 insideHorizontally = x >= rect.left - threshold && x <= rect.right + threshold,
1059 insideVertically = y >= rect.top - threshold && y <= rect.bottom + threshold;
1060
1061 if (threshold && insideHorizontally && insideVertically) {
1062 return sortables[i];
1063 }
1064 }
1065 },
1066 _prepareGroup = function _prepareGroup(options) {
1067 function toFn(value, pull) {
1068 return function (to, from, dragEl, evt) {
1069 var sameGroup = to.options.group.name && from.options.group.name && to.options.group.name === from.options.group.name;
1070
1071 if (value == null && (pull || sameGroup)) {
1072 // Default pull value
1073 // Default pull and put value if same group
1074 return true;
1075 } else if (value == null || value === false) {
1076 return false;
1077 } else if (pull && value === 'clone') {
1078 return value;
1079 } else if (typeof value === 'function') {
1080 return toFn(value(to, from, dragEl, evt), pull)(to, from, dragEl, evt);
1081 } else {
1082 var otherGroup = (pull ? to : from).options.group.name;
1083 return value === true || typeof value === 'string' && value === otherGroup || value.join && value.indexOf(otherGroup) > -1;
1084 }
1085 };
1086 }
1087
1088 var group = {};
1089 var originalGroup = options.group;
1090
1091 if (!originalGroup || _typeof(originalGroup) != 'object') {
1092 originalGroup = {
1093 name: originalGroup
1094 };
1095 }
1096
1097 group.name = originalGroup.name;
1098 group.checkPull = toFn(originalGroup.pull, true);
1099 group.checkPut = toFn(originalGroup.put);
1100 group.revertClone = originalGroup.revertClone;
1101 options.group = group;
1102 },
1103 _hideGhostForTarget = function _hideGhostForTarget() {
1104 if (!supportCssPointerEvents && ghostEl) {
1105 css(ghostEl, 'display', 'none');
1106 }
1107 },
1108 _unhideGhostForTarget = function _unhideGhostForTarget() {
1109 if (!supportCssPointerEvents && ghostEl) {
1110 css(ghostEl, 'display', '');
1111 }
1112 }; // #1184 fix - Prevent click event on fallback if dragged but item not changed position
1113
1114
1115 document.addEventListener('click', function (evt) {
1116 if (ignoreNextClick) {
1117 evt.preventDefault();
1118 evt.stopPropagation && evt.stopPropagation();
1119 evt.stopImmediatePropagation && evt.stopImmediatePropagation();
1120 ignoreNextClick = false;
1121 return false;
1122 }
1123 }, true);
1124
1125 var nearestEmptyInsertDetectEvent = function nearestEmptyInsertDetectEvent(evt) {
1126 if (dragEl) {
1127 evt = evt.touches ? evt.touches[0] : evt;
1128
1129 var nearest = _detectNearestEmptySortable(evt.clientX, evt.clientY);
1130
1131 if (nearest) {
1132 // Create imitation event
1133 var event = {};
1134
1135 for (var i in evt) {
1136 event[i] = evt[i];
1137 }
1138
1139 event.target = event.rootEl = nearest;
1140 event.preventDefault = void 0;
1141 event.stopPropagation = void 0;
1142
1143 nearest[expando]._onDragOver(event);
1144 }
1145 }
1146 };
1147
1148 var _checkOutsideTargetEl = function _checkOutsideTargetEl(evt) {
1149 if (dragEl) {
1150 dragEl.parentNode[expando]._isOutsideThisEl(evt.target);
1151 }
1152 };
1153 /**
1154 * @class Sortable
1155 * @param {HTMLElement} el
1156 * @param {Object} [options]
1157 */
1158
1159
1160 function Sortable$1(el, options) {
1161 if (!(el && el.nodeType && el.nodeType === 1)) {
1162 throw "Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(el));
1163 }
1164
1165 this.el = el; // root element
1166
1167 this.options = options = _extends({}, options); // Export instance
1168
1169 el[expando] = this;
1170 var defaults = {
1171 group: null,
1172 sort: true,
1173 disabled: false,
1174 store: null,
1175 handle: null,
1176 draggable: /[uo]l/i.test(el.nodeName) ? '>li' : '>*',
1177 swapThreshold: 1,
1178 // percentage; 0 <= x <= 1
1179 invertSwap: false,
1180 // invert always
1181 invertedSwapThreshold: null,
1182 // will be set to same as swapThreshold if default
1183 removeCloneOnHide: true,
1184 direction: function direction() {
1185 return _detectDirection(el, this.options);
1186 },
1187 ghostClass: 'sortable-ghost',
1188 chosenClass: 'sortable-chosen',
1189 dragClass: 'sortable-drag',
1190 ignore: 'a, img',
1191 filter: null,
1192 preventOnFilter: true,
1193 animation: 0,
1194 easing: null,
1195 setData: function setData(dataTransfer, dragEl) {
1196 dataTransfer.setData('Text', dragEl.textContent);
1197 },
1198 dropBubble: false,
1199 dragoverBubble: false,
1200 dataIdAttr: 'data-id',
1201 delay: 0,
1202 delayOnTouchOnly: false,
1203 touchStartThreshold: parseInt(window.devicePixelRatio, 10) || 1,
1204 forceFallback: false,
1205 fallbackClass: 'sortable-fallback',
1206 fallbackOnBody: false,
1207 fallbackTolerance: 0,
1208 fallbackOffset: {
1209 x: 0,
1210 y: 0
1211 },
1212 supportPointer: Sortable$1.supportPointer !== false && 'PointerEvent' in window,
1213 emptyInsertThreshold: 5
1214 };
1215 PluginManager.initializePlugins(this, el, defaults); // Set default options
1216
1217 for (var name in defaults) {
1218 !(name in options) && (options[name] = defaults[name]);
1219 }
1220
1221 _prepareGroup(options); // Bind all private methods
1222
1223
1224 for (var fn in this) {
1225 if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {
1226 this[fn] = this[fn].bind(this);
1227 }
1228 } // Setup drag mode
1229
1230
1231 this.nativeDraggable = options.forceFallback ? false : supportDraggable;
1232
1233 if (this.nativeDraggable) {
1234 // Touch start threshold cannot be greater than the native dragstart threshold
1235 this.options.touchStartThreshold = 1;
1236 } // Bind events
1237
1238
1239 if (options.supportPointer) {
1240 on(el, 'pointerdown', this._onTapStart);
1241 } else {
1242 on(el, 'mousedown', this._onTapStart);
1243 on(el, 'touchstart', this._onTapStart);
1244 }
1245
1246 if (this.nativeDraggable) {
1247 on(el, 'dragover', this);
1248 on(el, 'dragenter', this);
1249 }
1250
1251 sortables.push(this.el); // Restore sorting
1252
1253 options.store && options.store.get && this.sort(options.store.get(this) || []); // Add animation state manager
1254
1255 _extends(this, AnimationStateManager());
1256 }
1257
1258 Sortable$1.prototype =
1259 /** @lends Sortable.prototype */
1260 {
1261 constructor: Sortable$1,
1262 _isOutsideThisEl: function _isOutsideThisEl(target) {
1263 if (!this.el.contains(target) && target !== this.el) {
1264 lastTarget = null;
1265 }
1266 },
1267 _getDirection: function _getDirection(evt, target) {
1268 return typeof this.options.direction === 'function' ? this.options.direction.call(this, evt, target, dragEl) : this.options.direction;
1269 },
1270 _onTapStart: function _onTapStart(
1271 /** Event|TouchEvent */
1272 evt) {
1273 if (!evt.cancelable) return;
1274
1275 var _this = this,
1276 el = this.el,
1277 options = this.options,
1278 preventOnFilter = options.preventOnFilter,
1279 type = evt.type,
1280 touch = evt.touches && evt.touches[0],
1281 target = (touch || evt).target,
1282 originalTarget = evt.target.shadowRoot && (evt.path && evt.path[0] || evt.composedPath && evt.composedPath()[0]) || target,
1283 filter = options.filter;
1284
1285 _saveInputCheckedState(el); // Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group.
1286
1287
1288 if (dragEl) {
1289 return;
1290 }
1291
1292 if (/mousedown|pointerdown/.test(type) && evt.button !== 0 || options.disabled) {
1293 return; // only left button and enabled
1294 } // cancel dnd if original target is content editable
1295
1296
1297 if (originalTarget.isContentEditable) {
1298 return;
1299 }
1300
1301 target = closest(target, options.draggable, el, false);
1302
1303 if (target && target.animated) {
1304 return;
1305 }
1306
1307 if (lastDownEl === target) {
1308 // Ignoring duplicate `down`
1309 return;
1310 } // Get the index of the dragged element within its parent
1311
1312
1313 oldIndex = index(target);
1314 oldDraggableIndex = index(target, options.draggable); // Check filter
1315
1316 if (typeof filter === 'function') {
1317 if (filter.call(this, evt, target, this)) {
1318 _dispatchEvent({
1319 sortable: _this,
1320 rootEl: originalTarget,
1321 name: 'filter',
1322 targetEl: target,
1323 toEl: el,
1324 fromEl: el
1325 });
1326
1327 pluginEvent('filter', _this, {
1328 evt: evt
1329 });
1330 preventOnFilter && evt.cancelable && evt.preventDefault();
1331 return; // cancel dnd
1332 }
1333 } else if (filter) {
1334 filter = filter.split(',').some(function (criteria) {
1335 criteria = closest(originalTarget, criteria.trim(), el, false);
1336
1337 if (criteria) {
1338 _dispatchEvent({
1339 sortable: _this,
1340 rootEl: criteria,
1341 name: 'filter',
1342 targetEl: target,
1343 fromEl: el,
1344 toEl: el
1345 });
1346
1347 pluginEvent('filter', _this, {
1348 evt: evt
1349 });
1350 return true;
1351 }
1352 });
1353
1354 if (filter) {
1355 preventOnFilter && evt.cancelable && evt.preventDefault();
1356 return; // cancel dnd
1357 }
1358 }
1359
1360 if (options.handle && !closest(originalTarget, options.handle, el, false)) {
1361 return;
1362 } // Prepare `dragstart`
1363
1364
1365 this._prepareDragStart(evt, touch, target);
1366 },
1367 _prepareDragStart: function _prepareDragStart(
1368 /** Event */
1369 evt,
1370 /** Touch */
1371 touch,
1372 /** HTMLElement */
1373 target) {
1374 var _this = this,
1375 el = _this.el,
1376 options = _this.options,
1377 ownerDocument = el.ownerDocument,
1378 dragStartFn;
1379
1380 if (target && !dragEl && target.parentNode === el) {
1381 rootEl = el;
1382 dragEl = target;
1383 parentEl = dragEl.parentNode;
1384 nextEl = dragEl.nextSibling;
1385 lastDownEl = target;
1386 activeGroup = options.group;
1387 Sortable$1.dragged = dragEl;
1388 tapEvt = {
1389 target: dragEl,
1390 clientX: (touch || evt).clientX,
1391 clientY: (touch || evt).clientY
1392 };
1393 this._lastX = (touch || evt).clientX;
1394 this._lastY = (touch || evt).clientY;
1395 dragEl.style['will-change'] = 'all';
1396
1397 dragStartFn = function dragStartFn() {
1398 pluginEvent('delayEnded', _this, {
1399 evt: evt
1400 });
1401
1402 if (Sortable$1.eventCanceled) {
1403 _this._onDrop();
1404
1405 return;
1406 } // Delayed drag has been triggered
1407 // we can re-enable the events: touchmove/mousemove
1408
1409
1410 _this._disableDelayedDragEvents();
1411
1412 if (!FireFox && _this.nativeDraggable) {
1413 dragEl.draggable = true;
1414 } // Bind the events: dragstart/dragend
1415
1416
1417 _this._triggerDragStart(evt, touch); // Drag start event
1418
1419
1420 _dispatchEvent({
1421 sortable: _this,
1422 name: 'choose',
1423 originalEvent: evt
1424 }); // Chosen item
1425
1426
1427 toggleClass(dragEl, options.chosenClass, true);
1428 }; // Disable "draggable"
1429
1430
1431 options.ignore.split(',').forEach(function (criteria) {
1432 find(dragEl, criteria.trim(), _disableDraggable);
1433 });
1434 on(ownerDocument, 'dragover', nearestEmptyInsertDetectEvent);
1435 on(ownerDocument, 'mousemove', nearestEmptyInsertDetectEvent);
1436 on(ownerDocument, 'touchmove', nearestEmptyInsertDetectEvent);
1437 on(ownerDocument, 'mouseup', _this._onDrop);
1438 on(ownerDocument, 'touchend', _this._onDrop);
1439 on(ownerDocument, 'touchcancel', _this._onDrop); // Make dragEl draggable (must be before delay for FireFox)
1440
1441 if (FireFox && this.nativeDraggable) {
1442 this.options.touchStartThreshold = 4;
1443 dragEl.draggable = true;
1444 }
1445
1446 pluginEvent('delayStart', this, {
1447 evt: evt
1448 }); // Delay is impossible for native DnD in Edge or IE
1449
1450 if (options.delay && (!options.delayOnTouchOnly || touch) && (!this.nativeDraggable || !(Edge || IE11OrLess))) {
1451 if (Sortable$1.eventCanceled) {
1452 this._onDrop();
1453
1454 return;
1455 } // If the user moves the pointer or let go the click or touch
1456 // before the delay has been reached:
1457 // disable the delayed drag
1458
1459
1460 on(ownerDocument, 'mouseup', _this._disableDelayedDrag);
1461 on(ownerDocument, 'touchend', _this._disableDelayedDrag);
1462 on(ownerDocument, 'touchcancel', _this._disableDelayedDrag);
1463 on(ownerDocument, 'mousemove', _this._delayedDragTouchMoveHandler);
1464 on(ownerDocument, 'touchmove', _this._delayedDragTouchMoveHandler);
1465 options.supportPointer && on(ownerDocument, 'pointermove', _this._delayedDragTouchMoveHandler);
1466 _this._dragStartTimer = setTimeout(dragStartFn, options.delay);
1467 } else {
1468 dragStartFn();
1469 }
1470 }
1471 },
1472 _delayedDragTouchMoveHandler: function _delayedDragTouchMoveHandler(
1473 /** TouchEvent|PointerEvent **/
1474 e) {
1475 var touch = e.touches ? e.touches[0] : e;
1476
1477 if (Math.max(Math.abs(touch.clientX - this._lastX), Math.abs(touch.clientY - this._lastY)) >= Math.floor(this.options.touchStartThreshold / (this.nativeDraggable && window.devicePixelRatio || 1))) {
1478 this._disableDelayedDrag();
1479 }
1480 },
1481 _disableDelayedDrag: function _disableDelayedDrag() {
1482 dragEl && _disableDraggable(dragEl);
1483 clearTimeout(this._dragStartTimer);
1484
1485 this._disableDelayedDragEvents();
1486 },
1487 _disableDelayedDragEvents: function _disableDelayedDragEvents() {
1488 var ownerDocument = this.el.ownerDocument;
1489 off(ownerDocument, 'mouseup', this._disableDelayedDrag);
1490 off(ownerDocument, 'touchend', this._disableDelayedDrag);
1491 off(ownerDocument, 'touchcancel', this._disableDelayedDrag);
1492 off(ownerDocument, 'mousemove', this._delayedDragTouchMoveHandler);
1493 off(ownerDocument, 'touchmove', this._delayedDragTouchMoveHandler);
1494 off(ownerDocument, 'pointermove', this._delayedDragTouchMoveHandler);
1495 },
1496 _triggerDragStart: function _triggerDragStart(
1497 /** Event */
1498 evt,
1499 /** Touch */
1500 touch) {
1501 touch = touch || (evt.pointerType == 'touch' ? evt : null);
1502
1503 if (!this.nativeDraggable || touch) {
1504 if (this.options.supportPointer) {
1505 on(document, 'pointermove', this._onTouchMove);
1506 } else if (touch) {
1507 on(document, 'touchmove', this._onTouchMove);
1508 } else {
1509 on(document, 'mousemove', this._onTouchMove);
1510 }
1511 } else {
1512 on(dragEl, 'dragend', this);
1513 on(rootEl, 'dragstart', this._onDragStart);
1514 }
1515
1516 try {
1517 if (document.selection) {
1518 // Timeout neccessary for IE9
1519 _nextTick(function () {
1520 document.selection.empty();
1521 });
1522 } else {
1523 window.getSelection().removeAllRanges();
1524 }
1525 } catch (err) {}
1526 },
1527 _dragStarted: function _dragStarted(fallback, evt) {
1528
1529 awaitingDragStarted = false;
1530
1531 if (rootEl && dragEl) {
1532 pluginEvent('dragStarted', this, {
1533 evt: evt
1534 });
1535
1536 if (this.nativeDraggable) {
1537 on(document, 'dragover', _checkOutsideTargetEl);
1538 }
1539
1540 var options = this.options; // Apply effect
1541
1542 !fallback && toggleClass(dragEl, options.dragClass, false);
1543 toggleClass(dragEl, options.ghostClass, true);
1544 Sortable$1.active = this;
1545 fallback && this._appendGhost(); // Drag start event
1546
1547 _dispatchEvent({
1548 sortable: this,
1549 name: 'start',
1550 originalEvent: evt
1551 });
1552 } else {
1553 this._nulling();
1554 }
1555 },
1556 _emulateDragOver: function _emulateDragOver() {
1557 if (touchEvt) {
1558 this._lastX = touchEvt.clientX;
1559 this._lastY = touchEvt.clientY;
1560
1561 _hideGhostForTarget();
1562
1563 var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY);
1564 var parent = target;
1565
1566 while (target && target.shadowRoot) {
1567 target = target.shadowRoot.elementFromPoint(touchEvt.clientX, touchEvt.clientY);
1568 if (target === parent) break;
1569 parent = target;
1570 }
1571
1572 dragEl.parentNode[expando]._isOutsideThisEl(target);
1573
1574 if (parent) {
1575 do {
1576 if (parent[expando]) {
1577 var inserted = void 0;
1578 inserted = parent[expando]._onDragOver({
1579 clientX: touchEvt.clientX,
1580 clientY: touchEvt.clientY,
1581 target: target,
1582 rootEl: parent
1583 });
1584
1585 if (inserted && !this.options.dragoverBubble) {
1586 break;
1587 }
1588 }
1589
1590 target = parent; // store last element
1591 }
1592 /* jshint boss:true */
1593 while (parent = parent.parentNode);
1594 }
1595
1596 _unhideGhostForTarget();
1597 }
1598 },
1599 _onTouchMove: function _onTouchMove(
1600 /**TouchEvent*/
1601 evt) {
1602 if (tapEvt) {
1603 var options = this.options,
1604 fallbackTolerance = options.fallbackTolerance,
1605 fallbackOffset = options.fallbackOffset,
1606 touch = evt.touches ? evt.touches[0] : evt,
1607 ghostMatrix = ghostEl && matrix(ghostEl),
1608 scaleX = ghostEl && ghostMatrix && ghostMatrix.a,
1609 scaleY = ghostEl && ghostMatrix && ghostMatrix.d,
1610 relativeScrollOffset = PositionGhostAbsolutely && ghostRelativeParent && getRelativeScrollOffset(ghostRelativeParent),
1611 dx = (touch.clientX - tapEvt.clientX + fallbackOffset.x) / (scaleX || 1) + (relativeScrollOffset ? relativeScrollOffset[0] - ghostRelativeParentInitialScroll[0] : 0) / (scaleX || 1),
1612 dy = (touch.clientY - tapEvt.clientY + fallbackOffset.y) / (scaleY || 1) + (relativeScrollOffset ? relativeScrollOffset[1] - ghostRelativeParentInitialScroll[1] : 0) / (scaleY || 1),
1613 translate3d = evt.touches ? 'translate3d(' + dx + 'px,' + dy + 'px,0)' : 'translate(' + dx + 'px,' + dy + 'px)'; // only set the status to dragging, when we are actually dragging
1614
1615 if (!Sortable$1.active && !awaitingDragStarted) {
1616 if (fallbackTolerance && Math.max(Math.abs(touch.clientX - this._lastX), Math.abs(touch.clientY - this._lastY)) < fallbackTolerance) {
1617 return;
1618 }
1619
1620 this._onDragStart(evt, true);
1621 }
1622
1623 touchEvt = touch;
1624 css(ghostEl, 'webkitTransform', translate3d);
1625 css(ghostEl, 'mozTransform', translate3d);
1626 css(ghostEl, 'msTransform', translate3d);
1627 css(ghostEl, 'transform', translate3d);
1628 evt.cancelable && evt.preventDefault();
1629 }
1630 },
1631 _appendGhost: function _appendGhost() {
1632 // Bug if using scale(): https://stackoverflow.com/questions/2637058
1633 // Not being adjusted for
1634 if (!ghostEl) {
1635 var container = this.options.fallbackOnBody ? document.body : rootEl,
1636 rect = getRect(dragEl, true, PositionGhostAbsolutely, true, container),
1637 options = this.options; // Position absolutely
1638
1639 if (PositionGhostAbsolutely) {
1640 // Get relatively positioned parent
1641 ghostRelativeParent = container;
1642
1643 while (css(ghostRelativeParent, 'position') === 'static' && css(ghostRelativeParent, 'transform') === 'none' && ghostRelativeParent !== document) {
1644 ghostRelativeParent = ghostRelativeParent.parentNode;
1645 }
1646
1647 if (ghostRelativeParent !== document.body && ghostRelativeParent !== document.documentElement) {
1648 if (ghostRelativeParent === document) ghostRelativeParent = getWindowScrollingElement();
1649 rect.top += ghostRelativeParent.scrollTop;
1650 rect.left += ghostRelativeParent.scrollLeft;
1651 } else {
1652 ghostRelativeParent = getWindowScrollingElement();
1653 }
1654
1655 ghostRelativeParentInitialScroll = getRelativeScrollOffset(ghostRelativeParent);
1656 }
1657
1658 ghostEl = dragEl.cloneNode(true);
1659 toggleClass(ghostEl, options.ghostClass, false);
1660 toggleClass(ghostEl, options.fallbackClass, true);
1661 toggleClass(ghostEl, options.dragClass, true);
1662 css(ghostEl, 'transition', '');
1663 css(ghostEl, 'transform', '');
1664 css(ghostEl, 'box-sizing', 'border-box');
1665 css(ghostEl, 'margin', 0);
1666 css(ghostEl, 'top', rect.top);
1667 css(ghostEl, 'left', rect.left);
1668 css(ghostEl, 'width', rect.width);
1669 css(ghostEl, 'height', rect.height);
1670 css(ghostEl, 'opacity', '0.8');
1671 css(ghostEl, 'position', PositionGhostAbsolutely ? 'absolute' : 'fixed');
1672 css(ghostEl, 'zIndex', '100000');
1673 css(ghostEl, 'pointerEvents', 'none');
1674 Sortable$1.ghost = ghostEl;
1675 container.appendChild(ghostEl);
1676 }
1677 },
1678 _onDragStart: function _onDragStart(
1679 /**Event*/
1680 evt,
1681 /**boolean*/
1682 fallback) {
1683 var _this = this;
1684
1685 var dataTransfer = evt.dataTransfer;
1686 var options = _this.options;
1687 pluginEvent('dragStart', this, {
1688 evt: evt
1689 });
1690
1691 if (Sortable$1.eventCanceled) {
1692 this._onDrop();
1693
1694 return;
1695 }
1696
1697 pluginEvent('setupClone', this);
1698
1699 if (!Sortable$1.eventCanceled) {
1700 cloneEl = clone(dragEl);
1701 cloneEl.draggable = false;
1702 cloneEl.style['will-change'] = '';
1703
1704 this._hideClone();
1705
1706 toggleClass(cloneEl, this.options.chosenClass, false);
1707 Sortable$1.clone = cloneEl;
1708 } // #1143: IFrame support workaround
1709
1710
1711 _this.cloneId = _nextTick(function () {
1712 pluginEvent('clone', _this);
1713 if (Sortable$1.eventCanceled) return;
1714
1715 if (!_this.options.removeCloneOnHide) {
1716 rootEl.insertBefore(cloneEl, dragEl);
1717 }
1718
1719 _this._hideClone();
1720
1721 _dispatchEvent({
1722 sortable: _this,
1723 name: 'clone'
1724 });
1725 });
1726 !fallback && toggleClass(dragEl, options.dragClass, true); // Set proper drop events
1727
1728 if (fallback) {
1729 ignoreNextClick = true;
1730 _this._loopId = setInterval(_this._emulateDragOver, 50);
1731 } else {
1732 // Undo what was set in _prepareDragStart before drag started
1733 off(document, 'mouseup', _this._onDrop);
1734 off(document, 'touchend', _this._onDrop);
1735 off(document, 'touchcancel', _this._onDrop);
1736
1737 if (dataTransfer) {
1738 dataTransfer.effectAllowed = 'move';
1739 options.setData && options.setData.call(_this, dataTransfer, dragEl);
1740 }
1741
1742 on(document, 'drop', _this); // #1276 fix:
1743
1744 css(dragEl, 'transform', 'translateZ(0)');
1745 }
1746
1747 awaitingDragStarted = true;
1748 _this._dragStartId = _nextTick(_this._dragStarted.bind(_this, fallback, evt));
1749 on(document, 'selectstart', _this);
1750 moved = true;
1751
1752 if (Safari) {
1753 css(document.body, 'user-select', 'none');
1754 }
1755 },
1756 // Returns true - if no further action is needed (either inserted or another condition)
1757 _onDragOver: function _onDragOver(
1758 /**Event*/
1759 evt) {
1760 var el = this.el,
1761 target = evt.target,
1762 dragRect,
1763 targetRect,
1764 revert,
1765 options = this.options,
1766 group = options.group,
1767 activeSortable = Sortable$1.active,
1768 isOwner = activeGroup === group,
1769 canSort = options.sort,
1770 fromSortable = putSortable || activeSortable,
1771 vertical,
1772 _this = this,
1773 completedFired = false;
1774
1775 if (_silent) return;
1776
1777 function dragOverEvent(name, extra) {
1778 pluginEvent(name, _this, _objectSpread({
1779 evt: evt,
1780 isOwner: isOwner,
1781 axis: vertical ? 'vertical' : 'horizontal',
1782 revert: revert,
1783 dragRect: dragRect,
1784 targetRect: targetRect,
1785 canSort: canSort,
1786 fromSortable: fromSortable,
1787 target: target,
1788 completed: completed,
1789 onMove: function onMove(target, after) {
1790 _onMove(rootEl, el, dragEl, dragRect, target, getRect(target), evt, after);
1791 },
1792 changed: changed
1793 }, extra));
1794 } // Capture animation state
1795
1796
1797 function capture() {
1798 dragOverEvent('dragOverAnimationCapture');
1799
1800 _this.captureAnimationState();
1801
1802 if (_this !== fromSortable) {
1803 fromSortable.captureAnimationState();
1804 }
1805 } // Return invocation when dragEl is inserted (or completed)
1806
1807
1808 function completed(insertion) {
1809 dragOverEvent('dragOverCompleted', {
1810 insertion: insertion
1811 });
1812
1813 if (insertion) {
1814 // Clones must be hidden before folding animation to capture dragRectAbsolute properly
1815 if (isOwner) {
1816 activeSortable._hideClone();
1817 } else {
1818 activeSortable._showClone(_this);
1819 }
1820
1821 if (_this !== fromSortable) {
1822 // Set ghost class to new sortable's ghost class
1823 toggleClass(dragEl, putSortable ? putSortable.options.ghostClass : activeSortable.options.ghostClass, false);
1824 toggleClass(dragEl, options.ghostClass, true);
1825 }
1826
1827 if (putSortable !== _this && _this !== Sortable$1.active) {
1828 putSortable = _this;
1829 } else if (_this === Sortable$1.active && putSortable) {
1830 putSortable = null;
1831 } // Animation
1832
1833
1834 if (fromSortable === _this) {
1835 _this._ignoreWhileAnimating = target;
1836 }
1837
1838 _this.animateAll(function () {
1839 dragOverEvent('dragOverAnimationComplete');
1840 _this._ignoreWhileAnimating = null;
1841 });
1842
1843 if (_this !== fromSortable) {
1844 fromSortable.animateAll();
1845 fromSortable._ignoreWhileAnimating = null;
1846 }
1847 } // Null lastTarget if it is not inside a previously swapped element
1848
1849
1850 if (target === dragEl && !dragEl.animated || target === el && !target.animated) {
1851 lastTarget = null;
1852 } // no bubbling and not fallback
1853
1854
1855 if (!options.dragoverBubble && !evt.rootEl && target !== document) {
1856 dragEl.parentNode[expando]._isOutsideThisEl(evt.target); // Do not detect for empty insert if already inserted
1857
1858
1859 !insertion && nearestEmptyInsertDetectEvent(evt);
1860 }
1861
1862 !options.dragoverBubble && evt.stopPropagation && evt.stopPropagation();
1863 return completedFired = true;
1864 } // Call when dragEl has been inserted
1865
1866
1867 function changed() {
1868 newIndex = index(dragEl);
1869 newDraggableIndex = index(dragEl, options.draggable);
1870
1871 _dispatchEvent({
1872 sortable: _this,
1873 name: 'change',
1874 toEl: el,
1875 newIndex: newIndex,
1876 newDraggableIndex: newDraggableIndex,
1877 originalEvent: evt
1878 });
1879 }
1880
1881 if (evt.preventDefault !== void 0) {
1882 evt.cancelable && evt.preventDefault();
1883 }
1884
1885 target = closest(target, options.draggable, el, true);
1886 dragOverEvent('dragOver');
1887 if (Sortable$1.eventCanceled) return completedFired;
1888
1889 if (dragEl.contains(evt.target) || target.animated && target.animatingX && target.animatingY || _this._ignoreWhileAnimating === target) {
1890 return completed(false);
1891 }
1892
1893 ignoreNextClick = false;
1894
1895 if (activeSortable && !options.disabled && (isOwner ? canSort || (revert = !rootEl.contains(dragEl)) // Reverting item into the original list
1896 : putSortable === this || (this.lastPutMode = activeGroup.checkPull(this, activeSortable, dragEl, evt)) && group.checkPut(this, activeSortable, dragEl, evt))) {
1897 vertical = this._getDirection(evt, target) === 'vertical';
1898 dragRect = getRect(dragEl);
1899 dragOverEvent('dragOverValid');
1900 if (Sortable$1.eventCanceled) return completedFired;
1901
1902 if (revert) {
1903 parentEl = rootEl; // actualization
1904
1905 capture();
1906
1907 this._hideClone();
1908
1909 dragOverEvent('revert');
1910
1911 if (!Sortable$1.eventCanceled) {
1912 if (nextEl) {
1913 rootEl.insertBefore(dragEl, nextEl);
1914 } else {
1915 rootEl.appendChild(dragEl);
1916 }
1917 }
1918
1919 return completed(true);
1920 }
1921
1922 var elLastChild = lastChild(el, options.draggable);
1923
1924 if (!elLastChild || _ghostIsLast(evt, vertical, this) && !elLastChild.animated) {
1925 // If already at end of list: Do not insert
1926 if (elLastChild === dragEl) {
1927 return completed(false);
1928 } // assign target only if condition is true
1929
1930
1931 if (elLastChild && el === evt.target) {
1932 target = elLastChild;
1933 }
1934
1935 if (target) {
1936 targetRect = getRect(target);
1937 }
1938
1939 if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, !!target) !== false) {
1940 capture();
1941 el.appendChild(dragEl);
1942 parentEl = el; // actualization
1943
1944 changed();
1945 return completed(true);
1946 }
1947 } else if (target.parentNode === el) {
1948 var direction = 0,
1949 targetBeforeFirstSwap,
1950 differentLevel = dragEl.parentNode !== el,
1951 side1 = vertical ? 'top' : 'left',
1952 scrolledPastTop = isScrolledPast(target, null, 'top', 'top') || isScrolledPast(dragEl, null, 'top', 'top'),
1953 scrollBefore = scrolledPastTop ? scrolledPastTop.scrollTop : void 0;
1954
1955 if (lastTarget !== target) {
1956 targetBeforeFirstSwap = getRect(target)[side1];
1957 pastFirstInvertThresh = false;
1958 isCircumstantialInvert = options.invertSwap || differentLevel;
1959 }
1960
1961 direction = _getSwapDirection(evt, target, vertical, options.swapThreshold, options.invertedSwapThreshold == null ? options.swapThreshold : options.invertedSwapThreshold, isCircumstantialInvert, lastTarget === target);
1962 var sibling;
1963
1964 if (direction !== 0) {
1965 // Check if target is beside dragEl in respective direction (ignoring hidden elements)
1966 var dragIndex = index(dragEl);
1967
1968 do {
1969 dragIndex -= direction;
1970 sibling = parentEl.children[dragIndex];
1971 } while (sibling && (css(sibling, 'display') === 'none' || sibling === ghostEl));
1972 } // If dragEl is already beside target: Do not insert
1973
1974
1975 if (direction === 0 || sibling === target) {
1976 return completed(false);
1977 }
1978
1979 lastTarget = target;
1980 lastDirection = direction;
1981 targetRect = getRect(target);
1982 var nextSibling = target.nextElementSibling,
1983 after = false;
1984 after = direction === 1;
1985
1986 var moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, after);
1987
1988 if (moveVector !== false) {
1989 if (moveVector === 1 || moveVector === -1) {
1990 after = moveVector === 1;
1991 }
1992
1993 _silent = true;
1994 setTimeout(_unsilent, 30);
1995 capture();
1996
1997 if (after && !nextSibling) {
1998 el.appendChild(dragEl);
1999 } else {
2000 target.parentNode.insertBefore(dragEl, after ? nextSibling : target);
2001 } // Undo chrome's scroll adjustment (has no effect on other browsers)
2002
2003
2004 if (scrolledPastTop) {
2005 scrollBy(scrolledPastTop, 0, scrollBefore - scrolledPastTop.scrollTop);
2006 }
2007
2008 parentEl = dragEl.parentNode; // actualization
2009 // must be done before animation
2010
2011 if (targetBeforeFirstSwap !== undefined && !isCircumstantialInvert) {
2012 targetMoveDistance = Math.abs(targetBeforeFirstSwap - getRect(target)[side1]);
2013 }
2014
2015 changed();
2016 return completed(true);
2017 }
2018 }
2019
2020 if (el.contains(dragEl)) {
2021 return completed(false);
2022 }
2023 }
2024
2025 return false;
2026 },
2027 _ignoreWhileAnimating: null,
2028 _offMoveEvents: function _offMoveEvents() {
2029 off(document, 'mousemove', this._onTouchMove);
2030 off(document, 'touchmove', this._onTouchMove);
2031 off(document, 'pointermove', this._onTouchMove);
2032 off(document, 'dragover', nearestEmptyInsertDetectEvent);
2033 off(document, 'mousemove', nearestEmptyInsertDetectEvent);
2034 off(document, 'touchmove', nearestEmptyInsertDetectEvent);
2035 },
2036 _offUpEvents: function _offUpEvents() {
2037 var ownerDocument = this.el.ownerDocument;
2038 off(ownerDocument, 'mouseup', this._onDrop);
2039 off(ownerDocument, 'touchend', this._onDrop);
2040 off(ownerDocument, 'pointerup', this._onDrop);
2041 off(ownerDocument, 'touchcancel', this._onDrop);
2042 off(document, 'selectstart', this);
2043 },
2044 _onDrop: function _onDrop(
2045 /**Event*/
2046 evt) {
2047 var el = this.el,
2048 options = this.options; // Get the index of the dragged element within its parent
2049
2050 newIndex = index(dragEl);
2051 newDraggableIndex = index(dragEl, options.draggable);
2052 pluginEvent('drop', this, {
2053 evt: evt
2054 }); // Get again after plugin event
2055
2056 newIndex = index(dragEl);
2057 newDraggableIndex = index(dragEl, options.draggable);
2058
2059 if (Sortable$1.eventCanceled) {
2060 this._nulling();
2061
2062 return;
2063 }
2064
2065 awaitingDragStarted = false;
2066 isCircumstantialInvert = false;
2067 pastFirstInvertThresh = false;
2068 clearInterval(this._loopId);
2069 clearTimeout(this._dragStartTimer);
2070
2071 _cancelNextTick(this.cloneId);
2072
2073 _cancelNextTick(this._dragStartId); // Unbind events
2074
2075
2076 if (this.nativeDraggable) {
2077 off(document, 'drop', this);
2078 off(el, 'dragstart', this._onDragStart);
2079 }
2080
2081 this._offMoveEvents();
2082
2083 this._offUpEvents();
2084
2085 if (Safari) {
2086 css(document.body, 'user-select', '');
2087 }
2088
2089 if (evt) {
2090 if (moved) {
2091 evt.cancelable && evt.preventDefault();
2092 !options.dropBubble && evt.stopPropagation();
2093 }
2094
2095 ghostEl && ghostEl.parentNode && ghostEl.parentNode.removeChild(ghostEl);
2096
2097 if (rootEl === parentEl || putSortable && putSortable.lastPutMode !== 'clone') {
2098 // Remove clone(s)
2099 cloneEl && cloneEl.parentNode && cloneEl.parentNode.removeChild(cloneEl);
2100 }
2101
2102 if (dragEl) {
2103 if (this.nativeDraggable) {
2104 off(dragEl, 'dragend', this);
2105 }
2106
2107 _disableDraggable(dragEl);
2108
2109 dragEl.style['will-change'] = ''; // Remove classes
2110 // ghostClass is added in dragStarted
2111
2112 if (moved && !awaitingDragStarted) {
2113 toggleClass(dragEl, putSortable ? putSortable.options.ghostClass : this.options.ghostClass, false);
2114 }
2115
2116 toggleClass(dragEl, this.options.chosenClass, false); // Drag stop event
2117
2118 _dispatchEvent({
2119 sortable: this,
2120 name: 'unchoose',
2121 toEl: parentEl,
2122 newIndex: null,
2123 newDraggableIndex: null,
2124 originalEvent: evt
2125 });
2126
2127 if (rootEl !== parentEl) {
2128 if (newIndex >= 0) {
2129 // Add event
2130 _dispatchEvent({
2131 rootEl: parentEl,
2132 name: 'add',
2133 toEl: parentEl,
2134 fromEl: rootEl,
2135 originalEvent: evt
2136 }); // Remove event
2137
2138
2139 _dispatchEvent({
2140 sortable: this,
2141 name: 'remove',
2142 toEl: parentEl,
2143 originalEvent: evt
2144 }); // drag from one list and drop into another
2145
2146
2147 _dispatchEvent({
2148 rootEl: parentEl,
2149 name: 'sort',
2150 toEl: parentEl,
2151 fromEl: rootEl,
2152 originalEvent: evt
2153 });
2154
2155 _dispatchEvent({
2156 sortable: this,
2157 name: 'sort',
2158 toEl: parentEl,
2159 originalEvent: evt
2160 });
2161 }
2162
2163 putSortable && putSortable.save();
2164 } else {
2165 if (newIndex !== oldIndex) {
2166 if (newIndex >= 0) {
2167 // drag & drop within the same list
2168 _dispatchEvent({
2169 sortable: this,
2170 name: 'update',
2171 toEl: parentEl,
2172 originalEvent: evt
2173 });
2174
2175 _dispatchEvent({
2176 sortable: this,
2177 name: 'sort',
2178 toEl: parentEl,
2179 originalEvent: evt
2180 });
2181 }
2182 }
2183 }
2184
2185 if (Sortable$1.active) {
2186 /* jshint eqnull:true */
2187 if (newIndex == null || newIndex === -1) {
2188 newIndex = oldIndex;
2189 newDraggableIndex = oldDraggableIndex;
2190 }
2191
2192 _dispatchEvent({
2193 sortable: this,
2194 name: 'end',
2195 toEl: parentEl,
2196 originalEvent: evt
2197 }); // Save sorting
2198
2199
2200 this.save();
2201 }
2202 }
2203 }
2204
2205 this._nulling();
2206 },
2207 _nulling: function _nulling() {
2208 pluginEvent('nulling', this);
2209 rootEl = dragEl = parentEl = ghostEl = nextEl = cloneEl = lastDownEl = cloneHidden = tapEvt = touchEvt = moved = newIndex = newDraggableIndex = oldIndex = oldDraggableIndex = lastTarget = lastDirection = putSortable = activeGroup = Sortable$1.dragged = Sortable$1.ghost = Sortable$1.clone = Sortable$1.active = null;
2210 savedInputChecked.forEach(function (el) {
2211 el.checked = true;
2212 });
2213 savedInputChecked.length = 0;
2214 },
2215 handleEvent: function handleEvent(
2216 /**Event*/
2217 evt) {
2218 switch (evt.type) {
2219 case 'drop':
2220 case 'dragend':
2221 this._onDrop(evt);
2222
2223 break;
2224
2225 case 'dragenter':
2226 case 'dragover':
2227 if (dragEl) {
2228 this._onDragOver(evt);
2229
2230 _globalDragOver(evt);
2231 }
2232
2233 break;
2234
2235 case 'selectstart':
2236 evt.preventDefault();
2237 break;
2238 }
2239 },
2240
2241 /**
2242 * Serializes the item into an array of string.
2243 * @returns {String[]}
2244 */
2245 toArray: function toArray() {
2246 var order = [],
2247 el,
2248 children = this.el.children,
2249 i = 0,
2250 n = children.length,
2251 options = this.options;
2252
2253 for (; i < n; i++) {
2254 el = children[i];
2255
2256 if (closest(el, options.draggable, this.el, false)) {
2257 order.push(el.getAttribute(options.dataIdAttr) || _generateId(el));
2258 }
2259 }
2260
2261 return order;
2262 },
2263
2264 /**
2265 * Sorts the elements according to the array.
2266 * @param {String[]} order order of the items
2267 */
2268 sort: function sort(order) {
2269 var items = {},
2270 rootEl = this.el;
2271 this.toArray().forEach(function (id, i) {
2272 var el = rootEl.children[i];
2273
2274 if (closest(el, this.options.draggable, rootEl, false)) {
2275 items[id] = el;
2276 }
2277 }, this);
2278 order.forEach(function (id) {
2279 if (items[id]) {
2280 rootEl.removeChild(items[id]);
2281 rootEl.appendChild(items[id]);
2282 }
2283 });
2284 },
2285
2286 /**
2287 * Save the current sorting
2288 */
2289 save: function save() {
2290 var store = this.options.store;
2291 store && store.set && store.set(this);
2292 },
2293
2294 /**
2295 * For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
2296 * @param {HTMLElement} el
2297 * @param {String} [selector] default: `options.draggable`
2298 * @returns {HTMLElement|null}
2299 */
2300 closest: function closest$1(el, selector) {
2301 return closest(el, selector || this.options.draggable, this.el, false);
2302 },
2303
2304 /**
2305 * Set/get option
2306 * @param {string} name
2307 * @param {*} [value]
2308 * @returns {*}
2309 */
2310 option: function option(name, value) {
2311 var options = this.options;
2312
2313 if (value === void 0) {
2314 return options[name];
2315 } else {
2316 var modifiedValue = PluginManager.modifyOption(this, name, value);
2317
2318 if (typeof modifiedValue !== 'undefined') {
2319 options[name] = modifiedValue;
2320 } else {
2321 options[name] = value;
2322 }
2323
2324 if (name === 'group') {
2325 _prepareGroup(options);
2326 }
2327 }
2328 },
2329
2330 /**
2331 * Destroy
2332 */
2333 destroy: function destroy() {
2334 pluginEvent('destroy', this);
2335 var el = this.el;
2336 el[expando] = null;
2337 off(el, 'mousedown', this._onTapStart);
2338 off(el, 'touchstart', this._onTapStart);
2339 off(el, 'pointerdown', this._onTapStart);
2340
2341 if (this.nativeDraggable) {
2342 off(el, 'dragover', this);
2343 off(el, 'dragenter', this);
2344 } // Remove draggable attributes
2345
2346
2347 Array.prototype.forEach.call(el.querySelectorAll('[draggable]'), function (el) {
2348 el.removeAttribute('draggable');
2349 });
2350
2351 this._onDrop();
2352
2353 sortables.splice(sortables.indexOf(this.el), 1);
2354 this.el = el = null;
2355 },
2356 _hideClone: function _hideClone() {
2357 if (!cloneHidden) {
2358 pluginEvent('hideClone', this);
2359 if (Sortable$1.eventCanceled) return;
2360 css(cloneEl, 'display', 'none');
2361
2362 if (this.options.removeCloneOnHide && cloneEl.parentNode) {
2363 cloneEl.parentNode.removeChild(cloneEl);
2364 }
2365
2366 cloneHidden = true;
2367 }
2368 },
2369 _showClone: function _showClone(putSortable) {
2370 if (putSortable.lastPutMode !== 'clone') {
2371 this._hideClone();
2372
2373 return;
2374 }
2375
2376 if (cloneHidden) {
2377 pluginEvent('showClone', this);
2378 if (Sortable$1.eventCanceled) return; // show clone at dragEl or original position
2379
2380 if (rootEl.contains(dragEl) && !this.options.group.revertClone) {
2381 rootEl.insertBefore(cloneEl, dragEl);
2382 } else if (nextEl) {
2383 rootEl.insertBefore(cloneEl, nextEl);
2384 } else {
2385 rootEl.appendChild(cloneEl);
2386 }
2387
2388 if (this.options.group.revertClone) {
2389 this._animate(dragEl, cloneEl);
2390 }
2391
2392 css(cloneEl, 'display', '');
2393 cloneHidden = false;
2394 }
2395 }
2396 };
2397
2398 function _globalDragOver(
2399 /**Event*/
2400 evt) {
2401 if (evt.dataTransfer) {
2402 evt.dataTransfer.dropEffect = 'move';
2403 }
2404
2405 evt.cancelable && evt.preventDefault();
2406 }
2407
2408 function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvent, willInsertAfter) {
2409 var evt,
2410 sortable = fromEl[expando],
2411 onMoveFn = sortable.options.onMove,
2412 retVal; // Support for new CustomEvent feature
2413
2414 if (window.CustomEvent && !IE11OrLess && !Edge) {
2415 evt = new CustomEvent('move', {
2416 bubbles: true,
2417 cancelable: true
2418 });
2419 } else {
2420 evt = document.createEvent('Event');
2421 evt.initEvent('move', true, true);
2422 }
2423
2424 evt.to = toEl;
2425 evt.from = fromEl;
2426 evt.dragged = dragEl;
2427 evt.draggedRect = dragRect;
2428 evt.related = targetEl || toEl;
2429 evt.relatedRect = targetRect || getRect(toEl);
2430 evt.willInsertAfter = willInsertAfter;
2431 evt.originalEvent = originalEvent;
2432 fromEl.dispatchEvent(evt);
2433
2434 if (onMoveFn) {
2435 retVal = onMoveFn.call(sortable, evt, originalEvent);
2436 }
2437
2438 return retVal;
2439 }
2440
2441 function _disableDraggable(el) {
2442 el.draggable = false;
2443 }
2444
2445 function _unsilent() {
2446 _silent = false;
2447 }
2448
2449 function _ghostIsLast(evt, vertical, sortable) {
2450 var elRect = getRect(lastChild(sortable.el, sortable.options.draggable)),
2451 mouseOnAxis = vertical ? evt.clientY : evt.clientX,
2452 mouseOnOppAxis = vertical ? evt.clientX : evt.clientY,
2453 targetS2 = vertical ? elRect.bottom : elRect.right,
2454 targetS1Opp = vertical ? elRect.left : elRect.top,
2455 targetS2Opp = vertical ? elRect.right : elRect.bottom,
2456 spacer = 10;
2457 return vertical ? mouseOnOppAxis > targetS2Opp + spacer || mouseOnOppAxis <= targetS2Opp && mouseOnAxis > targetS2 && mouseOnOppAxis >= targetS1Opp : mouseOnAxis > targetS2 && mouseOnOppAxis > targetS1Opp || mouseOnAxis <= targetS2 && mouseOnOppAxis > targetS2Opp + spacer;
2458 }
2459
2460 function _getSwapDirection(evt, target, vertical, swapThreshold, invertedSwapThreshold, invertSwap, isLastTarget) {
2461 var targetRect = getRect(target),
2462 mouseOnAxis = vertical ? evt.clientY : evt.clientX,
2463 targetLength = vertical ? targetRect.height : targetRect.width,
2464 targetS1 = vertical ? targetRect.top : targetRect.left,
2465 targetS2 = vertical ? targetRect.bottom : targetRect.right,
2466 invert = false;
2467
2468 if (!invertSwap) {
2469 // Never invert or create dragEl shadow when target movemenet causes mouse to move past the end of regular swapThreshold
2470 if (isLastTarget && targetMoveDistance < targetLength * swapThreshold) {
2471 // multiplied only by swapThreshold because mouse will already be inside target by (1 - threshold) * targetLength / 2
2472 // check if past first invert threshold on side opposite of lastDirection
2473 if (!pastFirstInvertThresh && (lastDirection === 1 ? mouseOnAxis > targetS1 + targetLength * invertedSwapThreshold / 2 : mouseOnAxis < targetS2 - targetLength * invertedSwapThreshold / 2)) {
2474 // past first invert threshold, do not restrict inverted threshold to dragEl shadow
2475 pastFirstInvertThresh = true;
2476 }
2477
2478 if (!pastFirstInvertThresh) {
2479 // dragEl shadow (target move distance shadow)
2480 if (lastDirection === 1 ? mouseOnAxis < targetS1 + targetMoveDistance // over dragEl shadow
2481 : mouseOnAxis > targetS2 - targetMoveDistance) {
2482 return -lastDirection;
2483 }
2484 } else {
2485 invert = true;
2486 }
2487 } else {
2488 // Regular
2489 if (mouseOnAxis > targetS1 + targetLength * (1 - swapThreshold) / 2 && mouseOnAxis < targetS2 - targetLength * (1 - swapThreshold) / 2) {
2490 return _getInsertDirection(target);
2491 }
2492 }
2493 }
2494
2495 invert = invert || invertSwap;
2496
2497 if (invert) {
2498 // Invert of regular
2499 if (mouseOnAxis < targetS1 + targetLength * invertedSwapThreshold / 2 || mouseOnAxis > targetS2 - targetLength * invertedSwapThreshold / 2) {
2500 return mouseOnAxis > targetS1 + targetLength / 2 ? 1 : -1;
2501 }
2502 }
2503
2504 return 0;
2505 }
2506 /**
2507 * Gets the direction dragEl must be swapped relative to target in order to make it
2508 * seem that dragEl has been "inserted" into that element's position
2509 * @param {HTMLElement} target The target whose position dragEl is being inserted at
2510 * @return {Number} Direction dragEl must be swapped
2511 */
2512
2513
2514 function _getInsertDirection(target) {
2515 var dragElIndex = index(dragEl),
2516 targetIndex = index(target);
2517
2518 if (dragElIndex < targetIndex) {
2519 return 1;
2520 } else {
2521 return -1;
2522 }
2523 }
2524 /**
2525 * Generate id
2526 * @param {HTMLElement} el
2527 * @returns {String}
2528 * @private
2529 */
2530
2531
2532 function _generateId(el) {
2533 var str = el.tagName + el.className + el.src + el.href + el.textContent,
2534 i = str.length,
2535 sum = 0;
2536
2537 while (i--) {
2538 sum += str.charCodeAt(i);
2539 }
2540
2541 return sum.toString(36);
2542 }
2543
2544 function _saveInputCheckedState(root) {
2545 savedInputChecked.length = 0;
2546 var inputs = root.getElementsByTagName('input');
2547 var idx = inputs.length;
2548
2549 while (idx--) {
2550 var _el = inputs[idx];
2551 _el.checked && savedInputChecked.push(_el);
2552 }
2553 }
2554
2555 function _nextTick(fn) {
2556 return setTimeout(fn, 0);
2557 }
2558
2559 function _cancelNextTick(id) {
2560 return clearTimeout(id);
2561 } // Fixed #973:
2562
2563
2564 on(document, 'touchmove', function (evt) {
2565 if ((Sortable$1.active || awaitingDragStarted) && evt.cancelable) {
2566 evt.preventDefault();
2567 }
2568 }); // Export utils
2569
2570 Sortable$1.utils = {
2571 on: on,
2572 off: off,
2573 css: css,
2574 find: find,
2575 is: function is(el, selector) {
2576 return !!closest(el, selector, el, false);
2577 },
2578 extend: extend,
2579 throttle: throttle,
2580 closest: closest,
2581 toggleClass: toggleClass,
2582 clone: clone,
2583 index: index,
2584 nextTick: _nextTick,
2585 cancelNextTick: _cancelNextTick,
2586 detectDirection: _detectDirection,
2587 getChild: getChild
2588 };
2589 /**
2590 * Mount a plugin to Sortable
2591 * @param {...SortablePlugin|SortablePlugin[]} plugins Plugins being mounted
2592 */
2593
2594 Sortable$1.mount = function () {
2595 for (var _len = arguments.length, plugins = new Array(_len), _key = 0; _key < _len; _key++) {
2596 plugins[_key] = arguments[_key];
2597 }
2598
2599 if (plugins[0].constructor === Array) plugins = plugins[0];
2600
2601 for (var i in plugins) {
2602 var plugin = plugins[i];
2603
2604 if (!plugin.prototype || !plugin.prototype.constructor) {
2605 throw "Sortable: Mounted plugin must be a constructor function, not ".concat({}.toString.call(el));
2606 }
2607
2608 if (plugin.utils) Sortable$1.utils = _objectSpread({}, Sortable$1.utils, plugin.utils);
2609 PluginManager.mount(plugin);
2610 }
2611 };
2612 /**
2613 * Create sortable instance
2614 * @param {HTMLElement} el
2615 * @param {Object} [options]
2616 */
2617
2618
2619 Sortable$1.create = function (el, options) {
2620 return new Sortable$1(el, options);
2621 }; // Export
2622
2623
2624 Sortable$1.version = version;
2625
2626 var autoScrolls = [],
2627 scrollEl,
2628 scrollRootEl,
2629 scrolling = false,
2630 lastAutoScrollX,
2631 lastAutoScrollY,
2632 touchEvt$1,
2633 pointerElemChangedInterval;
2634
2635 function AutoScrollPlugin() {
2636 function AutoScroll() {
2637 this.options = {
2638 scroll: true,
2639 scrollSensitivity: 30,
2640 scrollSpeed: 10,
2641 bubbleScroll: true
2642 }; // Bind all private methods
2643
2644 for (var fn in this) {
2645 if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {
2646 this[fn] = this[fn].bind(this);
2647 }
2648 }
2649 }
2650
2651 AutoScroll.prototype = {
2652 dragStarted: function dragStarted(_ref) {
2653 var originalEvent = _ref.originalEvent;
2654
2655 if (this.sortable.nativeDraggable) {
2656 on(document, 'dragover', this._handleAutoScroll);
2657 } else {
2658 if (this.sortable.options.supportPointer) {
2659 on(document, 'pointermove', this._handleFallbackAutoScroll);
2660 } else if (originalEvent.touches) {
2661 on(document, 'touchmove', this._handleFallbackAutoScroll);
2662 } else {
2663 on(document, 'mousemove', this._handleFallbackAutoScroll);
2664 }
2665 }
2666 },
2667 dragOverCompleted: function dragOverCompleted(_ref2) {
2668 var originalEvent = _ref2.originalEvent;
2669
2670 // For when bubbling is canceled and using fallback (fallback 'touchmove' always reached)
2671 if (!this.sortable.options.dragOverBubble && !originalEvent.rootEl) {
2672 this._handleAutoScroll(originalEvent);
2673 }
2674 },
2675 drop: function drop() {
2676 if (this.sortable.nativeDraggable) {
2677 off(document, 'dragover', this._handleAutoScroll);
2678 } else {
2679 off(document, 'pointermove', this._handleFallbackAutoScroll);
2680 off(document, 'touchmove', this._handleFallbackAutoScroll);
2681 off(document, 'mousemove', this._handleFallbackAutoScroll);
2682 }
2683
2684 clearPointerElemChangedInterval();
2685 clearAutoScrolls();
2686 cancelThrottle();
2687 },
2688 nulling: function nulling() {
2689 touchEvt$1 = scrollRootEl = scrollEl = scrolling = pointerElemChangedInterval = lastAutoScrollX = lastAutoScrollY = null;
2690 autoScrolls.length = 0;
2691 },
2692 _handleFallbackAutoScroll: function _handleFallbackAutoScroll(evt) {
2693 this._handleAutoScroll(evt, true);
2694 },
2695 _handleAutoScroll: function _handleAutoScroll(evt, fallback) {
2696 var _this = this;
2697
2698 var x = evt.clientX,
2699 y = evt.clientY,
2700 elem = document.elementFromPoint(x, y);
2701 touchEvt$1 = evt; // IE does not seem to have native autoscroll,
2702 // Edge's autoscroll seems too conditional,
2703 // MACOS Safari does not have autoscroll,
2704 // Firefox and Chrome are good
2705
2706 if (fallback || Edge || IE11OrLess || Safari) {
2707 autoScroll(evt, this.options, elem, fallback); // Listener for pointer element change
2708
2709 var ogElemScroller = getParentAutoScrollElement(elem, true);
2710
2711 if (scrolling && (!pointerElemChangedInterval || x !== lastAutoScrollX || y !== lastAutoScrollY)) {
2712 pointerElemChangedInterval && clearPointerElemChangedInterval(); // Detect for pointer elem change, emulating native DnD behaviour
2713
2714 pointerElemChangedInterval = setInterval(function () {
2715 var newElem = getParentAutoScrollElement(document.elementFromPoint(x, y), true);
2716
2717 if (newElem !== ogElemScroller) {
2718 ogElemScroller = newElem;
2719 clearAutoScrolls();
2720 }
2721
2722 autoScroll(evt, _this.options, newElem, fallback);
2723 }, 10);
2724 lastAutoScrollX = x;
2725 lastAutoScrollY = y;
2726 }
2727 } else {
2728 // if DnD is enabled (and browser has good autoscrolling), first autoscroll will already scroll, so get parent autoscroll of first autoscroll
2729 if (!this.sortable.options.bubbleScroll || getParentAutoScrollElement(elem, true) === getWindowScrollingElement()) {
2730 clearAutoScrolls();
2731 return;
2732 }
2733
2734 autoScroll(evt, this.options, getParentAutoScrollElement(elem, false), false);
2735 }
2736 }
2737 };
2738 return _extends(AutoScroll, {
2739 pluginName: 'scroll',
2740 initializeByDefault: true
2741 });
2742 }
2743
2744 function clearAutoScrolls() {
2745 autoScrolls.forEach(function (autoScroll) {
2746 clearInterval(autoScroll.pid);
2747 });
2748 autoScrolls = [];
2749 }
2750
2751 function clearPointerElemChangedInterval() {
2752 clearInterval(pointerElemChangedInterval);
2753 }
2754
2755 var autoScroll = throttle(function (evt, options, rootEl, isFallback) {
2756 // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521
2757 if (!options.scroll) return;
2758 var sens = options.scrollSensitivity,
2759 speed = options.scrollSpeed,
2760 winScroller = getWindowScrollingElement();
2761 var scrollThisInstance = false,
2762 scrollCustomFn; // New scroll root, set scrollEl
2763
2764 if (scrollRootEl !== rootEl) {
2765 scrollRootEl = rootEl;
2766 clearAutoScrolls();
2767 scrollEl = options.scroll;
2768 scrollCustomFn = options.scrollFn;
2769
2770 if (scrollEl === true) {
2771 scrollEl = getParentAutoScrollElement(rootEl, true);
2772 }
2773 }
2774
2775 var layersOut = 0;
2776 var currentParent = scrollEl;
2777
2778 do {
2779 var el = currentParent,
2780 rect = getRect(el),
2781 top = rect.top,
2782 bottom = rect.bottom,
2783 left = rect.left,
2784 right = rect.right,
2785 width = rect.width,
2786 height = rect.height,
2787 canScrollX = void 0,
2788 canScrollY = void 0,
2789 scrollWidth = el.scrollWidth,
2790 scrollHeight = el.scrollHeight,
2791 elCSS = css(el),
2792 scrollPosX = el.scrollLeft,
2793 scrollPosY = el.scrollTop;
2794
2795 if (el === winScroller) {
2796 canScrollX = width < scrollWidth && (elCSS.overflowX === 'auto' || elCSS.overflowX === 'scroll' || elCSS.overflowX === 'visible');
2797 canScrollY = height < scrollHeight && (elCSS.overflowY === 'auto' || elCSS.overflowY === 'scroll' || elCSS.overflowY === 'visible');
2798 } else {
2799 canScrollX = width < scrollWidth && (elCSS.overflowX === 'auto' || elCSS.overflowX === 'scroll');
2800 canScrollY = height < scrollHeight && (elCSS.overflowY === 'auto' || elCSS.overflowY === 'scroll');
2801 }
2802
2803 var vx = canScrollX && (Math.abs(right - evt.clientX) <= sens && scrollPosX + width < scrollWidth) - (Math.abs(left - evt.clientX) <= sens && !!scrollPosX);
2804 var vy = canScrollY && (Math.abs(bottom - evt.clientY) <= sens && scrollPosY + height < scrollHeight) - (Math.abs(top - evt.clientY) <= sens && !!scrollPosY);
2805
2806 if (!autoScrolls[layersOut]) {
2807 for (var i = 0; i <= layersOut; i++) {
2808 if (!autoScrolls[i]) {
2809 autoScrolls[i] = {};
2810 }
2811 }
2812 }
2813
2814 if (autoScrolls[layersOut].vx != vx || autoScrolls[layersOut].vy != vy || autoScrolls[layersOut].el !== el) {
2815 autoScrolls[layersOut].el = el;
2816 autoScrolls[layersOut].vx = vx;
2817 autoScrolls[layersOut].vy = vy;
2818 clearInterval(autoScrolls[layersOut].pid);
2819
2820 if (vx != 0 || vy != 0) {
2821 scrollThisInstance = true;
2822 /* jshint loopfunc:true */
2823
2824 autoScrolls[layersOut].pid = setInterval(function () {
2825 // emulate drag over during autoscroll (fallback), emulating native DnD behaviour
2826 if (isFallback && this.layer === 0) {
2827 Sortable.active._onTouchMove(touchEvt$1); // To move ghost if it is positioned absolutely
2828
2829 }
2830
2831 var scrollOffsetY = autoScrolls[this.layer].vy ? autoScrolls[this.layer].vy * speed : 0;
2832 var scrollOffsetX = autoScrolls[this.layer].vx ? autoScrolls[this.layer].vx * speed : 0;
2833
2834 if (typeof scrollCustomFn === 'function') {
2835 if (scrollCustomFn.call(Sortable.dragged.parentNode[expando], scrollOffsetX, scrollOffsetY, evt, touchEvt$1, autoScrolls[this.layer].el) !== 'continue') {
2836 return;
2837 }
2838 }
2839
2840 scrollBy(autoScrolls[this.layer].el, scrollOffsetX, scrollOffsetY);
2841 }.bind({
2842 layer: layersOut
2843 }), 24);
2844 }
2845 }
2846
2847 layersOut++;
2848 } while (options.bubbleScroll && currentParent !== winScroller && (currentParent = getParentAutoScrollElement(currentParent, false)));
2849
2850 scrolling = scrollThisInstance; // in case another function catches scrolling as false in between when it is not
2851 }, 30);
2852
2853 var drop = function drop(_ref) {
2854 var originalEvent = _ref.originalEvent,
2855 putSortable = _ref.putSortable,
2856 dragEl = _ref.dragEl,
2857 activeSortable = _ref.activeSortable,
2858 dispatchSortableEvent = _ref.dispatchSortableEvent,
2859 hideGhostForTarget = _ref.hideGhostForTarget,
2860 unhideGhostForTarget = _ref.unhideGhostForTarget;
2861 var toSortable = putSortable || activeSortable;
2862 hideGhostForTarget();
2863 var target = document.elementFromPoint(originalEvent.clientX, originalEvent.clientY);
2864 unhideGhostForTarget();
2865
2866 if (toSortable && !toSortable.el.contains(target)) {
2867 dispatchSortableEvent('spill');
2868 this.onSpill(dragEl);
2869 }
2870 };
2871
2872 function Revert() {}
2873
2874 Revert.prototype = {
2875 startIndex: null,
2876 dragStart: function dragStart(_ref2) {
2877 var oldDraggableIndex = _ref2.oldDraggableIndex;
2878 this.startIndex = oldDraggableIndex;
2879 },
2880 onSpill: function onSpill(dragEl) {
2881 this.sortable.captureAnimationState();
2882 var nextSibling = getChild(this.sortable.el, this.startIndex, this.sortable.options);
2883
2884 if (nextSibling) {
2885 this.sortable.el.insertBefore(dragEl, nextSibling);
2886 } else {
2887 this.sortable.el.appendChild(dragEl);
2888 }
2889
2890 this.sortable.animateAll();
2891 },
2892 drop: drop
2893 };
2894
2895 _extends(Revert, {
2896 pluginName: 'revertOnSpill'
2897 });
2898
2899 function Remove() {}
2900
2901 Remove.prototype = {
2902 onSpill: function onSpill(dragEl) {
2903 this.sortable.captureAnimationState();
2904 dragEl.parentNode && dragEl.parentNode.removeChild(dragEl);
2905 this.sortable.animateAll();
2906 },
2907 drop: drop
2908 };
2909
2910 _extends(Remove, {
2911 pluginName: 'removeOnSpill'
2912 });
2913
2914 var lastSwapEl;
2915
2916 function SwapPlugin() {
2917 function Swap() {
2918 this.options = {
2919 swapClass: 'sortable-swap-highlight'
2920 };
2921 }
2922
2923 Swap.prototype = {
2924 dragStart: function dragStart(_ref) {
2925 var dragEl = _ref.dragEl;
2926 lastSwapEl = dragEl;
2927 },
2928 dragOverValid: function dragOverValid(_ref2) {
2929 var completed = _ref2.completed,
2930 target = _ref2.target,
2931 onMove = _ref2.onMove,
2932 activeSortable = _ref2.activeSortable,
2933 changed = _ref2.changed;
2934 if (!activeSortable.options.swap) return;
2935 var el = this.sortable.el,
2936 options = this.sortable.options;
2937
2938 if (target && target !== el) {
2939 var prevSwapEl = lastSwapEl;
2940
2941 if (onMove(target) !== false) {
2942 toggleClass(target, options.swapClass, true);
2943 lastSwapEl = target;
2944 } else {
2945 lastSwapEl = null;
2946 }
2947
2948 if (prevSwapEl && prevSwapEl !== lastSwapEl) {
2949 toggleClass(prevSwapEl, options.swapClass, false);
2950 }
2951 }
2952
2953 changed();
2954 return completed(true);
2955 },
2956 drop: function drop(_ref3) {
2957 var activeSortable = _ref3.activeSortable,
2958 putSortable = _ref3.putSortable,
2959 dragEl = _ref3.dragEl;
2960 var toSortable = putSortable || this.sortable;
2961 var options = this.sortable.options;
2962 lastSwapEl && toggleClass(lastSwapEl, options.swapClass, false);
2963
2964 if (lastSwapEl && (options.swap || putSortable && putSortable.options.swap)) {
2965 if (dragEl !== lastSwapEl) {
2966 toSortable.captureAnimationState();
2967 if (toSortable !== activeSortable) activeSortable.captureAnimationState();
2968 swapNodes(dragEl, lastSwapEl);
2969 toSortable.animateAll();
2970 if (toSortable !== activeSortable) activeSortable.animateAll();
2971 }
2972 }
2973 },
2974 nulling: function nulling() {
2975 lastSwapEl = null;
2976 }
2977 };
2978 return _extends(Swap, {
2979 pluginName: 'swap',
2980 eventOptions: function eventOptions() {
2981 return {
2982 swapItem: lastSwapEl
2983 };
2984 }
2985 });
2986 }
2987
2988 function swapNodes(n1, n2) {
2989 var p1 = n1.parentNode,
2990 p2 = n2.parentNode,
2991 i1,
2992 i2;
2993 if (!p1 || !p2 || p1.isEqualNode(n2) || p2.isEqualNode(n1)) return;
2994 i1 = index(n1);
2995 i2 = index(n2);
2996
2997 if (p1.isEqualNode(p2) && i1 < i2) {
2998 i2++;
2999 }
3000
3001 p1.insertBefore(n2, p1.children[i1]);
3002 p2.insertBefore(n1, p2.children[i2]);
3003 }
3004
3005 var multiDragElements = [],
3006 multiDragClones = [],
3007 lastMultiDragSelect,
3008 // for selection with modifier key down (SHIFT)
3009 multiDragSortable,
3010 initialFolding = false,
3011 // Initial multi-drag fold when drag started
3012 folding = false,
3013 // Folding any other time
3014 dragStarted = false,
3015 dragEl$1,
3016 clonesFromRect,
3017 clonesHidden;
3018
3019 function MultiDragPlugin() {
3020 function MultiDrag(sortable) {
3021 // Bind all private methods
3022 for (var fn in this) {
3023 if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {
3024 this[fn] = this[fn].bind(this);
3025 }
3026 }
3027
3028 if (sortable.options.supportPointer) {
3029 on(document, 'pointerup', this._deselectMultiDrag);
3030 } else {
3031 on(document, 'mouseup', this._deselectMultiDrag);
3032 on(document, 'touchend', this._deselectMultiDrag);
3033 }
3034
3035 on(document, 'keydown', this._checkKeyDown);
3036 on(document, 'keyup', this._checkKeyUp);
3037 this.options = {
3038 selectedClass: 'sortable-selected',
3039 multiDragKey: null,
3040 setData: function setData(dataTransfer, dragEl) {
3041 var data = '';
3042
3043 if (multiDragElements.length && multiDragSortable === sortable) {
3044 for (var i in multiDragElements) {
3045 data += (!i ? '' : ', ') + multiDragElements[i].textContent;
3046 }
3047 } else {
3048 data = dragEl.textContent;
3049 }
3050
3051 dataTransfer.setData('Text', data);
3052 }
3053 };
3054 }
3055
3056 MultiDrag.prototype = {
3057 multiDragKeyDown: false,
3058 isMultiDrag: false,
3059 delayStartGlobal: function delayStartGlobal(_ref) {
3060 var dragged = _ref.dragEl;
3061 dragEl$1 = dragged;
3062 },
3063 delayEnded: function delayEnded() {
3064 this.isMultiDrag = ~multiDragElements.indexOf(dragEl$1);
3065 },
3066 setupClone: function setupClone(_ref2) {
3067 var sortable = _ref2.sortable;
3068 if (!this.isMultiDrag) return;
3069
3070 for (var i in multiDragElements) {
3071 multiDragClones.push(clone(multiDragElements[i]));
3072 multiDragClones[i].sortableIndex = multiDragElements[i].sortableIndex;
3073 multiDragClones[i].draggable = false;
3074 multiDragClones[i].style['will-change'] = '';
3075 toggleClass(multiDragClones[i], sortable.options.selectedClass, false);
3076 multiDragElements[i] === dragEl$1 && toggleClass(multiDragClones[i], sortable.options.chosenClass, false);
3077 }
3078
3079 sortable._hideClone();
3080
3081 return true;
3082 },
3083 clone: function clone(_ref3) {
3084 var sortable = _ref3.sortable,
3085 rootEl = _ref3.rootEl,
3086 dispatchSortableEvent = _ref3.dispatchSortableEvent;
3087 if (!this.isMultiDrag) return;
3088
3089 if (!sortable.options.removeCloneOnHide) {
3090 if (multiDragElements.length && multiDragSortable === sortable) {
3091 insertMultiDragClones(true, rootEl);
3092 dispatchSortableEvent('clone');
3093 return true;
3094 }
3095 }
3096 },
3097 showClone: function showClone(_ref4) {
3098 var cloneNowShown = _ref4.cloneNowShown,
3099 rootEl = _ref4.rootEl;
3100 if (!this.isMultiDrag) return;
3101 insertMultiDragClones(false, rootEl);
3102
3103 for (var i in multiDragClones) {
3104 css(multiDragClones[i], 'display', '');
3105 }
3106
3107 cloneNowShown();
3108 clonesHidden = false;
3109 return true;
3110 },
3111 hideClone: function hideClone(_ref5) {
3112 var sortable = _ref5.sortable,
3113 cloneNowHidden = _ref5.cloneNowHidden;
3114 if (!this.isMultiDrag) return;
3115
3116 for (var i in multiDragClones) {
3117 css(multiDragClones[i], 'display', 'none');
3118
3119 if (sortable.options.removeCloneOnHide && multiDragClones[i].parentNode) {
3120 multiDragClones[i].parentNode.removeChild(multiDragClones[i]);
3121 }
3122 }
3123
3124 cloneNowHidden();
3125 clonesHidden = true;
3126 return true;
3127 },
3128 dragStartGlobal: function dragStartGlobal(_ref6) {
3129 var sortable = _ref6.sortable;
3130
3131 if (!this.isMultiDrag && multiDragSortable) {
3132 multiDragSortable.multiDrag._deselectMultiDrag();
3133 }
3134
3135 for (var i in multiDragElements) {
3136 multiDragElements[i].sortableIndex = index(multiDragElements[i]);
3137 } // Sort multi-drag elements
3138
3139
3140 multiDragElements = multiDragElements.sort(function (a, b) {
3141 return a.sortableIndex - b.sortableIndex;
3142 });
3143 dragStarted = true;
3144 },
3145 dragStarted: function dragStarted(_ref7) {
3146 var sortable = _ref7.sortable;
3147 if (!this.isMultiDrag) return;
3148
3149 if (sortable.options.sort) {
3150 // Capture rects,
3151 // hide multi drag elements (by positioning them absolute),
3152 // set multi drag elements rects to dragRect,
3153 // show multi drag elements,
3154 // animate to rects,
3155 // unset rects & remove from DOM
3156 sortable.captureAnimationState();
3157
3158 if (sortable.options.animation) {
3159 for (var i in multiDragElements) {
3160 if (multiDragElements[i] === dragEl$1) continue;
3161 css(multiDragElements[i], 'position', 'absolute');
3162 }
3163
3164 var dragRect = getRect(dragEl$1, false, true, true);
3165
3166 for (var _i in multiDragElements) {
3167 if (multiDragElements[_i] === dragEl$1) continue;
3168 setRect(multiDragElements[_i], dragRect);
3169 }
3170
3171 folding = true;
3172 initialFolding = true;
3173 }
3174 }
3175
3176 sortable.animateAll(function () {
3177 folding = false;
3178 initialFolding = false;
3179
3180 if (sortable.options.animation) {
3181 for (var _i2 in multiDragElements) {
3182 unsetRect(multiDragElements[_i2]);
3183 }
3184 } // Remove all auxiliary multidrag items from el, if sorting enabled
3185
3186
3187 if (sortable.options.sort) {
3188 removeMultiDragElements();
3189 }
3190 });
3191 },
3192 dragOver: function dragOver(_ref8) {
3193 var target = _ref8.target,
3194 completed = _ref8.completed;
3195
3196 if (folding && ~multiDragElements.indexOf(target)) {
3197 return completed(false);
3198 }
3199 },
3200 revert: function revert(_ref9) {
3201 var fromSortable = _ref9.fromSortable,
3202 rootEl = _ref9.rootEl,
3203 sortable = _ref9.sortable,
3204 dragRect = _ref9.dragRect;
3205
3206 if (multiDragElements.length > 1) {
3207 // Setup unfold animation
3208 for (var i in multiDragElements) {
3209 sortable.addAnimationState({
3210 target: multiDragElements[i],
3211 rect: folding ? getRect(multiDragElements[i]) : dragRect
3212 });
3213 unsetRect(multiDragElements[i]);
3214 multiDragElements[i].fromRect = dragRect;
3215 fromSortable.removeAnimationState(multiDragElements[i]);
3216 }
3217
3218 folding = false;
3219 insertMultiDragElements(!sortable.options.removeCloneOnHide, rootEl);
3220 }
3221 },
3222 dragOverCompleted: function dragOverCompleted(_ref10) {
3223 var sortable = _ref10.sortable,
3224 isOwner = _ref10.isOwner,
3225 insertion = _ref10.insertion,
3226 activeSortable = _ref10.activeSortable,
3227 parentEl = _ref10.parentEl,
3228 putSortable = _ref10.putSortable;
3229 var options = sortable.options;
3230
3231 if (insertion) {
3232 // Clones must be hidden before folding animation to capture dragRectAbsolute properly
3233 if (isOwner) {
3234 activeSortable._hideClone();
3235 }
3236
3237 initialFolding = false; // If leaving sort:false root, or already folding - Fold to new location
3238
3239 if (options.animation && multiDragElements.length > 1 && (folding || !isOwner && !activeSortable.options.sort && !putSortable)) {
3240 // Fold: Set all multi drag elements's rects to dragEl's rect when multi-drag elements are invisible
3241 var dragRectAbsolute = getRect(dragEl$1, false, true, true);
3242
3243 for (var i in multiDragElements) {
3244 if (multiDragElements[i] === dragEl$1) continue;
3245 setRect(multiDragElements[i], dragRectAbsolute); // Move element(s) to end of parentEl so that it does not interfere with multi-drag clones insertion if they are inserted
3246 // while folding, and so that we can capture them again because old sortable will no longer be fromSortable
3247
3248 parentEl.appendChild(multiDragElements[i]);
3249 }
3250
3251 folding = true;
3252 } // Clones must be shown (and check to remove multi drags) after folding when interfering multiDragElements are moved out
3253
3254
3255 if (!isOwner) {
3256 // Only remove if not folding (folding will remove them anyways)
3257 if (!folding) {
3258 removeMultiDragElements();
3259 }
3260
3261 if (multiDragElements.length > 1) {
3262 var clonesHiddenBefore = clonesHidden;
3263
3264 activeSortable._showClone(sortable); // Unfold animation for clones if showing from hidden
3265
3266
3267 if (activeSortable.options.animation && !clonesHidden && clonesHiddenBefore) {
3268 for (var _i3 in multiDragClones) {
3269 activeSortable.addAnimationState({
3270 target: multiDragClones[_i3],
3271 rect: clonesFromRect
3272 });
3273 multiDragClones[_i3].fromRect = clonesFromRect;
3274 multiDragClones[_i3].thisAnimationDuration = null;
3275 }
3276 }
3277 } else {
3278 activeSortable._showClone(sortable);
3279 }
3280 }
3281 }
3282 },
3283 dragOverAnimationCapture: function dragOverAnimationCapture(_ref11) {
3284 var dragRect = _ref11.dragRect,
3285 isOwner = _ref11.isOwner,
3286 activeSortable = _ref11.activeSortable;
3287
3288 for (var i in multiDragElements) {
3289 multiDragElements[i].thisAnimationDuration = null;
3290 }
3291
3292 if (activeSortable.options.animation && !isOwner && activeSortable.multiDrag.isMultiDrag) {
3293 clonesFromRect = _extends({}, dragRect);
3294 var dragMatrix = matrix(dragEl$1, true);
3295 clonesFromRect.top -= dragMatrix.f;
3296 clonesFromRect.left -= dragMatrix.e;
3297 }
3298 },
3299 dragOverAnimationComplete: function dragOverAnimationComplete() {
3300 if (folding) {
3301 folding = false;
3302 removeMultiDragElements();
3303 }
3304 },
3305 drop: function drop(_ref12) {
3306 var evt = _ref12.originalEvent,
3307 rootEl = _ref12.rootEl,
3308 parentEl = _ref12.parentEl,
3309 sortable = _ref12.sortable,
3310 dispatchSortableEvent = _ref12.dispatchSortableEvent,
3311 oldIndex = _ref12.oldIndex,
3312 putSortable = _ref12.putSortable;
3313 var toSortable = putSortable || this.sortable;
3314 if (!evt) return;
3315 var options = sortable.options,
3316 children = parentEl.children; // Multi-drag selection
3317
3318 if (!dragStarted) {
3319 if (options.multiDragKey && !this.multiDragKeyDown) {
3320 this._deselectMultiDrag();
3321 }
3322
3323 toggleClass(dragEl$1, options.selectedClass, !~multiDragElements.indexOf(dragEl$1));
3324
3325 if (!~multiDragElements.indexOf(dragEl$1)) {
3326 multiDragElements.push(dragEl$1);
3327 dispatchEvent({
3328 sortable: sortable,
3329 rootEl: rootEl,
3330 name: 'select',
3331 targetEl: dragEl$1,
3332 originalEvt: evt
3333 }); // Modifier activated, select from last to dragEl
3334
3335 if ((!options.multiDragKey || this.multiDragKeyDown) && evt.shiftKey && lastMultiDragSelect && sortable.el.contains(lastMultiDragSelect)) {
3336 var lastIndex = index(lastMultiDragSelect),
3337 currentIndex = index(dragEl$1);
3338
3339 if (~lastIndex && ~currentIndex && lastIndex !== currentIndex) {
3340 // Must include lastMultiDragSelect (select it), in case modified selection from no selection
3341 // (but previous selection existed)
3342 var n, i;
3343
3344 if (currentIndex > lastIndex) {
3345 i = lastIndex;
3346 n = currentIndex;
3347 } else {
3348 i = currentIndex;
3349 n = lastIndex + 1;
3350 }
3351
3352 for (; i < n; i++) {
3353 if (~multiDragElements.indexOf(children[i])) continue;
3354 toggleClass(children[i], options.selectedClass, true);
3355 multiDragElements.push(children[i]);
3356 dispatchEvent({
3357 sortable: sortable,
3358 rootEl: rootEl,
3359 name: 'select',
3360 targetEl: children[i],
3361 originalEvt: evt
3362 });
3363 }
3364 }
3365 } else {
3366 lastMultiDragSelect = dragEl$1;
3367 }
3368
3369 multiDragSortable = toSortable;
3370 } else {
3371 multiDragElements.splice(multiDragElements.indexOf(dragEl$1), 1);
3372 lastMultiDragSelect = null;
3373 dispatchEvent({
3374 sortable: sortable,
3375 rootEl: rootEl,
3376 name: 'deselect',
3377 targetEl: dragEl$1,
3378 originalEvt: evt
3379 });
3380 }
3381 } // Multi-drag drop
3382
3383
3384 if (dragStarted && this.isMultiDrag) {
3385 // Do not "unfold" after around dragEl if reverted
3386 if ((parentEl[expando].options.sort || parentEl !== rootEl) && multiDragElements.length > 1) {
3387 var dragRect = getRect(dragEl$1),
3388 multiDragIndex = index(dragEl$1, ':not(.' + Sortable.active.options.selectedClass + ')');
3389 if (!initialFolding && options.animation) dragEl$1.thisAnimationDuration = null;
3390 toSortable.captureAnimationState();
3391
3392 if (!initialFolding) {
3393 if (options.animation) {
3394 dragEl$1.fromRect = dragRect;
3395
3396 for (var _i4 in multiDragElements) {
3397 multiDragElements[_i4].thisAnimationDuration = null;
3398
3399 if (multiDragElements[_i4] !== dragEl$1) {
3400 var rect = folding ? getRect(multiDragElements[_i4]) : dragRect;
3401 multiDragElements[_i4].fromRect = rect; // Prepare unfold animation
3402
3403 toSortable.addAnimationState({
3404 target: multiDragElements[_i4],
3405 rect: rect
3406 });
3407 }
3408 }
3409 } // Multi drag elements are not necessarily removed from the DOM on drop, so to reinsert
3410 // properly they must all be removed
3411
3412
3413 removeMultiDragElements();
3414
3415 for (var _i5 in multiDragElements) {
3416 if (children[multiDragIndex]) {
3417 parentEl.insertBefore(multiDragElements[_i5], children[multiDragIndex]);
3418 } else {
3419 parentEl.appendChild(multiDragElements[_i5]);
3420 }
3421
3422 multiDragIndex++;
3423 } // If initial folding is done, the elements may have changed position because they are now
3424 // unfolding around dragEl, even though dragEl may not have his index changed, so update event
3425 // must be fired here as Sortable will not.
3426
3427
3428 if (oldIndex === index(dragEl$1)) {
3429 var update = false;
3430
3431 for (var _i6 in multiDragElements) {
3432 if (multiDragElements[_i6].sortableIndex !== index(multiDragElements[_i6])) {
3433 update = true;
3434 break;
3435 }
3436 }
3437
3438 if (update) {
3439 dispatchSortableEvent('update');
3440 }
3441 }
3442 } // Must be done after capturing individual rects (scroll bar)
3443
3444
3445 for (var _i7 in multiDragElements) {
3446 unsetRect(multiDragElements[_i7]);
3447 }
3448
3449 toSortable.animateAll();
3450 }
3451
3452 multiDragSortable = toSortable;
3453 } // Remove clones if necessary
3454
3455
3456 if (rootEl === parentEl || putSortable && putSortable.lastPutMode !== 'clone') {
3457 for (var _i8 in multiDragClones) {
3458 multiDragClones[_i8].parentNode && multiDragClones[_i8].parentNode.removeChild(multiDragClones[_i8]);
3459 }
3460 }
3461 },
3462 nullingGlobal: function nullingGlobal() {
3463 this.isMultiDrag = dragStarted = false;
3464 multiDragClones.length = 0;
3465 },
3466 destroy: function destroy() {
3467 this._deselectMultiDrag();
3468
3469 off(document, 'pointerup', this._deselectMultiDrag);
3470 off(document, 'mouseup', this._deselectMultiDrag);
3471 off(document, 'touchend', this._deselectMultiDrag);
3472 off(document, 'keydown', this._checkKeyDown);
3473 off(document, 'keyup', this._checkKeyUp);
3474 },
3475 _deselectMultiDrag: function _deselectMultiDrag(evt) {
3476 if (dragStarted) return; // Only deselect if selection is in this sortable
3477
3478 if (multiDragSortable !== this.sortable) return; // Only deselect if target is not item in this sortable
3479
3480 if (evt && closest(evt.target, this.sortable.options.draggable, this.sortable.el, false)) return; // Only deselect if left click
3481
3482 if (evt && evt.button !== 0) return;
3483
3484 while (multiDragElements.length) {
3485 var el = multiDragElements[0];
3486 toggleClass(el, this.sortable.options.selectedClass, false);
3487 multiDragElements.shift();
3488 dispatchEvent({
3489 sortable: this.sortable,
3490 rootEl: this.sortable.el,
3491 name: 'deselect',
3492 targetEl: el,
3493 originalEvt: evt
3494 });
3495 }
3496 },
3497 _checkKeyDown: function _checkKeyDown(evt) {
3498 if (evt.key === this.sortable.options.multiDragKey) {
3499 this.multiDragKeyDown = true;
3500 }
3501 },
3502 _checkKeyUp: function _checkKeyUp(evt) {
3503 if (evt.key === this.sortable.options.multiDragKey) {
3504 this.multiDragKeyDown = false;
3505 }
3506 }
3507 };
3508 return _extends(MultiDrag, {
3509 // Static methods & properties
3510 pluginName: 'multiDrag',
3511 utils: {
3512 /**
3513 * Selects the provided multi-drag item
3514 * @param {HTMLElement} el The element to be selected
3515 */
3516 select: function select(el) {
3517 var sortable = el.parentNode[expando];
3518 if (!sortable || !sortable.options.multiDrag || ~multiDragElements.indexOf(el)) return;
3519
3520 if (multiDragSortable && multiDragSortable !== sortable) {
3521 multiDragSortable.multiDrag._deselectMultiDrag();
3522
3523 multiDragSortable = sortable;
3524 }
3525
3526 toggleClass(el, sortable.options.selectedClass, true);
3527 multiDragElements.push(el);
3528 },
3529
3530 /**
3531 * Deselects the provided multi-drag item
3532 * @param {HTMLElement} el The element to be deselected
3533 */
3534 deselect: function deselect(el) {
3535 var sortable = el.parentNode[expando],
3536 index = multiDragElements.indexOf(el);
3537 if (!sortable || !sortable.options.multiDrag || !~index) return;
3538 toggleClass(el, sortable.options.selectedClass, false);
3539 multiDragElements.splice(index, 1);
3540 }
3541 },
3542 eventOptions: function eventOptions() {
3543 return {
3544 items: _toConsumableArray(multiDragElements),
3545 clones: [].concat(multiDragClones)
3546 };
3547 },
3548 optionListeners: {
3549 multiDragKey: function multiDragKey(key) {
3550 key = key.toLowerCase();
3551
3552 if (key === 'ctrl') {
3553 key = 'Control';
3554 } else if (key.length > 1) {
3555 key = key.charAt(0).toUpperCase() + key.substr(1);
3556 }
3557
3558 return key;
3559 }
3560 }
3561 });
3562 }
3563
3564 function insertMultiDragElements(clonesInserted, rootEl) {
3565 for (var i in multiDragElements) {
3566 var target = rootEl.children[multiDragElements[i].sortableIndex + (clonesInserted ? Number(i) : 0)];
3567
3568 if (target) {
3569 rootEl.insertBefore(multiDragElements[i], target);
3570 } else {
3571 rootEl.appendChild(multiDragElements[i]);
3572 }
3573 }
3574 }
3575 /**
3576 * Insert multi-drag clones
3577 * @param {[Boolean]} elementsInserted Whether the multi-drag elements are inserted
3578 * @param {HTMLElement} rootEl
3579 */
3580
3581
3582 function insertMultiDragClones(elementsInserted, rootEl) {
3583 for (var i in multiDragClones) {
3584 var target = rootEl.children[multiDragClones[i].sortableIndex + (elementsInserted ? Number(i) : 0)];
3585
3586 if (target) {
3587 rootEl.insertBefore(multiDragClones[i], target);
3588 } else {
3589 rootEl.appendChild(multiDragClones[i]);
3590 }
3591 }
3592 }
3593
3594 function removeMultiDragElements() {
3595 for (var i in multiDragElements) {
3596 if (multiDragElements[i] === dragEl$1) continue;
3597 multiDragElements[i].parentNode && multiDragElements[i].parentNode.removeChild(multiDragElements[i]);
3598 }
3599 }
3600
3601 Sortable$1.mount(new AutoScrollPlugin());
3602 Sortable$1.mount(Remove, Revert);
3603
3604 Sortable$1.mount(new SwapPlugin());
3605 Sortable$1.mount(new MultiDragPlugin());
3606
3607 return Sortable$1;
3608
3609}));