JavaScript での DOM による (X)HTML 操作
目次
- #1 はじめに
- #2 要素の取得
- #3 ノード木の探索
- #4 ノードの生成・追加
ノード木を探索する
前回は特定の要素 (element 型オブジェクト) を取得する方法を述べました。 今回は、ノード木の探索をする方法を述べます。 例えば、ある要素の親ノードを取得したり、子ノードを全て取得したりします。
親ノードの取得
Attr ノード、Document ノード、DocumentFragment ノード、Entity ノード、Notation ノードを除き、全てのノードは親ノードを持っています。 例えば、原則として HTML には html 要素と body 要素がありますが、body 要素の親ノードは html 要素です。 また、html 要素はルート要素 (root element) であり、その親ノードは Document ノードです。
DOM では、 Node インターフェイス (あらゆるノードはこれを実装している) の 読み取り専用属性 parentNode に、自分の親ノードが入っています。
// body 要素を取得
var bodyElem = document.getElementsByTagName("body").item(0);
// body 要素の親ノード (つまり html 要素) を取得
var node = bodyElem.parentNode;
親ノードを所有していない場合、parentNode プロパティは null です。 最初に述べたように、Attr ノード、Document ノード、DocumentFragment ノード、Entity ノード、Notation ノードは親ノードを持っていませんし、また、新たに生成し、まだノード木に追加していないノードも親はありません。
子ノードの取得
次に、自分の下にくっついているノード (子ノード) を取得する方法を説明します。 親ノードは必ず 1 つしかありませんが、子ノードは複数個持っている可能性があります。
自分の子ノードの一覧を取得するには Node インターフェイス の 読み取り専用属性 childNodes を使います。 このとき得られるのは NodeList オブジェクトです。 document.getElementsByTagName メソッドで得られるのも NodeList オブジェクトだったことを考えれば、同じように扱うことができます。 ただし、今回の場合は element オブジェクト以外のもの (Text ノードなど) も入っている可能性があることを考慮しなければいけません。 なお、子ノードが無い場合、childNodes プロパティは長さ 0 の NodeList オブジェクトです。
// body 要素を取得
var bodyElem = document.getElementsByTagName("body").item(0);
// body 要素の子ノード一覧を取得
var nodes = bodyElem.childNodes;
// nodes は NodeList 型なので, 配列のように扱うことができる
for( var i = 0; i < nodes.length; i++ ) {
// nodes[i] は element 型とは限らない
var node = nodes[i];
// nodes[i] は nodes.item(i) と完全に一致する
// 以下なんらかの処理...
}
また、全ての子ノードではなく、子ノードのうちの一番最初のもの、および一番最後のものを得る方法もあります。 Node インターフェイス の 読み取り専用属性 firstChild と 読み取り専用属性 lastChild を使用します。
// body 要素を取得
var bodyElem = document.getElementsByTagName("body").item(0);
// body 要素の最初の子ノードを取得
var firstNode = bodyElem.firstChild;
// bodyElem.firstChild は bodyElem.childNodes.item(0) と完全に一致する
// body 要素の最後の子ノードを取得
var lastNode = bodyElem.lastChild;
// bodyElem.lastChild は
// bodyElem.childNodes.item( bodyElem.childNodes.length - 1 ) と完全に一致する
なお、子ノードが 0 個のときは firstChild プロパティも lastChild プロパティも null です。
兄弟要素を取得する
以下のような HTML を考えます。
...
...
...
id が "t1"、"t2"、"t3" の div 要素は、id が "c1" の div 要素の子ノードです。 一方で、id が "t1"、"t2"、"t3" の div 要素同士は、兄弟ノードの関係にあります。 "t2" のノードから見て、"t1" は兄のノード、"t3" は弟のノードです。
自分の兄ノードを取得するには Node インターフェイス の 読み取り専用属性 previousSibling を使い、弟ノードを取得するには 読み取り専用属性 nextSibling を使用します。
// id = "t2" の要素を取得
var elem = document.getElementById("t2");
// 兄ノードを取得
var prev = elem.previousSibling;
// 弟ノードを取得
var next = elem.nextSibling;
ただし、今回の例の場合、"t2" の要素と "t3" の要素の間にスペースや改行があり、それが Text ノードだとみなされる場合があります。 その場合 "t2" の弟ノードは Text ノードということになりますので、注意が必要です。 (兄ノードについても同様。)
Sample
body 要素の子ノードを格納した NodeList オブジェクトを取得し、子ノードが何個あるか window.alert メソッドで表示します。
どのようなコードを書いているのかはソースコードをご覧ください。
備考
- document オブジェクトも element 型オブジェクトも、その他各種 DOM ノードを表すオブジェクトは Node インターフェイス を実装している
参考文献
- W3C 勧告: Node インターフェイス (Document Object Model Core) ... JavaScript に限らない DOM の勧告