关于各浏览器下textarea中光标位置的获取问题详解

本文详细讲解了在textarea中获取光标位置的方法,包括IE和非IE浏览器的兼容性处理。通过document.selection.createRange()在IE下获取选中内容,而非IE浏览器则使用selectionStart和selectionEnd。同时介绍了TextRange对象的相关属性和方法,以及如何进行文本替换操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

申明一下,我这里只是讲的textarea中的有关光标的几种方法,并不是针对整个document的,我相信把textarea中的光标方法弄清楚了的话,其他的就简单多了。

最近接触到一个新的东西,就是textarea中光标位置的获取。先来说一说我是怎么接触到这个东西的,最近一直在写一个能够通用的评论插件,在这个评论插件中我们加入了表情插入这个功能,也就是技能文字评论,也能表情评论,目前这个插件的样子是这样的

这里写图片描述

就是在做表情插入功能的过程中遇到的这个问题,按照最一般的从头到尾的写评论是不会出问题的,但是如果是评论写了一大段,然后回头想再插入一个表情的时候,问题就出现了。

这里写图片描述

那就是你必须知道你当前光标所在的位置是在哪里。。。

问题出现了当然得解决了,于是很正常的想法,当然是网上各种搜了,当然找到了获取光标位置的方法,但是很多都只是对其中某一个或某几个方法或属性的介绍或者是简单说明,并不是特别全面,所以在这里把握自己学到的一些关于光标位置获取的东西做一个小小的分享与总结

兼容性是老生常谈的一个问题,所以每一个功能的实现都有几种兼容性的实现方法,光标问题的兼容性主要表现在IE非IE浏览器下面,也就是要实现IE非IE的兼容性方法。首先,这里要说的是textarea中选中文本的获取

IE下选中内容的获取是很简单的,直接通过 document.selection.createRange()这个方法就可以获取到选中区域的内容,该方法返回的是一个对象,其中text字段就是选中的文本。

这里写图片描述

非IE下则是通过对象的selectionStart(选中范围的起点)和selectionEnd(选中范围的末点),然后通过截取字符串substring来获取选中范围的.

几个TextRange(顾名思义,TextRange就可以理解为文本的选择范围)的常用属性及方法:

属性

  • boundingWidth 获取绑定TextRange对象的矩形的宽度

  • boundingHeight 获取绑定TextRange对象的矩形的高度

  • boundingLeft 获取绑定TextRange对象的矩形左边缘和包含TextRange对象的左侧之间的距离

  • boundingTop Retrieves the distance between the top edge of the rectangle that bounds the TextRange object and the top side of the object that contains the TextRange.

  • offsetLeft 获取对象相对于版面或由offsetParent属性指定的父坐标的计算左侧位置

  • offsetTop 获取对象相对于版面或由offsetParent属性指定的父坐标的计算顶端位置

  • htmltext 选中范围内包含的html片段

  • text 设置或获取范围内包含的纯文本

方法

  • moveStart 设置文本范围的开始位置

  • moveEnd 设置文本范围的结束位置

  • collapse 将插入点移动到当前范围的开始或结尾

  • select 将当前选择区置为当前对象,也就是从moveStart设置的位置开始到moveEnd设置的位置结束的范围

    代码实例

<script>
    window.onload = function() {

      var textarea = document.getElementById('textarea');
      var getPosi = document.getElementById('getSelectedText');

      getPosi.onclick = function () {
        console.log(getSelectedText(textarea))
      }

      function getSelectedText(obj) {
        var userSelection;

        if (typeof obj.selectionStart === 'number' && typeof obj.selectionEnd === 'number') {
          // 非IE浏览器
          // 获取选区的开始位置
          var startPos = obj.selectionStart,
                    // 获取选区的结束位置
              endPos = obj.selectionEnd;
          console.log("非IE:")
          console.log("选区开始点:" + startPos + ',选区结束点:' + endPos)

          userSelection = obj.value.substring(startPos, endPos)

        } else if (document.selection) {
          // IE浏览器
          console.log("IE:")
          userSelection = document.selection.createRange().text
        }

        return userSelection
      }
    }
  </script>

测试效果

非IE下:

这里写图片描述

这里写图片描述

IE下:
这里写图片描述

这里写图片描述

文本替换,第二个要说的是文本替换,在非IE下直接通过setRangeText(str)即可替换选中文本,未选中文本,则在光标处添加文本;在IE下通过设置document.selection.createRange().text即可达到替换文本的效果,未选中文本,则在光标处添加文本。也就是达到了在任意位置插入文本的效果

<script>
    window.onload = function() {

      var textarea = document.getElementById('textarea');
      var getPosi = document.getElementById('changeSelectedText');

      getPosi.onclick = function () {
        changeSelectedText(textarea, '替换文本')
      }

      function changeSelectedText(obj, str) {

        if (window.getSelection) {
          // 非IE浏览器
          console.log("非IE:")
          textarea.setRangeText(str);
          //  在未选中文本的情况下,重新设置光标位置
          textarea.selectionStart += str.length;
          textarea.focus()

        } else if (document.selection) {
          // IE浏览器
          console.log("IE:")
          obj.focus();
          var sel = document.selection.createRange();
          sel.text = str;
        }

      }
    }
  </script>

讲完这两个案例,相信开头提出的问题已经能够解决了,,,有心人可以尝试一下其它方法,比如说getSelection,相信搜了光标问题的人基本上都见过这个方法,这里就不赘述了,对于开头的问题,这里直接把核心代码给出来,自己可以亲自实践一下。

function insertText(obj,str) {
        if (document.selection) {
            console.log('selection')
            obj.focus();
            var sel = document.selection.createRange();
            console.log(sel)
            // 设置或获取范围内包含的文本
            sel.text = str;

        } 
        else if (typeof obj.selectionStart === 'number' && typeof obj.selectionEnd === 'number') {

            // 这是一种复杂的方法,可一直接用上面讲到的方法代替

            console.log('selectionStart/selectionEnd')
            // console.log(window.getSelection())
            // 获取选区的其实位置
            var startPos = obj.selectionStart,
            // 获取选区的结束位置
                endPos = obj.selectionEnd,
                // 设置光标位置
                cursorPos = startPos,
                // 传入obj的内容
                tmpStr = obj.value;

            console.log('startPos: ' + startPos)
            console.log('endPos: ' + endPos)

            // 插入内容
            obj.value = tmpStr.substring(0, startPos) + str + tmpStr.substring(endPos, tmpStr.length);
            // 光标现在位置
            cursorPos += str.length;

            console.log('obj.selectionStart: ' + obj.selectionStart)
            console.log('obj.selectionEnd: ' + obj.selectionEnd)
            // 重新设置选中区域
            obj.selectionStart = obj.selectionEnd = cursorPos;

        } else {

            obj.value += str;

        }
    }

    function moveEnd(obj){
        obj.focus();
        // 获取整个obj对象的内容(value值)
        var len = obj.value.length;
        if (document.selection) {
            console.log('IE下选中文本')
            // IE
            var sel = obj.createTextRange();
            // 更改范围的开始位置
            sel.moveStart('character',len);
            // 更改范围的结束位置,开始位置和结束位置一样即为重合
            sel.moveEnd('character',len);
            console.log(sel.text);
            // 将插入点移动到当前范围的开始或结尾
            sel.collapse();
            // 将当前选择区置为当前对象
            // sel.select();

        } else if (typeof obj.selectionStart == 'number' && typeof obj.selectionEnd == 'number') {
            // 其他浏览器
            console.log('其他浏览器选中文本');
            // 文本选中
            // obj.setSelectionRange(len-4, len);
            // obj.setRangeText();
            // 设置光标位置
            obj.selectionStart = obj.selectionEnd = len;
        }
    }

有什么问题的话,欢迎指出

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值