2011-05-17
DOM の textContent と innerText について
javascript | |
一つ前のエントリで JavaScript のトピックスについて紹介しました.
避けなければいけない JavaScript の失敗 - フリーフォーム フリークアウト
この中でエレメントノードのテキスト部分を取り出す innerText プロパティについて説明していましたが, これは非標準で Firefox ではサポートされていません. 標準になっているものとして textContent というプロパティがあります.
一応エントリ下部のコメント欄紹介ページでこのことについて触れているんですが, もっときちんと取り上げないとフェアじゃない気がしたので, 改めてこの2つのプロパティについて取り急ぎエントリにしました.
仕様とブラウザサポート
textContent も innerText もある要素の text 部分にアクセスするためのプロパティです. 例えばこのような html に
<div id="myDiv"> This text is in Div. <p>A para in div element.</p> </div>
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
- ICanHaz.js | client-side templating with Mustache.js and jQuery or Zepto.js
- 114 http://www.google.co.jp/url?sa=t&rct=j&q=innertext&source=web&cd=6&sqi=2&ved=0CE8QFjAF&url=http://d.hatena.ne.jp/cou929_la/20110517/1305644081&ei=ACCETtryCKaImQXu9fEr&usg=AFQjCNE_DR4jl12bHUyjf20zFTFAO_ESlw
- 108 http://www.google.co.jp/url?sa=t&rct=j&q=textCOntent&source=web&cd=2&ved=0CCwQFjAB&url=http://d.hatena.ne.jp/cou929_la/20110517/1305644081&ei=n2BeTtOVGYOHmQW15aEu&usg=AFQjCNE_DR4jl12bHUyjf20zFTFAO_ESlw&sig2=gllU0ZV9dKrkpl-sqGrcpg
- 95 http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&ved=0CDAQFjAB&url=http://d.hatena.ne.jp/cou929_la/20110517/1305644081&ei=Q2IuT6jMNMXSmAXSl8DHDw&usg=AFQjCNE_DR4jl12bHUyjf20zFTFAO_ESlw&sig2=E355__YCRBMnd5Sr6oRUfQ
- 74 http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CCYQFjAA&url=http://d.hatena.ne.jp/cou929_la/20110517/1305644081&ei=BuonT7LDGOjxmAXipYHcAw&usg=AFQjCNE_DR4jl12bHUyjf20zFTFAO_ESlw&sig2=suAZaac4XMCHDEEBgzpwxQ
- 47 http://www.google.co.jp/url?sa=t&rct=j&q=javascript textcontent&source=web&cd=2&ved=0CCUQFjAB&url=http://d.hatena.ne.jp/cou929_la/20110517/1305644081&ei=hoOfTpzOFM_QrQf_0oyHAw&usg=AFQjCNE_DR4jl12bHUyjf20zFTFAO_ESlw
- 33 http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=4&ved=0CEsQFjAD&url=http://d.hatena.ne.jp/cou929_la/20110517/1305644081&ei=-othT_6eH5DHmQXvhuizCA&usg=AFQjCNE_DR4jl12bHUyjf20zFTFAO_ESlw&sig2=crw5GLZW35W8WZ2S5jtGrA
- 30 http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=3&ved=0CDwQFjAC&url=http://d.hatena.ne.jp/cou929_la/20110517/1305644081&ei=P45hT777FoaemQWZlJmDCA&usg=AFQjCNE_DR4jl12bHUyjf20zFTFAO_ESlw
- 27 http://postoro.blogspot.com/2011/06/firefox-innertext-ie-textcontent.html
- 22 http://www.google.co.jp/url?sa=t&rct=j&q=innertext textcontent&source=web&cd=3&ved=0CC8QFjAC&url=http://d.hatena.ne.jp/cou929_la/20110517/1305644081&ei=WOWzTv_rDqmhmQWC94XYAw&usg=AFQjCNE_DR4jl12bHUyjf20zFTFAO_ESlw&sig2=mdDET1diL_yczx2F3yZJlQ
- 20 http://www.google.co.jp/search?q=innertext&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:ja:official&hl=ja&client=firefox-a