para 0.8.3.1 → 0.8.8

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