DOM の textContent と innerText について
一つ前のエントリで JavaScript のトピックスについて紹介しました.
避けなければいけない JavaScript の失敗 - Please Sleep
この中でエレメントノードのテキスト部分を取り出す innerText プロパティについて説明していましたが, これは非標準で Firefox ではサポートされていません. 標準になっているものとして textContent というプロパティがあります.
一応エントリ下部のコメント欄紹介ページでこのことについて触れているんですが, もっときちんと取り上げないとフェアじゃない気がしたので, 改めてこの2つのプロパティについて取り急ぎエントリにしました.
仕様とブラウザサポート
textContent も innerText もある要素の text 部分にアクセスするためのプロパティです. 例えばこのような html に
<div id="myDiv">
This text is in Div.
<p>A para in div element.</p>
</div>
こういうふうに js からアクセスすると
document.getElementById('myDiv').innerText;
// または
document.getElementById('myDiv').textContent;
このような文字列が返されます.
This text is in DIV. A para in div element.
Chrome で実行してみた例:
textContent は W3C で標準化されたプロパティです. IE 以外のブラウザがサポートしています.
innerText は IE4 から実装されている IE の独自機能です. Firefox 以外のすべてのブラウザがサポートしています. IE 独自のものなので明文化された仕様はありません.
サイ本6版では次のような, ちょっとクロスブラウザな textContent 関数が紹介されていました. ノードの text が空文字列だった場合, “” は JavaScript では falsy なので, “===” で比較しているのがポイントですね.
/**
* With one argument, return the textContent or innerText of the element.
* With two arguments, set the textContent or innerText of element to value.
*/
function textContent(element, value) {
var content = element.textContent; // Check if textContent is defined
if (value === undefined) { // No value passed, so return current text
if (content !== undefined) return content;
else return element.innerText;
}
else { // A value was passed, so set text
if (content !== undefined) element.textContent = value;
else element.innerText = value;
}
}
両者の違い
両者はだいたい同じような挙動をしますが, いくつかの点では異なっています.
- textContent は script タグの中を返しますが, innerText は返しません
- textContent は空白類の文字 (スペース・タブ・改行など) を html に書いてあるまま返します. innerText はある程度見やすいように変換します
innerText の挙動の違い
上で述べたように, textContent と innerText の挙動が異なるため, 得られる text も違うものになります. 問題は innerText の挙動もブラウザによって微妙に異なる点です. こちらのブログでは WebKit と IE の innerText で得られるテキストの違いについて触れられています.
Plain Text vs innerText vs textContent by Mike Wilcox » Club✩AJAX
またこちらの stackoverflow の回答では, safari 2.x 系での innerText の実装が buggy であると言われています.
javascript - ‘innerText’ works in IE, but not in Firefox - Stack Overflow
問題への対策
先ほどのブログではブラウザ間の挙動を吸収するような “getPlainText()” という関数が紹介されていました.
http://clubajax.org/files/lang/plain-text.js
ただ, 個人的には上の StackOverflow での kangax さんの意見に共感しました.
- innerText や textContent の挙動の差異を吸収するのは大変
- なので, まず要件をもう一度みなおして本当に textContent / innerText が必要か考える. 大抵の場合は innerHTML からタグを取り除くだけで十分.
- 無理ならば DOM Tree を走査して Text ノードを見ていく
余談: インラインの script タグ
ちょっと話はそれますが, script タグのちょっと面白い利用法について.
サイ本6版のコラムにもあったのですが, script タグに src 属性を指定せずタグ中に文字列を書くと, ブラウザ上には表示されない文字列になります. 中の文字列は text というプロパティで取得できます. また script 要素の type 属性に “text/javascript” 以外の値を指定すれば JavaScript の処理系もこれを無視してくれます. これを利用すると JavaScript から自由に扱える文字列を script タグの中に書いておくことができます.
現実の利用例としては, John Resig さんがブログで紹介していた小さな関数 や ICanHaz といった js 製のテンプレートエンジンは script タグ (type は text/html) の中にテンプレートを記述するというアプローチをとっています.
参考
- Document Object Model Core
- W3C の仕様
- Plain Text vs innerText vs textContent by Mike Wilcox » Club✩AJAX
- 両プロパティの違いについて実例が載っていてわかりやすい
- javascript - ‘innerText’ works in IE, but not in Firefox - Stack Overflow
- kangax さんの answer が good
- John Resig - JavaScript Micro-Templating
- John Resig さんのテンプレート関数. script タグ内にテンプレート文字列を記述
- icanhazjs.com - Blog
- 上と似たアプローチの js 製テンプレートエンジン
オライリージャパン
売り上げランキング: 17,881