From 1b35ee796fee660fef06e76aaf7c0bdd7ae7fbf3 Mon Sep 17 00:00:00 2001 From: Alexey Plutalov Date: Fri, 5 May 2017 00:57:47 +0300 Subject: [PATCH] Add capturing support to `once` function --- d.ts/homey.d.ts | 2 +- spec/events/once.spec.js | 94 ++++++++++++++++++++++++++++++++++++---- src/events/once.js | 7 +-- 3 files changed, 90 insertions(+), 13 deletions(-) diff --git a/d.ts/homey.d.ts b/d.ts/homey.d.ts index 0917cfc..0533f4e 100644 --- a/d.ts/homey.d.ts +++ b/d.ts/homey.d.ts @@ -57,6 +57,6 @@ export function remove(element: Element): boolean; */ export function on(element: Element, eventType: EventType, listener: EventListener, useCapture?: boolean): () => void; -export function once(element: Element, eventType: EventType, listener: EventListener): () => void; +export function once(element: Element, eventType: EventType, listener: EventListener, useCapture?: boolean): () => void; export function delegate(element: Element, selector: Selector, eventType: EventType, listener: EventListener): () => void; export function dispatch(element: Element, eventType: EventType, listener: EventListener): boolean; diff --git a/spec/events/once.spec.js b/spec/events/once.spec.js index a842dac..1d711d2 100644 --- a/spec/events/once.spec.js +++ b/spec/events/once.spec.js @@ -1,19 +1,14 @@ import { once } from "../../src"; describe("once", () => { - let subject; - let listener; + afterEach(clearFixtures); - beforeEach(() => { + it("adds listener for DOM event", () => { useFixture(`
`); - subject = document.querySelector(".root"); - listener = jasmine.createSpy("listener"); - }); - - afterEach(clearFixtures); + const subject = document.querySelector(".root"); + const listener = jasmine.createSpy("listener"); - it("adds listener for DOM event", () => { once(subject, "click", listener); expect(listener).not.toHaveBeenCalled(); @@ -27,6 +22,11 @@ describe("once", () => { }); it("adds listener for custom event", () => { + useFixture(`
`); + + const subject = document.querySelector(".root"); + const listener = jasmine.createSpy("listener"); + once(subject, "custom", listener); expect(listener).not.toHaveBeenCalled(); @@ -40,6 +40,11 @@ describe("once", () => { }); it("adds listener which called on first event trigger only", () => { + useFixture(`
`); + + const subject = document.querySelector(".root"); + const listener = jasmine.createSpy("listener"); + once(subject, "click", listener); expect(listener).not.toHaveBeenCalled(); @@ -60,6 +65,11 @@ describe("once", () => { }); it("returns function for removing listener", () => { + useFixture(`
`); + + const subject = document.querySelector(".root"); + const listener = jasmine.createSpy("listener"); + const off = once(subject, "click", listener); expect(listener).not.toHaveBeenCalled(); @@ -72,4 +82,70 @@ describe("once", () => { expect(listener).not.toHaveBeenCalled(); }); + + describe("supports events capturing", () => { + it("doesn't use capturing by default", () => { + useFixture(` +
+
+
+
+
+ `); + + const parent = document.querySelector(".parent"); + const subject = document.querySelector(".root"); + const child = document.querySelector(".child"); + const parentListener = jasmine.createSpy("parentListener"); + const subjectListener = jasmine.createSpy("subjectListener"); + + once(parent, "click", parentListener); + once(subject, "click", subjectListener); + + expect(parentListener).not.toHaveBeenCalled(); + expect(subjectListener).not.toHaveBeenCalled(); + + const event = createEvent("click"); + + child.dispatchEvent(event); + + expect(parentListener).toHaveBeenCalledTimes(1); + expect(parentListener).toHaveBeenCalledWith(event); + expect(subjectListener).toHaveBeenCalledTimes(1); + expect(subjectListener).toHaveBeenCalledWith(event); + expect(subjectListener).toHaveBeenCalledBefore(parentListener); + }); + + it("uses capturing when flag given", () => { + useFixture(` +
+
+
+
+
+ `); + + const parent = document.querySelector(".parent"); + const subject = document.querySelector(".root"); + const child = document.querySelector(".child"); + const parentListener = jasmine.createSpy("parentListener"); + const subjectListener = jasmine.createSpy("subjectListener"); + + once(parent, "click", parentListener, true); + once(subject, "click", subjectListener, true); + + expect(parentListener).not.toHaveBeenCalled(); + expect(subjectListener).not.toHaveBeenCalled(); + + const event = createEvent("click"); + + child.dispatchEvent(event); + + expect(parentListener).toHaveBeenCalledTimes(1); + expect(parentListener).toHaveBeenCalledWith(event); + expect(subjectListener).toHaveBeenCalledTimes(1); + expect(subjectListener).toHaveBeenCalledWith(event); + expect(parentListener).toHaveBeenCalledBefore(subjectListener); + }); + }); }); diff --git a/src/events/once.js b/src/events/once.js index 1861e9b..dbdff08 100644 --- a/src/events/once.js +++ b/src/events/once.js @@ -7,15 +7,16 @@ import on from "./on"; function once( element: Element, eventType: EventType, - listener: EventListener + listener: EventListener, + useCapture?: boolean = false ): () => void { function wrappedListener(event) { - element.removeEventListener(eventType, wrappedListener); + element.removeEventListener(eventType, wrappedListener, useCapture); listener(event); } - return on(element, eventType, wrappedListener); + return on(element, eventType, wrappedListener, useCapture); } export default once;