var e = {}; //lets store references to the dom elemements
Array.prototype.slice.call(document.querySelectorAll("[id]")).
forEach(function (el) { e[el.id] = el; });
function UndoRedo(update_callback, clear_callback) {
this.update_callback = update_callback;
this.clear_callback = clear_callback;
this.clear();
}
UndoRedo.prototype = {
clear: function () {
this.stack = [];
this.stackPos = 0;
if (this.clear_callback) this.clear_callback();
this.update();
},
update: function () {
if (this.update_callback) this.update_callback();
},
canUndo: function () {
return this.stackPos > 0;
},
canRedo: function () {
return this.stackPos < this.stack.length;
},
doAction: function (doProc, undoProc) {
this.stack.splice(this.stackPos);
this.stack.push({
do: doProc,
undo: undoProc
});
this.stackPos ++;
doProc();
this.update();
},
undo: function () {
var p = this.stack[this.stackPos - 1];
this.stackPos --;
p.undo();
this.update();
},
redo: function () {
var p = this.stack[this.stackPos];
this.stackPos ++;
p.do();
this.update();
}
};
var
names = [],
undoRedo = new UndoRedo(
function update() {
e.lbNames.textContent = names.join(', ');
e.btUndo.disabled = !this.canUndo();
e.btRedo.disabled = !this.canRedo();
e.lbBuffer.textContent = this.stack.length;
},
function cleared() {
names = [];
}
);
btAdd.onclick = function () {
if (!ipName.value) return alert("Please enter some text");
undoRedo.doAction(
function add(name) {
return function () {
e.ipName.value = '';
e.ipName.focus();
names.push(name);
}
}(ipName.value),
function undo() {
names.pop();
}
);
};
btUndo.onclick = function () {
undoRedo.undo();
};
btRedo.onclick = function () {
undoRedo.redo();
};
btClear.onclick = function () {
undoRedo.clear();
}
<form onsubmit="return false">
name: <input id="ipName">
<br><br>
<button type="submit" id="btAdd" >Add</button>
<button id="btUndo">Undo</button>
<button id="btRedo">Redo</button>
Buffer = <span id="lbBuffer"></span>
<button id="btClear">Clear</button>
<pre id="lbNames"></pre>
</form>