目次

オブジェクトなJavaScriptの基礎講座

はじめてのDOM

◆ はじめに

最初に、DOMの基本である文書構造を示すノード (node) とは何かということと、ノードからノードへ DOM ツリー内アクセス 方法を学びます。次に、特定のノードを 取得する 方法と、ノードの値や属性を 変更する 方法を学びます。最後に、自分で ノードを作る 方法を学びます。

尚、DOM は、HTML/XML文書のあらゆる局面にアクセスし、それを変更する手段を提供するために開発されたので、DOM には、平均的なウェブ開発者にとって必要のない多くの機能がありますが...。とりあえず、重要な機能から勉強をはじめましょう!

◆ ノードとは何か

DOM はドキュメントオブジェクトモデルで、文書の様々なオブジェクトが互いにどのように関連しているのかを記述するモデルです。個々のオブジェクトは、それが何であれ、Node です。

<p>これは、段落です。</p>

2 つのノード、つまり 「p要素」要素ノード「これは、段落です。」 という内容の テキストノード を作ったことになります。テキストノードは要素の内部にあります。そのため、これは、要素の 子ノード と考えられます。逆に、要素はテキストノードの 親ノード と考えられます。

              <p> -+-  これは、段落です。
          (要素ノード)     (テキストノード)
          (親ノード)       (子ノード)

次のようにすると

<p>これは、<em>段落です。</em></p>

要素ノード p は、2 つの子をもち、そのうちの一つはそれ自身の子をもちます。

              <p> -+- これは
                     |
                     +- <em> -+-  段落です。

最後に、属性ノード (attribute node) があります。しかし、それは要素ノードの子として扱われません。

<p align="right">これは<em>段落です。</em></p>

これは次のようになります。

              <p> -+- これは
              |      |
              |      +- <em> -+-  段落です。
              |
              +- align -+- right

上記には、要素ノード、テキストノード、属性ノードがあり、この 3 つがHTML ページの内容の大分部を占めます。他にも種類がありますが、とりあえず、この3つが重要です。

また、実は、要素ノード p にはそれ自身の親がいます。これは、通常、body要素 ですが、時には div要素 のような別の要素の場合もあります。そのため、HTML 文書全体は、多くのノードからなるツリーと見ることができます(以後、DOMツリー)。その多くは、子ノードをもち、また、子ノードが子をもつ場合がほとんどです。

◆ DOMツリー内アクセス方法

DOM ツリー構造の雰囲気がわかったので、影響を及ぼしたい要素を検索するためにツリー内をアクセスしてみましょう。

例えば、要素ノード p が変数 x に保存されているとします。 (これは、後で、具体的に説明します。)

親のノードbody にアクセスしたい場合、次のようにします。

x.parentNode

また、子のノードにアクセスしたい場合、次のようにします。(たとえば、em ノードにたどり着くには次のようにします。)

x.childNodes[1]

childNodes はノード x のすべての子を含む配列です。もちろん、添え字(インデックス)は 0 から始まります。そのため、childNodes[0] はテキストノード 「これは」 で、childNodes[1] は要素ノード em です。

特殊なケースが2 つあり、x.firstChildx の最初の子 (テキストノード) にアクセスします。また、x.lastChildx の最後の子 (要素ノード B) にアクセスします。

そのため、p が document の最初の子である html の 最後の子の body の最初の子であるとすると、次のコマンドはいずれも、要素ノード em にたどり着くことができます。

document.firstChild.lastChild.firstChild.lastChild
document.firstChild.lastChild.childNodes[0].lastChild
document.firstChild.lastChild.childNodes[0].childNodes[1]
など

サンプル

<html>
<head>
<title>DOMサンプル</title>
</head>
<body><p>これは<em>段落です。</em></p>
<script>
alert(document.firstChild.firstChild);              // head要素ノード
alert(document.firstChild.firstChild.firstChild);   // title要素ノード
alert(document.firstChild.lastChild);               // body要素ノード
alert(document.firstChild.lastChild.firstChild);    // p要素ノード
alert(document.firstChild.lastChild.firstChild.lastChild);  //em要素ノード(spanエレメント)
alert(document.firstChild.lastChild.childNodes[0].lastChild);////em要素ノード(spanエレメント)
alert(document.firstChild.lastChild.childNodes[0].childNodes[1]);//em要素ノード(spanエレメント)
alert(document.firstChild.lastChild.childNodes[0].childNodes[1].firstChild);//テキストノード
</script>
</body>
</html>

注意:HTML文書を見やすくするために挿入した改行ひとつでも、ひとつのテキストノードになります。

◆ ノードを取得する

しかしながら、こうしたやり方で文書内をアクセスするのは、まったく面倒で、DOM ツリー全体の構造について完全に知っている必要があります。つまり、実際には、かなり複雑になり、実用は難しくなります。

そのため、選択した要素に直接ジャンプする方法が用意されました。そこにたどり着いたら、そこを起点として、行きたい場所にDOMツリーをアクセスします。

それでは、その方法を例を上げて説明することにしましょう。

要素ノード em にアクセスしたいとします。一番簡単な方法は、それに直接ジャンプすることです。メソッド document.getElementsByTagName によって、文書内のタグ em すべての配列を作ることができ、それを使ってそれらの一つにたどり着くことができます。この em が文書内の最初のものであるとしましょう。次のようにするだけで済みます。

var x = document.getElementsByTagName('em')[0]

x は要素ノード em をもちます。まず、ブラウザに文書内のすべての要素 em を取得するよう命令します (document.getElementsByTagName('em')) 。次に、文書内のすべての em のうち最初のものを選択します ([0])。これで行きたい場所にたどり着けました。

次のようなこともできます。

var x = document.getElementsByTagName('p')[0].lastChild;

今度は、文書内の最初の段落に行き (この場合の p は最初のものだと仮定します)、次にその lastChild に行きます。

また、DOMツリーの現在の構造に関わりなく正しい要素にたどり着く便利な方法があります。それは、em に id を与えることです。

<p align="right">これは <em id="kore">段落です。</em></p>

この場合は、次のようにするだけで済みます。

var x = document.getElementById('kore');

要素ノード em は x に保存されます。

注意:getElement で最後に s は付きません。これは、id属性の値は、その文書内においてユニークでなければならないからです。

◆ ノードの値や属性を変更する

やっと、ノードにたどり着いたので、今度は、何か変更することにしましょう。ちょっと右下のテキストの「段落です。」 を '「階段です。」' に変更したいとします。そのためには、正しいノードにアクセスしてその nodeValue を変更しなければなりません。この場合、正しいノードは、要素ノード em ではなく、その子のテキストノードです。テキストの変更がしたいのであって、要素を変更したい訳ではありません。次のようにするだけです。

document.getElementById('kore').firstChild.nodeValue='階段です。';

これでノードは変更されます。

サンプル

ノードの内容の変更元に戻す

これは 段落です。

個々のテキストノードや属性の nodeValue の変更もすることができます。

たとえば、p要素の align 属性を変更してみましょう。

これもとても簡単です。必要なノードを取り (この場合は em の parentNode)、align 属性を変更したい値に設定するため、setAttribute() メソッドを使います。

属性の変更元に戻す

function dom_test2(val)
{
	if(document.getElementById && document.createElement){
		node = document.getElementById('kore').parentNode;
		node.setAttribute('align',val);
	}
	else
		alert('あなたのブラウザは Level 1 DOM を未サポートです');
}

◆ ノードの追加と削除

今度は、ノードの追加です。本段落(p要素)のすぐ下に img要素を追加してみましょう。また、それを 削除 してみましょう。

要素を作るのは以下のメソッドを使って行ないます。

var x = document.createElement('img');

これにより img要素 が作られ、一時的に x に保存されます。2 番目のステップは x を文書に挿入することです。それを表示する場所に id="insert_img_here" をもつ特殊な span を書きました。そのため、span に appendChild() メソッドを使い、img を span の子にしました。それによって、img は魔法のように現われます。

document.getElementById('inser_img_here').appendChild(x);

それを削除するのは少しだけ複雑です。まず、一時変数 node を作り span を保存します。次に、それに最初の子 (img) を削除するよう指示します。

var node = document.getElementById('insert_img_here')
if(node.childNodes[0] != undefined)
   node.removeChild(node.childNodes[0]);

同じやり方で、新しいテキストノードを作り、それを id="kore" をもつem 要素に追加します。

var x = document.createTextNode('テキストノードが現れたはず!');
document.getElementById('kore').appendChild(x);

試してみて下さい。そして、結果を見るため 前に戻ります。古い関数を実行しても新しいテキストノードが削除されないことが分かると思います。これは、別のノード になったためです。

           <em> -+- 段落です。
                    |
                    +- テキストノードが現れたはず!

上記のサンプルソース

<script type="text/javascript">
<!--
function dom_test3() // img要素を追加
{
	if(document.getElementById && document.createElement){
		var x = document.createElement('img');
		x.setAttribute('src', "../img/chaichan_bana.gif");
		document.getElementById('insert_img_here').appendChild(x);
	}
	else
		alert('あなたのブラウザは Level 1 DOM を未サポートです');
}

function dom_test4()// img要素を削除
{
	if(document.getElementById && document.createElement){
		var node = document.getElementById('insert_img_here')
		if(node.childNodes[0] != undefined)
			node.removeChild(node.childNodes[0]);
	}
	else
		alert('あなたのブラウザは Level 1 DOM を未サポートです');
}
function dom_test5()//テキストノードの追加
{
	if(document.getElementById && document.createElement){
		var x = document.createTextNode(' テキストノードが現れたはず!');
		document.getElementById('kore').appendChild(x);
	}
	else
		alert('あなたのブラウザは Level 1 DOM を未サポートです');
}
// -->
</script>
<span id="insert_img_here"></span>
<p align="right">これは <em id="kore">段落です。</em></p>

◆ まとめ

HTMLは、見栄えをするものでなく、文書を各要素に分別し、構造化するためのもので、DOMは、その構造化されたものをDOMツリーとして扱い、各要素に対して参照/更新をするためのものです。

とりあえず、今回学んだDOMのプロパティとメソッドは以下の通りです。

プロパティ

メソッド

◆ おわりに

ということで、DOMの雰囲気をつかんで頂けたでしょうか、次回は、「DOMによるスタイルの変更」をまとめてみます。ご期待ください!

尚、本ページを作成するにあたり、以下のページを大変参考にさせて頂きました。謹んでお礼申し上げます。

目次