mirror of https://github.com/artf/grapesjs.git
13 changed files with 349 additions and 208 deletions
@ -0,0 +1,237 @@ |
|||
/** |
|||
* 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; |
|||
} |
|||
}; |
|||
}; |
|||
Loading…
Reference in new issue