diff --git a/src/UIEventObserver.js b/src/UIEventObserver.js index 5afdbeb..c4912ff 100644 --- a/src/UIEventObserver.js +++ b/src/UIEventObserver.js @@ -17,6 +17,7 @@ export default class UIEventObserver { * @param {Object} target target Element Node * @param {string} eventName event name * @param {Function} handler event handler + * @returns {Function} unsubscribe handler * @public */ subscribe(target, eventName, handler) { @@ -31,6 +32,26 @@ export default class UIEventObserver { target.addEventListener(eventName, handler); } domEventEmitter.on(handler); + return () => { + this.unsubscribe(target, eventName, handler); + } + } + + /** + * registers the specified `handler` on the `target` element it's called `eventName`. + * It is called at once difference from UIEventObserver#subscribe + * @param {Object} target target Element Node + * @param {string} eventName event name + * @param {Function} handler event handler + * @returns {Function} unsubscribe handler + * @public + */ + subscribeOnce(target, eventName, handler) { + const onceHandler = (event) => { + handler(event); + this.unsubscribe(target, eventName, onceHandler); + }; + return this.subscribe(target, eventName, onceHandler); } /** diff --git a/test/UIEventObserver-test.js b/test/UIEventObserver-test.js index fd3da1d..4a55e16 100644 --- a/test/UIEventObserver-test.js +++ b/test/UIEventObserver-test.js @@ -12,6 +12,23 @@ describe("UIEventObserver", () => { eventObserver.unsubscribeAll(); }); describe("#subscribe", () => { + context("return values", () => { + it("is unsubscribe function bind arguments", () => { + const called = []; + const handler = (event) => { + called.push(event); + }; + const unsubscribe = eventObserver.subscribe(window, "scroll", handler); + assert(typeof unsubscribe === "function"); + assert(called.length === 0); + // unsubscribe + unsubscribe(); + // fire + const event = new Event("scroll"); + window.dispatchEvent(event); + assert(called.length === 0); + }); + }); context("target is document.body", () => { it("add handler is called when the event is fired", (done) => { const handler = (event) => { @@ -52,6 +69,25 @@ describe("UIEventObserver", () => { }); }); }); + describe("#subscribeOnce", () => { + context("when fire it once", () => { + it("should automatically unsubscribe", () => { + const called = []; + const handler = (event) => { + called.push(event); + }; + const unsubscribe = eventObserver.subscribeOnce(window, "scroll", handler); + assert(typeof unsubscribe === "function"); + assert(called.length === 0); + // fire + window.dispatchEvent(new Event("scroll")); + assert(called.length === 1); + // fire twice, but is not called + window.dispatchEvent(new Event("scroll")); + assert(called.length === 1); + }); + }); + }); describe("#unsubscribe", () => { it("unSubscribe all -> Actual removeEventListener", () => { const handler = () => {