From f1579794c36215483fa8f6db06561a6dceeaaafb Mon Sep 17 00:00:00 2001 From: owen-m1 Date: Sat, 15 Dec 2018 17:16:00 -0500 Subject: [PATCH] 1.8.0-rc1 --- CONTRIBUTING.md | 6 +- ISSUE_TEMPLATE.md | 11 +- README.md | 72 ++++- Sortable.js | 654 ++++++++++++++++++++++++++++++++-------------- Sortable.min.js | 4 +- bower.json | 5 +- component.json | 9 +- package.json | 10 +- 8 files changed, 553 insertions(+), 218 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c78348a..ad4a3d8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,15 +2,15 @@ ### Issue - 1. Try [master](https://github.com/RubaXa/Sortable/tree/master/)-branch, perhaps the problem has been solved; - 2. [Use the search](https://github.com/RubaXa/Sortable/search?type=Issues&q=problem), maybe already have an answer; + 1. Try [master](https://github.com/SortableJS/Sortable/tree/master/)-branch, perhaps the problem has been solved; + 2. [Use the search](https://github.com/SortableJS/Sortable/search?type=Issues&q=problem), maybe already have an answer; 3. If not found, create example on [jsbin.com (draft)](http://jsbin.com/zunibaxada/1/edit?html,js,output) and describe the problem. --- ### Pull Request - 1. Only into [master](https://github.com/RubaXa/Sortable/tree/master/)-branch. + 1. Only into [master](https://github.com/SortableJS/Sortable/tree/master/)-branch. 2. Do not modify `Sortable.min.js`, this will be compiled before each release. ### Setup diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index 172eb13..a4ff620 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -1,12 +1,15 @@ -## Hi, this project very much requires the maintainer, if you have a chewing and appropriate skills, please [contact me](mailto:ibn@rubaxa.org?subject=Sortable%20vs.%20Maintainer)! +#### Problem: ---- +#### JSBin/JSFiddle demonstrating the problem: + + +--- Before you create an issue, check it: - 1. Try [master](https://github.com/RubaXa/Sortable/tree/master/)-branch, perhaps the problem has been solved; - 2. [Use the search](https://github.com/RubaXa/Sortable/search?q=problem), maybe already have an answer; + 1. Try [master](https://github.com/SortableJS/Sortable/tree/master/)-branch, perhaps the problem has been solved; + 2. [Use the search](https://github.com/SortableJS/Sortable/search?q=problem), maybe we already have an answer; 3. If not found, create an example on [jsbin.com (draft)](http://jsbin.com/vojixek/edit?html,js,output) and describe the problem. Bindings: diff --git a/README.md b/README.md index d01c521..d124d6d 100644 --- a/README.md +++ b/README.md @@ -34,10 +34,10 @@ Demo: http://sortablejs.github.io/Sortable/ ### Articles + * [Swap Thresholds and Direction](https://github.com/SortableJS/Sortable/wiki/Swap-Thresholds-and-Direction) (December 2, 2018) * [Sortable v1.0 — New capabilities](https://github.com/SortableJS/Sortable/wiki/Sortable-v1.0-—-New-capabilities/) (December 22, 2014) * [Sorting with the help of HTML5 Drag'n'Drop API](https://github.com/SortableJS/Sortable/wiki/Sorting-with-the-help-of-HTML5-Drag'n'Drop-API/) (December 23, 2013) -
### Install @@ -79,7 +79,7 @@ You can use any element for the list and its elements, not just `ul`/`li`. Here ### Options ```js var sortable = new Sortable(el, { - group: "name", // or { name: "...", pull: [true, false, clone], put: [true, false, array] } + group: "name", // or { name: "...", pull: [true, false, 'clone', array], put: [true, false, array] } sort: true, // sorting inside list delay: 0, // time in milliseconds to define when the sorting should start touchStartThreshold: 0, // px, how many pixels the point should move before cancelling a delayed drag event @@ -95,6 +95,11 @@ var sortable = new Sortable(el, { dragClass: "sortable-drag", // Class name for the dragging item dataIdAttr: 'data-id', + swapThreshold: 1, // Threshold of the swap zone + invertSwap: false, // Will always use inverted swap zone if set to true + invertedSwapThreshold: 1, // Threshold of the inverted swap zone (will be set to swapThreshold value by default) + direction: 'horizontal', // Direction of Sortable (will be detected automatically if not given) + forceFallback: false, // ignore the HTML5 DnD behaviour and force the fallback to kick in fallbackClass: "sortable-fallback", // Class name for the cloned DOM Element when using forceFallback @@ -107,6 +112,8 @@ var sortable = new Sortable(el, { scrollSpeed: 10, // px bubbleScroll: true, // apply autoscroll to all parent elements, allowing for easier movement + dragoverBubble: false, + setData: function (/** DataTransfer */dataTransfer, /** HTMLElement*/dragEl) { dataTransfer.setData('Text', dragEl.textContent); // `dataTransfer` object of HTML5 DragEvent }, @@ -183,7 +190,7 @@ To drag elements from one list into another, both lists must have the same `grou You can also define whether lists can give away, give and keep a copy (`clone`), and receive elements. * name: `String` — group name - * pull: `true|false|["foo", "bar"]|'clone'|function` — ability to move from the list. `clone` — copy the item, rather than move. Or an array of group names which the elements may be put in. + * pull: `true|false|["foo", "bar"]|'clone'|function` — ability to move from the list. `clone` — copy the item, rather than move. Or an array of group names which the elements may be put in. Defaults to `true`. * put: `true|false|["baz", "qux"]|function` — whether elements can be added from other lists, or an array of group names from which elements can be taken. * revertClone: `boolean` — revert cloned element to initial position after moving to a another list. @@ -215,6 +222,53 @@ Demo: https://jsbin.com/zosiwah/edit?js,output --- +#### `swapThreshold` option +Percentage of the target that the swap zone will take up, as a float between `0` and `1`. + +Read more: https://github.com/SortableJS/Sortable/wiki/Swap-Thresholds-and-Direction#swap-threshold + + +--- + + +#### `invertSwap` option +Set to `true` to set the swap zone to the sides of the target, for the effect of sorting "in between" items. + +Read more: https://github.com/SortableJS/Sortable/wiki/Swap-Thresholds-and-Direction#forcing-inverted-swap-zone + + +--- + + +#### `invertedSwapThreshold` option +Percentage of the target that the inverted swap zone will take up, as a float between `0` and `1`. If not given, will default to `swapThreshold`. + +Read more: https://github.com/SortableJS/Sortable/wiki/Swap-Thresholds-and-Direction#dealing-with-swap-glitching + + +--- + + +#### `direction` option +Direction that the Sortable should sort in. Can be set to `'vertical'`, `'horizontal'`, or a function, which will be called whenever a target is dragged over. Must return `'vertical'` or `'horizontal'`. + +Read more: https://github.com/SortableJS/Sortable/wiki/Swap-Thresholds-and-Direction#direction + + +Example of dynamic direction detection: + +```js +Sortable.create(el, { + direction: function(evt, target, dragEl) { + return Sortable.utils.detectDirection(el); + } +}); +``` + + +--- + + #### `touchStartThreshold` option This option is similar to `fallbackTolerance` option. @@ -413,6 +467,14 @@ Demo: https://jsbin.com/kesewor/edit?html,js,output --- + +#### `dragoverBubble` option +If set to `true`, the dragover event will bubble to parent Sortables. Useful for nested Sortables. Works on both fallback and native dragover event. + + +--- + + ### Event object ([demo](https://jsbin.com/fogujiv/edit?js,output)) - to:`HTMLElement` — list, in which moved element. @@ -576,6 +638,7 @@ Link to the active instance. * closest(el`:HTMLElement`, selector`:String`[, ctx`:HTMLElement`])`:HTMLElement|Null` — 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 * clone(el`:HTMLElement`)`:HTMLElement` — create a deep copy of the set of matched elements * toggleClass(el`:HTMLElement`, name`:String`, state`:Boolean`) — add or remove one classes from each element +* detectDirection(el`:HTMLElement`)`:String` — automatically detect the direction of the element as either `'vertical'` or `'horizontal'` --- @@ -636,9 +699,6 @@ Please, [read this](CONTRIBUTING.md). ## MIT LICENSE -Copyright 2013-2017 Lebedev Konstantin -http://SortableJS.github.io/Sortable/ - Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including diff --git a/Sortable.js b/Sortable.js index 8e458c4..15e59ca 100644 --- a/Sortable.js +++ b/Sortable.js @@ -1,6 +1,7 @@ /**! * Sortable * @author RubaXa + * @author owenm * @license MIT */ @@ -38,10 +39,6 @@ scrollParentEl, scrollCustomFn, - lastEl, - lastCSS, - lastParentCSS, - oldIndex, newIndex, @@ -49,6 +46,7 @@ putSortable, autoScrolls = [], + scrolling = false, pointerElemChangedInterval, lastPointerElemX, @@ -59,11 +57,16 @@ moved, + lastTarget, + lastDirection, + pastFirstInvertThresh = false, + isCircumstantialInvert = false, + forRepaintDummy, + realDragElRect, // dragEl rect after current animation /** @const */ R_SPACE = /\s+/g, - R_FLOAT = /left|right|inline/, expando = 'Sortable' + (new Date).getTime(), @@ -75,8 +78,10 @@ $ = win.jQuery || win.Zepto, Polymer = win.Polymer, - captureMode = false, - passiveMode = false, + captureMode = { + capture: false, + passive: false + }, supportDraggable = ('draggable' in document.createElement('div')), supportCssPointerEvents = (function (el) { @@ -90,6 +95,7 @@ })(), _silent = false, + _alignedSilent = false, abs = Math.abs, min = Math.min, @@ -99,31 +105,76 @@ alwaysFalse = function () { return false; }, - _getParentAutoScrollElement = function(rootEl, includeSelf) { - // will skip to window in _autoScroll - if (!rootEl || !rootEl.getBoundingClientRect) return; + _detectDirection = function(el, options) { + var elCSS = _css(el), + elWidth = parseInt(elCSS.width), + child1 = _getChild(el, 0, options), + child2 = _getChild(el, 1, options), + firstChildCSS = child1 && _css(child1), + secondChildCSS = child2 && _css(child2), + firstChildWidth = firstChildCSS && parseInt(firstChildCSS.marginLeft) + parseInt(firstChildCSS.marginRight) + child1.getBoundingClientRect().width, + secondChildWidth = secondChildCSS && parseInt(secondChildCSS.marginLeft) + parseInt(secondChildCSS.marginRight) + child2.getBoundingClientRect().width + ; + if (elCSS.display === 'flex') { + return elCSS.flexDirection === 'column' || elCSS.flexDirection === 'column-reverse' + ? 'vertical' : 'horizontal'; + } + return (child1 && + ( + firstChildCSS.display === 'block' || + firstChildCSS.display === 'grid' || + firstChildWidth >= elWidth && + elCSS.float === 'none' || + child2 && + elCSS.float === 'none' && + firstChildWidth + secondChildWidth > elWidth + ) ? + 'vertical' : 'horizontal' + ); + }, + + _isInRowColumn = function(x, y, el, axis, options) { + var targetRect = realDragElRect || dragEl.getBoundingClientRect(), + targetS1Opp = axis === 'vertical' ? targetRect.left : targetRect.top, + targetS2Opp = axis === 'vertical' ? targetRect.right : targetRect.bottom, + mouseOnOppAxis = axis === 'vertical' ? x : y + ; + + return targetS1Opp < mouseOnOppAxis && mouseOnOppAxis < targetS2Opp; + }, - var elem = rootEl; + _getParentAutoScrollElement = function(el, includeSelf) { + // skip to window + if (!el || !el.getBoundingClientRect) return win; + + var elem = el; var gotSelf = false; do { - if ( - (elem.clientWidth < elem.scrollWidth) || - (elem.clientHeight < elem.scrollHeight) - ) { - if (!elem || !elem.getBoundingClientRect || elem === document.body) return; + // we don't need to get elem css if it isn't even overflowing in the first place (performance) + if (elem.clientWidth < elem.scrollWidth || elem.clientHeight < elem.scrollHeight) { + var elemCSS = _css(elem); + if ( + elem.clientWidth < elem.scrollWidth && (elemCSS.overflowX == 'auto' || elemCSS.overflowX == 'scroll') || + elem.clientHeight < elem.scrollHeight && (elemCSS.overflowY == 'auto' || elemCSS.overflowY == 'scroll') + ) { + if (!elem || !elem.getBoundingClientRect || elem === document.body) return win; - if (gotSelf || includeSelf) return elem; - gotSelf = true; + if (gotSelf || includeSelf) return elem; + gotSelf = true; + } } - + /* jshint boss:true */ } while (elem = elem.parentNode); + + return win; }, - _autoScroll = _throttle(function (/**Event*/evt, /**Object*/options, /**HTMLElement*/rootEl) { + _autoScroll = _throttle(function (/**Event*/evt, /**Object*/options, /**HTMLElement*/rootEl, /**Boolean*/isFallback) { // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521 if (options.scroll) { var _this = rootEl ? rootEl[expando] : window, rect, + css, sens = options.scrollSensitivity, speed = options.scrollSpeed, @@ -136,8 +187,7 @@ vx, vy, - scrollOffsetX, - scrollOffsetY + scrollThisInstance = false ; // Detect scrollEl @@ -159,20 +209,19 @@ do { var el; - if (currentParent) { + if (currentParent && currentParent !== win) { el = currentParent; + css = _css(el); rect = currentParent.getBoundingClientRect(); - vx = (abs(rect.right - x) <= sens) - (abs(rect.left - x) <= sens); - vy = (abs(rect.bottom - y) <= sens) - (abs(rect.top - y) <= sens); - } - + vx = el.clientWidth < el.scrollWidth && (css.overflowX == 'auto' || css.overflowX == 'scroll') && + ((abs(rect.right - x) <= sens) - (abs(rect.left - x) <= sens)); - if (!(vx || vy)) { + vy = el.clientHeight < el.scrollHeight && (css.overflowY == 'auto' || css.overflowY == 'scroll') && + ((abs(rect.bottom - y) <= sens) - (abs(rect.top - y) <= sens)); + } else if (currentParent === win) { + el = win; vx = (winWidth - x <= sens) - (x <= sens); vy = (winHeight - y <= sens) - (y <= sens); - - /* jshint expr:true */ - (vx || vy) && (el = win); } if (!autoScrolls[layersOut]) { @@ -183,35 +232,41 @@ } } - if (autoScrolls[layersOut].vx !== vx || autoScrolls[layersOut].vy !== vy || autoScrolls[layersOut].el !== el) { + if (autoScrolls[layersOut].vx != vx || autoScrolls[layersOut].vy != vy || autoScrolls[layersOut].el !== el) { autoScrolls[layersOut].el = el; autoScrolls[layersOut].vx = vx; autoScrolls[layersOut].vy = vy; clearInterval(autoScrolls[layersOut].pid); - if (el) { + if (el && (vx != 0 || vy != 0)) { + scrollThisInstance = true; + /* jshint loopfunc:true */ autoScrolls[layersOut].pid = setInterval((function () { - scrollOffsetY = autoScrolls[this.layersOut].vy ? autoScrolls[this.layersOut].vy * speed : 0; - scrollOffsetX = autoScrolls[this.layersOut].vx ? autoScrolls[this.layersOut].vx * speed : 0; + // emulate drag over during autoscroll (fallback), emulating native DnD behaviour + if (isFallback && this.layer === 0) { + Sortable.active._emulateDragOver(true); + } + var scrollOffsetY = autoScrolls[this.layer].vy ? autoScrolls[this.layer].vy * speed : 0; + var scrollOffsetX = autoScrolls[this.layer].vx ? autoScrolls[this.layer].vx * speed : 0; if ('function' === typeof(scrollCustomFn)) { - if (scrollCustomFn.call(_this, scrollOffsetX, scrollOffsetY, evt, touchEvt, autoScrolls[this.layersOut].el) !== 'continue') { + if (scrollCustomFn.call(_this, scrollOffsetX, scrollOffsetY, evt, touchEvt, autoScrolls[this.layer].el) !== 'continue') { return; } } - - if (autoScrolls[this.layersOut].el === win) { + if (autoScrolls[this.layer].el === win) { win.scrollTo(win.pageXOffset + scrollOffsetX, win.pageYOffset + scrollOffsetY); } else { - autoScrolls[this.layersOut].el.scrollTop += scrollOffsetY; - autoScrolls[this.layersOut].el.scrollLeft += scrollOffsetX; + autoScrolls[this.layer].el.scrollTop += scrollOffsetY; + autoScrolls[this.layer].el.scrollLeft += scrollOffsetX; } - }).bind({layersOut: layersOut}), 24); + }).bind({layer: layersOut}), 24); } } layersOut++; - } while (options.bubbleScroll && (currentParent = _getParentAutoScrollElement(currentParent, false))); + } while (options.bubbleScroll && currentParent !== win && (currentParent = _getParentAutoScrollElement(currentParent, false))); + scrolling = scrollThisInstance; // in case another function catches scrolling as false in between when it is not } }, 30), @@ -227,7 +282,9 @@ return function(to, from, dragEl, evt) { var ret; - if (value == null || value === false) { + if (value == null && pull) { + ret = true; // default pull value: true (backwards compatibility) + } else if (value == null || value === false) { ret = false; } else if (pull && value === 'clone') { ret = value; @@ -240,9 +297,8 @@ (typeof value === 'string' && value === otherGroup) || (value.join && value.indexOf(otherGroup) > -1)); } - - return ret || to.options.group.name === from.options.group.name; - } + return ret || (to.options.group.name && from.options.group.name && to.options.group.name === from.options.group.name); + }; } var group = {}; @@ -258,23 +314,14 @@ group.revertClone = originalGroup.revertClone; options.group = group; + }, + + _checkAlignment = function(evt) { + if (!dragEl) return; + dragEl.parentNode[expando] && dragEl.parentNode[expando]._computeIsAligned(evt); } ; - // Detect support a passive mode - try { - window.addEventListener('test', null, Object.defineProperty({}, 'passive', { - get: function () { - // `false`, because everything starts to work incorrectly and instead of d'n'd, - // begins the page has scrolled. - passiveMode = false; - captureMode = { - capture: false, - passive: passiveMode - }; - } - })); - } catch (err) {} /** * @class Sortable @@ -300,11 +347,16 @@ disabled: false, store: null, handle: null, - scroll: true, + scroll: true, scrollSensitivity: 30, scrollSpeed: 10, bubbleScroll: true, draggable: /[uo]l/i.test(el.nodeName) ? 'li' : '>*', + + swapThreshold: 1, // percentage; 0 <= x <= 1 + invertSwap: false, // invert always + invertedSwapThreshold: null, // will be set to same as swapThreshold if default + ghostClass: 'sortable-ghost', chosenClass: 'sortable-chosen', dragClass: 'sortable-drag', @@ -325,7 +377,10 @@ fallbackOnBody: false, fallbackTolerance: 0, fallbackOffset: {x: 0, y: 0}, - supportPointer: Sortable.supportPointer !== false + supportPointer: Sortable.supportPointer !== false && ( + ('PointerEvent' in window) || + window.navigator && ('msPointerEnabled' in window.navigator) // microsoft + ) }; @@ -334,8 +389,15 @@ !(name in options) && (options[name] = defaults[name]); } + if (!('direction' in options)) { + options.direction = function() { + return _detectDirection(el, options); + }; + } + _prepareGroup(options); + options.invertedSwapThreshold == null && (options.invertedSwapThreshold = options.swapThreshold); // Bind all private methods for (var fn in this) { if (fn.charAt(0) === '_' && typeof this[fn] === 'function') { @@ -359,13 +421,32 @@ touchDragOverListeners.push(this._onDragOver); // Restore sorting - options.store && this.sort(options.store.get(this)); + options.store && options.store.get && this.sort(options.store.get(this) || []); } - Sortable.prototype = /** @lends Sortable.prototype */ { constructor: Sortable, + // is mouse aligned with dragEl? + _isAligned: true, + + _computeIsAligned: function(evt, isDragEl) { + if (_alignedSilent) return; + if (!dragEl || dragEl.parentNode !== this.el) return; + if (isDragEl !== true && isDragEl !== false) { + isDragEl = !!_closest(evt.target, null, dragEl, true); + } + this._isAligned = !scrolling && (isDragEl || this._isAligned && _isInRowColumn(evt.clientX, evt.clientY, this.el, this._getDirection(evt, null), this.options)); + _alignedSilent = true; + setTimeout(function() { + _alignedSilent = false; + }, 30); + }, + + _getDirection: function(evt, target) { + return (typeof this.options.direction === 'function') ? this.options.direction.call(this, evt, target, dragEl) : this.options.direction; + }, + _onTapStart: function (/** Event|TouchEvent */evt) { var _this = this, el = this.el, @@ -395,7 +476,7 @@ return; } - target = _closest(target, options.draggable, el); + target = _closest(target, options.draggable, el, true); if (!target) { return; @@ -413,13 +494,13 @@ if (typeof filter === 'function') { if (filter.call(this, evt, target, this)) { _dispatchEvent(_this, originalTarget, 'filter', target, el, el, startIndex); - preventOnFilter && evt.preventDefault(); + preventOnFilter && evt.cancelable && evt.preventDefault(); return; // cancel dnd } } else if (filter) { filter = filter.split(',').some(function (criteria) { - criteria = _closest(originalTarget, criteria.trim(), el); + criteria = _closest(originalTarget, criteria.trim(), el, false); if (criteria) { _dispatchEvent(_this, criteria, 'filter', target, el, el, startIndex); @@ -428,12 +509,12 @@ }); if (filter) { - preventOnFilter && evt.preventDefault(); + preventOnFilter && evt.cancelable && evt.preventDefault(); return; // cancel dnd } } - if (options.handle && !_closest(originalTarget, options.handle, el)) { + if (options.handle && !_closest(originalTarget, options.handle, el, false)) { return; } @@ -442,37 +523,40 @@ }, - _handleAutoScroll: function(evt) { - if (!dragEl || !this.options.scroll || (this.options.supportPointer && evt.type == 'touchmove')) return; - var - x = (evt.touches ? evt.touches[0] : evt).clientX, - y = (evt.touches ? evt.touches[0] : evt).clientY, + _handleAutoScroll: function(evt, fallback) { + if (!dragEl || !this.options.scroll) return; + var x = evt.clientX, + y = evt.clientY, elem = document.elementFromPoint(x, y), _this = this ; - - // touch does not have native autoscroll, even with DnD enabled - if (!_this.nativeDraggable || evt.touches || (evt.pointerType && evt.pointerType == 'touch')) { - - _autoScroll(evt.touches ? evt.touches[0] : evt, _this.options, elem); + // firefox does not have native autoscroll + if (fallback || (window.navigator && window.navigator.userAgent.toLowerCase().indexOf('firefox') > -1)) { + _autoScroll(evt, _this.options, elem, true); // Listener for pointer element change var ogElemScroller = _getParentAutoScrollElement(elem, true); - if (!pointerElemChangedInterval || - x != lastPointerElemX || - y != lastPointerElemY) { + if ( + scrolling && + ( + !pointerElemChangedInterval || + x !== lastPointerElemX || + y !== lastPointerElemY + ) + ) { pointerElemChangedInterval && clearInterval(pointerElemChangedInterval); // Detect for pointer elem change, emulating native DnD behaviour pointerElemChangedInterval = setInterval(function() { if (!dragEl) return; + // could also check if scroll direction on newElem changes due to parent autoscrolling var newElem = _getParentAutoScrollElement(document.elementFromPoint(x, y), true); - if (newElem != ogElemScroller) { + if (newElem !== ogElemScroller) { ogElemScroller = newElem; _clearAutoScrolls(); - _autoScroll(evt.touches ? evt.touches[0] : evt, _this.options, ogElemScroller); + _autoScroll(evt, _this.options, ogElemScroller, true); } }, 10); lastPointerElemX = x; @@ -480,8 +564,11 @@ } } else { - // if DnD is enabled, first autoscroll will already scroll, so get parent autoscroll of first autoscroll - if (!_this.options.bubbleScroll) return; + // if DnD is enabled (not on firefox), first autoscroll will already scroll, so get parent autoscroll of first autoscroll + if (!_this.options.bubbleScroll || _getParentAutoScrollElement(elem, true) === window) { + _clearAutoScrolls(); + return; + } _autoScroll(evt, _this.options, _getParentAutoScrollElement(elem, false)); } }, @@ -535,7 +622,6 @@ _on(ownerDocument, 'mouseup', _this._onDrop); _on(ownerDocument, 'touchend', _this._onDrop); _on(ownerDocument, 'touchcancel', _this._onDrop); - _on(ownerDocument, 'selectstart', _this); options.supportPointer && _on(ownerDocument, 'pointercancel', _this._onDrop); if (options.delay) { @@ -616,15 +702,22 @@ _dragStarted: function () { if (rootEl && dragEl) { - _on(document, 'drag', this._handleAutoScroll); + if (this.nativeDraggable) { + _on(document, 'dragover', this._handleAutoScroll); + _on(document, 'dragover', _checkAlignment); + } var options = this.options; // Apply effect - _toggleClass(dragEl, options.ghostClass, true); _toggleClass(dragEl, options.dragClass, false); + _toggleClass(dragEl, options.ghostClass, true); + + _css(dragEl, 'transform', ''); Sortable.active = this; + this._isAligned = true; + // Drag start event _dispatchEvent(this, rootEl, 'start', dragEl, rootEl, rootEl, oldIndex); } else { @@ -632,9 +725,9 @@ } }, - _emulateDragOver: function () { + _emulateDragOver: function (bypassLastTouchCheck) { if (touchEvt) { - if (this._lastX === touchEvt.clientX && this._lastY === touchEvt.clientY) { + if (this._lastX === touchEvt.clientX && this._lastY === touchEvt.clientY && !bypassLastTouchCheck) { return; } @@ -647,6 +740,7 @@ var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY); var parent = target; + var isDragEl = !!_closest(target, null, dragEl, true); while (target && target.shadowRoot) { target = target.shadowRoot.elementFromPoint(touchEvt.clientX, touchEvt.clientY); @@ -676,6 +770,7 @@ /* jshint boss:true */ while (parent = parent.parentNode); } + dragEl.parentNode[expando]._computeIsAligned(touchEvt, isDragEl); if (!supportCssPointerEvents) { _css(ghostEl, 'display', ''); @@ -694,6 +789,9 @@ dy = (touch.clientY - tapEvt.clientY) + fallbackOffset.y, translate3d = evt.touches ? 'translate3d(' + dx + 'px,' + dy + 'px,0)' : 'translate(' + dx + 'px,' + dy + 'px)'; + // prevent duplicate event firing + if (this.options.supportPointer && evt.type === 'touchmove') return; + // only set the status to dragging, when we are actually dragging if (!Sortable.active) { if (fallbackTolerance && @@ -708,6 +806,9 @@ // as well as creating the ghost element on the document body this._appendGhost(); + this._handleAutoScroll(touch, true); + + moved = true; touchEvt = touch; @@ -716,7 +817,7 @@ _css(ghostEl, 'msTransform', translate3d); _css(ghostEl, 'transform', translate3d); - evt.preventDefault(); + evt.cancelable && evt.preventDefault(); } }, @@ -757,7 +858,6 @@ var options = _this.options; _this._offUpEvents(); - if (activeGroup.checkPull(_this, _this, dragEl, evt)) { cloneEl = _clone(dragEl); @@ -779,26 +879,26 @@ if (useFallback) { if (useFallback === 'touch') { + // Fixed #973: + _on(document, 'touchmove', _preventScroll); + // Bind touch events _on(document, 'touchmove', _this._onTouchMove); - // onTouchMove before handleAutoScroll in this case, because onTouchMove sets touchEvt - _on(document, 'touchmove', _this._handleAutoScroll); _on(document, 'touchend', _this._onDrop); _on(document, 'touchcancel', _this._onDrop); if (options.supportPointer) { - _on(document, 'pointermove', _this._handleAutoScroll); _on(document, 'pointermove', _this._onTouchMove); _on(document, 'pointerup', _this._onDrop); } } else { // Old brwoser - _on(document, 'mousemove', _this._handleAutoScroll); _on(document, 'mousemove', _this._onTouchMove); _on(document, 'mouseup', _this._onDrop); } _this._loopId = setInterval(_this._emulateDragOver, 50); + _toggleClass(dragEl, options.dragClass, false); } else { if (dataTransfer) { @@ -808,13 +908,12 @@ _on(document, 'drop', _this); - // #1143: Бывает элемент с IFrame внутри блокирует `drop`, - // поэтому если вызвался `mouseover`, значит надо отменять весь d'n'd. - // Breaking Chrome 62+ - // _on(document, 'mouseover', _this); + // #1276 fix: + _css(dragEl, 'transform', 'translateZ(0)'); _this._dragStartId = _nextTick(_this._dragStarted); } + _on(document, 'selectstart', _this); }, _onDragOver: function (/**Event*/evt) { @@ -828,22 +927,40 @@ activeSortable = Sortable.active, isOwner = (activeGroup === group), isMovingBetweenSortable = false, - canSort = options.sort; + canSort = options.sort + ; + + + if (evt.rootEl !== void 0 && evt.rootEl !== this.el) return; // touch fallback + + // no bubbling and not fallback + if (!options.dragoverBubble && !evt.rootEl) { + this._handleAutoScroll(evt); + dragEl.parentNode[expando]._computeIsAligned(evt); + } if (evt.preventDefault !== void 0) { - evt.preventDefault(); + evt.cancelable && evt.preventDefault(); !options.dragoverBubble && evt.stopPropagation(); } - if (dragEl.animated) { + + moved = true; + + target = _closest(evt.target, options.draggable, el, true); + + + if (dragEl.animated && target === dragEl || target.animated || _silent) { return; } - moved = true; - target = evt.target == el ? evt.target : _closest(evt.target, options.draggable, el); + if (target !== lastTarget) { + isCircumstantialInvert = false; + pastFirstInvertThresh = false; + lastTarget = null; + } - if (target === el) return; if (activeSortable && !options.disabled && (isOwner @@ -855,12 +972,11 @@ group.checkPut(this, activeSortable, dragEl, evt) ) ) - ) && - (evt.rootEl === void 0 || evt.rootEl === this.el) // touch fallback + ) ) { - if (_silent) { - return; - } + var direction; + var axis = this._getDirection(evt, target); + dragRect = dragEl.getBoundingClientRect(); @@ -886,13 +1002,12 @@ return; } - if ((el.children.length === 0) || (el.children[0] === ghostEl) || - (el === evt.target) && (_ghostIsLast(el, evt)) + (el === evt.target) && _ghostIsLast(evt, axis, el) ) { //assign target only if condition is true if (el.children.length !== 0 && el.children[0] !== ghostEl && el === evt.target) { - target = el.lastElementChild; + target = _lastChild(el); } if (target) { @@ -909,51 +1024,46 @@ activeSortable._showClone(this); } - if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt) !== false) { + if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, !!target) !== false) { if (!dragEl.contains(el)) { el.appendChild(dragEl); parentEl = el; // actualization + this._isAligned = true; // must be for _ghostIsLast to pass + realDragElRect = null; } this._animate(dragRect, dragEl); target && this._animate(targetRect, target); } } - else if (target && !target.animated && target !== dragEl && (target.parentNode[expando] !== void 0)) { - if (lastEl !== target) { - lastEl = target; - lastCSS = _css(target); - lastParentCSS = _css(target.parentNode); + else if (target && !target.animated && target !== dragEl && (target.parentNode[expando] !== void 0) && target !== el) { + + isCircumstantialInvert = isCircumstantialInvert || options.invertSwap || dragEl.parentNode !== el || !this._isAligned; + direction = _getSwapDirection(evt, target, axis, + options.swapThreshold, options.invertedSwapThreshold, + isCircumstantialInvert, + lastTarget === target); + if (direction === 0) return; + realDragElRect = null; + + + this._isAligned = true; + + if (!lastTarget || lastTarget !== target && (!target || !target.animated)) { + pastFirstInvertThresh = false; + lastTarget = target; } + + lastDirection = direction; + targetRect = target.getBoundingClientRect(); - var width = targetRect.right - targetRect.left, - height = targetRect.bottom - targetRect.top, - floating = R_FLOAT.test(lastCSS.cssFloat + lastCSS.display) - || (lastParentCSS.display == 'flex' && lastParentCSS['flex-direction'].indexOf('row') === 0), - isWide = (target.offsetWidth > dragEl.offsetWidth), - isLong = (target.offsetHeight > dragEl.offsetHeight), - halfway = (floating ? (evt.clientX - targetRect.left) / width : (evt.clientY - targetRect.top) / height) > 0.5, - nextSibling = target.nextElementSibling, + var nextSibling = target.nextElementSibling, after = false ; - if (floating) { - var elTop = dragEl.offsetTop, - tgTop = target.offsetTop; - - if (elTop === tgTop) { - after = (target.previousElementSibling === dragEl) && !isWide || halfway && isWide; - } - else if (target.previousElementSibling === dragEl || dragEl.previousElementSibling === target) { - after = (evt.clientY - targetRect.top) / height > 0.5; - } else { - after = tgTop > elTop; - } - } else if (!isMovingBetweenSortable) { - after = (nextSibling !== dragEl) && !isLong || halfway && isLong; - } + after = direction === 1; var moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, after); @@ -994,10 +1104,19 @@ if (ms) { var currentRect = target.getBoundingClientRect(); + if (target === dragEl) { + realDragElRect = currentRect; + } + if (prevRect.nodeType === 1) { prevRect = prevRect.getBoundingClientRect(); } + // Check if actually moving position + if ((prevRect.left + prevRect.width / 2) === (currentRect.left + currentRect.width / 2) + && (prevRect.top + prevRect.height / 2) === (currentRect.top + currentRect.height / 2) + ) return; + _css(target, 'transition', 'none'); _css(target, 'transform', 'translate3d(' + (prevRect.left - currentRect.left) + 'px,' @@ -1021,9 +1140,7 @@ _offUpEvents: function () { var ownerDocument = this.el.ownerDocument; - _off(document, 'touchmove', this._handleAutoScroll); - _off(document, 'pointermove', this._handleAutoScroll); - _off(document, 'mousemove', this._handleAutoScroll); + _off(document, 'touchmove', _preventScroll); _off(document, 'touchmove', this._onTouchMove); _off(document, 'pointermove', this._onTouchMove); _off(ownerDocument, 'mouseup', this._onDrop); @@ -1031,12 +1148,15 @@ _off(ownerDocument, 'pointerup', this._onDrop); _off(ownerDocument, 'touchcancel', this._onDrop); _off(ownerDocument, 'pointercancel', this._onDrop); - _off(ownerDocument, 'selectstart', this); + _off(document, 'selectstart', this); }, _onDrop: function (/**Event*/evt) { var el = this.el, options = this.options; + scrolling = false; + isCircumstantialInvert = false; + pastFirstInvertThresh = false; clearInterval(this._loopId); @@ -1050,21 +1170,21 @@ _cancelNextTick(this._dragStartId); // Unbind events - _off(document, 'mouseover', this); _off(document, 'mousemove', this._onTouchMove); if (this.nativeDraggable) { _off(document, 'drop', this); _off(el, 'dragstart', this._onDragStart); - _off(document, 'drag', this._handleAutoScroll); + _off(document, 'dragover', this._handleAutoScroll); + _off(document, 'dragover', _checkAlignment); } this._offUpEvents(); if (evt) { if (moved) { - evt.preventDefault(); + evt.cancelable && evt.preventDefault(); !options.dropBubble && evt.stopPropagation(); } @@ -1104,6 +1224,8 @@ _dispatchEvent(null, parentEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex, evt); _dispatchEvent(this, rootEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex, evt); } + + putSortable && putSortable.save(); } else { if (dragEl.nextSibling !== nextEl) { @@ -1132,7 +1254,6 @@ } } - this._nulling(); }, @@ -1147,15 +1268,24 @@ scrollEl = scrollParentEl = + autoScrolls.length = + + pointerElemChangedInterval = + lastPointerElemX = + lastPointerElemY = tapEvt = touchEvt = moved = newIndex = + oldIndex = + + lastTarget = + lastDirection = - lastEl = - lastCSS = + forRepaintDummy = + realDragElRect = putSortable = activeGroup = @@ -1174,18 +1304,14 @@ this._onDrop(evt); break; - case 'dragover': case 'dragenter': + case 'dragover': if (dragEl) { this._onDragOver(evt); _globalDragOver(evt); } break; - case 'mouseover': - this._onDrop(evt); - break; - case 'selectstart': evt.preventDefault(); break; @@ -1207,7 +1333,7 @@ for (; i < n; i++) { el = children[i]; - if (_closest(el, options.draggable, this.el)) { + if (_closest(el, options.draggable, this.el, false)) { order.push(el.getAttribute(options.dataIdAttr) || _generateId(el)); } } @@ -1226,7 +1352,7 @@ this.toArray().forEach(function (id, i) { var el = rootEl.children[i]; - if (_closest(el, this.options.draggable, rootEl)) { + if (_closest(el, this.options.draggable, rootEl, false)) { items[id] = el; } }, this); @@ -1245,7 +1371,7 @@ */ save: function () { var store = this.options.store; - store && store.set(this); + store && store.set && store.set(this); }, @@ -1256,7 +1382,7 @@ * @returns {HTMLElement|null} */ closest: function (el, selector) { - return _closest(el, selector || this.options.draggable, this.el); + return _closest(el, selector || this.options.draggable, this.el, false); }, @@ -1297,7 +1423,6 @@ _off(el, 'dragover', this); _off(el, 'dragenter', this); } - // Remove draggable attributes Array.prototype.forEach.call(el.querySelectorAll('[draggable]'), function (el) { el.removeAttribute('draggable'); @@ -1318,11 +1443,20 @@ }, _showClone: function(putSortable) { - if (putSortable.lastPutMode !== 'clone') return; + if (putSortable.lastPutMode !== 'clone') { + this._hideClone(); + return; + } if (cloneEl.cloneHidden) { // show clone at dragEl or original position - rootEl.insertBefore(cloneEl, rootEl.contains(dragEl) && !this.options.group.revertClone ? dragEl : nextEl); + if (rootEl.contains(dragEl) && !this.options.group.revertClone) { + rootEl.insertBefore(cloneEl, dragEl); + } else if (nextEl) { + rootEl.insertBefore(cloneEl, nextEl); + } else { + rootEl.appendChild(cloneEl); + } if (this.options.group.revertClone) { this._animate(dragEl, cloneEl); @@ -1333,14 +1467,16 @@ } }; - function _closest(/**HTMLElement*/el, /**String*/selector, /**HTMLElement*/ctx) { + function _closest(/**HTMLElement*/el, /**String*/selector, /**HTMLElement*/ctx, includeCTX) { if (el) { ctx = ctx || document; do { - if ((selector === '>*' && el.parentNode === ctx) || _matches(el, selector)) { + if ((selector === '>*' && el.parentNode === ctx) || _matches(el, selector) || (includeCTX && el === ctx)) { return el; } + + if (el === ctx) break; /* jshint boss:true */ } while (el = _getParentOrHost(el)); } @@ -1360,7 +1496,7 @@ if (evt.dataTransfer) { evt.dataTransfer.dropEffect = 'move'; } - evt.preventDefault(); + evt.cancelable && evt.preventDefault(); } @@ -1375,7 +1511,7 @@ function _toggleClass(el, name, state) { - if (el) { + if (el && name) { if (el.classList) { el.classList[state ? 'add' : 'remove'](name); } @@ -1433,11 +1569,19 @@ function _dispatchEvent(sortable, rootEl, name, targetEl, toEl, fromEl, startIndex, newIndex, originalEvt) { sortable = (sortable || rootEl[expando]); - var evt = document.createEvent('Event'), + var evt, options = sortable.options, onName = 'on' + name.charAt(0).toUpperCase() + name.substr(1); - - evt.initEvent(name, true, true); + // Support for new CustomEvent feature + if (window.CustomEvent) { + evt = new CustomEvent(name, { + bubbles: true, + cancelable: true + }); + } else { + evt = document.createEvent('Event'); + evt.initEvent(name, true, true); + } evt.to = toEl || rootEl; evt.from = fromEl || rootEl; @@ -1462,9 +1606,16 @@ sortable = fromEl[expando], onMoveFn = sortable.options.onMove, retVal; - - evt = document.createEvent('Event'); - evt.initEvent('move', true, true); + // Support for new CustomEvent feature + if (window.CustomEvent) { + evt = new CustomEvent('move', { + bubbles: true, + cancelable: true + }); + } else { + evt = document.createEvent('Event'); + evt.initEvent('move', true, true); + } evt.to = toEl; evt.from = fromEl; @@ -1485,26 +1636,139 @@ return retVal; } - function _disableDraggable(el) { el.draggable = false; } - function _unsilent() { _silent = false; } + function _getChild(el, childNum, options) { + var currentChild = 0, + i = 0, + children = el.children + ; + while (i < children.length) { + if ( + children[i].style.display !== 'none' && + children[i] !== ghostEl && + children[i] !== dragEl && + _closest(children[i], options.draggable, el, false) + ) { + if (currentChild === childNum) { + return children[i]; + } + currentChild++; + } + + i++; + } + return null; + } + + function _lastChild(el) { + var last = el.lastElementChild; + + if (last === ghostEl) { + last = el.children[el.childElementCount - 2]; + } + + return last || null; + } + + function _ghostIsLast(evt, axis, el) { + var elRect = _lastChild(el).getBoundingClientRect(), + mouseOnAxis = axis === 'vertical' ? evt.clientY : evt.clientX, + mouseOnOppAxis = axis === 'vertical' ? evt.clientX : evt.clientY, + targetS2 = axis === 'vertical' ? elRect.bottom : elRect.right, + targetS1Opp = axis === 'vertical' ? elRect.left : elRect.top, + targetS2Opp = axis === 'vertical' ? elRect.right : elRect.bottom + ; + return ( + mouseOnOppAxis > targetS1Opp && + mouseOnOppAxis < targetS2Opp && + mouseOnAxis > targetS2 + ); + } + + function _getSwapDirection(evt, target, axis, swapThreshold, invertedSwapThreshold, invertSwap, inside) { + var targetRect = target.getBoundingClientRect(), + mouseOnAxis = axis === 'vertical' ? evt.clientY : evt.clientX, + targetLength = axis === 'vertical' ? targetRect.height : targetRect.width, + targetS1 = axis === 'vertical' ? targetRect.top : targetRect.left, + targetS2 = axis === 'vertical' ? targetRect.bottom : targetRect.right, + dragRect = dragEl.getBoundingClientRect(), + dragLength = axis === 'vertical' ? dragRect.height : dragRect.width, + invert = false + ; + var dragStyle = _css(dragEl); + dragLength += parseInt(dragStyle.marginLeft) + parseInt(dragStyle.marginRight); + + if (!invertSwap) { + // Never invert or create dragEl shadow when width causes mouse to move past the end of regular swapThreshold + if (inside && dragLength < targetLength * swapThreshold) { // multiplied only by swapThreshold because mouse will already be inside target by (1 - threshold) * targetLength / 2 + // check if past first invert threshold on side opposite of lastDirection + if (!pastFirstInvertThresh && + (lastDirection === 1 ? + ( + mouseOnAxis > targetS1 + targetLength * invertedSwapThreshold / 2 + ) : + ( + mouseOnAxis < targetS2 - targetLength * invertedSwapThreshold / 2 + ) + ) + ) + { + // past first invert threshold, do not restrict inverted threshold to dragEl shadow + pastFirstInvertThresh = true; + } + + if (!pastFirstInvertThresh) { + var dragS1 = axis === 'vertical' ? dragRect.top : dragRect.left, + dragS2 = axis === 'vertical' ? dragRect.bottom : dragRect.right + ; + // dragEl shadow + if ( + lastDirection === 1 ? + ( + mouseOnAxis < targetS1 + dragLength // over dragEl shadow + ) : + ( + mouseOnAxis > targetS2 - dragLength + ) + ) + { + return lastDirection * -1; + } + } else { + invert = true; + } + } else { + // Regular + if ( + mouseOnAxis > targetS1 + (targetLength * (1 - swapThreshold) / 2) && + mouseOnAxis < targetS2 - (targetLength * (1 - swapThreshold) / 2) + ) { + return ((mouseOnAxis > targetS1 + targetLength / 2) ? -1 : 1); + } + } + } - /** @returns {HTMLElement|false} */ - function _ghostIsLast(el, evt) { - var lastEl = el.lastElementChild, - rect = lastEl.getBoundingClientRect(); + invert = invert || invertSwap; - // 5 — min delta - // abs — нельзя добавлять, а то глюки при наведении сверху - return (evt.clientY - (rect.top + rect.height) > 5) || - (evt.clientX - (rect.left + rect.width) > 5); + if (invert) { + // Invert of regular + if ( + mouseOnAxis < targetS1 + (targetLength * invertedSwapThreshold / 2) || + mouseOnAxis > targetS2 - (targetLength * invertedSwapThreshold / 2) + ) + { + return ((mouseOnAxis > targetS1 + targetLength / 2) ? 1 : -1); + } + } + + return 0; } @@ -1635,12 +1899,12 @@ return clearTimeout(id); } - // Fixed #973: - _on(document, 'touchmove', function (evt) { - if (Sortable.active) { + function _preventScroll(evt) { + if (Sortable.active && evt.cancelable) { evt.preventDefault(); } - }); + } + // Export utils Sortable.utils = { @@ -1649,7 +1913,7 @@ css: _css, find: _find, is: function (el, selector) { - return !!_closest(el, selector, el); + return !!_closest(el, selector, el, false); }, extend: _extend, throttle: _throttle, @@ -1658,7 +1922,9 @@ clone: _clone, index: _index, nextTick: _nextTick, - cancelNextTick: _cancelNextTick + cancelNextTick: _cancelNextTick, + detectDirection: _detectDirection, + getChild: _getChild }; @@ -1673,6 +1939,6 @@ // Export - Sortable.version = '1.7.0'; + Sortable.version = '1.8.0-rc1'; return Sortable; -}); +}); \ No newline at end of file diff --git a/Sortable.min.js b/Sortable.min.js index 9b39621..4ae0349 100644 --- a/Sortable.min.js +++ b/Sortable.min.js @@ -1,3 +1,3 @@ -/*! Sortable 1.7.0 - MIT | git://github.com/rubaxa/Sortable.git */ +/*! Sortable 1.8.0-rc1 - MIT | git://github.com/SortableJS/Sortable.git */ -!function(t){"use strict";"function"==typeof define&&define.amd?define(t):"undefined"!=typeof module&&void 0!==module.exports?module.exports=t():window.Sortable=t()}(function(){"use strict";if("undefined"==typeof window||!window.document)return function(){throw new Error("Sortable.js requires a window with a document")};var C,E,x,k,N,P,h,v,m,_,B,Y,X,c,o,M,O,d,b,I,t,D={},i=/\s+/g,R=/left|right|inline/,A="Sortable"+(new Date).getTime(),y=window,u=y.document,r=y.parseInt,H=y.setTimeout,e=y.jQuery||y.Zepto,n=y.Polymer,a=!1,l=!1,s="draggable"in u.createElement("div"),f=!navigator.userAgent.match(/(?:Trident.*rv[ :]?11\.|msie)/i)&&((t=u.createElement("x")).style.cssText="pointer-events:auto","auto"===t.style.pointerEvents),L=!1,w=Math.abs,p=Math.min,g=[],T=[],S=function(){return!1},F=it(function(t,e,n){if(n&&e.scroll){var o,i,r,a,l,s,c=n[A],d=e.scrollSensitivity,h=e.scrollSpeed,u=t.clientX,f=t.clientY,p=window.innerWidth,g=window.innerHeight;if(m!==n&&(v=e.scroll,m=n,_=e.scrollFn,!0===v)){v=n;do{if(v.offsetWidth*",ghostClass:"sortable-ghost",chosenClass:"sortable-chosen",dragClass:"sortable-drag",ignore:"a, img",filter:null,preventOnFilter:!0,animation:0,setData:function(t,e){t.setData("Text",e.textContent)},dropBubble:!1,dragoverBubble:!1,dataIdAttr:"data-id",delay:0,touchStartThreshold:r(window.devicePixelRatio,10)||1,forceFallback:!1,fallbackClass:"sortable-fallback",fallbackOnBody:!1,fallbackTolerance:0,fallbackOffset:{x:0,y:0},supportPointer:!1!==j.supportPointer};for(var o in n)!(o in e)&&(e[o]=n[o]);for(var i in W(e),this)"_"===i.charAt(0)&&"function"==typeof this[i]&&(this[i]=this[i].bind(this));this.nativeDraggable=!e.forceFallback&&s,q(t,"mousedown",this._onTapStart),q(t,"touchstart",this._onTapStart),e.supportPointer&&q(t,"pointerdown",this._onTapStart),this.nativeDraggable&&(q(t,"dragover",this),q(t,"dragenter",this)),T.push(this._onDragOver),e.store&&this.sort(e.store.get(this))}function U(t,e){"clone"!==t.lastPullMode&&(e=!0),k&&k.state!==e&&(Q(k,"display",e?"none":""),e||k.state&&(t.options.group.revertClone?(N.insertBefore(k,P),t._animate(C,k)):N.insertBefore(k,C)),k.state=e)}function V(t,e,n){if(t){n=n||u;do{if(">*"===e&&t.parentNode===n||ot(t,e))return t}while(void 0,t=(i=(o=t).host)&&i.nodeType?i:o.parentNode)}var o,i;return null}function q(t,e,n){t.addEventListener(e,n,a)}function z(t,e,n){t.removeEventListener(e,n,a)}function G(t,e,n){if(t)if(t.classList)t.classList[n?"add":"remove"](e);else{var o=(" "+t.className+" ").replace(i," ").replace(" "+e+" "," ");t.className=(o+(n?" "+e:"")).replace(i," ")}}function Q(t,e,n){var o=t&&t.style;if(o){if(void 0===n)return u.defaultView&&u.defaultView.getComputedStyle?n=u.defaultView.getComputedStyle(t,""):t.currentStyle&&(n=t.currentStyle),void 0===e?n:n[e];e in o||(e="-webkit-"+e),o[e]=n+("string"==typeof n?"":"px")}}function Z(t,e,n){if(t){var o=t.getElementsByTagName(e),i=0,r=o.length;if(n)for(;i*"!==e&&!ot(t,e)||n++;return n}function ot(t,e){if(t)try{if(t.matches)return t.matches(e);if(t.msMatchesSelector)return t.msMatchesSelector(e)}catch(t){return!1}return!1}function it(t,e){var n,o;return function(){void 0===n&&(n=arguments,o=this,H(function(){1===n.length?t.call(o,n[0]):t.apply(o,n),n=void 0},e))}}function rt(t,e){if(t&&e)for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}function at(t){return n&&n.dom?n.dom(t).cloneNode(!0):e?e(t).clone(!0)[0]:t.cloneNode(!0)}function lt(t){return H(t,0)}function st(t){return clearTimeout(t)}return j.prototype={constructor:j,_onTapStart:function(t){var e,n=this,o=this.el,i=this.options,r=i.preventOnFilter,a=t.type,l=t.touches&&t.touches[0],s=(l||t).target,c=t.target.shadowRoot&&(t.path&&t.path[0]||t.composedPath&&t.composedPath()[0])||s,d=i.filter;if(function(t){g.length=0;var e=t.getElementsByTagName("input"),n=e.length;for(;n--;){var o=e[n];o.checked&&g.push(o)}}(o),!C&&!(/mousedown|pointerdown/.test(a)&&0!==t.button||i.disabled)&&!c.isContentEditable&&(s=V(s,i.draggable,o))&&h!==s){if(e=nt(s,i.draggable),"function"==typeof d){if(d.call(this,t,s,this))return J(n,c,"filter",s,o,o,e),void(r&&t.preventDefault())}else if(d&&(d=d.split(",").some(function(t){if(t=V(c,t.trim(),o))return J(n,t,"filter",s,o,o,e),!0})))return void(r&&t.preventDefault());i.handle&&!V(c,i.handle,o)||this._prepareDragStart(t,l,s,e)}},_prepareDragStart:function(t,e,n,o){var i,r=this,a=r.el,l=r.options,s=a.ownerDocument;n&&!C&&n.parentNode===a&&(d=t,N=a,E=(C=n).parentNode,P=C.nextSibling,h=n,M=l.group,c=o,this._lastX=(e||t).clientX,this._lastY=(e||t).clientY,C.style["will-change"]="all",i=function(){r._disableDelayedDrag(),C.draggable=r.nativeDraggable,G(C,l.chosenClass,!0),r._triggerDragStart(t,e),J(r,N,"choose",C,N,N,c)},l.ignore.split(",").forEach(function(t){Z(C,t.trim(),$)}),q(s,"mouseup",r._onDrop),q(s,"touchend",r._onDrop),q(s,"touchcancel",r._onDrop),q(s,"selectstart",r),l.supportPointer&&q(s,"pointercancel",r._onDrop),l.delay?(q(s,"mouseup",r._disableDelayedDrag),q(s,"touchend",r._disableDelayedDrag),q(s,"touchcancel",r._disableDelayedDrag),q(s,"mousemove",r._disableDelayedDrag),q(s,"touchmove",r._delayedDragTouchMoveHandler),l.supportPointer&&q(s,"pointermove",r._delayedDragTouchMoveHandler),r._dragStartTimer=H(i,l.delay)):i())},_delayedDragTouchMoveHandler:function(t){p(w(t.clientX-this._lastX),w(t.clientY-this._lastY))>=this.options.touchStartThreshold&&this._disableDelayedDrag()},_disableDelayedDrag:function(){var t=this.el.ownerDocument;clearTimeout(this._dragStartTimer),z(t,"mouseup",this._disableDelayedDrag),z(t,"touchend",this._disableDelayedDrag),z(t,"touchcancel",this._disableDelayedDrag),z(t,"mousemove",this._disableDelayedDrag),z(t,"touchmove",this._disableDelayedDrag),z(t,"pointermove",this._disableDelayedDrag)},_triggerDragStart:function(t,e){(e=e||("touch"==t.pointerType?t:null))?(d={target:C,clientX:e.clientX,clientY:e.clientY},this._onDragStart(d,"touch")):this.nativeDraggable?(q(C,"dragend",this),q(N,"dragstart",this._onDragStart)):this._onDragStart(d,!0);try{u.selection?lt(function(){u.selection.empty()}):window.getSelection().removeAllRanges()}catch(t){}},_dragStarted:function(){if(N&&C){var t=this.options;G(C,t.ghostClass,!0),G(C,t.dragClass,!1),J(j.active=this,N,"start",C,N,N,c)}else this._nulling()},_emulateDragOver:function(){if(b){if(this._lastX===b.clientX&&this._lastY===b.clientY)return;this._lastX=b.clientX,this._lastY=b.clientY,f||Q(x,"display","none");for(var t=u.elementFromPoint(b.clientX,b.clientY),e=t,n=T.length;t&&t.shadowRoot;)e=t=t.shadowRoot.elementFromPoint(b.clientX,b.clientY);if(e)do{if(e[A]){for(;n--;)T[n]({clientX:b.clientX,clientY:b.clientY,target:t,rootEl:e});break}t=e}while(e=e.parentNode);f||Q(x,"display","")}},_onTouchMove:function(t){if(d){var e=this.options,n=e.fallbackTolerance,o=e.fallbackOffset,i=t.touches?t.touches[0]:t,r=i.clientX-d.clientX+o.x,a=i.clientY-d.clientY+o.y,l=t.touches?"translate3d("+r+"px,"+a+"px,0)":"translate("+r+"px,"+a+"px)";if(!j.active){if(n&&p(w(i.clientX-this._lastX),w(i.clientY-this._lastY))C.offsetWidth,_=e.offsetHeight>C.offsetHeight,b=.5<(v?(t.clientX-o.left)/p:(t.clientY-o.top)/g),D=e.nextElementSibling,y=!1;if(v){var w=C.offsetTop,T=e.offsetTop;y=w===T?e.previousElementSibling===C&&!m||b&&m:e.previousElementSibling===C||C.previousElementSibling===e?.5<(t.clientY-o.top)/g:w*",swapThreshold:1,invertSwap:!1,invertedSwapThreshold:null,ghostClass:"sortable-ghost",chosenClass:"sortable-chosen",dragClass:"sortable-drag",ignore:"a, img",filter:null,preventOnFilter:!0,animation:0,setData:function(t,e){t.setData("Text",e.textContent)},dropBubble:!1,dragoverBubble:!1,dataIdAttr:"data-id",delay:0,touchStartThreshold:W(window.devicePixelRatio,10)||1,forceFallback:!1,fallbackClass:"sortable-fallback",fallbackOnBody:!1,fallbackTolerance:0,fallbackOffset:{x:0,y:0},supportPointer:!1!==K.supportPointer&&("PointerEvent"in window||window.navigator&&"msPointerEnabled"in window.navigator)};for(var i in n)!(i in e)&&(e[i]=n[i]);for(var o in"direction"in e||(e.direction=function(){return V(t,e)}),Q(e),null==e.invertedSwapThreshold&&(e.invertedSwapThreshold=e.swapThreshold),this)"_"===o.charAt(0)&&"function"==typeof this[o]&&(this[o]=this[o].bind(this));this.nativeDraggable=!e.forceFallback&&p,tt(t,"mousedown",this._onTapStart),tt(t,"touchstart",this._onTapStart),e.supportPointer&&tt(t,"pointerdown",this._onTapStart),this.nativeDraggable&&(tt(t,"dragover",this),tt(t,"dragenter",this)),b.push(this._onDragOver),e.store&&e.store.get&&this.sort(e.store.get(this)||[])}function $(t,e,n,i){if(t){n=n||f;do{if(">*"===e&&t.parentNode===n||ft(t,e)||i&&t===n)return t;if(t===n)break}while(t=(o=t).host&&o!==f&&o.host.nodeType?o.host:o.parentNode)}var o;return null}function tt(t,e,n){t.addEventListener(e,n,a)}function et(t,e,n){t.removeEventListener(e,n,a)}function nt(t,e,n){if(t&&e)if(t.classList)t.classList[n?"add":"remove"](e);else{var i=(" "+t.className+" ").replace(r," ").replace(" "+e+" "," ");t.className=(i+(n?" "+e:"")).replace(r," ")}}function it(t,e,n){var i=t&&t.style;if(i){if(void 0===n)return f.defaultView&&f.defaultView.getComputedStyle?n=f.defaultView.getComputedStyle(t,""):t.currentStyle&&(n=t.currentStyle),void 0===e?n:n[e];e in i||(e="-webkit-"+e),i[e]=n+("string"==typeof n?"":"px")}}function ot(t,e,n){if(t){var i=t.getElementsByTagName(e),o=0,r=i.length;if(n)for(;o*"!==e&&!ft(t,e)||n++;return n}function ft(t,e){if(t)try{if(t.matches)return t.matches(e);if(t.msMatchesSelector)return t.msMatchesSelector(e)}catch(t){return!1}return!1}function pt(n,i){return function(){if(!o){var t=arguments,e=this;o=U(function(){1===t.length?n.call(e,t[0]):n.apply(e,t),o=void 0},i)}}}function gt(t,e){if(t&&e)for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}function vt(t){return n&&n.dom?n.dom(t).cloneNode(!0):e?e(t).clone(!0)[0]:t.cloneNode(!0)}function mt(t){return U(t,0)}function _t(t){return clearTimeout(t)}function bt(t){K.active&&t.cancelable&&t.preventDefault()}return K.prototype={constructor:K,_isAligned:!0,_computeIsAligned:function(t,e){var n,i,o,r,a,l,s;v||T&&T.parentNode===this.el&&(!0!==e&&!1!==e&&(e=!!$(t.target,null,T,!0)),this._isAligned=!M&&(e||this._isAligned&&(n=t.clientX,i=t.clientY,this.el,o=this._getDirection(t,null),this.options,r=R||T.getBoundingClientRect(),a="vertical"===o?r.left:r.top,l="vertical"===o?r.right:r.bottom,a<(s="vertical"===o?n:i)&&s=this.options.touchStartThreshold&&this._disableDelayedDrag()},_disableDelayedDrag:function(){var t=this.el.ownerDocument;clearTimeout(this._dragStartTimer),et(t,"mouseup",this._disableDelayedDrag),et(t,"touchend",this._disableDelayedDrag),et(t,"touchcancel",this._disableDelayedDrag),et(t,"mousemove",this._delayedDragTouchMoveHandler),et(t,"touchmove",this._delayedDragTouchMoveHandler),et(t,"pointermove",this._delayedDragTouchMoveHandler)},_triggerDragStart:function(t,e){(e=e||("touch"==t.pointerType?t:null))?(u={target:T,clientX:e.clientX,clientY:e.clientY},this._onDragStart(u,"touch")):this.nativeDraggable?(tt(T,"dragend",this),tt(A,"dragstart",this._onDragStart)):this._onDragStart(u,!0);try{f.selection?mt(function(){f.selection.empty()}):window.getSelection().removeAllRanges()}catch(t){}},_dragStarted:function(){if(A&&T){this.nativeDraggable&&(tt(f,"dragover",this._handleAutoScroll),tt(f,"dragover",J));var t=this.options;nt(T,t.dragClass,!1),nt(T,t.ghostClass,!0),it(T,"transform",""),(K.active=this)._isAligned=!0,rt(this,A,"start",T,A,A,c)}else this._nulling()},_emulateDragOver:function(t){if(C){if(this._lastX===C.clientX&&this._lastY===C.clientY&&!t)return;this._lastX=C.clientX,this._lastY=C.clientY,g||it(E,"display","none");for(var e=f.elementFromPoint(C.clientX,C.clientY),n=e,i=!!$(e,null,T,!0);e&&e.shadowRoot;)n=e=e.shadowRoot.elementFromPoint(C.clientX,C.clientY);if(n)do{if(n[L]){for(var o=b.length;o--;)b[o]({clientX:C.clientX,clientY:C.clientY,target:e,rootEl:n});if(!this.options.dragoverBubble)break}e=n}while(n=n.parentNode);T.parentNode[L]._computeIsAligned(C,i),g||it(E,"display","")}},_onTouchMove:function(t){if(u){var e=this.options,n=e.fallbackTolerance,i=e.fallbackOffset,o=t.touches?t.touches[0]:t,r=o.clientX-u.clientX+i.x,a=o.clientY-u.clientY+i.y,l=t.touches?"translate3d("+r+"px,"+a+"px,0)":"translate("+r+"px,"+a+"px)";if(this.options.supportPointer&&"touchmove"===t.type)return;if(!K.active){if(n&&m(z(o.clientX-this._lastX),z(o.clientY-this._lastY))" + "RubaXa ", + "owenm " ], "description": "Minimalist library for reorderable drag-and-drop lists on modern browsers and touch devices. No jQuery.", "keywords": [ diff --git a/component.json b/component.json index 028c3b7..88fe5ef 100644 --- a/component.json +++ b/component.json @@ -1,11 +1,12 @@ { "name": "Sortable", "main": "Sortable.js", - "version": "1.7.0", - "homepage": "http://rubaxa.github.io/Sortable/", - "repo": "RubaXa/Sortable", + "version": "1.8.0-rc1", + "homepage": "http://SortableJS.github.io/Sortable/", + "repo": "SortableJS/Sortable", "authors": [ - "RubaXa " + "RubaXa ", + "owenm " ], "description": "Minimalist library for reorderable drag-and-drop lists on modern browsers and touch devices. No jQuery.", "keywords": [ diff --git a/package.json b/package.json index b9566b4..bba8c69 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "sortablejs", "exportName": "Sortable", - "version": "1.7.0", + "version": "1.8.0-rc1", "devDependencies": { "grunt": "*", "grunt-contrib-jshint": "*", @@ -18,9 +18,13 @@ "prepublish": "./node_modules/grunt/bin/grunt", "http-server": "http-server -s ./" }, + "contributors" : [ + "Konstantin Lebedev ", + "Owen Mills " + ], "repository": { "type": "git", - "url": "git://github.com/rubaxa/Sortable.git" + "url": "git://github.com/SortableJS/Sortable.git" }, "files": [ "Sortable.js", @@ -34,9 +38,9 @@ "angular", "ng-sortable", "react", + "vue", "mixin" ], - "author": "Konstantin Lebedev ", "license": "MIT", "spm": { "main": "Sortable.js", -- GitLab