UNPKG

@etsoo/shared

Version:

TypeScript shared utilities and functions

142 lines (141 loc) 3.45 kB
import { EventBase, EventClass } from "./EventClass"; /** * ETSOO Extended history event */ export class EHistoryEvent extends EventBase { } /** * ETSOO Extended history navigate event */ export class EHistoryNavigateEvent extends EventBase { constructor(target, data) { super(target, "navigate", data); } } /** * ETSOO Extended abstract history class */ export class EHistory extends EventClass { /** * States length */ get length() { return this.states.length; } /** * Get current state index */ get index() { return this._index; } /** * Get current state */ get state() { if (this._index === -1) return undefined; return this.states[this._index]; } /** * Constructor * @param maxDepth Max depth of the history */ constructor(maxDepth = 20) { super(); this.maxDepth = maxDepth; // Index this._index = -1; /** * States */ this.states = []; } /** * Back to the previous state */ back() { this.go(-1); } /** * Clear all states but keep event listeners */ clear() { // https://stackoverflow.com/questions/1232040/how-do-i-empty-an-array-in-javascript this.states.length = 0; this._index = -1; this.trigger(this.createEvent("clear", this._index)); } /** * Create event * @param type Type * @param index Current index */ createEvent(type, index) { return new EHistoryEvent(this, type, { index }); } createNavigateEvent(index, delta) { return new EHistoryNavigateEvent(this, { index, delta }); } /** * Forward to the next state */ forward() { this.go(1); } /** * Get [undo, redo] status */ getStatus() { if (this.length < 2) return [false, false]; if (this._index <= 0) return [false, true]; if (this._index + 1 >= this.length) return [true, false]; return [true, true]; } /** * Go to the specific state * @param delta A negative value moves backwards, a positive value moves forwards */ go(delta) { // No data if (this._index === -1) return undefined; // New index const newIndex = this._index + delta; // Not in the range if (newIndex < 0 || newIndex >= this.length) return undefined; // Update the index this._index = newIndex; // Trigger event this.trigger(this.createNavigateEvent(newIndex, delta)); } /** * Adds an entry to the history stack * @param state State */ pushState(state) { if (this._index >= 0) { // Remove states after the index this.states.splice(this._index + 1); } this.states.push(state); this._index++; if (this.length > this.maxDepth) { this.states.shift(); } this.trigger(this.createEvent("push", this._index)); } /** * Modifies the current history entry * @param state State */ replaceState(state) { if (this._index === -1) return; this.states[this._index] = state; this.trigger(this.createEvent("replace", this._index)); } }