如何在浏览器兼容的Javascript中撤消和重做事件?

我有一个T恤定制设计软件工具,并且必须为可拖动的文本添加重做和撤消事件

http://wordpress.tshirtecommerce.com/design-online/?product_id=17

我尝试过使用undo manager插件http://mattjmattj.github.io/simple-undo/

我们到了..

这是一个执行Undo和Redo缓冲区的简单示例,并使用函数闭包来处理重做。

这当然是一个非常简单的例子,所以希望它很容易跟随,但是没有理由不能使用这种技术撤消/重做任何东西。 任何东西,你传递给函数闭包都可以捕获,然后进行回放。

var e = {}; //lets store references to the dom elemements Array.prototype.slice.call(document.querySelectorAll("[id]")). forEach(function (el) { e[el.id] = el; }); var stack = [], stackPos = 0, names = []; function showNames() { e.lbNames.textContent = names.join(', '); e.btUndo.disabled = stackPos <= 0; e.btRedo.disabled = stackPos >= stack.length; e.lbBuffer.textContent = stack.length; } btAdd.onclick = function () { if (!ipName.value) return alert("Please enter some text"); //a function closure to capture the name function add(name) { return function () { e.ipName.value = ''; e.ipName.focus(); names.push(name); stackPos ++; showNames(); } } //no need for closure here, as were just going to pop the //last one of the names, and shift the undo-pos back function undo() { stackPos --; names.pop(); showNames(); } //now lets add our do & undo proc var doadd = add(ipName.value); stack.splice(stackPos); stack.push({ do: doadd, undo: undo }); //lets now do our inital do doadd(); }; btUndo.onclick = function () { var p = stack[stackPos - 1]; p.undo(); }; btRedo.onclick = function () { var p = stack[stackPos]; p.do(); }; showNames(); 
 
name:

Buffer =

好吧,有一件事让我对我原来的post感到困惑,那就是可重用性。 Undo / Redo也与实现细节紧密相关。

所以我创建了一个可重用的类版本,同时也增加了一个明确的选项。

我觉得保留原版是很方便的,而且这个用于比较。 这样人们就可以查看代码并进行比较。

 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(); } 
 
name:

Buffer =