選択中文字列の取得 ブラウザによる違い
Selection.toString() と Range.toString()
選択範囲には次の2つの方法がある。
getSelection.toString() getSelection.getRangeAt(0).toString()
この2つで得られる文字はブラウザによる差が結構ある。
大まかな違い
- 基本的には、Selectionは見た目通りの文字を返しやすく、Rangeはソースの文字を返す傾向にある。
- Firefoxでは改行が
\r\n
になる - FirefoxとGoogle Chromeは似ているが、 input, textareaで他と異なる
Selection.toStirng()
Range.toStirng()
- Rangeの中に含まれているノードの文字を返す。
- ソースの文字を反映する。
- ブラウザ間の差が小さい。
見た目の反映とは
例えば次のようなhtmlがあった時 Selection.toStringの結果は、IE以外は改行など実際の表示が反映された文字が返る。
<p>abc</p><p>def</p>
IE以外 | IE |
---|---|
abc \n \ndef |
abcdef |
具体的な違い
不可視要素
scriptやstyleを含む場合
中身(インラインのスクリプト・スタイル)が含まれるか
String | FF | GC | IE |
---|---|---|---|
Selection | no | no | yes |
Range | yes | yes*1 | yes |
*1 bodyの直前にあるのは含まれない。
display: none
String | FF | GC | IE |
---|---|---|---|
Selection | no | no | yes |
Range | yes | yes | yes |
scriptなども不可視要素なので同じ結果になるのは当たり前といえばそう
見た目上の改行を起こす要素
<br>
<p>abc<br>def</p>
<br>
は文字に変換されるか、消える
String | FF | GC | IE |
---|---|---|---|
Selection | \r\n | \n | - |
Range | - | - | - |
ブロックレベル要素
htmlソースの改行、インデントが変換される
<p>abc <p>def
String | FF | GC | IE |
---|---|---|---|
Selection | 見た目の改行が\r\nに | 見た目の改行が\nに | 左下に同じ |
Range | ソースの改行が\nに, インデントが空白に | 左に同じ | 左下に同じ |
そのままの結果
Selection : abc\n\ndef Range : abc\n def
入力要素
先に用語の説明
- active
- フォーカスがある状態、入力文字が直接選択されている状態
- 選択範囲内
- 選択範囲にその要素が含まれている状態
- 次のHTMLでtextareaをまたぐa-bを選択している時の状態
<p>a <textarea>12345</textarea> <p>b
- 次のHTMLでtextareaをまたぐa-bを選択している時の状態
input (type=text)
String | FF | GC | IE |
---|---|---|---|
Selection | - | active | - |
Range | - | - | - |
textarea
String | FF | GC | IE |
---|---|---|---|
Selection | 選択範囲内 | active | 選択範囲内 |
Range | 選択範囲内 | 選択範囲内 | 選択範囲内 |
button
String | FF | GC | IE |
---|---|---|---|
Selection | - | 選択範囲内 | 選択範囲内 |
Range | 選択範囲内 | 選択範囲内 | 選択範囲内 |
その他
u+00A0( )を含む場合
String | FF | GC | IE |
---|---|---|---|
Selection | 0020 | \xA0 | 0020 |
Range | \xA0 | \xA0 | 0020 |
調査に使ったコード
function getTextInfo(text) { return Array.prototype.map.call(text, function(e){ return e + "=" + e.charCodeAt(0) }).join(",") } document.onmouseup = function() { var sel = getSelection() , selText = sel.toString() , rangeText = sel.rangeCount ? sel.getRangeAt(0).toString() : "" ;[selText, rangeText].forEach(function(e){ console.log(getTextInfo(e)) }) }
横に置いておくと便利な文字コード
文字 | 10 | 16 |
---|---|---|
\r | 13 | 0x000D |
\n | 10 | 0x000A |
space | 32 | 0x0020 |
nbsp | 160 | 0x00A0 |
複数のwindow
iframe, frameなどは window.getSelection には含まれない。
そのウィンドウがアクセス可能ならば window.name.getSelection から個別に取得可能