[javascript DOM] Q. ノードウォーキングとは?

A.
DOMでは、getElementByIdなどで直接ノードを取得する以外にも
相対的にノードを取得する事が可能です。このように相対的に
ノードを取得する方法をノードウォーキング言います。

ノードウォーキングでよく使われるNodeオブジェクトのメンバーを確認してみます。

ノードウォーキングで使われるメンバー
プロパティ名 説明
firstChild 最初の子ノードを取得
lastChild 最後の子ノードを取得
perviousSibling 直前のノードを取得
nextSibling 直後のノードを取得
childNodes.length 子ノードに含まれるノード数を取得
parentNode 親ノードを取得


これらのNodeオブジェクトのメンバーを図に表すと次のようになります。
js_dom_node_w1.png

ここで実際のHTMLをみて確認してみます。
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>DOM childNodes</title>
  <script type="text/javascript">
  window.onload = function() {
    // 基準となるノードを取得する
    var ulnode = document.getElementById('item');
    console.dir(ulnode.childNodes);

    // 子ノードの1番最初を取得
    var first_child = ulnode.firstChild;
    console.dir(first_child);

    // 子ノードの2番目ノードを取得
    var next = first_child.nextSibling;
    console.dir(next);

    // 子ノードの一番最後のノードを取得
    var last_child = ulnode.lastChild;
    console.dir(last_child);

    // 子のノードの最後から2番目を取得
    var	before = last_child.previousSibling;
    console.dir(before);
  };
  </script>
  <style type="text/css">
  ul, li, div {
    border: 1px solid #f00;
    padding: 5px;
  }
  </style>
</head>
<body>
<h1>一覧</h1>
<div id="list">
  <ul id="item">
    <li>アイテム1</li>
    <li>アイテム2</li>
    <li>アイテム3</li>
  </ul>
</div>
</body>
</html>
実行結果は次のようになります。
js_dom_node_w3.png

実行結果を確認すると子ノードの1番最初を取得するとTextになっています。
ここでHTMLを修正してもう一度確認してみます。
ulのインデントを無くして一行で記述します。
<body>
<h1>一覧</h1>
<div id="list"><ul id="item"><li>アイテム1</li><li>アイテム2</li><li>アイテム3</li></ul></div>
</body>
</html>
実行結果は次のようになります。
js_dom_node_w4.png
HTMLをインデントした場合タグとタグの間の改行や空白も
Nodeリストに入るのでノードウォーキングの際は注意が必要です。

この影響を考慮するのはnodeTypeの確認を行いnodeType=1の要素ノードの時のみ処理を行ったり
nodeType=3テキストノードを取り除いたりします。

このような影響があるのでノードウォーキングは扱いにくかったのですが、
Element Traversalと言うAPIが定義されました。

Element Traversalを確認してみましょう
ElementTraversal API
プロパティ名 説明
firstElementChild 最初の子要素ノードを取得
lastElementChild 最後の子要素ノードを取得
perviousElementSibling 直前の要素ノードを取得
nextElementSibling 直後の要素ノードを取得
childElementCount 子ノードに含まれる要素ノード数を取得
parentNode 親ノードを取得

図に表すと以下のようになります。
js_dom_node_w5.png
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>DOM childNodes</title>
  <script type="text/javascript">
  window.onload = function() {
    // 基準となるノードを取得する
    var ulnode = document.getElementById('item');

    // childNode
    console.dir(ulnode.childNodes);

    // children
    console.dir(ulnode.children);

    // 子ノードの1番最初を取得
    var first_child = ulnode.firstElementChild;
    console.dir(first_child);

    // 子ノードの2番目ノードを取得
    var next = first_child.nextElementSibling;
    console.dir(next);

    // 子ノードの一番最後のノードを取得
    var last_child = ulnode.lastElementChild;
    console.dir(last_child);

    // 子のノードの最後から2番目を取得
    var before = last_child.previousElementSibling;
    console.dir(before);
  };
  </script>
  <style type="text/css">
  ul, li, div {
    border: 1px solid #f00;
    padding: 5px;
  }
  </style>
</head>
<body>
<h1>一覧</h1>
<div id="list">
  <ul id="item">
    <li>アイテム1</li>
    <li>アイテム2</li>
    <li>アイテム3</li>
    </ul>
  </div>
</body>
</html>
js_dom_node_w6.png
要素ノードのみを取得する事が可能な事が確認できました。

対応ブラウザは、以下のサイトから確認できます。
W3C DOM Compatibility - Traversal

参考サイト:
XML DOM Node Types
MDN Element.children
三等兵 Element Traversal API