govuk_publishing_components 43.0.1 → 43.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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;