From 34527d76e232ab2f5a764a2f8079add1ee61d3fd Mon Sep 17 00:00:00 2001 From: Harvey Kandola Date: Mon, 17 Jul 2017 11:50:29 +0100 Subject: [PATCH] upgraded sortable.js lib --- app/app/utils/net.js | 1 + app/vendor/sortable.js | 247 +++++++++++++++++++++++++++++------------ jsconfig.json | 2 +- 3 files changed, 179 insertions(+), 71 deletions(-) diff --git a/app/app/utils/net.js b/app/app/utils/net.js index e6919edd..ea49759e 100644 --- a/app/app/utils/net.js +++ b/app/app/utils/net.js @@ -44,6 +44,7 @@ function isAjaxAccessError(reason) { return false; } + // Sometimes we get not error code back so we detect failure to get all spaces for user. if (reason.message === 'Ajax authorization failed') { return true; } diff --git a/app/vendor/sortable.js b/app/vendor/sortable.js index e0c590a9..7617360d 100644 --- a/app/vendor/sortable.js +++ b/app/vendor/sortable.js @@ -13,10 +13,6 @@ else if (typeof module != "undefined" && typeof module.exports != "undefined") { module.exports = factory(); } - else if (typeof Package !== "undefined") { - //noinspection JSUnresolvedVariable - Sortable = factory(); // export for Meteor.js - } else { /* jshint sub:true */ window["Sortable"] = factory(); @@ -36,6 +32,7 @@ cloneEl, rootEl, nextEl, + lastDownEl, scrollEl, scrollParentEl, @@ -59,7 +56,8 @@ moved, /** @const */ - RSPACE = /\s+/g, + R_SPACE = /\s+/g, + R_FLOAT = /left|right|inline/, expando = 'Sortable' + (new Date).getTime(), @@ -70,6 +68,8 @@ $ = win.jQuery || win.Zepto, Polymer = win.Polymer, + captureMode = false, + supportDraggable = !!('draggable' in document.createElement('div')), supportCssPointerEvents = (function (el) { // false when IE11 @@ -85,14 +85,15 @@ abs = Math.abs, min = Math.min, - slice = [].slice, + savedInputChecked = [], touchDragOverListeners = [], _autoScroll = _throttle(function (/**Event*/evt, /**Object*/options, /**HTMLElement*/rootEl) { // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521 if (rootEl && options.scroll) { - var el, + var _this = rootEl[expando], + el, rect, sens = options.scrollSensitivity, speed = options.scrollSpeed, @@ -207,13 +208,13 @@ group.name = originalGroup.name; group.checkPull = toFn(originalGroup.pull, true); group.checkPut = toFn(originalGroup.put); + group.revertClone = originalGroup.revertClone; options.group = group; } ; - /** * @class Sortable * @param {HTMLElement} el @@ -231,7 +232,6 @@ // Export instance el[expando] = this; - // Default options var defaults = { group: Math.random(), @@ -248,6 +248,7 @@ dragClass: 'sortable-drag', ignore: 'a, img', filter: null, + preventOnFilter: true, animation: 0, setData: function (dataTransfer, dragEl) { dataTransfer.setData('Text', dragEl.textContent); @@ -305,6 +306,7 @@ var _this = this, el = this.el, options = this.options, + preventOnFilter = options.preventOnFilter, type = evt.type, touch = evt.touches && evt.touches[0], target = (touch || evt).target, @@ -312,18 +314,18 @@ filter = options.filter, startIndex; + _saveInputCheckedState(el); + + // Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group. if (dragEl) { return; } - if (type === 'mousedown' && evt.button !== 0 || options.disabled) { + if (/mousedown|pointerdown/.test(type) && evt.button !== 0 || options.disabled) { return; // only left button or enabled } - if (options.handle && !_closest(originalTarget, options.handle, el)) { - return; - } target = _closest(target, options.draggable, el); @@ -331,6 +333,11 @@ return; } + if (lastDownEl === target) { + // Ignoring duplicate `down` + return; + } + // Get the index of the dragged element within its parent startIndex = _index(target, options.draggable); @@ -338,7 +345,7 @@ if (typeof filter === 'function') { if (filter.call(this, evt, target, this)) { _dispatchEvent(_this, originalTarget, 'filter', target, el, startIndex); - evt.preventDefault(); + preventOnFilter && evt.preventDefault(); return; // cancel dnd } } @@ -353,11 +360,15 @@ }); if (filter) { - evt.preventDefault(); + preventOnFilter && evt.preventDefault(); return; // cancel dnd } } + if (options.handle && !_closest(originalTarget, options.handle, el)) { + return; + } + // Prepare `dragstart` this._prepareDragStart(evt, touch, target, startIndex); }, @@ -376,6 +387,7 @@ dragEl = target; parentEl = dragEl.parentNode; nextEl = dragEl.nextSibling; + lastDownEl = target; activeGroup = options.group; oldIndex = startIndex; @@ -411,6 +423,7 @@ _on(ownerDocument, 'touchend', _this._onDrop); _on(ownerDocument, 'touchcancel', _this._onDrop); _on(ownerDocument, 'pointercancel', _this._onDrop); + _on(ownerDocument, 'selectstart', _this); if (options.delay) { // If the user moves the pointer or let go the click or touch @@ -427,6 +440,8 @@ } else { dragStartFn(); } + + } }, @@ -444,6 +459,7 @@ _triggerDragStart: function (/** Event */evt, /** Touch */touch) { touch = touch || (evt.pointerType == 'touch' ? evt : null); + if (touch) { // Touch device support tapEvt = { @@ -487,6 +503,8 @@ // Drag start event _dispatchEvent(this, rootEl, 'start', dragEl, rootEl, oldIndex); + } else { + this._nulling(); } }, @@ -608,9 +626,15 @@ this._offUpEvents(); - if (activeGroup.checkPull(this, this, dragEl, evt) == 'clone') { + if (activeGroup.checkPull(this, this, dragEl, evt)) { cloneEl = _clone(dragEl); + + cloneEl.draggable = false; + cloneEl.style['will-change'] = ''; + _css(cloneEl, 'display', 'none'); + _toggleClass(cloneEl, this.options.chosenClass, false); + rootEl.insertBefore(cloneEl, dragEl); _dispatchEvent(this, rootEl, 'clone', dragEl); } @@ -654,6 +678,7 @@ group = options.group, activeSortable = Sortable.active, isOwner = (activeGroup === group), + isMovingBetweenSortable = false, canSort = options.sort; if (evt.preventDefault !== void 0) { @@ -661,14 +686,21 @@ !options.dragoverBubble && evt.stopPropagation(); } + if (dragEl.animated) { + return; + } + moved = true; - if (activeGroup && !options.disabled && + if (activeSortable && !options.disabled && (isOwner ? canSort || (revert = !rootEl.contains(dragEl)) // Reverting item into the original list : ( putSortable === this || - activeGroup.checkPull(this, activeSortable, dragEl, evt) && group.checkPut(this, activeSortable, dragEl, evt) + ( + (activeSortable.lastPullMode = activeGroup.checkPull(this, activeSortable, dragEl, evt)) && + group.checkPut(this, activeSortable, dragEl, evt) + ) ) ) && (evt.rootEl === void 0 || evt.rootEl === this.el) // touch fallback @@ -682,10 +714,14 @@ target = _closest(evt.target, options.draggable, el); dragRect = dragEl.getBoundingClientRect(); - putSortable = this; + + if (putSortable !== this) { + putSortable = this; + isMovingBetweenSortable = true; + } if (revert) { - _cloneHide(true); + _cloneHide(activeSortable, true); parentEl = rootEl; // actualization if (cloneEl || nextEl) { @@ -700,8 +736,13 @@ if ((el.children.length === 0) || (el.children[0] === ghostEl) || - (el === evt.target) && (target = _ghostIsLast(el, evt)) + (el === evt.target) && (_ghostIsLast(el, evt)) ) { + //assign target only if condition is true + if (el.children.length !== 0 && el.children[0] !== ghostEl && el === evt.target) { + target = el.lastElementChild; + } + if (target) { if (target.animated) { return; @@ -710,7 +751,7 @@ targetRect = target.getBoundingClientRect(); } - _cloneHide(isOwner); + _cloneHide(activeSortable, isOwner); if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt) !== false) { if (!dragEl.contains(el)) { @@ -733,40 +774,42 @@ var width = targetRect.right - targetRect.left, height = targetRect.bottom - targetRect.top, - floating = /left|right|inline/.test(lastCSS.cssFloat + lastCSS.display) + 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, - moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt), - after + 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; + } + + var moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, after); + if (moveVector !== false) { - _silent = true; - setTimeout(_unsilent, 30); - - _cloneHide(isOwner); - if (moveVector === 1 || moveVector === -1) { after = (moveVector === 1); } - else 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 { - after = (nextSibling !== dragEl) && !isLong || halfway && isLong; - } + _silent = true; + setTimeout(_unsilent, 30); + + _cloneHide(activeSortable, isOwner); if (!dragEl.contains(el)) { if (after && !nextSibling) { @@ -791,6 +834,10 @@ if (ms) { var currentRect = target.getBoundingClientRect(); + if (prevRect.nodeType === 1) { + prevRect = prevRect.getBoundingClientRect(); + } + _css(target, 'transition', 'none'); _css(target, 'transform', 'translate3d(' + (prevRect.left - currentRect.left) + 'px,' @@ -820,6 +867,8 @@ _off(ownerDocument, 'touchend', this._onDrop); _off(ownerDocument, 'pointerup', this._onDrop); _off(ownerDocument, 'touchcancel', this._onDrop); + _off(ownerDocument, 'pointercancel', this._onDrop); + _off(ownerDocument, 'selectstart', this); }, _onDrop: function (/**Event*/evt) { @@ -846,7 +895,12 @@ !options.dropBubble && evt.stopPropagation(); } - ghostEl && ghostEl.parentNode.removeChild(ghostEl); + ghostEl && ghostEl.parentNode && ghostEl.parentNode.removeChild(ghostEl); + + if (rootEl === parentEl || Sortable.active.lastPullMode !== 'clone') { + // Remove clone + cloneEl && cloneEl.parentNode && cloneEl.parentNode.removeChild(cloneEl); + } if (dragEl) { if (this.nativeDraggable) { @@ -860,11 +914,13 @@ _toggleClass(dragEl, this.options.ghostClass, false); _toggleClass(dragEl, this.options.chosenClass, false); + // Drag stop event + _dispatchEvent(this, rootEl, 'unchoose', dragEl, rootEl, oldIndex); + if (rootEl !== parentEl) { newIndex = _index(dragEl, options.draggable); if (newIndex >= 0) { - // Add event _dispatchEvent(null, parentEl, 'add', dragEl, rootEl, oldIndex, newIndex); @@ -877,9 +933,6 @@ } } else { - // Remove clone - cloneEl && cloneEl.parentNode.removeChild(cloneEl); - if (dragEl.nextSibling !== nextEl) { // Get the index of the dragged element within its parent newIndex = _index(dragEl, options.draggable); @@ -917,6 +970,7 @@ ghostEl = nextEl = cloneEl = + lastDownEl = scrollEl = scrollParentEl = @@ -933,19 +987,31 @@ putSortable = activeGroup = Sortable.active = null; + + savedInputChecked.forEach(function (el) { + el.checked = true; + }); + savedInputChecked.length = 0; }, handleEvent: function (/**Event*/evt) { - var type = evt.type; + switch (evt.type) { + case 'drop': + case 'dragend': + this._onDrop(evt); + break; - if (type === 'dragover' || type === 'dragenter') { - if (dragEl) { - this._onDragOver(evt); - _globalDragOver(evt); - } - } - else if (type === 'drop' || type === 'dragend') { - this._onDrop(evt); + case 'dragover': + case 'dragenter': + if (dragEl) { + this._onDragOver(evt); + _globalDragOver(evt); + } + break; + + case 'selectstart': + evt.preventDefault(); + break; } }, @@ -1069,10 +1135,25 @@ }; - function _cloneHide(state) { + function _cloneHide(sortable, state) { + if (sortable.lastPullMode !== 'clone') { + state = true; + } + if (cloneEl && (cloneEl.state !== state)) { _css(cloneEl, 'display', state ? 'none' : ''); - !state && cloneEl.state && rootEl.insertBefore(cloneEl, dragEl); + + if (!state) { + if (cloneEl.state) { + if (sortable.options.group.revertClone) { + rootEl.insertBefore(cloneEl, nextEl); + sortable._animate(dragEl, cloneEl); + } else { + rootEl.insertBefore(cloneEl, dragEl); + } + } + } + cloneEl.state = state; } } @@ -1110,12 +1191,12 @@ function _on(el, event, fn) { - el.addEventListener(event, fn, false); + el.addEventListener(event, fn, captureMode); } function _off(el, event, fn) { - el.removeEventListener(event, fn, false); + el.removeEventListener(event, fn, captureMode); } @@ -1125,8 +1206,8 @@ el.classList[state ? 'add' : 'remove'](name); } else { - var className = (' ' + el.className + ' ').replace(RSPACE, ' ').replace(' ' + name + ' ', ' '); - el.className = (className + (state ? ' ' + name : '')).replace(RSPACE, ' '); + var className = (' ' + el.className + ' ').replace(R_SPACE, ' ').replace(' ' + name + ' ', ' '); + el.className = (className + (state ? ' ' + name : '')).replace(R_SPACE, ' '); } } } @@ -1200,7 +1281,7 @@ } - function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvt) { + function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvt, willInsertAfter) { var evt, sortable = fromEl[expando], onMoveFn = sortable.options.onMove, @@ -1215,6 +1296,7 @@ evt.draggedRect = dragRect; evt.related = targetEl || toEl; evt.relatedRect = targetRect || toEl.getBoundingClientRect(); + evt.willInsertAfter = willInsertAfter; fromEl.dispatchEvent(evt); @@ -1243,10 +1325,8 @@ // 5 — min delta // abs — нельзя добавлять, а то глюки при наведении сверху - return ( - (evt.clientY - (rect.top + rect.height) > 5) || - (evt.clientX - (rect.right + rect.width) > 5) - ) && lastEl; + return (evt.clientY - (rect.top + rect.height) > 5) || + (evt.clientX - (rect.left + rect.width) > 5); } @@ -1349,6 +1429,33 @@ ); } + function _saveInputCheckedState(root) { + var inputs = root.getElementsByTagName('input'); + var idx = inputs.length; + + while (idx--) { + var el = inputs[idx]; + el.checked && savedInputChecked.push(el); + } + } + + // Fixed #973: + _on(document, 'touchmove', function (evt) { + if (Sortable.active) { + evt.preventDefault(); + } + }); + + try { + window.addEventListener('test', null, Object.defineProperty({}, 'passive', { + get: function () { + captureMode = { + capture: false, + passive: false + }; + } + })); + } catch (err) {} // Export utils Sortable.utils = { @@ -1379,6 +1486,6 @@ // Export - Sortable.version = '1.5.0-rc1'; + Sortable.version = '1.6.0'; return Sortable; }); diff --git a/jsconfig.json b/jsconfig.json index dc944605..de7d667c 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -4,4 +4,4 @@ "experimentalDecorators": true }, "exclude": ["node_modules", "bower_components", "tmp", "vendor", ".git", "dist", "dist-prod"] -} \ No newline at end of file +}