Skip to content

Instantly share code, notes, and snippets.

@ducksoupdev
Created October 20, 2016 08:14
Show Gist options
  • Select an option

  • Save ducksoupdev/1e13d40debea2d19d9ff6f20678a630c to your computer and use it in GitHub Desktop.

Select an option

Save ducksoupdev/1e13d40debea2d19d9ff6f20678a630c to your computer and use it in GitHub Desktop.
Angular_1_undo_manager_service
namespace MyModule {
export interface IUndoCommand {
undo: Function;
redo: Function;
}
export interface IUndoManagerService {
add(command: IUndoCommand): IUndoManagerService;
setCallback(callback: Function);
undo(): IUndoManagerService;
redo(): IUndoManagerService;
clear();
hasUndo(): boolean;
hasRedo(): boolean;
getCommands(): IUndoCommand[];
getIndex(): number;
setLimit(limit: number);
}
export class UndoManagerService implements IUndoManagerService {
private commands: IUndoCommand[];
private index = -1;
private limit = 0;
private isExecuting = false;
private callback: Function;
constructor() {
this.commands = [];
}
private execute(command: IUndoCommand, action: string) {
if (!command || typeof command[action] !== "function") {
return this;
}
this.isExecuting = true;
// call the command
command[action]();
this.isExecuting = false;
return this;
}
private removeFromTo(array: any[], from: number, to: number): number {
array.splice(from,
!to ||
1 + to - from + (!(to < 0 ^ from >= 0) && (to < 0 || -1) * array.length));
return array.length;
}
add(command: IUndoCommand) {
if (this.isExecuting) {
return this;
}
// if we are here after having called undo,
// invalidate items higher on the stack
this.commands.splice(this.index + 1, this.commands.length - this.index);
this.commands.push(command);
// if limit is set, remove items from the start
if (this.limit && this.commands.length > this.limit) {
this.removeFromTo(this.commands, 0, -(this.limit + 1));
}
// set the current index to the end
this.index = this.commands.length - 1;
if (this.callback) {
this.callback();
}
return this;
}
setCallback(callback: Function) {
this.callback = callback;
}
undo() {
var command = this.commands[this.index];
if (!command) {
return this;
}
this.execute(command, "undo");
this.index -= 1;
if (this.callback) {
this.callback();
}
return this;
}
redo() {
var command = this.commands[this.index + 1];
if (!command) {
return this;
}
this.execute(command, "redo");
this.index += 1;
if (this.callback) {
this.callback();
}
return this;
}
clear() {
let prev_size = this.commands.length;
this.commands = [];
this.index = -1;
if (this.callback && (prev_size > 0)) {
this.callback();
}
}
hasUndo() {
return this.index !== -1;
}
hasRedo() {
return this.index < (this.commands.length - 1);
}
getCommands() {
return this.commands;
}
getIndex() {
return this.index;
}
setLimit(limit: number) {
this.limit = limit;
}
}
angular
.module('myModule')
.service('undoManagerService', UndoManagerService);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment