1

我在这里写了一篇文章

基本上,我想要做的是在内容可编辑区域中选择 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 会返回一个 textnode 的 startContainer,其 startOffset 为 3,正好指向文本“foo”。这是我所期望的。光标移动到该位置。

FireFox 返回一个偏移量为 1 的可编辑 DIV 的 startContainer,指向整个文本节点。不是我所期望的。光标(如果您聚焦 div),正好指向 'bar' 的左侧。

如果将 HTML 更改为:

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

重复实验,FireFox 返回一个带有可编辑 DIV 和 startOffset 为 1 的 startContainer。光标停留在“bar”之前。鉴于上次测试的结果,这对我来说很有意义。

然而,Chrome 会返回一个 startContainer,其 textnode 的长度为 0,nextSibling previousSibling 都为 null,但 parentNode 设置为 div id=”test”。光标停留在'bar'前面。

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

4

1 回答 1

2

问题在于 WebKit 在选择范围时如何规范化范围,而不是范围本身。Range诸如此类的基本方法setStartBefore()在 WebKit 和 Mozilla(实际上是 IE >= 9 和 Opera)之间始终如一地工作。

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

在 Chrome 中,您的第二个示例将插入符号放在“bar”文本节点的开头。见http://jsfiddle.net/cRwee/

于 2013-01-18T10:18:31.497 回答