任意のタグを検索する
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として表示され、実行されてしまいます。悪意あるスクリプトの場合、危険なコードが実行される可能性があります。
