From d9c714c042739d5cbdbe51b876f16a3152d200e6 Mon Sep 17 00:00:00 2001 From: Ghislain B Date: Wed, 17 Jan 2024 01:47:57 -0500 Subject: [PATCH] fix: when `onDragInit` return false it should stop (#1340) * fix: when `onDragInit` return false it should stop - when `onDragInit` returns `false` then the row or cell dragging shouldn't be allowed - this is similar to previous PR #1339 --- .../src/core/__tests__/slickGrid.spec.ts | 53 ++++++++++++++++--- packages/common/src/core/slickInteractions.ts | 18 ++++--- 2 files changed, 55 insertions(+), 16 deletions(-) diff --git a/packages/common/src/core/__tests__/slickGrid.spec.ts b/packages/common/src/core/__tests__/slickGrid.spec.ts index 4db82d01c..07f03f69e 100644 --- a/packages/common/src/core/__tests__/slickGrid.spec.ts +++ b/packages/common/src/core/__tests__/slickGrid.spec.ts @@ -1938,15 +1938,44 @@ describe('SlickGrid core file', () => { expect(onDragEndSpy).not.toHaveBeenCalled(); }); - it('should return value onDragStart when event has cancelled bubbling (immediatePropagationStopped)', () => { + it('should not execute any events after onDragInit when it returns false', () => { grid = new SlickGrid(container, data, columns, defaultOptions); const cMouseDownEvent = new CustomEvent('mousedown'); - const sedMouseDown = new SlickEventData(); - sedMouseDown.addReturnValue(false); - sedMouseDown.stopImmediatePropagation(); const onDragInitSpy = jest.spyOn(grid.onDragInit, 'notify'); - const onDragStartSpy = jest.spyOn(grid.onDragStart, 'notify').mockReturnValue(sedMouseDown); + const onDragStartSpy = jest.spyOn(grid.onDragStart, 'notify'); + const onDragSpy = jest.spyOn(grid.onDrag, 'notify'); + const onDragEndSpy = jest.spyOn(grid.onDragEnd, 'notify'); + const slickCellElm = container.querySelector('.slick-cell.l1.r1') as HTMLDivElement; + slickCellElm.classList.add('dnd', 'cell-reorder'); + + const bodyMouseMoveEvent1 = new CustomEvent('mousemove'); + const bodyMouseUpEvent = new CustomEvent('mouseup'); + Object.defineProperty(cMouseDownEvent, 'target', { writable: true, value: slickCellElm }); + Object.defineProperty(bodyMouseMoveEvent1, 'target', { writable: true, value: slickCellElm }); + + container.dispatchEvent(cMouseDownEvent); + document.body.dispatchEvent(bodyMouseMoveEvent1); + document.body.dispatchEvent(bodyMouseUpEvent); + + expect(onDragInitSpy).toHaveBeenCalled(); + expect(onDragStartSpy).not.toHaveBeenCalled(); + expect(onDragSpy).not.toHaveBeenCalled(); + expect(onDragEndSpy).not.toHaveBeenCalled(); + }); + + it('should not execute onDragStart or any other events when onDragStart event has cancelled bubbling (immediatePropagationStopped)', () => { + grid = new SlickGrid(container, data, columns, defaultOptions); + + const cMouseDownEvent = new CustomEvent('mousedown'); + const sedDragInit = new SlickEventData(); + const sedDragStart = new SlickEventData(); + sedDragInit.addReturnValue(true); + sedDragStart.addReturnValue(false); + sedDragInit.stopImmediatePropagation(); + sedDragStart.stopImmediatePropagation(); + const onDragInitSpy = jest.spyOn(grid.onDragInit, 'notify').mockReturnValue(sedDragInit); + const onDragStartSpy = jest.spyOn(grid.onDragStart, 'notify').mockReturnValue(sedDragStart); const onDragSpy = jest.spyOn(grid.onDrag, 'notify'); const onDragEndSpy = jest.spyOn(grid.onDragEnd, 'notify'); const slickCellElm = container.querySelector('.slick-cell.l1.r1') as HTMLDivElement; @@ -1967,9 +1996,13 @@ describe('SlickGrid core file', () => { expect(onDragEndSpy).toHaveBeenCalled(); }); - it('should drag from a cell and execute all onDrag events when a slick-cell is dragged', () => { + it('should drag from a cell and execute all onDrag events when a slick-cell is dragged and its event is stopped', () => { grid = new SlickGrid(container, data, columns, defaultOptions); - const onDragInitSpy = jest.spyOn(grid.onDragInit, 'notify'); + + const sedDragInit = new SlickEventData(); + sedDragInit.addReturnValue(true); + sedDragInit.stopImmediatePropagation(); + const onDragInitSpy = jest.spyOn(grid.onDragInit, 'notify').mockReturnValue(sedDragInit); const onDragStartSpy = jest.spyOn(grid.onDragStart, 'notify'); const onDragSpy = jest.spyOn(grid.onDrag, 'notify'); const onDragEndSpy = jest.spyOn(grid.onDragEnd, 'notify'); @@ -1996,7 +2029,11 @@ describe('SlickGrid core file', () => { it('should drag from a cell and execute all onDrag events except onDragStart when mousemove event target is not a slick-cell', () => { grid = new SlickGrid(container, data, columns, defaultOptions); - const onDragInitSpy = jest.spyOn(grid.onDragInit, 'notify'); + + const sedDragInit = new SlickEventData(); + sedDragInit.addReturnValue(true); + sedDragInit.stopImmediatePropagation(); + const onDragInitSpy = jest.spyOn(grid.onDragInit, 'notify').mockReturnValue(sedDragInit); const onDragStartSpy = jest.spyOn(grid.onDragStart, 'notify'); const onDragSpy = jest.spyOn(grid.onDrag, 'notify'); const onDragEndSpy = jest.spyOn(grid.onDragEnd, 'notify'); diff --git a/packages/common/src/core/slickInteractions.ts b/packages/common/src/core/slickInteractions.ts index 994bd1c70..bc4fab230 100644 --- a/packages/common/src/core/slickInteractions.ts +++ b/packages/common/src/core/slickInteractions.ts @@ -55,7 +55,7 @@ export function Draggable(options: DraggableOption) { function executeDragCallbackWhenDefined(callback?: (e: DragEvent, dd: DragPosition) => boolean | void, evt?: MouseEvent | Touch | TouchEvent, dd?: DragItem) { if (typeof callback === 'function') { - callback(evt as DragEvent, dd as DragItem); + return callback(evt as DragEvent, dd as DragItem); } } @@ -79,13 +79,15 @@ export function Draggable(options: DraggableOption) { deltaX = targetEvent.clientX - targetEvent.clientX; deltaY = targetEvent.clientY - targetEvent.clientY; originaldd = Object.assign(originaldd, { deltaX, deltaY, startX, startY, target }); - executeDragCallbackWhenDefined(onDragInit as (e: DragEvent, dd: DragPosition) => boolean | void, event, originaldd as DragItem); - - document.body.addEventListener('mousemove', userMoved); - document.body.addEventListener('touchmove', userMoved); - document.body.addEventListener('mouseup', userReleased); - document.body.addEventListener('touchend', userReleased); - document.body.addEventListener('touchcancel', userReleased); + const result = executeDragCallbackWhenDefined(onDragInit as (e: DragEvent, dd: DragPosition) => boolean | void, event, originaldd as DragItem); + + if (result !== false) { + document.body.addEventListener('mousemove', userMoved); + document.body.addEventListener('touchmove', userMoved); + document.body.addEventListener('mouseup', userReleased); + document.body.addEventListener('touchend', userReleased); + document.body.addEventListener('touchcancel', userReleased); + } } }