diff --git a/README.md b/README.md index 201f94222..c46a5257f 100644 --- a/README.md +++ b/README.md @@ -146,6 +146,8 @@ var sortable = new Sortable(el, { evt.from; // previous list evt.oldIndex; // element's old index within old parent evt.newIndex; // element's new index within new parent + evt.oldDraggableIndex; // element's old index within old parent, only counting draggable elements + evt.newDraggableIndex; // element's new index within new parent, only counting draggable elements evt.clone // the clone element evt.pullMode; // when item is in another sortable: `"clone"` if cloning, `true` if moving }, @@ -531,6 +533,8 @@ Demo: https://jsbin.com/becavoj/edit?js,output - clone:`HTMLElement` - oldIndex:`Number|undefined` — old index within parent - newIndex:`Number|undefined` — new index within parent + - oldDraggableIndex: `Number|undefined` — old index within parent, only counting draggable elements + - newDraggableIndex: `Number|undefined` — new index within parent, only counting draggable elements - pullMode:`String|Boolean|undefined` — Pull mode if dragging into another sortable (`"clone"`, `true`, or `false`), otherwise undefined diff --git a/Sortable.js b/Sortable.js index d355813dc..d1e9cd416 100644 --- a/Sortable.js +++ b/Sortable.js @@ -41,6 +41,8 @@ oldIndex, newIndex, + oldDraggableIndex, + newDraggableIndex, activeGroup, putSortable, @@ -633,7 +635,8 @@ target = (touch || evt).target, originalTarget = evt.target.shadowRoot && ((evt.path && evt.path[0]) || (evt.composedPath && evt.composedPath()[0])) || target, filter = options.filter, - startIndex; + startIndex, + startDraggableIndex; _saveInputCheckedState(el); @@ -660,12 +663,13 @@ } // Get the index of the dragged element within its parent - startIndex = _index(target, options.draggable); + startIndex = _index(target); + startDraggableIndex = _index(target, options.draggable); // Check filter if (typeof filter === 'function') { if (filter.call(this, evt, target, this)) { - _dispatchEvent(_this, originalTarget, 'filter', target, el, el, startIndex); + _dispatchEvent(_this, originalTarget, 'filter', target, el, el, startIndex, undefined, startDraggableIndex); preventOnFilter && evt.cancelable && evt.preventDefault(); return; // cancel dnd } @@ -675,7 +679,7 @@ criteria = _closest(originalTarget, criteria.trim(), el, false); if (criteria) { - _dispatchEvent(_this, criteria, 'filter', target, el, el, startIndex); + _dispatchEvent(_this, criteria, 'filter', target, el, el, startIndex, undefined, startDraggableIndex); return true; } }); @@ -691,7 +695,7 @@ } // Prepare `dragstart` - this._prepareDragStart(evt, touch, target, startIndex); + this._prepareDragStart(evt, touch, target, startIndex, startDraggableIndex); }, @@ -747,7 +751,7 @@ } }, - _prepareDragStart: function (/** Event */evt, /** Touch */touch, /** HTMLElement */target, /** Number */startIndex) { + _prepareDragStart: function (/** Event */evt, /** Touch */touch, /** HTMLElement */target, /** Number */startIndex, /** Number */startDraggableIndex) { var _this = this, el = _this.el, options = _this.options, @@ -762,6 +766,7 @@ lastDownEl = target; activeGroup = options.group; oldIndex = startIndex; + oldDraggableIndex = startDraggableIndex; tapEvt = { target: dragEl, @@ -790,7 +795,7 @@ _this._triggerDragStart(evt, touch); // Drag start event - _dispatchEvent(_this, rootEl, 'choose', dragEl, rootEl, rootEl, oldIndex); + _dispatchEvent(_this, rootEl, 'choose', dragEl, rootEl, rootEl, oldIndex, undefined, oldDraggableIndex); // Chosen item _toggleClass(dragEl, options.chosenClass, true); @@ -914,7 +919,7 @@ fallback && this._appendGhost(); // Drag start event - _dispatchEvent(this, rootEl, 'start', dragEl, rootEl, rootEl, oldIndex, undefined, evt); + _dispatchEvent(this, rootEl, 'start', dragEl, rootEl, rootEl, oldIndex, undefined, oldDraggableIndex, undefined, evt); } else { this._nulling(); } @@ -1189,7 +1194,7 @@ // Call when dragEl has been inserted function changed() { - _dispatchEvent(_this, rootEl, 'change', target, el, rootEl, oldIndex, _index(dragEl, options.draggable), evt); + _dispatchEvent(_this, rootEl, 'change', target, el, rootEl, oldIndex, _index(dragEl), oldDraggableIndex, _index(dragEl, options.draggable), evt); } @@ -1203,7 +1208,7 @@ target = _closest(target, options.draggable, el, true); // target is dragEl or target is animated - if (!!_closest(evt.target, null, dragEl, true) || target.animated) { + if (dragEl.contains(evt.target) || target.animated) { return completed(false); } @@ -1493,21 +1498,22 @@ _toggleClass(dragEl, this.options.chosenClass, false); // Drag stop event - _dispatchEvent(this, rootEl, 'unchoose', dragEl, parentEl, rootEl, oldIndex, null, evt); + _dispatchEvent(this, rootEl, 'unchoose', dragEl, parentEl, rootEl, oldIndex, null, oldDraggableIndex, null, evt); if (rootEl !== parentEl) { - newIndex = _index(dragEl, options.draggable); + newIndex = _index(dragEl); + newDraggableIndex = _index(dragEl, options.draggable); if (newIndex >= 0) { // Add event - _dispatchEvent(null, parentEl, 'add', dragEl, parentEl, rootEl, oldIndex, newIndex, evt); + _dispatchEvent(null, parentEl, 'add', dragEl, parentEl, rootEl, oldIndex, newIndex, oldDraggableIndex, newDraggableIndex, evt); // Remove event - _dispatchEvent(this, rootEl, 'remove', dragEl, parentEl, rootEl, oldIndex, newIndex, evt); + _dispatchEvent(this, rootEl, 'remove', dragEl, parentEl, rootEl, oldIndex, newIndex, oldDraggableIndex, newDraggableIndex, evt); // drag from one list and drop into another - _dispatchEvent(null, parentEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex, evt); - _dispatchEvent(this, rootEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex, evt); + _dispatchEvent(null, parentEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex, oldDraggableIndex, newDraggableIndex, evt); + _dispatchEvent(this, rootEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex, oldDraggableIndex, newDraggableIndex, evt); } putSortable && putSortable.save(); @@ -1515,12 +1521,13 @@ else { if (dragEl.nextSibling !== nextEl) { // Get the index of the dragged element within its parent - newIndex = _index(dragEl, options.draggable); + newIndex = _index(dragEl); + newDraggableIndex = _index(dragEl, options.draggable); if (newIndex >= 0) { // drag & drop within the same list - _dispatchEvent(this, rootEl, 'update', dragEl, parentEl, rootEl, oldIndex, newIndex, evt); - _dispatchEvent(this, rootEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex, evt); + _dispatchEvent(this, rootEl, 'update', dragEl, parentEl, rootEl, oldIndex, newIndex, oldDraggableIndex, newDraggableIndex, evt); + _dispatchEvent(this, rootEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex, oldDraggableIndex, newDraggableIndex, evt); } } } @@ -1529,8 +1536,9 @@ /* jshint eqnull:true */ if (newIndex == null || newIndex === -1) { newIndex = oldIndex; + newDraggableIndex = oldDraggableIndex; } - _dispatchEvent(this, rootEl, 'end', dragEl, parentEl, rootEl, oldIndex, newIndex, evt); + _dispatchEvent(this, rootEl, 'end', dragEl, parentEl, rootEl, oldIndex, newIndex, oldDraggableIndex, newDraggableIndex, evt); // Save sorting this.save(); @@ -1763,7 +1771,8 @@ if ( selector != null && ( - selector[0] === '>' && el.parentNode === ctx && _matches(el, selector.substring(1)) || + selector[0] === '>' ? + el.parentNode === ctx && _matches(el, selector) : _matches(el, selector) ) || includeCTX && el === ctx @@ -1881,7 +1890,13 @@ - function _dispatchEvent(sortable, rootEl, name, targetEl, toEl, fromEl, startIndex, newIndex, originalEvt) { + function _dispatchEvent( + sortable, rootEl, name, + targetEl, toEl, fromEl, + startIndex, newIndex, + startDraggableIndex, newDraggableIndex, + originalEvt + ) { sortable = (sortable || rootEl[expando]); var evt, options = sortable.options, @@ -1905,6 +1920,9 @@ evt.oldIndex = startIndex; evt.newIndex = newIndex; + evt.oldDraggableIndex = startDraggableIndex; + evt.newDraggableIndex = newDraggableIndex; + evt.originalEvent = originalEvt; evt.pullMode = putSortable ? putSortable.lastPutMode : undefined; @@ -2149,7 +2167,7 @@ } while (el && (el = el.previousElementSibling)) { - if ((el.nodeName.toUpperCase() !== 'TEMPLATE') && el !== cloneEl) { + if ((el.nodeName.toUpperCase() !== 'TEMPLATE') && el !== cloneEl && (!selector || _matches(el, selector))) { index++; } } @@ -2158,6 +2176,10 @@ } function _matches(/**HTMLElement*/el, /**String*/selector) { + if (!selector) return; + + selector[0] === '>' && (selector = selector.substring(1)); + if (el) { try { if (el.matches) {