富文本编辑

239 阅读4分钟

纯 css 实现【富文本编辑区】的 placeholder

原生 div 没有属性placeholder
但是当 div 设置了 contentEditable 属性变成【富文本编辑区】后,会有要设置 placeholder 的需求
通常有两种解法:CSS、JS。肯定优先选择纯 CSS 的实现,毕竟 JS 要监听额外事件并保存对应的聚焦状态,很麻烦。

纯 CSS 的思路也很简单,既然 div 没有 placeholder 属性,那可以 data- 开头自定义属性,给它绑定对应的 placeholder 值

CSS 通过伪类 + 伪元素的方式,在其 empty 状态下设置对应的 before 伪元素。 content 直接通过 attr()  获取上面的自定义属性:

.editable-input-container:empty::before { 
    content: attr(data-placeholder); 
    color: #bfbfbf; 
}


【富文本编辑区】回车为什么要用P标签

看很多在线编辑器,回车都是写入一个p标签。
这是为什么?想要解决什么问题?

实测了下

<div id="editor" contenteditable="true" >
    <div id="abcd" draggable='true'>abcd</div>
</div>
//在 abcd 后面回车,成了下面这样

<div id="editor" contenteditable="true">
    <div id="abcd" draggable="true">abcd</div>
    <div id="abcd" draggable="true"><br></div>
</div>

【contenteditable 富文本编辑区】的默认【回车】并非在是后面直接加一个 br 标签。
反而是把当前光标所在标签复制了一份。然后再在里面加个 br标签。
所以回车最好不用浏览器默认行为,而是用js控制。
那为什么不直接就单单价格 br标签呢?而是通常加个 p标签把新内容都包裹起来?
这是为了方便,想想,如果dom结构是这样

<div id="editor" contenteditable="true">
    'some text-1'
    <br>
    'some text-2'
</div>

做 selection 相关操作的时候会很不方便,而且所有元素的父亲都是 id=editor
div也是块级元素,为什么不用div?
因为要用div 的地方太多了,有时候要用 p元素来判断是否到了最上层。

【富文本编辑区】应该如何处理粘贴

一个设置了 contentEditable 属性变成可【富文本编辑区】的 div 标签,不对它做任何额外处理,不添加任何事件。

实测其复制粘贴不同内容的表现。
发现其在 chrome 一个浏览器上表现出的默认的粘贴行为就压根不统一(详细可以看我的另一篇文章)。
更不用说在不同浏览器上的表现了(没测)。

所以【富文本编辑区】的粘贴事件,一定要阻止浏览器的默认行为,要用JS去控制内容的展现\color{deeppink} {所以【富文本编辑区】的粘贴事件,一定要阻止浏览器的默认行为,要用JS去控制内容的展现}

应该如何表现:

  • 粘贴文本
    • 无论所复制的文本是否有样式,粘贴进来后都表现为纯文本,即无样式文本(QQ就是这么做的)
  • 从网站上复制了图片进行粘贴
    • 粘贴进来展示时,不是能原尺寸,宽或高要有个最大值。
    • 复制进来的图片,img标签的src 不能是一个图片地址,而要转成 base64 ,方便上传
  • 复制的是本地文件,并进行粘贴
    • 图片展示在编辑区
    • 非图片文件,不需要enter 或者 send 操作,直接就上传发送

选中了一段文本,输入框失去焦点会导致选中效果消失

起因:
在【输入区】中选中了一段内容,要用 emoji 来替换这段内容。
但是点击 emoji 会让【输入区】失去焦点,从而「被选中的蓝色背景」就没了。此时内容的替换太突兀了,体验差。

需求:在点击打开 emoji列表 时,【输入区】中所选中的内容依旧有「被选中的效果 」。

一开始想到的方式: 在点击emoji的事件函数中,重新令【输入区】获取【焦点】。
这样,人眼看起来似乎选中效果始终存在

 document.addEventListener('selectionchange', function(){
    console.log('selectionchange');
});

但是参考别人的项目,发现他们实现此功能时,selection 并没有变化。

所以,应该是通过「阻止输入区失去焦点」这种方式来实现此功能。

对编辑区图片的resize

需求:点击图片后,让此图片处于【可编辑 active 状态】,要能对图片的大小进行调整。
所以,每个img图片,都要在外层套一个壳子。而调整的其实是这个壳子的大小。

图片处于 active 状态时,是否应该将此图片进行选中?即,放进 selection 中。

通过对 wangEditor 的测试,当图片处于active 状态时,按键盘 delete 是可以删除的。
但是按键盘其他键是没有输入的,并且图片没有那种被选中的蓝色背景。
所以,并非放进 selection 中,这个删除功能应该是专门监听的键盘 delete 按键 。

点击「非壳子」的地方,才能「退出 active」状态。

在 resize 的过程中,要注意通过 键盘 或 快捷角 切换软件造成的 bug。
切换软件时,img 不退出 【可编辑 active 状态】。