From 20037bad77a67aac1f99a7bc871222fb87fc69c8 Mon Sep 17 00:00:00 2001 From: Thijs Louisse Date: Thu, 26 Sep 2019 13:45:23 +0200 Subject: [PATCH] feat(overlays): delegate events in DynamicOverlayController --- .../overlays/src/DynamicOverlayController.js | 26 ++++++++++++++++ .../test/DynamicOverlayController.test.js | 30 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/packages/overlays/src/DynamicOverlayController.js b/packages/overlays/src/DynamicOverlayController.js index f7c8f70d6..02110b907 100644 --- a/packages/overlays/src/DynamicOverlayController.js +++ b/packages/overlays/src/DynamicOverlayController.js @@ -34,6 +34,8 @@ export class DynamicOverlayController { if (!this.content) { this.content = document.createElement('div'); } + this.__fakeExtendsEventTarget(); + this.__delegateEvent = this.__delegateEvent.bind(this); } add(ctrlToAdd) { @@ -71,9 +73,13 @@ export class DynamicOverlayController { if (this.isShown === true) { throw new Error('You can not switch overlays while being shown'); } + const prevActive = this.active; + this.active.switchOut(); ctrlToSwitchTo.switchIn(); this.__active = ctrlToSwitchTo; + + this._delegateEvents(this.__active, prevActive); } async show() { @@ -99,4 +105,24 @@ export class DynamicOverlayController { get invokerNode() { return this.active.invokerNode; } + + _delegateEvents(active, prevActive) { + ['show', 'hide'].forEach(event => { + active.addEventListener(event, this.__delegateEvent); + prevActive.removeEventListener(event, this.__delegateEvent); + }); + } + + __delegateEvent(ev) { + ev.stopPropagation(); + this.dispatchEvent(new Event(ev.type)); + } + + // TODO: this method has to be removed when EventTarget polyfill is available on IE11 + __fakeExtendsEventTarget() { + const delegate = document.createDocumentFragment(); + ['addEventListener', 'dispatchEvent', 'removeEventListener'].forEach(funcName => { + this[funcName] = (...args) => delegate[funcName](...args); + }); + } } diff --git a/packages/overlays/test/DynamicOverlayController.test.js b/packages/overlays/test/DynamicOverlayController.test.js index 07a8daf4a..aacc904ec 100644 --- a/packages/overlays/test/DynamicOverlayController.test.js +++ b/packages/overlays/test/DynamicOverlayController.test.js @@ -133,4 +133,34 @@ describe('DynamicOverlayController', () => { expect(globalOutSpy).to.have.callCount(1); expect(localInSpy).to.have.callCount(1); }); + + describe('API abstraction for active overlay controller', () => { + describe('Events', () => { + it('delegates "show/hide" event', async () => { + const ctrl = new DynamicOverlayController(); + const global = new FakeGlobalCtrl(defaultOptions); + const local = new FakeLocalCtrl(defaultOptions); + ctrl.add(global); + ctrl.add(local); + ctrl.switchTo(local); + + const showSpy = sinon.spy(); + const hideSpy = sinon.spy(); + + ctrl.addEventListener('show', showSpy); + ctrl.addEventListener('hide', hideSpy); + + await ctrl.show(); + expect(showSpy.callCount).to.equal(1); + await ctrl.hide(); + expect(hideSpy.callCount).to.equal(1); + + ctrl.switchTo(global); + await ctrl.show(); + expect(showSpy.callCount).to.equal(2); + await ctrl.hide(); + expect(hideSpy.callCount).to.equal(2); + }); + }); + }); });