|
|
@ -25,6 +25,7 @@ |
|
|
|
"use strict"; |
|
|
|
"use strict"; |
|
|
|
|
|
|
|
|
|
|
|
var dragEl, |
|
|
|
var dragEl, |
|
|
|
|
|
|
|
parentEl, |
|
|
|
ghostEl, |
|
|
|
ghostEl, |
|
|
|
cloneEl, |
|
|
|
cloneEl, |
|
|
|
rootEl, |
|
|
|
rootEl, |
|
|
@ -35,6 +36,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
lastEl, |
|
|
|
lastEl, |
|
|
|
lastCSS, |
|
|
|
lastCSS, |
|
|
|
|
|
|
|
lastParentCSS, |
|
|
|
|
|
|
|
|
|
|
|
oldIndex, |
|
|
|
oldIndex, |
|
|
|
newIndex, |
|
|
|
newIndex, |
|
|
@ -45,6 +47,8 @@ |
|
|
|
tapEvt, |
|
|
|
tapEvt, |
|
|
|
touchEvt, |
|
|
|
touchEvt, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
moved, |
|
|
|
|
|
|
|
|
|
|
|
/** @const */ |
|
|
|
/** @const */ |
|
|
|
RSPACE = /\s+/g, |
|
|
|
RSPACE = /\s+/g, |
|
|
|
|
|
|
|
|
|
|
@ -55,6 +59,11 @@ |
|
|
|
parseInt = win.parseInt, |
|
|
|
parseInt = win.parseInt, |
|
|
|
|
|
|
|
|
|
|
|
supportDraggable = !!('draggable' in document.createElement('div')), |
|
|
|
supportDraggable = !!('draggable' in document.createElement('div')), |
|
|
|
|
|
|
|
supportCssPointerEvents = (function (el) { |
|
|
|
|
|
|
|
el = document.createElement('x'); |
|
|
|
|
|
|
|
el.style.cssText = 'pointer-events:auto'; |
|
|
|
|
|
|
|
return el.style.pointerEvents === 'auto'; |
|
|
|
|
|
|
|
})(), |
|
|
|
|
|
|
|
|
|
|
|
_silent = false, |
|
|
|
_silent = false, |
|
|
|
|
|
|
|
|
|
|
@ -136,7 +145,23 @@ |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}, 30) |
|
|
|
}, 30), |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_prepareGroup = function (options) { |
|
|
|
|
|
|
|
var group = options.group; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!group || typeof group != 'object') { |
|
|
|
|
|
|
|
group = options.group = {name: group}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
['pull', 'put'].forEach(function (key) { |
|
|
|
|
|
|
|
if (!(key in group)) { |
|
|
|
|
|
|
|
group[key] = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
options.groups = ' ' + group.name + (group.put.join ? ' ' + group.put.join(' ') : '') + ' '; |
|
|
|
|
|
|
|
} |
|
|
|
; |
|
|
|
; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -167,6 +192,7 @@ |
|
|
|
scrollSpeed: 10, |
|
|
|
scrollSpeed: 10, |
|
|
|
draggable: /[uo]l/i.test(el.nodeName) ? 'li' : '>*', |
|
|
|
draggable: /[uo]l/i.test(el.nodeName) ? 'li' : '>*', |
|
|
|
ghostClass: 'sortable-ghost', |
|
|
|
ghostClass: 'sortable-ghost', |
|
|
|
|
|
|
|
chosenClass: 'sortable-chosen', |
|
|
|
ignore: 'a, img', |
|
|
|
ignore: 'a, img', |
|
|
|
filter: null, |
|
|
|
filter: null, |
|
|
|
animation: 0, |
|
|
|
animation: 0, |
|
|
@ -176,7 +202,10 @@ |
|
|
|
dropBubble: false, |
|
|
|
dropBubble: false, |
|
|
|
dragoverBubble: false, |
|
|
|
dragoverBubble: false, |
|
|
|
dataIdAttr: 'data-id', |
|
|
|
dataIdAttr: 'data-id', |
|
|
|
delay: 0 |
|
|
|
delay: 0, |
|
|
|
|
|
|
|
forceFallback: false, |
|
|
|
|
|
|
|
fallbackClass: 'sortable-fallback', |
|
|
|
|
|
|
|
fallbackOnBody: false |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -185,38 +214,26 @@ |
|
|
|
!(name in options) && (options[name] = defaults[name]); |
|
|
|
!(name in options) && (options[name] = defaults[name]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_prepareGroup(options); |
|
|
|
var group = options.group; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!group || typeof group != 'object') { |
|
|
|
|
|
|
|
group = options.group = { name: group }; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
['pull', 'put'].forEach(function (key) { |
|
|
|
|
|
|
|
if (!(key in group)) { |
|
|
|
|
|
|
|
group[key] = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
options.groups = ' ' + group.name + (group.put.join ? ' ' + group.put.join(' ') : '') + ' '; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Bind all private methods
|
|
|
|
// Bind all private methods
|
|
|
|
for (var fn in this) { |
|
|
|
for (var fn in this) { |
|
|
|
if (fn.charAt(0) === '_') { |
|
|
|
if (fn.charAt(0) === '_') { |
|
|
|
this[fn] = _bind(this, this[fn]); |
|
|
|
this[fn] = this[fn].bind(this); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Setup drag mode
|
|
|
|
|
|
|
|
this.nativeDraggable = options.forceFallback ? false : supportDraggable; |
|
|
|
|
|
|
|
|
|
|
|
// Bind events
|
|
|
|
// Bind events
|
|
|
|
_on(el, 'mousedown', this._onTapStart); |
|
|
|
_on(el, 'mousedown', this._onTapStart); |
|
|
|
_on(el, 'touchstart', this._onTapStart); |
|
|
|
_on(el, 'touchstart', this._onTapStart); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (this.nativeDraggable) { |
|
|
|
_on(el, 'dragover', this); |
|
|
|
_on(el, 'dragover', this); |
|
|
|
_on(el, 'dragenter', this); |
|
|
|
_on(el, 'dragenter', this); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
touchDragOverListeners.push(this._onDragOver); |
|
|
|
touchDragOverListeners.push(this._onDragOver); |
|
|
|
|
|
|
|
|
|
|
@ -298,6 +315,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
rootEl = el; |
|
|
|
rootEl = el; |
|
|
|
dragEl = target; |
|
|
|
dragEl = target; |
|
|
|
|
|
|
|
parentEl = dragEl.parentNode; |
|
|
|
nextEl = dragEl.nextSibling; |
|
|
|
nextEl = dragEl.nextSibling; |
|
|
|
activeGroup = options.group; |
|
|
|
activeGroup = options.group; |
|
|
|
|
|
|
|
|
|
|
@ -309,22 +327,29 @@ |
|
|
|
// Make the element draggable
|
|
|
|
// Make the element draggable
|
|
|
|
dragEl.draggable = true; |
|
|
|
dragEl.draggable = true; |
|
|
|
|
|
|
|
|
|
|
|
// Disable "draggable"
|
|
|
|
// Chosen item
|
|
|
|
options.ignore.split(',').forEach(function (criteria) { |
|
|
|
_toggleClass(dragEl, _this.options.chosenClass, true); |
|
|
|
_find(dragEl, criteria.trim(), _disableDraggable); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Bind the events: dragstart/dragend
|
|
|
|
// Bind the events: dragstart/dragend
|
|
|
|
_this._triggerDragStart(touch); |
|
|
|
_this._triggerDragStart(touch); |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Disable "draggable"
|
|
|
|
|
|
|
|
options.ignore.split(',').forEach(function (criteria) { |
|
|
|
|
|
|
|
_find(dragEl, criteria.trim(), _disableDraggable); |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
_on(ownerDocument, 'mouseup', _this._onDrop); |
|
|
|
_on(ownerDocument, 'mouseup', _this._onDrop); |
|
|
|
_on(ownerDocument, 'touchend', _this._onDrop); |
|
|
|
_on(ownerDocument, 'touchend', _this._onDrop); |
|
|
|
_on(ownerDocument, 'touchcancel', _this._onDrop); |
|
|
|
_on(ownerDocument, 'touchcancel', _this._onDrop); |
|
|
|
|
|
|
|
|
|
|
|
if (options.delay) { |
|
|
|
if (options.delay) { |
|
|
|
// If the user moves the pointer before the delay has been reached:
|
|
|
|
// If the user moves the pointer or let go the click or touch
|
|
|
|
|
|
|
|
// before the delay has been reached:
|
|
|
|
// disable the delayed drag
|
|
|
|
// disable the delayed drag
|
|
|
|
|
|
|
|
_on(ownerDocument, 'mouseup', _this._disableDelayedDrag); |
|
|
|
|
|
|
|
_on(ownerDocument, 'touchend', _this._disableDelayedDrag); |
|
|
|
|
|
|
|
_on(ownerDocument, 'touchcancel', _this._disableDelayedDrag); |
|
|
|
_on(ownerDocument, 'mousemove', _this._disableDelayedDrag); |
|
|
|
_on(ownerDocument, 'mousemove', _this._disableDelayedDrag); |
|
|
|
_on(ownerDocument, 'touchmove', _this._disableDelayedDrag); |
|
|
|
_on(ownerDocument, 'touchmove', _this._disableDelayedDrag); |
|
|
|
|
|
|
|
|
|
|
@ -339,7 +364,9 @@ |
|
|
|
var ownerDocument = this.el.ownerDocument; |
|
|
|
var ownerDocument = this.el.ownerDocument; |
|
|
|
|
|
|
|
|
|
|
|
clearTimeout(this._dragStartTimer); |
|
|
|
clearTimeout(this._dragStartTimer); |
|
|
|
|
|
|
|
_off(ownerDocument, 'mouseup', this._disableDelayedDrag); |
|
|
|
|
|
|
|
_off(ownerDocument, 'touchend', this._disableDelayedDrag); |
|
|
|
|
|
|
|
_off(ownerDocument, 'touchcancel', this._disableDelayedDrag); |
|
|
|
_off(ownerDocument, 'mousemove', this._disableDelayedDrag); |
|
|
|
_off(ownerDocument, 'mousemove', this._disableDelayedDrag); |
|
|
|
_off(ownerDocument, 'touchmove', this._disableDelayedDrag); |
|
|
|
_off(ownerDocument, 'touchmove', this._disableDelayedDrag); |
|
|
|
}, |
|
|
|
}, |
|
|
@ -355,7 +382,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
this._onDragStart(tapEvt, 'touch'); |
|
|
|
this._onDragStart(tapEvt, 'touch'); |
|
|
|
} |
|
|
|
} |
|
|
|
else if (!supportDraggable) { |
|
|
|
else if (!this.nativeDraggable) { |
|
|
|
this._onDragStart(tapEvt, true); |
|
|
|
this._onDragStart(tapEvt, true); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
@ -387,7 +414,16 @@ |
|
|
|
|
|
|
|
|
|
|
|
_emulateDragOver: function () { |
|
|
|
_emulateDragOver: function () { |
|
|
|
if (touchEvt) { |
|
|
|
if (touchEvt) { |
|
|
|
|
|
|
|
if (this._lastX === touchEvt.clientX && this._lastY === touchEvt.clientY) { |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this._lastX = touchEvt.clientX; |
|
|
|
|
|
|
|
this._lastY = touchEvt.clientY; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!supportCssPointerEvents) { |
|
|
|
_css(ghostEl, 'display', 'none'); |
|
|
|
_css(ghostEl, 'display', 'none'); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY), |
|
|
|
var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY), |
|
|
|
parent = target, |
|
|
|
parent = target, |
|
|
@ -415,18 +451,29 @@ |
|
|
|
while (parent = parent.parentNode); |
|
|
|
while (parent = parent.parentNode); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!supportCssPointerEvents) { |
|
|
|
_css(ghostEl, 'display', ''); |
|
|
|
_css(ghostEl, 'display', ''); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_onTouchMove: function (/**TouchEvent*/evt) { |
|
|
|
_onTouchMove: function (/**TouchEvent*/evt) { |
|
|
|
if (tapEvt) { |
|
|
|
if (tapEvt) { |
|
|
|
|
|
|
|
// only set the status to dragging, when we are actually dragging
|
|
|
|
|
|
|
|
if (!Sortable.active) { |
|
|
|
|
|
|
|
this._dragStarted(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// as well as creating the ghost element on the document body
|
|
|
|
|
|
|
|
this._appendGhost(); |
|
|
|
|
|
|
|
|
|
|
|
var touch = evt.touches ? evt.touches[0] : evt, |
|
|
|
var touch = evt.touches ? evt.touches[0] : evt, |
|
|
|
dx = touch.clientX - tapEvt.clientX, |
|
|
|
dx = touch.clientX - tapEvt.clientX, |
|
|
|
dy = touch.clientY - tapEvt.clientY, |
|
|
|
dy = touch.clientY - tapEvt.clientY, |
|
|
|
translate3d = evt.touches ? 'translate3d(' + dx + 'px,' + dy + 'px,0)' : 'translate(' + dx + 'px,' + dy + 'px)'; |
|
|
|
translate3d = evt.touches ? 'translate3d(' + dx + 'px,' + dy + 'px,0)' : 'translate(' + dx + 'px,' + dy + 'px)'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
moved = true; |
|
|
|
touchEvt = touch; |
|
|
|
touchEvt = touch; |
|
|
|
|
|
|
|
|
|
|
|
_css(ghostEl, 'webkitTransform', translate3d); |
|
|
|
_css(ghostEl, 'webkitTransform', translate3d); |
|
|
@ -438,26 +485,17 @@ |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_appendGhost: function () { |
|
|
|
_onDragStart: function (/**Event*/evt, /**boolean*/useFallback) { |
|
|
|
if (!ghostEl) { |
|
|
|
var dataTransfer = evt.dataTransfer, |
|
|
|
|
|
|
|
options = this.options; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this._offUpEvents(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (activeGroup.pull == 'clone') { |
|
|
|
|
|
|
|
cloneEl = dragEl.cloneNode(true); |
|
|
|
|
|
|
|
_css(cloneEl, 'display', 'none'); |
|
|
|
|
|
|
|
rootEl.insertBefore(cloneEl, dragEl); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (useFallback) { |
|
|
|
|
|
|
|
var rect = dragEl.getBoundingClientRect(), |
|
|
|
var rect = dragEl.getBoundingClientRect(), |
|
|
|
css = _css(dragEl), |
|
|
|
css = _css(dragEl), |
|
|
|
ghostRect; |
|
|
|
ghostRect; |
|
|
|
|
|
|
|
|
|
|
|
ghostEl = dragEl.cloneNode(true); |
|
|
|
ghostEl = dragEl.cloneNode(true); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_toggleClass(ghostEl, this.options.ghostClass, false); |
|
|
|
|
|
|
|
_toggleClass(ghostEl, this.options.fallbackClass, true); |
|
|
|
|
|
|
|
|
|
|
|
_css(ghostEl, 'top', rect.top - parseInt(css.marginTop, 10)); |
|
|
|
_css(ghostEl, 'top', rect.top - parseInt(css.marginTop, 10)); |
|
|
|
_css(ghostEl, 'left', rect.left - parseInt(css.marginLeft, 10)); |
|
|
|
_css(ghostEl, 'left', rect.left - parseInt(css.marginLeft, 10)); |
|
|
|
_css(ghostEl, 'width', rect.width); |
|
|
|
_css(ghostEl, 'width', rect.width); |
|
|
@ -465,13 +503,30 @@ |
|
|
|
_css(ghostEl, 'opacity', '0.8'); |
|
|
|
_css(ghostEl, 'opacity', '0.8'); |
|
|
|
_css(ghostEl, 'position', 'fixed'); |
|
|
|
_css(ghostEl, 'position', 'fixed'); |
|
|
|
_css(ghostEl, 'zIndex', '100000'); |
|
|
|
_css(ghostEl, 'zIndex', '100000'); |
|
|
|
|
|
|
|
_css(ghostEl, 'pointerEvents', 'none'); |
|
|
|
|
|
|
|
|
|
|
|
rootEl.appendChild(ghostEl); |
|
|
|
this.options.fallbackOnBody && document.body.appendChild(ghostEl) || rootEl.appendChild(ghostEl); |
|
|
|
|
|
|
|
|
|
|
|
// Fixing dimensions.
|
|
|
|
// Fixing dimensions.
|
|
|
|
ghostRect = ghostEl.getBoundingClientRect(); |
|
|
|
ghostRect = ghostEl.getBoundingClientRect(); |
|
|
|
_css(ghostEl, 'width', rect.width * 2 - ghostRect.width); |
|
|
|
_css(ghostEl, 'width', rect.width * 2 - ghostRect.width); |
|
|
|
_css(ghostEl, 'height', rect.height * 2 - ghostRect.height); |
|
|
|
_css(ghostEl, 'height', rect.height * 2 - ghostRect.height); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_onDragStart: function (/**Event*/evt, /**boolean*/useFallback) { |
|
|
|
|
|
|
|
var dataTransfer = evt.dataTransfer, |
|
|
|
|
|
|
|
options = this.options; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this._offUpEvents(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (activeGroup.pull == 'clone') { |
|
|
|
|
|
|
|
cloneEl = dragEl.cloneNode(true); |
|
|
|
|
|
|
|
_css(cloneEl, 'display', 'none'); |
|
|
|
|
|
|
|
rootEl.insertBefore(cloneEl, dragEl); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (useFallback) { |
|
|
|
|
|
|
|
|
|
|
|
if (useFallback === 'touch') { |
|
|
|
if (useFallback === 'touch') { |
|
|
|
// Bind touch events
|
|
|
|
// Bind touch events
|
|
|
@ -484,7 +539,7 @@ |
|
|
|
_on(document, 'mouseup', this._onDrop); |
|
|
|
_on(document, 'mouseup', this._onDrop); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this._loopId = setInterval(this._emulateDragOver, 150); |
|
|
|
this._loopId = setInterval(this._emulateDragOver, 50); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
if (dataTransfer) { |
|
|
|
if (dataTransfer) { |
|
|
@ -493,9 +548,8 @@ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
_on(document, 'drop', this); |
|
|
|
_on(document, 'drop', this); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setTimeout(this._dragStarted, 0); |
|
|
|
setTimeout(this._dragStarted, 0); |
|
|
|
|
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
_onDragOver: function (/**Event*/evt) { |
|
|
|
_onDragOver: function (/**Event*/evt) { |
|
|
@ -514,6 +568,8 @@ |
|
|
|
!options.dragoverBubble && evt.stopPropagation(); |
|
|
|
!options.dragoverBubble && evt.stopPropagation(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
moved = true; |
|
|
|
|
|
|
|
|
|
|
|
if (activeGroup && !options.disabled && |
|
|
|
if (activeGroup && !options.disabled && |
|
|
|
(isOwner |
|
|
|
(isOwner |
|
|
|
? canSort || (revert = !rootEl.contains(dragEl)) // Reverting item into the original list
|
|
|
|
? canSort || (revert = !rootEl.contains(dragEl)) // Reverting item into the original list
|
|
|
@ -534,7 +590,6 @@ |
|
|
|
target = _closest(evt.target, options.draggable, el); |
|
|
|
target = _closest(evt.target, options.draggable, el); |
|
|
|
dragRect = dragEl.getBoundingClientRect(); |
|
|
|
dragRect = dragEl.getBoundingClientRect(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (revert) { |
|
|
|
if (revert) { |
|
|
|
_cloneHide(true); |
|
|
|
_cloneHide(true); |
|
|
|
|
|
|
|
|
|
|
@ -550,19 +605,25 @@ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((el.children.length === 0) || (el.children[0] === ghostEl) || |
|
|
|
if ((el.children.length === 0) || (el.children[0] === ghostEl) || |
|
|
|
(el === evt.target) && (target = _ghostInBottom(el, evt)) |
|
|
|
(el === evt.target) && (target = _ghostIsLast(el, evt)) |
|
|
|
) { |
|
|
|
) { |
|
|
|
|
|
|
|
|
|
|
|
if (target) { |
|
|
|
if (target) { |
|
|
|
if (target.animated) { |
|
|
|
if (target.animated) { |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
targetRect = target.getBoundingClientRect(); |
|
|
|
targetRect = target.getBoundingClientRect(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
_cloneHide(isOwner); |
|
|
|
_cloneHide(isOwner); |
|
|
|
|
|
|
|
|
|
|
|
if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect) !== false) { |
|
|
|
if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect) !== false) { |
|
|
|
|
|
|
|
if (!dragEl.contains(el)) { |
|
|
|
el.appendChild(dragEl); |
|
|
|
el.appendChild(dragEl); |
|
|
|
|
|
|
|
parentEl = el; // actualization
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this._animate(dragRect, dragEl); |
|
|
|
this._animate(dragRect, dragEl); |
|
|
|
target && this._animate(targetRect, target); |
|
|
|
target && this._animate(targetRect, target); |
|
|
|
} |
|
|
|
} |
|
|
@ -571,13 +632,15 @@ |
|
|
|
if (lastEl !== target) { |
|
|
|
if (lastEl !== target) { |
|
|
|
lastEl = target; |
|
|
|
lastEl = target; |
|
|
|
lastCSS = _css(target); |
|
|
|
lastCSS = _css(target); |
|
|
|
|
|
|
|
lastParentCSS = _css(target.parentNode); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var targetRect = target.getBoundingClientRect(), |
|
|
|
var targetRect = target.getBoundingClientRect(), |
|
|
|
width = targetRect.right - targetRect.left, |
|
|
|
width = targetRect.right - targetRect.left, |
|
|
|
height = targetRect.bottom - targetRect.top, |
|
|
|
height = targetRect.bottom - targetRect.top, |
|
|
|
floating = /left|right|inline/.test(lastCSS.cssFloat + lastCSS.display), |
|
|
|
floating = /left|right|inline/.test(lastCSS.cssFloat + lastCSS.display) |
|
|
|
|
|
|
|
|| (lastParentCSS.display == 'flex' && lastParentCSS['flex-direction'].indexOf('row') === 0), |
|
|
|
isWide = (target.offsetWidth > dragEl.offsetWidth), |
|
|
|
isWide = (target.offsetWidth > dragEl.offsetWidth), |
|
|
|
isLong = (target.offsetHeight > dragEl.offsetHeight), |
|
|
|
isLong = (target.offsetHeight > dragEl.offsetHeight), |
|
|
|
halfway = (floating ? (evt.clientX - targetRect.left) / width : (evt.clientY - targetRect.top) / height) > 0.5, |
|
|
|
halfway = (floating ? (evt.clientX - targetRect.left) / width : (evt.clientY - targetRect.top) / height) > 0.5, |
|
|
@ -596,16 +659,27 @@ |
|
|
|
after = (moveVector === 1); |
|
|
|
after = (moveVector === 1); |
|
|
|
} |
|
|
|
} |
|
|
|
else if (floating) { |
|
|
|
else if (floating) { |
|
|
|
|
|
|
|
var elTop = dragEl.offsetTop, |
|
|
|
|
|
|
|
tgTop = target.offsetTop; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (elTop === tgTop) { |
|
|
|
after = (target.previousElementSibling === dragEl) && !isWide || halfway && isWide; |
|
|
|
after = (target.previousElementSibling === dragEl) && !isWide || halfway && isWide; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
after = tgTop > elTop; |
|
|
|
|
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
after = (nextSibling !== dragEl) && !isLong || halfway && isLong; |
|
|
|
after = (nextSibling !== dragEl) && !isLong || halfway && isLong; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!dragEl.contains(el)) { |
|
|
|
if (after && !nextSibling) { |
|
|
|
if (after && !nextSibling) { |
|
|
|
el.appendChild(dragEl); |
|
|
|
el.appendChild(dragEl); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
target.parentNode.insertBefore(dragEl, after ? nextSibling : target); |
|
|
|
target.parentNode.insertBefore(dragEl, after ? nextSibling : target); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
parentEl = dragEl.parentNode; // actualization
|
|
|
|
|
|
|
|
|
|
|
|
this._animate(dragRect, dragEl); |
|
|
|
this._animate(dragRect, dragEl); |
|
|
|
this._animate(targetRect, target); |
|
|
|
this._animate(targetRect, target); |
|
|
@ -658,14 +732,17 @@ |
|
|
|
clearTimeout(this._dragStartTimer); |
|
|
|
clearTimeout(this._dragStartTimer); |
|
|
|
|
|
|
|
|
|
|
|
// Unbind events
|
|
|
|
// Unbind events
|
|
|
|
_off(document, 'drop', this); |
|
|
|
|
|
|
|
_off(document, 'mousemove', this._onTouchMove); |
|
|
|
_off(document, 'mousemove', this._onTouchMove); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (this.nativeDraggable) { |
|
|
|
|
|
|
|
_off(document, 'drop', this); |
|
|
|
_off(el, 'dragstart', this._onDragStart); |
|
|
|
_off(el, 'dragstart', this._onDragStart); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this._offUpEvents(); |
|
|
|
this._offUpEvents(); |
|
|
|
|
|
|
|
|
|
|
|
if (evt) { |
|
|
|
if (evt) { |
|
|
|
if (Sortable.active) { |
|
|
|
if (moved) { |
|
|
|
evt.preventDefault(); |
|
|
|
evt.preventDefault(); |
|
|
|
!options.dropBubble && evt.stopPropagation(); |
|
|
|
!options.dropBubble && evt.stopPropagation(); |
|
|
|
} |
|
|
|
} |
|
|
@ -673,24 +750,31 @@ |
|
|
|
ghostEl && ghostEl.parentNode.removeChild(ghostEl); |
|
|
|
ghostEl && ghostEl.parentNode.removeChild(ghostEl); |
|
|
|
|
|
|
|
|
|
|
|
if (dragEl) { |
|
|
|
if (dragEl) { |
|
|
|
|
|
|
|
if (this.nativeDraggable) { |
|
|
|
_off(dragEl, 'dragend', this); |
|
|
|
_off(dragEl, 'dragend', this); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
_disableDraggable(dragEl); |
|
|
|
_disableDraggable(dragEl); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Remove class's
|
|
|
|
_toggleClass(dragEl, this.options.ghostClass, false); |
|
|
|
_toggleClass(dragEl, this.options.ghostClass, false); |
|
|
|
|
|
|
|
_toggleClass(dragEl, this.options.chosenClass, false); |
|
|
|
|
|
|
|
|
|
|
|
if (rootEl !== dragEl.parentNode) { |
|
|
|
if (rootEl !== parentEl) { |
|
|
|
newIndex = _index(dragEl); |
|
|
|
newIndex = _index(dragEl); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (newIndex != -1) { |
|
|
|
// drag from one list and drop into another
|
|
|
|
// drag from one list and drop into another
|
|
|
|
_dispatchEvent(null, dragEl.parentNode, 'sort', dragEl, rootEl, oldIndex, newIndex); |
|
|
|
_dispatchEvent(null, parentEl, 'sort', dragEl, rootEl, oldIndex, newIndex); |
|
|
|
_dispatchEvent(this, rootEl, 'sort', dragEl, rootEl, oldIndex, newIndex); |
|
|
|
_dispatchEvent(this, rootEl, 'sort', dragEl, rootEl, oldIndex, newIndex); |
|
|
|
|
|
|
|
|
|
|
|
// Add event
|
|
|
|
// Add event
|
|
|
|
_dispatchEvent(null, dragEl.parentNode, 'add', dragEl, rootEl, oldIndex, newIndex); |
|
|
|
_dispatchEvent(null, parentEl, 'add', dragEl, rootEl, oldIndex, newIndex); |
|
|
|
|
|
|
|
|
|
|
|
// Remove event
|
|
|
|
// Remove event
|
|
|
|
_dispatchEvent(this, rootEl, 'remove', dragEl, rootEl, oldIndex, newIndex); |
|
|
|
_dispatchEvent(this, rootEl, 'remove', dragEl, rootEl, oldIndex, newIndex); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
// Remove clone
|
|
|
|
// Remove clone
|
|
|
|
cloneEl && cloneEl.parentNode.removeChild(cloneEl); |
|
|
|
cloneEl && cloneEl.parentNode.removeChild(cloneEl); |
|
|
@ -698,12 +782,13 @@ |
|
|
|
if (dragEl.nextSibling !== nextEl) { |
|
|
|
if (dragEl.nextSibling !== nextEl) { |
|
|
|
// Get the index of the dragged element within its parent
|
|
|
|
// Get the index of the dragged element within its parent
|
|
|
|
newIndex = _index(dragEl); |
|
|
|
newIndex = _index(dragEl); |
|
|
|
|
|
|
|
if (newIndex != -1) { |
|
|
|
// drag & drop within the same list
|
|
|
|
// drag & drop within the same list
|
|
|
|
_dispatchEvent(this, rootEl, 'update', dragEl, rootEl, oldIndex, newIndex); |
|
|
|
_dispatchEvent(this, rootEl, 'update', dragEl, rootEl, oldIndex, newIndex); |
|
|
|
_dispatchEvent(this, rootEl, 'sort', dragEl, rootEl, oldIndex, newIndex); |
|
|
|
_dispatchEvent(this, rootEl, 'sort', dragEl, rootEl, oldIndex, newIndex); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (Sortable.active) { |
|
|
|
if (Sortable.active) { |
|
|
|
// Drag end event
|
|
|
|
// Drag end event
|
|
|
@ -717,6 +802,7 @@ |
|
|
|
// Nulling
|
|
|
|
// Nulling
|
|
|
|
rootEl = |
|
|
|
rootEl = |
|
|
|
dragEl = |
|
|
|
dragEl = |
|
|
|
|
|
|
|
parentEl = |
|
|
|
ghostEl = |
|
|
|
ghostEl = |
|
|
|
nextEl = |
|
|
|
nextEl = |
|
|
|
cloneEl = |
|
|
|
cloneEl = |
|
|
@ -727,6 +813,9 @@ |
|
|
|
tapEvt = |
|
|
|
tapEvt = |
|
|
|
touchEvt = |
|
|
|
touchEvt = |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
moved = |
|
|
|
|
|
|
|
newIndex = |
|
|
|
|
|
|
|
|
|
|
|
lastEl = |
|
|
|
lastEl = |
|
|
|
lastCSS = |
|
|
|
lastCSS = |
|
|
|
|
|
|
|
|
|
|
@ -831,6 +920,10 @@ |
|
|
|
return options[name]; |
|
|
|
return options[name]; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
options[name] = value; |
|
|
|
options[name] = value; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (name === 'group') { |
|
|
|
|
|
|
|
_prepareGroup(options); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
|
|
|
@ -846,8 +939,10 @@ |
|
|
|
_off(el, 'mousedown', this._onTapStart); |
|
|
|
_off(el, 'mousedown', this._onTapStart); |
|
|
|
_off(el, 'touchstart', this._onTapStart); |
|
|
|
_off(el, 'touchstart', this._onTapStart); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (this.nativeDraggable) { |
|
|
|
_off(el, 'dragover', this); |
|
|
|
_off(el, 'dragover', this); |
|
|
|
_off(el, 'dragenter', this); |
|
|
|
_off(el, 'dragenter', this); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Remove draggable attributes
|
|
|
|
// Remove draggable attributes
|
|
|
|
Array.prototype.forEach.call(el.querySelectorAll('[draggable]'), function (el) { |
|
|
|
Array.prototype.forEach.call(el.querySelectorAll('[draggable]'), function (el) { |
|
|
@ -872,14 +967,6 @@ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function _bind(ctx, fn) { |
|
|
|
|
|
|
|
var args = slice.call(arguments, 2); |
|
|
|
|
|
|
|
return fn.bind ? fn.bind.apply(fn, [ctx].concat(args)) : function () { |
|
|
|
|
|
|
|
return fn.apply(ctx, args.concat(slice.call(arguments))); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function _closest(/**HTMLElement*/el, /**String*/selector, /**HTMLElement*/ctx) { |
|
|
|
function _closest(/**HTMLElement*/el, /**String*/selector, /**HTMLElement*/ctx) { |
|
|
|
if (el) { |
|
|
|
if (el) { |
|
|
|
ctx = ctx || document; |
|
|
|
ctx = ctx || document; |
|
|
@ -906,7 +993,9 @@ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function _globalDragOver(/**Event*/evt) { |
|
|
|
function _globalDragOver(/**Event*/evt) { |
|
|
|
|
|
|
|
if (evt.dataTransfer) { |
|
|
|
evt.dataTransfer.dropEffect = 'move'; |
|
|
|
evt.dataTransfer.dropEffect = 'move'; |
|
|
|
|
|
|
|
} |
|
|
|
evt.preventDefault(); |
|
|
|
evt.preventDefault(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1006,7 +1095,6 @@ |
|
|
|
onMoveFn = sortable.options.onMove, |
|
|
|
onMoveFn = sortable.options.onMove, |
|
|
|
retVal; |
|
|
|
retVal; |
|
|
|
|
|
|
|
|
|
|
|
if (onMoveFn) { |
|
|
|
|
|
|
|
evt = document.createEvent('Event'); |
|
|
|
evt = document.createEvent('Event'); |
|
|
|
evt.initEvent('move', true, true); |
|
|
|
evt.initEvent('move', true, true); |
|
|
|
|
|
|
|
|
|
|
@ -1017,6 +1105,9 @@ |
|
|
|
evt.related = targetEl || toEl; |
|
|
|
evt.related = targetEl || toEl; |
|
|
|
evt.relatedRect = targetRect || toEl.getBoundingClientRect(); |
|
|
|
evt.relatedRect = targetRect || toEl.getBoundingClientRect(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fromEl.dispatchEvent(evt); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (onMoveFn) { |
|
|
|
retVal = onMoveFn.call(sortable, evt); |
|
|
|
retVal = onMoveFn.call(sortable, evt); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1035,11 +1126,11 @@ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** @returns {HTMLElement|false} */ |
|
|
|
/** @returns {HTMLElement|false} */ |
|
|
|
function _ghostInBottom(el, evt) { |
|
|
|
function _ghostIsLast(el, evt) { |
|
|
|
var lastEl = el.lastElementChild, |
|
|
|
var lastEl = el.lastElementChild, |
|
|
|
rect = lastEl.getBoundingClientRect(); |
|
|
|
rect = lastEl.getBoundingClientRect(); |
|
|
|
|
|
|
|
|
|
|
|
return (evt.clientY - (rect.top + rect.height) > 5) && lastEl; // min delta
|
|
|
|
return ((evt.clientY - (rect.top + rect.height) > 5) || (evt.clientX - (rect.right + rect.width) > 5)) && lastEl; // min delta
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1068,6 +1159,9 @@ |
|
|
|
* @private |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
function _index(/**HTMLElement*/el) { |
|
|
|
function _index(/**HTMLElement*/el) { |
|
|
|
|
|
|
|
if (!el || !el.parentNode) { |
|
|
|
|
|
|
|
return -1; |
|
|
|
|
|
|
|
} |
|
|
|
var index = 0; |
|
|
|
var index = 0; |
|
|
|
while (el && (el = el.previousElementSibling)) { |
|
|
|
while (el && (el = el.previousElementSibling)) { |
|
|
|
if (el.nodeName.toUpperCase() !== 'TEMPLATE') { |
|
|
|
if (el.nodeName.toUpperCase() !== 'TEMPLATE') { |
|
|
@ -1117,7 +1211,6 @@ |
|
|
|
off: _off, |
|
|
|
off: _off, |
|
|
|
css: _css, |
|
|
|
css: _css, |
|
|
|
find: _find, |
|
|
|
find: _find, |
|
|
|
bind: _bind, |
|
|
|
|
|
|
|
is: function (el, selector) { |
|
|
|
is: function (el, selector) { |
|
|
|
return !!_closest(el, selector, el); |
|
|
|
return !!_closest(el, selector, el); |
|
|
|
}, |
|
|
|
}, |
|
|
@ -1129,9 +1222,6 @@ |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Sortable.version = '1.2.1'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Create sortable instance |
|
|
|
* Create sortable instance |
|
|
|
* @param {HTMLElement} el |
|
|
|
* @param {HTMLElement} el |
|
|
@ -1141,6 +1231,8 @@ |
|
|
|
return new Sortable(el, options); |
|
|
|
return new Sortable(el, options); |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Export
|
|
|
|
// Export
|
|
|
|
|
|
|
|
Sortable.version = '1.3.0-rc1'; |
|
|
|
return Sortable; |
|
|
|
return Sortable; |
|
|
|
}); |
|
|
|
}); |
|
|
|