mirror of
https://github.com/codex-team/editor.js
synced 2024-05-19 23:06:49 +02:00
b7b00fd060
* block onchange stash * improve block filtration * update tool root * chore(block): remove willSelect und willUnselect * onchange events batching * get rid of CustomEvent extension, create custom event map instead * improve types of EventsDispatcher * fix tests * custom sinon + chai matchers * improve tests, add mutex for fake cursor * add test for fake-cursor mutex * test for batch filtering * fix caret setting by enter press at the end of the block * test for detectToolRootChange * remove resolved todos * changelog added * fix tests * Update CHANGELOG.md * rename FakeCursorAboutToBeSet -> FakeCursorAboutToBeToggled * update didMutated statements * move inputs cache clearing to a separate method * rm Record inheritance from Event maps * add type alisases * rename isElementContainsFakeCursor -> isFakeCursorInsideContainer * improve code style
113 lines
3 KiB
TypeScript
113 lines
3 KiB
TypeScript
import { isEmpty } from '../utils';
|
|
|
|
/**
|
|
* Event Dispatcher event listener
|
|
*/
|
|
type Listener<Data> = (data?: Data) => void;
|
|
|
|
/**
|
|
* Mapped type with subscriptions list
|
|
*
|
|
* event name -> array of callbacks
|
|
*/
|
|
type Subscriptions<EventMap> = {
|
|
[Key in keyof EventMap]: Listener<EventMap[Key]>[];
|
|
};
|
|
|
|
/**
|
|
* Provides methods for working with Event Bus:
|
|
* - {Function} on - appends subscriber to the event. If event doesn't exist - creates new one
|
|
* - {Function} emit - fires all subscribers with data
|
|
* - {Function off - unsubscribes callback
|
|
*/
|
|
export default class EventsDispatcher<EventMap> {
|
|
/**
|
|
* All subscribers grouped by event name
|
|
* Object with events` names as key and array of callback functions as value
|
|
*/
|
|
private subscribers = <Subscriptions<EventMap>>{};
|
|
|
|
/**
|
|
* Subscribe any event on callback
|
|
*
|
|
* @param eventName - event name
|
|
* @param callback - subscriber
|
|
*/
|
|
public on<Name extends keyof EventMap>(eventName: Name, callback: Listener<EventMap[Name]>): void {
|
|
if (!(eventName in this.subscribers)) {
|
|
this.subscribers[eventName] = [];
|
|
}
|
|
|
|
// group by events
|
|
this.subscribers[eventName].push(callback);
|
|
}
|
|
|
|
/**
|
|
* Subscribe any event on callback. Callback will be called once and be removed from subscribers array after call.
|
|
*
|
|
* @param eventName - event name
|
|
* @param callback - subscriber
|
|
*/
|
|
public once<Name extends keyof EventMap>(eventName: Name, callback: Listener<EventMap[Name]>): void {
|
|
if (!(eventName in this.subscribers)) {
|
|
this.subscribers[eventName] = [];
|
|
}
|
|
|
|
const wrappedCallback = (data: EventMap[typeof eventName]): void => {
|
|
const result = callback(data);
|
|
|
|
const indexOfHandler = this.subscribers[eventName].indexOf(wrappedCallback);
|
|
|
|
if (indexOfHandler !== -1) {
|
|
this.subscribers[eventName].splice(indexOfHandler, 1);
|
|
}
|
|
|
|
return result;
|
|
};
|
|
|
|
// group by events
|
|
this.subscribers[eventName].push(wrappedCallback);
|
|
}
|
|
|
|
/**
|
|
* Emit callbacks with passed data
|
|
*
|
|
* @param eventName - event name
|
|
* @param data - subscribers get this data when they were fired
|
|
*/
|
|
public emit<Name extends keyof EventMap>(eventName: Name, data?: EventMap[Name]): void {
|
|
if (isEmpty(this.subscribers) || !this.subscribers[eventName]) {
|
|
return;
|
|
}
|
|
|
|
this.subscribers[eventName].reduce((previousData, currentHandler) => {
|
|
const newData = currentHandler(previousData);
|
|
|
|
return newData !== undefined ? newData : previousData;
|
|
}, data);
|
|
}
|
|
|
|
/**
|
|
* Unsubscribe callback from event
|
|
*
|
|
* @param eventName - event name
|
|
* @param callback - event handler
|
|
*/
|
|
public off<Name extends keyof EventMap>(eventName: Name, callback: Listener<EventMap[Name]>): void {
|
|
for (let i = 0; i < this.subscribers[eventName].length; i++) {
|
|
if (this.subscribers[eventName][i] === callback) {
|
|
delete this.subscribers[eventName][i];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Destroyer
|
|
* clears subscribers list
|
|
*/
|
|
public destroy(): void {
|
|
this.subscribers = null;
|
|
}
|
|
}
|