DOMおれおれAdvent Calendar 2015 – 09日目
テキストノートはあくまでノードなので、文字列ではありません。 toString()
も特に用意されてないみたいです。
文字列を取得するにはテキストノードの nodeValue
を見ます。
var elTitle = document.querySelector('title'); var nText = elTitle.firstChild; var text = nText.nodeValue; console.log(text); // => "Ginpen.com"
任意の要素内の文字列を全部取得するなら
要素ノードの textContent
を使います。ノードを再帰的に検索して、全ての文字列をかき集めてくれます。(正確には要素ノード以外でも使えるけど、まあ要素ノードで使うよね。)
取得だけじゃなくて設定もできるので、ユーザー入力値を画面に表示する場合は innerHTML
じゃなくてこっち使った方が良いですね。
問題点
問題は文字列なら何でも持ってきてくれちゃうところです。 <script>
だろうが <style>
だろうがお構いなし。 display:none
を指定してある要素以下の文字列も持ってきます。jQueryも textContent
を使ってるので同じ。
自力で見えない要素を無視して文字列取得
こんな感じではいかがでしょうか。
/** * 要素内の文字列を返す。 * @param {Element} el * @returns {String} */ function getText(el) { var text = ''; // 子ノードを再帰的に全検索 var children = el.childNodes; for (var i=0; i<children.length; i++) { var child = children[i]; var childText; // テキストノードなら、文字列を取得 if (child.nodeType === child.TEXT_NODE) { childText = String.trim(child.nodeValue); // インデント等を除去 } // 非表示でない要素ノードなら、子孫の文字列を取得 else if (child.nodeType === child.ELEMENT_NODE) { var display = getComputedStyle(child).display; if (display !== 'none') { childText = getText(child); // インラインでなければ改行を追加 if (childText && display !== 'inline' && display !== 'inline-block') { childText += '\n'; } } } text += childText; } return text; }
からの、こう。
var text = getText(document.querySelector('title'));
<iframe>
を無視するとかが必要かも。まあいいか。
getComputedStyle()
は要素に実際当たっているスタイルを得る仕組みです。最終的に有効なスタイルの位置が要素の style
属性でもCSSのセレクターでも大丈夫。ただこの関数、パフォーマンス的に問題になりやすいので、多用するとよくないかもです。 textContent
が非表示要素以下を無視しないのもたぶんこのせい。
環境
textContent
、 getComputedStyle
共にIEは9+、Androidは問題なさそう。
nodeValue
は一通りで使えます。