From 38e4d8739285deabb71469730bdf35065c874e55 Mon Sep 17 00:00:00 2001 From: Owen Mills Date: Sat, 13 Jan 2024 17:36:57 +0000 Subject: [PATCH] #2339: Use child containing rect for ghostIsLast & ghostIsFirst --- src/Sortable.js | 36 ++++++++++++++++++------------------ src/utils.js | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/Sortable.js b/src/Sortable.js index 8147c97d5..74045d4f4 100644 --- a/src/Sortable.js +++ b/src/Sortable.js @@ -35,7 +35,7 @@ import { scrollBy, clone, expando, - getContentRect + getChildContainingRectFromElement } from './utils.js'; @@ -1790,22 +1790,22 @@ function _unsilent() { function _ghostIsFirst(evt, vertical, sortable) { let firstElRect = getRect(getChild(sortable.el, 0, sortable.options, true)); - const sortableContentRect = getContentRect(sortable.el); + const childContainingRect = getChildContainingRectFromElement(sortable.el, sortable.options, ghostEl); const spacer = 10; return vertical ? - (evt.clientX < sortableContentRect.left - spacer || evt.clientY < firstElRect.top && evt.clientX < firstElRect.right) : - (evt.clientY < sortableContentRect.top - spacer || evt.clientY < firstElRect.bottom && evt.clientX < firstElRect.left) + (evt.clientX < childContainingRect.left - spacer || evt.clientY < firstElRect.top && evt.clientX < firstElRect.right) : + (evt.clientY < childContainingRect.top - spacer || evt.clientY < firstElRect.bottom && evt.clientX < firstElRect.left) } function _ghostIsLast(evt, vertical, sortable) { const lastElRect = getRect(lastChild(sortable.el, sortable.options.draggable)); - const sortableContentRect = getContentRect(sortable.el); + const childContainingRect = getChildContainingRectFromElement(sortable.el, sortable.options, ghostEl); const spacer = 10; return vertical ? - (evt.clientX > sortableContentRect.right + spacer || evt.clientY > lastElRect.bottom && evt.clientX > lastElRect.left) : - (evt.clientY > sortableContentRect.bottom + spacer || evt.clientX > lastElRect.right && evt.clientY > lastElRect.top); + (evt.clientX > childContainingRect.right + spacer || evt.clientY > lastElRect.bottom && evt.clientX > lastElRect.left) : + (evt.clientY > childContainingRect.bottom + spacer || evt.clientX > lastElRect.right && evt.clientY > lastElRect.top); } function _getSwapDirection(evt, target, targetRect, vertical, swapThreshold, invertedSwapThreshold, invertSwap, isLastTarget) { @@ -1944,23 +1944,23 @@ if (documentExists) { // Export utils Sortable.utils = { - on: on, - off: off, - css: css, - find: find, + on, + off, + css, + find, is: function (el, selector) { return !!closest(el, selector, el, false); }, - extend: extend, - throttle: throttle, - closest: closest, - toggleClass: toggleClass, - clone: clone, - index: index, + extend, + throttle, + closest, + toggleClass, + clone, + index, nextTick: _nextTick, cancelNextTick: _cancelNextTick, detectDirection: _detectDirection, - getChild: getChild + getChild }; diff --git a/src/utils.js b/src/utils.js index b7649629e..c26c5bb90 100644 --- a/src/utils.js +++ b/src/utils.js @@ -541,6 +541,23 @@ function unsetRect(el) { css(el, 'height', ''); } +function getChildContainingRectFromElement(container, options, ghostEl) { + const rect = {}; + + Array.from(container.children).forEach(child => { + if (!closest(child, options.draggable, container, false) || child.animated || child === ghostEl) return; + const childRect = getRect(child); + rect.left = Math.min(rect.left ?? Infinity, childRect.left); + rect.top = Math.min(rect.top ?? Infinity, childRect.top); + rect.right = Math.max(rect.right ?? -Infinity, childRect.right); + rect.bottom = Math.max(rect.bottom ?? -Infinity, childRect.bottom); + }); + rect.width = rect.right - rect.left; + rect.height = rect.bottom - rect.top; + rect.x = rect.left; + rect.y = rect.top; + return rect; +} const expando = 'Sortable' + (new Date).getTime(); @@ -573,5 +590,6 @@ export { setRect, unsetRect, getContentRect, + getChildContainingRectFromElement, expando };