UNPKG

grapesjs

Version:

Free and Open Source Web Builder Framework

243 lines (203 loc) 4.46 kB
/** * This module allows to manage the stack of changes applied in canvas * * You can access the module in this way * ```js * const um = editor.UndoManager; * ``` * */ import UndoManager from 'backbone-undo'; module.exports = () => { let em; let um; let config; let beforeCache; const configDef = {}; return { name: 'UndoManager', /** * Initialize module * @param {Object} config Configurations * @private */ init(opts = {}) { config = { ...opts, ...configDef }; em = config.em; this.em = em; um = new UndoManager({ track: true, register: [] }); um.changeUndoType('change', { condition: false }); const customUndoType = { on(object, value, opt = {}) { !beforeCache && (beforeCache = object.previousAttributes()); if (opt.avoidStore) { return; } else { const result = { object, before: beforeCache, after: object.toJSON() }; beforeCache = null; return result; } }, undo(model, bf, af, opt) { model.set(bf); }, redo(model, bf, af, opt) { model.set(af); } }; const events = ['style', 'attributes', 'content', 'src']; events.forEach(ev => um.addUndoType(`change:${ev}`, customUndoType)); um.on('undo redo', () => em.trigger('change:selectedComponent change:canvasOffset')); ['undo', 'redo'].forEach(ev => um.on(ev, () => em.trigger(ev))); return this; }, /** * Get module configurations * @return {Object} Configuration object * @example * const config = um.getConfig(); * // { ... } */ getConfig() { return config; }, /** * Add an entity (Model/Collection) to track * Note: New Components and CSSRules will be added automatically * @param {Model|Collection} entity Entity to track * @return {this} * @example * um.add(someModelOrCollection); */ add(entity) { um.register(entity); return this; }, /** * Remove and stop tracking the entity (Model/Collection) * @param {Model|Collection} entity Entity to remove * @return {this} * @example * um.remove(someModelOrCollection); */ remove(entity) { um.unregister(entity); return this; }, /** * Remove all entities * @return {this} * @example * um.removeAll(); */ removeAll() { um.unregisterAll(); return this; }, /** * Start/resume tracking changes * @return {this} * @example * um.start(); */ start() { um.startTracking(); return this; }, /** * Stop tracking changes * @return {this} * @example * um.stop(); */ stop() { um.stopTracking(); return this; }, /** * Undo last change * @return {this} * @example * um.undo(); */ undo() { if (!em.get('Canvas').isInputFocused()) um.undo(1); return this; }, /** * Undo all changes * @return {this} * @example * um.undoAll(); */ undoAll() { um.undoAll(); return this; }, /** * Redo last change * @return {this} * @example * um.redo(); */ redo() { if (!em.get('Canvas').isInputFocused()) um.redo(1); return this; }, /** * Redo all changes * @return {this} * @example * um.redoAll(); */ redoAll() { um.redoAll(); return this; }, /** * Checks if exists an available undo * @return {Boolean} * @example * um.hasUndo(); */ hasUndo() { return um.isAvailable('undo'); }, /** * Checks if exists an available redo * @return {Boolean} * @example * um.hasRedo(); */ hasRedo() { return um.isAvailable('redo'); }, /** * Get stack of changes * @return {Collection} * @example * const stack = um.getStack(); * stack.each(item => ...); */ getStack() { return um.stack; }, /** * Clear the stack * @return {this} * @example * um.clear(); */ clear() { um.clear(); return this; }, getInstance() { return um; } }; };