emu in blogjava

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            171 隨筆 :: 103 文章 :: 1052 評(píng)論 :: 2 Trackbacks
          早上看了水晶龍的一個(gè)undo的例子,其中雖然有一些command模式的思想,但是用的好像不夠正宗。其實(shí)用command模式實(shí)現(xiàn)undo和redo應(yīng)該還是比較容易的,做個(gè)例子練練手吧:


          <!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;//操作棧中當(dāng)前操作的指針

          //-----------------------  command對(duì)象基類 ------------------------------
          function BaseAction(){
          }
          BaseAction.prototype.exec
          =function(){
                  actionStack[actionIndex
          ++= this;
                  actionStack.length 
          = actionIndex;
          }
          BaseAction.prototype.undo
          =function(){
                  alert(
          "此操作未定義相應(yīng)的undo操作");
          }
          BaseAction.prototype.redo
          =function(){
                  alert(
          "此操作未定義相應(yīng)的redo操作");
          }

          //-----------------------  move操作的command對(duì)象 ------------------------------
          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對(duì)象 ------------------------------
          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";
          }


          //---------------------  全局函數(shù)  ----------------------------
          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>

          用鼠標(biāo)右鍵拖動(dòng)輸入框,或者直接修改輸入框的內(nèi)容,可以一一 undo 再 redo 。

          看來(lái)效果還不錯(cuò)。秋水說(shuō)有bug,不過(guò)我沒(méi)有重現(xiàn)出來(lái)呢?
          posted on 2005-09-28 18:16 emu 閱讀(5568) 評(píng)論(6)  編輯  收藏

          評(píng)論

          # re: 在javascript中用command 模式實(shí)現(xiàn)undo和redo 2005-09-28 18:23 huangyi
          有意思 從來(lái)沒(méi)想過(guò)用js來(lái)做這種事情  回復(fù)  更多評(píng)論
            

          # re: 在javascript中用command 模式實(shí)現(xiàn)undo和redo 2005-09-28 18:55 emu
          呵呵,我現(xiàn)在不做java了,只能在js上干這些事情了。

          JK手腳真快,一下發(fā)現(xiàn)了兩個(gè)bug:

          1 從一個(gè)textbox把文字拖放到另一個(gè)textbox的情況下不能undo,因?yàn)閕e沒(méi)有觸發(fā)兩個(gè)onchange事件給我,不能全怪我啊。

          2 修改值后我的undo功能和IE自帶的ctrl-z有沖突,呵呵。  回復(fù)  更多評(píng)論
            

          # re: 在javascript中用command 模式實(shí)現(xiàn)undo和redo 2006-01-17 10:38 errorfun
          牛哥......
          你太牛了,我佩服得五體投地  回復(fù)  更多評(píng)論
            

          # re: 在javascript中用command 模式實(shí)現(xiàn)undo和redo 2006-05-24 09:27 jlove
          真強(qiáng)  回復(fù)  更多評(píng)論
            

          # re: 在javascript中用command 模式實(shí)現(xiàn)undo和redo 2013-08-16 10:07 帝君
          樓主我想問(wèn)下啊 你這個(gè)代碼 在文本域輸入內(nèi)容的時(shí)候 如果不失去焦點(diǎn)就無(wú)法進(jìn)行撤銷啊 有沒(méi)有什么辦法解決呢  回復(fù)  更多評(píng)論
            

          # re: 在javascript中用command 模式實(shí)現(xiàn)undo和redo 2013-08-16 10:08 帝君
          如果有解決的辦法 請(qǐng)您聯(lián)系下我啊 我很急 32227304 郵箱QQ都可以 謝謝  回復(fù)  更多評(píng)論
            


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 乐清市| 通辽市| 弥渡县| 奉新县| 江都市| 当涂县| 南漳县| 景德镇市| 辰溪县| 平远县| 阿鲁科尔沁旗| 临汾市| 新田县| 镇康县| 磴口县| 金坛市| 桑植县| 宜州市| 牟定县| 台江县| 凉山| 宣化县| 平塘县| 汉沽区| 贵德县| 同德县| 芒康县| 衡阳市| 汤阴县| 勃利县| 高雄市| 醴陵市| 长汀县| 久治县| 余江县| 丁青县| 太原市| 天门市| 台东县| 中阳县| 巴东县|