JavaScript Examples
第24回 NamedNodeMapを利用する方法について考える

 前回はNodeListインターフェイスについて調べてみたが、今回は NamedNodeMapだ。名前に同じNodeが付いているがアプローチの対象とその方法が違っている。 NodeListとは異なり「名前」を用いて属性ノードにアクセスするためのインターフェイスというのがそのポピュラーな使い道だ。




■NamedNodeMapの使い方

  前回みたようにNodeListはchildNodesや
getElementsByTagNameを使うことで得ること
ができた。たとえば、ページの一番最初にあ
るFORMに対しては、

  f=document.getElementsByTagName('FORM')   test=f.item(0)
と書けば、そのページのすべてのFORMのリス トが変数fに収まり、最初(0番目のitem)の FORMにtestという変数名でアクセスできるよ うになる。  つまり、ノードに対して0から始まる「連 番」でアクセスできるリストがNodeListとい うわけだ。これに対して、NamedNodeMapは 「名前」を用いてノードにアクセスするとい うのが大きな違いだ。  ただし、NodeListのようにタグ(要素)の 集合というわけではない。あるタグの中の属 性(アトリビュート)の集合、つまり、name, id,href,src,width,heightといったおなじみ のタグ内の属性をリストアップしてくれる*注1。  では、NamedNodeMapを作成し確認する簡単 なサンプルをみてみよう。
<script type="text/javascript"> function getTest() {   //1 id名がabcのエレメントを変数eへ入れる   e = document.getElementById('abc')
  //2 e内のNamedNodeMapを変数aへ入れる   a = e.attributes
  //3 aの属性名typeの値を表示する(textが返る)   e.value = a.getNamedItem("type") } </script> <form> <input id      = "abc"        type    = "text"         value   = ""> <input type    = "button"          value   = "テスト"        onclick = "getTest()"> </form>

↑このスクリプトサンプル ./sample/f1.htm
 このサンプルのテストボタンをクリックす るとabcというid名のついたinputタグ内の NamedNodeMapを利用してtype属性が表示さ れる。ちなみgetTest関数内の"type"の代わ りに"size"を指定すれば50が返り、"id"なら abcが表示されるというわけだ。 注1:これ以外にもDOCTYPE関連でも使えるが実装状況 を含めて一般的ではないので今回は省略する。 NamedNodeMapの命令について NamedNodeMapインターフェイスで利用できるいくつかの命令について確認しておこう。 ■setNamedItemを使ってみる  NamedNodeMapインターフェイスにはつぎの 通り4つのメソッドとひとつのプロパティ(ア トリビュート)が定義されている*注2。 メソッド getNamedItem(名前) setNamedItem(ノード) removeNamedItem(名前) item(index番号) プロパティ length  getNamedItemは前ページでみたとおり名前 で指定されたノードを返す。setNamedItemと removeNamedItemは名前の通りノードの追加と 削除だ。itemはマップ内のindex番目の項目を 返し、lengthはマップ内のノードリストの数 だ。  ここで、注意が必要なのは、itemのindex 番号だ。番号で取り出すことはできるし、一 見順番どおり取りだせるかのようにもみえる がNodeListのような順番の保証は無い。単に すべての項目を取り出すといった作業に限定 するなどして使うのが安全だろう。  次に、setNamedItemを使って属性widthの値 を書き換えるサンプルをみてみよう。ボタン を押すと新しくwidthがセットされて画像の横 幅がグイーンと大きくなるというものだ。
<script type="text/javascript"> <!--
function setTest() {   //1 id名がdefのエレメントを変数imへ入れる   im = document.getElementById('def')
  //2 widthと言う名前の属性を生成し変数attriへ入れる   attri = document.createAttribute("width")
  //3 width属性をimのマップにセットする   im.attributes.setNamedItem(attri)
  //4 セットされたwidth属性に値を書き込む   im.setAttribute("width","300") } //--> </script> <img   id      = "def"        height  = "80"        src     = "./bar1.gif"> <form> <input type    = "button"          value   = "テスト"        onclick = "setTest()"> </form>

↑このスクリプトサンプル ./sample/f2.htm
書式
oj.getNamedItem( Name )

オブジェクト
oj
対象NamedNodeMap
引数
Name
ノードの名前
説明
名前によって指定されたノードを返す
戻り値
指定されたノード。該当しない場合はnull
インターフェイス
/Core/NamedNodeMap
仕様
DOM1 /Core/Document/getNamedItem
DOM2 /Core/Document/getNamedItem
DOM3 /Core/Document/getNamedItem


書式
oj.setNamedItem( Node )

オブジェクト
oj
対象NamedNodeMap
引数
Node
セットするべきノード
説明
引数によって指定されたノードを追加する。既存の名前の場合は置き換える
戻り値
置き換えた場合は既存のノード。それ以外はnull
インターフェイス
/Core/NamedNodeMap
仕様
DOM1 /Core/Document/setNamedItem
DOM2 /Core/Document/setNamedItem
DOM3 /Core/Document/setNamedItem


書式
oj.removeNamedItem( Name )

オブジェクト
oj
対象NamedNodeMap
引数
Node
取り除かれるノード名
説明
引数によって指定されたノードを取り除く。そのノードがデフォルト値を持つ属性なら即座に置き換えられる。
戻り値
取り除かれたノード。該当しない場合はnull
インターフェイス
/Core/NamedNodeMap
仕様
DOM1 /Core/Document/removeNamedItem
DOM2 /Core/Document/removeNamedItem
DOM3 /Core/Document/removeNamedItem


書式
oj.item( index番号 )

オブジェクト
oj
対象NamedNodeMap
引数
Node
0で始まる連番
説明
マップ内のindex番目にあるノードを返す。ただし、NodeListのitemのような順番の保証は無い。JavaScriptではoj[index番号]であらわすこともできる。
戻り値
indexが示すノード。無ければnull。
インターフェイス
/Core/NamedNodeMap
仕様
DOM1 /Core/Document/item
DOM2 /Core/Document/item
DOM3 /Core/Document/item


書式
oj.lengh

オブジェクト
oj
対象NamedNodeMap
説明
マップ内のノードの数。IE以外のブラウザは実際にセットされているノードの数を返すが、IEはそのマップとして利用可能なすべてのノード数を返すので100以上の値になってしまう。。
戻り値
数値 長整数型
インターフェイス
/Core/NamedNodeMap
仕様
DOM1 /Core/Document/length
DOM2 /Core/Document/length
DOM3 /Core/Document/length
 NamedNodeMapのlengthとitemについては、 IEの実装が他のブラウザとかなり異なっている こともありNodeListのものに比べるとかなり使 いにくいので今回は省略し、次に、 removeNamedItemについてみてみたい。 *注2:DOM2以降はnamespace関連のメソッドも 追加されているがここでは省略する。 ■removeNamedItemを使ってみる  下記のサンプルは画像につけたtitle属性 をボタンクリックで取り除いてみるという ものだ。titleを取り除いたついでに新しい titleをsetNamedItemで追加するということ もやっている。  最初画像の上にマウスカーソルを当てる と説明のツールチップが現れるが、"titleを 除去"というボタンをクリックした後は二度 と出なくなる。そして、"titleを追加"とい うボタンを押すと今度は新しいメッセージの title属性がセットされるというわけだ。 (Safariはベータ2現在title属性が表示され ないが、SafariのエンジンであるKonqueror3 では動作する)

<script type="text/javascript"> <!--
function removeTest() {   //1 id名がtest3のエレメントを変数img3へ入れる   img3 = document.getElementById('test3')
  //2 title属性をimg3のマップから取り除く   img3.attributes.removeNamedItem("title") }
function setTest() {   //1 id名がtest3のエレメントを変数img3へ入れる   img3 = document.getElementById('test3')
  //2 titleと言う名前の属性を生成し変数attriへ入れる   attri = document.createAttribute("title")
  //3 title属性をimg3のマップにセットする   img3.attributes.setNamedItem(attri)
  //4 セットされたtitle属性に値を書き込む   img3.setAttribute("title","ティーカップでもあるよ") }
//--> </script> <img   id      = "test3"        title   = "これはコーヒーカップです"        src     = "./cap.jpg"> <form> <input type    = "button"          value   = "titleを除去"        onclick = "removeTest()"> <input type    = "button"          value   = "titleを追加"        onclick = "setTest()"> </form>

↑このスクリプトサンプル ./sample/f3.htm
 NamedNodeMapのサンプルということでこの サンプルを用意したわけだが、実は、このス クリプトの2と3の行は省略しても動作する。 DOMには少し過剰な仕様なのではないかと思 われるほど幾通りもの処理方法があるのだ。 その点について次に簡単に確認しておこう。 ■NamedNodeMapを使う多様な方法と実装  ここまでみてきて、こんな書き方をしなく ても別の方法があるよと思った読者の方も少 なくないはずだ。そう、これに限らずDOMの 仕様は同じ機能を実現するために複数のアプ ローチを用意しており、また、ブラウザ依存 の言い回しも世間では結構流通しているのが 現実だ。  ちなみに、<div id="a">test</div>という タグのid名にアクセスし、そのid名を取得す るという方法を列挙してみよう。
  1.document.getElementById("a").id     2.document.getElementById("a").getAttribute("id")    3.document.getElementById("a").attributes.id.value     4.document.getElementById("a").attributes.id.nodeValue    5.document.getElementById("a").attributes.item("id").value    6.document.getElementById("a").attributes.getNamedItem("id").value    7.document.getElementById("a").attributes.getNamedItem("id").nodeValue    8.document.getElementsByTagName("div").item(0).id    9.document.getElementsByTagName("div").item(0).getAttribute("id")   10.document.all("a").getAttribute("id") 
 同じ機能にもかかわらず、ざっと並べただ けでもこんなにあるのだ。しかし、問題はこ れらすべてがDOM対応と言われるブラウザで 動作するというわけではないことだ。  ということは、どれがブラウザ依存し、ど れが依存しない書き方なのかを知っておく必 要があるというわけだ。そこで、今回はとり あえず、上記10種類の書き方についてW3C-DOM 対応と呼ばれているブラウザの動作について 確認してみたので参考にして欲しい。今回の パターンでおそらく安全と思われるのは、 1,2,6,7,8,9だ。この結果をみる限りではやは り、W3C-DOMの仕様に従ったものが安全という ことのようだ。
    win              mac           linux     n7 m1 e5 e6 o7   n7 m1 e5 s1   n7 m1 k3  1  ○ ○ ○ ○ ○   ○ ○ ○ ○   ○ ○ ○  2  ○ ○ ○ ○ ○   ○ ○ ○ ○   ○ ○ ○  3  ○ ○ ○ ○ ×   ○ ○ ○ ×   ○ ○ ×  4  ○ ○ ○ ○ ×   ○ ○ ○ ×   ○ ○ ×  5  ○ ○ ○ ○ ○   ○ ○ × ×   ○ ○ ×  6  ○ ○ ○ ○ ○   ○ ○ ○ ○   ○ ○ ○  7  ○ ○ ○ ○ ○   ○ ○ ○ ○   ○ ○ ○  8  ○ ○ ○ ○ ○   ○ ○ ○ ○   ○ ○ ○  9  ○ ○ ○ ○ ○   ○ ○ ○ ○   ○ ○ ○ 10  × × ○ ○ ○   × × ○ ×   × × ○
凡例
 Win   n7 -- NetscapeNavogator 7.x   m1 -- Mozilla1.x   e5 -- Internet Explorer 5.x   e6 -- Internet Explorer 6.x   o7 -- Opera 7.0
 Mac   n7 -- NetscapeNavogator 7.x   m1 -- Mozilla1.x   e5 -- Internet Explorer 5.0 または 5.1  s1 -- Safari
 Linux   n7 -- NetscapeNavogator 7.x   m1 -- Mozilla1.x   k3 -- Konqueror 3.x
■Sample   SELECTタグのマルチ表示を切り替える1   SELECTタグのマルチ表示を切り替える2 [+]印をクリックするとオプションリストが展開される。1と2は 同じ動作だが別の方法で実現している。NamedNodeMapを利用しているのは 2のサンプルだが、このケースの場合は1の方が多くのブラウザで動作する。 ■Sample   OLタグのタイプ属性を切り替える OLタグのナンバリングタイプをアトリビュートを生成し切り替えている。 ■Sample   Aタグのターゲット先を切り替える   Aタグのターゲット先を切り替える Aタグのターゲットは読み込むページをフレームやサブウインドウへ振り分ける 機能を持っているが、ここではそのtarget属性を取り替えることでリンクを クリックした時の表示先を変更できるようになっている。 //////////////////////////////////////////////////////////////////// *上記サンプルの動作環境は各サンプルをご確認ください ==================================================================== 凡例 Win n3 -- NetscapeNavogator 3.x n4 -- NetscapeNavogator 4.x n6 -- NetscapeNavogator 6.x n7 -- NetscapeNavogator 7.x m1 -- Mozilla1.x 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 m1 -- Mozilla1.x e4.5 -- Internet Explorer 4.5 e5 -- Internet Explorer 5.0 または 5.1 s1 -- Safari Linux n3 -- NetscapeNavogator 3.x n4 -- NetscapeNavogator 4.x n6 -- NetscapeNavogator 6.x n7 -- NetscapeNavogator 7.x m1 -- Mozilla1.x k3 -- Konqueror 3.x --------------------------------------------------------------------




●JavaScript 資料




Toshirou Takahashi tato@fureai.or.jp