1.获取光标位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
<!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>

  

posted on   ygunoil  阅读(746)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示