编辑器撤销(undo)与重做(redo)插件的设计与实现
,涉及三个方面:
1. 编辑器状态定义
不仅要包含当前编辑器的内容(body.innerHTML),还要考虑编辑区域用户的选中状态,用户选中每个区域进行高亮等操作,则操作前要把当前选中区域以及内容html都要保存下来:
/**
* 当前编辑区域状态,包括html与选择区域
* @param editor
*/
function Snapshot(editor) {
var contents = editor.getData(),selection = contents && editor.getSelection();
//内容html
this.contents = contents;
//选择区域书签标志
this.bookmarks = selection && selection.createBookmarks2(true);
}
2.编辑状态历史的管理
历史管理器维护着编辑状态的栈数据, 其他插件通过触发编辑器的 save 与 restore 事件来通知历史管理器更新内部的状态。
当 save 操作时,历史管理器将当前状态添加到编辑状态栈即可,并更新内部游标。
restore 操作时,需要利用管理器内部的游标来在状态栈间前(undo)后(redo)游走,用游标处的状态替换当前状态。
注意点在于,当进行了re/undo操作后,再进行save状态保存,需要对状态栈进行清理,将当前游标以后的历史状态删掉,防止出现历史分支:
另一点在于:对于键盘的连续输入,可buffer处理,只有当空闲一定时间后才进行保存,避免细微冗余信息。
/**
* 通过编辑器的save与restore事件,编辑器实例的历史栈管理,与键盘监控
* @param editor
*/
function UndoManager(editor) {
//redo undo history stack
/**
* 编辑器状态历史保存
*/
this.history = [];
this.index = 0;
this.editor = editor;
this.bufferTimer = new BufferTimer(500, this.save, this);
this._init();
}
S.augment(UndoManager, {
/**
* 监控键盘输入,buffer处理
* @param ev
*/
_keyMonitor: function (ev) {
//ctrl+z,撤销
//ctrl+y,重做
//其他可见字符buffer处理
},
_init: function () {
var self = this,
editor = self.editor;
//外部通过editor触发save|restore,管理器捕获事件处理
editor.on("save", function (ev) {
if (ev.buffer)
//键盘操作需要缓存
self.bufferTimer.run();
else {
//其他立即save
self.save();
}
});
//un/re do
editor.on("restore", this.restore, this);
self._keyMonitor();
//先save一下
self.save();
},
/**
* 保存历史
*/
save: function () {
//游标后面的历史抛弃
//超过占最大容量,shift队列出列
//当前状态和栈顶状态不同,入栈
//更新游标
//触发afterSave事件
},
/**
*
* @param ev
* ev.d :1.向前撤销 ,-1.向后重做
*/
restore: function (ev) {
//更新游标,用游标所在状态替换当前状态
}
});
3.工具栏 ui 与功能调用
RestoreUI 封装工具栏撤销与重做的功能与表现,使用 attribute
抽象出三状态按钮(可用并选中,可用,禁用),监听通过2触发的编辑器 afterSave,afterRestore 事件,通过游标位置和历史栈大小的比较,来决定redo ,undo按钮的禁用与可用状态.
/**
* save,restore完,更新工具栏状态
*/
editor.on("afterSave", this._respond, this);
editor.on("afterRestore", this._respond, this);
undo:当游标不在状态栈底部时可用(index>0&&history.length>0)
redo:当游标不在状态栈顶部时可用(index < history.length-1)
当点击工具栏按钮时,触发editor的restore事件,注意参数,redo为向后restore,undo为向前restore。
/**
* 触发重做或撤销动作,都是restore,方向不同
*/
self.el.on("click", function() {
editor.fire("restore", {
d:RedoMap[self.text]
});
});
4.整合
当编辑器实例生成后,全局空间事件通知undo/redo插件,插件对每个编辑器生成对应的历史管理器与工具栏按钮:
KE.on("instanceCreated", function(ev) {
var editor = ev.editor;
/**
* 编辑器历史中央管理
*/
new UndoManager(editor);
/**
* 撤销工具栏按钮
*/
new RestoreUI(editor, "undo");
/**
* 重做工具栏按钮
*/
new RestoreUI(editor, "redo");
});
插件源码
demo
- 大小: 3.6 KB
- 大小: 882 Bytes
- 大小: 10.8 KB
- 大小: 14.1 KB
- 大小: 22.4 KB
分享到:
相关推荐
GIS 中的undo与redo实现的论文,采用命令模式实现,有相关的数据结构描述
Multiple Level Undo/Redo多级Undo/Redo功能的实现(7KB)
实现redo,undo操作,来源于网络分享下。
实现Java中编辑器的Undo、Redo操作,功能比较强大
VC & C++ 源码 多重 undo redo 实现 多重Undo/Redo实现
delphi实现undo/redo,仅作参考
监控绘图软件中Undo/Redo的设计和实现,对于redo、undo有详细的介绍
针对一个window窗体实现了undo/redo功能,包括textBox,checkBox, listBox, comboBox, radioButton以及按钮焦点变化的实现。可能有些小bug思路仅供参考。完整的工程文件,VS打开即可运行,欢迎评论~ 详细说明参见...
在Element增删改处 添加 IOperationStack .DO(); 方法,即可将Element的操作过程保存到操作堆 自行对Element的变化进行记录,以便在IOperation 中Redo Undo中使用
MagicGearEditor3D是一个免费的地形、室外场景编辑器!计划支持目前主流的室外引擎技术,为广大的游戏开发者,demo maker提供一个有用的工具。目前版本还是一个很初级的测试版本,已经实现的功能有: 水面编辑, ...
import { undoable , UNDO , REDO } from "@storeon/undo/full" ;const store = createStore ( [ /* all your modules */ undoable ,] ) ;// now you can use UNDO and REDO with dispatchdispatch ( UNDO ) ;安装...
这个是做实验时,简单基本的Undo、Redo的操作、在一个winForm中实现,并且可以设置Undo的最大次数。包中除了项目外,还附有报告.
图像编辑中的undo的实现方法
c# datagridview 撤销/恢复
NULL 博文链接:https://saga-java.iteye.com/blog/1549583
本工程用vs2008打开,但需要qt库的支持,需要先安装qt-in-vs2008,才可通过编译。或者直接将里面的代码拷贝出来,然后在自己的环境中编译也行。代码中应用了QUndoCommand来实现撤销与反撤销操作。
Undo_Redo机制在CAD中的应用, 摘要:为了增强CAD系统的灵活...持无限Undo/Redo和批量化操作的CAD图形绘制系统,文章介绍了各模块的实现原理及核心算法。 关键词:无限撤消/重做设计模式对象持久化批量化操作绘图CAD
实现多步Undo和Redo的方法,对于mfc绘图程序来说,这个很必要,而且很实用!
c# undo/redo例子 支持文字的样式,颜色修改 动态进度条
Simple Undo/redo library for C#/.NET