DOMレンジによる複雑な選択
複雑なレンジを作成するには、レンジのsetStart()メソッドとsetEnd()メソッドを使用する必要があります。どちらのメソッドも、参照ノードとオフセットという2つの引数を取ります。setStart()では、参照ノードはstartContainerに割り当てられ、オフセットはstartOffsetに割り当てられます。setEnd()の場合、参照ノードはendContainerに割り当てられ、オフセットはendOffsetに割り当てられます。
これらのメソッドを使用して、selectNode()およびselectNodeContents()と同等の機能を実現することができます。たとえば、前の例に出てきたuseRanges()関数を、setStart()とsetEnd()を使って次のように書き換えることができます。
function useRanges() { var oRange1 = document.createRange(); var oRange2 = document.createRange(); var oP1 = document.getElementById("p1"); var iP1Index = -1; for (var i=0; i < oP1.parentNode.childNodes.length; i++) { if (oP1.parentNode.childNodes[i] == oP1) { iP1Index = i; break; } } oRange1.setStart(oP1.parentNode, iP1Index); oRange1.setEnd(oP1.parentNode, iP1Index + 1); oRange2.setStart(oP1, 0); oRange2.setEnd(oP1, oP1.childNodes.length); //textbox assignments here }
ノードを選択する(oRange1)には、まず目的のノード(oP1)について、その親ノードのchildNodesコレクションにおけるインデックスを特定する必要があります。ノードの内容を選択する(oRange2)には、特に計算は必要ありません。もっとも、既にご存知のとおり、ノードやノードの内容を選択するにはもっと簡単な方法が他にあります。この方法のポイントは、ノードの一部だけを選択できるということです。
たとえば、<p id="p1"><b>Hello</b> World</p>というHTMLコードから、「Hello」の「llo」だけと「World」の「Wo」だけを選択したい場合を考えてみましょう。この方法を使えば、これを簡単に実現できます。
まず、通常のDOMメソッドを使用して、「Hello」と「World」を含む2つのテキストノードの参照を取得します。
var oP1 = document.getElementById("p1"); var oHello = oP1.firstChild.firstChild; var oWorld = oP1.lastChild;
テキストノード「Hello」は、実際には<p/>の孫にあたるので(直接の親は<b/>)、oP1.firstChildによって<b/>を取得し、oP1.firstChild.firstChildによって目的のテキストノードを取得します。テキストノード「World」は<p/>の2番目の(かつ最後の)子なので、oP1.lastChildによって取得できます。
次に、レンジを作成して適切なオフセットを設定します。
var oP1 = document.getElementById("p1"); var oHello = oP1.firstChild.firstChild; var oWorld = oP1.lastChild; var oRange = document.createRange(); oRange.setStart(oHello, 2); oRange.setEnd(oWorld, 3);
setStart()ではオフセットを2に設定します。これは、「Hello」中の1つ目の「l」は位置2にあたるからです(先頭の文字「H」は位置0です)。setEnd()ではオフセットを3に設定します。このオフセットには、選択しない最初の文字の位置を指定するので、「r」が登場する位置3を指定しています(図3に示すように、実は位置0のところにスペースが入っています)。

oHelloとoWorldはどちらもテキストノードなので、これらのノードはこのレンジのstartContainerとendContainerに割り当てられます。これにより、startOffsetとendOffsetは、要素が渡されたときのように子ノードを探すのではなく、各ノードに含まれているテキストを探すようになります。commonAncestorContainerは、両方のノードを含んでいる最初の祖先である<p/>要素になります。
当然ながら、ドキュメントのセクションを選択しただけでは何の役にも立たないので、この選択範囲に対して何らかの操作を行うことになります。以降では、この点について説明します。
