はじめに
文字列を選択するときに、後ろから選択しても前から選択したのと同じように扱いたい!という要求があったため、実装してみました。
やりたいこと
<p>
<span>ふるいけや</span>
<span>かわずとびこむ</span>
<span>みずのおと</span>
</p>
例えば、以上のような DOM 構造の文字列を以下のように選択すると、選択範囲の始点のノード(anchorNode)と終点のノード(focusNode)はそれぞれ次のようになります。
| 選択した範囲 | 始点ノード(anchorNode) |
終点ノード(focusNode) |
|
|---|---|---|---|
| 前からの選択 | 「い」から「み」まで | <span>ふるいけや</span> | <span>みずのおと</span> |
| 後ろからの選択 | 「み」から「い」まで | <span>みずのおと</span> | <span>ふるいけや</span> |
このとき、「後ろからの選択」でも「前からの選択」と同じようにしたい、すなわち、「後ろからの選択」の始点ノードと終点ノードを入れ替えたいというのが今回のやりたいことになります。
書いたコード
以上のやりたいことに対して、以下のコードを書きました。
const selection = window.getSelection()
const range = selection.getRangeAt(0).cloneRange()
selection.removeAllRanges()
selection.addRange(range)
getRangeAt(0)で取得したRangeオブジェクトですでに始点・終点のノードが逆転しているので、これを利用しています。
-
selection.getRangeAt(0).startContainer... <span>ふるいけや</span> -
selection.getRangeAt(0).endContainer... <span>みずのおと</span>
(Rangeでは前から選択したか後ろから選択したかどうかは気にせず、親要素における位置関係からstartContainerとendContainerを設定しているのでしょうか)