HTML 的选择对象返回错误的节点



对我来说,知道在一个字母之前点击和在前一个字母之后点击的区别是很重要的,尽管这两种情况在屏幕上看起来是一样的。这是因为可以通过嵌套的跨的数量来传递含义。一个例子:

<span id="x-container"><span id="x">x</span></span><span id="y">y</span>
<script>
  document.addEventListener('selectionchange', e => {
    var selection = window.getSelection();
    if (selection.type =='Caret')
      console.log(selection.anchorNode.textContent,selection.anchorOffset)
  })
</script>

console.log()如下所示:

点击x稍微偏左,我们得到x 0(正确)

点击x稍微居中偏右,我们得到x 1(正确)

点击y稍微偏左,我们再次得到x 1:错误!!!!

点击y在中间偏右一点,我们得到y 1(正确)

我如何修复第三种情况,这样我就可以知道我们是在y之前点击还是在x之后点击?我试着在两者之间添加一个虚拟的span,但它不起作用。

注意这里的x和y看起来有点靠近。在我正在做的实际事情中,我添加了填充,所以它看起来不那么奇怪,更容易点击y之前和x之后。请相信我的话,添加填充/边距并不能改变问题…

由于您只对由鼠标事件触发的selectionchange事件感兴趣,因此您可以检查哪个元素接收了触发此selectionchange事件的mousedown事件。
你只需要将它存储在你的selectionchange处理程序可访问的变量中,然后如果它不是选择的anchorNode,或者不包含它,你就知道浏览器搞砸了。
您必须检查实际目标是否在之前或之后才能正确找到新的anchorOffset:

let activeElem = null;
document.addEventListener('selectionchange', e => {
  const selection = window.getSelection();
  let { anchorNode, anchorOffset } = selection;
  if (anchorNode === selection.focusNode) {
    if (activeElem && (!activeElem.contains(anchorNode))) {
      const isBefore = activeElem.nextElementSibling.contains(anchorNode);
      anchorOffset = isBefore ? activeElem.textContent.length : 0;
      anchorNode = activeElem;
    }
    console.log(anchorNode.textContent, anchorOffset);
  }
})
document.addEventListener("mousedown", e =>
  // here you can change the selector from "span" to anything more restrictive
  // as long as it matches your "targetted" elements
  activeElem = e.target.matches("span") ? e.target : null
);
document.addEventListener("mouseup", e => activeElem = null);
<span id="x">x</span><span id="b">b</span>

最新更新