Z

开发一个富文本编辑器

最近打算自己开发一个富文本编辑器,虽然已经有很多轮子了,但为了学习还是要亲自实现一下。

现在国内开源的的富文本编辑器也不少,但大部分样子已经丑死了,比如百度这个:

ueditor

虽然功能很多,但在Retina屏幕上看全是煳的,这么多功能堆在一起,容易引发选择困难症…….

我的富文本编辑器目标:

  1. 实现基本的文本操作,包括加粗,下划线,斜体,删除线,列表插入,引用,代码编辑。
  2. 兼容firefox,safari,chrome的最新版,ie8+。

我开发的编辑器最重要的就是简洁酷炫,而且我认为真正对富文本编辑有要求的用户是不会在网页上进行编辑的,所以功能不用太多,常用的就行了,所以我把编辑器设计成了这个样子的: 是不是有种逼格满满的感觉==。 因为我用的是macbook,所以低分辨率的图片看上去效果非常差,所以我选择了fonticon,用的是这个字体库:fontawesome,后面还需要删除字体库中的大部分字体。 文本编辑区域我使用普通的div,设置contentEditable属性,这也是常见的富文本编辑形式,但在跨浏览器时需要注意,firefox在输入英文字符时会超出输入框,解决办法很简单,加入以下css规则即可。

1word-wrap: break-word;

接着要完成加粗,斜体,下划线,删除线这四个功能。这时你会怎么做?使用b,i,u,strike这些标签么?如果真的是这样就太繁琐了,维护节点关系和清理空白节点会很繁琐,幸好有document.execCommand 这个方法。使用方法很简单,只要传入预定的功能参数即刻,下面是几个例子:

1document.execCommand('bold'); // 加粗
2document.execCommand('italic'); // 倾斜
3document.execCommand('underline'); // 下划线
4document.execCommand('strikeThrough'); // 删除线
5
6document.execCommand('createLink', true, 'http://xx.com'); // 为所选文字加链接

详细说明可以看MDN文档

在这里要说明总结下document.execCommand的使用方法。 document.execCommand就是像上面那样用的,最开始我看文档的时候以为是先获取要改变样式的文字范围的range对象,接着对这个对象使用execCommand方法。但事实上不是的,直接使用document.execCommand方法就好。 假如你为加粗按钮绑定了事件,点击后选定文字会加粗或者没有选定文字,光标之后的文字进入粗体模式,只要一行document.execCommand('bold'); 即可,这个方法会自动确定工作模式。也就是说, 如果你在选定了某范围的文字后调用该方法,选定文字会自动加粗;若没有选定文字,当前光标之后的内容会进入加粗模式,再次调用,退出加粗模式;如果文字中有某段是被加粗过的,将光标移至该范围中,不需要调用这个方法,浏览器会自动进入加粗模式中;再将光标移出这个加粗的文字范围,浏览器会自动退出加粗模式。有了这个特性,开发就方便多了。这个规则同样适用于另外三个功能。

现在四个样式编辑功能就基本完成了,但光这样还不够,还需要让光标移动到样式已修改的范围中,按钮状态发生变化,就像这样: 要实现这个功能,就要检测当前光标位置文本的样式,你可以通过遍历其父节点,看看当前光标位置的文字元素被哪些元素包裹着,这样就能知道被赋予了哪些样式。但浏览器还是为我们提供了一个简便的方法:document.queryCommandState('bold')。这个方法的作用就是获取当前光标位置或者当前选区的文字有哪些样式,使用方法同上面的execCommand方法类似:

1document.queryCommandState('bold');
2document.queryCommandState('italic');
3document.queryCommandState('underline');
4document.queryCommandState('strikeThrough');

当改方法检测到文字被赋予参数中的样式时返回true,否则返回false。有了这个方法,不论是选取还是单个光标,我们都能知道他的样式是什么,接着再根据返回值的情况动态更新对应按钮的状态即可。

同样也要总结下queryCommandState方法的一些值得注意的点。 当你选择了一个选区后再调用queryCommandState方法,如果该选区中的文字样式有相同类型但样式相反的状态,则以改变后的样式为准。这是什么意思呢,假如你选择了一段文字,文字中既有加粗也有不加粗,这时调用queryCommandState方法,就会返回true,说明这段文字是经过加粗的,即使被选中的文字也有不加粗的部分,具体情况就是下面这样: 出现这样的情况也是符合逻辑的。而且更重要的是,如果在这之后调用了document.execCommand('bold');方法,因为当前queryCommandState返回的是true,所以选区中的文字加粗部分会被取消加粗,而没有加粗的部分并不会加粗,而是继续保持原样。

现在一个超轻量级的富文本编辑器的雏形已经出来了,暂时写到这吧。