PDA

View Full Version : undo-redo function


axinya
06-08-2004, 09:16 PM
<!--

Hi out there!


I'm working on an undo-redo function.
Couldnt really find anything useful in the internet.
So I have a try.
Guess it could be quite useful for a lot of people out there

Wonder if the concept is any good?

Please critizise hard!
Try it out if you dare!
Any feedback is welcome!
All suggestions are appreciated!

Yours

Axinya

-->
<html>
<head>
<style type="text/css">
<!--
#wisiwig {
overflow: auto;
position: relative;
height: 300px;
width: 600px;
margin-top: 5px;
padding: 5px;
border: thin groove #999999;
}
-->
</style>
<script language="JavaScript">
<!--
var b_ackup = new Array(); //Store data in Array
var undo_pos= 0;//Position of undo
var flag = false;// shall we start new undo thread and delete obsolete items?
var w_isiwig;//editor interface

function init(){
w_isiwig = document.getElementById("wisiwig");
w_isiwig.contentEditable = true;
w_isiwig.onkeyup = HandleKeys;
b_ackup[0] = w_isiwig.innerHTML;
}

function HandleKeys(evt) {//events to write to backup
//
if (event) {

switch (event.keyCode) {
case 32:
BACKUP();
break;
case 8:
BACKUP();
break;
case 13:
BACKUP();
break;
case 46:
BACKUP();
break;
default:
return;
}
}
}

function BACKUP(){

if (flag){// action if undo was clicked

var removed= b_ackup.splice(flag,b_ackup.length - flag);
for (var i = 0; i < removed.length; i++) {
delete removed[i];//delete obsolete array items
}

b_ackup[b_ackup.length] = w_isiwig.innerHTML;
undo_pos = b_ackup.length - 1;
flag = false;
w_isiwig.focus();

}
else{//write to backup array
b_ackup[b_ackup.length] = w_isiwig.innerHTML;
undo_pos = b_ackup.length - 1;
flag = false;
w_isiwig.focus();
}
}

function undo(){

if (b_ackup.length){//

if(undo_pos==0){w_isiwig.focus();return;}// beginning of backup items

if(flag == false){BACKUP();}// save last state of document

w_isiwig.innerHTML=b_ackup[undo_pos -1];

undo_pos=undo_pos - 1;

flag = undo_pos +1;

look();

w_isiwig.focus();
}
}

function redo(){
if(undo_pos == b_ackup.length -1){w_isiwig.focus();return;}
//end of backup array

w_isiwig.innerHTML=b_ackup[undo_pos +1];

undo_pos=undo_pos + 1;

flag = undo_pos +1;
look();
w_isiwig.focus();

}

function look(){// monitor our Array data
var e='flag:'+flag+'\r\nundo_pos:'+undo_pos+'\r\n';
e+='b_ackup.length:'+b_ackup.length+'\r\n';
for (i=0; i<b_ackup.length; i++){

e+= 'Backup item '+i+':'+b_ackup[i]+'\r\n';
}
document.getElementById('bup_a').value=e;
}

</script>
<title>undo-redo</title>
</head>
<body id = "body" onload= "init();">
<p><b>undo/redo</b> <br>
development version: for <b>IE</b> only<br>
Backup written by <b>'onkeyup'</b> event(space,back,return,del), or
<b>'add to backup'</b> button. </p>
<div id="menu">
<a href="#" onclick='BACKUP();return false';>[add to backup]</a>
<a href="#" onclick='setTimeout("undo()",10)'>[undo]</a>
<a href="#" onclick='setTimeout("redo()",10)'>[redo]</a>
<a href="#" onclick='look()'>[view backup-data]</a> </div>
<div id="wisiwig">Type text: </div>
Backup Array Data: <br>
<div id="bup">
<textarea id="bup_a" name="bup_a" cols="80" rows="6"></textarea>
</div>
</body>
</html>

homerUK
06-10-2004, 01:14 AM
looks fantastic!! gonna give it a try shortly... hopefully it will solve a few people's problems with the commandExec undo command which for some reason sucks!!

homerUK
06-10-2004, 10:05 PM
managed to get this script working in my code now! its brilliant!!

I was wondering if there was a way to stop the cursor from going to the beginning of the document when you press "undo" ?

ie: forcing it to stay in its current position?

Great job!! :D

Alex Vincent
06-10-2004, 10:52 PM
IE only, eh? Sounds interesting, though I won't get to play with it.

From looking at the source code, it looks like you're trying to make it work for rich-text areas.

Mozilla has its own functionality for handling undo/redo operations, through its nsITransactionManager interface. It's rather interesting, but probably not appropriate for the task you have here.

starrwriter
06-12-2004, 07:55 AM
Why would I want to use all that script when the following works perfectly for me in IE 5+?

function doUndo()
{
iView.document.execCommand('undo', false, null);
}

function doRedo()
{
iView.document.execCommand('redo', false, null);
}

homerUK
06-12-2004, 11:50 AM
the execCommand is very buggy and often doesnt actually work!!
with the above undo-redo code you can control it much better!!

starrwriter
06-20-2004, 07:28 AM
the execCommand is very buggy and often doesnt actually work!!
with the above undo-redo code you can control it much better!!

Sorry, but I have to disagree with you. I developed a WYSIWYG editor with dozens of execCommands and they have all worked perfectly for everyone who used it. And the code is a small fraction in length compared to yours (small is always better.)

Plus your script only undoes/redoes the last word typed in a sentence while the execCommand undoes/redoes the whole sentence.

To answer your question, if you DON'T want the cursor to return to the point of undo/redo, then delete w_isiwig.focus();

homerUK
06-20-2004, 06:30 PM
Sorry, but I have to disagree with you. I developed a WYSIWYG editor with dozens of execCommands and they have all worked perfectly for everyone who used it. And the code is a small fraction in length compared to yours (small is always better.)

sorry, I meant only the undo/redo parts of execCommand... the rest are excellent. Maybe it's just my browser, I dont know... but the undo sometimes works and other times doesnt.

Terry
06-26-2004, 01:22 PM
Good going. I think this is the way to go for undo/redo functionality. As someone mentioned before the undo/redo execCommand is buggy at best. Specifically, whenever you use an innerHTML on the page that has the undo/redo exec's you lose focus and "memory" of the state is lost. That is the biggest drawback and I contemplated creating a script like yours because of that annoying behaviour.

Reinventing the wheel for this particular functionality, so to speak, allows for (potential) cross-browser support using the same code. And for those who don't need a wisiwig and can already code, it would be a great tool to have a mature redo/undo as an added bonus for CMS textareas - quick and dirty editing, etc. Adding tabbing functionality is pretty easy, so with redo/undo you essentially transform the textarea into a functional "text editor".