octobercms
Version:
AJAX Framework for October CMS
107 lines (91 loc) • 3.56 kB
JavaScript
import { EventListener } from "./event-listener";
export class Dispatcher
{
constructor(application) {
this.application = application;
this.eventListenerMaps = new Map();
this.started = false;
}
start() {
if (!this.started) {
this.started = true;
this.eventListeners.forEach((eventListener) => eventListener.connect());
}
}
stop() {
if (this.started) {
this.started = false;
this.eventListeners.forEach((eventListener) => eventListener.disconnect());
}
}
get eventListeners() {
return Array.from(this.eventListenerMaps.values()).reduce((listeners, map) => listeners.concat(Array.from(map.values())), []);
}
// Binding observer delegate
bindingConnected(binding) {
this.fetchEventListenerForBinding(binding).bindingConnected(binding);
}
bindingDisconnected(binding, clearEventListeners = false) {
this.fetchEventListenerForBinding(binding).bindingDisconnected(binding);
if (clearEventListeners)
this.clearEventListenersForBinding(binding);
}
// Error handling
handleError(error, message, detail = {}) {
this.application.handleError(error, `Error ${message}`, detail);
}
clearEventListenersForBinding(binding) {
const eventListener = this.fetchEventListenerForBinding(binding);
if (!eventListener.hasBindings()) {
eventListener.disconnect();
this.removeMappedEventListenerFor(binding);
}
}
removeMappedEventListenerFor(binding) {
const { eventTarget, eventName, eventOptions } = binding;
const eventListenerMap = this.fetchEventListenerMapForEventTarget(eventTarget);
const cacheKey = this.cacheKey(eventName, eventOptions);
eventListenerMap.delete(cacheKey);
if (eventListenerMap.size == 0) {
this.eventListenerMaps.delete(eventTarget);
}
}
fetchEventListenerForBinding(binding) {
const { eventTarget, eventName, eventOptions } = binding;
return this.fetchEventListener(eventTarget, eventName, eventOptions);
}
fetchEventListener(eventTarget, eventName, eventOptions) {
const eventListenerMap = this.fetchEventListenerMapForEventTarget(eventTarget);
const cacheKey = this.cacheKey(eventName, eventOptions);
let eventListener = eventListenerMap.get(cacheKey);
if (!eventListener) {
eventListener = this.createEventListener(eventTarget, eventName, eventOptions);
eventListenerMap.set(cacheKey, eventListener);
}
return eventListener;
}
createEventListener(eventTarget, eventName, eventOptions) {
const eventListener = new EventListener(eventTarget, eventName, eventOptions);
if (this.started) {
eventListener.connect();
}
return eventListener;
}
fetchEventListenerMapForEventTarget(eventTarget) {
let eventListenerMap = this.eventListenerMaps.get(eventTarget);
if (!eventListenerMap) {
eventListenerMap = new Map();
this.eventListenerMaps.set(eventTarget, eventListenerMap);
}
return eventListenerMap;
}
cacheKey(eventName, eventOptions) {
const parts = [eventName];
Object.keys(eventOptions)
.sort()
.forEach((key) => {
parts.push(`${eventOptions[key] ? "" : "!"}${key}`);
});
return parts.join(":");
}
}