JavaScript Examples
第23回 ノードリストインターフェイスの活用法について考える

今回もDOMのノードについてだが「NodeListインターフェイス」についてみていきたい。 NodeListはページ内のノードをタグやツリーなどのグループでまとめたもので、 連番でアクセスできるためプログラムからのアクセスに便利なものだ。 JavaScriptでは配列と同じ方法で扱うことができる。




■ノードリストを使ったアクセス方法

  たとえば、FORMタグの中のINPUT要素を探
すときに今までのJavaScriptには

  <form name="f0">     <input type="text" name="e0">   </form>
このようなフォームのe0は
  document.forms[0].elements[0]
といった書き方で特定する方法がある。 これは、そのページ(document)の中の最初 (0番目)のFORMタグ内にある最初(0番目)の エレメントという意味だ。つまり、各オブ ジェクト内のエレメントを連番によって特 定できる仕組みになっているわけだ。 これは便利だがこの方法が使えるオブジ ェクトはimages,options,appletsなど一部 のタグに限られておりHTML内のすべての要 素にアクセスできるというわけではない。 これに対してW3C-DOMでは、これと同様な 仕組みがすべての要素にアクセスできる形 で用意されている。
  oj.item(index番号)
という書き方だ。この場合のojは、タグ名 で検索するgetElementsByTagNameなどに よって用意することができる。たとえば、
  f=document.getElementsByTagName('FORM')
と書けば、ページ内のすべてのformタグの リストが作られて変数fに格納され、
  f0=f.item(0)
で最初(0番目)のフォームにアクセスできる。 同様にして更に、
  e=f0.getElementsByTagName('INPUT')
と書くことで、formタグ内のすべてのinput タグのリストがeへ格納される。このリスト がノードリスト(NodeList)という集合で、
  e.item(0)
と書けば、インプットタグe0にアクセスで きるようになる。ちなみに、JavaScript ではe[0]という書き方も可能だが、他の JavaScript以外の言語で使える保証はない ので覚える時には一応注意が必要だ。 ノードリストを使いこなす W3C-DOMだからといってブラウザ依存しないということはない。ブラウザメーカーには 良かれ悪しかれ「自由もバグもある」ということで現実に対応する知恵を絞ってみよう。 ■nodeListの道具箱  nodeListインターフェイスにはひとつのプ ロパティ(アトリビュート)とひとつのメソッ ド、つごうふたつの命令が定義されている。 ノードリスト内のノード数をあらわす lengthとリスト内のノードを連番で取り出す ためのitem(index番号)だ。  そしてノードリストは自体は、前述の通り getElementsByTagNameやchildNodesによって 得ることができる。ちなみに、このnodeList はW3C-DOMのCoreという仕様内のものだが別 に定義されているHTML仕様内のHTMLCollect ionも同様のリストで、たとえば、Tableオブ ジェクト.rowsなどで取り出されるテーブル 行のリストもnodeListと同じ命令で制御する ことが可能だ。
書式
oj.item( index番号 )

オブジェクト
oj
対象ノードリスト
引数
index番号
コレクションのindex(0からはじまる)
説明
ノードリスト内のindex番目にある項目を返す。 JavaScriptではoj[index番号]であらわすこと  もできる。
戻り値
ノードリスト内のindex番目にある項目(なければnull)
インターフェイス
/Core/NodeList
仕様
DOM1 /Core/NodeList/item
DOM2 /Core/NodeList/item
DOM3 /Core/NodeList/item

書式
oj.length

オブジェクト
oj
対象ノードリスト
説明
対象ノードが含むノードリストの数
戻り値
数値 長整数型
インターフェイス
NodeList
仕様
DOM1 /Core/NodeList/length
DOM2 /Core/NodeList/length
DOM3 /Core/NodeList/length
■ノードリストで処理してみる 前ページのinputタグへDOMを利用して JavaScriptから書き込む方法を試してみよう。 インプットフィールドへの入力を別のフィ ールドへ即座にコピーするというサンプルだ。

<script type="text/javascript"> <!--
  //書き換え処理   function writeTest(oj)   {     //FORMのノードリストを取得する     vf =document.getElementsByTagName('form')     //FORMを特定する     vf0=vf.item(0)
    //INPUTのノードリストを取得する     ve =vf0.getElementsByTagName('input')     //INPUTを特定し書き換える     ve.item(0).value=oj.value   }
//--> </script>
  <form name="f0">     <input type="text" name="e0">   </form>
  <form name="f1">     <input type="text"             name="e1"            onkeyup="writeTest(this)"><br>   ↑ここへ書くと上のフォームに書き込まれます   </form>
↑このスクリプトサンプル ./sample/f1.htm
 上記の関数writeTest内の変数vfがページ 内のフォームのノードリスト、変数veがフォ ームf0内のinputタグを網羅したノードリス トになっている。 ■ブラウザ互換に過剰な期待は禁物  ノードリストを取得する方法としては、 getElementsByTagNameの他に、childNodes を使う手もある。この命令は、
   oj.childNodes.item(index番号)
という書式で、ノードオブジェクト内のす べての子ノードをリスト化し、連番でアク セスできるようにしてくれる。ところが、 ここで困った問題が生じている。  例によって、ブラウザごとの動作が違う のだ。詳細の説明は省くが、簡単に言うと たとえばWin版IEは、
  <p>   </p>
この改行を無視するが、これ以外のブラウ ザ(Mac版IEはじめOpera7,Safari,Mozilla, N7)ではこの改行はtextノードとして解釈 される。したがって、
  <p><b>test</b></p>
などのようなべたで書いたり、タグをスク リプトから生成するなどの回避を考えない と、pのchildNodes.item(0)はブラウザごと に異なってしまうというわけだ。互換で苦 労したDHTMLの反省の上に生まれたW3C-DOM ではあるが、やはり過剰な期待は禁物とい うことのようだ。  したがって、厳密に処理したければやは り、各ブラウザの動作検証を行いながら作 っていくのが王道のようだ。  異なるメーカーの異なるプログラマー達が 作った異なるブラウザ間での同じ動作を期待 するなら、結局ユーザー側でクロスブラウザ の互換を用意しなければならないのは避けよ うのない宿命と受け止めるべきなのかもしれ ない。  そういった理解のうえで、W3C-DOMが多く の共通の仕様を提供して、各メーカーもそれ にしたがっている状況はDHTMLの時代よりは やはりありがたいといえる(とはいえ...)。
書式
oj.getElementsByTagName( tagName )

オブジェクト
oj
document
引数
tagName

タグ名。ワイルドカード「*」も使用可能。「*」はすべてのタグをあらわす
説明
引数のタグ名を持つすべてのエレメントのノードリスト配列を返す。順序はDocumentのツリー順。
戻り値
合致したすべてのエレメントを含むNodeList
インターフェイス
/Core/Document
仕様
DOM1 /Core/Document/getElementsByTagName
DOM2 /Core/Document/getElementsByTagName
DOM3 /Core/Document/getElementsByTagName
nodeListを使って操作してみよう ノードリストへのアクセス方法はLIやTD,TR,IMGなどそれぞれの要素ごとに 当然のことだが異なっている。ここではそれを具体的に試してみよう。 ■LIのノードリストを操作する
<script type="text/javascript"> <!--
//データ var li0 = new Array()     li0[0] = 'テスト0'     li0[1] = 'テスト1'     li0[2] = 'テスト2'
//書き換え処理 function wk(textoj) {
  //LIのノードリストを取得する   chlds = document.getElementsByTagName('LI')
  //LIをitem(0)から順番にスキャンする   for ( i = 0 ; i < chlds.length ; i++ )   {
    //各LIの最初の子をセットする     oj = chlds.item(i).firstChild
    //最初の子がTEXTノードなら書き換える     if(oj.nodeType == 3)       oj.nodeValue = textoj[i]
  } }
//--> </script>
<ul>   <li>その0   <li>その1   <li>その2 </ul>
<form> <input type=button         value=" 書き換える "        onclick="wk(li0)"> </form>

↑このスクリプトサンプル ./sample/f2.htm
 ボタンをクリックするとLIタグのノードリ ストが作成されて。変数chldsへ格納される。 LIの下には普通最初のノードとして箇条書き された文字列があるので、それを順番に調べ てその値であるnodeValueを書き換えている。 ■TABLEのノードリストを操作する
<script type="text/javascript"> <!--
//データ var a = new Array()     a[0] = 'data0'     a[1] = 'data1'     a[2] = 'data2'     a[3] = 'data3'
//書き換え処理 function wk(textoj) {   //対象TABLEを特定する   tbl0 = document.getElementById('table0')
  //対象TABLE内TDのノードリストを取得する   tds = tbl0.getElementsByTagName('TD')
  //TDをitem(0)から順番にスキャンする   for ( i = 0 ; i < tds.length ; i++ )   {     //各LIの最初の子をセットする     oj = tds.item(i).firstChild
    //最初の子がTEXTノードなら書き換える     if(oj.nodeType == 3)       oj.nodeValue = textoj[i]   } }
//--> </script>
<table id="table0" border="1">   <tr>    <td>データ0</td>    <td>データ1</td>   </tr>   <tr>    <td>データ2</td>    <td>データ3</td>   </tr> </table>
<form> <input type=button         value=" wk(a) "        onclick="wk(a)"> </form>

↑このスクリプトサンプル ./sample/f3.htm
 テーブルは内部にTRやTD,TBODYなどいろい ろな要素を持っているので目的に合わせて対 象を絞り込んで使う。  ここでは、まず、id名でテーブルを特定し たあとTDのノードリストを作成してから、 ひとつひとつ操作を行っている。  他に、たとえば、IMG要素なら同様に作成 したノードリストへsetAttributeなどでsrc 属性をセットすれば画像を書き換えることが できる。 ■Sample   ボタンクリックで画像を取り替える ■Sample   ボタンクリックでリンクグループを切り替える ■Sample   テーブルを制御する //////////////////////////////////////////////////////////////////// *上記サンプルは主に次の環境で動作するように作成されています ==================================================================== 動作環境 -------------------------------------------------------------------- Win n6 n7 moz e5 e6 o7, Mac n6 n7 moz e5 safari, Linux n6 n7 moz -------------------------------------------------------------------- //////////////////////////////////////////////////////////////////// 凡例 Win n3 -- NetscapeNavogator 3.x n4 -- NetscapeNavogator 4.x n6 -- NetscapeNavogator 6.x n7 -- NetscapeNavogator 7.x moz -- Mozilla e4 -- Internet Explorer 4.x e5 -- Internet Explorer 5.x e6 -- Internet Explorer 6.x o6 -- Opera 6.0 o7 -- Opera 7.0 Mac n3 -- NetscapeNavogator 3.x n4 -- NetscapeNavogator 4.x n6 -- NetscapeNavogator 6.x n7 -- NetscapeNavogator 7.x moz -- Mozilla e4.5 -- Internet Explorer 4.5 e5 -- Internet Explorer 5.0 または 5.1 safari -- Safari Linux n3 -- NetscapeNavogator 3.x n4 -- NetscapeNavogator 4.x n6 -- NetscapeNavogator 6.x n7 -- NetscapeNavogator 7.x moz -- Mozilla --------------------------------------------------------------------




●JavaScript 資料




Toshirou Takahashi tato@fureai.or.jp