I have some code implementing a context menu on a textbox, the context menu is to have an Undo
and Redo
item that calls the browsers native methods by using document.execCommand('undo')
.
This code functions as I require on Chromium based browsers but on FireFox and Opera the results are not as expected.
My expectation is that undo and redo will function like the native browser context menu for an input element. The result is that the input elements do not undo and redo, however div elements with the contenteditable
attribute set, do function as expected.
So I'm wondering if this is a bug in one of the browsers, either Chromium or FireFox/Opera, or if I am not implementing the code correctly?
The following code gives an example of the issue that I'm facing. All help is appreciated.
<input contenteditable id="input" type="text"></input>
<div contenteditable id="div" class="inputLike" type="text"></div>
<button id="button1" type="button">Undo</button>
<button id="button2" type="button">Redo</button>
var input = document.getElementById("input"),
button1 = document.getElementById("button1"),
button2 = document.getElementById("button2"),
div = document.getElementById("div");
console.log("Undo", document.queryCommandSupported("undo"));
console.log("Redo", document.queryCommandSupported("redo"));
function doUndo() {
document.execCommand('undo', false, null);
}
function doRedo() {
document.execCommand('redo', false, null);
}
button1.addEventListener("click", doUndo, false);
button2.addEventListener("click", doRedo, false);
On jsfiddle
If you want to look at the actual context menu code, then it is also available on jsfiddle.
As I discovered from the question I asked, the undoManager API in Firefox DOES work. I looked at the jsFiddle link (http://jsfiddle.net/DULV4/1/) posted by Tim Down, and there appear to be a couple issues:
undoScope
attribute must be set totrue
(either in-line or programmatically). This enables theundoManager
for that element.undoManager.transact()
function (though I'm wondering if there is any way to incorporate the native undo stack into the current undoManager's transaction history).I'm only a novice with this, so take what I say with a grain of salt and see https://dvcs.w3.org/hg/undomanager/raw-file/tip/undomanager.html for all the information on using it.
I don't think it's possible with
document.execCommand()
, in Firefox at least. You could make your own undo stack, or in future use the new UndoManager API (implemented in Firefox 20 but disabled by default).Here's an example of using your own undo stack by taking snapshots of the value and selection using the
input
event. You could improve this by merging consecutive typing events into a single undo item, for example. There is also some inconsistency between browsers with the caret position, but it's just a proof of concept.http://jsfiddle.net/FMSsL/
Using the new DOM UndoManager API seems to be simple: if I understand it right and if the browser supports it, the
<input>
element will have anundoManager
property, which is an object withundo()
andredo()
methods, so the task is as simple asUnfortunately only Firefox 20 and above supports the
UndoManager
API and it's disabled by default. Even once it's enabled, the following demo does not work even though I think it should, so this option is some way off being viable.http://jsfiddle.net/DULV4/2/