Skip to content

Commit f7e8e32

Browse files
sebastien-rochEisenbergEffect
authored andcommitted
fix(ElementEvents): ElementEvents.defaultListenerOptions allows to set default options when subscribing to events
ElementEvents.subscribe will set capture to true be default if not explicitely passed in argument. This is not the standard behavior of the native addEventListener() and confuses developers. This new options let you define the default behavior. Fixes issue #657
1 parent 87d11c7 commit f7e8e32

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

src/element-events.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ interface EventHandler {
1313
* @param element
1414
*/
1515
export class ElementEvents {
16+
static defaultListenerOptions: boolean | AddEventListenerOptions = { capture: true };
17+
1618
constructor(element: EventTarget) {
1719
this.element = element;
1820
this.subscriptions = {};
@@ -51,8 +53,11 @@ export class ElementEvents {
5153
* Adds and Event Listener on the context element.
5254
* @return Returns the eventHandler containing a dispose method
5355
*/
54-
subscribe(eventName: string, handler: Function, captureOrOptions?: boolean = true): EventHandler {
56+
subscribe(eventName: string, handler: Function, captureOrOptions?: boolean | AddEventListenerOptions): EventHandler {
5557
if (typeof handler === 'function') {
58+
if (typeof captureOrOptions === 'undefined') {
59+
captureOrOptions = ElementEvents.defaultListenerOptions;
60+
}
5661
const eventHandler = new EventHandlerImpl(this, eventName, handler, captureOrOptions, false);
5762
return eventHandler;
5863
}
@@ -64,8 +69,11 @@ export class ElementEvents {
6469
* Adds an Event Listener on the context element, that will be disposed on the first trigger.
6570
* @return Returns the eventHandler containing a dispose method
6671
*/
67-
subscribeOnce(eventName: string, handler: Function, captureOrOptions?: boolean = true): EventHandler {
72+
subscribeOnce(eventName: string, handler: Function, captureOrOptions?: boolean | AddEventListenerOptions): EventHandler {
6873
if (typeof handler === 'function') {
74+
if (typeof captureOrOptions === 'undefined') {
75+
captureOrOptions = ElementEvents.defaultListenerOptions;
76+
}
6977
const eventHandler = new EventHandlerImpl(this, eventName, handler, captureOrOptions, true);
7078
return eventHandler;
7179
}

test/element-events.spec.js

+42
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,48 @@ describe('ElementEvents', () => {
5353
expect(callCount).toBe(1);
5454
});
5555

56+
it("should subscribe and take ElementEvent default listener options into account", () => {
57+
let isCapture;
58+
59+
// we need to track event on a parent of the input, let's take body
60+
const bodyElementEvents = new ElementEvents(document.body);
61+
ElementEvents.defaultListenerOptions = { capture: false };
62+
let eventHandler = bodyElementEvents.subscribe('input', event => {
63+
isCapture = event.eventPhase === Event.CAPTURING_PHASE;
64+
});
65+
66+
// input has to be attached for the event to bubble up
67+
document.body.appendChild(input);
68+
input.dispatchEvent(new CustomEvent('input', {bubbles: true}));
69+
expect(isCapture).toBe(false);
70+
eventHandler.dispose();
71+
72+
73+
// set capture back to true and check if it's being used
74+
ElementEvents.defaultListenerOptions = { capture: true };
75+
eventHandler = bodyElementEvents.subscribe('input', event => {
76+
isCapture = event.eventPhase === Event.CAPTURING_PHASE;
77+
});
78+
79+
input.dispatchEvent(new CustomEvent('input', {bubbles: true}));
80+
expect(isCapture).toBe(true);
81+
eventHandler.dispose();
82+
});
83+
84+
it("should subscribe and ignore ElementEvent default listener options when argument captureOrOptions is passed", () => {
85+
let isCapture;
86+
87+
const bodyElementEvents = new ElementEvents(document.body);
88+
ElementEvents.defaultListenerOptions = { capture: false };
89+
bodyElementEvents.subscribe('input', event => {
90+
isCapture = event.eventPhase === Event.CAPTURING_PHASE;
91+
}, true);
92+
93+
document.body.appendChild(input);
94+
input.dispatchEvent(new CustomEvent('input', {bubbles: true}));
95+
expect(isCapture).toBe(true);
96+
});
97+
5698
it('should dispose single event', () => {
5799
let value;
58100
let callCount = 0;

0 commit comments

Comments
 (0)