任意のタグを検索する
document.all
コレクションは、HTMLドキュメントの要素を先頭からすべて取得することができるので、HTMLドキュメント全体の構造を実行時に把握したいときに利用できますが、そのようなシナリオは多くはないでしょう。むしろ、HTMLドキュメント内の特定のタグを取得したいというシナリオの方が一般的だと思います。
HTML要素オブジェクトは、tagName
のように全ての要素で共通しているプロパティもありますが、一方で要素固有のプロパティもあります。A
要素オブジェクトであれば、ハイパーリンク先のURLを表すhref
プロパティがありますし、IMG
要素であればイメージソースのURLを表すsrc
プロパティや、イメージが表示できない場合の代替テキストを表すalt
プロパティ、幅を取得するwidth
プロパティ、高さを取得するheight
プロパティなどがあります。
こうした、要素オブジェクト固有の操作を安全に行うには、document
オブジェクトが管理する要素オブジェクトのコレクションの中から、特定のタグだけを抽出しなければなりません。特定の要素のみを取得するにはall
コレクションのtags()
メソッドを使います。
all.tags(tag)
tag
には、コレクションの中から取得したい要素オブジェクトのタグを文字列で指定します。例えば、IMG
要素のみを取得したいという場合は"IMG"と指定します。このメソッドは、指定したタグに一致した要素オブジェクトの配列を返します。これで、実行時に複雑なHTMLドキュメントから目的の要素だけを抽出して操作することができます。次のプログラムは、HTMLドキュメント内に表示されているイメージの情報を、実行時にスクリプトで表示します。
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=shift_jis"> <title>サンプル 01</title> </head> <body> <p><img src="test00.jpg" width="400" height="300" alt="貴様を倒すのはこの俺だ"></p> <p><img src="test01.jpg" width="300" height="400" alt="三分間待ってやる"></p> <p>以下は、スクリプトから動的に生成しています</p> <script language="javascript"> var imgElements = document.all.tags("img"); var max = imgElements.length; for(i = 0 ; i < max ; i++) { var image = imgElements[i]; document.write("<p><table border=\"1\" cellspacint=\"0\">"); document.write( "<tr><th>ソース</th><td>" + image.src + "</td></tr>"); document.write( "<tr><th>代替テキスト</th><td>" + image.alt + "</td></tr>"); document.write( "<tr><th>幅</th><td>" + image.width + "</td></tr>"); document.write( "<tr><th>高さ</th><td>" + image.height + "</td></tr>"); document.write("</table></p>"); } </script> </body> </html>
このプログラムを実行すると、IMG
タグに記述されている属性値を表示する次のような結果が得られるでしょう。
ソース | ~/サンプル/test00.jpg |
代替テキスト | 貴様を倒すのはこの俺だ |
幅 | 400 |
高さ | 300 |
プログラムは、最初にdocument.all.tags("img")
を実行してIMG
要素オブジェクトの配列を取得します。imgElements
変数はIMG
要素オブジェクトの配列なので、IMG タグ特有のsrc
やalt
属性に対応したプロパティに、安全にアクセスすることができます。
識別子で検索する
タグ名で要素オブジェクトの配列を取得する方法は、指定したタグ名に一致するドキュメント内の全ての要素オブジェクトを返してしまうため、HTML ドキュメント内の特定のタグだけを取得したい場合には不便です。HTMLでは、全ての要素にID
属性を指定することができ、スクリプトから指定した識別子に一致するID
属性を持つ要素オブジェクトを取得することができます。
これまで、all
コレクションから要素オブジェクトを取得するときに整数のインデックスを指定しましたが、整数の代わりに文字列の識別子を設定することができます。この場合、コレクションの中から識別子に一致する要素オブジェクトが返ります。
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=shift_jis"> <title>サンプル 02</title> </head> <body> <img src="test00.jpg" id="test00" width="0" height="0"> <img src="test01.jpg" id="test01" width="0" height="0"> <p>以下は、スクリプトから動的に生成しています</p> <script language="javascript"> var id = prompt( "表示するイメージのID属性を入力してください", "test00") var image = document.all(id); if(image == null) document.write( "<p>指定したイメージは存在しません</p>"); else document.write("<p><img src=\"" + image.src + "\"></p>"); </script> </body> </html>
このプログラムを実行すると、入力用のダイアログボックスが表示されます。id
属性で"test00"と"test01"という識別子を持つ二つのIMG
要素を表示し、ダイアログで入力した文字列に一致するIMG
要素のイメージを表示するというものです。静的なHTMLのイメージとして指定している二つのIMG
要素は幅と高さを0ピクセルに設定しているため、画面には表示されません。
当然、識別子に一致する要素が存在しなければall
コレクションはnull
を返します。プログラムでは"test00"でも"test01"でもない場合、all
コレクションの結果がnull
となるでしょう。image
変数がnull
であるかどうかを調べ、null
の場合はイメージが存在しないことを通知するテキストを表示します。
ちなみに、スクリプトを記述する時点で要素オブジェクトの識別子が分かっている場合、all
で検索する必要はありません。id
属性で指定した識別子を使って、そのまま変数としてオブジェクトにアクセスすることができます。つまり、上記のプログラムの場合はすでに要素オブジェクトを格納するtest00
とtest01
変数が定義されているのです。
HTMLを動的に変更する
例えば、IMG
要素オブジェクトのsrc
やalt
プロパティは書き込みが可能なプロパティなので、実行時に表示するイメージのURLを変更するということが可能です。しかし、P
要素など、子要素や内容となるテキストを持つタグの全体を変更することはできません。要素オブジェクトのtagName
プロパティも読み取り専用となっているので、実行時にこうしたプロパティから、タグやタグの内容を書き換えることができないのです。
要素が持つテキストや子要素などを含めたタグ全体の内容を変更するには、innerText
、innerHTML
、outerText
、outerHTML
プロパティのいずれかを使います。inner系は開始タグと終了タグに挟まれている要素の内部を表すのに対し、outer系は開始タグと終了タグを含む要素オブジェクト全体を表します。
innerText
は、開始タグと終了タグに挟まれた内部テキストを設定したり取得することができるプロパティです。P
タグに囲まれた内部のテキストを変更するというような場合に、このプロパティを利用することができます。innerHTML
は内部テキストと子要素を含めた全体の設定・取得をすることができます。同様にouterText
プロパティは、要素オブジェクトの内部テキストを、outerHTML
プロパティは要素全体のHTMLテキストを設定したり取得することができます。
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=shift_jis"> <title>サンプル 03</title> </head> <body> <p id="label">このテキストは <i>label</i> のテスト用です。</p> <p>以下のテキストが動的に取得した HTML ドキュメントの構造です</p> <script language="javascript"> document.write("<p>innerText=" + toText(label.innerText) + "</p>"); document.write("<p>innerHTML=" + toText(label.innerHTML) + "</p>"); document.write("<p>outerText=" + toText(label.outerText) + "</p>"); document.write("<p>outerText=" + toText(label.outerHTML) + "</p>"); function toText(html) { var result = html.replace(/</g, "<"); result = result.replace(/>/g, ">"); return result; } </script> </body> </html>
このプログラムのHTMLドキュメントでは、P
要素に指定したID
属性で"label"という名前を与えています。プログラムからはID
属性に渡したlabel
という名前の変数から、HTML ドキュメントのP
要素にアクセスすることができます。プログラムでは、label
変数のオブジェクトから、innerText
、innerHTML
、outerText
、outerHTML
をそれぞれ表示して、これらのプロパティが表す内容の違いを比較します。
innerText
とouterText
は、それぞれ要素内部のテキストを表すプロパティなので得られる結果は同じでしょう。テキストとして取得されるため、P
要素の子要素として指定されているI
要素は省略されます。これに対してinnerHTML
は内部のテキストをHTMLテキストとして返すため、P
要素の内部がHTMLドキュメントに記載されているそのままの形で返されます。そのため<i>~</i>
タグを取得することができます。
outerHTML
は、要素の内部だけではなく、要素オブジェクト自身もテキストとして返すためP
要素の開始と終了タグも含めた全体「<P id=label>このテキストは <I>label</I> のテスト用です。</P>
」が表示されます。
これらのプロパティは書き換え可能なので、innerHTML
やouterHTML
プロパティの値を書き換えることによって、要素全体を実行時に動的に変更することができます。この機能を使えば、HTMLドキュメントを読み込んだ後で、スクリプトから新しい要素オブジェクトを追加することができます。ただし、HTML
、HEAD
、TITLE
要素を置き換えることはできません。
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=shift_jis"> <title>サンプル 04</title> </head> <body> <p id="label">ここに入力したHTMLが表示されます</p> <p>以下のテキストが動的に取得した HTML ドキュメントの構造です</p> <script language="javascript"> label.innerHTML = prompt( "HTMLを入力してください", "例えば<img src=\"test00.jpg\">"); </script> </body> </html>
このプログラムを実行すると、スクリプトがwindow
オブジェクトのprompt()
メソッドを呼び出して、入力ダイアログが表示されます。ダイアログのテキスト入力フィールドに、任意の文字列やHTMLを記述して[OK]ボタンを押してください。入力を終了すると、入力したテキストが返されるので、これをlabel
という名前のP
要素オブジェクトにHTMLとして保存します。
入力結果となるテキストはlabel
オブジェクトのinnerHTML
に設定しています。この結果、id
属性にlabel
を指定しているP
要素の内部テキストと子要素が設定したテキストに入れ替わるため、動的にHTMLドキュメントが変更されます。
実際には、上記のようなプログラムはセキュリティ上のリスクがあるため、ユーザー入力の結果をそのままHTMLで表示するようなことをしてはいけません。入力ダイアログのテキストにSCRIPT
タグを記述すると、スクリプトがそのままHTMLとして表示され、実行されてしまいます。悪意あるスクリプトの場合、危険なコードが実行される可能性があります。