自己寫的一個有限撤消/恢復算法。並用文本框進行了測試。
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Undo Redo</title>
<script src="http://libs.baidu.com/jquery/2.1.1/jquery.min.js"></script>
<style type="text/css">
body{margin:0;padding:0;font-family:Microsoft YaHei;}
.click{width:80px;height:20px;line-height:20px;margin-left:10px;float:left;text-align:center;border:#bbb solid 1px;background-color:#f5f5f5;cursor:pointer;}
</style>
</head>
<body>
<br/><br/><br/>
<div style='width:400px;height:400px;margin:0 auto;'>
<input type="text" id="itext" maxlength='2' style='width:76px;float:left;'>
<div id="do" class='click'>do</div>
<div id="undo" class='click'>undo</div>
<div id="redo" class='click'>redo</div>
<br/><br/><br/>
<div id='debug' style='clear:both;'></div>
<br/><br/>
<div id='prevnow' style='clear:both;width:400px;height:20px;line-height:20px;text-align:center;font-size:14px;'></div>
<br/><br/>
<textarea id='tt' maxlength='100' style='width:390px;height:100px;'></textarea>
<div style='width:400px;font-size:14px;color:#e00;text-align:center;'>(*限字母和數字,漢字無法觸發keyup)</div>
<div style='width:400px;height:20px;margin-top:20px;margin-left:200px;'>
<div id="tundo" class='click'>undo</div>
<div id="tredo" class='click'>redo</div>
</div>
<br/>
<div id='debug2' style='width:400px;height:100px;display:none;'></div>
</div>
<script language="javascript">
var ud = new UndoRedo(10);
var ud2 = new UndoRedo(100);
for(var i=1;i<=10;++i){
ud.do(i+"");
}
$("#debug").append(ud.debug());
var now = ud.now();
now = now == null ? "無" : now;
var prev = ud.prev();
prev = prev == null ? "無" : prev;
$("#prevnow").text("當前數據:"+now+",上一個數據:"+prev);
$(".click").each(function(){
$(this).click(function(){
switch($(this).prop("id")){
case "do":
var t = $("#itext").val();
if(t != null && t != undefined && t.length > 0){
ud.do(t);
$("#debug").empty();
$("#debug").append(ud.debug());
var now = ud.now();
now = now == null ? "無" : now;
var prev = ud.prev();
prev = prev == null ? "無" : prev;
$("#prevnow").text("當前數據:"+now+",上一個數據:"+prev);
}
break;
case "undo":
var t = ud.undo();
if(t != null && t != undefined){
$("#debug").empty();
$("#debug").append(ud.debug());
var now = ud.now();
now = now == null ? "無" : now;
var prev = ud.prev();
prev = prev == null ? "無" : prev;
$("#prevnow").text("當前數據:"+now+",上一個數據:"+prev);
}
break;
case "redo":
var t = ud.redo();
if(t != null && t != undefined){
$("#debug").empty();
$("#debug").append(ud.debug());
var now = ud.now();
now = now == null ? "無" : now;
var prev = ud.prev();
prev = prev == null ? "無" : prev;
$("#prevnow").text("當前數據:"+now+",上一個數據:"+prev);
}
break;
case "tundo":
var t = ud2.undo();
if(t != null){
$("#tt").val(t);
}
$("#debug2").empty();
$("#debug2").append(ud2.debug());
break;
case "tredo":
var t = ud2.redo();
if(t != null){
$("#tt").val(t);
}
$("#debug2").empty();
$("#debug2").append(ud2.debug());
break;
}
});
});
$("document").ready(function(){
$("#itext")[0].value = "";
$("#tt")[0].value = "";
ud2.do("");
$("#debug2").empty();
$("#debug2").append(ud2.debug());
$("#tt").keyup(function(){
var t = $("#tt").val();
if(t != null && t != undefined){
ud2.do(t);
$("#debug2").empty();
$("#debug2").append(ud2.debug());
}
});
});
function UndoRedo(size)
{
var s = size;
var l = 0;//obj count
var pos = -1;//current data
var a = new Array(l);
for(var i=0;i<s;++i){
a[i] = null;
}
this.do = function(obj)
{
if(pos == l-1){//指針在數據未尾
if(l == s){//如數組已滿則清除掉最舊的數據
for(var i=0;i<s-1;++i){
a[i] = a[i+1];
}
a[s-1] = obj;
}
else{
a[pos+1] = obj;
pos +=1;
l++;
}
}
else{//指針不在數據未尾
if(pos >= 0){
a[pos+1] = obj;
for(var i=pos+2;i<s;++i){
a[i] = null;
}
l = pos + 2;
pos+=1;
}
else{
a[0] = obj;
l=1;
pos = 0;
}
}
}
//返回上一個數據,但不移動標誌
this.prev = function()
{
if(pos > 0){
return a[pos-1];
}
return null;
}
//返回當前數據
this.now = function()
{
if(pos >=0 && pos < l){
return a[pos];
}
return null;
}
//返回上一個數據
this.undo = function(state)
{
if(state == true){
return pos > 0 ? true : false;
}
else{
if(pos > 0){
var re = a[pos-1];
pos-= 1;
return re;
}
else{
return null;
}
}
}
//返回下一個數據
this.redo = function(state)
{
if(state == true){
return (pos < l-1) ? true : false;
}
else{
if(l > 0){
if(pos < l-1){
var obj = a[pos + 1];
pos += 1;
return obj;
}
else{
return null;
}
}
else{
return null;
}
}
}
//測試用
this.debug = function()
{
var temp="<div>";
for(var i=0;i<s;++i){
temp+="<div style='width:30px;height:20px;line-height:20px;float:left;text-align:center;background-color:#f00;margin:2px;color:#fff;'></div>";
}
temp +="</div>";
var o = $(temp);
for(var i=0;i<l;++i){
o.children().eq(i).css("background-color","#00f");
o.children().eq(i).text(a[i]);
}
if(pos >= 0){
o.children().eq(pos).css("color","#f00");
}
return o;
}
}
</script>
</body>
</html>