HTMLをドキュメントオブジェクトとして扱うための約束事「DOM」を、JavaScriptを通して使うことで、HTMLの好きな部分を読み書きすることができます。
連載の前回、「第6回 配列とオブジェクトでデータをまとめる」では、配列とオブジェクトの基本的な扱い方を説明しました。扱うデータの量が少ないうちは、普通の変数だけでなんとかなってしまいますが、データの量が増えれば増えるほど、配列やオブジェクトのありがたみが分かります。
特に、配列に入れたデータを、ループで一気に処理する快感が分かるようになれば、初心者卒業といってもいいでしょう。
それでは、前回の課題の答え合わせをしてみましょう。平均点の求め方は、配列のサンプルでやっていたので簡単すぎたでしょうか。解答サンプルでは、成績の一覧と平均点を同時に表示するようにしてみました。
<html> <body> <script type="text/javascript"> function Seito(_namae, _seiseki) { this.namae = _namae; this.seiseki = _seiseki; } var kumi=[]; kumi[0]=new Seito("山田太郎",95); kumi[1]=new Seito("田中一郎",73); kumi[2]=new Seito("鈴木花子",86); var total=0; for(i=0;i<kumi.length;i++){ document.write(kumi[i].namae+":"+kumi[i].seiseki+"点<br>"); total+=kumi[i].seiseki; } var heikin = total/kumi.length; document.write("成績の平均 = "+heikin); </script> </body> </html>
成績一覧を表示するループ内に、平均点用の変数totalを加算する式を入れて、表示と計算を同じループ内で処理しています。
今回は、HTMLを操作する「DOM」(ドム)にチャレンジしてみましょう。
DOMの説明の前に、まず簡単にHTMLの構造をおさらいしてみましょう。次のHTMLを見てください。
<html> <head> <title>タイトル</title> </head> <body> <div>ブロック1</div> <div>ブロック2</div> </body> </html>
HTMLは、<img>タグや、改行のための<br>タグなどいくつかのタグを除いて、基本的には<html>のような開始タグと、</html>のような頭に「/」(スラッシュ)の付いた終了タグがセットで使われます。
例えば、上のHTMLでいえば、最初の<html>と最後の</html>がセットになっています。このタグのセットの間に書かれた部分が、<html>タグの中身と言えます。
<html>〜</html>の中身を見てみると、<head>〜</head>というセットと、<body>〜</body>というセットがあります。さらに、<head>〜</head>の中身には<title>〜</title>というセットがあって、<body>〜</body>の中身には<div>〜</div>というセットが2つ入っています。
イメージとしては図1のように、<html>という箱の中に、<head>と<body>という箱が入っていて、<head>という箱の中には<title>という箱があり、<body>という箱の中には<div>という箱が2つ入っています。そして、それぞれの要素が「入れ子」になっている構造といえます。
このように「入れ子」になっている構造を「階層構造」と呼びます。ブラウザは、HTMLを階層構造として扱っています。もう少し身近な例で言えば、パソコンのOSのフォルダも階層構造になっています。
「OSのフォルダとHTMLが構造的に同じ」と言われても、ピンと来ない人がいるかもしれません。もう少し具体的にいうと、例えば、「マイドキュメント」の中に「マイピクチャ」と「マイミュージック」があるように、<html>の中に<head>と<body>が入っているイメージ、と言えば分かっていただけるでしょうか。
HTMLの階層構造がイメージできたでしょうか?
「DOMの話なのに、なんでHTMLの話から入るのか」と思うかもしれませんが、HTMLの階層構造がイメージできるかできないかで、DOMの理解度にも差が出てしまいます。
「イメージができない……」という人は、この先を読む前に、階層構造という言葉を念頭において、もう少しHTML自体を勉強してみることをお勧めします。HTMLに対して、きっと新しい発見があると思います。
「そんなの簡単だよ」と言える人は、すぐにDOMも理解できるようになります。安心して先を読んでください。
JavaScriptはHTMLをドキュメントオブジェクトというオブジェクトとして扱っています。「オブジェクト」については第6回でやりました。オブジェクトはHTMLのような階層構造を扱うのにも、とても便利なのです。
DOMというのは、HTMLをドキュメントオブジェクトとして扱うための約束事です。Document Object Model(ドキュメント・オブジェクト・モデル)を略してDOMと呼んでいます。
DOMが何かを知らなかったという方も多いかもしれませんが、実は、この連載の中ですでに何回もDOMを使っています。
第4回で出てきた「document.getElementById("★").innerHTML」は、実はDOMなのです。このように、JavaScriptからHTMLを簡単に参照して使うための仕組みがDOMだと考えてください。
「.」(ドット)でつなぐ書き方も、オブジェクトに似ていますね。さすがに、慣れるまでは普通のオブジェクトを扱うようにはいきませんが、基本的な仕組みが分かれば簡単です。
第6回でやったように、普通のオブジェクトの場合、オブジェクトの中身を参照するためには、「オブジェクト名.プロパティー名」のように名前で参照ができました。ところが、DOMの中身には参照のための「オブジェクト名」にあたる名前がないため、例えば「html.body.div」のような参照ができないのです。
名前での参照ができないので、どうするかというと、「document」というオブジェクトを親として、図2のような親子関係、兄弟関係でオブジェクトを参照していきます。このような参照構造のことを、木が1本の幹から枝分かれしていくようにも見えるのでツリー(木)構造とも呼びます。また、HTMLの場合、このツリーはdocumentオブジェクトが親なので、「ドキュメントツリー」と呼ばれます。
図2は、次のサンプルのInternet Explorer 8でのドキュメントツリーです。
<html> <head> <title>ドキュメントツリーって?</title> </head> <body> <div> ドキュメントオブジェクトはツリー構造で表せます。 </div> <script> alert(document.firstChild.childNodes[1].firstChild.firstChild.nodeValue); </script> </body> </html>
実行すると、bodyタグ内のdivタグの内容がアラートで表示されます。ドキュメントツリーは「document」から始まって、このサンプルの場合、最初の子どもは「<html>」になります。「<html>」の子どもは「<head>」と「<body>」になっているのが分かるでしょうか?
このように、枝分かれしている要素をNode(ノード)と呼びます。ノードというのは元々は結び目のことです。ドキュメントツリーでは、HTML内のすべての要素をこのノードという単位に分けて管理しています。
DOMで扱うノードの種類は主にHTMLに関わる次の3種類になります。
ノードの種類 | 説明 |
---|---|
要素ノード | HTMLタグのことです |
属性ノード | HTMLタグ内にあるプロパティーのことで、href、src、idなどです |
テキストノード | タグ以外のテキスト部分のことです |
DOMで扱うノード |
特に、慣れないうちはテキストノードと要素ノードの違いに戸惑うかもしれません。サンプルの「document.firstChild.childNodes[1].firstChild.firstChild.nodeValue」というDOM部分を詳しくみてみましょう。
「firstChild(ファーストチャイルド)」というのは、その名の通り、自分のドキュメントツリー上にある最初の子どものことを指します。このサンプルの場合では、「document.firstChild」は「<html>」になります。
「<html>」には子どもが2つあります。最初の子どもは「<head>」です。これをDOMで書くと、「ドキュメントの最初の子どもの最初の子ども」なので、「document.firstChild.firstChild」となります。
どうですか? 簡単ですね。
では、2番目以降の子どもはどうやって書けばよいのでしょうか。
DOMでは、子どもノードは「childNodes」という配列で管理されています。普通の配列と同じように、「子どもノード(配列)の何番目」というのを指定するだけで大丈夫です。ただし、配列は「0」から始まるので、数え方に注意してください。0がいちばん最初の子どもなので、「firstChild」を「childNodes[0]」と書き換えることもできます。
2番目の子どもを参照したいときは「childNodes[1]」と書きます。サンプルの場合では、「document.firstChild.childNodes[1]」で「<body>」を表します。「<body>」の最初の子どもは「<div>」ですね。「document.firstChild.childNodes[1].firstChild」が「<div>」を表しています。
サンプルのDOMでは、さらにその後ろに「firstChild」を付けています。
HTML上では「<div>」は子どもがいないはずですが……、実は、「<div>」内のテキストが、テキストノードとして存在しています。「document.firstChild.childNodes[1].firstChild.firstChild」という、ここまでが「<div>」のテキストノードを表しています。
これだけでは、DOMはテキストノードの位置を指し示しただけです。この位置に何が書かれているかを取り出すためには、「nodeValue」が必要になります。つまり、「document.firstChild.childNodes[1].firstChild.firstChild.nodeValue」というDOMは、「ドキュメントの、最初の子どもの、2番目の子どもの、最初の子どもの、最初の子どもに書かれている内容」という意味になります。
「nodeValue」を「nodeName」に変えてみると、DOMがどこを見ているのかが分かります。例えば、「document.firstChild.nodeName」とすると、アラートウィンドウに「HTML」と表示され、「<html>」を指していることが分かります。「document.firstChild.childNodes[1].firstChild.firstChild.nodeName」の場合はテキストノードなので、「#text」と表示されます。
DOMを扱うには、HTMLの構造をドキュメントツリーとして理解できるようになる必要がありますが、ある程度慣れてしまえば、簡単にJavaScriptからHTMLを操作できるようになります。
Copyright © ITmedia, Inc. All Rights Reserved.