Skip to content

Commit c4890bf

Browse files
authored
Merge pull request #3254 from adumesny/master
more scroll fixes when entering other grids
2 parents eb9c136 + 089eabd commit c4890bf

File tree

4 files changed

+10
-6
lines changed

4 files changed

+10
-6
lines changed

doc/API.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4288,7 +4288,7 @@ Subclasses should override to perform additional cleanup.
42884288
drop(e): void;
42894289
```
42904290

4291-
Defined in: [dd-droppable.ts:143](https://github.com/adumesny/gridstack.js/blob/master/src/dd-droppable.ts#L143)
4291+
Defined in: [dd-droppable.ts:146](https://github.com/adumesny/gridstack.js/blob/master/src/dd-droppable.ts#L146)
42924292

42934293
item is being dropped on us - called by the drag mouseup handler - this calls the client drop event
42944294

src/dd-draggable.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ export class DDDraggable extends DDBaseImplement implements HTMLElementExtendOpt
410410
/** @internal starts or continues auto-scroll when the dragged helper is clipped by the scroll container.
411411
* Takes the grid's own element to find the scroll container so external/sidebar drags work too (#2074). */
412412
public updateScrollPosition(gridEl: HTMLElement): void {
413-
this._autoScrollContainer ??= Utils.getScrollElement(gridEl);
413+
this._autoScrollContainer = Utils.getScrollElement(gridEl); // always use latest active grid
414414
const clipping = this._getClipping(this.helper, this._autoScrollContainer);
415415
if (clipping === 0) {
416416
this._stopScrolling();
@@ -419,11 +419,12 @@ export class DDDraggable extends DDBaseImplement implements HTMLElementExtendOpt
419419
}
420420
}
421421

422-
/** @internal compute how many pixels the element is clipped: negative = above, positive = below, 0 = fully visible */
422+
/** @internal compute how many pixels the element is clipped: negative = above, positive = below, 0 = fully inside OR outside (stop scrolling) */
423423
protected _getClipping(el: HTMLElement, scrollEl: HTMLElement): number {
424424
const elRect = el.getBoundingClientRect();
425425
const scrollRect = scrollEl.getBoundingClientRect();
426426
const viewportH = window.innerHeight || document.documentElement.clientHeight;
427+
if (elRect.bottom < scrollRect.top || elRect.top > scrollRect.bottom) return 0; // fully outside
427428
const clippedBelow = elRect.bottom - Math.min(scrollRect.bottom, viewportH);
428429
const clippedAbove = elRect.top - Math.max(scrollRect.top, 0);
429430
if (clippedAbove < 0) return clippedAbove;

src/dd-droppable.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export class DDDroppable extends DDBaseImplement implements HTMLElementExtendOpt
8282

8383
/** @internal called when the cursor enters our area - prepare for a possible drop and track leaving */
8484
protected _mouseEnter(e: MouseEvent): void {
85-
// console.log(`${count++} Enter ${this.el.id || (this.el as GridHTMLElement).gridstack.opts.id}`); // TEST
85+
// console.log(`${count++} Enter ${this.el.id}`); // TEST
8686
if (!DDManager.dragElement) return;
8787
// During touch drag operations, ignore real browser-generated mouseenter events (isTrusted:true) vs our simulated ones (isTrusted:false).
8888
// The browser can fire spurious mouseenter events when we dispatch simulated mousemove events.
@@ -91,6 +91,7 @@ export class DDDroppable extends DDBaseImplement implements HTMLElementExtendOpt
9191
if (!this._canDrop(DDManager.dragElement.el)) return;
9292
e.preventDefault();
9393
e.stopPropagation();
94+
DDManager.dragElement._stopScrolling();
9495

9596
// make sure when we enter this, that the last one gets a leave FIRST to correctly cleanup as we don't always do
9697
if (DDManager.dropElement && DDManager.dropElement !== this) {
@@ -109,10 +110,12 @@ export class DDDroppable extends DDBaseImplement implements HTMLElementExtendOpt
109110

110111
/** @internal called when the item is leaving our area, stop tracking if we had moving item */
111112
protected _mouseLeave(e: MouseEvent, calledByEnter = false): void {
112-
// console.log(`${count++} Leave ${this.el.id || (this.el as GridHTMLElement).gridstack.opts.id}`); // TEST
113+
// console.log(`${count++} Leave ${this.el.id}`); // TEST
113114
if (!DDManager.dragElement || DDManager.dropElement !== this) return;
114115
e.preventDefault();
115116
e.stopPropagation();
117+
// stop the old grid's auto-scroll only when entering a new grid; if leaving to empty space keep scrolling until mouseup
118+
if (calledByEnter) DDManager.dragElement._stopScrolling();
116119

117120
const ev = Utils.initEvent<DragEvent>(e, { target: this.el, type: 'dropout' });
118121
if (this.option.out) {

src/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ export class Utils {
573573
static getScrollElement(el?: HTMLElement): HTMLElement {
574574
if (!el) return document.scrollingElement as HTMLElement || document.documentElement; // IE support
575575
const overflowY = getComputedStyle(el).overflowY;
576-
if (overflowY === 'auto' || overflowY === 'scroll') {
576+
if ((overflowY === 'auto' || overflowY === 'scroll') && el.scrollHeight > el.clientHeight) {
577577
return el;
578578
} else {
579579
return Utils.getScrollElement(el.parentElement);

0 commit comments

Comments
 (0)