添加第一个功能按钮 – 在线编辑器(3)
在实现了在网页中插入一个可编辑区域以后,用户已经可以在这个区域中操作富文本内容。但是做为一个真正的编辑器是要有工具栏的,用户能通过工具栏上的按钮方便的对选中的文本进行操作。本文将介绍如何添加编辑器功能按钮。
加粗按钮
首先,我们在页面中添加工具条的HTML代码:
<div id="editor_toolbar"> <input id="editor_toolbar_bold" type="button" value="B" style="font-weight:bold;" onclick="editorInstance.bold()" /> </div>
工具条中包含一个按钮,在按钮被按下时,调用editorInstance的bold()方法。期望的结果是:在编辑框内,选中的区域将被加粗。
加粗操作
接下来需要实现加粗功能,在此之前,需要对execCommand()有一定了解
execCommand
execCommand浏览器自带的一个接口,通过它,我们可以对document、selection、或者一个给定的range进行操作。如加粗、斜体等。
语法:
bSuccess = object.execCommand(sCommand [, bUserInterface] [, vValue]) sCommand String,指定需要执行的命令,如Bold bUserInterface Boolean,可选,决定是否显示用户界面,如弹出一个提示框让用户输入,默认为false。 vValue Variant,可选,一个字符串、数字、或者其他需要assign的值
一般来说,第二个参数会传入false,因为编辑器本身会接管用户界面,第三个参数按照实际需要传入。这样就可以实现对选区的加粗:
document.execCommand("Bold", false, false);
代码实现
只需调用浏览器的execCommand方法,选区就被加粗了。
editor.Editor.prototype.bold = function(){ this.document.execCommand("Bold",false,false); };
简单极了!但是总觉得少了什么?是的,没有状态反射。不论用户选中的是否一段加粗的文本,按钮只有一个状态,用户无法感知当前选中文本的状态。
状态反射
添加状态反射的思路是:在选区发生变化的时候,编辑器核心派发一个事件,在此事件发生时判断此时选区的状态,根据状态设置按钮样式。
为何不由编辑器核心直接设置按钮样式呢?这是因为通过事件通讯能最大程度的降低模块和核心之间的耦合,也是模块可插拔的基础。
监听选区变化
造成选区发生变化的根源是鼠标点击或者键盘击键。因此,通过监听onkeydown和onmouseup事件就可以较粗略的得知选区变化。其实,此处将成为编辑器复杂后的第一个性能瓶颈,具体优化办法今后将具体描述。
事件机制
在本示例中,我实现了一个很简单的事件机制,外部模块通过 addEventListener 方法绑定方法到指定的事件,编辑器可以通过 dispatchEvent 方法派发指定的事件。具体代码见文末示例,不再赘述。
queryCommandState
在获得选区变化信息,并且能成功派发事件后,就需要使用浏览器提供的queryCommandState方法来获知选区状态了。
语法:
bDone = object.queryCommandState(sCmdID)
其中的sCmdID是命令标识符,和execCommand接受的第一个参数是相同的。
于是,只需使用:
editor.document.queryCommandState("Bold");
就可以获得当前选区是否处于加粗状态了。
好了,加粗按钮到此就完成了,大家可以看看示例,只在上次示例的基础上新增了60行代码。
浏览器差异
最后不得不提的是浏览器差异。
execCommand和queryCommandState各个浏览器支持的程度相去甚远,ppk大神有一个execCommand浏览器支持程度的详细表格:execCommand Compatibility。正是由于这些浏览器的差异,可能会造成一些在A浏览器下编辑好的内容,在B浏览器下无法修改,或者状态无法反射。
因此,一些成熟的编辑器都会重写这些命令和查询方法,以达到浏览器之间表现一致的目的。做的最好的当属ckeditor
小结
本文完成了加粗按钮,一个按钮一般包括两个部分,设置选区状态,反射选区状态。可以使用浏览器的接口 execCommand 和 queryCommandState 来简单实现。
通过前几篇文章,大家应该对编辑器的基本知识有了一定了解了,下一篇文章开始,我将和大家一起分析编辑器的需求,首先会从功能层面开始。本文是在线编辑器系列文章的第三篇,在这个系列文章中,我会逐步深入和大家分享编辑器开发过程中的奥妙和各种奇怪的问题。如果你对我的文章感兴趣,欢迎订阅我的博客及时收到更新。