sortablejs 1.8.1 → 1.9.0
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.
- package/README.md +17 -0
- package/Sortable.js +337 -214
- package/Sortable.min.js +2 -2
- package/package.json +3 -3
package/Sortable.js
CHANGED
|
@@ -41,6 +41,8 @@
|
|
|
41
41
|
|
|
42
42
|
oldIndex,
|
|
43
43
|
newIndex,
|
|
44
|
+
oldDraggableIndex,
|
|
45
|
+
newDraggableIndex,
|
|
44
46
|
|
|
45
47
|
activeGroup,
|
|
46
48
|
putSortable,
|
|
@@ -70,8 +72,10 @@
|
|
|
70
72
|
|
|
71
73
|
targetMoveDistance,
|
|
72
74
|
|
|
75
|
+
// For positioning ghost absolutely
|
|
76
|
+
ghostRelativeParent,
|
|
77
|
+
ghostRelativeParentInitialScroll = [], // (left, top)
|
|
73
78
|
|
|
74
|
-
forRepaintDummy,
|
|
75
79
|
realDragElRect, // dragEl rect after current animation
|
|
76
80
|
|
|
77
81
|
/** @const */
|
|
@@ -94,7 +98,11 @@
|
|
|
94
98
|
|
|
95
99
|
IE11OrLess = !!navigator.userAgent.match(/(?:Trident.*rv[ :]?11\.|msie|iemobile)/i),
|
|
96
100
|
Edge = !!navigator.userAgent.match(/Edge/i),
|
|
97
|
-
|
|
101
|
+
FireFox = !!navigator.userAgent.match(/firefox/i),
|
|
102
|
+
Safari = !!(navigator.userAgent.match(/safari/i) && !navigator.userAgent.match(/chrome/i) && !navigator.userAgent.match(/android/i)),
|
|
103
|
+
IOS = !!(navigator.userAgent.match(/iP(ad|od|hone)/i)),
|
|
104
|
+
|
|
105
|
+
PositionGhostAbsolutely = IOS,
|
|
98
106
|
|
|
99
107
|
CSSFloatProperty = Edge || IE11OrLess ? 'cssFloat' : 'float',
|
|
100
108
|
|
|
@@ -116,22 +124,40 @@
|
|
|
116
124
|
|
|
117
125
|
abs = Math.abs,
|
|
118
126
|
min = Math.min,
|
|
127
|
+
max = Math.max,
|
|
119
128
|
|
|
120
129
|
savedInputChecked = [],
|
|
121
130
|
|
|
122
131
|
_detectDirection = function(el, options) {
|
|
123
132
|
var elCSS = _css(el),
|
|
124
|
-
elWidth = parseInt(elCSS.width)
|
|
133
|
+
elWidth = parseInt(elCSS.width)
|
|
134
|
+
- parseInt(elCSS.paddingLeft)
|
|
135
|
+
- parseInt(elCSS.paddingRight)
|
|
136
|
+
- parseInt(elCSS.borderLeftWidth)
|
|
137
|
+
- parseInt(elCSS.borderRightWidth),
|
|
125
138
|
child1 = _getChild(el, 0, options),
|
|
126
139
|
child2 = _getChild(el, 1, options),
|
|
127
140
|
firstChildCSS = child1 && _css(child1),
|
|
128
141
|
secondChildCSS = child2 && _css(child2),
|
|
129
142
|
firstChildWidth = firstChildCSS && parseInt(firstChildCSS.marginLeft) + parseInt(firstChildCSS.marginRight) + _getRect(child1).width,
|
|
130
143
|
secondChildWidth = secondChildCSS && parseInt(secondChildCSS.marginLeft) + parseInt(secondChildCSS.marginRight) + _getRect(child2).width;
|
|
144
|
+
|
|
131
145
|
if (elCSS.display === 'flex') {
|
|
132
146
|
return elCSS.flexDirection === 'column' || elCSS.flexDirection === 'column-reverse'
|
|
133
147
|
? 'vertical' : 'horizontal';
|
|
134
148
|
}
|
|
149
|
+
|
|
150
|
+
if (elCSS.display === 'grid') {
|
|
151
|
+
return elCSS.gridTemplateColumns.split(' ').length <= 1 ? 'vertical' : 'horizontal';
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (child1 && firstChildCSS.float !== 'none') {
|
|
155
|
+
var touchingSideChild2 = firstChildCSS.float === 'left' ? 'left' : 'right';
|
|
156
|
+
|
|
157
|
+
return child2 && (secondChildCSS.clear === 'both' || secondChildCSS.clear === touchingSideChild2) ?
|
|
158
|
+
'vertical' : 'horizontal';
|
|
159
|
+
}
|
|
160
|
+
|
|
135
161
|
return (child1 &&
|
|
136
162
|
(
|
|
137
163
|
firstChildCSS.display === 'block' ||
|
|
@@ -156,14 +182,14 @@
|
|
|
156
182
|
*/
|
|
157
183
|
_detectNearestEmptySortable = function(x, y) {
|
|
158
184
|
for (var i = 0; i < sortables.length; i++) {
|
|
159
|
-
if (sortables[i]
|
|
185
|
+
if (_lastChild(sortables[i])) continue;
|
|
160
186
|
|
|
161
187
|
var rect = _getRect(sortables[i]),
|
|
162
188
|
threshold = sortables[i][expando].options.emptyInsertThreshold,
|
|
163
189
|
insideHorizontally = x >= (rect.left - threshold) && x <= (rect.right + threshold),
|
|
164
190
|
insideVertically = y >= (rect.top - threshold) && y <= (rect.bottom + threshold);
|
|
165
191
|
|
|
166
|
-
if (insideHorizontally && insideVertically) {
|
|
192
|
+
if (threshold && insideHorizontally && insideVertically) {
|
|
167
193
|
return sortables[i];
|
|
168
194
|
}
|
|
169
195
|
}
|
|
@@ -197,7 +223,7 @@
|
|
|
197
223
|
|
|
198
224
|
_getParentAutoScrollElement = function(el, includeSelf) {
|
|
199
225
|
// skip to window
|
|
200
|
-
if (!el || !el.getBoundingClientRect) return
|
|
226
|
+
if (!el || !el.getBoundingClientRect) return _getWindowScrollingElement();
|
|
201
227
|
|
|
202
228
|
var elem = el;
|
|
203
229
|
var gotSelf = false;
|
|
@@ -209,7 +235,7 @@
|
|
|
209
235
|
elem.clientWidth < elem.scrollWidth && (elemCSS.overflowX == 'auto' || elemCSS.overflowX == 'scroll') ||
|
|
210
236
|
elem.clientHeight < elem.scrollHeight && (elemCSS.overflowY == 'auto' || elemCSS.overflowY == 'scroll')
|
|
211
237
|
) {
|
|
212
|
-
if (!elem || !elem.getBoundingClientRect || elem === document.body) return
|
|
238
|
+
if (!elem || !elem.getBoundingClientRect || elem === document.body) return _getWindowScrollingElement();
|
|
213
239
|
|
|
214
240
|
if (gotSelf || includeSelf) return elem;
|
|
215
241
|
gotSelf = true;
|
|
@@ -218,7 +244,20 @@
|
|
|
218
244
|
/* jshint boss:true */
|
|
219
245
|
} while (elem = elem.parentNode);
|
|
220
246
|
|
|
221
|
-
return
|
|
247
|
+
return _getWindowScrollingElement();
|
|
248
|
+
},
|
|
249
|
+
|
|
250
|
+
_getWindowScrollingElement = function() {
|
|
251
|
+
if (IE11OrLess) {
|
|
252
|
+
return document.documentElement;
|
|
253
|
+
} else {
|
|
254
|
+
return document.scrollingElement;
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
|
|
258
|
+
_scrollBy = function(el, x, y) {
|
|
259
|
+
el.scrollLeft += x;
|
|
260
|
+
el.scrollTop += y;
|
|
222
261
|
},
|
|
223
262
|
|
|
224
263
|
_autoScroll = _throttle(function (/**Event*/evt, /**Object*/options, /**HTMLElement*/rootEl, /**Boolean*/isFallback) {
|
|
@@ -231,8 +270,7 @@
|
|
|
231
270
|
x = evt.clientX,
|
|
232
271
|
y = evt.clientY,
|
|
233
272
|
|
|
234
|
-
|
|
235
|
-
winHeight = window.innerHeight,
|
|
273
|
+
winScroller = _getWindowScrollingElement(),
|
|
236
274
|
|
|
237
275
|
scrollThisInstance = false;
|
|
238
276
|
|
|
@@ -279,28 +317,20 @@
|
|
|
279
317
|
scrollPosY;
|
|
280
318
|
|
|
281
319
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
scrollHeight = el.scrollHeight;
|
|
285
|
-
|
|
286
|
-
css = _css(el);
|
|
320
|
+
scrollWidth = el.scrollWidth;
|
|
321
|
+
scrollHeight = el.scrollHeight;
|
|
287
322
|
|
|
288
|
-
|
|
289
|
-
canScrollY = height < scrollHeight && (css.overflowY === 'auto' || css.overflowY === 'scroll');
|
|
290
|
-
|
|
291
|
-
scrollPosX = el.scrollLeft;
|
|
292
|
-
scrollPosY = el.scrollTop;
|
|
293
|
-
} else {
|
|
294
|
-
scrollWidth = document.documentElement.scrollWidth;
|
|
295
|
-
scrollHeight = document.documentElement.scrollHeight;
|
|
323
|
+
css = _css(el);
|
|
296
324
|
|
|
297
|
-
|
|
325
|
+
scrollPosX = el.scrollLeft;
|
|
326
|
+
scrollPosY = el.scrollTop;
|
|
298
327
|
|
|
328
|
+
if (el === winScroller) {
|
|
299
329
|
canScrollX = width < scrollWidth && (css.overflowX === 'auto' || css.overflowX === 'scroll' || css.overflowX === 'visible');
|
|
300
330
|
canScrollY = height < scrollHeight && (css.overflowY === 'auto' || css.overflowY === 'scroll' || css.overflowY === 'visible');
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
331
|
+
} else {
|
|
332
|
+
canScrollX = width < scrollWidth && (css.overflowX === 'auto' || css.overflowX === 'scroll');
|
|
333
|
+
canScrollY = height < scrollHeight && (css.overflowY === 'auto' || css.overflowY === 'scroll');
|
|
304
334
|
}
|
|
305
335
|
|
|
306
336
|
vx = canScrollX && (abs(right - x) <= sens && (scrollPosX + width) < scrollWidth) - (abs(left - x) <= sens && !!scrollPosX);
|
|
@@ -330,6 +360,7 @@
|
|
|
330
360
|
// emulate drag over during autoscroll (fallback), emulating native DnD behaviour
|
|
331
361
|
if (isFallback && this.layer === 0) {
|
|
332
362
|
Sortable.active._emulateDragOver(true);
|
|
363
|
+
Sortable.active._onTouchMove(touchEvt, true);
|
|
333
364
|
}
|
|
334
365
|
var scrollOffsetY = autoScrolls[this.layer].vy ? autoScrolls[this.layer].vy * speed : 0;
|
|
335
366
|
var scrollOffsetX = autoScrolls[this.layer].vx ? autoScrolls[this.layer].vx * speed : 0;
|
|
@@ -339,17 +370,13 @@
|
|
|
339
370
|
return;
|
|
340
371
|
}
|
|
341
372
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
} else {
|
|
345
|
-
autoScrolls[this.layer].el.scrollTop += scrollOffsetY;
|
|
346
|
-
autoScrolls[this.layer].el.scrollLeft += scrollOffsetX;
|
|
347
|
-
}
|
|
373
|
+
|
|
374
|
+
_scrollBy(autoScrolls[this.layer].el, scrollOffsetX, scrollOffsetY);
|
|
348
375
|
}).bind({layer: layersOut}), 24);
|
|
349
376
|
}
|
|
350
377
|
}
|
|
351
378
|
layersOut++;
|
|
352
|
-
} while (options.bubbleScroll && currentParent !==
|
|
379
|
+
} while (options.bubbleScroll && currentParent !== winScroller && (currentParent = _getParentAutoScrollElement(currentParent, false)));
|
|
353
380
|
scrolling = scrollThisInstance; // in case another function catches scrolling as false in between when it is not
|
|
354
381
|
}
|
|
355
382
|
}, 30),
|
|
@@ -408,29 +435,6 @@
|
|
|
408
435
|
dragEl.parentNode[expando] && dragEl.parentNode[expando]._computeIsAligned(evt);
|
|
409
436
|
},
|
|
410
437
|
|
|
411
|
-
_isTrueParentSortable = function(el, target) {
|
|
412
|
-
var trueParent = target;
|
|
413
|
-
while (!trueParent[expando]) {
|
|
414
|
-
trueParent = trueParent.parentNode;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
return el === trueParent;
|
|
418
|
-
},
|
|
419
|
-
|
|
420
|
-
_artificalBubble = function(sortable, originalEvt, method) {
|
|
421
|
-
// Artificial IE bubbling
|
|
422
|
-
var nextParent = sortable.parentNode;
|
|
423
|
-
while (nextParent && !nextParent[expando]) {
|
|
424
|
-
nextParent = nextParent.parentNode;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
if (nextParent) {
|
|
428
|
-
nextParent[expando][method](_extend(originalEvt, {
|
|
429
|
-
artificialBubble: true
|
|
430
|
-
}));
|
|
431
|
-
}
|
|
432
|
-
},
|
|
433
|
-
|
|
434
438
|
_hideGhostForTarget = function() {
|
|
435
439
|
if (!supportCssPointerEvents && ghostEl) {
|
|
436
440
|
_css(ghostEl, 'display', 'none');
|
|
@@ -457,21 +461,22 @@
|
|
|
457
461
|
|
|
458
462
|
var nearestEmptyInsertDetectEvent = function(evt) {
|
|
459
463
|
if (dragEl) {
|
|
464
|
+
evt = evt.touches ? evt.touches[0] : evt;
|
|
460
465
|
var nearest = _detectNearestEmptySortable(evt.clientX, evt.clientY);
|
|
461
466
|
|
|
462
467
|
if (nearest) {
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
468
|
+
// Create imitation event
|
|
469
|
+
var event = {};
|
|
470
|
+
for (var i in evt) {
|
|
471
|
+
event[i] = evt[i];
|
|
472
|
+
}
|
|
473
|
+
event.target = event.rootEl = nearest;
|
|
474
|
+
event.preventDefault = void 0;
|
|
475
|
+
event.stopPropagation = void 0;
|
|
476
|
+
nearest[expando]._onDragOver(event);
|
|
469
477
|
}
|
|
470
478
|
}
|
|
471
479
|
};
|
|
472
|
-
// We do not want this to be triggered if completed (bubbling canceled), so only define it here
|
|
473
|
-
document.addEventListener('dragover', nearestEmptyInsertDetectEvent);
|
|
474
|
-
document.addEventListener('mousemove', nearestEmptyInsertDetectEvent);
|
|
475
480
|
|
|
476
481
|
/**
|
|
477
482
|
* @class Sortable
|
|
@@ -501,7 +506,7 @@
|
|
|
501
506
|
scrollSensitivity: 30,
|
|
502
507
|
scrollSpeed: 10,
|
|
503
508
|
bubbleScroll: true,
|
|
504
|
-
draggable: /[uo]l/i.test(el.nodeName) ? 'li' : '>*',
|
|
509
|
+
draggable: /[uo]l/i.test(el.nodeName) ? '>li' : '>*',
|
|
505
510
|
swapThreshold: 1, // percentage; 0 <= x <= 1
|
|
506
511
|
invertSwap: false, // invert always
|
|
507
512
|
invertedSwapThreshold: null, // will be set to same as swapThreshold if default
|
|
@@ -524,16 +529,14 @@
|
|
|
524
529
|
dragoverBubble: false,
|
|
525
530
|
dataIdAttr: 'data-id',
|
|
526
531
|
delay: 0,
|
|
532
|
+
delayOnTouchOnly: false,
|
|
527
533
|
touchStartThreshold: parseInt(window.devicePixelRatio, 10) || 1,
|
|
528
534
|
forceFallback: false,
|
|
529
535
|
fallbackClass: 'sortable-fallback',
|
|
530
536
|
fallbackOnBody: false,
|
|
531
537
|
fallbackTolerance: 0,
|
|
532
538
|
fallbackOffset: {x: 0, y: 0},
|
|
533
|
-
supportPointer: Sortable.supportPointer !== false && (
|
|
534
|
-
('PointerEvent' in window) ||
|
|
535
|
-
window.navigator && ('msPointerEnabled' in window.navigator) // microsoft
|
|
536
|
-
),
|
|
539
|
+
supportPointer: Sortable.supportPointer !== false && ('PointerEvent' in window),
|
|
537
540
|
emptyInsertThreshold: 5
|
|
538
541
|
};
|
|
539
542
|
|
|
@@ -555,6 +558,11 @@
|
|
|
555
558
|
// Setup drag mode
|
|
556
559
|
this.nativeDraggable = options.forceFallback ? false : supportDraggable;
|
|
557
560
|
|
|
561
|
+
if (this.nativeDraggable) {
|
|
562
|
+
// Touch start threshold cannot be greater than the native dragstart threshold
|
|
563
|
+
this.options.touchStartThreshold = 1;
|
|
564
|
+
}
|
|
565
|
+
|
|
558
566
|
// Bind events
|
|
559
567
|
if (options.supportPointer) {
|
|
560
568
|
_on(el, 'pointerdown', this._onTapStart);
|
|
@@ -617,7 +625,6 @@
|
|
|
617
625
|
|
|
618
626
|
_onTapStart: function (/** Event|TouchEvent */evt) {
|
|
619
627
|
if (!evt.cancelable) return;
|
|
620
|
-
|
|
621
628
|
var _this = this,
|
|
622
629
|
el = this.el,
|
|
623
630
|
options = this.options,
|
|
@@ -627,17 +634,11 @@
|
|
|
627
634
|
target = (touch || evt).target,
|
|
628
635
|
originalTarget = evt.target.shadowRoot && ((evt.path && evt.path[0]) || (evt.composedPath && evt.composedPath()[0])) || target,
|
|
629
636
|
filter = options.filter,
|
|
630
|
-
startIndex
|
|
637
|
+
startIndex,
|
|
638
|
+
startDraggableIndex;
|
|
631
639
|
|
|
632
640
|
_saveInputCheckedState(el);
|
|
633
641
|
|
|
634
|
-
|
|
635
|
-
// IE: Calls events in capture mode if event element is nested. This ensures only correct element's _onTapStart goes through.
|
|
636
|
-
// This process is also done in _onDragOver
|
|
637
|
-
if (IE11OrLess && !evt.artificialBubble && !_isTrueParentSortable(el, target)) {
|
|
638
|
-
return;
|
|
639
|
-
}
|
|
640
|
-
|
|
641
642
|
// Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group.
|
|
642
643
|
if (dragEl) {
|
|
643
644
|
return;
|
|
@@ -654,12 +655,6 @@
|
|
|
654
655
|
|
|
655
656
|
target = _closest(target, options.draggable, el, false);
|
|
656
657
|
|
|
657
|
-
if (!target) {
|
|
658
|
-
if (IE11OrLess) {
|
|
659
|
-
_artificalBubble(el, evt, '_onTapStart');
|
|
660
|
-
}
|
|
661
|
-
return;
|
|
662
|
-
}
|
|
663
658
|
|
|
664
659
|
if (lastDownEl === target) {
|
|
665
660
|
// Ignoring duplicate `down`
|
|
@@ -667,12 +662,13 @@
|
|
|
667
662
|
}
|
|
668
663
|
|
|
669
664
|
// Get the index of the dragged element within its parent
|
|
670
|
-
startIndex = _index(target
|
|
665
|
+
startIndex = _index(target);
|
|
666
|
+
startDraggableIndex = _index(target, options.draggable);
|
|
671
667
|
|
|
672
668
|
// Check filter
|
|
673
669
|
if (typeof filter === 'function') {
|
|
674
670
|
if (filter.call(this, evt, target, this)) {
|
|
675
|
-
_dispatchEvent(_this, originalTarget, 'filter', target, el, el, startIndex);
|
|
671
|
+
_dispatchEvent(_this, originalTarget, 'filter', target, el, el, startIndex, undefined, startDraggableIndex);
|
|
676
672
|
preventOnFilter && evt.cancelable && evt.preventDefault();
|
|
677
673
|
return; // cancel dnd
|
|
678
674
|
}
|
|
@@ -682,7 +678,7 @@
|
|
|
682
678
|
criteria = _closest(originalTarget, criteria.trim(), el, false);
|
|
683
679
|
|
|
684
680
|
if (criteria) {
|
|
685
|
-
_dispatchEvent(_this, criteria, 'filter', target, el, el, startIndex);
|
|
681
|
+
_dispatchEvent(_this, criteria, 'filter', target, el, el, startIndex, undefined, startDraggableIndex);
|
|
686
682
|
return true;
|
|
687
683
|
}
|
|
688
684
|
});
|
|
@@ -698,7 +694,7 @@
|
|
|
698
694
|
}
|
|
699
695
|
|
|
700
696
|
// Prepare `dragstart`
|
|
701
|
-
this._prepareDragStart(evt, touch, target, startIndex);
|
|
697
|
+
this._prepareDragStart(evt, touch, target, startIndex, startDraggableIndex);
|
|
702
698
|
},
|
|
703
699
|
|
|
704
700
|
|
|
@@ -712,8 +708,9 @@
|
|
|
712
708
|
|
|
713
709
|
// IE does not seem to have native autoscroll,
|
|
714
710
|
// Edge's autoscroll seems too conditional,
|
|
711
|
+
// MACOS Safari does not have autoscroll,
|
|
715
712
|
// Firefox and Chrome are good
|
|
716
|
-
if (fallback || Edge || IE11OrLess) {
|
|
713
|
+
if (fallback || Edge || IE11OrLess || Safari) {
|
|
717
714
|
_autoScroll(evt, _this.options, elem, fallback);
|
|
718
715
|
|
|
719
716
|
// Listener for pointer element change
|
|
@@ -745,7 +742,7 @@
|
|
|
745
742
|
|
|
746
743
|
} else {
|
|
747
744
|
// if DnD is enabled (and browser has good autoscrolling), first autoscroll will already scroll, so get parent autoscroll of first autoscroll
|
|
748
|
-
if (!_this.options.bubbleScroll || _getParentAutoScrollElement(elem, true) ===
|
|
745
|
+
if (!_this.options.bubbleScroll || _getParentAutoScrollElement(elem, true) === _getWindowScrollingElement()) {
|
|
749
746
|
_clearAutoScrolls();
|
|
750
747
|
return;
|
|
751
748
|
}
|
|
@@ -753,7 +750,7 @@
|
|
|
753
750
|
}
|
|
754
751
|
},
|
|
755
752
|
|
|
756
|
-
_prepareDragStart: function (/** Event */evt, /** Touch */touch, /** HTMLElement */target, /** Number */startIndex) {
|
|
753
|
+
_prepareDragStart: function (/** Event */evt, /** Touch */touch, /** HTMLElement */target, /** Number */startIndex, /** Number */startDraggableIndex) {
|
|
757
754
|
var _this = this,
|
|
758
755
|
el = _this.el,
|
|
759
756
|
options = _this.options,
|
|
@@ -768,6 +765,7 @@
|
|
|
768
765
|
lastDownEl = target;
|
|
769
766
|
activeGroup = options.group;
|
|
770
767
|
oldIndex = startIndex;
|
|
768
|
+
oldDraggableIndex = startDraggableIndex;
|
|
771
769
|
|
|
772
770
|
tapEvt = {
|
|
773
771
|
target: dragEl,
|
|
@@ -786,16 +784,17 @@
|
|
|
786
784
|
dragStartFn = function () {
|
|
787
785
|
// Delayed drag has been triggered
|
|
788
786
|
// we can re-enable the events: touchmove/mousemove
|
|
789
|
-
_this.
|
|
787
|
+
_this._disableDelayedDragEvents();
|
|
790
788
|
|
|
791
|
-
|
|
792
|
-
|
|
789
|
+
if (!FireFox && _this.nativeDraggable) {
|
|
790
|
+
dragEl.draggable = true;
|
|
791
|
+
}
|
|
793
792
|
|
|
794
793
|
// Bind the events: dragstart/dragend
|
|
795
794
|
_this._triggerDragStart(evt, touch);
|
|
796
795
|
|
|
797
796
|
// Drag start event
|
|
798
|
-
_dispatchEvent(_this, rootEl, 'choose', dragEl, rootEl, rootEl, oldIndex);
|
|
797
|
+
_dispatchEvent(_this, rootEl, 'choose', dragEl, rootEl, rootEl, oldIndex, undefined, oldDraggableIndex);
|
|
799
798
|
|
|
800
799
|
// Chosen item
|
|
801
800
|
_toggleClass(dragEl, options.chosenClass, true);
|
|
@@ -806,16 +805,22 @@
|
|
|
806
805
|
_find(dragEl, criteria.trim(), _disableDraggable);
|
|
807
806
|
});
|
|
808
807
|
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
808
|
+
_on(ownerDocument, 'dragover', nearestEmptyInsertDetectEvent);
|
|
809
|
+
_on(ownerDocument, 'mousemove', nearestEmptyInsertDetectEvent);
|
|
810
|
+
_on(ownerDocument, 'touchmove', nearestEmptyInsertDetectEvent);
|
|
811
|
+
|
|
812
|
+
_on(ownerDocument, 'mouseup', _this._onDrop);
|
|
813
|
+
_on(ownerDocument, 'touchend', _this._onDrop);
|
|
814
|
+
_on(ownerDocument, 'touchcancel', _this._onDrop);
|
|
815
|
+
|
|
816
|
+
// Make dragEl draggable (must be before delay for FireFox)
|
|
817
|
+
if (FireFox && this.nativeDraggable) {
|
|
818
|
+
this.options.touchStartThreshold = 4;
|
|
819
|
+
dragEl.draggable = true;
|
|
816
820
|
}
|
|
817
821
|
|
|
818
|
-
|
|
822
|
+
// Delay is impossible for native DnD in Edge or IE
|
|
823
|
+
if (options.delay && (options.delayOnTouchOnly ? touch : true) && (!this.nativeDraggable || !(Edge || IE11OrLess))) {
|
|
819
824
|
// If the user moves the pointer or let go the click or touch
|
|
820
825
|
// before the delay has been reached:
|
|
821
826
|
// disable the delayed drag
|
|
@@ -835,17 +840,22 @@
|
|
|
835
840
|
|
|
836
841
|
_delayedDragTouchMoveHandler: function (/** TouchEvent|PointerEvent **/e) {
|
|
837
842
|
var touch = e.touches ? e.touches[0] : e;
|
|
838
|
-
if (
|
|
839
|
-
>= this.options.touchStartThreshold
|
|
843
|
+
if (max(abs(touch.clientX - this._lastX), abs(touch.clientY - this._lastY))
|
|
844
|
+
>= Math.floor(this.options.touchStartThreshold / (this.nativeDraggable && window.devicePixelRatio || 1))
|
|
840
845
|
) {
|
|
841
846
|
this._disableDelayedDrag();
|
|
842
847
|
}
|
|
843
848
|
},
|
|
844
849
|
|
|
845
850
|
_disableDelayedDrag: function () {
|
|
846
|
-
|
|
847
|
-
|
|
851
|
+
dragEl && _disableDraggable(dragEl);
|
|
848
852
|
clearTimeout(this._dragStartTimer);
|
|
853
|
+
|
|
854
|
+
this._disableDelayedDragEvents();
|
|
855
|
+
},
|
|
856
|
+
|
|
857
|
+
_disableDelayedDragEvents: function () {
|
|
858
|
+
var ownerDocument = this.el.ownerDocument;
|
|
849
859
|
_off(ownerDocument, 'mouseup', this._disableDelayedDrag);
|
|
850
860
|
_off(ownerDocument, 'touchend', this._disableDelayedDrag);
|
|
851
861
|
_off(ownerDocument, 'touchcancel', this._disableDelayedDrag);
|
|
@@ -883,7 +893,7 @@
|
|
|
883
893
|
}
|
|
884
894
|
},
|
|
885
895
|
|
|
886
|
-
_dragStarted: function (fallback) {
|
|
896
|
+
_dragStarted: function (fallback, evt) {
|
|
887
897
|
awaitingDragStarted = false;
|
|
888
898
|
if (rootEl && dragEl) {
|
|
889
899
|
if (this.nativeDraggable) {
|
|
@@ -904,15 +914,15 @@
|
|
|
904
914
|
fallback && this._appendGhost();
|
|
905
915
|
|
|
906
916
|
// Drag start event
|
|
907
|
-
_dispatchEvent(this, rootEl, 'start', dragEl, rootEl, rootEl, oldIndex);
|
|
917
|
+
_dispatchEvent(this, rootEl, 'start', dragEl, rootEl, rootEl, oldIndex, undefined, oldDraggableIndex, undefined, evt);
|
|
908
918
|
} else {
|
|
909
919
|
this._nulling();
|
|
910
920
|
}
|
|
911
921
|
},
|
|
912
922
|
|
|
913
|
-
_emulateDragOver: function (
|
|
923
|
+
_emulateDragOver: function (forAutoScroll) {
|
|
914
924
|
if (touchEvt) {
|
|
915
|
-
if (this._lastX === touchEvt.clientX && this._lastY === touchEvt.clientY && !
|
|
925
|
+
if (this._lastX === touchEvt.clientX && this._lastY === touchEvt.clientY && !forAutoScroll) {
|
|
916
926
|
return;
|
|
917
927
|
}
|
|
918
928
|
this._lastX = touchEvt.clientX;
|
|
@@ -925,6 +935,7 @@
|
|
|
925
935
|
|
|
926
936
|
while (target && target.shadowRoot) {
|
|
927
937
|
target = target.shadowRoot.elementFromPoint(touchEvt.clientX, touchEvt.clientY);
|
|
938
|
+
if (target === parent) break;
|
|
928
939
|
parent = target;
|
|
929
940
|
}
|
|
930
941
|
|
|
@@ -957,9 +968,8 @@
|
|
|
957
968
|
},
|
|
958
969
|
|
|
959
970
|
|
|
960
|
-
_onTouchMove: function (/**TouchEvent*/evt) {
|
|
971
|
+
_onTouchMove: function (/**TouchEvent*/evt, forAutoScroll) {
|
|
961
972
|
if (tapEvt) {
|
|
962
|
-
if (!evt.cancelable) return;
|
|
963
973
|
var options = this.options,
|
|
964
974
|
fallbackTolerance = options.fallbackTolerance,
|
|
965
975
|
fallbackOffset = options.fallbackOffset,
|
|
@@ -967,11 +977,15 @@
|
|
|
967
977
|
matrix = ghostEl && _matrix(ghostEl),
|
|
968
978
|
scaleX = ghostEl && matrix && matrix.a,
|
|
969
979
|
scaleY = ghostEl && matrix && matrix.d,
|
|
970
|
-
|
|
971
|
-
|
|
980
|
+
relativeScrollOffset = PositionGhostAbsolutely && ghostRelativeParent && _getRelativeScrollOffset(ghostRelativeParent),
|
|
981
|
+
dx = ((touch.clientX - tapEvt.clientX)
|
|
982
|
+
+ fallbackOffset.x) / (scaleX || 1)
|
|
983
|
+
+ (relativeScrollOffset ? (relativeScrollOffset[0] - ghostRelativeParentInitialScroll[0]) : 0) / (scaleX || 1),
|
|
984
|
+
dy = ((touch.clientY - tapEvt.clientY)
|
|
985
|
+
+ fallbackOffset.y) / (scaleY || 1)
|
|
986
|
+
+ (relativeScrollOffset ? (relativeScrollOffset[1] - ghostRelativeParentInitialScroll[1]) : 0) / (scaleY || 1),
|
|
972
987
|
translate3d = evt.touches ? 'translate3d(' + dx + 'px,' + dy + 'px,0)' : 'translate(' + dx + 'px,' + dy + 'px)';
|
|
973
988
|
|
|
974
|
-
|
|
975
989
|
// only set the status to dragging, when we are actually dragging
|
|
976
990
|
if (!Sortable.active && !awaitingDragStarted) {
|
|
977
991
|
if (fallbackTolerance &&
|
|
@@ -982,13 +996,11 @@
|
|
|
982
996
|
this._onDragStart(evt, true);
|
|
983
997
|
}
|
|
984
998
|
|
|
985
|
-
this._handleAutoScroll(touch, true);
|
|
986
|
-
|
|
999
|
+
!forAutoScroll && this._handleAutoScroll(touch, true);
|
|
987
1000
|
|
|
988
1001
|
moved = true;
|
|
989
1002
|
touchEvt = touch;
|
|
990
1003
|
|
|
991
|
-
|
|
992
1004
|
_css(ghostEl, 'webkitTransform', translate3d);
|
|
993
1005
|
_css(ghostEl, 'mozTransform', translate3d);
|
|
994
1006
|
_css(ghostEl, 'msTransform', translate3d);
|
|
@@ -999,11 +1011,46 @@
|
|
|
999
1011
|
},
|
|
1000
1012
|
|
|
1001
1013
|
_appendGhost: function () {
|
|
1014
|
+
// Bug if using scale(): https://stackoverflow.com/questions/2637058
|
|
1015
|
+
// Not being adjusted for
|
|
1002
1016
|
if (!ghostEl) {
|
|
1003
|
-
var
|
|
1017
|
+
var container = this.options.fallbackOnBody ? document.body : rootEl,
|
|
1018
|
+
rect = _getRect(dragEl, true, container, !PositionGhostAbsolutely),
|
|
1004
1019
|
css = _css(dragEl),
|
|
1005
1020
|
options = this.options;
|
|
1006
1021
|
|
|
1022
|
+
// Position absolutely
|
|
1023
|
+
if (PositionGhostAbsolutely) {
|
|
1024
|
+
// Get relatively positioned parent
|
|
1025
|
+
ghostRelativeParent = container;
|
|
1026
|
+
|
|
1027
|
+
while (
|
|
1028
|
+
_css(ghostRelativeParent, 'position') === 'static' &&
|
|
1029
|
+
_css(ghostRelativeParent, 'transform') === 'none' &&
|
|
1030
|
+
ghostRelativeParent !== document
|
|
1031
|
+
) {
|
|
1032
|
+
ghostRelativeParent = ghostRelativeParent.parentNode;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
if (ghostRelativeParent !== document) {
|
|
1036
|
+
var ghostRelativeParentRect = _getRect(ghostRelativeParent, true);
|
|
1037
|
+
|
|
1038
|
+
rect.top -= ghostRelativeParentRect.top;
|
|
1039
|
+
rect.left -= ghostRelativeParentRect.left;
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
if (ghostRelativeParent !== document.body && ghostRelativeParent !== document.documentElement) {
|
|
1043
|
+
if (ghostRelativeParent === document) ghostRelativeParent = _getWindowScrollingElement();
|
|
1044
|
+
|
|
1045
|
+
rect.top += ghostRelativeParent.scrollTop;
|
|
1046
|
+
rect.left += ghostRelativeParent.scrollLeft;
|
|
1047
|
+
} else {
|
|
1048
|
+
ghostRelativeParent = _getWindowScrollingElement();
|
|
1049
|
+
}
|
|
1050
|
+
ghostRelativeParentInitialScroll = _getRelativeScrollOffset(ghostRelativeParent);
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
|
|
1007
1054
|
ghostEl = dragEl.cloneNode(true);
|
|
1008
1055
|
|
|
1009
1056
|
_toggleClass(ghostEl, options.ghostClass, false);
|
|
@@ -1017,11 +1064,11 @@
|
|
|
1017
1064
|
_css(ghostEl, 'width', rect.width);
|
|
1018
1065
|
_css(ghostEl, 'height', rect.height);
|
|
1019
1066
|
_css(ghostEl, 'opacity', '0.8');
|
|
1020
|
-
_css(ghostEl, 'position', 'fixed');
|
|
1067
|
+
_css(ghostEl, 'position', (PositionGhostAbsolutely ? 'absolute' : 'fixed'));
|
|
1021
1068
|
_css(ghostEl, 'zIndex', '100000');
|
|
1022
1069
|
_css(ghostEl, 'pointerEvents', 'none');
|
|
1023
1070
|
|
|
1024
|
-
|
|
1071
|
+
container.appendChild(ghostEl);
|
|
1025
1072
|
}
|
|
1026
1073
|
},
|
|
1027
1074
|
|
|
@@ -1061,7 +1108,6 @@
|
|
|
1061
1108
|
_off(document, 'mouseup', _this._onDrop);
|
|
1062
1109
|
_off(document, 'touchend', _this._onDrop);
|
|
1063
1110
|
_off(document, 'touchcancel', _this._onDrop);
|
|
1064
|
-
_off(document, 'pointercancel', _this._onDrop);
|
|
1065
1111
|
|
|
1066
1112
|
if (dataTransfer) {
|
|
1067
1113
|
dataTransfer.effectAllowed = 'move';
|
|
@@ -1076,10 +1122,14 @@
|
|
|
1076
1122
|
|
|
1077
1123
|
awaitingDragStarted = true;
|
|
1078
1124
|
|
|
1079
|
-
_this._dragStartId = _nextTick(_this._dragStarted.bind(_this, fallback));
|
|
1125
|
+
_this._dragStartId = _nextTick(_this._dragStarted.bind(_this, fallback, evt));
|
|
1080
1126
|
_on(document, 'selectstart', _this);
|
|
1127
|
+
if (Safari) {
|
|
1128
|
+
_css(document.body, 'user-select', 'none');
|
|
1129
|
+
}
|
|
1081
1130
|
},
|
|
1082
1131
|
|
|
1132
|
+
|
|
1083
1133
|
// Returns true - if no further action is needed (either inserted or another condition)
|
|
1084
1134
|
_onDragOver: function (/**Event*/evt) {
|
|
1085
1135
|
var el = this.el,
|
|
@@ -1096,23 +1146,30 @@
|
|
|
1096
1146
|
|
|
1097
1147
|
if (_silent) return;
|
|
1098
1148
|
|
|
1099
|
-
//
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1149
|
+
// Return invocation when dragEl is inserted (or completed)
|
|
1150
|
+
function completed(insertion) {
|
|
1151
|
+
if (insertion) {
|
|
1152
|
+
if (isOwner) {
|
|
1153
|
+
activeSortable._hideClone();
|
|
1154
|
+
} else {
|
|
1155
|
+
activeSortable._showClone(_this);
|
|
1156
|
+
}
|
|
1103
1157
|
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
_toggleClass(dragEl, options.ghostClass, true);
|
|
1110
|
-
}
|
|
1158
|
+
if (activeSortable) {
|
|
1159
|
+
// Set ghost class to new sortable's ghost class
|
|
1160
|
+
_toggleClass(dragEl, putSortable ? putSortable.options.ghostClass : activeSortable.options.ghostClass, false);
|
|
1161
|
+
_toggleClass(dragEl, options.ghostClass, true);
|
|
1162
|
+
}
|
|
1111
1163
|
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1164
|
+
if (putSortable !== _this && _this !== Sortable.active) {
|
|
1165
|
+
putSortable = _this;
|
|
1166
|
+
} else if (_this === Sortable.active) {
|
|
1167
|
+
putSortable = null;
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
// Animation
|
|
1171
|
+
dragRect && _this._animate(dragRect, dragEl);
|
|
1172
|
+
target && targetRect && _this._animate(targetRect, target);
|
|
1116
1173
|
}
|
|
1117
1174
|
|
|
1118
1175
|
|
|
@@ -1120,10 +1177,14 @@
|
|
|
1120
1177
|
if ((target === dragEl && !dragEl.animated) || (target === el && !target.animated)) {
|
|
1121
1178
|
lastTarget = null;
|
|
1122
1179
|
}
|
|
1180
|
+
|
|
1123
1181
|
// no bubbling and not fallback
|
|
1124
1182
|
if (!options.dragoverBubble && !evt.rootEl && target !== document) {
|
|
1125
1183
|
_this._handleAutoScroll(evt);
|
|
1126
1184
|
dragEl.parentNode[expando]._computeIsAligned(evt);
|
|
1185
|
+
|
|
1186
|
+
// Do not detect for empty insert if already inserted
|
|
1187
|
+
!insertion && nearestEmptyInsertDetectEvent(evt);
|
|
1127
1188
|
}
|
|
1128
1189
|
|
|
1129
1190
|
!options.dragoverBubble && evt.stopPropagation && evt.stopPropagation();
|
|
@@ -1133,7 +1194,7 @@
|
|
|
1133
1194
|
|
|
1134
1195
|
// Call when dragEl has been inserted
|
|
1135
1196
|
function changed() {
|
|
1136
|
-
_dispatchEvent(_this, rootEl, 'change', target, el, rootEl, oldIndex, _index(dragEl, options.draggable), evt);
|
|
1197
|
+
_dispatchEvent(_this, rootEl, 'change', target, el, rootEl, oldIndex, _index(dragEl), oldDraggableIndex, _index(dragEl, options.draggable), evt);
|
|
1137
1198
|
}
|
|
1138
1199
|
|
|
1139
1200
|
|
|
@@ -1147,8 +1208,8 @@
|
|
|
1147
1208
|
target = _closest(target, options.draggable, el, true);
|
|
1148
1209
|
|
|
1149
1210
|
// target is dragEl or target is animated
|
|
1150
|
-
if (
|
|
1151
|
-
return completed();
|
|
1211
|
+
if (dragEl.contains(evt.target) || target.animated) {
|
|
1212
|
+
return completed(false);
|
|
1152
1213
|
}
|
|
1153
1214
|
|
|
1154
1215
|
if (target !== dragEl) {
|
|
@@ -1181,15 +1242,15 @@
|
|
|
1181
1242
|
rootEl.appendChild(dragEl);
|
|
1182
1243
|
}
|
|
1183
1244
|
|
|
1184
|
-
return completed();
|
|
1245
|
+
return completed(true);
|
|
1185
1246
|
}
|
|
1186
1247
|
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
) {
|
|
1190
|
-
//assign target only if condition is true
|
|
1191
|
-
if (
|
|
1192
|
-
target =
|
|
1248
|
+
var elLastChild = _lastChild(el);
|
|
1249
|
+
|
|
1250
|
+
if (!elLastChild || _ghostIsLast(evt, axis, el) && !elLastChild.animated) {
|
|
1251
|
+
// assign target only if condition is true
|
|
1252
|
+
if (elLastChild && el === evt.target) {
|
|
1253
|
+
target = elLastChild;
|
|
1193
1254
|
}
|
|
1194
1255
|
|
|
1195
1256
|
if (target) {
|
|
@@ -1208,21 +1269,22 @@
|
|
|
1208
1269
|
realDragElRect = null;
|
|
1209
1270
|
|
|
1210
1271
|
changed();
|
|
1211
|
-
|
|
1212
|
-
target && this._animate(targetRect, target);
|
|
1213
|
-
return completed();
|
|
1272
|
+
return completed(true);
|
|
1214
1273
|
}
|
|
1215
1274
|
}
|
|
1216
|
-
else if (target && target !== dragEl &&
|
|
1275
|
+
else if (target && target !== dragEl && target.parentNode === el) {
|
|
1217
1276
|
var direction = 0,
|
|
1218
1277
|
targetBeforeFirstSwap,
|
|
1219
1278
|
aligned = target.sortableMouseAligned,
|
|
1220
1279
|
differentLevel = dragEl.parentNode !== el,
|
|
1221
|
-
|
|
1280
|
+
side1 = axis === 'vertical' ? 'top' : 'left',
|
|
1281
|
+
scrolledPastTop = _isScrolledPast(target, 'top') || _isScrolledPast(dragEl, 'top'),
|
|
1282
|
+
scrollBefore = scrolledPastTop ? scrolledPastTop.scrollTop : void 0;
|
|
1283
|
+
|
|
1222
1284
|
|
|
1223
1285
|
if (lastTarget !== target) {
|
|
1224
1286
|
lastMode = null;
|
|
1225
|
-
targetBeforeFirstSwap = _getRect(target)[
|
|
1287
|
+
targetBeforeFirstSwap = _getRect(target)[side1];
|
|
1226
1288
|
pastFirstInvertThresh = false;
|
|
1227
1289
|
}
|
|
1228
1290
|
|
|
@@ -1239,7 +1301,7 @@
|
|
|
1239
1301
|
) {
|
|
1240
1302
|
// New target that we will be inside
|
|
1241
1303
|
if (lastMode !== 'swap') {
|
|
1242
|
-
isCircumstantialInvert = options.invertSwap || differentLevel
|
|
1304
|
+
isCircumstantialInvert = options.invertSwap || differentLevel;
|
|
1243
1305
|
}
|
|
1244
1306
|
|
|
1245
1307
|
direction = _getSwapDirection(evt, target, axis,
|
|
@@ -1249,10 +1311,10 @@
|
|
|
1249
1311
|
lastMode = 'swap';
|
|
1250
1312
|
} else {
|
|
1251
1313
|
// Insert at position
|
|
1252
|
-
direction = _getInsertDirection(target
|
|
1314
|
+
direction = _getInsertDirection(target);
|
|
1253
1315
|
lastMode = 'insert';
|
|
1254
1316
|
}
|
|
1255
|
-
if (direction === 0) return completed();
|
|
1317
|
+
if (direction === 0) return completed(false);
|
|
1256
1318
|
|
|
1257
1319
|
realDragElRect = null;
|
|
1258
1320
|
lastTarget = target;
|
|
@@ -1288,29 +1350,28 @@
|
|
|
1288
1350
|
target.parentNode.insertBefore(dragEl, after ? nextSibling : target);
|
|
1289
1351
|
}
|
|
1290
1352
|
|
|
1353
|
+
// Undo chrome's scroll adjustment
|
|
1354
|
+
if (scrolledPastTop) {
|
|
1355
|
+
_scrollBy(scrolledPastTop, 0, scrollBefore - scrolledPastTop.scrollTop);
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1291
1358
|
parentEl = dragEl.parentNode; // actualization
|
|
1292
1359
|
|
|
1293
1360
|
// must be done before animation
|
|
1294
1361
|
if (targetBeforeFirstSwap !== undefined && !isCircumstantialInvert) {
|
|
1295
|
-
targetMoveDistance = abs(targetBeforeFirstSwap - _getRect(target)[
|
|
1362
|
+
targetMoveDistance = abs(targetBeforeFirstSwap - _getRect(target)[side1]);
|
|
1296
1363
|
}
|
|
1297
1364
|
changed();
|
|
1298
|
-
!differentLevel && this._animate(targetRect, target);
|
|
1299
|
-
this._animate(dragRect, dragEl);
|
|
1300
1365
|
|
|
1301
|
-
return completed();
|
|
1366
|
+
return completed(true);
|
|
1302
1367
|
}
|
|
1303
1368
|
}
|
|
1304
1369
|
|
|
1305
1370
|
if (el.contains(dragEl)) {
|
|
1306
|
-
return completed();
|
|
1371
|
+
return completed(false);
|
|
1307
1372
|
}
|
|
1308
1373
|
}
|
|
1309
1374
|
|
|
1310
|
-
if (IE11OrLess && !evt.rootEl) {
|
|
1311
|
-
_artificalBubble(el, evt, '_onDragOver');
|
|
1312
|
-
}
|
|
1313
|
-
|
|
1314
1375
|
return false;
|
|
1315
1376
|
},
|
|
1316
1377
|
|
|
@@ -1342,7 +1403,7 @@
|
|
|
1342
1403
|
+ (prevRect.top - currentRect.top) / (scaleY ? scaleY : 1) + 'px,0)'
|
|
1343
1404
|
);
|
|
1344
1405
|
|
|
1345
|
-
|
|
1406
|
+
this._repaint(target);
|
|
1346
1407
|
_css(target, 'transition', 'transform ' + ms + 'ms' + (this.options.easing ? ' ' + this.options.easing : ''));
|
|
1347
1408
|
_css(target, 'transform', 'translate3d(0,0,0)');
|
|
1348
1409
|
}
|
|
@@ -1356,23 +1417,31 @@
|
|
|
1356
1417
|
}
|
|
1357
1418
|
},
|
|
1358
1419
|
|
|
1359
|
-
|
|
1360
|
-
|
|
1420
|
+
_repaint: function(target) {
|
|
1421
|
+
return target.offsetWidth;
|
|
1422
|
+
},
|
|
1361
1423
|
|
|
1424
|
+
_offMoveEvents: function() {
|
|
1362
1425
|
_off(document, 'touchmove', this._onTouchMove);
|
|
1363
1426
|
_off(document, 'pointermove', this._onTouchMove);
|
|
1427
|
+
_off(document, 'dragover', nearestEmptyInsertDetectEvent);
|
|
1428
|
+
_off(document, 'mousemove', nearestEmptyInsertDetectEvent);
|
|
1429
|
+
_off(document, 'touchmove', nearestEmptyInsertDetectEvent);
|
|
1430
|
+
},
|
|
1431
|
+
|
|
1432
|
+
_offUpEvents: function () {
|
|
1433
|
+
var ownerDocument = this.el.ownerDocument;
|
|
1434
|
+
|
|
1364
1435
|
_off(ownerDocument, 'mouseup', this._onDrop);
|
|
1365
1436
|
_off(ownerDocument, 'touchend', this._onDrop);
|
|
1366
1437
|
_off(ownerDocument, 'pointerup', this._onDrop);
|
|
1367
1438
|
_off(ownerDocument, 'touchcancel', this._onDrop);
|
|
1368
|
-
_off(ownerDocument, 'pointercancel', this._onDrop);
|
|
1369
1439
|
_off(document, 'selectstart', this);
|
|
1370
1440
|
},
|
|
1371
1441
|
|
|
1372
1442
|
_onDrop: function (/**Event*/evt) {
|
|
1373
1443
|
var el = this.el,
|
|
1374
1444
|
options = this.options;
|
|
1375
|
-
|
|
1376
1445
|
awaitingDragStarted = false;
|
|
1377
1446
|
scrolling = false;
|
|
1378
1447
|
isCircumstantialInvert = false;
|
|
@@ -1400,6 +1469,11 @@
|
|
|
1400
1469
|
_off(document, 'dragover', _checkAlignment);
|
|
1401
1470
|
}
|
|
1402
1471
|
|
|
1472
|
+
if (Safari) {
|
|
1473
|
+
_css(document.body, 'user-select', '');
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
this._offMoveEvents();
|
|
1403
1477
|
this._offUpEvents();
|
|
1404
1478
|
|
|
1405
1479
|
if (evt) {
|
|
@@ -1428,21 +1502,22 @@
|
|
|
1428
1502
|
_toggleClass(dragEl, this.options.chosenClass, false);
|
|
1429
1503
|
|
|
1430
1504
|
// Drag stop event
|
|
1431
|
-
_dispatchEvent(this, rootEl, 'unchoose', dragEl, parentEl, rootEl, oldIndex, null, evt);
|
|
1505
|
+
_dispatchEvent(this, rootEl, 'unchoose', dragEl, parentEl, rootEl, oldIndex, null, oldDraggableIndex, null, evt);
|
|
1432
1506
|
|
|
1433
1507
|
if (rootEl !== parentEl) {
|
|
1434
|
-
newIndex = _index(dragEl
|
|
1508
|
+
newIndex = _index(dragEl);
|
|
1509
|
+
newDraggableIndex = _index(dragEl, options.draggable);
|
|
1435
1510
|
|
|
1436
1511
|
if (newIndex >= 0) {
|
|
1437
1512
|
// Add event
|
|
1438
|
-
_dispatchEvent(null, parentEl, 'add', dragEl, parentEl, rootEl, oldIndex, newIndex, evt);
|
|
1513
|
+
_dispatchEvent(null, parentEl, 'add', dragEl, parentEl, rootEl, oldIndex, newIndex, oldDraggableIndex, newDraggableIndex, evt);
|
|
1439
1514
|
|
|
1440
1515
|
// Remove event
|
|
1441
|
-
_dispatchEvent(this, rootEl, 'remove', dragEl, parentEl, rootEl, oldIndex, newIndex, evt);
|
|
1516
|
+
_dispatchEvent(this, rootEl, 'remove', dragEl, parentEl, rootEl, oldIndex, newIndex, oldDraggableIndex, newDraggableIndex, evt);
|
|
1442
1517
|
|
|
1443
1518
|
// drag from one list and drop into another
|
|
1444
|
-
_dispatchEvent(null, parentEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex, evt);
|
|
1445
|
-
_dispatchEvent(this, rootEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex, evt);
|
|
1519
|
+
_dispatchEvent(null, parentEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex, oldDraggableIndex, newDraggableIndex, evt);
|
|
1520
|
+
_dispatchEvent(this, rootEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex, oldDraggableIndex, newDraggableIndex, evt);
|
|
1446
1521
|
}
|
|
1447
1522
|
|
|
1448
1523
|
putSortable && putSortable.save();
|
|
@@ -1450,12 +1525,13 @@
|
|
|
1450
1525
|
else {
|
|
1451
1526
|
if (dragEl.nextSibling !== nextEl) {
|
|
1452
1527
|
// Get the index of the dragged element within its parent
|
|
1453
|
-
newIndex = _index(dragEl
|
|
1528
|
+
newIndex = _index(dragEl);
|
|
1529
|
+
newDraggableIndex = _index(dragEl, options.draggable);
|
|
1454
1530
|
|
|
1455
1531
|
if (newIndex >= 0) {
|
|
1456
1532
|
// drag & drop within the same list
|
|
1457
|
-
_dispatchEvent(this, rootEl, 'update', dragEl, parentEl, rootEl, oldIndex, newIndex, evt);
|
|
1458
|
-
_dispatchEvent(this, rootEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex, evt);
|
|
1533
|
+
_dispatchEvent(this, rootEl, 'update', dragEl, parentEl, rootEl, oldIndex, newIndex, oldDraggableIndex, newDraggableIndex, evt);
|
|
1534
|
+
_dispatchEvent(this, rootEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex, oldDraggableIndex, newDraggableIndex, evt);
|
|
1459
1535
|
}
|
|
1460
1536
|
}
|
|
1461
1537
|
}
|
|
@@ -1464,9 +1540,9 @@
|
|
|
1464
1540
|
/* jshint eqnull:true */
|
|
1465
1541
|
if (newIndex == null || newIndex === -1) {
|
|
1466
1542
|
newIndex = oldIndex;
|
|
1543
|
+
newDraggableIndex = oldDraggableIndex;
|
|
1467
1544
|
}
|
|
1468
|
-
|
|
1469
|
-
_dispatchEvent(this, rootEl, 'end', dragEl, parentEl, rootEl, oldIndex, newIndex, evt);
|
|
1545
|
+
_dispatchEvent(this, rootEl, 'end', dragEl, parentEl, rootEl, oldIndex, newIndex, oldDraggableIndex, newDraggableIndex, evt);
|
|
1470
1546
|
|
|
1471
1547
|
// Save sorting
|
|
1472
1548
|
this.save();
|
|
@@ -1504,7 +1580,6 @@
|
|
|
1504
1580
|
lastTarget =
|
|
1505
1581
|
lastDirection =
|
|
1506
1582
|
|
|
1507
|
-
forRepaintDummy =
|
|
1508
1583
|
realDragElRect =
|
|
1509
1584
|
|
|
1510
1585
|
putSortable =
|
|
@@ -1696,7 +1771,15 @@
|
|
|
1696
1771
|
ctx = ctx || document;
|
|
1697
1772
|
|
|
1698
1773
|
do {
|
|
1699
|
-
if (
|
|
1774
|
+
if (
|
|
1775
|
+
selector != null &&
|
|
1776
|
+
(
|
|
1777
|
+
selector[0] === '>' ?
|
|
1778
|
+
el.parentNode === ctx && _matches(el, selector) :
|
|
1779
|
+
_matches(el, selector)
|
|
1780
|
+
) ||
|
|
1781
|
+
includeCTX && el === ctx
|
|
1782
|
+
) {
|
|
1700
1783
|
return el;
|
|
1701
1784
|
}
|
|
1702
1785
|
|
|
@@ -1725,12 +1808,12 @@
|
|
|
1725
1808
|
|
|
1726
1809
|
|
|
1727
1810
|
function _on(el, event, fn) {
|
|
1728
|
-
el.addEventListener(event, fn, captureMode);
|
|
1811
|
+
el.addEventListener(event, fn, IE11OrLess ? false : captureMode);
|
|
1729
1812
|
}
|
|
1730
1813
|
|
|
1731
1814
|
|
|
1732
1815
|
function _off(el, event, fn) {
|
|
1733
|
-
el.removeEventListener(event, fn, captureMode);
|
|
1816
|
+
el.removeEventListener(event, fn, IE11OrLess ? false : captureMode);
|
|
1734
1817
|
}
|
|
1735
1818
|
|
|
1736
1819
|
|
|
@@ -1810,7 +1893,13 @@
|
|
|
1810
1893
|
|
|
1811
1894
|
|
|
1812
1895
|
|
|
1813
|
-
function _dispatchEvent(
|
|
1896
|
+
function _dispatchEvent(
|
|
1897
|
+
sortable, rootEl, name,
|
|
1898
|
+
targetEl, toEl, fromEl,
|
|
1899
|
+
startIndex, newIndex,
|
|
1900
|
+
startDraggableIndex, newDraggableIndex,
|
|
1901
|
+
originalEvt
|
|
1902
|
+
) {
|
|
1814
1903
|
sortable = (sortable || rootEl[expando]);
|
|
1815
1904
|
var evt,
|
|
1816
1905
|
options = sortable.options,
|
|
@@ -1834,11 +1923,15 @@
|
|
|
1834
1923
|
evt.oldIndex = startIndex;
|
|
1835
1924
|
evt.newIndex = newIndex;
|
|
1836
1925
|
|
|
1926
|
+
evt.oldDraggableIndex = startDraggableIndex;
|
|
1927
|
+
evt.newDraggableIndex = newDraggableIndex;
|
|
1928
|
+
|
|
1837
1929
|
evt.originalEvent = originalEvt;
|
|
1930
|
+
evt.pullMode = putSortable ? putSortable.lastPutMode : undefined;
|
|
1838
1931
|
|
|
1839
1932
|
if (rootEl) {
|
|
1840
1933
|
rootEl.dispatchEvent(evt);
|
|
1841
|
-
|
|
1934
|
+
}
|
|
1842
1935
|
|
|
1843
1936
|
if (options[onName]) {
|
|
1844
1937
|
options[onName].call(sortable, evt);
|
|
@@ -1921,15 +2014,15 @@
|
|
|
1921
2014
|
}
|
|
1922
2015
|
|
|
1923
2016
|
/**
|
|
1924
|
-
* Gets the last child in the el, ignoring ghostEl
|
|
2017
|
+
* Gets the last child in the el, ignoring ghostEl or invisible elements (clones)
|
|
1925
2018
|
* @param {HTMLElement} el Parent element
|
|
1926
2019
|
* @return {HTMLElement} The last child, ignoring ghostEl
|
|
1927
2020
|
*/
|
|
1928
2021
|
function _lastChild(el) {
|
|
1929
2022
|
var last = el.lastElementChild;
|
|
1930
2023
|
|
|
1931
|
-
|
|
1932
|
-
last =
|
|
2024
|
+
while (last && (last === ghostEl || _css(last, 'display') === 'none')) {
|
|
2025
|
+
last = last.previousElementSibling;
|
|
1933
2026
|
}
|
|
1934
2027
|
|
|
1935
2028
|
return last || null;
|
|
@@ -1941,12 +2034,13 @@
|
|
|
1941
2034
|
mouseOnOppAxis = axis === 'vertical' ? evt.clientX : evt.clientY,
|
|
1942
2035
|
targetS2 = axis === 'vertical' ? elRect.bottom : elRect.right,
|
|
1943
2036
|
targetS1Opp = axis === 'vertical' ? elRect.left : elRect.top,
|
|
1944
|
-
targetS2Opp = axis === 'vertical' ? elRect.right : elRect.bottom
|
|
2037
|
+
targetS2Opp = axis === 'vertical' ? elRect.right : elRect.bottom,
|
|
2038
|
+
spacer = 10;
|
|
1945
2039
|
|
|
1946
2040
|
return (
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
2041
|
+
axis === 'vertical' ?
|
|
2042
|
+
(mouseOnOppAxis > targetS2Opp + spacer || mouseOnOppAxis <= targetS2Opp && mouseOnAxis > targetS2 && mouseOnOppAxis >= targetS1Opp) :
|
|
2043
|
+
(mouseOnAxis > targetS2 && mouseOnOppAxis > targetS1Opp || mouseOnAxis <= targetS2 && mouseOnOppAxis > targetS2Opp + spacer)
|
|
1950
2044
|
);
|
|
1951
2045
|
}
|
|
1952
2046
|
|
|
@@ -2004,7 +2098,7 @@
|
|
|
2004
2098
|
mouseOnAxis > targetS1 + (targetLength * (1 - swapThreshold) / 2) &&
|
|
2005
2099
|
mouseOnAxis < targetS2 - (targetLength * (1 - swapThreshold) / 2)
|
|
2006
2100
|
) {
|
|
2007
|
-
return (
|
|
2101
|
+
return _getInsertDirection(target);
|
|
2008
2102
|
}
|
|
2009
2103
|
}
|
|
2010
2104
|
}
|
|
@@ -2029,12 +2123,11 @@
|
|
|
2029
2123
|
* Gets the direction dragEl must be swapped relative to target in order to make it
|
|
2030
2124
|
* seem that dragEl has been "inserted" into that element's position
|
|
2031
2125
|
* @param {HTMLElement} target The target whose position dragEl is being inserted at
|
|
2032
|
-
* @param {Object} options options of the parent sortable
|
|
2033
2126
|
* @return {Number} Direction dragEl must be swapped
|
|
2034
2127
|
*/
|
|
2035
|
-
function _getInsertDirection(target
|
|
2036
|
-
var dragElIndex = _index(dragEl
|
|
2037
|
-
targetIndex = _index(target
|
|
2128
|
+
function _getInsertDirection(target) {
|
|
2129
|
+
var dragElIndex = _index(dragEl),
|
|
2130
|
+
targetIndex = _index(target);
|
|
2038
2131
|
|
|
2039
2132
|
if (dragElIndex < targetIndex) {
|
|
2040
2133
|
return 1;
|
|
@@ -2077,7 +2170,7 @@
|
|
|
2077
2170
|
}
|
|
2078
2171
|
|
|
2079
2172
|
while (el && (el = el.previousElementSibling)) {
|
|
2080
|
-
if ((el.nodeName.toUpperCase() !== 'TEMPLATE') && el !== cloneEl) {
|
|
2173
|
+
if ((el.nodeName.toUpperCase() !== 'TEMPLATE') && el !== cloneEl && (!selector || _matches(el, selector))) {
|
|
2081
2174
|
index++;
|
|
2082
2175
|
}
|
|
2083
2176
|
}
|
|
@@ -2086,6 +2179,10 @@
|
|
|
2086
2179
|
}
|
|
2087
2180
|
|
|
2088
2181
|
function _matches(/**HTMLElement*/el, /**String*/selector) {
|
|
2182
|
+
if (!selector) return;
|
|
2183
|
+
|
|
2184
|
+
selector[0] === '>' && (selector = selector.substring(1));
|
|
2185
|
+
|
|
2089
2186
|
if (el) {
|
|
2090
2187
|
try {
|
|
2091
2188
|
if (el.matches) {
|
|
@@ -2178,10 +2275,9 @@
|
|
|
2178
2275
|
* @param {HTMLElement} el The element whose boundingClientRect is wanted
|
|
2179
2276
|
* @param {[HTMLElement]} container the parent the element will be placed in
|
|
2180
2277
|
* @param {[Boolean]} adjustForTransform Whether the rect should compensate for parent's transform
|
|
2181
|
-
* (used for fixed positioning on el)
|
|
2182
2278
|
* @return {Object} The boundingClientRect of el
|
|
2183
2279
|
*/
|
|
2184
|
-
function _getRect(el, container,
|
|
2280
|
+
function _getRect(el, adjustForTransform, container, adjustForFixed) {
|
|
2185
2281
|
if (!el.getBoundingClientRect && el !== win) return;
|
|
2186
2282
|
|
|
2187
2283
|
var elRect,
|
|
@@ -2192,7 +2288,7 @@
|
|
|
2192
2288
|
height,
|
|
2193
2289
|
width;
|
|
2194
2290
|
|
|
2195
|
-
if (el !== win) {
|
|
2291
|
+
if (el !== win && el !== _getWindowScrollingElement()) {
|
|
2196
2292
|
elRect = el.getBoundingClientRect();
|
|
2197
2293
|
top = elRect.top;
|
|
2198
2294
|
left = elRect.left;
|
|
@@ -2209,7 +2305,7 @@
|
|
|
2209
2305
|
width = window.innerWidth;
|
|
2210
2306
|
}
|
|
2211
2307
|
|
|
2212
|
-
if (
|
|
2308
|
+
if (adjustForFixed && el !== win) {
|
|
2213
2309
|
// Adjust for translate()
|
|
2214
2310
|
container = container || el.parentNode;
|
|
2215
2311
|
|
|
@@ -2231,9 +2327,11 @@
|
|
|
2231
2327
|
/* jshint boss:true */
|
|
2232
2328
|
} while (container = container.parentNode);
|
|
2233
2329
|
}
|
|
2330
|
+
}
|
|
2234
2331
|
|
|
2332
|
+
if (adjustForTransform && el !== win) {
|
|
2235
2333
|
// Adjust for scale()
|
|
2236
|
-
var matrix = _matrix(el),
|
|
2334
|
+
var matrix = _matrix(container || el),
|
|
2237
2335
|
scaleX = matrix && matrix.a,
|
|
2238
2336
|
scaleY = matrix && matrix.d;
|
|
2239
2337
|
|
|
@@ -2264,10 +2362,10 @@
|
|
|
2264
2362
|
* Checks if a side of an element is scrolled past a side of it's parents
|
|
2265
2363
|
* @param {HTMLElement} el The element who's side being scrolled out of view is in question
|
|
2266
2364
|
* @param {String} side Side of the element in question ('top', 'left', 'right', 'bottom')
|
|
2267
|
-
* @return {
|
|
2365
|
+
* @return {HTMLElement} The parent scroll element that the el's side is scrolled past, or null if there is no such element
|
|
2268
2366
|
*/
|
|
2269
2367
|
function _isScrolledPast(el, side) {
|
|
2270
|
-
var parent = _getParentAutoScrollElement(
|
|
2368
|
+
var parent = _getParentAutoScrollElement(el, true),
|
|
2271
2369
|
elSide = _getRect(el)[side];
|
|
2272
2370
|
|
|
2273
2371
|
/* jshint boss:true */
|
|
@@ -2281,9 +2379,9 @@
|
|
|
2281
2379
|
visible = elSide <= parentSide;
|
|
2282
2380
|
}
|
|
2283
2381
|
|
|
2284
|
-
if (!visible) return
|
|
2382
|
+
if (!visible) return parent;
|
|
2285
2383
|
|
|
2286
|
-
if (parent ===
|
|
2384
|
+
if (parent === _getWindowScrollingElement()) break;
|
|
2287
2385
|
|
|
2288
2386
|
parent = _getParentAutoScrollElement(parent, false);
|
|
2289
2387
|
}
|
|
@@ -2291,6 +2389,31 @@
|
|
|
2291
2389
|
return false;
|
|
2292
2390
|
}
|
|
2293
2391
|
|
|
2392
|
+
/**
|
|
2393
|
+
* Returns the scroll offset of the given element, added with all the scroll offsets of parent elements.
|
|
2394
|
+
* The value is returned in real pixels.
|
|
2395
|
+
* @param {HTMLElement} el
|
|
2396
|
+
* @return {Array} Offsets in the format of [left, top]
|
|
2397
|
+
*/
|
|
2398
|
+
function _getRelativeScrollOffset(el) {
|
|
2399
|
+
var offsetLeft = 0,
|
|
2400
|
+
offsetTop = 0,
|
|
2401
|
+
winScroller = _getWindowScrollingElement();
|
|
2402
|
+
|
|
2403
|
+
if (el) {
|
|
2404
|
+
do {
|
|
2405
|
+
var matrix = _matrix(el),
|
|
2406
|
+
scaleX = matrix.a,
|
|
2407
|
+
scaleY = matrix.d;
|
|
2408
|
+
|
|
2409
|
+
offsetLeft += el.scrollLeft * scaleX;
|
|
2410
|
+
offsetTop += el.scrollTop * scaleY;
|
|
2411
|
+
} while (el !== winScroller && (el = el.parentNode));
|
|
2412
|
+
}
|
|
2413
|
+
|
|
2414
|
+
return [offsetLeft, offsetTop];
|
|
2415
|
+
}
|
|
2416
|
+
|
|
2294
2417
|
// Fixed #973:
|
|
2295
2418
|
_on(document, 'touchmove', function(evt) {
|
|
2296
2419
|
if ((Sortable.active || awaitingDragStarted) && evt.cancelable) {
|
|
@@ -2332,6 +2455,6 @@
|
|
|
2332
2455
|
|
|
2333
2456
|
|
|
2334
2457
|
// Export
|
|
2335
|
-
Sortable.version = '1.
|
|
2458
|
+
Sortable.version = '1.9.0';
|
|
2336
2459
|
return Sortable;
|
|
2337
2460
|
});
|