DOMスクリプティングで動的なアクションを与えるためには,まずHTML上に存在する要素をJavaScriptから特定できなければいけません。ここではDOMで規定されている各種手法を解説していきます。

 DOMを使ってHTMLの特定の要素を参照するために,次の三つのメソッドのいずれかを使います。

document.getElementById('id属性値');

document.getElementsByTagName('要素【タグ】名');

document.getElementsByName('name属性値');

 実はHTML全体から特定の要素を参照するために利用できるメソッドは,これら三つしかありません。たったこれだけを覚えておくだけで,自由自在に特定の要素にたどり着くことができます。

 次のHTMLを例に,それぞれのメソッドの使い方を見ていきましょう。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Language" content="ja">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>W3C Document Object Model</title>
</head>

<body>

<a name="level1"></a>
<h2>Document Object Model Level 1</h2>
<a href="http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html"
 id="dom1_core">Core</a>
<a href="http://www.w3.org/TR/REC-DOM-Level-1/level-one-html.html"
 id="dom1_html">HTML</a>

<a name="level2"></a>
<h2>Document Object Model Level 2</h2>
<a href="http://www.w3.org/TR/DOM-Level-2-Core/"
 id="dom2_core">Core</a> |
<a href="http://www.w3.org/TR/DOM-Level-2-HTML/"
 id="dom2_html">HTML</a> |
<a href="http://www.w3.org/TR/DOM-Level-2-Events/"
 id="dom2_events">Events</a>

</body>

</html>

getElementByIdメソッド

 getElementByIdメソッドは引数にid属性値を指定することで,一発で特定の要素を抜き出します。要素を特定するメソッドの中では最も扱いやすいといえます。

 では,サンプルHTMLから,id属性値に"dom2_html"がセットされた要素を参照してみましょう。次のコードを,</body>の直前に記述します。

<script type="text/javascript">
   var elm = document.getElementById('dom2_html');
   alert(elm.href);
</script>

 このコードは,参照された要素のhref属性の値をアラートウィンドウに表示します。このように,id属性値がセットされた要素であれば,その値を引数に指定するだけで,簡単に目的の要素を参照することができるようになります。実践では最も利用度が高いメソッドといえます。

getElementsByTagNameメソッド

 id属性値がセットされていない要素を参照したい場合は,getElementByIdメソッドを使うことができません。その代りに要素名を指定することで,指定された要素名の要素をすべて取り出すgetElementsByTagNameメソッドを使います。

 このメソッドは,引数に要素名を与えることで,該当する要素をリストとして返します。では,先ほどと同じく,id属性値に"dom2_html"がセットされた要素を参照してみましょう。

<script type="text/javascript">
    var list = document.getElementsByTagName('A');
    var elm = list.item(5);
    alert(elm.href);
  </script>

 getElementsByTagNameメソッドから得られたA要素のリストを,listという変数に格納します。そしてlistに対してitemメソッドを使い,インデックス番号に5を指定して,目的の要素を参照します。

 getElementsByTagNameメソッドで指定する要素名を持った要素は,HTML上に一つだけとは限りません。このサンプルでもA要素が七つも存在しています。そのため,getElementsByTagNameメソッドは,getElementByIdメソッドとは違い,リストが返ってきます

 しかし,得られたリストは,JavaScriptの配列とは異なります。この得られたリストは,NodeListと呼ばれます。NodeListには次のメソッドとプロパティが規定されています(表1)。

itemメソッド 引数にインデックス番号を指定することで,該当の要素を返します。インデックス番号は0から数えます。
lengthプロパティ NodeListに格納されている要素の数を返します。
表1●NodeListのメソッドとプロパティ

getElementsByNameメソッド

 フォームに使うINPUT要素や,アンカーとして使うA要素にはname属性がセットされます。DOMでは,name属性値から要素を参照するために,getElementsByNameメソッドを規定しています。

 特定のname属性値がセットされた要素は,必ずしも一つとは限りません。そのため,getElementsByNameメソッドは,getElementsByTagNameメソッドと同様に,該当の要素のリストをNodeListとして返します。

 ではサンプルHTMLから,name属性値に"level2"がセットされた要素を参照してみましょう。

<script type="text/javascript">
    var list = document.getElementsByName('level2');
    var elm = list.item(0);
    alert(elm.name);
</script>

 このコードは,name属性値に"level2"がセットされたA要素を参照しています。実際に該当する要素は,HTML上に一つしかありませんので,取り出されたNodeListであるlistに対してitemメソッドにインデックス番号0を指定して,該当の要素を参照しています。

メソッドを組み合わせて使う

 これまでは,documentオブジェクトに対してメソッドを適用してきました。documentオブジェクトはHTML文書全体を表しますので,これらのメソッドを使うたびに,HTML文書全体からサーチすることになります。

 実践では,HTMLがかなり複雑になってきます。例えば,getElementsByTagNameメソッドを使ってリストを得られたとしても,目的の要素が何番目なのかを特定するのは容易ではありませんし,効率が悪いといえます。そのため,実践では,これらのメソッドを組み合わせて使います。

 次のHTMLを例に使い方を見ていきましょう。

<ul id="levels">
<li title="level1">Level 1</li>
<li title="level2">Level 2</li>
<li title="level3">Level 3</li>
</ul>

 このUL要素は,膨大なHTMLの一部と考えてください。もしかしたら,UL要素やLI要素が,他にもたくさんあるかもしれません。このような状況化の中,title属性値に"level2"がセットされたLI要素を参照したい場合には,次のようなコードを使います。

  var ul = document.getElementById('levels');
  var elm = ul.getElementsByTagName('LI').item(1);
  alert(elm.title);

 もしdocumentオブジェクトに対してgetElementsByTagNameメソッドを使った場合には,目的のLI要素が何番目かわかりません。そのため,ここでは,まずgetElementByIdメソッドを使ってUL要素を特定し,それに対してgetElementsByTagNameメソッドを適用しています。こうすることで,要素をサーチする範囲を限定することができ,目的の要素が簡単に取り出せるようになるのです。

 なお,getElementsByNameメソッドは,documentオブジェクトに対してしか適用できませんので,注意してください。

子要素・親要素を参照する

 これまではHTML全体から特定の要素を参照する方法を見てきましたが,ここでは,ある特定の要素から,その中にある子要素や親要素を参照する方法を見ていきます。

 DOMでは次の四つのプロパティが規定されています(表2)。

childNodesプロパティ 子要素のリストをNodeListとして返します。
firstChildプロパティ 子要素のうち,最初の要素を返します。
lastChildプロパティ 子要素のうち,最後の要素を返します。
parentNodeプロパティ 親要素を返します。
表2●子要素・親要素を参照するプロパティ

 では,先ほどのUL要素のサンプルHTMLを使って,これらプロパティの具体的な使い方を見ていきましょう。

  var ul = document.getElementById('levels');
  /* UL要素の子要素のリスト */
  var children = ul.childNodes;
  /* 子要素の数をレポート */
  /* IEは3,それ以外では7 */
  alert(children.length);
  /* 最初の子要素のtitle属性値をレポート */
  /* IEはlevel1,それ以外ではundefined */
  alert(ul.firstChild.title);
  /* 最後の子要素のtitle属性値をレポート */
  /* IEはlevel3,それ以外ではundefined */
  alert(ul.lastChild.title);

 このコードの実行結果は,コード内のコメントに記述されている通りですが,Internet Explorerとそれ以外のブラウザとで結果が異なります。おそらく皆さんはInternet Explorerの結果を期待していたのではないでしょうか。

 ではInternet Explorer以外のブラウザでは何が起こっているのでしょうか。そこで,FirefoxのDOM Inspectorを使ってみましょう。このサンプルHTMLをDOM Inspectorで調べた結果は次の通りです(図1)。

図1●DOM Inspectorの結果
図1●DOM Inspectorの結果

 ご覧のとおり,UL要素の前後にテキストノードが存在しています。これは,前回で紹介したホワイトスペースノードです。ホワイトスペースノードの存在によって,期待する結果が得られなかったわけです。これを回避する方法は二つです。

(1)子要素を特定する際に,childNodes/firstChild/lastChildプロパティを使わず,getElementsByTagNameメソッドを使って,必要な要素だけを取り出すようにする。

(2)childNodes/firstChild/lastChildプロパティを使って取り出した要素の種類を判別するロジックを加える。

 (1)の方法はすでにご紹介したとおりです。(2)の方法については次回で詳しく解説していきます。いずれにせよ,ホワイトスペースノードの存在については,十分に理解しておいてください。

子要素の存在をチェックする

 先ほどの子要素を参照するプロパティは,はじめから子要素が存在していることを前提に話を進めてきました。しかし,実践では,本当に子要素が存在するかどうかわからない場合があります。例えば,サーバー側で実行されるウェブアプリケーションが表示する動的な画面が挙げられるでしょう。状況に応じて表示される内容が変化します。この場合,JavaScript側では,子要素を参照する前に,本当に子要素が存在するかどうかをチェックしたいものです。その方法は二つあります。

(1)childNodesプロパティから得られるNodeListのlengthプロパティを使う。

(2)hasChildNodesメソッドを使う。

 これらの方法を具体的に見ていきましょう。(1)はこれまで学んできた手法を使ったものです。

  var ul = document.getElementById('levels');
  if(ul.childNodes.length > 0) {
   /* 子要素が存在した場合の処理 */
}

 (2)のhasChildNodesメソッドは,子要素が存在していればtrueが,存在しなければfalseが返されますので,それをif文の条件式で使います。

  if(ul.hasChildNodes()) {
    /* 子要素が存在した場合の処理 */
}

 hasChildNodesはメソッドですので,()が必要です。これを忘れるとJavaScriptエラーとなりますので,注意してください。

 以上,HTML上の特定の要素を参照する方法を学んできました。しかし,取り出した要素がいったい何なのかをスクリプト上で認識できたわけではありません。取り出された要素が本当に目的の要素なのかを知る必要があります。次回は,取り出した要素の情報を知るためのテクニックを紹介していきます。