如何在一个指定的div中选中字段?

1.场景
打算用vue写一个指令,并在使用指令的div中选中文字调用相应的功能。想到一个问题,如果用户选中文字跨越了该div,window.getSelection得到的是包含在该divtext以及div外的text,如何做个filter,提取我需要的text,但目前发现通过selection来查找有瓶颈,貌似走不通

  1. 歪路子解决办法

指定该divuser-selectcss特性,除了该元素外的元素则指定其user-select: none,根本上避免了用户选择不规范。

问问大神们,有没有其他方式来对选中的文本做一个筛选,提取自己想要的文本?

阅读 5.5k
2 个回答

Range API 很强大的, 有 compareBoundaryPoints 可以比较 range 的边界,所以 filter 是走得通的。

关键API:

  • window.getSelection
  • selection.getRangeAt
  • document.createRange
  • range.selectNode
  • range.compareBoundaryPoints
  • range.setStart / range.setEnd

且看例子,按我理解的实现的一个:

JSFiddle Range 操作示例

之前没接触过,花了点时间研究下,以下例子已做备注,不明白再问:

html js:

<!DOCTYPE html>
<html lang="en">

<head>
  <title></title>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body>

  <div id="test">
    Click the text!
    <span>---span---</span>
    <div>换行</div>
  </div>
  <div>qwerasdfzxcv</div>
  <div>123456789</div>

  <script>
    document.getElementById('test').onmousedown = function (e) {
      document.body.onmouseup = mouseup //绑定在 body 上而不是在 id test 上,以免选择超出的时候不响应
    }
    function mouseup(e) {
      var selector = document.getSelection()
      var sRange = selector.getRangeAt(0)
      var sText = sRange.toString() //选择的文字
      var newRange = document.createRange()
      newRange.setStart(selector.anchorNode, selector.anchorOffset) //从点击开始
      newRange.setEndBefore(document.getElementById('test').nextSibling) //到本元素最后一个字符的 range
      var totalText = newRange.toString() //从点击开始到本元素最后一个字符的文字

      if (totalText.indexOf(sText) === -1) { //选择区域跨元素
        sText = totalText
      }

      if (sText.trim()) alert(sText)

      document.body.onmouseup = null //注销,以免在其他 dom 节点也响应事件,导致报错
    }
  </script>
</body>

</html>

vue指令的实现:

Vue.directive('selection', {
  bind: function (el, binding, vnode) {
    el.onmousedown = function (e) {
      document.body.onmouseup = mouseup //绑定在 body 上而不是在 id test 上,以免选择超出的时候不响应
    }
    function mouseup() {
      var selector = document.getSelection()
      var sRange = selector.getRangeAt(0)
      var sText = sRange.toString() //选择的文字
      var newRange = document.createRange()
      newRange.setStart(selector.anchorNode, selector.anchorOffset) //从点击开始
      newRange.setEndBefore(el.nextSibling) //到本元素最后一个字符的 range
      var totalText = newRange.toString() //从点击开始到本元素最后一个字符的文字

      if (totalText.indexOf(sText) === -1) { //选择区域跨元素
        sText = totalText
      }

      if (sText.trim()) alert(sText)

      document.body.onmouseup = null //注销,以免在其他 dom 节点也响应事件,导致报错
    }
  }
})

其他拓展功能可在此基础上拓展

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题