IE在线编辑器器 Undo / Redo 失效问题及解决方案

今天遇到个问题,我的MocolaEditor之前有效的 Undo / Redo 功能突然失效了,这应该是编写HTML在线编辑器的PG都会遇到的一个问题。

先看看这个问题是什么:

<script>
function onchange(){
info.innerText=editor.innerText;
}
</script>
</HEAD>
<BODY>
<div style="width:500px;height:500px;border:1px solid #cccccc" contenteditable="true" ></div>
<div style="width:500px;height:50px;padding:4px;background-color:#F0f0f0"></div>
</BODY>
运行上面这段代码,你会发现,你的编辑器 将无法 Undo和Redo。



为什么会这样?



原因在于 info.innerText=editor.innerText; 这一脚本,改变了当前HTML渲染。起初我以为编辑器放在IFrame里就没事了,结果发现,放哪里都一样。



<script>
function onchange(){
info.innerText=Editor.document.body.innerText;
}
window.οnlοad=function(){
Editor.document.designMode="ON";
Editor.document.οnkeyup=onchange;
}
</script>
</HEAD>
<BODY>
<iframe style="width:500px;height:500px;border:1px solid #cccccc"></iframe>
<div style="width:500px;height:50px;padding:4px;background-color:#F0f0f0"></div>
</BODY>
Google的Writly (http://docs.google.com),有相同的问题。他的操作界面的弹出窗口都是用 div 来实现的。这样在显示和关闭的时候 必然会做一些Dom的操作,结果是只要弹出过窗口,Undo/Redo就失效了。

问题到此,应该很清楚了。那么如何解决呢?

既然浏览器的Undo/Redo不行了,那我就自己来写一个Undo/Redo方法。

每次文档发生改变的时候,我们可以把其HTMLCode 和 Selection 选区一起保存。存入一个数组里,只要数据都存好了,想undo/redo都是很轻松的事情了。

小Tips: 可以通过 document.selection.createRange().getBookmark()方来 来保存选区状态。
Undo的时候用 document.selection.createRange().moveToBookmark()方法来恢复选区。

以下是网上找的一段Undo/Redo 类。Typeing是为了对打字进行一些特殊处理,因为没有必要每输入一个字就增加一个UndoStep,这样太浪费内存空间了。 这里还需要对document.onkeydown函数做一些配合处理。

var CMSUndo=new Object();
CMSUndo.UndoLevels=new Array();
CMSUndo.CurrentStep=0;
CMSUndo.MaxLevel=20;
CMSUndo.Typing=false;
CMSUndo.TypingCount=CMSUndo.TypingMaxCount=25;
CMSUndo.SaveUndoStep=function(){
if(EMode == "Code") return;
this.UndoLevels[this.CurrentStep]=this.GetSaveData();
this.CurrentStep++;
this.UndoLevels=this.UndoLevels.slice(0,this.CurrentStep);
if(this.UndoLevels>this.MaxLevel) this.UndoLevels.shift();
this.CurrentStep=this.UndoLevels.length;
}
CMSUndo.Redo=function(){
if(this.CurrentStep<this.UndoLevels.length-1) this.ApplyUndoLevel(this.UndoLevels[++this.CurrentStep]);
}
CMSUndo.Undo=function(){
if(this.UndoLevels.length<1) return;
if(this.CurrentStep==this.UndoLevels.length) this.SaveUndoStep();
if(this.CurrentStep>0) this.ApplyUndoLevel(this.UndoLevels[--this.CurrentStep]);
}
CMSUndo.ApplyUndoLevel=function(cStep){
EditorDesignContent.body.innerHTML=cStep.htmlcode;
if(cStep.selrange) {
var range=EditorDesignContent.selection.createRange()
range.moveToBookmark(cStep.selrange)
range.select();
onEditContentSelChange();
}
this.TypesCount=0;
this.Typing=false;
}
CMSUndo.GetSaveData=function(){
var cStep=new Object();
cStep.htmlcode=EditorDesignContent.body.innerHTML;
if (EditorDesignContent.selection.type=='Text') cStep.selrange=EditorDesignContent.selection.createRange().getBookmark();
return cStep;
}

原文:[url]http://www.mockte.com/rewrite.php/read-30.html[/url]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Eclipse 中,可以使用 `org.eclipse.ui.actions.ActionFactory.UNDO` 和 `org.eclipse.ui.actions.ActionFactory.REDO` 来创建 UndoRedo 动作。然后,将这些动作关联到菜单栏 Edit 中的 UndoRedo 菜单项。 要在 `ViewPart` 中实现 Undo/Redo,您需要遵循以下步骤: 1. 在 `ViewPart` 类中添加以下字段: ```java private IUndoContext undoContext; private IUndoableOperation undoOperation; private IAction undoAction; private IAction redoAction; ``` 2. 在 `createPartControl` 方法中初始化这些字段: ```java public void createPartControl(Composite parent) { // 创建 Undo/Redo 上下文 undoContext = new ObjectUndoContext(new Object()); // 创建 Undo/Redo 动作 undoAction = ActionFactory.UNDO.create(getSite().getWorkbenchWindow()); undoAction.setText("Undo"); undoAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages() .getImageDescriptor(ISharedImages.IMG_TOOL_UNDO)); undoAction.setEnabled(false); redoAction = ActionFactory.REDO.create(getSite().getWorkbenchWindow()); redoAction.setText("Redo"); redoAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages() .getImageDescriptor(ISharedImages.IMG_TOOL_REDO)); redoAction.setEnabled(false); // 将 Undo/Redo 动作添加到菜单栏 Edit 中 IMenuManager menuMgr = getViewSite().getActionBars().getMenuManager(); menuMgr.add(new Separator()); menuMgr.add(undoAction); menuMgr.add(redoAction); } ``` 3. 在 `createPartControl` 方法中为 Undo/Redo 动作添加处理程序: ```java public void createPartControl(Composite parent) { // ... // 为 Undo/Redo 动作添加处理程序 undoAction.setHandler(new UndoActionHandler(getViewSite(), undoContext)); redoAction.setHandler(new RedoActionHandler(getViewSite(), undoContext)); } ``` 4. 在 `createPartControl` 方法中为 `parent` 控件创建上下文菜单,并将 Undo/Redo 动作添加到上下文菜单中: ```java public void createPartControl(Composite parent) { // ... // 为 parent 控件创建上下文菜单,并将 Undo/Redo 动作添加到上下文菜单中 MenuManager menuMgr = new MenuManager(); menuMgr.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); getSite().registerContextMenu(menuMgr, getSite().getSelectionProvider()); parent.setMenu(menuMgr.createContextMenu(parent)); menuMgr.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager manager) { manager.add(new Separator()); manager.add(undoAction); manager.add(redoAction); } }); } ``` 5. 在 `ViewPart` 类中添加以下方法: ```java public void executeCommand(final IUndoableOperation operation) { // 如果操作不可撤销,则返回 if (!operation.canUndo()) { return; } // 如果当前有未完成的撤消操作,则合并操作 if (undoOperation != null) { undoOperation.addContext(operation.getContext()); undoOperation.add(operation); } else { // 否则,开始新的撤消操作 undoOperation = operation; } // 注册撤消操作 IOperationHistory operationHistory = OperationHistoryFactory.getOperationHistory(); operationHistory.add(undoOperation); // 更新 Undo/Redo 动作的状态 undoAction.setEnabled(undoOperation.canUndo()); redoAction.setEnabled(undoOperation.canRedo()); // 将操作添加到 Undo/Redo 上下文中 undoContext.addMatch(undoOperation); } public void undo() { // 撤消上一个操作 IOperationHistory operationHistory = OperationHistoryFactory.getOperationHistory(); operationHistory.undo(undoContext, null, null); } public void redo() { // 重做上一个操作 IOperationHistory operationHistory = OperationHistoryFactory.getOperationHistory(); operationHistory.redo(undoContext, null, null); } ``` 6. 在 `ViewPart` 类中添加以下代码,以便在视图关闭时清除 Undo/Redo 上下文中的操作: ```java public void dispose() { // 清除 Undo/Redo 上下文中的操作 IOperationHistory operationHistory = OperationHistoryFactory.getOperationHistory(); operationHistory.dispose(undoContext, true, true, true); super.dispose(); } ``` 现在,您可以在 `executeCommand` 方法中执行所有需要撤消/恢复支持的操作,并且在菜单栏 Edit 中的 Undo/Redo 菜单项中使用 Undo/Redo 动作来撤消/恢复操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值