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 は一通りで使えます。
