@ima/core
Version:
IMA.js framework for isomorphic javascript application
164 lines (163 loc) • 5.96 kB
JavaScript
import { EventBus } from './EventBus';
import { GenericError } from '../error/GenericError';
import { Window } from '../window/Window';
/**
* Global name of IMA.js custom event.
*/ export const IMA_EVENT = '$IMA.CustomEvent';
/**
* Helper for custom events.
*
* It offers public methods for firing custom events and two methods for
* catching events (e.g. inside view components).
*/ export class EventBusImpl extends EventBus {
_window;
/**
* Map of listeners provided to the public API of this event bus to a
* map of event targets to a map of event names to actual listeners
* bound to the native API.
*
* The "listen all" event listeners are not registered in this map.
*/ _listeners = new WeakMap();
/**
* Map of event targets to listeners executed on all IMA.js event bus
* events.
*/ _allListenersTargets = new WeakMap();
static get $dependencies() {
return [
Window
];
}
/**
* Initializes the custom event helper.
*
* @param window The IMA window helper.
*/ constructor(window){
super();
/**
* The IMA window helper.
*/ this._window = window;
}
/**
* @inheritDoc
*/ fire(eventTarget, eventName, data, options = {}) {
const eventInitialization = {};
const params = {
detail: {
eventName,
data
}
};
const defaultOptions = {
bubbles: true,
cancelable: true
};
Object.assign(eventInitialization, defaultOptions, options, params);
const event = this._window.createCustomEvent(IMA_EVENT, eventInitialization);
if (eventTarget && typeof eventTarget.dispatchEvent !== 'undefined') {
eventTarget.dispatchEvent(event);
} else {
throw new GenericError(`ima.core.event.EventBusImpl.fire: The EventSource ` + `${eventTarget} is not defined or can not dispatch event ` + `'${eventName}' (data: ${data}).`, {
eventTarget,
eventName,
data,
eventInitialization
});
}
return this;
}
/**
* @inheritDoc
*/ listenAll(eventTarget, listener) {
if (!this._allListenersTargets.has(eventTarget)) {
this._allListenersTargets.set(eventTarget, new WeakMap());
}
const nativeListener = (event)=>{
if (event.type === IMA_EVENT && event.detail && event.detail.eventName) {
listener(event);
}
};
this._allListenersTargets.get(eventTarget).set(listener, nativeListener);
this._window.bindEventListener(eventTarget, IMA_EVENT, nativeListener);
return this;
}
/**
* @inheritDoc
*/ listen(eventTarget, eventName, listener) {
if (!eventTarget) {
if ($Debug) {
console.warn(`The eventTarget is not defined for event '${eventName}'.`);
}
return this;
}
if (!this._listeners.has(listener)) {
this._listeners.set(listener, new WeakMap());
}
const targetToEventName = this._listeners.get(listener);
if (!targetToEventName.has(eventTarget)) {
targetToEventName.set(eventTarget, new Map());
}
const eventNameToNativeListener = targetToEventName.get(eventTarget);
const nativeListener = (event)=>{
if (event.type === IMA_EVENT && event.detail && event.detail.eventName === eventName) {
listener(event);
}
};
eventNameToNativeListener.set(eventName, nativeListener);
this._window.bindEventListener(eventTarget, IMA_EVENT, nativeListener);
return this;
}
/**
* @inheritDoc
*/ unlistenAll(eventTarget, listener) {
if (!this._allListenersTargets.has(eventTarget)) {
if ($Debug) {
console.warn('The provided listener is not registered on the ' + 'specified event target');
}
return this;
}
const listeners = this._allListenersTargets.get(eventTarget);
if (!listeners.has(listener)) {
if ($Debug) {
console.warn('The provided listener is not registered on the ' + 'specified event target');
}
return this;
}
const nativeListener = listeners.get(listener);
this._window.unbindEventListener(eventTarget, IMA_EVENT, nativeListener);
listeners.delete(listener);
return this;
}
/**
* @inheritDoc
*/ unlisten(eventTarget, eventName, listener) {
if (!this._listeners.has(listener)) {
if ($Debug) {
console.warn('The provided listener is not bound to listen for the ' + 'specified event on the specified event target.');
}
return this;
}
const targets = this._listeners.get(listener);
if (!targets.has(eventTarget)) {
if ($Debug) {
console.warn('The provided listener is not bound to listen for the ' + 'specified event on the specified event target.');
}
return this;
}
const eventNameToNativeListener = targets.get(eventTarget);
if (!eventNameToNativeListener.has(eventName)) {
if ($Debug) {
console.warn('The provided listener is not bound to listen for the ' + 'specified event on the specified event target.');
}
return this;
}
const nativeListener = eventNameToNativeListener.get(eventName);
this._window.unbindEventListener(eventTarget, IMA_EVENT, nativeListener);
eventNameToNativeListener.delete(eventName);
if (eventNameToNativeListener.size) {
return this;
}
targets.delete(eventTarget);
return this;
}
}
//# sourceMappingURL=EventBusImpl.js.map