Skip to content

Commit 946c0a2

Browse files
committed
Use active event listener when using preventDefault for wheel and touch events
1 parent e6178b7 commit 946c0a2

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

src/Components/Samples/BlazorUnitedApp/Pages/Counter.razor

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,16 @@
1111

1212
@if (showElements)
1313
{
14+
<div @onwheel:preventDefault="preventDefault" style="width: 400px; height: 200px; border: 1px solid black;">
15+
Scroll here
16+
</div>
17+
1418
<button class="btn btn-primary" @onclick="IncrementCount" @onmousedown:preventDefault="preventDefault">
1519
Click me
1620
</button>
1721
}
1822

19-
<p>
23+
<p style="padding-bottom: 2000px;">
2024
<button class="btn btn-secondary" @onclick="ToggleShow">
2125
Toggle show
2226
</button>

src/Components/Web.JS/src/Rendering/Events/EventDelegator.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,11 @@ export class EventDelegator {
152152
infoForElement.preventDefault(eventName, value);
153153

154154
if (!currentValue && value) {
155-
this.eventInfoStore.addGlobalListener(eventName);
155+
// To ensure that preventDefault works for wheel and touch events,,
156+
// we need to register a listener with the passive mode explicitly disabled.
157+
// Note that this does not change behavior for other events as those
158+
// use active mode by default.
159+
this.eventInfoStore.addActiveGlobalListener(eventName);
156160
} else if (currentValue && !value) {
157161
this.eventInfoStore.decrementCountByEventName(eventName);
158162
}
@@ -293,6 +297,25 @@ class EventInfoStore {
293297
}
294298
}
295299

300+
public addActiveGlobalListener(eventName: string) {
301+
// If this event name is an alias, update the global listener for the corresponding browser event
302+
eventName = getBrowserEventName(eventName);
303+
304+
// If the listener for this event is already registered, we recreate it to ensure
305+
// that it is using the active mode.
306+
if (Object.prototype.hasOwnProperty.call(this.countByEventName, eventName)) {
307+
this.countByEventName[eventName]++;
308+
document.removeEventListener(eventName, this.globalListener);
309+
} else {
310+
this.countByEventName[eventName] = 1;
311+
}
312+
313+
// To make delegation work with non-bubbling events, register a 'capture' listener.
314+
// We preserve the non-bubbling behavior by only dispatching such events to the targeted element.
315+
const useCapture = Object.prototype.hasOwnProperty.call(nonBubblingEvents, eventName);
316+
document.addEventListener(eventName, this.globalListener, { capture: useCapture, passive: false });
317+
}
318+
296319
public update(oldEventHandlerId: number, newEventHandlerId: number) {
297320
if (Object.prototype.hasOwnProperty.call(this.infosByEventHandlerId, newEventHandlerId)) {
298321
// Should never happen, but we want to know if it does

0 commit comments

Comments
 (0)