“选区”和“光标”

  • 选区: 鼠标选中的那一部分,通常是蓝色
  • 光标:闪烁的竖线
  • “选区”和“光标”是什么?
    • Selection 对象表示用户选择的文本范围或插入符号的当前位置。它代表页面中的文本选区,可能横跨多个元素。通常由用户拖拽鼠标经过文字而产生。

      • 获取 selection ,可以通过全局的 getSelection方法:
        const selection = window.getSelection();

      • 通常情况下我们不会直接操作 selection 对象,而是需要操作用 seleciton 对象所对应的用户选择的 range
        const range = selection.getRangeAt(0);
        注意:firefox支持多选区,可以通过selection返回的rangeCount看;因此getRangeAt需要传入一个序号,但目前就只有火狐支持多选区,其他在那不考虑

      • 获取选区的内容:这个暂时只支持不可编辑元素,可编辑的会获取不到
        window.getSelection().toString() // 或者 window.getSelection().getRangeAt(0).toString()

    • Range 对象表示包含节点和部分文本节点的文档片段。通过 selection 对象获得的 range对象才是我们操作光标的重点。

      • collapsed:表示选区的起点与终点是否重叠。true表示重叠
      • 光标:选区的起点与终点重叠
  • input和textarea选区操作
    • 主动选中某一区域:setSelectionRange(selectionStart, selectionEnd [, selectionDirection])

      • selectionStart :开始位置
      • selectionEnd:结束位置
      • selectionDirection:方向
        txt.setSelectionRange(0,2); txt.focus();
    • 聚焦到某一位置(起始位置一样):txt.setSelectionRange(2, 2)

    • 还原之前的选区:有时候,我们需要在点击其他地方后,再重新选中之前的选区。
      const pos = {} document.onmouseup = (ev) => { pos.start = txt.selectionStart; pos.end = txt.selectionEnd; } btn.onclick = () => { txt.setSelectionRange(pos.start,pos.end) txt.focus(); }

    • 在指定选区插入(替换)内容:setRangeText(replacement)setRangeText(replacement, start, end [, selectMode])

      • replacement:表示需要替换的文本
      • start:开始位置
      • end:结束位置
      • selectMode:替换后选区的状态(select 替换后选中;start 替换后光标位于替换词之前;end 替换后光标位于替换词之后; preserve 默认值,尝试保留选区)
        • 尝试保留选区:假设手动选中的区域是[9,10],如果在[1,2]的位置替换新内容,那么选区仍然在之前位置。如果在[8,11]的位置替换新内容,由于新内容的位置覆盖了之前的选区,原选区也就不存在了,那么替换完之后,选区会选中刚刚插入的新内容
  • 普通元素的选取操作
    • 主动选中某一区域(这要求偏移量不能超过一个节点的最大偏移量,不适用于包含富文本)

      1. 先设置区域的起始位置:range.setStart(startNode, startOffset);range.setEnd(endtNode, endOffset);
        • 注意:如果起始节点类型是 TextComment , or CDATASection 之一, 那么 startOffset 指的是从起始节点算起字符的偏移量。 对于其他 Node 类型节点, startOffset是指从起始结点开始算起子节点的偏移量。
      2. 移除选区:selection.removeAllRanges()
      3. 添加选区:selection.addRange(range)
        在这里插入图片描述
    • 主动选中富文本中的某一区域(富文本:支持内嵌标签)

      • 找选中区间的节点和偏移量
        1. 递归遍历,找到所有文本节点 #text

        2. 计算文本的位置区间

        3. 查找满足条件的范围区间
          在这里插入图片描述

          [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aWIFPpFB-1655799282590)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/9ebe2dd1-bd51-47d4-845f-0d367cfe8c4a/Untitled.png)]

    • 聚焦到某一位置

      只需要把起始位置设置相同
      在这里插入图片描述

    • 还原之前的选区

      • 计算相对于整段文本的偏移量
        1. 遍历,找出所有的#text

        2. 计算文本的位置区间

        3. 匹配选区与区间的#text,计算偏移量

          [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SqFhKf1L-1655799282591)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/96cbde94-44dc-4f82-b6c5-9878ead0f13d/Untitled.png)]

          [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1TGPcguN-1655799282592)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/d4fc8b71-240c-4d6f-af23-273bbb7203bd/Untitled.png)]

    • 在指定选区插入(替换)内容

      • range.insertNode:在选区的起点处插入一个节点,并不会替换掉当前已选中的。

      • deleteContents:删除选区的内容

      • document.createTextNode: 创建文本

      • document.createElement: 创建带标签的文本

      • range.setStartAfter:设置区间的起点为该元素的后面

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BHrZM3E8-1655799282593)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/fc297369-27b6-4fbc-bc6f-15a1ea2810e5/Untitled.png)]

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dFUL0GcW-1655799282593)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/b96b372a-16db-44a4-b92d-d4c0de0ccb9a/Untitled.png)]

    • 给指定选区包裹标签

      • range.surroundContents:表示给选区包裹一层标签

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4rz5IfZZ-1655799282594)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/a2f532bb-e814-4145-9dd7-03733b0e2143/Untitled.png)]

        注意:当选区有“断层”时,会报错。比如:

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p0kUYGq5-1655799282595)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/f6c5d545-37e2-4cf8-9d5d-8d4f95874088/Untitled.png)]

      • 先通过range.extractContents方法获取选区的内容,然后将选区内容添加到新节点上,最后插入新内容(避免选区有断层现象出现)
        在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值