From 1f5192b4ad9f8199da85226f42eca2e87a133ae0 Mon Sep 17 00:00:00 2001 From: Konstantin Vyatkin Date: Tue, 29 Oct 2019 13:46:10 -0400 Subject: [PATCH] remove delegateEvents (#703) --- .github/workflows/lint.yml | 2 +- src/scripts/choices.js | 96 +++++++++++++++++++--------- src/scripts/components/input.js | 32 ++++++---- src/scripts/components/input.test.js | 11 ++-- src/scripts/lib/delegate-events.js | 39 ----------- 5 files changed, 92 insertions(+), 88 deletions(-) delete mode 100644 src/scripts/lib/delegate-events.js diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index f14001f..3fe5e90 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -27,7 +27,7 @@ jobs: - name: run eslint run: | - CHANGED_JS=$(git --no-pager diff --name-only ..origin/master | grep '^src\/scripts\/.*\.js$' | paste -sd " " -) + CHANGED_JS=$(git --no-pager diff --name-only ..origin/master | grep '^src\/scripts\/.*\.js$' | xargs ls -d 2>/dev/null | paste -sd " " -) if [[ -z $(sed -e 's/[[:space:]]*$//' <<<${CHANGED_JS}) ]]; then CHANGED_JS="src/scripts"; fi echo $CHANGED_JS node node_modules/eslint/bin/eslint.js $CHANGED_JS diff --git a/src/scripts/choices.js b/src/scripts/choices.js index 21ec34c..9e2a865 100644 --- a/src/scripts/choices.js +++ b/src/scripts/choices.js @@ -1,7 +1,6 @@ import Fuse from 'fuse.js'; import merge from 'deepmerge'; -import './lib/delegate-events'; import Store from './store/store'; import { Dropdown, @@ -1131,48 +1130,91 @@ class Choices { } _addEventListeners() { - window.delegateEvent.add('keyup', this._onKeyUp); - window.delegateEvent.add('keydown', this._onKeyDown); - window.delegateEvent.add('click', this._onClick); - window.delegateEvent.add('touchmove', this._onTouchMove); - window.delegateEvent.add('touchend', this._onTouchEnd); - window.delegateEvent.add('mousedown', this._onMouseDown); - window.delegateEvent.add('mouseover', this._onMouseOver); + const { documentElement } = document; + + // capture events - can cancel event processing or propagation + documentElement.addEventListener('keydown', this._onKeyDown, true); + documentElement.addEventListener('touchend', this._onTouchEnd, true); + documentElement.addEventListener('mousedown', this._onMouseDown, true); + + // passive events - doesn't call `preventDefault` or `stopPropagation` + documentElement.addEventListener('click', this._onClick, { passive: true }); + documentElement.addEventListener('touchmove', this._onTouchMove, { + passive: true, + }); + documentElement.addEventListener('mouseover', this._onMouseOver, { + passive: true, + }); if (this._isSelectOneElement) { - this.containerOuter.element.addEventListener('focus', this._onFocus); - this.containerOuter.element.addEventListener('blur', this._onBlur); + this.containerOuter.element.addEventListener('focus', this._onFocus, { + passive: true, + }); + this.containerOuter.element.addEventListener('blur', this._onBlur, { + passive: true, + }); } - this.input.element.addEventListener('focus', this._onFocus); - this.input.element.addEventListener('blur', this._onBlur); + this.input.element.addEventListener('keyup', this._onKeyUp, { + passive: true, + }); + + this.input.element.addEventListener('focus', this._onFocus, { + passive: true, + }); + this.input.element.addEventListener('blur', this._onBlur, { + passive: true, + }); if (this.input.element.form) { - this.input.element.form.addEventListener('reset', this._onFormReset); + this.input.element.form.addEventListener('reset', this._onFormReset, { + passive: true, + }); } this.input.addEventListeners(); } _removeEventListeners() { - window.delegateEvent.remove('keyup', this._onKeyUp); - window.delegateEvent.remove('keydown', this._onKeyDown); - window.delegateEvent.remove('click', this._onClick); - window.delegateEvent.remove('touchmove', this._onTouchMove); - window.delegateEvent.remove('touchend', this._onTouchEnd); - window.delegateEvent.remove('mousedown', this._onMouseDown); - window.delegateEvent.remove('mouseover', this._onMouseOver); + const { documentElement } = document; + + documentElement.removeEventListener('keydown', this._onKeyDown, true); + documentElement.removeEventListener('touchend', this._onTouchEnd, true); + documentElement.removeEventListener('mousedown', this._onMouseDown, true); + + documentElement.removeEventListener('keyup', this._onKeyUp, { + passive: true, + }); + documentElement.removeEventListener('click', this._onClick, { + passive: true, + }); + documentElement.removeEventListener('touchmove', this._onTouchMove, { + passive: true, + }); + documentElement.removeEventListener('mouseover', this._onMouseOver, { + passive: true, + }); if (this._isSelectOneElement) { - this.containerOuter.element.removeEventListener('focus', this._onFocus); - this.containerOuter.element.removeEventListener('blur', this._onBlur); + this.containerOuter.element.removeEventListener('focus', this._onFocus, { + passive: true, + }); + this.containerOuter.element.removeEventListener('blur', this._onBlur, { + passive: true, + }); } - this.input.element.removeEventListener('focus', this._onFocus); - this.input.element.removeEventListener('blur', this._onBlur); + this.input.element.removeEventListener('focus', this._onFocus, { + passive: true, + }); + this.input.element.removeEventListener('blur', this._onBlur, { + passive: true, + }); if (this.input.element.form) { - this.input.element.form.removeEventListener('reset', this._onFormReset); + this.input.element.form.removeEventListener('reset', this._onFormReset, { + passive: true, + }); } this.input.removeEventListeners(); @@ -1242,10 +1284,6 @@ class Choices { } _onKeyUp({ target, keyCode }) { - if (target !== this.input.element) { - return; - } - const { value } = this.input; const { activeItems } = this._store; const canAddItem = this._canAddItem(activeItems, value); diff --git a/src/scripts/components/input.js b/src/scripts/components/input.js index dec6051..a5d59cb 100644 --- a/src/scripts/components/input.js +++ b/src/scripts/components/input.js @@ -34,25 +34,29 @@ export default class Input { } addEventListeners() { - this.element.addEventListener('input', this._onInput); this.element.addEventListener('paste', this._onPaste); - this.element.addEventListener('focus', this._onFocus); - this.element.addEventListener('blur', this._onBlur); - - if (this.element.form) { - this.element.form.addEventListener('reset', this._onFormReset); - } + this.element.addEventListener('input', this._onInput, { + passive: true, + }); + this.element.addEventListener('focus', this._onFocus, { + passive: true, + }); + this.element.addEventListener('blur', this._onBlur, { + passive: true, + }); } removeEventListeners() { - this.element.removeEventListener('input', this._onInput); + this.element.removeEventListener('input', this._onInput, { + passive: true, + }); this.element.removeEventListener('paste', this._onPaste); - this.element.removeEventListener('focus', this._onFocus); - this.element.removeEventListener('blur', this._onBlur); - - if (this.element.form) { - this.element.form.removeEventListener('reset', this._onFormReset); - } + this.element.removeEventListener('focus', this._onFocus, { + passive: true, + }); + this.element.removeEventListener('blur', this._onBlur, { + passive: true, + }); } enable() { diff --git a/src/scripts/components/input.test.js b/src/scripts/components/input.test.js index 2065335..3ea3d71 100644 --- a/src/scripts/components/input.test.js +++ b/src/scripts/components/input.test.js @@ -46,11 +46,12 @@ describe('components/input', () => { it('adds event listeners', () => { instance.addEventListeners(); - expect(addEventListenerStub.callCount).to.equal(4); - expect(addEventListenerStub.getCall(0).args[0]).to.equal('input'); - expect(addEventListenerStub.getCall(1).args[0]).to.equal('paste'); - expect(addEventListenerStub.getCall(2).args[0]).to.equal('focus'); - expect(addEventListenerStub.getCall(3).args[0]).to.equal('blur'); + expect(['input', 'paste', 'focus', 'blur']).to.have.members( + Array.from( + { length: addEventListenerStub.callCount }, + (v, i) => addEventListenerStub.getCall(i).args[0], + ), + ); }); }); diff --git a/src/scripts/lib/delegate-events.js b/src/scripts/lib/delegate-events.js deleted file mode 100644 index e327b73..0000000 --- a/src/scripts/lib/delegate-events.js +++ /dev/null @@ -1,39 +0,0 @@ -window.delegateEvent = (function delegateEvent() { - let events; - let addedListenerTypes; - if (typeof events === 'undefined') { - events = new Map(); - } - if (typeof addedListenerTypes === 'undefined') { - addedListenerTypes = []; - } - - function _callback(event) { - const type = events.get(event.type); - if (!type) return; - type.forEach(fn => fn(event)); - } - - return { - add: function add(type, fn) { - // Cache list of events. - if (events.has(type)) { - events.get(type).push(fn); - } else { - events.set(type, [fn]); - } - // Setup events. - if (addedListenerTypes.indexOf(type) === -1) { - document.documentElement.addEventListener(type, _callback, true); - addedListenerTypes.push(type); - } - }, - remove: function remove(type, fn) { - if (!events.get(type)) return; - events.set(type, events.get(type).filter(item => item !== fn)); - if (!events.get(type).length) { - addedListenerTypes.splice(addedListenerTypes.indexOf(type), 1); - } - }, - }; -})();