Skip to content

Commit 8cc4efd

Browse files
authored
fix: keep widget scrolling local (#6594)
1 parent a7ff28c commit 8cc4efd

File tree

2 files changed

+64
-17
lines changed

2 files changed

+64
-17
lines changed

js/widgets/__tests__/widgetWindows.test.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,42 @@ describe("widgetWindows", () => {
435435
expect(removeSpy).toHaveBeenCalledWith("mousedown", win._docMouseDownHandler, true);
436436
removeSpy.mockRestore();
437437
});
438+
439+
test("removes widget-local wheel listeners", () => {
440+
const win = createTestWindow();
441+
const removeSpy = jest.spyOn(win._widget, "removeEventListener");
442+
443+
win.destroy();
444+
445+
expect(removeSpy).toHaveBeenCalledWith("wheel", win._widgetWheelHandler, false);
446+
expect(removeSpy).toHaveBeenCalledWith(
447+
"DOMMouseScroll",
448+
win._widgetWheelHandler,
449+
false
450+
);
451+
removeSpy.mockRestore();
452+
});
453+
});
454+
455+
describe("widget scroll handling", () => {
456+
test("keeps window.onscroll untouched when scrolling inside a widget", () => {
457+
const win = createTestWindow();
458+
const existingScrollHandler = jest.fn();
459+
window.onscroll = existingScrollHandler;
460+
win._widget.scrollTop = 10;
461+
462+
const event = new window.WheelEvent("wheel", {
463+
deltaY: 30,
464+
bubbles: true,
465+
cancelable: true
466+
});
467+
468+
win._widget.dispatchEvent(event);
469+
470+
expect(win._widget.scrollTop).toBe(40);
471+
expect(event.defaultPrevented).toBe(true);
472+
expect(window.onscroll).toBe(existingScrollHandler);
473+
});
438474
});
439475

440476
describe("sendToCenter", () => {

js/widgets/widgetWindows.js

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -253,20 +253,31 @@ class WidgetWindow {
253253
this._body = this._create("div", "wfWinBody", this._frame);
254254
this._toolbar = this._create("div", "wfbToolbar", this._body);
255255

256-
const disableScroll = () => {
257-
// Get the current page scroll position
258-
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
259-
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
260-
// if any scroll is attempted,
261-
// set this to the previous value
262-
window.onscroll = () => {
263-
window.scrollTo(scrollLeft, scrollTop);
264-
};
265-
};
266-
267256
this._widget = this._create("div", "wfbWidget", this._body);
268-
this._widget.addEventListener("wheel", disableScroll, { passive: true });
269-
this._widget.addEventListener("DOMMouseScroll", disableScroll, { passive: true });
257+
this._widgetWheelHandler = event => {
258+
const deltaY =
259+
typeof event.deltaY === "number"
260+
? event.deltaY
261+
: typeof event.detail === "number"
262+
? event.detail * 16
263+
: 0;
264+
const deltaX = typeof event.deltaX === "number" ? event.deltaX : 0;
265+
266+
this._widget.scrollTop += deltaY;
267+
this._widget.scrollLeft += deltaX;
268+
269+
if (event.cancelable) {
270+
event.preventDefault();
271+
}
272+
273+
event.stopPropagation();
274+
};
275+
this._widget.addEventListener("wheel", this._widgetWheelHandler, {
276+
passive: false
277+
});
278+
this._widget.addEventListener("DOMMouseScroll", this._widgetWheelHandler, {
279+
passive: false
280+
});
270281
}
271282

272283
/**
@@ -630,10 +641,10 @@ class WidgetWindow {
630641
if (this._docMouseDownHandler) {
631642
document.removeEventListener("mousedown", this._docMouseDownHandler, true);
632643
}
633-
// Clear the scroll lock that may have been set by the disableScroll
634-
// handler in _createUIelements(). Without this, window.onscroll remains
635-
// permanently overridden after the widget is closed, freezing page scroll.
636-
window.onscroll = null;
644+
if (this._widget && this._widgetWheelHandler) {
645+
this._widget.removeEventListener("wheel", this._widgetWheelHandler, false);
646+
this._widget.removeEventListener("DOMMouseScroll", this._widgetWheelHandler, false);
647+
}
637648
if (this._frame && this._frame.parentElement) {
638649
this._frame.parentElement.removeChild(this._frame);
639650
}

0 commit comments

Comments
 (0)