govuk_publishing_components 43.0.1 → 43.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-reporter.js +39 -17
  3. data/app/assets/stylesheets/component_guide/application.scss +1 -1
  4. data/app/assets/stylesheets/govuk_publishing_components/components/_cross-service-header.scss +3 -1
  5. data/app/assets/stylesheets/govuk_publishing_components/components/_intervention.scss +1 -1
  6. data/app/assets/stylesheets/govuk_publishing_components/components/_inverse-header.scss +3 -1
  7. data/app/assets/stylesheets/govuk_publishing_components/components/_layout-footer.scss +32 -3
  8. data/app/assets/stylesheets/govuk_publishing_components/components/_layout-header.scss +1 -3
  9. data/app/assets/stylesheets/govuk_publishing_components/components/_layout-super-navigation-header.scss +1 -1
  10. data/app/assets/stylesheets/govuk_publishing_components/components/_metadata.scss +1 -1
  11. data/app/assets/stylesheets/govuk_publishing_components/components/_phase-banner.scss +1 -1
  12. data/app/assets/stylesheets/govuk_publishing_components/components/_step-by-step-nav-header.scss +1 -1
  13. data/app/assets/stylesheets/govuk_publishing_components/components/_step-by-step-nav-related.scss +1 -1
  14. data/app/assets/stylesheets/govuk_publishing_components/components/_success-alert.scss +1 -1
  15. data/app/assets/stylesheets/govuk_publishing_components/components/_table.scss +1 -1
  16. data/app/assets/stylesheets/govuk_publishing_components/components/_warning-text.scss +1 -1
  17. data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_button.scss +1 -1
  18. data/app/assets/stylesheets/govuk_publishing_components/components/govspeak/_highlight-answer.scss +2 -4
  19. data/app/assets/stylesheets/govuk_publishing_components/govuk_frontend_support.scss +4 -0
  20. data/app/views/govuk_publishing_components/components/_layout_footer.html.erb +1 -1
  21. data/app/views/govuk_publishing_components/components/layout_header/_navigation_items.html.erb +6 -3
  22. data/app/views/govuk_publishing_components/components/layout_header/_search.html.erb +7 -2
  23. data/lib/govuk_publishing_components/version.rb +1 -1
  24. data/node_modules/sortablejs/README.md +3 -2
  25. data/node_modules/sortablejs/Sortable.js +5 -4
  26. data/node_modules/sortablejs/Sortable.min.js +2 -2
  27. data/node_modules/sortablejs/modular/sortable.complete.esm.js +5 -4
  28. data/node_modules/sortablejs/modular/sortable.core.esm.js +5 -4
  29. data/node_modules/sortablejs/modular/sortable.esm.js +5 -4
  30. data/node_modules/sortablejs/package.json +3 -2
  31. data/node_modules/sortablejs/src/Animation.js +175 -0
  32. data/node_modules/sortablejs/src/BrowserInfo.js +12 -0
  33. data/node_modules/sortablejs/src/EventDispatcher.js +57 -0
  34. data/node_modules/sortablejs/src/PluginManager.js +94 -0
  35. data/node_modules/sortablejs/src/Sortable.js +2011 -0
  36. data/node_modules/sortablejs/src/utils.js +595 -0
  37. metadata +8 -2
@@ -0,0 +1,2011 @@
1
+ /**!
2
+ * Sortable
3
+ * @author RubaXa <trash@rubaxa.org>
4
+ * @author owenm <owen23355@gmail.com>
5
+ * @license MIT
6
+ */
7
+
8
+ import { version } from '../package.json';
9
+
10
+ import { IE11OrLess, Edge, FireFox, Safari, IOS, ChromeForAndroid } from './BrowserInfo.js';
11
+
12
+ import AnimationStateManager from './Animation.js';
13
+
14
+ import PluginManager from './PluginManager.js';
15
+
16
+ import dispatchEvent from './EventDispatcher.js';
17
+
18
+ import {
19
+ on,
20
+ off,
21
+ closest,
22
+ toggleClass,
23
+ css,
24
+ matrix,
25
+ find,
26
+ getWindowScrollingElement,
27
+ getRect,
28
+ isScrolledPast,
29
+ getChild,
30
+ lastChild,
31
+ index,
32
+ getRelativeScrollOffset,
33
+ extend,
34
+ throttle,
35
+ scrollBy,
36
+ clone,
37
+ expando,
38
+ getChildContainingRectFromElement,
39
+ getParentOrHost
40
+ } from './utils.js';
41
+
42
+
43
+ let pluginEvent = function(eventName, sortable, { evt: originalEvent, ...data } = {}) {
44
+ PluginManager.pluginEvent.bind(Sortable)(eventName, sortable, {
45
+ dragEl,
46
+ parentEl,
47
+ ghostEl,
48
+ rootEl,
49
+ nextEl,
50
+ lastDownEl,
51
+ cloneEl,
52
+ cloneHidden,
53
+ dragStarted: moved,
54
+ putSortable,
55
+ activeSortable: Sortable.active,
56
+ originalEvent,
57
+
58
+ oldIndex,
59
+ oldDraggableIndex,
60
+ newIndex,
61
+ newDraggableIndex,
62
+
63
+ hideGhostForTarget: _hideGhostForTarget,
64
+ unhideGhostForTarget: _unhideGhostForTarget,
65
+
66
+
67
+ cloneNowHidden() {
68
+ cloneHidden = true;
69
+ },
70
+ cloneNowShown() {
71
+ cloneHidden = false;
72
+ },
73
+
74
+ dispatchSortableEvent(name) {
75
+ _dispatchEvent({ sortable, name, originalEvent });
76
+ },
77
+
78
+ ...data
79
+ });
80
+ };
81
+
82
+ function _dispatchEvent(info) {
83
+ dispatchEvent({
84
+ putSortable,
85
+ cloneEl,
86
+ targetEl: dragEl,
87
+ rootEl,
88
+ oldIndex,
89
+ oldDraggableIndex,
90
+ newIndex,
91
+ newDraggableIndex,
92
+ ...info
93
+ });
94
+ }
95
+
96
+
97
+ let dragEl,
98
+ parentEl,
99
+ ghostEl,
100
+ rootEl,
101
+ nextEl,
102
+ lastDownEl,
103
+
104
+ cloneEl,
105
+ cloneHidden,
106
+
107
+ oldIndex,
108
+ newIndex,
109
+ oldDraggableIndex,
110
+ newDraggableIndex,
111
+
112
+ activeGroup,
113
+ putSortable,
114
+
115
+ awaitingDragStarted = false,
116
+ ignoreNextClick = false,
117
+ sortables = [],
118
+
119
+ tapEvt,
120
+ touchEvt,
121
+ lastDx,
122
+ lastDy,
123
+ tapDistanceLeft,
124
+ tapDistanceTop,
125
+
126
+ moved,
127
+
128
+ lastTarget,
129
+ lastDirection,
130
+ pastFirstInvertThresh = false,
131
+ isCircumstantialInvert = false,
132
+
133
+ targetMoveDistance,
134
+
135
+ // For positioning ghost absolutely
136
+ ghostRelativeParent,
137
+ ghostRelativeParentInitialScroll = [], // (left, top)
138
+
139
+ _silent = false,
140
+ savedInputChecked = [];
141
+
142
+ /** @const */
143
+ const documentExists = typeof document !== 'undefined',
144
+
145
+ PositionGhostAbsolutely = IOS,
146
+
147
+ CSSFloatProperty = Edge || IE11OrLess ? 'cssFloat' : 'float',
148
+
149
+ // This will not pass for IE9, because IE9 DnD only works on anchors
150
+ supportDraggable = documentExists && !ChromeForAndroid && !IOS && ('draggable' in document.createElement('div')),
151
+
152
+ supportCssPointerEvents = (function() {
153
+ if (!documentExists) return;
154
+ // false when <= IE11
155
+ if (IE11OrLess) {
156
+ return false;
157
+ }
158
+ let el = document.createElement('x');
159
+ el.style.cssText = 'pointer-events:auto';
160
+ return el.style.pointerEvents === 'auto';
161
+ })(),
162
+
163
+ _detectDirection = function(el, options) {
164
+ let elCSS = css(el),
165
+ elWidth = parseInt(elCSS.width)
166
+ - parseInt(elCSS.paddingLeft)
167
+ - parseInt(elCSS.paddingRight)
168
+ - parseInt(elCSS.borderLeftWidth)
169
+ - parseInt(elCSS.borderRightWidth),
170
+ child1 = getChild(el, 0, options),
171
+ child2 = getChild(el, 1, options),
172
+ firstChildCSS = child1 && css(child1),
173
+ secondChildCSS = child2 && css(child2),
174
+ firstChildWidth = firstChildCSS && parseInt(firstChildCSS.marginLeft) + parseInt(firstChildCSS.marginRight) + getRect(child1).width,
175
+ secondChildWidth = secondChildCSS && parseInt(secondChildCSS.marginLeft) + parseInt(secondChildCSS.marginRight) + getRect(child2).width;
176
+
177
+ if (elCSS.display === 'flex') {
178
+ return elCSS.flexDirection === 'column' || elCSS.flexDirection === 'column-reverse'
179
+ ? 'vertical' : 'horizontal';
180
+ }
181
+
182
+ if (elCSS.display === 'grid') {
183
+ return elCSS.gridTemplateColumns.split(' ').length <= 1 ? 'vertical' : 'horizontal';
184
+ }
185
+
186
+ if (child1 && firstChildCSS.float && firstChildCSS.float !== 'none') {
187
+ let touchingSideChild2 = firstChildCSS.float === 'left' ? 'left' : 'right';
188
+
189
+ return child2 && (secondChildCSS.clear === 'both' || secondChildCSS.clear === touchingSideChild2) ?
190
+ 'vertical' : 'horizontal';
191
+ }
192
+
193
+ return (child1 &&
194
+ (
195
+ firstChildCSS.display === 'block' ||
196
+ firstChildCSS.display === 'flex' ||
197
+ firstChildCSS.display === 'table' ||
198
+ firstChildCSS.display === 'grid' ||
199
+ firstChildWidth >= elWidth &&
200
+ elCSS[CSSFloatProperty] === 'none' ||
201
+ child2 &&
202
+ elCSS[CSSFloatProperty] === 'none' &&
203
+ firstChildWidth + secondChildWidth > elWidth
204
+ ) ?
205
+ 'vertical' : 'horizontal'
206
+ );
207
+ },
208
+
209
+ _dragElInRowColumn = function(dragRect, targetRect, vertical) {
210
+ let dragElS1Opp = vertical ? dragRect.left : dragRect.top,
211
+ dragElS2Opp = vertical ? dragRect.right : dragRect.bottom,
212
+ dragElOppLength = vertical ? dragRect.width : dragRect.height,
213
+ targetS1Opp = vertical ? targetRect.left : targetRect.top,
214
+ targetS2Opp = vertical ? targetRect.right : targetRect.bottom,
215
+ targetOppLength = vertical ? targetRect.width : targetRect.height;
216
+
217
+ return (
218
+ dragElS1Opp === targetS1Opp ||
219
+ dragElS2Opp === targetS2Opp ||
220
+ (dragElS1Opp + dragElOppLength / 2) === (targetS1Opp + targetOppLength / 2)
221
+ );
222
+ },
223
+
224
+ /**
225
+ * Detects first nearest empty sortable to X and Y position using emptyInsertThreshold.
226
+ * @param {Number} x X position
227
+ * @param {Number} y Y position
228
+ * @return {HTMLElement} Element of the first found nearest Sortable
229
+ */
230
+ _detectNearestEmptySortable = function(x, y) {
231
+ let ret;
232
+ sortables.some((sortable) => {
233
+ const threshold = sortable[expando].options.emptyInsertThreshold;
234
+ if (!threshold || lastChild(sortable)) return;
235
+
236
+ const rect = getRect(sortable),
237
+ insideHorizontally = x >= (rect.left - threshold) && x <= (rect.right + threshold),
238
+ insideVertically = y >= (rect.top - threshold) && y <= (rect.bottom + threshold);
239
+
240
+ if (insideHorizontally && insideVertically) {
241
+ return (ret = sortable);
242
+ }
243
+ });
244
+ return ret;
245
+ },
246
+
247
+ _prepareGroup = function (options) {
248
+ function toFn(value, pull) {
249
+ return function(to, from, dragEl, evt) {
250
+ let sameGroup = to.options.group.name &&
251
+ from.options.group.name &&
252
+ to.options.group.name === from.options.group.name;
253
+
254
+ if (value == null && (pull || sameGroup)) {
255
+ // Default pull value
256
+ // Default pull and put value if same group
257
+ return true;
258
+ } else if (value == null || value === false) {
259
+ return false;
260
+ } else if (pull && value === 'clone') {
261
+ return value;
262
+ } else if (typeof value === 'function') {
263
+ return toFn(value(to, from, dragEl, evt), pull)(to, from, dragEl, evt);
264
+ } else {
265
+ let otherGroup = (pull ? to : from).options.group.name;
266
+
267
+ return (value === true ||
268
+ (typeof value === 'string' && value === otherGroup) ||
269
+ (value.join && value.indexOf(otherGroup) > -1));
270
+ }
271
+ };
272
+ }
273
+
274
+ let group = {};
275
+ let originalGroup = options.group;
276
+
277
+ if (!originalGroup || typeof originalGroup != 'object') {
278
+ originalGroup = {name: originalGroup};
279
+ }
280
+
281
+ group.name = originalGroup.name;
282
+ group.checkPull = toFn(originalGroup.pull, true);
283
+ group.checkPut = toFn(originalGroup.put);
284
+ group.revertClone = originalGroup.revertClone;
285
+
286
+ options.group = group;
287
+ },
288
+
289
+ _hideGhostForTarget = function() {
290
+ if (!supportCssPointerEvents && ghostEl) {
291
+ css(ghostEl, 'display', 'none');
292
+ }
293
+ },
294
+
295
+ _unhideGhostForTarget = function() {
296
+ if (!supportCssPointerEvents && ghostEl) {
297
+ css(ghostEl, 'display', '');
298
+ }
299
+ };
300
+
301
+
302
+ // #1184 fix - Prevent click event on fallback if dragged but item not changed position
303
+ if (documentExists && !ChromeForAndroid) {
304
+ document.addEventListener('click', function(evt) {
305
+ if (ignoreNextClick) {
306
+ evt.preventDefault();
307
+ evt.stopPropagation && evt.stopPropagation();
308
+ evt.stopImmediatePropagation && evt.stopImmediatePropagation();
309
+ ignoreNextClick = false;
310
+ return false;
311
+ }
312
+ }, true);
313
+ }
314
+
315
+ let nearestEmptyInsertDetectEvent = function(evt) {
316
+ if (dragEl) {
317
+ evt = evt.touches ? evt.touches[0] : evt;
318
+ let nearest = _detectNearestEmptySortable(evt.clientX, evt.clientY);
319
+
320
+ if (nearest) {
321
+ // Create imitation event
322
+ let event = {};
323
+ for (let i in evt) {
324
+ if (evt.hasOwnProperty(i)) {
325
+ event[i] = evt[i];
326
+ }
327
+ }
328
+ event.target = event.rootEl = nearest;
329
+ event.preventDefault = void 0;
330
+ event.stopPropagation = void 0;
331
+ nearest[expando]._onDragOver(event);
332
+ }
333
+ }
334
+ };
335
+
336
+
337
+ let _checkOutsideTargetEl = function(evt) {
338
+ if (dragEl) {
339
+ dragEl.parentNode[expando]._isOutsideThisEl(evt.target);
340
+ }
341
+ };
342
+
343
+
344
+ /**
345
+ * @class Sortable
346
+ * @param {HTMLElement} el
347
+ * @param {Object} [options]
348
+ */
349
+ function Sortable(el, options) {
350
+ if (!(el && el.nodeType && el.nodeType === 1)) {
351
+ throw `Sortable: \`el\` must be an HTMLElement, not ${ {}.toString.call(el) }`;
352
+ }
353
+
354
+ this.el = el; // root element
355
+ this.options = options = Object.assign({}, options);
356
+
357
+
358
+ // Export instance
359
+ el[expando] = this;
360
+
361
+ let defaults = {
362
+ group: null,
363
+ sort: true,
364
+ disabled: false,
365
+ store: null,
366
+ handle: null,
367
+ draggable: /^[uo]l$/i.test(el.nodeName) ? '>li' : '>*',
368
+ swapThreshold: 1, // percentage; 0 <= x <= 1
369
+ invertSwap: false, // invert always
370
+ invertedSwapThreshold: null, // will be set to same as swapThreshold if default
371
+ removeCloneOnHide: true,
372
+ direction: function() {
373
+ return _detectDirection(el, this.options);
374
+ },
375
+ ghostClass: 'sortable-ghost',
376
+ chosenClass: 'sortable-chosen',
377
+ dragClass: 'sortable-drag',
378
+ ignore: 'a, img',
379
+ filter: null,
380
+ preventOnFilter: true,
381
+ animation: 0,
382
+ easing: null,
383
+ setData: function (dataTransfer, dragEl) {
384
+ dataTransfer.setData('Text', dragEl.textContent);
385
+ },
386
+ dropBubble: false,
387
+ dragoverBubble: false,
388
+ dataIdAttr: 'data-id',
389
+ delay: 0,
390
+ delayOnTouchOnly: false,
391
+ touchStartThreshold: (Number.parseInt ? Number : window).parseInt(window.devicePixelRatio, 10) || 1,
392
+ forceFallback: false,
393
+ fallbackClass: 'sortable-fallback',
394
+ fallbackOnBody: false,
395
+ fallbackTolerance: 0,
396
+ fallbackOffset: {x: 0, y: 0},
397
+ supportPointer: Sortable.supportPointer !== false && ('PointerEvent' in window) && !Safari,
398
+ emptyInsertThreshold: 5
399
+ };
400
+
401
+ PluginManager.initializePlugins(this, el, defaults);
402
+
403
+ // Set default options
404
+ for (let name in defaults) {
405
+ !(name in options) && (options[name] = defaults[name]);
406
+ }
407
+
408
+ _prepareGroup(options);
409
+
410
+ // Bind all private methods
411
+ for (let fn in this) {
412
+ if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {
413
+ this[fn] = this[fn].bind(this);
414
+ }
415
+ }
416
+
417
+ // Setup drag mode
418
+ this.nativeDraggable = options.forceFallback ? false : supportDraggable;
419
+
420
+ if (this.nativeDraggable) {
421
+ // Touch start threshold cannot be greater than the native dragstart threshold
422
+ this.options.touchStartThreshold = 1;
423
+ }
424
+
425
+ // Bind events
426
+ if (options.supportPointer) {
427
+ on(el, 'pointerdown', this._onTapStart);
428
+ } else {
429
+ on(el, 'mousedown', this._onTapStart);
430
+ on(el, 'touchstart', this._onTapStart);
431
+ }
432
+
433
+ if (this.nativeDraggable) {
434
+ on(el, 'dragover', this);
435
+ on(el, 'dragenter', this);
436
+ }
437
+
438
+ sortables.push(this.el);
439
+
440
+ // Restore sorting
441
+ options.store && options.store.get && this.sort(options.store.get(this) || []);
442
+
443
+ // Add animation state manager
444
+ Object.assign(this, AnimationStateManager());
445
+ }
446
+
447
+ Sortable.prototype = /** @lends Sortable.prototype */ {
448
+ constructor: Sortable,
449
+
450
+ _isOutsideThisEl: function(target) {
451
+ if (!this.el.contains(target) && target !== this.el) {
452
+ lastTarget = null;
453
+ }
454
+ },
455
+
456
+ _getDirection: function(evt, target) {
457
+ return (typeof this.options.direction === 'function') ? this.options.direction.call(this, evt, target, dragEl) : this.options.direction;
458
+ },
459
+
460
+ _onTapStart: function (/** Event|TouchEvent */evt) {
461
+ if (!evt.cancelable) return;
462
+ let _this = this,
463
+ el = this.el,
464
+ options = this.options,
465
+ preventOnFilter = options.preventOnFilter,
466
+ type = evt.type,
467
+ touch = (evt.touches && evt.touches[0]) || (evt.pointerType && evt.pointerType === 'touch' && evt),
468
+ target = (touch || evt).target,
469
+ originalTarget = evt.target.shadowRoot && ((evt.path && evt.path[0]) || (evt.composedPath && evt.composedPath()[0])) || target,
470
+ filter = options.filter;
471
+
472
+ _saveInputCheckedState(el);
473
+
474
+
475
+ // Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group.
476
+ if (dragEl) {
477
+ return;
478
+ }
479
+
480
+ if (/mousedown|pointerdown/.test(type) && evt.button !== 0 || options.disabled) {
481
+ return; // only left button and enabled
482
+ }
483
+
484
+ // cancel dnd if original target is content editable
485
+ if (originalTarget.isContentEditable) {
486
+ return;
487
+ }
488
+
489
+ // Safari ignores further event handling after mousedown
490
+ if (!this.nativeDraggable && Safari && target && target.tagName.toUpperCase() === 'SELECT') {
491
+ return;
492
+ }
493
+
494
+ target = closest(target, options.draggable, el, false);
495
+
496
+
497
+ if (target && target.animated) {
498
+ return;
499
+ }
500
+
501
+ if (lastDownEl === target) {
502
+ // Ignoring duplicate `down`
503
+ return;
504
+ }
505
+
506
+ // Get the index of the dragged element within its parent
507
+ oldIndex = index(target);
508
+ oldDraggableIndex = index(target, options.draggable);
509
+
510
+ // Check filter
511
+ if (typeof filter === 'function') {
512
+ if (filter.call(this, evt, target, this)) {
513
+ _dispatchEvent({
514
+ sortable: _this,
515
+ rootEl: originalTarget,
516
+ name: 'filter',
517
+ targetEl: target,
518
+ toEl: el,
519
+ fromEl: el
520
+ });
521
+ pluginEvent('filter', _this, { evt });
522
+ preventOnFilter && evt.cancelable && evt.preventDefault();
523
+ return; // cancel dnd
524
+ }
525
+ }
526
+ else if (filter) {
527
+ filter = filter.split(',').some(function (criteria) {
528
+ criteria = closest(originalTarget, criteria.trim(), el, false);
529
+
530
+ if (criteria) {
531
+ _dispatchEvent({
532
+ sortable: _this,
533
+ rootEl: criteria,
534
+ name: 'filter',
535
+ targetEl: target,
536
+ fromEl: el,
537
+ toEl: el
538
+ });
539
+ pluginEvent('filter', _this, { evt });
540
+ return true;
541
+ }
542
+ });
543
+
544
+ if (filter) {
545
+ preventOnFilter && evt.cancelable && evt.preventDefault();
546
+ return; // cancel dnd
547
+ }
548
+ }
549
+
550
+ if (options.handle && !closest(originalTarget, options.handle, el, false)) {
551
+ return;
552
+ }
553
+
554
+ // Prepare `dragstart`
555
+ this._prepareDragStart(evt, touch, target);
556
+ },
557
+
558
+ _prepareDragStart: function (/** Event */evt, /** Touch */touch, /** HTMLElement */target) {
559
+ let _this = this,
560
+ el = _this.el,
561
+ options = _this.options,
562
+ ownerDocument = el.ownerDocument,
563
+ dragStartFn;
564
+
565
+ if (target && !dragEl && (target.parentNode === el)) {
566
+ let dragRect = getRect(target);
567
+ rootEl = el;
568
+ dragEl = target;
569
+ parentEl = dragEl.parentNode;
570
+ nextEl = dragEl.nextSibling;
571
+ lastDownEl = target;
572
+ activeGroup = options.group;
573
+
574
+ Sortable.dragged = dragEl;
575
+
576
+ tapEvt = {
577
+ target: dragEl,
578
+ clientX: (touch || evt).clientX,
579
+ clientY: (touch || evt).clientY
580
+ };
581
+
582
+ tapDistanceLeft = tapEvt.clientX - dragRect.left;
583
+ tapDistanceTop = tapEvt.clientY - dragRect.top;
584
+
585
+ this._lastX = (touch || evt).clientX;
586
+ this._lastY = (touch || evt).clientY;
587
+
588
+ dragEl.style['will-change'] = 'all';
589
+
590
+ dragStartFn = function () {
591
+ pluginEvent('delayEnded', _this, { evt });
592
+ if (Sortable.eventCanceled) {
593
+ _this._onDrop();
594
+ return;
595
+ }
596
+ // Delayed drag has been triggered
597
+ // we can re-enable the events: touchmove/mousemove
598
+ _this._disableDelayedDragEvents();
599
+
600
+ if (!FireFox && _this.nativeDraggable) {
601
+ dragEl.draggable = true;
602
+ }
603
+
604
+ // Bind the events: dragstart/dragend
605
+ _this._triggerDragStart(evt, touch);
606
+
607
+ // Drag start event
608
+ _dispatchEvent({
609
+ sortable: _this,
610
+ name: 'choose',
611
+ originalEvent: evt
612
+ });
613
+
614
+ // Chosen item
615
+ toggleClass(dragEl, options.chosenClass, true);
616
+ };
617
+
618
+ // Disable "draggable"
619
+ options.ignore.split(',').forEach(function (criteria) {
620
+ find(dragEl, criteria.trim(), _disableDraggable);
621
+ });
622
+
623
+ on(ownerDocument, 'dragover', nearestEmptyInsertDetectEvent);
624
+ on(ownerDocument, 'mousemove', nearestEmptyInsertDetectEvent);
625
+ on(ownerDocument, 'touchmove', nearestEmptyInsertDetectEvent);
626
+
627
+ on(ownerDocument, 'mouseup', _this._onDrop);
628
+ on(ownerDocument, 'touchend', _this._onDrop);
629
+ on(ownerDocument, 'touchcancel', _this._onDrop);
630
+
631
+ // Make dragEl draggable (must be before delay for FireFox)
632
+ if (FireFox && this.nativeDraggable) {
633
+ this.options.touchStartThreshold = 4;
634
+ dragEl.draggable = true;
635
+ }
636
+
637
+ pluginEvent('delayStart', this, { evt });
638
+
639
+ // Delay is impossible for native DnD in Edge or IE
640
+ if (options.delay && (!options.delayOnTouchOnly || touch) && (!this.nativeDraggable || !(Edge || IE11OrLess))) {
641
+ if (Sortable.eventCanceled) {
642
+ this._onDrop();
643
+ return;
644
+ }
645
+ // If the user moves the pointer or let go the click or touch
646
+ // before the delay has been reached:
647
+ // disable the delayed drag
648
+ on(ownerDocument, 'mouseup', _this._disableDelayedDrag);
649
+ on(ownerDocument, 'touchend', _this._disableDelayedDrag);
650
+ on(ownerDocument, 'touchcancel', _this._disableDelayedDrag);
651
+ on(ownerDocument, 'mousemove', _this._delayedDragTouchMoveHandler);
652
+ on(ownerDocument, 'touchmove', _this._delayedDragTouchMoveHandler);
653
+ options.supportPointer && on(ownerDocument, 'pointermove', _this._delayedDragTouchMoveHandler);
654
+
655
+ _this._dragStartTimer = setTimeout(dragStartFn, options.delay);
656
+ } else {
657
+ dragStartFn();
658
+ }
659
+ }
660
+ },
661
+
662
+ _delayedDragTouchMoveHandler: function (/** TouchEvent|PointerEvent **/e) {
663
+ let touch = e.touches ? e.touches[0] : e;
664
+ if (Math.max(Math.abs(touch.clientX - this._lastX), Math.abs(touch.clientY - this._lastY))
665
+ >= Math.floor(this.options.touchStartThreshold / (this.nativeDraggable && window.devicePixelRatio || 1))
666
+ ) {
667
+ this._disableDelayedDrag();
668
+ }
669
+ },
670
+
671
+ _disableDelayedDrag: function () {
672
+ dragEl && _disableDraggable(dragEl);
673
+ clearTimeout(this._dragStartTimer);
674
+
675
+ this._disableDelayedDragEvents();
676
+ },
677
+
678
+ _disableDelayedDragEvents: function () {
679
+ let ownerDocument = this.el.ownerDocument;
680
+ off(ownerDocument, 'mouseup', this._disableDelayedDrag);
681
+ off(ownerDocument, 'touchend', this._disableDelayedDrag);
682
+ off(ownerDocument, 'touchcancel', this._disableDelayedDrag);
683
+ off(ownerDocument, 'mousemove', this._delayedDragTouchMoveHandler);
684
+ off(ownerDocument, 'touchmove', this._delayedDragTouchMoveHandler);
685
+ off(ownerDocument, 'pointermove', this._delayedDragTouchMoveHandler);
686
+ },
687
+
688
+ _triggerDragStart: function (/** Event */evt, /** Touch */touch) {
689
+ touch = touch || (evt.pointerType == 'touch' && evt);
690
+
691
+ if (!this.nativeDraggable || touch) {
692
+ if (this.options.supportPointer) {
693
+ on(document, 'pointermove', this._onTouchMove);
694
+ } else if (touch) {
695
+ on(document, 'touchmove', this._onTouchMove);
696
+ } else {
697
+ on(document, 'mousemove', this._onTouchMove);
698
+ }
699
+ } else {
700
+ on(dragEl, 'dragend', this);
701
+ on(rootEl, 'dragstart', this._onDragStart);
702
+ }
703
+
704
+ try {
705
+ if (document.selection) {
706
+ // Timeout neccessary for IE9
707
+ _nextTick(function () {
708
+ document.selection.empty();
709
+ });
710
+ } else {
711
+ window.getSelection().removeAllRanges();
712
+ }
713
+ } catch (err) {
714
+ }
715
+ },
716
+
717
+ _dragStarted: function (fallback, evt) {
718
+ let _this = this;
719
+ awaitingDragStarted = false;
720
+ if (rootEl && dragEl) {
721
+ pluginEvent('dragStarted', this, { evt });
722
+
723
+ if (this.nativeDraggable) {
724
+ on(document, 'dragover', _checkOutsideTargetEl);
725
+ }
726
+ let options = this.options;
727
+
728
+ // Apply effect
729
+ !fallback && toggleClass(dragEl, options.dragClass, false);
730
+ toggleClass(dragEl, options.ghostClass, true);
731
+
732
+ Sortable.active = this;
733
+
734
+ fallback && this._appendGhost();
735
+
736
+ // Drag start event
737
+ _dispatchEvent({
738
+ sortable: this,
739
+ name: 'start',
740
+ originalEvent: evt
741
+ });
742
+ } else {
743
+ this._nulling();
744
+ }
745
+ },
746
+
747
+ _emulateDragOver: function () {
748
+ if (touchEvt) {
749
+ this._lastX = touchEvt.clientX;
750
+ this._lastY = touchEvt.clientY;
751
+
752
+ _hideGhostForTarget();
753
+
754
+ let target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY);
755
+ let parent = target;
756
+
757
+ while (target && target.shadowRoot) {
758
+ target = target.shadowRoot.elementFromPoint(touchEvt.clientX, touchEvt.clientY);
759
+ if (target === parent) break;
760
+ parent = target;
761
+ }
762
+
763
+ dragEl.parentNode[expando]._isOutsideThisEl(target);
764
+
765
+ if (parent) {
766
+ do {
767
+ if (parent[expando]) {
768
+ let inserted;
769
+
770
+ inserted = parent[expando]._onDragOver({
771
+ clientX: touchEvt.clientX,
772
+ clientY: touchEvt.clientY,
773
+ target: target,
774
+ rootEl: parent
775
+ });
776
+
777
+ if (inserted && !this.options.dragoverBubble) {
778
+ break;
779
+ }
780
+ }
781
+
782
+ target = parent; // store last element
783
+ }
784
+ /* jshint boss:true */
785
+ while (parent = getParentOrHost(parent));
786
+ }
787
+
788
+ _unhideGhostForTarget();
789
+ }
790
+ },
791
+
792
+
793
+ _onTouchMove: function (/**TouchEvent*/evt) {
794
+ if (tapEvt) {
795
+ let options = this.options,
796
+ fallbackTolerance = options.fallbackTolerance,
797
+ fallbackOffset = options.fallbackOffset,
798
+ touch = evt.touches ? evt.touches[0] : evt,
799
+ ghostMatrix = ghostEl && matrix(ghostEl, true),
800
+ scaleX = ghostEl && ghostMatrix && ghostMatrix.a,
801
+ scaleY = ghostEl && ghostMatrix && ghostMatrix.d,
802
+ relativeScrollOffset = PositionGhostAbsolutely && ghostRelativeParent && getRelativeScrollOffset(ghostRelativeParent),
803
+ dx = ((touch.clientX - tapEvt.clientX)
804
+ + fallbackOffset.x) / (scaleX || 1)
805
+ + (relativeScrollOffset ? (relativeScrollOffset[0] - ghostRelativeParentInitialScroll[0]) : 0) / (scaleX || 1),
806
+ dy = ((touch.clientY - tapEvt.clientY)
807
+ + fallbackOffset.y) / (scaleY || 1)
808
+ + (relativeScrollOffset ? (relativeScrollOffset[1] - ghostRelativeParentInitialScroll[1]) : 0) / (scaleY || 1);
809
+
810
+ // only set the status to dragging, when we are actually dragging
811
+ if (!Sortable.active && !awaitingDragStarted) {
812
+ if (fallbackTolerance &&
813
+ Math.max(Math.abs(touch.clientX - this._lastX), Math.abs(touch.clientY - this._lastY)) < fallbackTolerance
814
+ ) {
815
+ return;
816
+ }
817
+ this._onDragStart(evt, true);
818
+ }
819
+
820
+ if (ghostEl) {
821
+ if (ghostMatrix) {
822
+ ghostMatrix.e += dx - (lastDx || 0);
823
+ ghostMatrix.f += dy - (lastDy || 0);
824
+ } else {
825
+ ghostMatrix = {
826
+ a: 1,
827
+ b: 0,
828
+ c: 0,
829
+ d: 1,
830
+ e: dx,
831
+ f: dy
832
+ };
833
+ }
834
+
835
+ let cssMatrix = `matrix(${ghostMatrix.a},${ghostMatrix.b},${ghostMatrix.c},${ghostMatrix.d},${ghostMatrix.e},${ghostMatrix.f})`;
836
+
837
+ css(ghostEl, 'webkitTransform', cssMatrix);
838
+ css(ghostEl, 'mozTransform', cssMatrix);
839
+ css(ghostEl, 'msTransform', cssMatrix);
840
+ css(ghostEl, 'transform', cssMatrix);
841
+
842
+ lastDx = dx;
843
+ lastDy = dy;
844
+
845
+ touchEvt = touch;
846
+ }
847
+
848
+ evt.cancelable && evt.preventDefault();
849
+ }
850
+ },
851
+
852
+ _appendGhost: function () {
853
+ // Bug if using scale(): https://stackoverflow.com/questions/2637058
854
+ // Not being adjusted for
855
+ if (!ghostEl) {
856
+ let container = this.options.fallbackOnBody ? document.body : rootEl,
857
+ rect = getRect(dragEl, true, PositionGhostAbsolutely, true, container),
858
+ options = this.options;
859
+
860
+ // Position absolutely
861
+ if (PositionGhostAbsolutely) {
862
+ // Get relatively positioned parent
863
+ ghostRelativeParent = container;
864
+
865
+ while (
866
+ css(ghostRelativeParent, 'position') === 'static' &&
867
+ css(ghostRelativeParent, 'transform') === 'none' &&
868
+ ghostRelativeParent !== document
869
+ ) {
870
+ ghostRelativeParent = ghostRelativeParent.parentNode;
871
+ }
872
+
873
+ if (ghostRelativeParent !== document.body && ghostRelativeParent !== document.documentElement) {
874
+ if (ghostRelativeParent === document) ghostRelativeParent = getWindowScrollingElement();
875
+
876
+ rect.top += ghostRelativeParent.scrollTop;
877
+ rect.left += ghostRelativeParent.scrollLeft;
878
+ } else {
879
+ ghostRelativeParent = getWindowScrollingElement();
880
+ }
881
+ ghostRelativeParentInitialScroll = getRelativeScrollOffset(ghostRelativeParent);
882
+ }
883
+
884
+
885
+ ghostEl = dragEl.cloneNode(true);
886
+
887
+ toggleClass(ghostEl, options.ghostClass, false);
888
+ toggleClass(ghostEl, options.fallbackClass, true);
889
+ toggleClass(ghostEl, options.dragClass, true);
890
+
891
+ css(ghostEl, 'transition', '');
892
+ css(ghostEl, 'transform', '');
893
+
894
+ css(ghostEl, 'box-sizing', 'border-box');
895
+ css(ghostEl, 'margin', 0);
896
+ css(ghostEl, 'top', rect.top);
897
+ css(ghostEl, 'left', rect.left);
898
+ css(ghostEl, 'width', rect.width);
899
+ css(ghostEl, 'height', rect.height);
900
+ css(ghostEl, 'opacity', '0.8');
901
+ css(ghostEl, 'position', (PositionGhostAbsolutely ? 'absolute' : 'fixed'));
902
+ css(ghostEl, 'zIndex', '100000');
903
+ css(ghostEl, 'pointerEvents', 'none');
904
+
905
+
906
+ Sortable.ghost = ghostEl;
907
+
908
+ container.appendChild(ghostEl);
909
+
910
+ // Set transform-origin
911
+ css(ghostEl, 'transform-origin', (tapDistanceLeft / parseInt(ghostEl.style.width) * 100) + '% ' + (tapDistanceTop / parseInt(ghostEl.style.height) * 100) + '%');
912
+ }
913
+ },
914
+
915
+ _onDragStart: function (/**Event*/evt, /**boolean*/fallback) {
916
+ let _this = this;
917
+ let dataTransfer = evt.dataTransfer;
918
+ let options = _this.options;
919
+
920
+ pluginEvent('dragStart', this, { evt });
921
+ if (Sortable.eventCanceled) {
922
+ this._onDrop();
923
+ return;
924
+ }
925
+
926
+ pluginEvent('setupClone', this);
927
+ if (!Sortable.eventCanceled) {
928
+ cloneEl = clone(dragEl);
929
+ cloneEl.removeAttribute("id");
930
+ cloneEl.draggable = false;
931
+ cloneEl.style['will-change'] = '';
932
+
933
+ this._hideClone();
934
+
935
+ toggleClass(cloneEl, this.options.chosenClass, false);
936
+ Sortable.clone = cloneEl;
937
+ }
938
+
939
+
940
+ // #1143: IFrame support workaround
941
+ _this.cloneId = _nextTick(function() {
942
+ pluginEvent('clone', _this);
943
+ if (Sortable.eventCanceled) return;
944
+
945
+ if (!_this.options.removeCloneOnHide) {
946
+ rootEl.insertBefore(cloneEl, dragEl);
947
+ }
948
+ _this._hideClone();
949
+
950
+ _dispatchEvent({
951
+ sortable: _this,
952
+ name: 'clone'
953
+ });
954
+ });
955
+
956
+
957
+ !fallback && toggleClass(dragEl, options.dragClass, true);
958
+
959
+ // Set proper drop events
960
+ if (fallback) {
961
+ ignoreNextClick = true;
962
+ _this._loopId = setInterval(_this._emulateDragOver, 50);
963
+ } else {
964
+ // Undo what was set in _prepareDragStart before drag started
965
+ off(document, 'mouseup', _this._onDrop);
966
+ off(document, 'touchend', _this._onDrop);
967
+ off(document, 'touchcancel', _this._onDrop);
968
+
969
+ if (dataTransfer) {
970
+ dataTransfer.effectAllowed = 'move';
971
+ options.setData && options.setData.call(_this, dataTransfer, dragEl);
972
+ }
973
+
974
+ on(document, 'drop', _this);
975
+
976
+ // #1276 fix:
977
+ css(dragEl, 'transform', 'translateZ(0)');
978
+ }
979
+
980
+ awaitingDragStarted = true;
981
+
982
+ _this._dragStartId = _nextTick(_this._dragStarted.bind(_this, fallback, evt));
983
+ on(document, 'selectstart', _this);
984
+
985
+ moved = true;
986
+
987
+ if (Safari) {
988
+ css(document.body, 'user-select', 'none');
989
+ }
990
+ },
991
+
992
+
993
+ // Returns true - if no further action is needed (either inserted or another condition)
994
+ _onDragOver: function (/**Event*/evt) {
995
+ let el = this.el,
996
+ target = evt.target,
997
+ dragRect,
998
+ targetRect,
999
+ revert,
1000
+ options = this.options,
1001
+ group = options.group,
1002
+ activeSortable = Sortable.active,
1003
+ isOwner = (activeGroup === group),
1004
+ canSort = options.sort,
1005
+ fromSortable = (putSortable || activeSortable),
1006
+ vertical,
1007
+ _this = this,
1008
+ completedFired = false;
1009
+
1010
+ if (_silent) return;
1011
+
1012
+ function dragOverEvent(name, extra) {
1013
+ pluginEvent(name, _this, {
1014
+ evt,
1015
+ isOwner,
1016
+ axis: vertical ? 'vertical' : 'horizontal',
1017
+ revert,
1018
+ dragRect,
1019
+ targetRect,
1020
+ canSort,
1021
+ fromSortable,
1022
+ target,
1023
+ completed,
1024
+ onMove(target, after) {
1025
+ return onMove(rootEl, el, dragEl, dragRect, target, getRect(target), evt, after);
1026
+ },
1027
+ changed,
1028
+ ...extra
1029
+ });
1030
+ }
1031
+
1032
+ // Capture animation state
1033
+ function capture() {
1034
+ dragOverEvent('dragOverAnimationCapture');
1035
+
1036
+ _this.captureAnimationState();
1037
+ if (_this !== fromSortable) {
1038
+ fromSortable.captureAnimationState();
1039
+ }
1040
+ }
1041
+
1042
+ // Return invocation when dragEl is inserted (or completed)
1043
+ function completed(insertion) {
1044
+ dragOverEvent('dragOverCompleted', { insertion });
1045
+
1046
+ if (insertion) {
1047
+ // Clones must be hidden before folding animation to capture dragRectAbsolute properly
1048
+ if (isOwner) {
1049
+ activeSortable._hideClone();
1050
+ } else {
1051
+ activeSortable._showClone(_this);
1052
+ }
1053
+
1054
+ if (_this !== fromSortable) {
1055
+ // Set ghost class to new sortable's ghost class
1056
+ toggleClass(dragEl, putSortable ? putSortable.options.ghostClass : activeSortable.options.ghostClass, false);
1057
+ toggleClass(dragEl, options.ghostClass, true);
1058
+ }
1059
+
1060
+ if (putSortable !== _this && _this !== Sortable.active) {
1061
+ putSortable = _this;
1062
+ } else if (_this === Sortable.active && putSortable) {
1063
+ putSortable = null;
1064
+ }
1065
+
1066
+ // Animation
1067
+ if (fromSortable === _this) {
1068
+ _this._ignoreWhileAnimating = target;
1069
+ }
1070
+ _this.animateAll(function() {
1071
+ dragOverEvent('dragOverAnimationComplete');
1072
+ _this._ignoreWhileAnimating = null;
1073
+ });
1074
+ if (_this !== fromSortable) {
1075
+ fromSortable.animateAll();
1076
+ fromSortable._ignoreWhileAnimating = null;
1077
+ }
1078
+ }
1079
+
1080
+
1081
+ // Null lastTarget if it is not inside a previously swapped element
1082
+ if ((target === dragEl && !dragEl.animated) || (target === el && !target.animated)) {
1083
+ lastTarget = null;
1084
+ }
1085
+
1086
+ // no bubbling and not fallback
1087
+ if (!options.dragoverBubble && !evt.rootEl && target !== document) {
1088
+ dragEl.parentNode[expando]._isOutsideThisEl(evt.target);
1089
+
1090
+ // Do not detect for empty insert if already inserted
1091
+ !insertion && nearestEmptyInsertDetectEvent(evt);
1092
+ }
1093
+
1094
+ !options.dragoverBubble && evt.stopPropagation && evt.stopPropagation();
1095
+
1096
+ return (completedFired = true);
1097
+ }
1098
+
1099
+ // Call when dragEl has been inserted
1100
+ function changed() {
1101
+ newIndex = index(dragEl);
1102
+ newDraggableIndex = index(dragEl, options.draggable);
1103
+ _dispatchEvent({
1104
+ sortable: _this,
1105
+ name: 'change',
1106
+ toEl: el,
1107
+ newIndex,
1108
+ newDraggableIndex,
1109
+ originalEvent: evt
1110
+ });
1111
+ }
1112
+
1113
+
1114
+ if (evt.preventDefault !== void 0) {
1115
+ evt.cancelable && evt.preventDefault();
1116
+ }
1117
+
1118
+
1119
+ target = closest(target, options.draggable, el, true);
1120
+
1121
+ dragOverEvent('dragOver');
1122
+ if (Sortable.eventCanceled) return completedFired;
1123
+
1124
+ if (
1125
+ dragEl.contains(evt.target) ||
1126
+ target.animated && target.animatingX && target.animatingY ||
1127
+ _this._ignoreWhileAnimating === target
1128
+ ) {
1129
+ return completed(false);
1130
+ }
1131
+
1132
+ ignoreNextClick = false;
1133
+
1134
+ if (activeSortable && !options.disabled &&
1135
+ (isOwner
1136
+ ? canSort || (revert = parentEl !== rootEl) // Reverting item into the original list
1137
+ : (
1138
+ putSortable === this ||
1139
+ (
1140
+ (this.lastPutMode = activeGroup.checkPull(this, activeSortable, dragEl, evt)) &&
1141
+ group.checkPut(this, activeSortable, dragEl, evt)
1142
+ )
1143
+ )
1144
+ )
1145
+ ) {
1146
+ vertical = this._getDirection(evt, target) === 'vertical';
1147
+
1148
+ dragRect = getRect(dragEl);
1149
+
1150
+ dragOverEvent('dragOverValid');
1151
+ if (Sortable.eventCanceled) return completedFired;
1152
+
1153
+ if (revert) {
1154
+ parentEl = rootEl; // actualization
1155
+ capture();
1156
+
1157
+ this._hideClone();
1158
+
1159
+ dragOverEvent('revert');
1160
+
1161
+ if (!Sortable.eventCanceled) {
1162
+ if (nextEl) {
1163
+ rootEl.insertBefore(dragEl, nextEl);
1164
+ } else {
1165
+ rootEl.appendChild(dragEl);
1166
+ }
1167
+ }
1168
+
1169
+ return completed(true);
1170
+ }
1171
+
1172
+ let elLastChild = lastChild(el, options.draggable);
1173
+
1174
+ if (!elLastChild || _ghostIsLast(evt, vertical, this) && !elLastChild.animated) {
1175
+ // Insert to end of list
1176
+
1177
+ // If already at end of list: Do not insert
1178
+ if (elLastChild === dragEl) {
1179
+ return completed(false);
1180
+ }
1181
+
1182
+ // if there is a last element, it is the target
1183
+ if (elLastChild && el === evt.target) {
1184
+ target = elLastChild;
1185
+ }
1186
+
1187
+ if (target) {
1188
+ targetRect = getRect(target);
1189
+ }
1190
+
1191
+ if (onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, !!target) !== false) {
1192
+ capture();
1193
+ if (elLastChild && elLastChild.nextSibling) { // the last draggable element is not the last node
1194
+ el.insertBefore(dragEl, elLastChild.nextSibling);
1195
+ }
1196
+ else {
1197
+ el.appendChild(dragEl);
1198
+ }
1199
+ parentEl = el; // actualization
1200
+
1201
+ changed();
1202
+ return completed(true);
1203
+ }
1204
+ }
1205
+ else if (elLastChild && _ghostIsFirst(evt, vertical, this)) {
1206
+ // Insert to start of list
1207
+ let firstChild = getChild(el, 0, options, true);
1208
+ if (firstChild === dragEl) {
1209
+ return completed(false);
1210
+ }
1211
+ target = firstChild;
1212
+ targetRect = getRect(target);
1213
+
1214
+ if (onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, false) !== false) {
1215
+ capture();
1216
+ el.insertBefore(dragEl, firstChild);
1217
+ parentEl = el; // actualization
1218
+
1219
+ changed();
1220
+ return completed(true);
1221
+ }
1222
+ }
1223
+ else if (target.parentNode === el) {
1224
+ targetRect = getRect(target);
1225
+ let direction = 0,
1226
+ targetBeforeFirstSwap,
1227
+ differentLevel = dragEl.parentNode !== el,
1228
+ differentRowCol = !_dragElInRowColumn(dragEl.animated && dragEl.toRect || dragRect, target.animated && target.toRect || targetRect, vertical),
1229
+ side1 = vertical ? 'top' : 'left',
1230
+ scrolledPastTop = isScrolledPast(target, 'top', 'top') || isScrolledPast(dragEl, 'top', 'top'),
1231
+ scrollBefore = scrolledPastTop ? scrolledPastTop.scrollTop : void 0;
1232
+
1233
+
1234
+ if (lastTarget !== target) {
1235
+ targetBeforeFirstSwap = targetRect[side1];
1236
+ pastFirstInvertThresh = false;
1237
+ isCircumstantialInvert = (!differentRowCol && options.invertSwap) || differentLevel;
1238
+ }
1239
+
1240
+ direction = _getSwapDirection(
1241
+ evt, target, targetRect, vertical,
1242
+ differentRowCol ? 1 : options.swapThreshold,
1243
+ options.invertedSwapThreshold == null ? options.swapThreshold : options.invertedSwapThreshold,
1244
+ isCircumstantialInvert,
1245
+ lastTarget === target
1246
+ );
1247
+
1248
+ let sibling;
1249
+
1250
+ if (direction !== 0) {
1251
+ // Check if target is beside dragEl in respective direction (ignoring hidden elements)
1252
+ let dragIndex = index(dragEl);
1253
+
1254
+ do {
1255
+ dragIndex -= direction;
1256
+ sibling = parentEl.children[dragIndex];
1257
+ } while (sibling && (css(sibling, 'display') === 'none' || sibling === ghostEl));
1258
+ }
1259
+ // If dragEl is already beside target: Do not insert
1260
+ if (
1261
+ direction === 0 ||
1262
+ sibling === target
1263
+ ) {
1264
+ return completed(false);
1265
+ }
1266
+
1267
+ lastTarget = target;
1268
+
1269
+ lastDirection = direction;
1270
+
1271
+ let nextSibling = target.nextElementSibling,
1272
+ after = false;
1273
+
1274
+ after = direction === 1;
1275
+
1276
+ let moveVector = onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, after);
1277
+
1278
+ if (moveVector !== false) {
1279
+ if (moveVector === 1 || moveVector === -1) {
1280
+ after = (moveVector === 1);
1281
+ }
1282
+
1283
+ _silent = true;
1284
+ setTimeout(_unsilent, 30);
1285
+
1286
+ capture();
1287
+
1288
+ if (after && !nextSibling) {
1289
+ el.appendChild(dragEl);
1290
+ } else {
1291
+ target.parentNode.insertBefore(dragEl, after ? nextSibling : target);
1292
+ }
1293
+
1294
+ // Undo chrome's scroll adjustment (has no effect on other browsers)
1295
+ if (scrolledPastTop) {
1296
+ scrollBy(scrolledPastTop, 0, scrollBefore - scrolledPastTop.scrollTop);
1297
+ }
1298
+
1299
+ parentEl = dragEl.parentNode; // actualization
1300
+
1301
+ // must be done before animation
1302
+ if (targetBeforeFirstSwap !== undefined && !isCircumstantialInvert) {
1303
+ targetMoveDistance = Math.abs(targetBeforeFirstSwap - getRect(target)[side1]);
1304
+ }
1305
+ changed();
1306
+
1307
+ return completed(true);
1308
+ }
1309
+ }
1310
+
1311
+ if (el.contains(dragEl)) {
1312
+ return completed(false);
1313
+ }
1314
+ }
1315
+
1316
+ return false;
1317
+ },
1318
+
1319
+ _ignoreWhileAnimating: null,
1320
+
1321
+ _offMoveEvents: function() {
1322
+ off(document, 'mousemove', this._onTouchMove);
1323
+ off(document, 'touchmove', this._onTouchMove);
1324
+ off(document, 'pointermove', this._onTouchMove);
1325
+ off(document, 'dragover', nearestEmptyInsertDetectEvent);
1326
+ off(document, 'mousemove', nearestEmptyInsertDetectEvent);
1327
+ off(document, 'touchmove', nearestEmptyInsertDetectEvent);
1328
+ },
1329
+
1330
+ _offUpEvents: function () {
1331
+ let ownerDocument = this.el.ownerDocument;
1332
+
1333
+ off(ownerDocument, 'mouseup', this._onDrop);
1334
+ off(ownerDocument, 'touchend', this._onDrop);
1335
+ off(ownerDocument, 'pointerup', this._onDrop);
1336
+ off(ownerDocument, 'touchcancel', this._onDrop);
1337
+ off(document, 'selectstart', this);
1338
+ },
1339
+
1340
+ _onDrop: function (/**Event*/evt) {
1341
+ let el = this.el,
1342
+ options = this.options;
1343
+
1344
+ // Get the index of the dragged element within its parent
1345
+ newIndex = index(dragEl);
1346
+ newDraggableIndex = index(dragEl, options.draggable);
1347
+
1348
+ pluginEvent('drop', this, {
1349
+ evt
1350
+ });
1351
+
1352
+ parentEl = dragEl && dragEl.parentNode;
1353
+
1354
+ // Get again after plugin event
1355
+ newIndex = index(dragEl);
1356
+ newDraggableIndex = index(dragEl, options.draggable);
1357
+
1358
+ if (Sortable.eventCanceled) {
1359
+ this._nulling();
1360
+ return;
1361
+ }
1362
+
1363
+ awaitingDragStarted = false;
1364
+ isCircumstantialInvert = false;
1365
+ pastFirstInvertThresh = false;
1366
+
1367
+ clearInterval(this._loopId);
1368
+
1369
+ clearTimeout(this._dragStartTimer);
1370
+
1371
+ _cancelNextTick(this.cloneId);
1372
+ _cancelNextTick(this._dragStartId);
1373
+
1374
+ // Unbind events
1375
+ if (this.nativeDraggable) {
1376
+ off(document, 'drop', this);
1377
+ off(el, 'dragstart', this._onDragStart);
1378
+ }
1379
+ this._offMoveEvents();
1380
+ this._offUpEvents();
1381
+
1382
+
1383
+ if (Safari) {
1384
+ css(document.body, 'user-select', '');
1385
+ }
1386
+
1387
+ css(dragEl, 'transform', '');
1388
+
1389
+ if (evt) {
1390
+ if (moved) {
1391
+ evt.cancelable && evt.preventDefault();
1392
+ !options.dropBubble && evt.stopPropagation();
1393
+ }
1394
+
1395
+ ghostEl && ghostEl.parentNode && ghostEl.parentNode.removeChild(ghostEl);
1396
+
1397
+ if (rootEl === parentEl || (putSortable && putSortable.lastPutMode !== 'clone')) {
1398
+ // Remove clone(s)
1399
+ cloneEl && cloneEl.parentNode && cloneEl.parentNode.removeChild(cloneEl);
1400
+ }
1401
+
1402
+ if (dragEl) {
1403
+ if (this.nativeDraggable) {
1404
+ off(dragEl, 'dragend', this);
1405
+ }
1406
+
1407
+ _disableDraggable(dragEl);
1408
+ dragEl.style['will-change'] = '';
1409
+
1410
+ // Remove classes
1411
+ // ghostClass is added in dragStarted
1412
+ if (moved && !awaitingDragStarted) {
1413
+ toggleClass(dragEl, putSortable ? putSortable.options.ghostClass : this.options.ghostClass, false);
1414
+ }
1415
+ toggleClass(dragEl, this.options.chosenClass, false);
1416
+
1417
+ // Drag stop event
1418
+ _dispatchEvent({
1419
+ sortable: this,
1420
+ name: 'unchoose',
1421
+ toEl: parentEl,
1422
+ newIndex: null,
1423
+ newDraggableIndex: null,
1424
+ originalEvent: evt
1425
+ });
1426
+
1427
+
1428
+ if (rootEl !== parentEl) {
1429
+
1430
+ if (newIndex >= 0) {
1431
+ // Add event
1432
+ _dispatchEvent({
1433
+ rootEl: parentEl,
1434
+ name: 'add',
1435
+ toEl: parentEl,
1436
+ fromEl: rootEl,
1437
+ originalEvent: evt
1438
+ });
1439
+
1440
+ // Remove event
1441
+ _dispatchEvent({
1442
+ sortable: this,
1443
+ name: 'remove',
1444
+ toEl: parentEl,
1445
+ originalEvent: evt
1446
+ });
1447
+
1448
+ // drag from one list and drop into another
1449
+ _dispatchEvent({
1450
+ rootEl: parentEl,
1451
+ name: 'sort',
1452
+ toEl: parentEl,
1453
+ fromEl: rootEl,
1454
+ originalEvent: evt
1455
+ });
1456
+
1457
+ _dispatchEvent({
1458
+ sortable: this,
1459
+ name: 'sort',
1460
+ toEl: parentEl,
1461
+ originalEvent: evt
1462
+ });
1463
+ }
1464
+
1465
+ putSortable && putSortable.save();
1466
+ } else {
1467
+ if (newIndex !== oldIndex) {
1468
+ if (newIndex >= 0) {
1469
+ // drag & drop within the same list
1470
+ _dispatchEvent({
1471
+ sortable: this,
1472
+ name: 'update',
1473
+ toEl: parentEl,
1474
+ originalEvent: evt
1475
+ });
1476
+
1477
+ _dispatchEvent({
1478
+ sortable: this,
1479
+ name: 'sort',
1480
+ toEl: parentEl,
1481
+ originalEvent: evt
1482
+ });
1483
+ }
1484
+ }
1485
+ }
1486
+
1487
+ if (Sortable.active) {
1488
+ /* jshint eqnull:true */
1489
+ if (newIndex == null || newIndex === -1) {
1490
+ newIndex = oldIndex;
1491
+ newDraggableIndex = oldDraggableIndex;
1492
+ }
1493
+
1494
+ _dispatchEvent({
1495
+ sortable: this,
1496
+ name: 'end',
1497
+ toEl: parentEl,
1498
+ originalEvent: evt
1499
+ });
1500
+
1501
+ // Save sorting
1502
+ this.save();
1503
+ }
1504
+ }
1505
+
1506
+ }
1507
+ this._nulling();
1508
+ },
1509
+
1510
+ _nulling: function() {
1511
+ pluginEvent('nulling', this);
1512
+
1513
+ rootEl =
1514
+ dragEl =
1515
+ parentEl =
1516
+ ghostEl =
1517
+ nextEl =
1518
+ cloneEl =
1519
+ lastDownEl =
1520
+ cloneHidden =
1521
+
1522
+ tapEvt =
1523
+ touchEvt =
1524
+
1525
+ moved =
1526
+ newIndex =
1527
+ newDraggableIndex =
1528
+ oldIndex =
1529
+ oldDraggableIndex =
1530
+
1531
+ lastTarget =
1532
+ lastDirection =
1533
+
1534
+ putSortable =
1535
+ activeGroup =
1536
+ Sortable.dragged =
1537
+ Sortable.ghost =
1538
+ Sortable.clone =
1539
+ Sortable.active = null;
1540
+
1541
+ savedInputChecked.forEach(function (el) {
1542
+ el.checked = true;
1543
+ });
1544
+
1545
+ savedInputChecked.length =
1546
+ lastDx =
1547
+ lastDy = 0;
1548
+ },
1549
+
1550
+ handleEvent: function (/**Event*/evt) {
1551
+ switch (evt.type) {
1552
+ case 'drop':
1553
+ case 'dragend':
1554
+ this._onDrop(evt);
1555
+ break;
1556
+
1557
+ case 'dragenter':
1558
+ case 'dragover':
1559
+ if (dragEl) {
1560
+ this._onDragOver(evt);
1561
+ _globalDragOver(evt);
1562
+ }
1563
+ break;
1564
+
1565
+ case 'selectstart':
1566
+ evt.preventDefault();
1567
+ break;
1568
+ }
1569
+ },
1570
+
1571
+
1572
+ /**
1573
+ * Serializes the item into an array of string.
1574
+ * @returns {String[]}
1575
+ */
1576
+ toArray: function () {
1577
+ let order = [],
1578
+ el,
1579
+ children = this.el.children,
1580
+ i = 0,
1581
+ n = children.length,
1582
+ options = this.options;
1583
+
1584
+ for (; i < n; i++) {
1585
+ el = children[i];
1586
+ if (closest(el, options.draggable, this.el, false)) {
1587
+ order.push(el.getAttribute(options.dataIdAttr) || _generateId(el));
1588
+ }
1589
+ }
1590
+
1591
+ return order;
1592
+ },
1593
+
1594
+
1595
+ /**
1596
+ * Sorts the elements according to the array.
1597
+ * @param {String[]} order order of the items
1598
+ */
1599
+ sort: function (order, useAnimation) {
1600
+ let items = {}, rootEl = this.el;
1601
+
1602
+ this.toArray().forEach(function (id, i) {
1603
+ let el = rootEl.children[i];
1604
+
1605
+ if (closest(el, this.options.draggable, rootEl, false)) {
1606
+ items[id] = el;
1607
+ }
1608
+ }, this);
1609
+
1610
+ useAnimation && this.captureAnimationState();
1611
+ order.forEach(function (id) {
1612
+ if (items[id]) {
1613
+ rootEl.removeChild(items[id]);
1614
+ rootEl.appendChild(items[id]);
1615
+ }
1616
+ });
1617
+ useAnimation && this.animateAll();
1618
+ },
1619
+
1620
+
1621
+ /**
1622
+ * Save the current sorting
1623
+ */
1624
+ save: function () {
1625
+ let store = this.options.store;
1626
+ store && store.set && store.set(this);
1627
+ },
1628
+
1629
+
1630
+ /**
1631
+ * 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.
1632
+ * @param {HTMLElement} el
1633
+ * @param {String} [selector] default: `options.draggable`
1634
+ * @returns {HTMLElement|null}
1635
+ */
1636
+ closest: function (el, selector) {
1637
+ return closest(el, selector || this.options.draggable, this.el, false);
1638
+ },
1639
+
1640
+
1641
+ /**
1642
+ * Set/get option
1643
+ * @param {string} name
1644
+ * @param {*} [value]
1645
+ * @returns {*}
1646
+ */
1647
+ option: function (name, value) {
1648
+ let options = this.options;
1649
+
1650
+ if (value === void 0) {
1651
+ return options[name];
1652
+ } else {
1653
+ let modifiedValue = PluginManager.modifyOption(this, name, value);
1654
+ if (typeof modifiedValue !== 'undefined') {
1655
+ options[name] = modifiedValue;
1656
+ } else {
1657
+ options[name] = value;
1658
+ }
1659
+
1660
+ if (name === 'group') {
1661
+ _prepareGroup(options);
1662
+ }
1663
+ }
1664
+ },
1665
+
1666
+
1667
+ /**
1668
+ * Destroy
1669
+ */
1670
+ destroy: function () {
1671
+ pluginEvent('destroy', this);
1672
+ let el = this.el;
1673
+
1674
+ el[expando] = null;
1675
+
1676
+ off(el, 'mousedown', this._onTapStart);
1677
+ off(el, 'touchstart', this._onTapStart);
1678
+ off(el, 'pointerdown', this._onTapStart);
1679
+
1680
+ if (this.nativeDraggable) {
1681
+ off(el, 'dragover', this);
1682
+ off(el, 'dragenter', this);
1683
+ }
1684
+ // Remove draggable attributes
1685
+ Array.prototype.forEach.call(el.querySelectorAll('[draggable]'), function (el) {
1686
+ el.removeAttribute('draggable');
1687
+ });
1688
+
1689
+ this._onDrop();
1690
+
1691
+ this._disableDelayedDragEvents();
1692
+
1693
+ sortables.splice(sortables.indexOf(this.el), 1);
1694
+
1695
+ this.el = el = null;
1696
+ },
1697
+
1698
+ _hideClone: function() {
1699
+ if (!cloneHidden) {
1700
+ pluginEvent('hideClone', this);
1701
+ if (Sortable.eventCanceled) return;
1702
+
1703
+
1704
+ css(cloneEl, 'display', 'none');
1705
+ if (this.options.removeCloneOnHide && cloneEl.parentNode) {
1706
+ cloneEl.parentNode.removeChild(cloneEl);
1707
+ }
1708
+ cloneHidden = true;
1709
+ }
1710
+ },
1711
+
1712
+ _showClone: function(putSortable) {
1713
+ if (putSortable.lastPutMode !== 'clone') {
1714
+ this._hideClone();
1715
+ return;
1716
+ }
1717
+
1718
+
1719
+ if (cloneHidden) {
1720
+ pluginEvent('showClone', this);
1721
+ if (Sortable.eventCanceled) return;
1722
+
1723
+ // show clone at dragEl or original position
1724
+ if (dragEl.parentNode == rootEl && !this.options.group.revertClone) {
1725
+ rootEl.insertBefore(cloneEl, dragEl);
1726
+ } else if (nextEl) {
1727
+ rootEl.insertBefore(cloneEl, nextEl);
1728
+ } else {
1729
+ rootEl.appendChild(cloneEl);
1730
+ }
1731
+
1732
+ if (this.options.group.revertClone) {
1733
+ this.animate(dragEl, cloneEl);
1734
+ }
1735
+
1736
+ css(cloneEl, 'display', '');
1737
+ cloneHidden = false;
1738
+ }
1739
+ }
1740
+ };
1741
+
1742
+ function _globalDragOver(/**Event*/evt) {
1743
+ if (evt.dataTransfer) {
1744
+ evt.dataTransfer.dropEffect = 'move';
1745
+ }
1746
+ evt.cancelable && evt.preventDefault();
1747
+ }
1748
+
1749
+ function onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvent, willInsertAfter) {
1750
+ let evt,
1751
+ sortable = fromEl[expando],
1752
+ onMoveFn = sortable.options.onMove,
1753
+ retVal;
1754
+ // Support for new CustomEvent feature
1755
+ if (window.CustomEvent && !IE11OrLess && !Edge) {
1756
+ evt = new CustomEvent('move', {
1757
+ bubbles: true,
1758
+ cancelable: true
1759
+ });
1760
+ } else {
1761
+ evt = document.createEvent('Event');
1762
+ evt.initEvent('move', true, true);
1763
+ }
1764
+
1765
+ evt.to = toEl;
1766
+ evt.from = fromEl;
1767
+ evt.dragged = dragEl;
1768
+ evt.draggedRect = dragRect;
1769
+ evt.related = targetEl || toEl;
1770
+ evt.relatedRect = targetRect || getRect(toEl);
1771
+ evt.willInsertAfter = willInsertAfter;
1772
+
1773
+ evt.originalEvent = originalEvent;
1774
+
1775
+ fromEl.dispatchEvent(evt);
1776
+
1777
+ if (onMoveFn) {
1778
+ retVal = onMoveFn.call(sortable, evt, originalEvent);
1779
+ }
1780
+
1781
+ return retVal;
1782
+ }
1783
+
1784
+ function _disableDraggable(el) {
1785
+ el.draggable = false;
1786
+ }
1787
+
1788
+ function _unsilent() {
1789
+ _silent = false;
1790
+ }
1791
+
1792
+ function _ghostIsFirst(evt, vertical, sortable) {
1793
+ let firstElRect = getRect(getChild(sortable.el, 0, sortable.options, true));
1794
+ const childContainingRect = getChildContainingRectFromElement(sortable.el, sortable.options, ghostEl);
1795
+ const spacer = 10;
1796
+
1797
+ return vertical ?
1798
+ (evt.clientX < childContainingRect.left - spacer || evt.clientY < firstElRect.top && evt.clientX < firstElRect.right) :
1799
+ (evt.clientY < childContainingRect.top - spacer || evt.clientY < firstElRect.bottom && evt.clientX < firstElRect.left)
1800
+ }
1801
+
1802
+ function _ghostIsLast(evt, vertical, sortable) {
1803
+ const lastElRect = getRect(lastChild(sortable.el, sortable.options.draggable));
1804
+ const childContainingRect = getChildContainingRectFromElement(sortable.el, sortable.options, ghostEl);
1805
+ const spacer = 10;
1806
+
1807
+ return vertical ?
1808
+ (evt.clientX > childContainingRect.right + spacer || evt.clientY > lastElRect.bottom && evt.clientX > lastElRect.left) :
1809
+ (evt.clientY > childContainingRect.bottom + spacer || evt.clientX > lastElRect.right && evt.clientY > lastElRect.top);
1810
+ }
1811
+
1812
+ function _getSwapDirection(evt, target, targetRect, vertical, swapThreshold, invertedSwapThreshold, invertSwap, isLastTarget) {
1813
+ let mouseOnAxis = vertical ? evt.clientY : evt.clientX,
1814
+ targetLength = vertical ? targetRect.height : targetRect.width,
1815
+ targetS1 = vertical ? targetRect.top : targetRect.left,
1816
+ targetS2 = vertical ? targetRect.bottom : targetRect.right,
1817
+ invert = false;
1818
+
1819
+
1820
+ if (!invertSwap) {
1821
+ // Never invert or create dragEl shadow when target movemenet causes mouse to move past the end of regular swapThreshold
1822
+ if (isLastTarget && targetMoveDistance < targetLength * swapThreshold) { // multiplied only by swapThreshold because mouse will already be inside target by (1 - threshold) * targetLength / 2
1823
+ // check if past first invert threshold on side opposite of lastDirection
1824
+ if (!pastFirstInvertThresh &&
1825
+ (lastDirection === 1 ?
1826
+ (
1827
+ mouseOnAxis > targetS1 + targetLength * invertedSwapThreshold / 2
1828
+ ) :
1829
+ (
1830
+ mouseOnAxis < targetS2 - targetLength * invertedSwapThreshold / 2
1831
+ )
1832
+ )
1833
+ )
1834
+ {
1835
+ // past first invert threshold, do not restrict inverted threshold to dragEl shadow
1836
+ pastFirstInvertThresh = true;
1837
+ }
1838
+
1839
+ if (!pastFirstInvertThresh) {
1840
+ // dragEl shadow (target move distance shadow)
1841
+ if (
1842
+ lastDirection === 1 ?
1843
+ (
1844
+ mouseOnAxis < targetS1 + targetMoveDistance // over dragEl shadow
1845
+ ) :
1846
+ (
1847
+ mouseOnAxis > targetS2 - targetMoveDistance
1848
+ )
1849
+ )
1850
+ {
1851
+ return -lastDirection;
1852
+ }
1853
+ } else {
1854
+ invert = true;
1855
+ }
1856
+ } else {
1857
+ // Regular
1858
+ if (
1859
+ mouseOnAxis > targetS1 + (targetLength * (1 - swapThreshold) / 2) &&
1860
+ mouseOnAxis < targetS2 - (targetLength * (1 - swapThreshold) / 2)
1861
+ ) {
1862
+ return _getInsertDirection(target);
1863
+ }
1864
+ }
1865
+ }
1866
+
1867
+ invert = invert || invertSwap;
1868
+
1869
+ if (invert) {
1870
+ // Invert of regular
1871
+ if (
1872
+ mouseOnAxis < targetS1 + (targetLength * invertedSwapThreshold / 2) ||
1873
+ mouseOnAxis > targetS2 - (targetLength * invertedSwapThreshold / 2)
1874
+ )
1875
+ {
1876
+ return ((mouseOnAxis > targetS1 + targetLength / 2) ? 1 : -1);
1877
+ }
1878
+ }
1879
+
1880
+ return 0;
1881
+ }
1882
+
1883
+ /**
1884
+ * Gets the direction dragEl must be swapped relative to target in order to make it
1885
+ * seem that dragEl has been "inserted" into that element's position
1886
+ * @param {HTMLElement} target The target whose position dragEl is being inserted at
1887
+ * @return {Number} Direction dragEl must be swapped
1888
+ */
1889
+ function _getInsertDirection(target) {
1890
+ if (index(dragEl) < index(target)) {
1891
+ return 1;
1892
+ } else {
1893
+ return -1;
1894
+ }
1895
+ }
1896
+
1897
+
1898
+ /**
1899
+ * Generate id
1900
+ * @param {HTMLElement} el
1901
+ * @returns {String}
1902
+ * @private
1903
+ */
1904
+ function _generateId(el) {
1905
+ let str = el.tagName + el.className + el.src + el.href + el.textContent,
1906
+ i = str.length,
1907
+ sum = 0;
1908
+
1909
+ while (i--) {
1910
+ sum += str.charCodeAt(i);
1911
+ }
1912
+
1913
+ return sum.toString(36);
1914
+ }
1915
+
1916
+ function _saveInputCheckedState(root) {
1917
+ savedInputChecked.length = 0;
1918
+
1919
+ let inputs = root.getElementsByTagName('input');
1920
+ let idx = inputs.length;
1921
+
1922
+ while (idx--) {
1923
+ let el = inputs[idx];
1924
+ el.checked && savedInputChecked.push(el);
1925
+ }
1926
+ }
1927
+
1928
+ function _nextTick(fn) {
1929
+ return setTimeout(fn, 0);
1930
+ }
1931
+
1932
+ function _cancelNextTick(id) {
1933
+ return clearTimeout(id);
1934
+ }
1935
+
1936
+ // Fixed #973:
1937
+ if (documentExists) {
1938
+ on(document, 'touchmove', function(evt) {
1939
+ if ((Sortable.active || awaitingDragStarted) && evt.cancelable) {
1940
+ evt.preventDefault();
1941
+ }
1942
+ });
1943
+ }
1944
+
1945
+
1946
+ // Export utils
1947
+ Sortable.utils = {
1948
+ on,
1949
+ off,
1950
+ css,
1951
+ find,
1952
+ is: function (el, selector) {
1953
+ return !!closest(el, selector, el, false);
1954
+ },
1955
+ extend,
1956
+ throttle,
1957
+ closest,
1958
+ toggleClass,
1959
+ clone,
1960
+ index,
1961
+ nextTick: _nextTick,
1962
+ cancelNextTick: _cancelNextTick,
1963
+ detectDirection: _detectDirection,
1964
+ getChild,
1965
+ expando
1966
+ };
1967
+
1968
+
1969
+ /**
1970
+ * Get the Sortable instance of an element
1971
+ * @param {HTMLElement} element The element
1972
+ * @return {Sortable|undefined} The instance of Sortable
1973
+ */
1974
+ Sortable.get = function(element) {
1975
+ return element[expando];
1976
+ };
1977
+
1978
+ /**
1979
+ * Mount a plugin to Sortable
1980
+ * @param {...SortablePlugin|SortablePlugin[]} plugins Plugins being mounted
1981
+ */
1982
+ Sortable.mount = function(...plugins) {
1983
+ if (plugins[0].constructor === Array) plugins = plugins[0];
1984
+
1985
+ plugins.forEach((plugin) => {
1986
+ if (!plugin.prototype || !plugin.prototype.constructor) {
1987
+ throw `Sortable: Mounted plugin must be a constructor function, not ${ {}.toString.call(plugin) }`;
1988
+ }
1989
+ if (plugin.utils) Sortable.utils = { ...Sortable.utils, ...plugin.utils };
1990
+
1991
+ PluginManager.mount(plugin);
1992
+ });
1993
+ };
1994
+
1995
+
1996
+
1997
+ /**
1998
+ * Create sortable instance
1999
+ * @param {HTMLElement} el
2000
+ * @param {Object} [options]
2001
+ */
2002
+ Sortable.create = function (el, options) {
2003
+ return new Sortable(el, options);
2004
+ };
2005
+
2006
+
2007
+ // Export
2008
+ Sortable.version = version;
2009
+
2010
+
2011
+ export default Sortable;