range.setStartBefore()在Chrome和FireFox中的行为非常奇怪.这就是它应该的工作方式吗?

range.setStartBefore() behaving very strangely in Chrome vs. FireFox. Is this how it's supposed to work?

本文关键字:方式吗 工作 setStartBefore Chrome range FireFox 非常      更新时间:2023-09-26

我在这里写了一篇文章。

基本上,我想做的是在可满足内容的区域中选择DIV前面的元素。我遇到了我不理解的行为,我发现自己在想这是不是"它应该工作"的方式。

考虑以下标记:

<DIV contenteditable="true">foo<div id="test">bar</div></div>

我想选择<div id="test">之前的元素。

所以我用:

var sel = document.getSelection();
var range = document.createRange();
var dom_node = document.getElementById( 'test' );
// this is the critical method
range.setStartBefore( dom_node );
range.collapse( true );
sel.removeAllRanges();
sel.addRange( range );
console.log( "selection is :", document.getSelection().getRangeAt(0) );

(不幸的是,尝试这个作为jsfiddle.net产生一些jsfiddle错误,所以我把它放在一个静态页面在这里)

我得到的范围在FireFox和Chrome之间非常不同。

Chrome返回一个startContainer的textnode与startOffset的3,这很好地指向刚刚过去的文本'foo'。这是我所期望的。光标被移动到该位置

FireFox返回可编辑DIV的startContainer,其偏移量为1,指向整个textnode。不是我想的那样。光标(如果你聚焦div)刚好指向'bar'的左边。

如果把HTML改成:

就更奇怪了
<DIV contenteditable="true"><div>foo</div><div id="test">bar</div></div>

重复这个实验,FireFox返回一个startContainer,其中包含可编辑的DIV和startOffset为1。游标保持在'bar'前面。根据上次测试的结果,这对我来说是有意义的。

Chrome,然而,返回一个startContainer与长度为0的textnode和nextSibling previousSibling都是null,但parentNode设置为div id= " test "。光标保持在'bar'前面。

这是正确的行为吗?当你得到这样的范围时,你应该怎么做?或者setStartBefore()/After()只是坏了?

这个问题是关于WebKit如何规范化一个范围时,它被选中,而不是范围本身。Range的基本方法,如setStartBefore(),在WebKit和Mozilla(以及IE>= 9和Opera)之间是一致的。

范围并不仅仅存在于服务选择中,范围边界可以存在于任何类型的节点中,而不仅仅是文本节点。对于非基于文本的节点(文本节点、注释、cdata),范围边界表示为父节点中边界之前的子节点的数量。在所有浏览器中都是如此。只有当范围被添加到选择时,情况才会不一致。

在Chrome中,第二个示例将插入符号放置在"bar"文本节点的开始处。见http://jsfiddle.net/cRwee/