1.获取光标位置
<html> <head> <title>光标测试</title> <style> p { display: flex; flex-direction: row; } .btn { height: 24px; margin: 0 10px; } .edit-div { display: inline-block; width: 225px; border: 1px solid #decdcd; } </style> <script> function getCursortPosition(e) { var eleP = e.target.parentNode; //获取父级元素 var pos = 0; if (e.target.nodeName == "DIV") { pos = getDivPosition(e.target); } else { pos = getPosition(e.target); } var spanEle = (eleP.childNodes)[7]; spanEle.innerText = pos; } //可编辑div获取坐标 const getDivPosition = function (element) { var caretOffset = 0; var doc = element.ownerDocument || element.document; var win = doc.defaultView || doc.parentWindow; var sel; if (typeof win.getSelection != "undefined") {//谷歌、火狐 sel = win.getSelection(); if (sel.rangeCount > 0) {//选中的区域 var range = win.getSelection().getRangeAt(0); var preCaretRange = range.cloneRange();//克隆一个选中区域 preCaretRange.selectNodeContents(element);//设置选中区域的节点内容为当前节点 preCaretRange.setEnd(range.endContainer, range.endOffset); //重置选中区域的结束位置 caretOffset = preCaretRange.toString().length; } } else if ((sel = doc.selection) && sel.type != "Control") {//IE var textRange = sel.createRange(); var preCaretTextRange = doc.body.createTextRange(); preCaretTextRange.moveToElementText(element); preCaretTextRange.setEndPoint("EndToEnd", textRange); caretOffset = preCaretTextRange.text.length; } return caretOffset; } //输入框获取光标 const getPosition = function (element) { let cursorPos = 0; if (document.selection) {//IE var selectRange = document.selection.createRange(); selectRange.moveStart(‘character‘, -element.value.length); cursorPos = selectRange.text.length; } else if (element.selectionStart || element.selectionStart == ‘0‘) { cursorPos = element.selectionStart; } return cursorPos; } </script> </head> <body> <p> <label>输入框测试:</label> <input type="text" style="width:220px" onclick="getCursortPosition(event);" /> <span>光标位置:</span> <span></span> </p> <p> <label>文本框测试:</label> <textarea rows="5" style="width:220px" onclick="getCursortPosition(event);"></textarea> <span>光标位置:</span> <span></span> </p> <div> <label>可编辑div:</label> <div contenteditable="true" class="edit-div" onclick="getCursortPosition(event);"></div> <span>光标位置:</span> <span></span> </div> </body> </html>
2.设置光标位置
2.1 设置光标位置input、textarea
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <input type="text" id="test-input" value="Example" /> <input type="text" id="test-input2" value="Example" /> </body> <script> function setCaretPosition(ctrl, pos) { // Modern browsers if(ctrl.setSelectionRange) { ctrl.focus(); ctrl.setSelectionRange(pos, pos); // IE8 and below } else if(ctrl.createTextRange) { var range = ctrl.createTextRange(); range.collapse(true); range.moveEnd(‘character‘, pos); range.moveStart(‘character‘, pos); range.select(); } } var input = document.getElementById(‘test-input‘); setCaretPosition(input, input.value.length); </script> </html>
2.2 设置光标位置可编辑div
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>在可编辑div中定位和设置光标</title> <style> #edit { height: 500px; width: 500px; border: 1px solid red; } </style> </head> <body> <div id="edit" contenteditable></div> <input type="text" id="emojiInput"> <button id="sendEmoji">发送表情</button> <script> // 发送表情的按钮 var sendEmoji = document.getElementById(‘sendEmoji‘); // 定义最后光标对象 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‘); // 获取输入框 var emojiInput = document.getElementById(‘emojiInput‘); // 编辑框获得焦点 edit.focus(); // 获取选定对象 var selection = getSelection(); // 如果保存的有上次的光标对象 if (lastEditRange) { // 清除所有选区 selection.removeAllRanges(); // 添加最后光标还原之前的状态 selection.addRange(lastEditRange); } // 判断选定对象范围是编辑框还是文本节点,如果是编辑框范围 if (selection.anchorNode.nodeName != ‘#text‘) { // 创建表情文本节点进行插入 var emojiText = document.createTextNode(emojiInput.value); // 如果文本框的子元素大于0,则表示有其他元素,则按照位置插入表情节点 if (edit.childNodes.length > 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, emojiInput.value); // 添加了新内容,将光标移动到新的位置 range.setStart(textNode, rangeStartOffset + emojiInput.value.length); // 将选区折叠为一个光标 range.collapse(true); // 清除所有光标对象 selection.removeAllRanges(); // 添加新的光标对象 selection.addRange(range); } // 记录最后光标对象 lastEditRange = selection.getRangeAt(0) } </script> </body> </html>