mirror of
https://github.com/Choices-js/Choices.git
synced 2024-06-16 12:45:10 +02:00
Use event delegation (#644)
Instead of attaching a new root-level event listener for bubbling events for every choices instance, use a simple event delegation script to handle each event type. Each event callback function already is coded as if it were fully delegated, since the events are attached at the document level, so no changes are needed to detect which element is being called. Note that focus and blur event do not bubble, so they have been left as they are. Also note that the event delegation uses an IIFE purposely instead of ES6 modules, since the event list should be globally cached, and it doesn't make sense to instantiate a new scope for each instance (then we're back where we started!) fix #643
This commit is contained in:
parent
5cf226f166
commit
e7d775e2ae
|
@ -1,6 +1,7 @@
|
|||
import Fuse from 'fuse.js';
|
||||
import merge from 'deepmerge';
|
||||
|
||||
import './lib/delegate-events';
|
||||
import Store from './store/store';
|
||||
import {
|
||||
Dropdown,
|
||||
|
@ -1072,13 +1073,13 @@ class Choices {
|
|||
}
|
||||
|
||||
_addEventListeners() {
|
||||
document.addEventListener('keyup', this._onKeyUp);
|
||||
document.addEventListener('keydown', this._onKeyDown);
|
||||
document.addEventListener('click', this._onClick);
|
||||
document.addEventListener('touchmove', this._onTouchMove);
|
||||
document.addEventListener('touchend', this._onTouchEnd);
|
||||
document.addEventListener('mousedown', this._onMouseDown);
|
||||
document.addEventListener('mouseover', this._onMouseOver);
|
||||
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);
|
||||
|
||||
if (this._isSelectOneElement) {
|
||||
this.containerOuter.element.addEventListener('focus', this._onFocus);
|
||||
|
@ -1096,13 +1097,13 @@ class Choices {
|
|||
}
|
||||
|
||||
_removeEventListeners() {
|
||||
document.removeEventListener('keyup', this._onKeyUp);
|
||||
document.removeEventListener('keydown', this._onKeyDown);
|
||||
document.removeEventListener('click', this._onClick);
|
||||
document.removeEventListener('touchmove', this._onTouchMove);
|
||||
document.removeEventListener('touchend', this._onTouchEnd);
|
||||
document.removeEventListener('mousedown', this._onMouseDown);
|
||||
document.removeEventListener('mouseover', this._onMouseOver);
|
||||
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);
|
||||
|
||||
if (this._isSelectOneElement) {
|
||||
this.containerOuter.element.removeEventListener('focus', this._onFocus);
|
||||
|
|
39
src/scripts/lib/delegate-events.js
Normal file
39
src/scripts/lib/delegate-events.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
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);
|
||||
}
|
||||
},
|
||||
};
|
||||
})();
|
Loading…
Reference in a new issue