Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
/**!
2
 * Sortable 1.15.2
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.2";
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
      supportPointer: Sortable.supportPointer !== false && 'PointerEvent' in window && !Safari,
1131
      emptyInsertThreshold: 5
1132
    };
1133
    PluginManager.initializePlugins(this, el, defaults);
1134
 
1135
    // Set default options
1136
    for (var name in defaults) {
1137
      !(name in options) && (options[name] = defaults[name]);
1138
    }
1139
    _prepareGroup(options);
1140
 
1141
    // Bind all private methods
1142
    for (var fn in this) {
1143
      if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {
1144
        this[fn] = this[fn].bind(this);
1145
      }
1146
    }
1147
 
1148
    // Setup drag mode
1149
    this.nativeDraggable = options.forceFallback ? false : supportDraggable;
1150
    if (this.nativeDraggable) {
1151
      // Touch start threshold cannot be greater than the native dragstart threshold
1152
      this.options.touchStartThreshold = 1;
1153
    }
1154
 
1155
    // Bind events
1156
    if (options.supportPointer) {
1157
      on(el, 'pointerdown', this._onTapStart);
1158
    } else {
1159
      on(el, 'mousedown', this._onTapStart);
1160
      on(el, 'touchstart', this._onTapStart);
1161
    }
1162
    if (this.nativeDraggable) {
1163
      on(el, 'dragover', this);
1164
      on(el, 'dragenter', this);
1165
    }
1166
    sortables.push(this.el);
1167
 
1168
    // Restore sorting
1169
    options.store && options.store.get && this.sort(options.store.get(this) || []);
1170
 
1171
    // Add animation state manager
1172
    _extends(this, AnimationStateManager());
1173
  }
1174
  Sortable.prototype = /** @lends Sortable.prototype */{
1175
    constructor: Sortable,
1176
    _isOutsideThisEl: function _isOutsideThisEl(target) {
1177
      if (!this.el.contains(target) && target !== this.el) {
1178
        lastTarget = null;
1179
      }
1180
    },
1181
    _getDirection: function _getDirection(evt, target) {
1182
      return typeof this.options.direction === 'function' ? this.options.direction.call(this, evt, target, dragEl) : this.options.direction;
1183
    },
1184
    _onTapStart: function _onTapStart( /** Event|TouchEvent */evt) {
1185
      if (!evt.cancelable) return;
1186
      var _this = this,
1187
        el = this.el,
1188
        options = this.options,
1189
        preventOnFilter = options.preventOnFilter,
1190
        type = evt.type,
1191
        touch = evt.touches && evt.touches[0] || evt.pointerType && evt.pointerType === 'touch' && evt,
1192
        target = (touch || evt).target,
1193
        originalTarget = evt.target.shadowRoot && (evt.path && evt.path[0] || evt.composedPath && evt.composedPath()[0]) || target,
1194
        filter = options.filter;
1195
      _saveInputCheckedState(el);
1196
 
1197
      // Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group.
1198
      if (dragEl) {
1199
        return;
1200
      }
1201
      if (/mousedown|pointerdown/.test(type) && evt.button !== 0 || options.disabled) {
1202
        return; // only left button and enabled
1203
      }
1204
 
1205
      // cancel dnd if original target is content editable
1206
      if (originalTarget.isContentEditable) {
1207
        return;
1208
      }
1209
 
1210
      // Safari ignores further event handling after mousedown
1211
      if (!this.nativeDraggable && Safari && target && target.tagName.toUpperCase() === 'SELECT') {
1212
        return;
1213
      }
1214
      target = closest(target, options.draggable, el, false);
1215
      if (target && target.animated) {
1216
        return;
1217
      }
1218
      if (lastDownEl === target) {
1219
        // Ignoring duplicate `down`
1220
        return;
1221
      }
1222
 
1223
      // Get the index of the dragged element within its parent
1224
      oldIndex = index(target);
1225
      oldDraggableIndex = index(target, options.draggable);
1226
 
1227
      // Check filter
1228
      if (typeof filter === 'function') {
1229
        if (filter.call(this, evt, target, this)) {
1230
          _dispatchEvent({
1231
            sortable: _this,
1232
            rootEl: originalTarget,
1233
            name: 'filter',
1234
            targetEl: target,
1235
            toEl: el,
1236
            fromEl: el
1237
          });
1238
          pluginEvent('filter', _this, {
1239
            evt: evt
1240
          });
1241
          preventOnFilter && evt.cancelable && evt.preventDefault();
1242
          return; // cancel dnd
1243
        }
1244
      } else if (filter) {
1245
        filter = filter.split(',').some(function (criteria) {
1246
          criteria = closest(originalTarget, criteria.trim(), el, false);
1247
          if (criteria) {
1248
            _dispatchEvent({
1249
              sortable: _this,
1250
              rootEl: criteria,
1251
              name: 'filter',
1252
              targetEl: target,
1253
              fromEl: el,
1254
              toEl: el
1255
            });
1256
            pluginEvent('filter', _this, {
1257
              evt: evt
1258
            });
1259
            return true;
1260
          }
1261
        });
1262
        if (filter) {
1263
          preventOnFilter && evt.cancelable && evt.preventDefault();
1264
          return; // cancel dnd
1265
        }
1266
      }
1267
      if (options.handle && !closest(originalTarget, options.handle, el, false)) {
1268
        return;
1269
      }
1270
 
1271
      // Prepare `dragstart`
1272
      this._prepareDragStart(evt, touch, target);
1273
    },
1274
    _prepareDragStart: function _prepareDragStart( /** Event */evt, /** Touch */touch, /** HTMLElement */target) {
1275
      var _this = this,
1276
        el = _this.el,
1277
        options = _this.options,
1278
        ownerDocument = el.ownerDocument,
1279
        dragStartFn;
1280
      if (target && !dragEl && target.parentNode === el) {
1281
        var dragRect = getRect(target);
1282
        rootEl = el;
1283
        dragEl = target;
1284
        parentEl = dragEl.parentNode;
1285
        nextEl = dragEl.nextSibling;
1286
        lastDownEl = target;
1287
        activeGroup = options.group;
1288
        Sortable.dragged = dragEl;
1289
        tapEvt = {
1290
          target: dragEl,
1291
          clientX: (touch || evt).clientX,
1292
          clientY: (touch || evt).clientY
1293
        };
1294
        tapDistanceLeft = tapEvt.clientX - dragRect.left;
1295
        tapDistanceTop = tapEvt.clientY - dragRect.top;
1296
        this._lastX = (touch || evt).clientX;
1297
        this._lastY = (touch || evt).clientY;
1298
        dragEl.style['will-change'] = 'all';
1299
        dragStartFn = function dragStartFn() {
1300
          pluginEvent('delayEnded', _this, {
1301
            evt: evt
1302
          });
1303
          if (Sortable.eventCanceled) {
1304
            _this._onDrop();
1305
            return;
1306
          }
1307
          // Delayed drag has been triggered
1308
          // we can re-enable the events: touchmove/mousemove
1309
          _this._disableDelayedDragEvents();
1310
          if (!FireFox && _this.nativeDraggable) {
1311
            dragEl.draggable = true;
1312
          }
1313
 
1314
          // Bind the events: dragstart/dragend
1315
          _this._triggerDragStart(evt, touch);
1316
 
1317
          // Drag start event
1318
          _dispatchEvent({
1319
            sortable: _this,
1320
            name: 'choose',
1321
            originalEvent: evt
1322
          });
1323
 
1324
          // Chosen item
1325
          toggleClass(dragEl, options.chosenClass, true);
1326
        };
1327
 
1328
        // Disable "draggable"
1329
        options.ignore.split(',').forEach(function (criteria) {
1330
          find(dragEl, criteria.trim(), _disableDraggable);
1331
        });
1332
        on(ownerDocument, 'dragover', nearestEmptyInsertDetectEvent);
1333
        on(ownerDocument, 'mousemove', nearestEmptyInsertDetectEvent);
1334
        on(ownerDocument, 'touchmove', nearestEmptyInsertDetectEvent);
1335
        on(ownerDocument, 'mouseup', _this._onDrop);
1336
        on(ownerDocument, 'touchend', _this._onDrop);
1337
        on(ownerDocument, 'touchcancel', _this._onDrop);
1338
 
1339
        // Make dragEl draggable (must be before delay for FireFox)
1340
        if (FireFox && this.nativeDraggable) {
1341
          this.options.touchStartThreshold = 4;
1342
          dragEl.draggable = true;
1343
        }
1344
        pluginEvent('delayStart', this, {
1345
          evt: evt
1346
        });
1347
 
1348
        // Delay is impossible for native DnD in Edge or IE
1349
        if (options.delay && (!options.delayOnTouchOnly || touch) && (!this.nativeDraggable || !(Edge || IE11OrLess))) {
1350
          if (Sortable.eventCanceled) {
1351
            this._onDrop();
1352
            return;
1353
          }
1354
          // If the user moves the pointer or let go the click or touch
1355
          // before the delay has been reached:
1356
          // disable the delayed drag
1357
          on(ownerDocument, 'mouseup', _this._disableDelayedDrag);
1358
          on(ownerDocument, 'touchend', _this._disableDelayedDrag);
1359
          on(ownerDocument, 'touchcancel', _this._disableDelayedDrag);
1360
          on(ownerDocument, 'mousemove', _this._delayedDragTouchMoveHandler);
1361
          on(ownerDocument, 'touchmove', _this._delayedDragTouchMoveHandler);
1362
          options.supportPointer && on(ownerDocument, 'pointermove', _this._delayedDragTouchMoveHandler);
1363
          _this._dragStartTimer = setTimeout(dragStartFn, options.delay);
1364
        } else {
1365
          dragStartFn();
1366
        }
1367
      }
1368
    },
1369
    _delayedDragTouchMoveHandler: function _delayedDragTouchMoveHandler( /** TouchEvent|PointerEvent **/e) {
1370
      var touch = e.touches ? e.touches[0] : e;
1371
      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))) {
1372
        this._disableDelayedDrag();
1373
      }
1374
    },
1375
    _disableDelayedDrag: function _disableDelayedDrag() {
1376
      dragEl && _disableDraggable(dragEl);
1377
      clearTimeout(this._dragStartTimer);
1378
      this._disableDelayedDragEvents();
1379
    },
1380
    _disableDelayedDragEvents: function _disableDelayedDragEvents() {
1381
      var ownerDocument = this.el.ownerDocument;
1382
      off(ownerDocument, 'mouseup', this._disableDelayedDrag);
1383
      off(ownerDocument, 'touchend', this._disableDelayedDrag);
1384
      off(ownerDocument, 'touchcancel', this._disableDelayedDrag);
1385
      off(ownerDocument, 'mousemove', this._delayedDragTouchMoveHandler);
1386
      off(ownerDocument, 'touchmove', this._delayedDragTouchMoveHandler);
1387
      off(ownerDocument, 'pointermove', this._delayedDragTouchMoveHandler);
1388
    },
1389
    _triggerDragStart: function _triggerDragStart( /** Event */evt, /** Touch */touch) {
1390
      touch = touch || evt.pointerType == 'touch' && evt;
1391
      if (!this.nativeDraggable || touch) {
1392
        if (this.options.supportPointer) {
1393
          on(document, 'pointermove', this._onTouchMove);
1394
        } else if (touch) {
1395
          on(document, 'touchmove', this._onTouchMove);
1396
        } else {
1397
          on(document, 'mousemove', this._onTouchMove);
1398
        }
1399
      } else {
1400
        on(dragEl, 'dragend', this);
1401
        on(rootEl, 'dragstart', this._onDragStart);
1402
      }
1403
      try {
1404
        if (document.selection) {
1405
          // Timeout neccessary for IE9
1406
          _nextTick(function () {
1407
            document.selection.empty();
1408
          });
1409
        } else {
1410
          window.getSelection().removeAllRanges();
1411
        }
1412
      } catch (err) {}
1413
    },
1414
    _dragStarted: function _dragStarted(fallback, evt) {
1415
      awaitingDragStarted = false;
1416
      if (rootEl && dragEl) {
1417
        pluginEvent('dragStarted', this, {
1418
          evt: evt
1419
        });
1420
        if (this.nativeDraggable) {
1421
          on(document, 'dragover', _checkOutsideTargetEl);
1422
        }
1423
        var options = this.options;
1424
 
1425
        // Apply effect
1426
        !fallback && toggleClass(dragEl, options.dragClass, false);
1427
        toggleClass(dragEl, options.ghostClass, true);
1428
        Sortable.active = this;
1429
        fallback && this._appendGhost();
1430
 
1431
        // Drag start event
1432
        _dispatchEvent({
1433
          sortable: this,
1434
          name: 'start',
1435
          originalEvent: evt
1436
        });
1437
      } else {
1438
        this._nulling();
1439
      }
1440
    },
1441
    _emulateDragOver: function _emulateDragOver() {
1442
      if (touchEvt) {
1443
        this._lastX = touchEvt.clientX;
1444
        this._lastY = touchEvt.clientY;
1445
        _hideGhostForTarget();
1446
        var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY);
1447
        var parent = target;
1448
        while (target && target.shadowRoot) {
1449
          target = target.shadowRoot.elementFromPoint(touchEvt.clientX, touchEvt.clientY);
1450
          if (target === parent) break;
1451
          parent = target;
1452
        }
1453
        dragEl.parentNode[expando]._isOutsideThisEl(target);
1454
        if (parent) {
1455
          do {
1456
            if (parent[expando]) {
1457
              var inserted = void 0;
1458
              inserted = parent[expando]._onDragOver({
1459
                clientX: touchEvt.clientX,
1460
                clientY: touchEvt.clientY,
1461
                target: target,
1462
                rootEl: parent
1463
              });
1464
              if (inserted && !this.options.dragoverBubble) {
1465
                break;
1466
              }
1467
            }
1468
            target = parent; // store last element
1469
          }
1470
          /* jshint boss:true */ while (parent = parent.parentNode);
1471
        }
1472
        _unhideGhostForTarget();
1473
      }
1474
    },
1475
    _onTouchMove: function _onTouchMove( /**TouchEvent*/evt) {
1476
      if (tapEvt) {
1477
        var options = this.options,
1478
          fallbackTolerance = options.fallbackTolerance,
1479
          fallbackOffset = options.fallbackOffset,
1480
          touch = evt.touches ? evt.touches[0] : evt,
1481
          ghostMatrix = ghostEl && matrix(ghostEl, true),
1482
          scaleX = ghostEl && ghostMatrix && ghostMatrix.a,
1483
          scaleY = ghostEl && ghostMatrix && ghostMatrix.d,
1484
          relativeScrollOffset = PositionGhostAbsolutely && ghostRelativeParent && getRelativeScrollOffset(ghostRelativeParent),
1485
          dx = (touch.clientX - tapEvt.clientX + fallbackOffset.x) / (scaleX || 1) + (relativeScrollOffset ? relativeScrollOffset[0] - ghostRelativeParentInitialScroll[0] : 0) / (scaleX || 1),
1486
          dy = (touch.clientY - tapEvt.clientY + fallbackOffset.y) / (scaleY || 1) + (relativeScrollOffset ? relativeScrollOffset[1] - ghostRelativeParentInitialScroll[1] : 0) / (scaleY || 1);
1487
 
1488
        // only set the status to dragging, when we are actually dragging
1489
        if (!Sortable.active && !awaitingDragStarted) {
1490
          if (fallbackTolerance && Math.max(Math.abs(touch.clientX - this._lastX), Math.abs(touch.clientY - this._lastY)) < fallbackTolerance) {
1491
            return;
1492
          }
1493
          this._onDragStart(evt, true);
1494
        }
1495
        if (ghostEl) {
1496
          if (ghostMatrix) {
1497
            ghostMatrix.e += dx - (lastDx || 0);
1498
            ghostMatrix.f += dy - (lastDy || 0);
1499
          } else {
1500
            ghostMatrix = {
1501
              a: 1,
1502
              b: 0,
1503
              c: 0,
1504
              d: 1,
1505
              e: dx,
1506
              f: dy
1507
            };
1508
          }
1509
          var cssMatrix = "matrix(".concat(ghostMatrix.a, ",").concat(ghostMatrix.b, ",").concat(ghostMatrix.c, ",").concat(ghostMatrix.d, ",").concat(ghostMatrix.e, ",").concat(ghostMatrix.f, ")");
1510
          css(ghostEl, 'webkitTransform', cssMatrix);
1511
          css(ghostEl, 'mozTransform', cssMatrix);
1512
          css(ghostEl, 'msTransform', cssMatrix);
1513
          css(ghostEl, 'transform', cssMatrix);
1514
          lastDx = dx;
1515
          lastDy = dy;
1516
          touchEvt = touch;
1517
        }
1518
        evt.cancelable && evt.preventDefault();
1519
      }
1520
    },
1521
    _appendGhost: function _appendGhost() {
1522
      // Bug if using scale(): https://stackoverflow.com/questions/2637058
1523
      // Not being adjusted for
1524
      if (!ghostEl) {
1525
        var container = this.options.fallbackOnBody ? document.body : rootEl,
1526
          rect = getRect(dragEl, true, PositionGhostAbsolutely, true, container),
1527
          options = this.options;
1528
 
1529
        // Position absolutely
1530
        if (PositionGhostAbsolutely) {
1531
          // Get relatively positioned parent
1532
          ghostRelativeParent = container;
1533
          while (css(ghostRelativeParent, 'position') === 'static' && css(ghostRelativeParent, 'transform') === 'none' && ghostRelativeParent !== document) {
1534
            ghostRelativeParent = ghostRelativeParent.parentNode;
1535
          }
1536
          if (ghostRelativeParent !== document.body && ghostRelativeParent !== document.documentElement) {
1537
            if (ghostRelativeParent === document) ghostRelativeParent = getWindowScrollingElement();
1538
            rect.top += ghostRelativeParent.scrollTop;
1539
            rect.left += ghostRelativeParent.scrollLeft;
1540
          } else {
1541
            ghostRelativeParent = getWindowScrollingElement();
1542
          }
1543
          ghostRelativeParentInitialScroll = getRelativeScrollOffset(ghostRelativeParent);
1544
        }
1545
        ghostEl = dragEl.cloneNode(true);
1546
        toggleClass(ghostEl, options.ghostClass, false);
1547
        toggleClass(ghostEl, options.fallbackClass, true);
1548
        toggleClass(ghostEl, options.dragClass, true);
1549
        css(ghostEl, 'transition', '');
1550
        css(ghostEl, 'transform', '');
1551
        css(ghostEl, 'box-sizing', 'border-box');
1552
        css(ghostEl, 'margin', 0);
1553
        css(ghostEl, 'top', rect.top);
1554
        css(ghostEl, 'left', rect.left);
1555
        css(ghostEl, 'width', rect.width);
1556
        css(ghostEl, 'height', rect.height);
1557
        css(ghostEl, 'opacity', '0.8');
1558
        css(ghostEl, 'position', PositionGhostAbsolutely ? 'absolute' : 'fixed');
1559
        css(ghostEl, 'zIndex', '100000');
1560
        css(ghostEl, 'pointerEvents', 'none');
1561
        Sortable.ghost = ghostEl;
1562
        container.appendChild(ghostEl);
1563
 
1564
        // Set transform-origin
1565
        css(ghostEl, 'transform-origin', tapDistanceLeft / parseInt(ghostEl.style.width) * 100 + '% ' + tapDistanceTop / parseInt(ghostEl.style.height) * 100 + '%');
1566
      }
1567
    },
1568
    _onDragStart: function _onDragStart( /**Event*/evt, /**boolean*/fallback) {
1569
      var _this = this;
1570
      var dataTransfer = evt.dataTransfer;
1571
      var options = _this.options;
1572
      pluginEvent('dragStart', this, {
1573
        evt: evt
1574
      });
1575
      if (Sortable.eventCanceled) {
1576
        this._onDrop();
1577
        return;
1578
      }
1579
      pluginEvent('setupClone', this);
1580
      if (!Sortable.eventCanceled) {
1581
        cloneEl = clone(dragEl);
1582
        cloneEl.removeAttribute("id");
1583
        cloneEl.draggable = false;
1584
        cloneEl.style['will-change'] = '';
1585
        this._hideClone();
1586
        toggleClass(cloneEl, this.options.chosenClass, false);
1587
        Sortable.clone = cloneEl;
1588
      }
1589
 
1590
      // #1143: IFrame support workaround
1591
      _this.cloneId = _nextTick(function () {
1592
        pluginEvent('clone', _this);
1593
        if (Sortable.eventCanceled) return;
1594
        if (!_this.options.removeCloneOnHide) {
1595
          rootEl.insertBefore(cloneEl, dragEl);
1596
        }
1597
        _this._hideClone();
1598
        _dispatchEvent({
1599
          sortable: _this,
1600
          name: 'clone'
1601
        });
1602
      });
1603
      !fallback && toggleClass(dragEl, options.dragClass, true);
1604
 
1605
      // Set proper drop events
1606
      if (fallback) {
1607
        ignoreNextClick = true;
1608
        _this._loopId = setInterval(_this._emulateDragOver, 50);
1609
      } else {
1610
        // Undo what was set in _prepareDragStart before drag started
1611
        off(document, 'mouseup', _this._onDrop);
1612
        off(document, 'touchend', _this._onDrop);
1613
        off(document, 'touchcancel', _this._onDrop);
1614
        if (dataTransfer) {
1615
          dataTransfer.effectAllowed = 'move';
1616
          options.setData && options.setData.call(_this, dataTransfer, dragEl);
1617
        }
1618
        on(document, 'drop', _this);
1619
 
1620
        // #1276 fix:
1621
        css(dragEl, 'transform', 'translateZ(0)');
1622
      }
1623
      awaitingDragStarted = true;
1624
      _this._dragStartId = _nextTick(_this._dragStarted.bind(_this, fallback, evt));
1625
      on(document, 'selectstart', _this);
1626
      moved = true;
1627
      if (Safari) {
1628
        css(document.body, 'user-select', 'none');
1629
      }
1630
    },
1631
    // Returns true - if no further action is needed (either inserted or another condition)
1632
    _onDragOver: function _onDragOver( /**Event*/evt) {
1633
      var el = this.el,
1634
        target = evt.target,
1635
        dragRect,
1636
        targetRect,
1637
        revert,
1638
        options = this.options,
1639
        group = options.group,
1640
        activeSortable = Sortable.active,
1641
        isOwner = activeGroup === group,
1642
        canSort = options.sort,
1643
        fromSortable = putSortable || activeSortable,
1644
        vertical,
1645
        _this = this,
1646
        completedFired = false;
1647
      if (_silent) return;
1648
      function dragOverEvent(name, extra) {
1649
        pluginEvent(name, _this, _objectSpread2({
1650
          evt: evt,
1651
          isOwner: isOwner,
1652
          axis: vertical ? 'vertical' : 'horizontal',
1653
          revert: revert,
1654
          dragRect: dragRect,
1655
          targetRect: targetRect,
1656
          canSort: canSort,
1657
          fromSortable: fromSortable,
1658
          target: target,
1659
          completed: completed,
1660
          onMove: function onMove(target, after) {
1661
            return _onMove(rootEl, el, dragEl, dragRect, target, getRect(target), evt, after);
1662
          },
1663
          changed: changed
1664
        }, extra));
1665
      }
1666
 
1667
      // Capture animation state
1668
      function capture() {
1669
        dragOverEvent('dragOverAnimationCapture');
1670
        _this.captureAnimationState();
1671
        if (_this !== fromSortable) {
1672
          fromSortable.captureAnimationState();
1673
        }
1674
      }
1675
 
1676
      // Return invocation when dragEl is inserted (or completed)
1677
      function completed(insertion) {
1678
        dragOverEvent('dragOverCompleted', {
1679
          insertion: insertion
1680
        });
1681
        if (insertion) {
1682
          // Clones must be hidden before folding animation to capture dragRectAbsolute properly
1683
          if (isOwner) {
1684
            activeSortable._hideClone();
1685
          } else {
1686
            activeSortable._showClone(_this);
1687
          }
1688
          if (_this !== fromSortable) {
1689
            // Set ghost class to new sortable's ghost class
1690
            toggleClass(dragEl, putSortable ? putSortable.options.ghostClass : activeSortable.options.ghostClass, false);
1691
            toggleClass(dragEl, options.ghostClass, true);
1692
          }
1693
          if (putSortable !== _this && _this !== Sortable.active) {
1694
            putSortable = _this;
1695
          } else if (_this === Sortable.active && putSortable) {
1696
            putSortable = null;
1697
          }
1698
 
1699
          // Animation
1700
          if (fromSortable === _this) {
1701
            _this._ignoreWhileAnimating = target;
1702
          }
1703
          _this.animateAll(function () {
1704
            dragOverEvent('dragOverAnimationComplete');
1705
            _this._ignoreWhileAnimating = null;
1706
          });
1707
          if (_this !== fromSortable) {
1708
            fromSortable.animateAll();
1709
            fromSortable._ignoreWhileAnimating = null;
1710
          }
1711
        }
1712
 
1713
        // Null lastTarget if it is not inside a previously swapped element
1714
        if (target === dragEl && !dragEl.animated || target === el && !target.animated) {
1715
          lastTarget = null;
1716
        }
1717
 
1718
        // no bubbling and not fallback
1719
        if (!options.dragoverBubble && !evt.rootEl && target !== document) {
1720
          dragEl.parentNode[expando]._isOutsideThisEl(evt.target);
1721
 
1722
          // Do not detect for empty insert if already inserted
1723
          !insertion && nearestEmptyInsertDetectEvent(evt);
1724
        }
1725
        !options.dragoverBubble && evt.stopPropagation && evt.stopPropagation();
1726
        return completedFired = true;
1727
      }
1728
 
1729
      // Call when dragEl has been inserted
1730
      function changed() {
1731
        newIndex = index(dragEl);
1732
        newDraggableIndex = index(dragEl, options.draggable);
1733
        _dispatchEvent({
1734
          sortable: _this,
1735
          name: 'change',
1736
          toEl: el,
1737
          newIndex: newIndex,
1738
          newDraggableIndex: newDraggableIndex,
1739
          originalEvent: evt
1740
        });
1741
      }
1742
      if (evt.preventDefault !== void 0) {
1743
        evt.cancelable && evt.preventDefault();
1744
      }
1745
      target = closest(target, options.draggable, el, true);
1746
      dragOverEvent('dragOver');
1747
      if (Sortable.eventCanceled) return completedFired;
1748
      if (dragEl.contains(evt.target) || target.animated && target.animatingX && target.animatingY || _this._ignoreWhileAnimating === target) {
1749
        return completed(false);
1750
      }
1751
      ignoreNextClick = false;
1752
      if (activeSortable && !options.disabled && (isOwner ? canSort || (revert = parentEl !== rootEl) // Reverting item into the original list
1753
      : putSortable === this || (this.lastPutMode = activeGroup.checkPull(this, activeSortable, dragEl, evt)) && group.checkPut(this, activeSortable, dragEl, evt))) {
1754
        vertical = this._getDirection(evt, target) === 'vertical';
1755
        dragRect = getRect(dragEl);
1756
        dragOverEvent('dragOverValid');
1757
        if (Sortable.eventCanceled) return completedFired;
1758
        if (revert) {
1759
          parentEl = rootEl; // actualization
1760
          capture();
1761
          this._hideClone();
1762
          dragOverEvent('revert');
1763
          if (!Sortable.eventCanceled) {
1764
            if (nextEl) {
1765
              rootEl.insertBefore(dragEl, nextEl);
1766
            } else {
1767
              rootEl.appendChild(dragEl);
1768
            }
1769
          }
1770
          return completed(true);
1771
        }
1772
        var elLastChild = lastChild(el, options.draggable);
1773
        if (!elLastChild || _ghostIsLast(evt, vertical, this) && !elLastChild.animated) {
1774
          // Insert to end of list
1775
 
1776
          // If already at end of list: Do not insert
1777
          if (elLastChild === dragEl) {
1778
            return completed(false);
1779
          }
1780
 
1781
          // if there is a last element, it is the target
1782
          if (elLastChild && el === evt.target) {
1783
            target = elLastChild;
1784
          }
1785
          if (target) {
1786
            targetRect = getRect(target);
1787
          }
1788
          if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, !!target) !== false) {
1789
            capture();
1790
            if (elLastChild && elLastChild.nextSibling) {
1791
              // the last draggable element is not the last node
1792
              el.insertBefore(dragEl, elLastChild.nextSibling);
1793
            } else {
1794
              el.appendChild(dragEl);
1795
            }
1796
            parentEl = el; // actualization
1797
 
1798
            changed();
1799
            return completed(true);
1800
          }
1801
        } else if (elLastChild && _ghostIsFirst(evt, vertical, this)) {
1802
          // Insert to start of list
1803
          var firstChild = getChild(el, 0, options, true);
1804
          if (firstChild === dragEl) {
1805
            return completed(false);
1806
          }
1807
          target = firstChild;
1808
          targetRect = getRect(target);
1809
          if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, false) !== false) {
1810
            capture();
1811
            el.insertBefore(dragEl, firstChild);
1812
            parentEl = el; // actualization
1813
 
1814
            changed();
1815
            return completed(true);
1816
          }
1817
        } else if (target.parentNode === el) {
1818
          targetRect = getRect(target);
1819
          var direction = 0,
1820
            targetBeforeFirstSwap,
1821
            differentLevel = dragEl.parentNode !== el,
1822
            differentRowCol = !_dragElInRowColumn(dragEl.animated && dragEl.toRect || dragRect, target.animated && target.toRect || targetRect, vertical),
1823
            side1 = vertical ? 'top' : 'left',
1824
            scrolledPastTop = isScrolledPast(target, 'top', 'top') || isScrolledPast(dragEl, 'top', 'top'),
1825
            scrollBefore = scrolledPastTop ? scrolledPastTop.scrollTop : void 0;
1826
          if (lastTarget !== target) {
1827
            targetBeforeFirstSwap = targetRect[side1];
1828
            pastFirstInvertThresh = false;
1829
            isCircumstantialInvert = !differentRowCol && options.invertSwap || differentLevel;
1830
          }
1831
          direction = _getSwapDirection(evt, target, targetRect, vertical, differentRowCol ? 1 : options.swapThreshold, options.invertedSwapThreshold == null ? options.swapThreshold : options.invertedSwapThreshold, isCircumstantialInvert, lastTarget === target);
1832
          var sibling;
1833
          if (direction !== 0) {
1834
            // Check if target is beside dragEl in respective direction (ignoring hidden elements)
1835
            var dragIndex = index(dragEl);
1836
            do {
1837
              dragIndex -= direction;
1838
              sibling = parentEl.children[dragIndex];
1839
            } while (sibling && (css(sibling, 'display') === 'none' || sibling === ghostEl));
1840
          }
1841
          // If dragEl is already beside target: Do not insert
1842
          if (direction === 0 || sibling === target) {
1843
            return completed(false);
1844
          }
1845
          lastTarget = target;
1846
          lastDirection = direction;
1847
          var nextSibling = target.nextElementSibling,
1848
            after = false;
1849
          after = direction === 1;
1850
          var moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, after);
1851
          if (moveVector !== false) {
1852
            if (moveVector === 1 || moveVector === -1) {
1853
              after = moveVector === 1;
1854
            }
1855
            _silent = true;
1856
            setTimeout(_unsilent, 30);
1857
            capture();
1858
            if (after && !nextSibling) {
1859
              el.appendChild(dragEl);
1860
            } else {
1861
              target.parentNode.insertBefore(dragEl, after ? nextSibling : target);
1862
            }
1863
 
1864
            // Undo chrome's scroll adjustment (has no effect on other browsers)
1865
            if (scrolledPastTop) {
1866
              scrollBy(scrolledPastTop, 0, scrollBefore - scrolledPastTop.scrollTop);
1867
            }
1868
            parentEl = dragEl.parentNode; // actualization
1869
 
1870
            // must be done before animation
1871
            if (targetBeforeFirstSwap !== undefined && !isCircumstantialInvert) {
1872
              targetMoveDistance = Math.abs(targetBeforeFirstSwap - getRect(target)[side1]);
1873
            }
1874
            changed();
1875
            return completed(true);
1876
          }
1877
        }
1878
        if (el.contains(dragEl)) {
1879
          return completed(false);
1880
        }
1881
      }
1882
      return false;
1883
    },
1884
    _ignoreWhileAnimating: null,
1885
    _offMoveEvents: function _offMoveEvents() {
1886
      off(document, 'mousemove', this._onTouchMove);
1887
      off(document, 'touchmove', this._onTouchMove);
1888
      off(document, 'pointermove', this._onTouchMove);
1889
      off(document, 'dragover', nearestEmptyInsertDetectEvent);
1890
      off(document, 'mousemove', nearestEmptyInsertDetectEvent);
1891
      off(document, 'touchmove', nearestEmptyInsertDetectEvent);
1892
    },
1893
    _offUpEvents: function _offUpEvents() {
1894
      var ownerDocument = this.el.ownerDocument;
1895
      off(ownerDocument, 'mouseup', this._onDrop);
1896
      off(ownerDocument, 'touchend', this._onDrop);
1897
      off(ownerDocument, 'pointerup', this._onDrop);
1898
      off(ownerDocument, 'touchcancel', this._onDrop);
1899
      off(document, 'selectstart', this);
1900
    },
1901
    _onDrop: function _onDrop( /**Event*/evt) {
1902
      var el = this.el,
1903
        options = this.options;
1904
 
1905
      // Get the index of the dragged element within its parent
1906
      newIndex = index(dragEl);
1907
      newDraggableIndex = index(dragEl, options.draggable);
1908
      pluginEvent('drop', this, {
1909
        evt: evt
1910
      });
1911
      parentEl = dragEl && dragEl.parentNode;
1912
 
1913
      // Get again after plugin event
1914
      newIndex = index(dragEl);
1915
      newDraggableIndex = index(dragEl, options.draggable);
1916
      if (Sortable.eventCanceled) {
1917
        this._nulling();
1918
        return;
1919
      }
1920
      awaitingDragStarted = false;
1921
      isCircumstantialInvert = false;
1922
      pastFirstInvertThresh = false;
1923
      clearInterval(this._loopId);
1924
      clearTimeout(this._dragStartTimer);
1925
      _cancelNextTick(this.cloneId);
1926
      _cancelNextTick(this._dragStartId);
1927
 
1928
      // Unbind events
1929
      if (this.nativeDraggable) {
1930
        off(document, 'drop', this);
1931
        off(el, 'dragstart', this._onDragStart);
1932
      }
1933
      this._offMoveEvents();
1934
      this._offUpEvents();
1935
      if (Safari) {
1936
        css(document.body, 'user-select', '');
1937
      }
1938
      css(dragEl, 'transform', '');
1939
      if (evt) {
1940
        if (moved) {
1941
          evt.cancelable && evt.preventDefault();
1942
          !options.dropBubble && evt.stopPropagation();
1943
        }
1944
        ghostEl && ghostEl.parentNode && ghostEl.parentNode.removeChild(ghostEl);
1945
        if (rootEl === parentEl || putSortable && putSortable.lastPutMode !== 'clone') {
1946
          // Remove clone(s)
1947
          cloneEl && cloneEl.parentNode && cloneEl.parentNode.removeChild(cloneEl);
1948
        }
1949
        if (dragEl) {
1950
          if (this.nativeDraggable) {
1951
            off(dragEl, 'dragend', this);
1952
          }
1953
          _disableDraggable(dragEl);
1954
          dragEl.style['will-change'] = '';
1955
 
1956
          // Remove classes
1957
          // ghostClass is added in dragStarted
1958
          if (moved && !awaitingDragStarted) {
1959
            toggleClass(dragEl, putSortable ? putSortable.options.ghostClass : this.options.ghostClass, false);
1960
          }
1961
          toggleClass(dragEl, this.options.chosenClass, false);
1962
 
1963
          // Drag stop event
1964
          _dispatchEvent({
1965
            sortable: this,
1966
            name: 'unchoose',
1967
            toEl: parentEl,
1968
            newIndex: null,
1969
            newDraggableIndex: null,
1970
            originalEvent: evt
1971
          });
1972
          if (rootEl !== parentEl) {
1973
            if (newIndex >= 0) {
1974
              // Add event
1975
              _dispatchEvent({
1976
                rootEl: parentEl,
1977
                name: 'add',
1978
                toEl: parentEl,
1979
                fromEl: rootEl,
1980
                originalEvent: evt
1981
              });
1982
 
1983
              // Remove event
1984
              _dispatchEvent({
1985
                sortable: this,
1986
                name: 'remove',
1987
                toEl: parentEl,
1988
                originalEvent: evt
1989
              });
1990
 
1991
              // drag from one list and drop into another
1992
              _dispatchEvent({
1993
                rootEl: parentEl,
1994
                name: 'sort',
1995
                toEl: parentEl,
1996
                fromEl: rootEl,
1997
                originalEvent: evt
1998
              });
1999
              _dispatchEvent({
2000
                sortable: this,
2001
                name: 'sort',
2002
                toEl: parentEl,
2003
                originalEvent: evt
2004
              });
2005
            }
2006
            putSortable && putSortable.save();
2007
          } else {
2008
            if (newIndex !== oldIndex) {
2009
              if (newIndex >= 0) {
2010
                // drag & drop within the same list
2011
                _dispatchEvent({
2012
                  sortable: this,
2013
                  name: 'update',
2014
                  toEl: parentEl,
2015
                  originalEvent: evt
2016
                });
2017
                _dispatchEvent({
2018
                  sortable: this,
2019
                  name: 'sort',
2020
                  toEl: parentEl,
2021
                  originalEvent: evt
2022
                });
2023
              }
2024
            }
2025
          }
2026
          if (Sortable.active) {
2027
            /* jshint eqnull:true */
2028
            if (newIndex == null || newIndex === -1) {
2029
              newIndex = oldIndex;
2030
              newDraggableIndex = oldDraggableIndex;
2031
            }
2032
            _dispatchEvent({
2033
              sortable: this,
2034
              name: 'end',
2035
              toEl: parentEl,
2036
              originalEvent: evt
2037
            });
2038
 
2039
            // Save sorting
2040
            this.save();
2041
          }
2042
        }
2043
      }
2044
      this._nulling();
2045
    },
2046
    _nulling: function _nulling() {
2047
      pluginEvent('nulling', this);
2048
      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;
2049
      savedInputChecked.forEach(function (el) {
2050
        el.checked = true;
2051
      });
2052
      savedInputChecked.length = lastDx = lastDy = 0;
2053
    },
2054
    handleEvent: function handleEvent( /**Event*/evt) {
2055
      switch (evt.type) {
2056
        case 'drop':
2057
        case 'dragend':
2058
          this._onDrop(evt);
2059
          break;
2060
        case 'dragenter':
2061
        case 'dragover':
2062
          if (dragEl) {
2063
            this._onDragOver(evt);
2064
            _globalDragOver(evt);
2065
          }
2066
          break;
2067
        case 'selectstart':
2068
          evt.preventDefault();
2069
          break;
2070
      }
2071
    },
2072
    /**
2073
     * Serializes the item into an array of string.
2074
     * @returns {String[]}
2075
     */
2076
    toArray: function toArray() {
2077
      var order = [],
2078
        el,
2079
        children = this.el.children,
2080
        i = 0,
2081
        n = children.length,
2082
        options = this.options;
2083
      for (; i < n; i++) {
2084
        el = children[i];
2085
        if (closest(el, options.draggable, this.el, false)) {
2086
          order.push(el.getAttribute(options.dataIdAttr) || _generateId(el));
2087
        }
2088
      }
2089
      return order;
2090
    },
2091
    /**
2092
     * Sorts the elements according to the array.
2093
     * @param  {String[]}  order  order of the items
2094
     */
2095
    sort: function sort(order, useAnimation) {
2096
      var items = {},
2097
        rootEl = this.el;
2098
      this.toArray().forEach(function (id, i) {
2099
        var el = rootEl.children[i];
2100
        if (closest(el, this.options.draggable, rootEl, false)) {
2101
          items[id] = el;
2102
        }
2103
      }, this);
2104
      useAnimation && this.captureAnimationState();
2105
      order.forEach(function (id) {
2106
        if (items[id]) {
2107
          rootEl.removeChild(items[id]);
2108
          rootEl.appendChild(items[id]);
2109
        }
2110
      });
2111
      useAnimation && this.animateAll();
2112
    },
2113
    /**
2114
     * Save the current sorting
2115
     */
2116
    save: function save() {
2117
      var store = this.options.store;
2118
      store && store.set && store.set(this);
2119
    },
2120
    /**
2121
     * 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.
2122
     * @param   {HTMLElement}  el
2123
     * @param   {String}       [selector]  default: `options.draggable`
2124
     * @returns {HTMLElement|null}
2125
     */
2126
    closest: function closest$1(el, selector) {
2127
      return closest(el, selector || this.options.draggable, this.el, false);
2128
    },
2129
    /**
2130
     * Set/get option
2131
     * @param   {string} name
2132
     * @param   {*}      [value]
2133
     * @returns {*}
2134
     */
2135
    option: function option(name, value) {
2136
      var options = this.options;
2137
      if (value === void 0) {
2138
        return options[name];
2139
      } else {
2140
        var modifiedValue = PluginManager.modifyOption(this, name, value);
2141
        if (typeof modifiedValue !== 'undefined') {
2142
          options[name] = modifiedValue;
2143
        } else {
2144
          options[name] = value;
2145
        }
2146
        if (name === 'group') {
2147
          _prepareGroup(options);
2148
        }
2149
      }
2150
    },
2151
    /**
2152
     * Destroy
2153
     */
2154
    destroy: function destroy() {
2155
      pluginEvent('destroy', this);
2156
      var el = this.el;
2157
      el[expando] = null;
2158
      off(el, 'mousedown', this._onTapStart);
2159
      off(el, 'touchstart', this._onTapStart);
2160
      off(el, 'pointerdown', this._onTapStart);
2161
      if (this.nativeDraggable) {
2162
        off(el, 'dragover', this);
2163
        off(el, 'dragenter', this);
2164
      }
2165
      // Remove draggable attributes
2166
      Array.prototype.forEach.call(el.querySelectorAll('[draggable]'), function (el) {
2167
        el.removeAttribute('draggable');
2168
      });
2169
      this._onDrop();
2170
      this._disableDelayedDragEvents();
2171
      sortables.splice(sortables.indexOf(this.el), 1);
2172
      this.el = el = null;
2173
    },
2174
    _hideClone: function _hideClone() {
2175
      if (!cloneHidden) {
2176
        pluginEvent('hideClone', this);
2177
        if (Sortable.eventCanceled) return;
2178
        css(cloneEl, 'display', 'none');
2179
        if (this.options.removeCloneOnHide && cloneEl.parentNode) {
2180
          cloneEl.parentNode.removeChild(cloneEl);
2181
        }
2182
        cloneHidden = true;
2183
      }
2184
    },
2185
    _showClone: function _showClone(putSortable) {
2186
      if (putSortable.lastPutMode !== 'clone') {
2187
        this._hideClone();
2188
        return;
2189
      }
2190
      if (cloneHidden) {
2191
        pluginEvent('showClone', this);
2192
        if (Sortable.eventCanceled) return;
2193
 
2194
        // show clone at dragEl or original position
2195
        if (dragEl.parentNode == rootEl && !this.options.group.revertClone) {
2196
          rootEl.insertBefore(cloneEl, dragEl);
2197
        } else if (nextEl) {
2198
          rootEl.insertBefore(cloneEl, nextEl);
2199
        } else {
2200
          rootEl.appendChild(cloneEl);
2201
        }
2202
        if (this.options.group.revertClone) {
2203
          this.animate(dragEl, cloneEl);
2204
        }
2205
        css(cloneEl, 'display', '');
2206
        cloneHidden = false;
2207
      }
2208
    }
2209
  };
2210
  function _globalDragOver( /**Event*/evt) {
2211
    if (evt.dataTransfer) {
2212
      evt.dataTransfer.dropEffect = 'move';
2213
    }
2214
    evt.cancelable && evt.preventDefault();
2215
  }
2216
  function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvent, willInsertAfter) {
2217
    var evt,
2218
      sortable = fromEl[expando],
2219
      onMoveFn = sortable.options.onMove,
2220
      retVal;
2221
    // Support for new CustomEvent feature
2222
    if (window.CustomEvent && !IE11OrLess && !Edge) {
2223
      evt = new CustomEvent('move', {
2224
        bubbles: true,
2225
        cancelable: true
2226
      });
2227
    } else {
2228
      evt = document.createEvent('Event');
2229
      evt.initEvent('move', true, true);
2230
    }
2231
    evt.to = toEl;
2232
    evt.from = fromEl;
2233
    evt.dragged = dragEl;
2234
    evt.draggedRect = dragRect;
2235
    evt.related = targetEl || toEl;
2236
    evt.relatedRect = targetRect || getRect(toEl);
2237
    evt.willInsertAfter = willInsertAfter;
2238
    evt.originalEvent = originalEvent;
2239
    fromEl.dispatchEvent(evt);
2240
    if (onMoveFn) {
2241
      retVal = onMoveFn.call(sortable, evt, originalEvent);
2242
    }
2243
    return retVal;
2244
  }
2245
  function _disableDraggable(el) {
2246
    el.draggable = false;
2247
  }
2248
  function _unsilent() {
2249
    _silent = false;
2250
  }
2251
  function _ghostIsFirst(evt, vertical, sortable) {
2252
    var firstElRect = getRect(getChild(sortable.el, 0, sortable.options, true));
2253
    var childContainingRect = getChildContainingRectFromElement(sortable.el, sortable.options, ghostEl);
2254
    var spacer = 10;
2255
    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;
2256
  }
2257
  function _ghostIsLast(evt, vertical, sortable) {
2258
    var lastElRect = getRect(lastChild(sortable.el, sortable.options.draggable));
2259
    var childContainingRect = getChildContainingRectFromElement(sortable.el, sortable.options, ghostEl);
2260
    var spacer = 10;
2261
    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;
2262
  }
2263
  function _getSwapDirection(evt, target, targetRect, vertical, swapThreshold, invertedSwapThreshold, invertSwap, isLastTarget) {
2264
    var mouseOnAxis = vertical ? evt.clientY : evt.clientX,
2265
      targetLength = vertical ? targetRect.height : targetRect.width,
2266
      targetS1 = vertical ? targetRect.top : targetRect.left,
2267
      targetS2 = vertical ? targetRect.bottom : targetRect.right,
2268
      invert = false;
2269
    if (!invertSwap) {
2270
      // Never invert or create dragEl shadow when target movemenet causes mouse to move past the end of regular swapThreshold
2271
      if (isLastTarget && targetMoveDistance < targetLength * swapThreshold) {
2272
        // multiplied only by swapThreshold because mouse will already be inside target by (1 - threshold) * targetLength / 2
2273
        // check if past first invert threshold on side opposite of lastDirection
2274
        if (!pastFirstInvertThresh && (lastDirection === 1 ? mouseOnAxis > targetS1 + targetLength * invertedSwapThreshold / 2 : mouseOnAxis < targetS2 - targetLength * invertedSwapThreshold / 2)) {
2275
          // past first invert threshold, do not restrict inverted threshold to dragEl shadow
2276
          pastFirstInvertThresh = true;
2277
        }
2278
        if (!pastFirstInvertThresh) {
2279
          // dragEl shadow (target move distance shadow)
2280
          if (lastDirection === 1 ? mouseOnAxis < targetS1 + targetMoveDistance // over dragEl shadow
2281
          : mouseOnAxis > targetS2 - targetMoveDistance) {
2282
            return -lastDirection;
2283
          }
2284
        } else {
2285
          invert = true;
2286
        }
2287
      } else {
2288
        // Regular
2289
        if (mouseOnAxis > targetS1 + targetLength * (1 - swapThreshold) / 2 && mouseOnAxis < targetS2 - targetLength * (1 - swapThreshold) / 2) {
2290
          return _getInsertDirection(target);
2291
        }
2292
      }
2293
    }
2294
    invert = invert || invertSwap;
2295
    if (invert) {
2296
      // Invert of regular
2297
      if (mouseOnAxis < targetS1 + targetLength * invertedSwapThreshold / 2 || mouseOnAxis > targetS2 - targetLength * invertedSwapThreshold / 2) {
2298
        return mouseOnAxis > targetS1 + targetLength / 2 ? 1 : -1;
2299
      }
2300
    }
2301
    return 0;
2302
  }
2303
 
2304
  /**
2305
   * Gets the direction dragEl must be swapped relative to target in order to make it
2306
   * seem that dragEl has been "inserted" into that element's position
2307
   * @param  {HTMLElement} target       The target whose position dragEl is being inserted at
2308
   * @return {Number}                   Direction dragEl must be swapped
2309
   */
2310
  function _getInsertDirection(target) {
2311
    if (index(dragEl) < index(target)) {
2312
      return 1;
2313
    } else {
2314
      return -1;
2315
    }
2316
  }
2317
 
2318
  /**
2319
   * Generate id
2320
   * @param   {HTMLElement} el
2321
   * @returns {String}
2322
   * @private
2323
   */
2324
  function _generateId(el) {
2325
    var str = el.tagName + el.className + el.src + el.href + el.textContent,
2326
      i = str.length,
2327
      sum = 0;
2328
    while (i--) {
2329
      sum += str.charCodeAt(i);
2330
    }
2331
    return sum.toString(36);
2332
  }
2333
  function _saveInputCheckedState(root) {
2334
    savedInputChecked.length = 0;
2335
    var inputs = root.getElementsByTagName('input');
2336
    var idx = inputs.length;
2337
    while (idx--) {
2338
      var el = inputs[idx];
2339
      el.checked && savedInputChecked.push(el);
2340
    }
2341
  }
2342
  function _nextTick(fn) {
2343
    return setTimeout(fn, 0);
2344
  }
2345
  function _cancelNextTick(id) {
2346
    return clearTimeout(id);
2347
  }
2348
 
2349
  // Fixed #973:
2350
  if (documentExists) {
2351
    on(document, 'touchmove', function (evt) {
2352
      if ((Sortable.active || awaitingDragStarted) && evt.cancelable) {
2353
        evt.preventDefault();
2354
      }
2355
    });
2356
  }
2357
 
2358
  // Export utils
2359
  Sortable.utils = {
2360
    on: on,
2361
    off: off,
2362
    css: css,
2363
    find: find,
2364
    is: function is(el, selector) {
2365
      return !!closest(el, selector, el, false);
2366
    },
2367
    extend: extend,
2368
    throttle: throttle,
2369
    closest: closest,
2370
    toggleClass: toggleClass,
2371
    clone: clone,
2372
    index: index,
2373
    nextTick: _nextTick,
2374
    cancelNextTick: _cancelNextTick,
2375
    detectDirection: _detectDirection,
2376
    getChild: getChild
2377
  };
2378
 
2379
  /**
2380
   * Get the Sortable instance of an element
2381
   * @param  {HTMLElement} element The element
2382
   * @return {Sortable|undefined}         The instance of Sortable
2383
   */
2384
  Sortable.get = function (element) {
2385
    return element[expando];
2386
  };
2387
 
2388
  /**
2389
   * Mount a plugin to Sortable
2390
   * @param  {...SortablePlugin|SortablePlugin[]} plugins       Plugins being mounted
2391
   */
2392
  Sortable.mount = function () {
2393
    for (var _len = arguments.length, plugins = new Array(_len), _key = 0; _key < _len; _key++) {
2394
      plugins[_key] = arguments[_key];
2395
    }
2396
    if (plugins[0].constructor === Array) plugins = plugins[0];
2397
    plugins.forEach(function (plugin) {
2398
      if (!plugin.prototype || !plugin.prototype.constructor) {
2399
        throw "Sortable: Mounted plugin must be a constructor function, not ".concat({}.toString.call(plugin));
2400
      }
2401
      if (plugin.utils) Sortable.utils = _objectSpread2(_objectSpread2({}, Sortable.utils), plugin.utils);
2402
      PluginManager.mount(plugin);
2403
    });
2404
  };
2405
 
2406
  /**
2407
   * Create sortable instance
2408
   * @param {HTMLElement}  el
2409
   * @param {Object}      [options]
2410
   */
2411
  Sortable.create = function (el, options) {
2412
    return new Sortable(el, options);
2413
  };
2414
 
2415
  // Export
2416
  Sortable.version = version;
2417
 
2418
  var autoScrolls = [],
2419
    scrollEl,
2420
    scrollRootEl,
2421
    scrolling = false,
2422
    lastAutoScrollX,
2423
    lastAutoScrollY,
2424
    touchEvt$1,
2425
    pointerElemChangedInterval;
2426
  function AutoScrollPlugin() {
2427
    function AutoScroll() {
2428
      this.defaults = {
2429
        scroll: true,
2430
        forceAutoScrollFallback: false,
2431
        scrollSensitivity: 30,
2432
        scrollSpeed: 10,
2433
        bubbleScroll: true
2434
      };
2435
 
2436
      // Bind all private methods
2437
      for (var fn in this) {
2438
        if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {
2439
          this[fn] = this[fn].bind(this);
2440
        }
2441
      }
2442
    }
2443
    AutoScroll.prototype = {
2444
      dragStarted: function dragStarted(_ref) {
2445
        var originalEvent = _ref.originalEvent;
2446
        if (this.sortable.nativeDraggable) {
2447
          on(document, 'dragover', this._handleAutoScroll);
2448
        } else {
2449
          if (this.options.supportPointer) {
2450
            on(document, 'pointermove', this._handleFallbackAutoScroll);
2451
          } else if (originalEvent.touches) {
2452
            on(document, 'touchmove', this._handleFallbackAutoScroll);
2453
          } else {
2454
            on(document, 'mousemove', this._handleFallbackAutoScroll);
2455
          }
2456
        }
2457
      },
2458
      dragOverCompleted: function dragOverCompleted(_ref2) {
2459
        var originalEvent = _ref2.originalEvent;
2460
        // For when bubbling is canceled and using fallback (fallback 'touchmove' always reached)
2461
        if (!this.options.dragOverBubble && !originalEvent.rootEl) {
2462
          this._handleAutoScroll(originalEvent);
2463
        }
2464
      },
2465
      drop: function drop() {
2466
        if (this.sortable.nativeDraggable) {
2467
          off(document, 'dragover', this._handleAutoScroll);
2468
        } else {
2469
          off(document, 'pointermove', this._handleFallbackAutoScroll);
2470
          off(document, 'touchmove', this._handleFallbackAutoScroll);
2471
          off(document, 'mousemove', this._handleFallbackAutoScroll);
2472
        }
2473
        clearPointerElemChangedInterval();
2474
        clearAutoScrolls();
2475
        cancelThrottle();
2476
      },
2477
      nulling: function nulling() {
2478
        touchEvt$1 = scrollRootEl = scrollEl = scrolling = pointerElemChangedInterval = lastAutoScrollX = lastAutoScrollY = null;
2479
        autoScrolls.length = 0;
2480
      },
2481
      _handleFallbackAutoScroll: function _handleFallbackAutoScroll(evt) {
2482
        this._handleAutoScroll(evt, true);
2483
      },
2484
      _handleAutoScroll: function _handleAutoScroll(evt, fallback) {
2485
        var _this = this;
2486
        var x = (evt.touches ? evt.touches[0] : evt).clientX,
2487
          y = (evt.touches ? evt.touches[0] : evt).clientY,
2488
          elem = document.elementFromPoint(x, y);
2489
        touchEvt$1 = evt;
2490
 
2491
        // IE does not seem to have native autoscroll,
2492
        // Edge's autoscroll seems too conditional,
2493
        // MACOS Safari does not have autoscroll,
2494
        // Firefox and Chrome are good
2495
        if (fallback || this.options.forceAutoScrollFallback || Edge || IE11OrLess || Safari) {
2496
          autoScroll(evt, this.options, elem, fallback);
2497
 
2498
          // Listener for pointer element change
2499
          var ogElemScroller = getParentAutoScrollElement(elem, true);
2500
          if (scrolling && (!pointerElemChangedInterval || x !== lastAutoScrollX || y !== lastAutoScrollY)) {
2501
            pointerElemChangedInterval && clearPointerElemChangedInterval();
2502
            // Detect for pointer elem change, emulating native DnD behaviour
2503
            pointerElemChangedInterval = setInterval(function () {
2504
              var newElem = getParentAutoScrollElement(document.elementFromPoint(x, y), true);
2505
              if (newElem !== ogElemScroller) {
2506
                ogElemScroller = newElem;
2507
                clearAutoScrolls();
2508
              }
2509
              autoScroll(evt, _this.options, newElem, fallback);
2510
            }, 10);
2511
            lastAutoScrollX = x;
2512
            lastAutoScrollY = y;
2513
          }
2514
        } else {
2515
          // if DnD is enabled (and browser has good autoscrolling), first autoscroll will already scroll, so get parent autoscroll of first autoscroll
2516
          if (!this.options.bubbleScroll || getParentAutoScrollElement(elem, true) === getWindowScrollingElement()) {
2517
            clearAutoScrolls();
2518
            return;
2519
          }
2520
          autoScroll(evt, this.options, getParentAutoScrollElement(elem, false), false);
2521
        }
2522
      }
2523
    };
2524
    return _extends(AutoScroll, {
2525
      pluginName: 'scroll',
2526
      initializeByDefault: true
2527
    });
2528
  }
2529
  function clearAutoScrolls() {
2530
    autoScrolls.forEach(function (autoScroll) {
2531
      clearInterval(autoScroll.pid);
2532
    });
2533
    autoScrolls = [];
2534
  }
2535
  function clearPointerElemChangedInterval() {
2536
    clearInterval(pointerElemChangedInterval);
2537
  }
2538
  var autoScroll = throttle(function (evt, options, rootEl, isFallback) {
2539
    // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521
2540
    if (!options.scroll) return;
2541
    var x = (evt.touches ? evt.touches[0] : evt).clientX,
2542
      y = (evt.touches ? evt.touches[0] : evt).clientY,
2543
      sens = options.scrollSensitivity,
2544
      speed = options.scrollSpeed,
2545
      winScroller = getWindowScrollingElement();
2546
    var scrollThisInstance = false,
2547
      scrollCustomFn;
2548
 
2549
    // New scroll root, set scrollEl
2550
    if (scrollRootEl !== rootEl) {
2551
      scrollRootEl = rootEl;
2552
      clearAutoScrolls();
2553
      scrollEl = options.scroll;
2554
      scrollCustomFn = options.scrollFn;
2555
      if (scrollEl === true) {
2556
        scrollEl = getParentAutoScrollElement(rootEl, true);
2557
      }
2558
    }
2559
    var layersOut = 0;
2560
    var currentParent = scrollEl;
2561
    do {
2562
      var el = currentParent,
2563
        rect = getRect(el),
2564
        top = rect.top,
2565
        bottom = rect.bottom,
2566
        left = rect.left,
2567
        right = rect.right,
2568
        width = rect.width,
2569
        height = rect.height,
2570
        canScrollX = void 0,
2571
        canScrollY = void 0,
2572
        scrollWidth = el.scrollWidth,
2573
        scrollHeight = el.scrollHeight,
2574
        elCSS = css(el),
2575
        scrollPosX = el.scrollLeft,
2576
        scrollPosY = el.scrollTop;
2577
      if (el === winScroller) {
2578
        canScrollX = width < scrollWidth && (elCSS.overflowX === 'auto' || elCSS.overflowX === 'scroll' || elCSS.overflowX === 'visible');
2579
        canScrollY = height < scrollHeight && (elCSS.overflowY === 'auto' || elCSS.overflowY === 'scroll' || elCSS.overflowY === 'visible');
2580
      } else {
2581
        canScrollX = width < scrollWidth && (elCSS.overflowX === 'auto' || elCSS.overflowX === 'scroll');
2582
        canScrollY = height < scrollHeight && (elCSS.overflowY === 'auto' || elCSS.overflowY === 'scroll');
2583
      }
2584
      var vx = canScrollX && (Math.abs(right - x) <= sens && scrollPosX + width < scrollWidth) - (Math.abs(left - x) <= sens && !!scrollPosX);
2585
      var vy = canScrollY && (Math.abs(bottom - y) <= sens && scrollPosY + height < scrollHeight) - (Math.abs(top - y) <= sens && !!scrollPosY);
2586
      if (!autoScrolls[layersOut]) {
2587
        for (var i = 0; i <= layersOut; i++) {
2588
          if (!autoScrolls[i]) {
2589
            autoScrolls[i] = {};
2590
          }
2591
        }
2592
      }
2593
      if (autoScrolls[layersOut].vx != vx || autoScrolls[layersOut].vy != vy || autoScrolls[layersOut].el !== el) {
2594
        autoScrolls[layersOut].el = el;
2595
        autoScrolls[layersOut].vx = vx;
2596
        autoScrolls[layersOut].vy = vy;
2597
        clearInterval(autoScrolls[layersOut].pid);
2598
        if (vx != 0 || vy != 0) {
2599
          scrollThisInstance = true;
2600
          /* jshint loopfunc:true */
2601
          autoScrolls[layersOut].pid = setInterval(function () {
2602
            // emulate drag over during autoscroll (fallback), emulating native DnD behaviour
2603
            if (isFallback && this.layer === 0) {
2604
              Sortable.active._onTouchMove(touchEvt$1); // To move ghost if it is positioned absolutely
2605
            }
2606
            var scrollOffsetY = autoScrolls[this.layer].vy ? autoScrolls[this.layer].vy * speed : 0;
2607
            var scrollOffsetX = autoScrolls[this.layer].vx ? autoScrolls[this.layer].vx * speed : 0;
2608
            if (typeof scrollCustomFn === 'function') {
2609
              if (scrollCustomFn.call(Sortable.dragged.parentNode[expando], scrollOffsetX, scrollOffsetY, evt, touchEvt$1, autoScrolls[this.layer].el) !== 'continue') {
2610
                return;
2611
              }
2612
            }
2613
            scrollBy(autoScrolls[this.layer].el, scrollOffsetX, scrollOffsetY);
2614
          }.bind({
2615
            layer: layersOut
2616
          }), 24);
2617
        }
2618
      }
2619
      layersOut++;
2620
    } while (options.bubbleScroll && currentParent !== winScroller && (currentParent = getParentAutoScrollElement(currentParent, false)));
2621
    scrolling = scrollThisInstance; // in case another function catches scrolling as false in between when it is not
2622
  }, 30);
2623
 
2624
  var drop = function drop(_ref) {
2625
    var originalEvent = _ref.originalEvent,
2626
      putSortable = _ref.putSortable,
2627
      dragEl = _ref.dragEl,
2628
      activeSortable = _ref.activeSortable,
2629
      dispatchSortableEvent = _ref.dispatchSortableEvent,
2630
      hideGhostForTarget = _ref.hideGhostForTarget,
2631
      unhideGhostForTarget = _ref.unhideGhostForTarget;
2632
    if (!originalEvent) return;
2633
    var toSortable = putSortable || activeSortable;
2634
    hideGhostForTarget();
2635
    var touch = originalEvent.changedTouches && originalEvent.changedTouches.length ? originalEvent.changedTouches[0] : originalEvent;
2636
    var target = document.elementFromPoint(touch.clientX, touch.clientY);
2637
    unhideGhostForTarget();
2638
    if (toSortable && !toSortable.el.contains(target)) {
2639
      dispatchSortableEvent('spill');
2640
      this.onSpill({
2641
        dragEl: dragEl,
2642
        putSortable: putSortable
2643
      });
2644
    }
2645
  };
2646
  function Revert() {}
2647
  Revert.prototype = {
2648
    startIndex: null,
2649
    dragStart: function dragStart(_ref2) {
2650
      var oldDraggableIndex = _ref2.oldDraggableIndex;
2651
      this.startIndex = oldDraggableIndex;
2652
    },
2653
    onSpill: function onSpill(_ref3) {
2654
      var dragEl = _ref3.dragEl,
2655
        putSortable = _ref3.putSortable;
2656
      this.sortable.captureAnimationState();
2657
      if (putSortable) {
2658
        putSortable.captureAnimationState();
2659
      }
2660
      var nextSibling = getChild(this.sortable.el, this.startIndex, this.options);
2661
      if (nextSibling) {
2662
        this.sortable.el.insertBefore(dragEl, nextSibling);
2663
      } else {
2664
        this.sortable.el.appendChild(dragEl);
2665
      }
2666
      this.sortable.animateAll();
2667
      if (putSortable) {
2668
        putSortable.animateAll();
2669
      }
2670
    },
2671
    drop: drop
2672
  };
2673
  _extends(Revert, {
2674
    pluginName: 'revertOnSpill'
2675
  });
2676
  function Remove() {}
2677
  Remove.prototype = {
2678
    onSpill: function onSpill(_ref4) {
2679
      var dragEl = _ref4.dragEl,
2680
        putSortable = _ref4.putSortable;
2681
      var parentSortable = putSortable || this.sortable;
2682
      parentSortable.captureAnimationState();
2683
      dragEl.parentNode && dragEl.parentNode.removeChild(dragEl);
2684
      parentSortable.animateAll();
2685
    },
2686
    drop: drop
2687
  };
2688
  _extends(Remove, {
2689
    pluginName: 'removeOnSpill'
2690
  });
2691
 
2692
  var lastSwapEl;
2693
  function SwapPlugin() {
2694
    function Swap() {
2695
      this.defaults = {
2696
        swapClass: 'sortable-swap-highlight'
2697
      };
2698
    }
2699
    Swap.prototype = {
2700
      dragStart: function dragStart(_ref) {
2701
        var dragEl = _ref.dragEl;
2702
        lastSwapEl = dragEl;
2703
      },
2704
      dragOverValid: function dragOverValid(_ref2) {
2705
        var completed = _ref2.completed,
2706
          target = _ref2.target,
2707
          onMove = _ref2.onMove,
2708
          activeSortable = _ref2.activeSortable,
2709
          changed = _ref2.changed,
2710
          cancel = _ref2.cancel;
2711
        if (!activeSortable.options.swap) return;
2712
        var el = this.sortable.el,
2713
          options = this.options;
2714
        if (target && target !== el) {
2715
          var prevSwapEl = lastSwapEl;
2716
          if (onMove(target) !== false) {
2717
            toggleClass(target, options.swapClass, true);
2718
            lastSwapEl = target;
2719
          } else {
2720
            lastSwapEl = null;
2721
          }
2722
          if (prevSwapEl && prevSwapEl !== lastSwapEl) {
2723
            toggleClass(prevSwapEl, options.swapClass, false);
2724
          }
2725
        }
2726
        changed();
2727
        completed(true);
2728
        cancel();
2729
      },
2730
      drop: function drop(_ref3) {
2731
        var activeSortable = _ref3.activeSortable,
2732
          putSortable = _ref3.putSortable,
2733
          dragEl = _ref3.dragEl;
2734
        var toSortable = putSortable || this.sortable;
2735
        var options = this.options;
2736
        lastSwapEl && toggleClass(lastSwapEl, options.swapClass, false);
2737
        if (lastSwapEl && (options.swap || putSortable && putSortable.options.swap)) {
2738
          if (dragEl !== lastSwapEl) {
2739
            toSortable.captureAnimationState();
2740
            if (toSortable !== activeSortable) activeSortable.captureAnimationState();
2741
            swapNodes(dragEl, lastSwapEl);
2742
            toSortable.animateAll();
2743
            if (toSortable !== activeSortable) activeSortable.animateAll();
2744
          }
2745
        }
2746
      },
2747
      nulling: function nulling() {
2748
        lastSwapEl = null;
2749
      }
2750
    };
2751
    return _extends(Swap, {
2752
      pluginName: 'swap',
2753
      eventProperties: function eventProperties() {
2754
        return {
2755
          swapItem: lastSwapEl
2756
        };
2757
      }
2758
    });
2759
  }
2760
  function swapNodes(n1, n2) {
2761
    var p1 = n1.parentNode,
2762
      p2 = n2.parentNode,
2763
      i1,
2764
      i2;
2765
    if (!p1 || !p2 || p1.isEqualNode(n2) || p2.isEqualNode(n1)) return;
2766
    i1 = index(n1);
2767
    i2 = index(n2);
2768
    if (p1.isEqualNode(p2) && i1 < i2) {
2769
      i2++;
2770
    }
2771
    p1.insertBefore(n2, p1.children[i1]);
2772
    p2.insertBefore(n1, p2.children[i2]);
2773
  }
2774
 
2775
  var multiDragElements = [],
2776
    multiDragClones = [],
2777
    lastMultiDragSelect,
2778
    // for selection with modifier key down (SHIFT)
2779
    multiDragSortable,
2780
    initialFolding = false,
2781
    // Initial multi-drag fold when drag started
2782
    folding = false,
2783
    // Folding any other time
2784
    dragStarted = false,
2785
    dragEl$1,
2786
    clonesFromRect,
2787
    clonesHidden;
2788
  function MultiDragPlugin() {
2789
    function MultiDrag(sortable) {
2790
      // Bind all private methods
2791
      for (var fn in this) {
2792
        if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {
2793
          this[fn] = this[fn].bind(this);
2794
        }
2795
      }
2796
      if (!sortable.options.avoidImplicitDeselect) {
2797
        if (sortable.options.supportPointer) {
2798
          on(document, 'pointerup', this._deselectMultiDrag);
2799
        } else {
2800
          on(document, 'mouseup', this._deselectMultiDrag);
2801
          on(document, 'touchend', this._deselectMultiDrag);
2802
        }
2803
      }
2804
      on(document, 'keydown', this._checkKeyDown);
2805
      on(document, 'keyup', this._checkKeyUp);
2806
      this.defaults = {
2807
        selectedClass: 'sortable-selected',
2808
        multiDragKey: null,
2809
        avoidImplicitDeselect: false,
2810
        setData: function setData(dataTransfer, dragEl) {
2811
          var data = '';
2812
          if (multiDragElements.length && multiDragSortable === sortable) {
2813
            multiDragElements.forEach(function (multiDragElement, i) {
2814
              data += (!i ? '' : ', ') + multiDragElement.textContent;
2815
            });
2816
          } else {
2817
            data = dragEl.textContent;
2818
          }
2819
          dataTransfer.setData('Text', data);
2820
        }
2821
      };
2822
    }
2823
    MultiDrag.prototype = {
2824
      multiDragKeyDown: false,
2825
      isMultiDrag: false,
2826
      delayStartGlobal: function delayStartGlobal(_ref) {
2827
        var dragged = _ref.dragEl;
2828
        dragEl$1 = dragged;
2829
      },
2830
      delayEnded: function delayEnded() {
2831
        this.isMultiDrag = ~multiDragElements.indexOf(dragEl$1);
2832
      },
2833
      setupClone: function setupClone(_ref2) {
2834
        var sortable = _ref2.sortable,
2835
          cancel = _ref2.cancel;
2836
        if (!this.isMultiDrag) return;
2837
        for (var i = 0; i < multiDragElements.length; i++) {
2838
          multiDragClones.push(clone(multiDragElements[i]));
2839
          multiDragClones[i].sortableIndex = multiDragElements[i].sortableIndex;
2840
          multiDragClones[i].draggable = false;
2841
          multiDragClones[i].style['will-change'] = '';
2842
          toggleClass(multiDragClones[i], this.options.selectedClass, false);
2843
          multiDragElements[i] === dragEl$1 && toggleClass(multiDragClones[i], this.options.chosenClass, false);
2844
        }
2845
        sortable._hideClone();
2846
        cancel();
2847
      },
2848
      clone: function clone(_ref3) {
2849
        var sortable = _ref3.sortable,
2850
          rootEl = _ref3.rootEl,
2851
          dispatchSortableEvent = _ref3.dispatchSortableEvent,
2852
          cancel = _ref3.cancel;
2853
        if (!this.isMultiDrag) return;
2854
        if (!this.options.removeCloneOnHide) {
2855
          if (multiDragElements.length && multiDragSortable === sortable) {
2856
            insertMultiDragClones(true, rootEl);
2857
            dispatchSortableEvent('clone');
2858
            cancel();
2859
          }
2860
        }
2861
      },
2862
      showClone: function showClone(_ref4) {
2863
        var cloneNowShown = _ref4.cloneNowShown,
2864
          rootEl = _ref4.rootEl,
2865
          cancel = _ref4.cancel;
2866
        if (!this.isMultiDrag) return;
2867
        insertMultiDragClones(false, rootEl);
2868
        multiDragClones.forEach(function (clone) {
2869
          css(clone, 'display', '');
2870
        });
2871
        cloneNowShown();
2872
        clonesHidden = false;
2873
        cancel();
2874
      },
2875
      hideClone: function hideClone(_ref5) {
2876
        var _this = this;
2877
        var sortable = _ref5.sortable,
2878
          cloneNowHidden = _ref5.cloneNowHidden,
2879
          cancel = _ref5.cancel;
2880
        if (!this.isMultiDrag) return;
2881
        multiDragClones.forEach(function (clone) {
2882
          css(clone, 'display', 'none');
2883
          if (_this.options.removeCloneOnHide && clone.parentNode) {
2884
            clone.parentNode.removeChild(clone);
2885
          }
2886
        });
2887
        cloneNowHidden();
2888
        clonesHidden = true;
2889
        cancel();
2890
      },
2891
      dragStartGlobal: function dragStartGlobal(_ref6) {
2892
        var sortable = _ref6.sortable;
2893
        if (!this.isMultiDrag && multiDragSortable) {
2894
          multiDragSortable.multiDrag._deselectMultiDrag();
2895
        }
2896
        multiDragElements.forEach(function (multiDragElement) {
2897
          multiDragElement.sortableIndex = index(multiDragElement);
2898
        });
2899
 
2900
        // Sort multi-drag elements
2901
        multiDragElements = multiDragElements.sort(function (a, b) {
2902
          return a.sortableIndex - b.sortableIndex;
2903
        });
2904
        dragStarted = true;
2905
      },
2906
      dragStarted: function dragStarted(_ref7) {
2907
        var _this2 = this;
2908
        var sortable = _ref7.sortable;
2909
        if (!this.isMultiDrag) return;
2910
        if (this.options.sort) {
2911
          // Capture rects,
2912
          // hide multi drag elements (by positioning them absolute),
2913
          // set multi drag elements rects to dragRect,
2914
          // show multi drag elements,
2915
          // animate to rects,
2916
          // unset rects & remove from DOM
2917
 
2918
          sortable.captureAnimationState();
2919
          if (this.options.animation) {
2920
            multiDragElements.forEach(function (multiDragElement) {
2921
              if (multiDragElement === dragEl$1) return;
2922
              css(multiDragElement, 'position', 'absolute');
2923
            });
2924
            var dragRect = getRect(dragEl$1, false, true, true);
2925
            multiDragElements.forEach(function (multiDragElement) {
2926
              if (multiDragElement === dragEl$1) return;
2927
              setRect(multiDragElement, dragRect);
2928
            });
2929
            folding = true;
2930
            initialFolding = true;
2931
          }
2932
        }
2933
        sortable.animateAll(function () {
2934
          folding = false;
2935
          initialFolding = false;
2936
          if (_this2.options.animation) {
2937
            multiDragElements.forEach(function (multiDragElement) {
2938
              unsetRect(multiDragElement);
2939
            });
2940
          }
2941
 
2942
          // Remove all auxiliary multidrag items from el, if sorting enabled
2943
          if (_this2.options.sort) {
2944
            removeMultiDragElements();
2945
          }
2946
        });
2947
      },
2948
      dragOver: function dragOver(_ref8) {
2949
        var target = _ref8.target,
2950
          completed = _ref8.completed,
2951
          cancel = _ref8.cancel;
2952
        if (folding && ~multiDragElements.indexOf(target)) {
2953
          completed(false);
2954
          cancel();
2955
        }
2956
      },
2957
      revert: function revert(_ref9) {
2958
        var fromSortable = _ref9.fromSortable,
2959
          rootEl = _ref9.rootEl,
2960
          sortable = _ref9.sortable,
2961
          dragRect = _ref9.dragRect;
2962
        if (multiDragElements.length > 1) {
2963
          // Setup unfold animation
2964
          multiDragElements.forEach(function (multiDragElement) {
2965
            sortable.addAnimationState({
2966
              target: multiDragElement,
2967
              rect: folding ? getRect(multiDragElement) : dragRect
2968
            });
2969
            unsetRect(multiDragElement);
2970
            multiDragElement.fromRect = dragRect;
2971
            fromSortable.removeAnimationState(multiDragElement);
2972
          });
2973
          folding = false;
2974
          insertMultiDragElements(!this.options.removeCloneOnHide, rootEl);
2975
        }
2976
      },
2977
      dragOverCompleted: function dragOverCompleted(_ref10) {
2978
        var sortable = _ref10.sortable,
2979
          isOwner = _ref10.isOwner,
2980
          insertion = _ref10.insertion,
2981
          activeSortable = _ref10.activeSortable,
2982
          parentEl = _ref10.parentEl,
2983
          putSortable = _ref10.putSortable;
2984
        var options = this.options;
2985
        if (insertion) {
2986
          // Clones must be hidden before folding animation to capture dragRectAbsolute properly
2987
          if (isOwner) {
2988
            activeSortable._hideClone();
2989
          }
2990
          initialFolding = false;
2991
          // If leaving sort:false root, or already folding - Fold to new location
2992
          if (options.animation && multiDragElements.length > 1 && (folding || !isOwner && !activeSortable.options.sort && !putSortable)) {
2993
            // Fold: Set all multi drag elements's rects to dragEl's rect when multi-drag elements are invisible
2994
            var dragRectAbsolute = getRect(dragEl$1, false, true, true);
2995
            multiDragElements.forEach(function (multiDragElement) {
2996
              if (multiDragElement === dragEl$1) return;
2997
              setRect(multiDragElement, dragRectAbsolute);
2998
 
2999
              // Move element(s) to end of parentEl so that it does not interfere with multi-drag clones insertion if they are inserted
3000
              // while folding, and so that we can capture them again because old sortable will no longer be fromSortable
3001
              parentEl.appendChild(multiDragElement);
3002
            });
3003
            folding = true;
3004
          }
3005
 
3006
          // Clones must be shown (and check to remove multi drags) after folding when interfering multiDragElements are moved out
3007
          if (!isOwner) {
3008
            // Only remove if not folding (folding will remove them anyways)
3009
            if (!folding) {
3010
              removeMultiDragElements();
3011
            }
3012
            if (multiDragElements.length > 1) {
3013
              var clonesHiddenBefore = clonesHidden;
3014
              activeSortable._showClone(sortable);
3015
 
3016
              // Unfold animation for clones if showing from hidden
3017
              if (activeSortable.options.animation && !clonesHidden && clonesHiddenBefore) {
3018
                multiDragClones.forEach(function (clone) {
3019
                  activeSortable.addAnimationState({
3020
                    target: clone,
3021
                    rect: clonesFromRect
3022
                  });
3023
                  clone.fromRect = clonesFromRect;
3024
                  clone.thisAnimationDuration = null;
3025
                });
3026
              }
3027
            } else {
3028
              activeSortable._showClone(sortable);
3029
            }
3030
          }
3031
        }
3032
      },
3033
      dragOverAnimationCapture: function dragOverAnimationCapture(_ref11) {
3034
        var dragRect = _ref11.dragRect,
3035
          isOwner = _ref11.isOwner,
3036
          activeSortable = _ref11.activeSortable;
3037
        multiDragElements.forEach(function (multiDragElement) {
3038
          multiDragElement.thisAnimationDuration = null;
3039
        });
3040
        if (activeSortable.options.animation && !isOwner && activeSortable.multiDrag.isMultiDrag) {
3041
          clonesFromRect = _extends({}, dragRect);
3042
          var dragMatrix = matrix(dragEl$1, true);
3043
          clonesFromRect.top -= dragMatrix.f;
3044
          clonesFromRect.left -= dragMatrix.e;
3045
        }
3046
      },
3047
      dragOverAnimationComplete: function dragOverAnimationComplete() {
3048
        if (folding) {
3049
          folding = false;
3050
          removeMultiDragElements();
3051
        }
3052
      },
3053
      drop: function drop(_ref12) {
3054
        var evt = _ref12.originalEvent,
3055
          rootEl = _ref12.rootEl,
3056
          parentEl = _ref12.parentEl,
3057
          sortable = _ref12.sortable,
3058
          dispatchSortableEvent = _ref12.dispatchSortableEvent,
3059
          oldIndex = _ref12.oldIndex,
3060
          putSortable = _ref12.putSortable;
3061
        var toSortable = putSortable || this.sortable;
3062
        if (!evt) return;
3063
        var options = this.options,
3064
          children = parentEl.children;
3065
 
3066
        // Multi-drag selection
3067
        if (!dragStarted) {
3068
          if (options.multiDragKey && !this.multiDragKeyDown) {
3069
            this._deselectMultiDrag();
3070
          }
3071
          toggleClass(dragEl$1, options.selectedClass, !~multiDragElements.indexOf(dragEl$1));
3072
          if (!~multiDragElements.indexOf(dragEl$1)) {
3073
            multiDragElements.push(dragEl$1);
3074
            dispatchEvent({
3075
              sortable: sortable,
3076
              rootEl: rootEl,
3077
              name: 'select',
3078
              targetEl: dragEl$1,
3079
              originalEvent: evt
3080
            });
3081
 
3082
            // Modifier activated, select from last to dragEl
3083
            if (evt.shiftKey && lastMultiDragSelect && sortable.el.contains(lastMultiDragSelect)) {
3084
              var lastIndex = index(lastMultiDragSelect),
3085
                currentIndex = index(dragEl$1);
3086
              if (~lastIndex && ~currentIndex && lastIndex !== currentIndex) {
3087
                // Must include lastMultiDragSelect (select it), in case modified selection from no selection
3088
                // (but previous selection existed)
3089
                var n, i;
3090
                if (currentIndex > lastIndex) {
3091
                  i = lastIndex;
3092
                  n = currentIndex;
3093
                } else {
3094
                  i = currentIndex;
3095
                  n = lastIndex + 1;
3096
                }
3097
                for (; i < n; i++) {
3098
                  if (~multiDragElements.indexOf(children[i])) continue;
3099
                  toggleClass(children[i], options.selectedClass, true);
3100
                  multiDragElements.push(children[i]);
3101
                  dispatchEvent({
3102
                    sortable: sortable,
3103
                    rootEl: rootEl,
3104
                    name: 'select',
3105
                    targetEl: children[i],
3106
                    originalEvent: evt
3107
                  });
3108
                }
3109
              }
3110
            } else {
3111
              lastMultiDragSelect = dragEl$1;
3112
            }
3113
            multiDragSortable = toSortable;
3114
          } else {
3115
            multiDragElements.splice(multiDragElements.indexOf(dragEl$1), 1);
3116
            lastMultiDragSelect = null;
3117
            dispatchEvent({
3118
              sortable: sortable,
3119
              rootEl: rootEl,
3120
              name: 'deselect',
3121
              targetEl: dragEl$1,
3122
              originalEvent: evt
3123
            });
3124
          }
3125
        }
3126
 
3127
        // Multi-drag drop
3128
        if (dragStarted && this.isMultiDrag) {
3129
          folding = false;
3130
          // Do not "unfold" after around dragEl if reverted
3131
          if ((parentEl[expando].options.sort || parentEl !== rootEl) && multiDragElements.length > 1) {
3132
            var dragRect = getRect(dragEl$1),
3133
              multiDragIndex = index(dragEl$1, ':not(.' + this.options.selectedClass + ')');
3134
            if (!initialFolding && options.animation) dragEl$1.thisAnimationDuration = null;
3135
            toSortable.captureAnimationState();
3136
            if (!initialFolding) {
3137
              if (options.animation) {
3138
                dragEl$1.fromRect = dragRect;
3139
                multiDragElements.forEach(function (multiDragElement) {
3140
                  multiDragElement.thisAnimationDuration = null;
3141
                  if (multiDragElement !== dragEl$1) {
3142
                    var rect = folding ? getRect(multiDragElement) : dragRect;
3143
                    multiDragElement.fromRect = rect;
3144
 
3145
                    // Prepare unfold animation
3146
                    toSortable.addAnimationState({
3147
                      target: multiDragElement,
3148
                      rect: rect
3149
                    });
3150
                  }
3151
                });
3152
              }
3153
 
3154
              // Multi drag elements are not necessarily removed from the DOM on drop, so to reinsert
3155
              // properly they must all be removed
3156
              removeMultiDragElements();
3157
              multiDragElements.forEach(function (multiDragElement) {
3158
                if (children[multiDragIndex]) {
3159
                  parentEl.insertBefore(multiDragElement, children[multiDragIndex]);
3160
                } else {
3161
                  parentEl.appendChild(multiDragElement);
3162
                }
3163
                multiDragIndex++;
3164
              });
3165
 
3166
              // If initial folding is done, the elements may have changed position because they are now
3167
              // unfolding around dragEl, even though dragEl may not have his index changed, so update event
3168
              // must be fired here as Sortable will not.
3169
              if (oldIndex === index(dragEl$1)) {
3170
                var update = false;
3171
                multiDragElements.forEach(function (multiDragElement) {
3172
                  if (multiDragElement.sortableIndex !== index(multiDragElement)) {
3173
                    update = true;
3174
                    return;
3175
                  }
3176
                });
3177
                if (update) {
3178
                  dispatchSortableEvent('update');
3179
                  dispatchSortableEvent('sort');
3180
                }
3181
              }
3182
            }
3183
 
3184
            // Must be done after capturing individual rects (scroll bar)
3185
            multiDragElements.forEach(function (multiDragElement) {
3186
              unsetRect(multiDragElement);
3187
            });
3188
            toSortable.animateAll();
3189
          }
3190
          multiDragSortable = toSortable;
3191
        }
3192
 
3193
        // Remove clones if necessary
3194
        if (rootEl === parentEl || putSortable && putSortable.lastPutMode !== 'clone') {
3195
          multiDragClones.forEach(function (clone) {
3196
            clone.parentNode && clone.parentNode.removeChild(clone);
3197
          });
3198
        }
3199
      },
3200
      nullingGlobal: function nullingGlobal() {
3201
        this.isMultiDrag = dragStarted = false;
3202
        multiDragClones.length = 0;
3203
      },
3204
      destroyGlobal: function destroyGlobal() {
3205
        this._deselectMultiDrag();
3206
        off(document, 'pointerup', this._deselectMultiDrag);
3207
        off(document, 'mouseup', this._deselectMultiDrag);
3208
        off(document, 'touchend', this._deselectMultiDrag);
3209
        off(document, 'keydown', this._checkKeyDown);
3210
        off(document, 'keyup', this._checkKeyUp);
3211
      },
3212
      _deselectMultiDrag: function _deselectMultiDrag(evt) {
3213
        if (typeof dragStarted !== "undefined" && dragStarted) return;
3214
 
3215
        // Only deselect if selection is in this sortable
3216
        if (multiDragSortable !== this.sortable) return;
3217
 
3218
        // Only deselect if target is not item in this sortable
3219
        if (evt && closest(evt.target, this.options.draggable, this.sortable.el, false)) return;
3220
 
3221
        // Only deselect if left click
3222
        if (evt && evt.button !== 0) return;
3223
        while (multiDragElements.length) {
3224
          var el = multiDragElements[0];
3225
          toggleClass(el, this.options.selectedClass, false);
3226
          multiDragElements.shift();
3227
          dispatchEvent({
3228
            sortable: this.sortable,
3229
            rootEl: this.sortable.el,
3230
            name: 'deselect',
3231
            targetEl: el,
3232
            originalEvent: evt
3233
          });
3234
        }
3235
      },
3236
      _checkKeyDown: function _checkKeyDown(evt) {
3237
        if (evt.key === this.options.multiDragKey) {
3238
          this.multiDragKeyDown = true;
3239
        }
3240
      },
3241
      _checkKeyUp: function _checkKeyUp(evt) {
3242
        if (evt.key === this.options.multiDragKey) {
3243
          this.multiDragKeyDown = false;
3244
        }
3245
      }
3246
    };
3247
    return _extends(MultiDrag, {
3248
      // Static methods & properties
3249
      pluginName: 'multiDrag',
3250
      utils: {
3251
        /**
3252
         * Selects the provided multi-drag item
3253
         * @param  {HTMLElement} el    The element to be selected
3254
         */
3255
        select: function select(el) {
3256
          var sortable = el.parentNode[expando];
3257
          if (!sortable || !sortable.options.multiDrag || ~multiDragElements.indexOf(el)) return;
3258
          if (multiDragSortable && multiDragSortable !== sortable) {
3259
            multiDragSortable.multiDrag._deselectMultiDrag();
3260
            multiDragSortable = sortable;
3261
          }
3262
          toggleClass(el, sortable.options.selectedClass, true);
3263
          multiDragElements.push(el);
3264
        },
3265
        /**
3266
         * Deselects the provided multi-drag item
3267
         * @param  {HTMLElement} el    The element to be deselected
3268
         */
3269
        deselect: function deselect(el) {
3270
          var sortable = el.parentNode[expando],
3271
            index = multiDragElements.indexOf(el);
3272
          if (!sortable || !sortable.options.multiDrag || !~index) return;
3273
          toggleClass(el, sortable.options.selectedClass, false);
3274
          multiDragElements.splice(index, 1);
3275
        }
3276
      },
3277
      eventProperties: function eventProperties() {
3278
        var _this3 = this;
3279
        var oldIndicies = [],
3280
          newIndicies = [];
3281
        multiDragElements.forEach(function (multiDragElement) {
3282
          oldIndicies.push({
3283
            multiDragElement: multiDragElement,
3284
            index: multiDragElement.sortableIndex
3285
          });
3286
 
3287
          // multiDragElements will already be sorted if folding
3288
          var newIndex;
3289
          if (folding && multiDragElement !== dragEl$1) {
3290
            newIndex = -1;
3291
          } else if (folding) {
3292
            newIndex = index(multiDragElement, ':not(.' + _this3.options.selectedClass + ')');
3293
          } else {
3294
            newIndex = index(multiDragElement);
3295
          }
3296
          newIndicies.push({
3297
            multiDragElement: multiDragElement,
3298
            index: newIndex
3299
          });
3300
        });
3301
        return {
3302
          items: _toConsumableArray(multiDragElements),
3303
          clones: [].concat(multiDragClones),
3304
          oldIndicies: oldIndicies,
3305
          newIndicies: newIndicies
3306
        };
3307
      },
3308
      optionListeners: {
3309
        multiDragKey: function multiDragKey(key) {
3310
          key = key.toLowerCase();
3311
          if (key === 'ctrl') {
3312
            key = 'Control';
3313
          } else if (key.length > 1) {
3314
            key = key.charAt(0).toUpperCase() + key.substr(1);
3315
          }
3316
          return key;
3317
        }
3318
      }
3319
    });
3320
  }
3321
  function insertMultiDragElements(clonesInserted, rootEl) {
3322
    multiDragElements.forEach(function (multiDragElement, i) {
3323
      var target = rootEl.children[multiDragElement.sortableIndex + (clonesInserted ? Number(i) : 0)];
3324
      if (target) {
3325
        rootEl.insertBefore(multiDragElement, target);
3326
      } else {
3327
        rootEl.appendChild(multiDragElement);
3328
      }
3329
    });
3330
  }
3331
 
3332
  /**
3333
   * Insert multi-drag clones
3334
   * @param  {[Boolean]} elementsInserted  Whether the multi-drag elements are inserted
3335
   * @param  {HTMLElement} rootEl
3336
   */
3337
  function insertMultiDragClones(elementsInserted, rootEl) {
3338
    multiDragClones.forEach(function (clone, i) {
3339
      var target = rootEl.children[clone.sortableIndex + (elementsInserted ? Number(i) : 0)];
3340
      if (target) {
3341
        rootEl.insertBefore(clone, target);
3342
      } else {
3343
        rootEl.appendChild(clone);
3344
      }
3345
    });
3346
  }
3347
  function removeMultiDragElements() {
3348
    multiDragElements.forEach(function (multiDragElement) {
3349
      if (multiDragElement === dragEl$1) return;
3350
      multiDragElement.parentNode && multiDragElement.parentNode.removeChild(multiDragElement);
3351
    });
3352
  }
3353
 
3354
  Sortable.mount(new AutoScrollPlugin());
3355
  Sortable.mount(Remove, Revert);
3356
 
3357
  Sortable.mount(new SwapPlugin());
3358
  Sortable.mount(new MultiDragPlugin());
3359
 
3360
  return Sortable;
3361
 
3362
})));