Undo Manager
Simple undo manager to provide undo and redo actions in JavaScript applications.
Demos
Installation
npm
npm install undo-manager
Bower
bower install undo-manager
jspm
jspm install npm:undo-manager
Background
Actions (typing a character, moving an object) are structured as command pairs: one command for destruction (undo) and one for creation (redo). Each pair is added to the undo stack:
var undoManager = new UndoManager(); undoManager.add({ undo: function() { // ... }, redo: function() { // ... } });
Note that you are responsible for the initial creation; Undo Manager only bothers with destruction and recreation.
Example
var undoManager = new UndoManager(), people = {}, addPerson, removePerson, createPerson; addPerson = function(id, name) { people[id] = name; }; removePerson = function(id) { delete people[id]; }; createPerson = function (id, name) { // first creation addPerson(id, name); // make undo-able undoManager.add({ undo: function() { removePerson(id) }, redo: function() { addPerson(id, name); } }); } createPerson(101, "John"); createPerson(102, "Mary"); console.log("people", people); // {101: "John", 102: "Mary"} undoManager.undo(); console.log("people", people); // {101: "John"} undoManager.undo(); console.log("people", people); // {} undoManager.redo(); console.log("people", people); // {101: "John"}
Methods
undoManager.undo();
Performs the undo action.
undoManager.redo();
Performs the redo action.
undoManager.clear();
Clears all stored states.
undoManager.setLimit(limit);
Set the maximum number of undo steps. Default: 0 (unlimited).
var hasUndo = undoManager.hasUndo();
Tests if any undo actions exist.
var hasRedo = undoManager.hasRedo();
Tests if any redo actions exist.
undoManager.setCallback(myCallback);
Get notified on changes.
var index = undoManager.getIndex();
Returns the index of the actions list.
Use with CommonJS (Webpack, Browserify, Node, etc)
npm install undo-manager
var UndoManager = require('undo-manager')
If you only need a single instance of UndoManager throughout your application, it may be wise to create a module that exports a singleton:
In undoManager.js
:
var UndoManager = require('undo-manager'); // require the lib from node_modules var singleton; if (!singleton) { singleton = new UndoManager(); } module.exports = singleton;
Then in your app:
var undoManager = require('undoManager'); undoManager.add(...); undoManager.undo();
Use with RequireJS
If you are using RequireJS, you need to use the shim
config parameter.
Assuming require.js
and domReady.js
are located in js/extern
, the index.html
load call would be:
<script src="js/extern/require.js" data-main="js/demo"></script>
And demo.js
would look like this:
requirejs.config({ baseUrl: "js", paths: { domReady: "extern/domReady", app: "../demo", undomanager: "../../js/undomanager", circledrawer: "circledrawer" }, shim: { "undomanager": { exports: "UndoManager" }, "circledrawer": { exports: "CircleDrawer" } } }); require(["domReady", "undomanager", "circledrawer"], function(domReady, UndoManager, CircleDrawer) { "use strict"; var undoManager, circleDrawer, btnUndo, btnRedo, btnClear; undoManager = new UndoManager(); circleDrawer = new CircleDrawer("view", undoManager); // etcetera });