【问题标题】:Setting selection to edge of node makes WebKit report inconsistent range将选择设置为节点边缘使 WebKit 报告范围不一致
【发布时间】:2013-09-03 13:25:13
【问题描述】:

假设以下 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);

现在查询当前选择范围的窗口并检查其commonAncestorContainer:

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

你会发现在 Firefox 中结果和预期的一样; id 为edit 的相同元素。

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

Click here for a live demo.

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

感谢您的 $.02。

【问题讨论】:

  • 哦,所以您是说该属性正在为您将要编辑的元素返回不正确的元素?
  • 我是说 WebKit 返回的范围与我们刚刚分配给它的范围、Firefox 的行为以及浏览器对用户的行为方式不一致。
  • 我明白你现在在说什么,我一直在这里查看 Range 文档:dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#concept-range,我想你可能发现了一个可能需要报告的错误。
  • @ars265:这不是错误。
  • @TimDown,不是吗?如果 Range 对象最初包含节点,为什么它不保留继承的端点,或者文档中的以下内容对此进行了描述:The content that one would think of as being within the range consists of all contained nodes, plus possibly some of the contents of the start node and end node if those are Text or Comment nodes. 并且由于 begin 和 endpoint 不是文本节点,因此它们被删除了?

标签: javascript dom webkit range selection


【解决方案1】:

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

还有另一个问题,那就是 WebKit 在链接末尾有一个插入符号位置的特殊情况,它将键入的文本放置在链接之后而不是链接内部的那个位置。鉴于浏览器将选择报告为在链接内,这无疑是一个令人讨厌的黑客攻击。但是,其他内联元素不会发生这种情况,您可以在修改后的演示版本中看到这一点:

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

【讨论】:

    猜你喜欢
    • 2012-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-23
    • 1970-01-01
    • 2020-05-18
    相关资源
    最近更新 更多