import range from '../core/range';
export default class History {
constructor($editable) {
this.stack = [];
this.stackOffset = -1;
this.$editable = $editable;
this.editable = $editable[0];
}
makeSnapshot() {
const rng = range.create(this.editable);
const emptyBookmark = {s: {path: [], offset: 0}, e: {path: [], offset: 0}};
return {
contents: this.$editable.html(),
bookmark: (rng ? rng.bookmark(this.editable) : emptyBookmark)
};
}
applySnapshot(snapshot) {
Eif (snapshot.contents !== null) {
this.$editable.html(snapshot.contents);
}
Eif (snapshot.bookmark !== null) {
range.createFromBookmark(this.editable, snapshot.bookmark).select();
}
}
/**
* @method rewind
* Rewinds the history stack back to the first snapshot taken.
* Leaves the stack intact, so that "Redo" can still be used.
*/
rewind() {
// Create snap shot if not yet recorded
if (this.$editable.html() !== this.stack[this.stackOffset].contents) {
this.recordUndo();
}
// Return to the first available snapshot.
this.stackOffset = 0;
// Apply that snapshot.
this.applySnapshot(this.stack[this.stackOffset]);
}
/**
* @method reset
* Resets the history stack completely; reverting to an empty editor.
*/
reset() {
// Clear the stack.
this.stack = [];
// Restore stackOffset to its original value.
this.stackOffset = -1;
// Clear the editable area.
this.$editable.html('');
// Record our first snapshot (of nothing).
this.recordUndo();
}
/**
* undo
*/
undo() {
// Create snap shot if not yet recorded
Iif (this.$editable.html() !== this.stack[this.stackOffset].contents) {
this.recordUndo();
}
Eif (this.stackOffset > 0) {
this.stackOffset--;
this.applySnapshot(this.stack[this.stackOffset]);
}
}
/**
* redo
*/
redo() {
Eif (this.stack.length - 1 > this.stackOffset) {
this.stackOffset++;
this.applySnapshot(this.stack[this.stackOffset]);
}
}
/**
* recorded undo
*/
recordUndo() {
this.stackOffset++;
// Wash out stack after stackOffset
Iif (this.stack.length > this.stackOffset) {
this.stack = this.stack.slice(0, this.stackOffset);
}
// Create new snapshot and push it to the end
this.stack.push(this.makeSnapshot());
}
}
|