首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > Web前端 >

编辑器re/undo设计与兑现

2012-11-10 
编辑器re/undo设计与实现编辑器撤销(undo)与重做(redo)插件的设计与实现,涉及三个方面:?1. 编辑器状态定义

编辑器re/undo设计与实现

编辑器撤销(undo)与重做(redo)插件的设计与实现编辑器re/undo设计与兑现,涉及三个方面:

?

1. 编辑器状态定义

?

不仅要包含当前编辑器的内容(body.innerHTML),还要考虑编辑区域用户的选中状态,用户选中每个区域进行高亮等操作,则操作前要把当前选中区域以及内容html都要保存下来:

?

编辑器re/undo设计与兑现

?

?

/**     * 当前编辑区域状态,包括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 操作时,历史管理器将当前状态添加到编辑状态栈即可,并更新内部游标。

?

编辑器re/undo设计与兑现

?

restore 操作时,需要利用管理器内部的游标来在状态栈间前(undo)后(redo)游走,用游标处的状态替换当前状态。


编辑器re/undo设计与兑现

?

?

注意点在于,当进行了re/undo操作后,再进行save状态保存,需要对状态栈进行清理,将当前游标以后的历史状态删掉,防止出现历史分支:

?

编辑器re/undo设计与兑现

?

?

?

另一点在于:对于键盘的连续输入,可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

?

?

1 楼 xtyong 2010-09-25   这个编辑与撤消的插件,能够整合到xheditor编辑器中吗? 2 楼 yiminghe 2010-09-25   不能,属于kissy editor一部分

热点排行