首先谢谢原文作者的文章带来的灵感,然后道歉我实在是找不到原文链接了,毕竟过了一段时间才来写这个文章的,最后如侵权请联系删除。
前段时间刚有个需求,就是在富文本编辑器中在光标处添加固定字段,而固定字段是当前下拉选择框中的文字。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<script src="js/jquery-3.2.1.js" type="text/javascript" charset="utf-8"></script>
<style>
#edit {
height: 200px;
width: 200px;
border: 1px solid black;
}
</style>
</head>
<body>
<div id="edit" contenteditable></div>
<select name="AreaId" size="1" class="sel" id="AreaId">
<option value="1">北京</option>
<option value="2">上海</option>
<option value="3">深圳</option>
<option value="4">广州</option>
</select>
<button id="sendEmoji">发送表情</button>
<script>
// 定义最后光标对象
var lastEditRange;
// 编辑框点击事件
document.getElementById('edit').onclick = function() {
// 获取选定对象
var selection = getSelection()
// 设置最后光标对象
lastEditRange = selection.getRangeAt(0)
}
// 编辑框按键弹起事件
document.getElementById('edit').onkeyup = function() {
// 获取选定对象
var selection = getSelection()
// 设置最后光标对象
lastEditRange = selection.getRangeAt(0)
}
// 表情点击事件
document.getElementById('sendEmoji').onclick = function() {
// 获取编辑框对象
var edit = document.getElementById('edit')
// 编辑框设置焦点
edit.focus()
// 获取选定对象
var selection = getSelection()
// 判断是否有最后光标对象存在
$("#AreaId").val();
var options = $("#AreaId option:selected").text();
//获得下拉框内容
if(lastEditRange) {
// 存在最后光标对象,选定对象清除所有光标并添加最后光标还原之前的状态
selection.removeAllRanges()
selection.addRange(lastEditRange)
}
// 获取输入框对象
var emojiInput = document.getElementById('emojiInput')
// 判断选定对象范围是编辑框还是文本节点
if(selection.anchorNode.nodeName != '#text') {
// 如果是编辑框范围。则创建表情文本节点进行插入
var obj = document.getElementById('AreaId');
var index = obj.selectedIndex;
var text = obj.options[index].text;
var value = obj.options[index].text;
var emojiText = document.createTextNode(value)
if(edit.childNodes.length > 0) {
// 如果文本框的子元素大于0,则表示有其他元素,则按照位置插入表情节点
for(var i = 0; i < edit.childNodes.length; i++) {
if(i == selection.anchorOffset) {
edit.insertBefore(emojiText, edit.childNodes[i])
}
}
} else {
// 否则直接插入一个表情元素
edit.appendChild(emojiText)
}
// 创建新的光标对象
var range = document.createRange()
// 光标对象的范围界定为新建的表情节点
range.selectNodeContents(emojiText)
// 光标位置定位在表情节点的最大长度
range.setStart(emojiText, emojiText.length)
// 使光标开始和光标结束重叠
range.collapse(true)
// 清除选定对象的所有光标对象
selection.removeAllRanges()
// 插入新的光标对象
selection.addRange(range)
} else {
// 如果是文本节点则先获取光标对象
var range = selection.getRangeAt(0)
// 获取光标对象的范围界定对象,一般就是textNode对象
var textNode = range.startContainer;
// 获取光标位置
var rangeStartOffset = range.startOffset;
// 文本节点在光标位置处插入新的表情内容
textNode.insertData(rangeStartOffset, options)
// textNode.insertData(rangeStartOffset, emojiInput.value)
// 光标移动到到原来的位置加上新内容的长度
range.setStart(textNode, rangeStartOffset + options.length)
// range.setStart(textNode, rangeStartOffset + emojiInput.value.length)
// 光标开始和光标结束重叠
range.collapse(true)
// 清除选定对象的所有光标对象
selection.removeAllRanges()
// 插入新的光标对象
selection.addRange(range)
}
// 无论如何都要记录最后光标对象
lastEditRange = selection.getRangeAt(0)
}
</script>
</body>
</html>
因为原文是利用JS写的,我为了偷懒新增代码中部分使用了JQ,然后可能会有人看的不习惯,抱歉毕竟是新手。如果有更好的方法,请直接贴出代码,我可能对语言了解能力比较差,还是喜欢直接看代码