输入框插入表情的实现

在普通的 textarea 中,只能显示普通的文本。若是简单的输入文本,textarea 便足以胜任。可是实际状况每每要复杂得多。html

简单版本的插入表情

常见的版本通常都是使用 textarea,而后表情使用某种约定的文本格式代替,好比“你好啊[微笑]”。在呈现的时候,经过固定的文本解析方法将内容中的表情文本替换成图片。新浪微博中发微博的输入框就是如此。可是,在这有一点须要注意,若是只是简单的在文本的最后插入表情之类的预约好的文本格式,只需获取到到 textarea 的 value 而后作加法便可。前端

let editor = document.querySelect('#editor');
editor.value += '[微笑]';

没你想的这么简单

但实际状况却没有这么简单,由于用户能够本身选择光标的位置。当用户在某一段文本中间插入光标以后,可不是简单的加法了。在这种状况下,须要获取到光标所在位置,在这个位置上插入用来代替表情的文本,而后将光标设置到表情文本的后面。在这须要两个额外的方法:getCaretPositionsetCaretPositionsegmentfault

getCaretPosition/setCaretPosition

浏览器并无提供直接获取光标位置的方法,须要咱们变通的处理。浏览器基本上都支持文本框的select()方法,这个方法用于选中文本框中全部的文本,可是只能乖乖的拿到返回的全部文本。HTML5 添加了两个属性:selectionStart 和 selectionEnd 帮助咱们更加顺利地获取选择的文本。这两个属性中保存的是基于0的数值,表示所选择的文本的范围,分别表示文本选区(选中的文本)开头和结尾相对整个文本内容的偏移量(在整个文本内容中的位置)。例如:浏览器

let editor = document.querySelector('#editor');
// 从第一个字符开始,选中三个字符
editor.selectionStart = 0;
editor.selectionEnd = 1;

// 从第三个字符开始选中三个字符
editor.selectionStart = 2;
editor.selectionEnd = 5;

说到这你可能要问了,这个光标有啥关系啊?别急,听我慢慢说。既然上述两个设置不一样数字能够选择文本,那若是两个值设置成相同的数字,会怎么样呢?code

// 从第三个字符开始选中零个字符
editor.selectionStart = 2;
editor.selectionEnd = 2;

起点和终点重合了!那么换个角度来描述就是:当咱们在获取光标位置的时候,其实就是选中的文本范围起点和重点重合,至关于文本范围的起点偏移量其实就是光标所在的位置偏移量,因此此时selectionStart的返回值就是咱们须要的结果。htm

更关键的是,当 End 和 Start 设置成相同值时,选区也是空的,起点和重点充电,就好像是设置了光标的位置。其实有一个简便的方法 setSelectionRange(start, end),原理相同。对象

固然有兴趣你也能够试试 End小于 Start的状况。上述这些在现代浏览器和 IE9+ 上都支持。图片

前端向来麻烦的仍是浏览器的兼容问题。在低版本的 IE 中只能使用 document.selection 对象来模拟光标定位了。document.selection 只存在于 IE8 及更早的版本(可使用 window.getSelection 代替),保存着用户在整个文档范围内选择的文本信息,可是没法肯定用户选择的是页面中哪一个部位的文本。要想取得选择的文本,首先须要建立一个范围(Range,IE9+ 支持 DOM Range API,可是 IE8及以前的版本不支持,可是有相似的概念,text range。这是 IE 专有的特性)。可以使用 document.selection.createTextRange 来建立咱们所须要的 text range。而后利用moveStart().aspx)将文本的范围的起点从当前位置(当前位置起点和重点是重合的)移动到文本的开头,而后计算选中文本的长度,这个长度值能够用来代替当前光标的位置。文档

let range = document.selection.createRange();
range.moveStart("character", editor.value.length);
cursurPosition = range.text.length;

设置光标位置思路相似,可是代码稍有不一样:get

let range = editor.createTextRange();
range.collapse(true);
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();

总的来讲,在 textarea 中获取和设置光标位置仍是蛮简单的。讲到这里了,我想插入表情应该是很轻松的一件事情了

获取光标位置(文本范围先后重叠) -> 修改文本范围(或者手动拼接) -> 从新设置光标位置

至此,表情插入功能的基本实现。

还没结束

上述例子中,在输入框中表情只能以文本的形式呈现。若是想在输入框中呈现输入的表情,该怎么办呢?使用 contenteditable 属性为 true 的容器代替 textarea 是必须的,由于 textarea 中只能显示文本。可是这就足够了吗?不,显然不够。没有了 textarea 则觉得这没有了 setSelectionRange, selectionStart 和 selectionEnd。可是好在原理也是相似,依旧使用 Range API 或者 Text Range(IE8及其更低版本)。具体的能够参考这篇:html元素contenteditable属性如何定位光标和设置光标和这篇在可编辑的div中插入图片。 具体实现代码我就不贴了,你们能够本身思考捋一捋。触类旁通,若是你真真正正地知道如何正确插入图片,那么插入复杂的 DOM 结构对你来讲也是垂手可得。

相关文章
相关标签/搜索