Skip to content
Permalink
Browse files

fix(ElementEvents): ElementEvents.defaultListenerOptions allows to se…

…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 18, 2019
1 parent 87d11c7 commit f7e8e324eb21c8c528b15a6ec9096a9206e47684
Showing with 52 additions and 2 deletions.
  1. +10 −2 src/element-events.js
  2. +42 −0 test/element-events.spec.js
@@ -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 = {};
@@ -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;
}
@@ -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;
}
@@ -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;

0 comments on commit f7e8e32

Please sign in to comment.
You can’t perform that action at this time.