diff --git a/README.md b/README.md index 755afcb..26c1938 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,7 @@ var container = SmoothDnD(containerElement, options); |dragBeginDelay|number| `0` (`200` for touch devices)|Time in milisecond. Delay to start dragging after item is pressed. Moving cursor before the delay more than 5px will cancel dragging. |animationDuration|number|`250`|Animation duration in milisecond. To be consistent this animation duration will be applied to both drop and reorder animations.| |autoScrollEnabled|boolean|`true`|First scrollable parent will scroll automatically if dragging item is close to boundaries. +|disableScrollOverlapDetection|boolean|`false`|Will detect what elements overlap and only scroll on the direct element you're dragging over. Disabling this will scroll on all scrollable elements at the same time. |dragClass|string|`undefined`|Class to be added to the ghost item being dragged. The class will be added after it's added to the DOM so any transition in the class will be applied as intended. |dropClass|string|`undefined`|Class to be added to the ghost item just before the drop animation begins.| |removeOnDropOut|boolean|`undefined`|When set true onDrop will be called with a removedIndex if you drop element out of any relevant container| @@ -212,4 +213,4 @@ The function to be called by the relevant container whenever a dragged item leav function onDragLeave() { ... } -``` \ No newline at end of file +``` diff --git a/src/defaults.ts b/src/defaults.ts index 74eedbd..29f531b 100644 --- a/src/defaults.ts +++ b/src/defaults.ts @@ -7,6 +7,7 @@ export const defaultOptions: ContainerOptions = { getChildPayload: undefined, animationDuration: 250, autoScrollEnabled: true, + disableScrollOverlapDetection: false, shouldAcceptDrop: undefined, shouldAnimateDrop: undefined, -}; \ No newline at end of file +}; diff --git a/src/exportTypes.ts b/src/exportTypes.ts index db1be3f..b1d17c1 100644 --- a/src/exportTypes.ts +++ b/src/exportTypes.ts @@ -7,6 +7,7 @@ export type SmoothDnDCreator = ((element: HTMLElement, options?: ContainerOption dropHandler?: any; wrapChild?: boolean; maxScrollSpeed?: number; + disableScrollOverlapDetection?: boolean; useTransformForGhost?: boolean; cancelDrag: () => void; isDragging: () => boolean; @@ -45,6 +46,7 @@ export interface ContainerOptions { dragBeginDelay?: number; animationDuration?: number; autoScrollEnabled?: boolean; + disableScrollOverlapDetection?: boolean; lockAxis?: 'x' | 'y'; dragClass?: string; dropClass?: string; diff --git a/src/mediator.ts b/src/mediator.ts index 5cf743d..ee94565 100644 --- a/src/mediator.ts +++ b/src/mediator.ts @@ -78,13 +78,10 @@ function getGhostParent() { } function getGhostElement(wrapperElement: HTMLElement, { x, y }: Position, container: IContainer, cursor: string): GhostInfo { - const wrapperRect = wrapperElement.getBoundingClientRect(); - const { left, top, right, bottom } = wrapperRect; - - const wrapperVisibleRect = Utils.getIntersection(container.layout.getContainerRectangles().visibleRect, wrapperRect); - - const midX = wrapperVisibleRect.left + (wrapperVisibleRect.right - wrapperVisibleRect.left) / 2; - const midY = wrapperVisibleRect.top + (wrapperVisibleRect.bottom - wrapperVisibleRect.top) / 2; + const { left, top, right, bottom } = wrapperElement.getBoundingClientRect(); + const midX = left + (right - left) / 2; + const midY = top + (bottom - top) / 2; + const ghost: HTMLElement = wrapperElement.cloneNode(true) as HTMLElement; ghost.style.zIndex = '1000'; ghost.style.boxSizing = 'border-box'; @@ -541,7 +538,7 @@ function dragHandler(dragListeningContainers: IContainer[]): (draggableInfo: Dra function getScrollHandler(container: IContainer, dragListeningContainers: IContainer[]) { if (container.getOptions().autoScrollEnabled) { - return dragScroller(dragListeningContainers, container.getScrollMaxSpeed()); + return dragScroller(dragListeningContainers, container.getScrollMaxSpeed(), container.getOptions().disableScrollOverlapDetection); } else { return (props: { draggableInfo?: DraggableInfo; reset?: boolean }) => null; } diff --git a/src/scroller.ts b/src/scroller.ts index fbaf584..c7f6186 100644 --- a/src/scroller.ts +++ b/src/scroller.ts @@ -214,7 +214,7 @@ function getTopmostScrollAnimator(animatorInfos: ScrollerAnimator[], position: P return null; } -export default (containers: IContainer[], maxScrollSpeed = maxSpeed) => { +export default (containers: IContainer[], maxScrollSpeed = maxSpeed, disableOverlapDetection = false) => { const animatorInfos = containers.reduce((acc: ScrollerAnimator[], container: IContainer) => { const filteredAnimators = getScrollerAnimator(container).filter(p => { return !acc.find(q => q.scrollerElement === p.scrollerElement); @@ -256,20 +256,22 @@ export default (containers: IContainer[], maxScrollSpeed = maxSpeed) => { } }); - const overlappingAnimators = animatorInfos.filter(p => p.cachedRect); - if (overlappingAnimators.length && overlappingAnimators.length > 1) { - // stop animations except topmost - const topScrollerAnimator = getTopmostScrollAnimator(overlappingAnimators, draggableInfo.mousePosition); - - if (topScrollerAnimator) { - overlappingAnimators.forEach(p => { - if (p !== topScrollerAnimator) { - p.axisAnimations.x && p.axisAnimations.x.animator.stop(); - p.axisAnimations.y && p.axisAnimations.y.animator.stop(); - } - }) + if (disableOverlapDetection !== true) { + const overlappingAnimators = animatorInfos.filter(p => p.cachedRect); + if (overlappingAnimators.length && overlappingAnimators.length > 1) { + // stop animations except topmost + const topScrollerAnimator = getTopmostScrollAnimator(overlappingAnimators, draggableInfo.mousePosition); + + if (topScrollerAnimator) { + overlappingAnimators.forEach(p => { + if (p !== topScrollerAnimator) { + p.axisAnimations.x && p.axisAnimations.x.animator.stop(); + p.axisAnimations.y && p.axisAnimations.y.animator.stop(); + } + }) + } } } } } -} \ No newline at end of file +}