我在这里写了一篇文章。
基本上,我想要做的是在内容可编辑区域中选择 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() 刚刚坏了?