PluginProbe
Booking Calendar / 11.8.3
Booking Calendar v11.8.3
11.8.3 11.8.2 11.8.1 11.8 11.7 11.6.1 11.6 11.5 11.4.3 11.4.2 11.4.1 11.4 11.3 11.2.1 11.2 11.1 11.0 10.15.7 10.15.6 10.1.3 10.10 10.10.1 10.10.2 10.11 10.11.2 All 203 releases
booking / vendors / sortablejs / Sortable.js

Sortable.js in Booking Calendar 11.8.3, at vendors/sortablejs/Sortable.js

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