emu in blogjava

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  171 随笔 :: 103 文章 :: 1052 评论 :: 2 Trackbacks
早上看了水晶龙的一个undo的例子,其中虽然有一些command模式的思想,但是用的好像不够正宗。其实用command模式实现undo和redo应该还是比较容易的,做个例子练练手吧:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> test command </TITLE>
<META NAME="Author" CONTENT="emu">

<SCRIPT LANGUAGE="JavaScript">
<!--
var actionStack = [];//操作栈
var actionIndex = 0;//操作栈中当前操作的指针

//-----------------------  command对象基类 ------------------------------
function BaseAction(){
}
BaseAction.prototype.exec
=function(){
        actionStack[actionIndex
++= this;
        actionStack.length 
= actionIndex;
}
BaseAction.prototype.undo
=function(){
        alert(
"此操作未定义相应的undo操作");
}
BaseAction.prototype.redo
=function(){
        alert(
"此操作未定义相应的redo操作");
}

//-----------------------  move操作的command对象 ------------------------------
function MoveAction(elm){
    
this.oldX = elm.oldX;
    
this.oldY = elm.oldY;
    
this.newX = elm.newX;
    
this.newY = elm.newY;
    
this.sourceElement = elm;
    
this.status = "done";
}
MoveAction.prototype 
= new BaseAction();
MoveAction.prototype.undo
=function(){
    
if (this.status != "done"return;
    
this.sourceElement.style.left = this.oldX;
    
this.sourceElement.style.top = this.oldY;
    
this.status = "undone";
}
MoveAction.prototype.redo
=function(){
    
if (this.status != "undone"return;
    
this.sourceElement.style.left = this.newX;
    
this.sourceElement.style.top = this.newY;
    
this.status = "done";
}
//-----------------------  change操作的command对象 ------------------------------
function ChangeAction(elm){
    
this.sourceElement = elm;
    
this.oldValue = elm.defaultValue;
    
this.newValue = elm.value;
    elm.defaultValue 
= elm.value;
    
this.status = "done";
}
ChangeAction.prototype 
= new BaseAction();
ChangeAction.prototype.undo 
= function(){
    
if (this.status != "done"return;
    
this.sourceElement.value = this.sourceElement.defaultValue = this.oldValue;
    
this.status = "undone";
}

ChangeAction.prototype.redo 
= function(){
    
if (this.status != "undone"return;
    
this.sourceElement.value = this.newValue;
    
this.status = "done";
}


//---------------------  全局函数  ----------------------------
function undo(){
    
if (actionIndex>0){
        actionStack[
--actionIndex].undo();
    }
}
function redo(){
    
if (actionIndex<actionStack.length){
        actionStack[actionIndex
++].redo();
    }
}

function checkMouseMove(){
    
if (window.activeElement){
        
var elm = window.activeElement;
        elm.style.left 
= event.x-elm.innerX;
        elm.style.top 
= event.y-elm.innerY;
    }
}
function releaseMouse(){
    
if (window.activeElement){
        activeElement.newX 
= event.x-activeElement.innerX;
        activeElement.newY 
= event.y-activeElement.innerY;
        
new MoveAction(activeElement).exec();
        window.activeElement 
= null;
    }
}
function drag(){
    
if (event.button!=2return;
    
var elm = event.srcElement;
    window.activeElement 
= elm;
    elm.oldX 
= elm.offsetLeft;
    elm.oldY 
= elm.offsetTop;
    elm.innerX 
= event.x - elm.oldX;
    elm.innerY 
= event.y - elm.oldY;
}

function changeValue(){
    
new ChangeAction(event.srcElement).exec();
}
//-->
</SCRIPT>
</HEAD>

<BODY onmousemove="checkMouseMove()" onmouseup="releaseMouse()" oncontextmenu="return false">
<input type=button onclick=undo() value=undo>
<input type=button onclick=redo() value=redo>
<input value="drag me" onmousedown="drag()" onchange="changeValue()" style="position:absolute;left:150;color:blue">
<input value="drag me" onmousedown="drag()" onchange="changeValue()" style="position:absolute;left:350;color:green">
<input value="drag me" onmousedown="drag()" onchange="changeValue()" style="position:absolute;left:550;color:violet">
</BODY>
</HTML>

用鼠标右键拖动输入框,或者直接修改输入框的内容,可以一一 undo 再 redo 。

看来效果还不错。秋水说有bug,不过我没有重现出来呢?
posted on 2005-09-28 18:16 emu 阅读(5543) 评论(6)  编辑  收藏

评论

# re: 在javascript中用command 模式实现undo和redo 2005-09-28 18:23 huangyi
有意思 从来没想过用js来做这种事情  回复  更多评论
  

# re: 在javascript中用command 模式实现undo和redo 2005-09-28 18:55 emu
呵呵,我现在不做java了,只能在js上干这些事情了。

JK手脚真快,一下发现了两个bug:

1 从一个textbox把文字拖放到另一个textbox的情况下不能undo,因为ie没有触发两个onchange事件给我,不能全怪我啊。

2 修改值后我的undo功能和IE自带的ctrl-z有冲突,呵呵。  回复  更多评论
  

# re: 在javascript中用command 模式实现undo和redo 2006-01-17 10:38 errorfun
牛哥......
你太牛了,我佩服得五体投地  回复  更多评论
  

# re: 在javascript中用command 模式实现undo和redo 2006-05-24 09:27 jlove
真强  回复  更多评论
  

# re: 在javascript中用command 模式实现undo和redo 2013-08-16 10:07 帝君
楼主我想问下啊 你这个代码 在文本域输入内容的时候 如果不失去焦点就无法进行撤销啊 有没有什么办法解决呢  回复  更多评论
  

# re: 在javascript中用command 模式实现undo和redo 2013-08-16 10:08 帝君
如果有解决的办法 请您联系下我啊 我很急 32227304 邮箱QQ都可以 谢谢  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: