import Cookie from '../cookie'; import {root} from '../root'; const JSON = root.JSON; const localStorage = root.localStorage; const location = root.location; /** * Checks if browser has Storage feature */ export const hasStorage = () => { return 'Storage' in root; }; /** * Stores the features state in browser's local storage or cookie * * @export * @class Storage */ export class Storage { /** * Creates an instance of Storage * * @param {State} state Instance of State */ constructor(state) { /** * State object * @type {State} * @private */ this.state = state; /** * TableFilter object * @type {TableFilter} * @private */ this.tf = state.tf; /** * Persist with local storage * @type {Boolean} * @private */ this.enableLocalStorage = state.enableLocalStorage && hasStorage(); /** * Persist with cookie * @type {Boolean} * @private */ this.enableCookie = state.enableCookie && !this.enableLocalStorage; /** * Emitter object * @type {Emitter} * @private */ this.emitter = state.emitter; /** * Cookie duration in hours from state object * @type {Number} * @private */ this.duration = state.cookieDuration; } /** * Initializes the Storage object */ init() { this.emitter.on(['state-changed'], (tf, state) => this.save(state)); this.emitter.on(['initialized'], () => this.sync()); } /** * Persists the features state on state changes * * @param {State} state Instance of State */ save(state) { if (this.enableLocalStorage) { localStorage[this.getKey()] = JSON.stringify(state); } else { Cookie.write(this.getKey(), JSON.stringify(state), this.duration); } } /** * Turns stored string into a State JSON object * * @returns {Object} JSON object */ retrieve() { let state = null; if (this.enableLocalStorage) { state = localStorage[this.getKey()]; } else { state = Cookie.read(this.getKey()); } if (!state) { return null; } return JSON.parse(state); } /** * Removes persisted state from storage */ remove() { if (this.enableLocalStorage) { localStorage.removeItem(this.getKey()); } else { Cookie.remove(this.getKey()); } } /** * Applies persisted state to features */ sync() { let state = this.retrieve(); if (!state) { return; } // override current state with persisted one and sync features this.state.overrideAndSync(state); } /** * Returns the storage key * * @returns {String} Key */ getKey() { return JSON.stringify({ key: `${this.tf.prfxTf}_${this.tf.id}`, path: location.pathname }); } /** * Release Storage event subscriptions and clear fields */ destroy() { this.emitter.off(['state-changed'], (tf, state) => this.save(state)); this.emitter.off(['initialized'], () => this.sync()); this.remove(); this.state = null; this.emitter = null; } }