UNPKG

maplair

Version:

JavaScript library for mobile-friendly interactive maps

149 lines (148 loc) • 4.59 kB
import { falseFn, splitWords, stamp } from "./Util.js"; import { Class } from "./Class.js"; //#region src/core/Events.js var Evented = class Evented extends Class { on(types, fn, context) { if (typeof types === "object") for (const [type, f] of Object.entries(types)) this._on(type, f, fn); else for (const type of splitWords(types)) this._on(type, fn, context); return this; } off(types, fn, context) { if (!arguments.length) { delete this._events; delete this._listenerIndex; } else if (typeof types === "object") for (const [type, f] of Object.entries(types)) this._off(type, f, fn); else { const removeAll = arguments.length === 1; for (const type of splitWords(types)) if (removeAll) this._off(type); else this._off(type, fn, context); } return this; } static __REMOVED_EVENTS = [ "mousedown", "mouseup", "mouseover", "mouseout", "mousemove" ]; _on(type, fn, context, _once) { if (Evented.__REMOVED_EVENTS.includes(type)) console.error(`The event ${type} has been removed. Use the PointerEvent variant instead.`); if (typeof fn !== "function") { console.warn(`wrong listener type: ${typeof fn}`); return; } if (context === this) context = void 0; const contexts = this._getListenerIndex(type).get(fn); if (contexts?.has(context)) return; const newListener = { fn, ctx: context }; if (_once) newListener.once = true; this._events ??= {}; this._events[type] ??= /* @__PURE__ */ new Set(); this._events[type].add(newListener); if (contexts) contexts.set(context, newListener); else this._listenerIndex[type].set(fn, /* @__PURE__ */ new Map([[context, newListener]])); } _getListenerIndex(type) { this._listenerIndex ??= {}; return this._listenerIndex[type] ??= /* @__PURE__ */ new Map(); } _off(type, fn, context) { if (!this._events) return; let listeners = this._events[type]; if (!listeners) return; if (arguments.length === 1) { if (this._firingCount) for (const listener of listeners) listener.fn = falseFn; delete this._events[type]; delete this._listenerIndex?.[type]; return; } if (typeof fn !== "function") { console.warn(`wrong listener type: ${typeof fn}`); return; } if (context === this) context = void 0; const contexts = this._listenerIndex?.[type]?.get(fn), listener = contexts?.get(context); if (listener) { contexts.delete(context); if (!contexts.size) this._listenerIndex[type].delete(fn); if (this._firingCount) { listener.fn = falseFn; this._events[type] = listeners = new Set(listeners); } listeners.delete(listener); } } fire(type, data, propagate) { if (!this.listens(type, propagate)) return this; const event = { ...data, type, target: this, sourceTarget: data?.sourceTarget || this }; if (this._events) { const listeners = this._events[type]; if (listeners) { this._firingCount = this._firingCount + 1 || 1; for (const l of listeners) { const fn = l.fn; if (l.once) this.off(type, fn, l.ctx); fn.call(l.ctx || this, event); } this._firingCount--; } } if (propagate) this._propagateEvent(event); return this; } listens(type, fn, context, propagate) { if (typeof type !== "string") console.warn("\"string\" type argument expected"); let _fn = fn; if (typeof fn !== "function") { propagate = !!fn; _fn = void 0; context = void 0; } if (this._events?.[type]?.size) { if (this._listens(type, _fn, context) !== false) return true; } if (propagate) { for (const p of Object.values(this._eventParents ?? {})) if (p.listens(type, fn, context, propagate)) return true; } return false; } _listens(type, fn, context) { if (!this._events) return false; const listeners = this._events[type]; if (!fn) return !!listeners?.size; if (context === this) context = void 0; return !!this._listenerIndex?.[type]?.get(fn)?.has(context); } once(types, fn, context) { if (typeof types === "object") for (const [type, f] of Object.entries(types)) this._on(type, f, fn, true); else for (const type of splitWords(types)) this._on(type, fn, context, true); return this; } addEventParent(obj) { this._eventParents ??= {}; this._eventParents[stamp(obj)] = obj; return this; } removeEventParent(obj) { if (this._eventParents) delete this._eventParents[stamp(obj)]; return this; } _propagateEvent(e) { for (const p of Object.values(this._eventParents ?? {})) p.fire(e.type, { propagatedFrom: e.target, ...e }, true); } }; //#endregion export { Evented }; //# sourceMappingURL=Events.js.map