代码之家  ›  专栏  ›  技术社区  ›  Tim Molendijk

将选择设置为节点的边缘会使WebKit报告的范围不一致

  •  2
  • Tim Molendijk  · 技术社区  · 11 年前

    假设以下DOM树:

    <div id="edit" contenteditable="true">
      this content <a id="link" href="http://www.google.com/">contains</a> a link
    </div>
    

    然后创建一个范围 之后 锚:

    var r = document.createRange();
    var link = document.getElementById('link');
    r.setStartAfter(link);
    r.setEndAfter(link);
    

    正如预期的那样 commonAncestorContainer 是id为的元素 edit :

    console.log(r.commonAncestorContainer);  /* => <div id="edit" contenteditable="true">…</div> */
    

    将选择设置为此范围:

    var s = window.getSelection();
    s.removeAllRanges();
    s.addRange(r);
    

    现在查询窗口中的当前选择范围,并检查其 commonAncestor容器 :

    var r2 = s.getRangeAt(0);
    console.log(r2.commonAncestorContainer);
    

    你会发现,在Firefox中,结果是意料之中的;与id相同的元素 编辑 .

    然而,在WebKit浏览器中,选择范围的祖先容器突然变成了锚点内的文本节点; "contains" ,但当你开始打字时,你会发现你真的不在锚内。世界跆拳道联盟!?

    Click here for a live demo .

    这种行为背后有什么潜在的理由吗?有什么理由认为这不是WebKit漏洞吗??

    谢谢你的0.02美元。

    1 回复  |  直到 11 年前
        1
  •  1
  •   Community CDub    7 年前

    WebKit只允许DOM中的某些位置用作选择边界或插入符号位置。因此,它会修改使用选择的 addRange() 方法以符合此要求。另请参阅 https://stackoverflow.com/a/14104166/96100 .

    还有一个问题在起作用,那就是WebKit在链接末尾有一个特殊的插入符号位置,它将键入的文本放在链接后面的那个位置,而不是放在链接里面。考虑到浏览器报告选择在链接里面,这无疑有点令人讨厌。然而,其他内联元素不会发生这种情况,正如您在这个修改后的演示版本中看到的那样:

    http://jsbin.com/EYoWuWe/7/edit