Reputation: 2169
I'm creating my own editor, and I'm finally tackling the undo/redo issue that I've been dodging for weeks.
I have created the base framework for storing and traversing the history of custom actions, but I cannot seem to find good information on how to interact with the browsers history in a contentEditable
area.
Looking at https://github.com/jzaefferer/undo/blob/master/undo.js, I still do not see how this is done.
I can undo/redo my custom actions, but I'm oblivious to how I can tap into the browsers default history.
Will I have to add all of the original functionality if I am to override the default control + ( z | y )?
Update: Where can I find more information about how the browser handles these undo/redo actions?
Upvotes: 8
Views: 5847
Reputation: 1089
Use this, but it works as it should only with <div contentEditable="true">
boxes. In textarea it undoes and redoes all text at once, not word by word as in div.
<script language="JavaScript">
function Undo() { document.execCommand("undo", false, null); }
function Redo() { document.execCommand("redo", false, null); }
</script>
<div contentEditable="true" style="background-color:rgba(0,0,0,0.8); resize:none; width: 499px; height: 230px; border: 1px solid red;"></div>
<input type="button" onmouseup="Undo()" value="Undo" />
<input type="button" onmouseup="Redo()" value="Redo" />
Upvotes: 4
Reputation: 1524
Check out the source of the contenteditable demo to figure out more about how he attached the library to the div.
$(function() {
var stack = new Undo.Stack(),
EditCommand = Undo.Command.extend({
constructor: function(textarea, oldValue, newValue) {
this.textarea = textarea;
this.oldValue = oldValue;
this.newValue = newValue;
},
execute: function() {
},
undo: function() {
this.textarea.html(this.oldValue);
},
redo: function() {
this.textarea.html(this.newValue);
}
});
stack.changed = function() {
stackUI();
};
var undo = $(".undo"),
redo = $(".redo"),
dirty = $(".dirty");
function stackUI() {
undo.attr("disabled", !stack.canUndo());
redo.attr("disabled", !stack.canRedo());
dirty.toggle(stack.dirty());
}
stackUI();
$(document.body).delegate(".undo, .redo, .save", "click", function() {
var what = $(this).attr("class");
stack[what]();
return false;
});
var text = $("#text"),
startValue = text.html(),
timer;
$("#text").bind("keyup", function() {
// a way too simple algorithm in place of single-character undo
clearTimeout(timer);
timer = setTimeout(function() {
var newValue = text.html();
// ignore meta key presses
if (newValue != startValue) {
// this could try and make a diff instead of storing snapshots
stack.execute(new EditCommand(text, startValue, newValue));
startValue = newValue;
}
}, 250);
});
$(".bold").click(function() {
document.execCommand("bold", false);
var newValue = text.html();
stack.execute(new EditCommand(text, startValue, newValue));
startValue = newValue;
});
// This is where he attaches the observer for undo / redo.
// For more information: https://stackoverflow.com/questions/16006583/capturing-ctrlz-key-combination-in-javascript
$(document).keydown(function(event) {
if (!event.metaKey || event.keyCode != 90) {
return;
}
event.preventDefault();
if (event.shiftKey) {
stack.canRedo() && stack.redo()
} else {
stack.canUndo() && stack.undo();
}
});
});
Capturing ctrl+z key combination in javascript
Upvotes: 4
Reputation:
I don't believe there is anyway to directly access the contents of the undo buffer, but you can trigger an undo or redo using document.execCommand. Simple example:
<html>
<head>
<style>
#box {
width: 200px;
height: 100px;
background-color: grey;
}
</style>
</head>
<body>
<div id="box" contenteditable="true"></div>
<button id="undo">Undo</button>
<button id="redo">Redo</button>
<script>
var box = document.getElementById('box');
var undo = document.getElementById('undo');
var redo = document.getElementById('redo');
undo.addEventListener('click', function (ev) {
document.execCommand('undo', false, null);
});
redo.addEventListener('click', function (ev) {
document.execCommand('redo', false, null);
});
</script>
</body>
</html>
Check it is out as a jsfiddle.
Upvotes: 2