エメラルドマウンテンの麓。

pettanRのテキストレンジAPI

はじめに

W3C Range と IE 独自の先行実装 TextRange をラップしています。リッチテキストエディタ的なものを実装しながら必要なAPIを追加しています。

用語

テキスト編集要素
textarea と type が text, search, url, telephone, password の input 要素。
W3C レンジと Mozilla セレクション
Firefox, Webkit がサポートする。IEは9以降でサポート。
IE独自レンジ
IE4~IE10までサポートした。テキスト編集要素のテキスト(value)に対しても矩形の測定などができて高性能。

BODY、BUTTON、TEXTAREAの各エレメント、およびtextタイプを持ったINPUTエレメントでのみTextRangeオブジェクトが作成できる。

使用技術とブラウザのサポート

ブラウザSelection APIHTMLInputElement.setSelectionRange()IE独自レンジ
IE9+9+4~10
Opera9+8+7 or 8~10.5
Firefox2+1.0
Safari2+2.0.3+ または 1.3.2+

概要

レンジ操作中の要素のDOMツリーへの変更を禁止。誤った古い値が返る。createRangeを取り直す。

メソッドレンジのタイプ
選択範囲indexn行目最後からn行目ドキュメント座標ドキュメント座標の行
xnode.createRangeIE独自レンジが無い場合に制限があり *1IE独自レンジが無い場合テキスト編集要素についてはレンジを作ることができない
range.getOffset
range.getRectIE独自レンジが無い場合、テキスト編集要素についてはメソッドが居ない *1
range.move
range.select〇 *2
range.textテキスト編集要素でない場合、メソッドが居ない
  1. IE独自レンジが無い場合、テキスト編集要素のコンテンツに対して座標系の操作が行えません。このため、行の取得、座標の文字を取得もできません。
  2. iOS11.2 でも選択範囲を js から変更できないcontentEditable を true にすれば良い という書き込みがある。またおいおい。

レンジの作成

選択範囲から作成

現在の選択範囲からレンジを作ります。テキスト編集要素の場合、要素にフォーカスが無いとレンジは作られません。

選択範囲から xnode がはみ出す場合、truncate オプションに true を与えると xnode の範囲に切り詰めたレンジにします。true 以外の場合、レンジは作られません。

var range = xnode.createRange("selection", true);
xnode.createRange("selection" [, truncate=false])
引数名値または型ノート
rangeType"selection"現在の選択範囲からレンジを作ります。
truncatebooleanレンジが xnode からはみ出している場合の処理を決めます。true の場合 xnode の範囲にレンジを切り詰めます。falseではレンジは作成されません。
戻り値レンジ | nullxnodeの範囲にレンジが無い場合、テキストエリアでフォーカスが無い場合 null が返る。

開始位置と終了位置から作成

from が要素の文字数を超えた場合、最後の文字の後ろにカーソルがセットされます。

var range = xnode.createRange("index", 0, 5);
xnode.createRange("index", from [, to])
引数名値または型ノート
rangeType"index"開始位置と終了位置からレンジを作ります。
fromNumber0以上。テキストの文字数を超えた場合、テキストの終端にカーソルを置く。
toNumber省略した場合、from と同じ値。
戻り値レンジ

pageXとpageYから作成

var range = xnode.createRange("point", e.pageX, e.pageY);
xnode.createRange("point", pageX, pageY)
引数名値または型ノート
rangeType"point"開始位置と終了位置からレンジを作ります。
pageXNumber
pageYNumber
戻り値レンジ | null座標の位置に文字が無い場合、null が返ります。

開始行と終了行からラインレンジを作成

var range = xnode.createRange("line-index", 0);
xnode.createRange("line-index", lineFrom [, lineTo])
引数名値または型ノート
rangeType"line-index"開始行と終了行からラインレンジを作ります。
lineFromNumber0以上。開始行。
lineToNumber省略した場合、lineFrom と同じ値。
戻り値レンジ | nulllineFrom が xnode の行数を超える場合、null が返ります。

最終行からのindexから行レンジを作成

var range = xnode.createRange("line-last", 0);
xnode.createRange("line-last", lastLineFrom [, lastLineTo])
引数名値または型ノート
rangeType"line-last"最終行からのindexから行レンジを作ります。
lastLineFromNumber0以上。
lastLineToNumber省略した場合、lastLineFrom と同じ値。
戻り値レンジ | nulllastLineFrom が xnode の行数を超える場合、null が返ります。

pageXとpageYから行レンジを作成

var range = xnode.createRange("line-point", e.pageX, e.pageY);
xnode.createRange("line-point", pageX, pageY)
引数名値または型ノート
rangeType"line-point"
pageXNumber
pageYNumber
戻り値レンジ | null座標の位置に文字が無い場合、null が返ります。

レンジのメソッド

レンジの開始位置、終了位置の取得

xnode のコンテンツの中で、レンジの開始 index と終了 index を返します。

range.getOffset()
引数名値または型ノート
無し
戻り値{ from : Number, to : Number }

レンジのドキュメント上の座標と幅と高さを取得

テキスト編集要素であり、ブラウザが IE TextRange をサポートしない場合、getRect は range に居ません。

range.getRect()
引数名値または型ノート
無し
戻り値{ x : Number, y : Number, width : Number, height : Number }文書上の座標です。

レンジの移動

レンジを移動します。負の値を指定した場合、現在の各位置に加算します。

range.move( from [, to] )
引数名値または型ノート
fromNumber負の値を指定した場合、現在の開始位置に加算した位置に移動します。開始位置は0以下にはなりません。
toNumber負の値を指定した場合、現在の修了位置に加算した位置に移動します。修了位置はxnodeからはみ出すことはありません。
戻り値レンジチェインメソッド用に自信を返します。

レンジを選択する

レンジを選択します。以前の選択範囲は解除される点に注意します。rangeType = "selection" で作ったレンジはこのメソッドが提供されません。

range.select()
引数名値または型ノート
無し
戻り値レンジチェインメソッド用に自信を返します。

レンジのテキストを取得、またはテキスト挿入ないし置換

レンジのテキストを取得または選択範囲へテキストを挿入または置換します。テキスト編集要素の場合だけこのメソッドが提供されます。

挿入した場合、レンジの開始位置・終了位置は挿入したテキストの最後に移動します。

置換した場合、レンジの終了位置は置換したテキストの最後に移動します。

range.text([text])
引数名値または型ノート
textString選択範囲がこのテキストで置換されます。
戻り値String | レンジ

参考情報

Linux版FireFoxだと、designMode = "On"の時に図1のようにセルを選択できる。このような場合、選択した各々のセルが1つのRegionとなり、Selectionに3つのRangeが含まれることになる。

DOM 標準には document.caretRangeFromPoint というメソッドがあり、座標から collapsed range を得ることができる。ただし WebKit しか実装してないらしい。

http://www.w3.org/TR/cssom-view/#dom-documentview-caretrangefrompoint

Firefox はマウスイベントの rangeParent と rangeOffset というガラパゴスプロパティがある。