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 は、startOffset が 3 の textnode の startContainer を返します。これは、テキスト「foo」のすぐ後ろを適切に指しています。これは私が期待するものです。その位置にカーソルが移動します。

FireFox は、編集可能な DIV の startContainer をオフセット 1 で返し、textnode 全体を指します。私が期待するものではありません。カーソル (div にフォーカスがある場合) は、'bar' のすぐ左を指します。

HTML が次のように変更されると、より奇妙になります。

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

実験を繰り返すと、FireFox は編集可能な DIV と 1 の startOffset を持つ startContainer を返します。カーソルは「bar」の前に残ります。前回のテストの結果を考えると、これは理にかなっています。

ただし、Chrome は、長さが 0 の textnode と nextSibling previousSibling を含む startContainer を返します。どちらも null ですが、parentNode は div id="test" に設定されています。カーソルは「バー」の前に残ります。

これは正しい動作ですか?このような範囲を取得したとき、あなたは何をすることになっていますか?それとも setStartBefore()/After() が壊れていますか?

4

1 に答える 1

2

問題は、範囲自体ではなく、選択されたときに WebKit が範囲を正規化する方法に関するものです。Rangeなどの基本的なメソッドはsetStartBefore()、WebKit と Mozilla (実際には IE >= 9 と Opera) の間で一貫して機能します。

範囲は選択を提供するためだけに存在するわけではなく、範囲境界はテキスト ノードだけでなく、任意のタイプのノードに存在できます。非テキストベースのノード (テキスト ノード、コメント、cdata) の場合、範囲境界は、親ノード内の境界に先行する子ノードの数として表されます。これはすべてのブラウザに当てはまります。範囲が選択に追加された場合にのみ、一貫性がなくなります。

Chrome では、2 番目の例ではキャレットを「バー」テキスト ノードの先頭に配置します。http://jsfiddle.net/cRwee/を参照してください

于 2013-01-18T10:18:31.497 に答える