项目中可能会遇到这样的简单需求,就是要点击相关的按钮在文本编辑器的光标处点插入相应的纯文本(不带格式粘贴);同时文本编辑器要求有不带格式粘贴的功能。
涉及到的知识是对光标的处理、剪贴板处理相关的知识。
简单富文本编辑器界面如下:
代码如下:
const $input = document.getElementById('my-input') const $btns = [...document.querySelectorAll('.my-btn')] let lastEditRange // 重置 placeholder function resetPlaceholder () { if ($input.innerText.length > 0) { $input.classList.remove('placeholder-visible') } else { $input.classList.add('placeholder-visible') } } resetPlaceholder() // 点击事件 $input.onclick = function () { // 获取选定对象 // 设置最后光标对象 lastEditRange = getSelection().getRangeAt(0) } // 编辑框按键弹起事件 $input.onkeyup = function () { // 获取选定对象 // 设置最后光标对象 lastEditRange = getSelection().getRangeAt(0) resetPlaceholder() } $input.onpaste = function (event) { const e = event || window.event // 阻止默认粘贴 e.preventDefault() // 粘贴事件有一个 clipboardData 的属性,提供了对剪贴板的访问 // clipboardData 的 getData(fomat) 从剪贴板获取指定格式的数据 const text = (e.originalEvent || e).clipboardData.getData('text/plain') || prompt('在这里输入文本') // 插入 document.execCommand('insertText', false, text) } $btns.forEach((el) => { el.onclick = function () { // 获取值 const dataVal = el.getAttribute('data-val') $input.focus() // 获取选定对象 const selection = getSelection() // 判断是否有最后光标对象存在 if (lastEditRange) { // 存在最后光标对象,选定对象清除所有光标并添加最后光标还原之前的状态 selection.removeAllRanges() selection.addRange(lastEditRange) } // console.log(selection.anchorNode.nodeName) if (selection.anchorNode.nodeName === '#text') { // 在文本中插入 // 如果是文本节点则先获取光标对象 const range = selection.getRangeAt(0) // 获取光标对象的范围界定对象,一般就是 textNode 对象 const textNode = range.startContainer // 获取光标位置 const rangeStartOffset = range.startOffset // 文本节点在光标位置处插入新的表情内容 textNode.insertData(rangeStartOffset, dataVal) // 光标移动到到原来的位置加上新内容的长度 range.setStart(textNode, rangeStartOffset + dataVal.length) // 光标开始和光标结束重叠 range.collapse(true) // 清除选定对象的所有光标对象 selection.removeAllRanges() // 插入新的光标对象 selection.addRange(range) } else if (selection.anchorNode.nodeName === 'DIV') { // 内容为空时,点击按钮 const dataValText = document.createTextNode(dataVal) $input.appendChild(dataValText) // 创建新的光标对象 const range = document.createRange() // 光标对象的范围界定为新建的表情节点 range.selectNodeContents(dataValText) // 光标位置定位在表情节点的最大长度 range.setStart(dataValText, dataValText.length) // 使光标开始和光标结束重叠 range.collapse(true) // 清除选定对象的所有光标对象 selection.removeAllRanges() // 插入新的光标对象 selection.addRange(range) } resetPlaceholder() } })
JS 实现复制功能(document.execCommand)
function copy(text) { const input = document.createElement('input'); document.body.appendChild(input); input.setAttribute('value', text); input.select(); if (document.execCommand('copy')) { document.execCommand('copy'); console.log('复制成功'); } document.body.removeChild(input); }
参考引用:
1. contenteditable change events
2. html 元素 contenteditable 属性如何定位光标和设置光标
3. contenteditable 插入及粘贴纯文本内容