@etsoo/shared
Version:
TypeScript shared utilities and functions
161 lines (160 loc) • 4.23 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EventClass = exports.EventBase = void 0;
/**
* Abstract event base class
* T for type
* D for data
*/
class EventBase {
/**
* stopImmediatePropagation called
*/
get propagationStopped() {
return this._propagationStopped;
}
/**
* Time stamp
*/
get timeStamp() {
return this._timeStamp;
}
/**
* Constructor
* @param type Type
*/
constructor(target, type, data) {
this.target = target;
this.type = type;
this.data = data;
this._propagationStopped = false;
this._timeStamp = Date.now();
}
/**
* Prevent all other listeners from being called
*/
stopImmediatePropagation() {
this._propagationStopped = true;
}
}
exports.EventBase = EventBase;
/**
* Event class
* T for type
* D for data
*/
class EventClass {
constructor() {
// Listeners
this.listeners = new Map();
}
/**
* Has specific type and callback events
* @param type Type
* @param callback Callback
* @returns Result
*/
hasEvents(type, callback) {
const items = this.listeners.get(type);
if (items == null || items.length === 0)
return false;
if (callback) {
return items.some((item) => item[0] == callback);
}
return true;
}
/**
* Remove specific type and callback event
* @param type Type
* @param callback Callback
*/
off(type, callback) {
if (callback == null) {
this.listeners.delete(type);
return;
}
const items = this.listeners.get(type);
if (items == null)
return;
for (let i = items.length - 1; i >= 0; i--) {
if (items[i][0] == callback) {
items.splice(i, 1);
}
}
}
/**
* Add events
* @param type Type
* @param callback Callback
* @param options Options
*/
on(type, callback, options) {
if (typeof type === "object") {
for (const key in type) {
const item = key;
const itemCallback = type[item] ?? callback;
if (itemCallback)
this.on(item, itemCallback, options);
}
return;
}
if (callback == null)
return;
this.listeners.has(type) || this.listeners.set(type, []);
// String to T conversion problem
// "keyofStringsOnly": true could solve part of it
this.listeners.get(type)?.push([callback, options]);
}
/**
* Trigger event
* @param event Event
*/
trigger(event) {
const items = this.listeners.get(event.type);
if (items == null)
return;
// Len
const len = items.length;
if (len === 0)
return;
// Need to be removed indicies
const indicies = [];
// Capture items first
let stopped = false;
for (let c = 0; c < len; c++) {
const item = items[c];
const [callback, options] = item;
if (options == null || !options.capture)
continue;
callback(event);
if (options.once) {
indicies.push(c);
}
if (event.propagationStopped) {
stopped = true;
break;
}
}
if (!stopped) {
for (let c = 0; c < len; c++) {
const item = items[c];
const [callback, options] = item;
if (options?.capture)
continue;
callback(event);
if (options?.once) {
indicies.push(c);
}
if (event.propagationStopped) {
stopped = true;
break;
}
}
}
// Remove all once handlers
for (let i = indicies.length - 1; i >= 0; i--) {
items.splice(indicies[i], 1);
}
}
}
exports.EventClass = EventClass;