JavaScript Undo-Redo(根据《在javascript中用command 模式实现undo和redo》修改兼容Firefox)

这篇博客介绍了如何在JavaScript中利用Command模式实现撤销(Undo)和重做(Redo)功能,特别针对Firefox浏览器进行了兼容性处理。通过创建BaseAction基类和具体的操作类如MoveAction、ChangeAction,实现了元素位置移动和值更改的可逆操作。全局函数undo()和redo()用于触发撤销和重做,同时,拖放和输入事件触发了对应操作的记录。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<!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 + "px";
    this.sourceElement.style.top = this.oldY + "px";
    this.status = "undone";
}
MoveAction.prototype.redo=function(){
    if (this.status != "undone") return;
    this.sourceElement.style.left = this.newX + "px";
    this.sourceElement.style.top = this.newY + "px";
    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(event){
    if (window.activeElement){
        var elm = window.activeElement;
        elm.style.left = (event.clientX - elm.innerX) + "px";
        elm.style.top = (event.clientY - elm.innerY) + "px";
    }
}
function releaseMouse(event){
    event = (event)?event:window.event;
    if (window.activeElement){
        activeElement.newX = event.clientX - activeElement.innerX;
        activeElement.newY = event.clientY - activeElement.innerY;
        new MoveAction(activeElement).exec();
        window.activeElement = null;
    }
}
function drag(event){
    event = (event)?event:window.event;
    if (event.button!=2) return;
    var elm = event.srcElement || event.target
    window.activeElement = elm;
    elm.oldX = elm.offsetLeft;
    elm.oldY = elm.offsetTop;
//    elm.style.left = (event.x - elm.oldX) + "px";
//    elm.style.top = (event.y - elm.oldY) + "px";
    elm.innerX = event.clientX - elm.oldX;
    elm.innerY = event.clientY - elm.oldY;
}

function changeValue(event){
    event = (event) ? event:window.event;
    new ChangeAction(event.srcElement || event.target).exec();
}
//-->
</SCRIPT>
</HEAD>

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值