Skip to content

Commit

Permalink
fix(ElementEvents): ElementEvents.defaultListenerOptions allows to se…
Browse files Browse the repository at this point in the history
…t 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
  • Loading branch information
sebastien-roch authored and EisenbergEffect committed Mar 19, 2019
1 parent 87d11c7 commit f7e8e32
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 2 deletions.
12 changes: 10 additions & 2 deletions src/element-events.js
Expand Up @@ -13,6 +13,8 @@ interface EventHandler {
* @param element
*/
export class ElementEvents {
static defaultListenerOptions: boolean | AddEventListenerOptions = { capture: true };

constructor(element: EventTarget) {
this.element = element;
this.subscriptions = {};
Expand Down Expand Up @@ -51,8 +53,11 @@ export class ElementEvents {
* Adds and Event Listener on the context element.
* @return Returns the eventHandler containing a dispose method
*/
subscribe(eventName: string, handler: Function, captureOrOptions?: boolean = true): EventHandler {
subscribe(eventName: string, handler: Function, captureOrOptions?: boolean | AddEventListenerOptions): EventHandler {
if (typeof handler === 'function') {
if (typeof captureOrOptions === 'undefined') {
captureOrOptions = ElementEvents.defaultListenerOptions;
}
const eventHandler = new EventHandlerImpl(this, eventName, handler, captureOrOptions, false);
return eventHandler;
}
Expand All @@ -64,8 +69,11 @@ export class ElementEvents {
* Adds an Event Listener on the context element, that will be disposed on the first trigger.
* @return Returns the eventHandler containing a dispose method
*/
subscribeOnce(eventName: string, handler: Function, captureOrOptions?: boolean = true): EventHandler {
subscribeOnce(eventName: string, handler: Function, captureOrOptions?: boolean | AddEventListenerOptions): EventHandler {
if (typeof handler === 'function') {
if (typeof captureOrOptions === 'undefined') {
captureOrOptions = ElementEvents.defaultListenerOptions;
}
const eventHandler = new EventHandlerImpl(this, eventName, handler, captureOrOptions, true);
return eventHandler;
}
Expand Down
42 changes: 42 additions & 0 deletions test/element-events.spec.js
Expand Up @@ -53,6 +53,48 @@ describe('ElementEvents', () => {
expect(callCount).toBe(1);
});

it("should subscribe and take ElementEvent default listener options into account", () => {
let isCapture;

// we need to track event on a parent of the input, let's take body
const bodyElementEvents = new ElementEvents(document.body);
ElementEvents.defaultListenerOptions = { capture: false };
let eventHandler = bodyElementEvents.subscribe('input', event => {
isCapture = event.eventPhase === Event.CAPTURING_PHASE;
});

// input has to be attached for the event to bubble up
document.body.appendChild(input);
input.dispatchEvent(new CustomEvent('input', {bubbles: true}));
expect(isCapture).toBe(false);
eventHandler.dispose();


// set capture back to true and check if it's being used
ElementEvents.defaultListenerOptions = { capture: true };
eventHandler = bodyElementEvents.subscribe('input', event => {
isCapture = event.eventPhase === Event.CAPTURING_PHASE;
});

input.dispatchEvent(new CustomEvent('input', {bubbles: true}));
expect(isCapture).toBe(true);
eventHandler.dispose();
});

it("should subscribe and ignore ElementEvent default listener options when argument captureOrOptions is passed", () => {
let isCapture;

const bodyElementEvents = new ElementEvents(document.body);
ElementEvents.defaultListenerOptions = { capture: false };
bodyElementEvents.subscribe('input', event => {
isCapture = event.eventPhase === Event.CAPTURING_PHASE;
}, true);

document.body.appendChild(input);
input.dispatchEvent(new CustomEvent('input', {bubbles: true}));
expect(isCapture).toBe(true);
});

it('should dispose single event', () => {
let value;
let callCount = 0;
Expand Down

0 comments on commit f7e8e32

Please sign in to comment.