Hatena::ブログ(Diary)

三等兵

2009-10-26

jsのDOMによるノード取得

DOMとはdocument object modelの略。マークアップ言語の文書を操作するためのAPIだそうです。

ブラウザオブジェクトを使うだけでもだいぶ楽なわけですが、クロスブラウザを意識すればやっぱり面倒なんだそうで。大変だね。で、DOMを利用すればブラウザオブジェクトより互換性の高いコードが書きやすいということみたい。

その文書のそれぞれの要素をオブジェクトとみて、文書をオブジェクトの集合であると考えればいいのかな。アクセス方法もそれっぽいし。


文書の解釈上IEとFFでは若干違いがあるようで、IEは、

  • ノード間の空白/改行(空白ノード)を無視する
  • title要素配下のテキストノードを無視する

らしい。ノードっつーのはオブジェクトのことで、要素ノード、属性ノード、テキストノードなどと呼んだりする。html上要素ノードはタグで、属性ノードはプロパティのことでしょう。


とりあえず空白ノード(スペースキーでスペース入れたり)、titleタグのテキストは無視されるわけです。特に空白ノードは注意したいところ。


特定のノードを取得

方法はいくつかあるみたいですが、大きくダイレクトアクセスとノードウォーキングに分類できるそうです。ダイレクトに取得するか、起点から要素を辿って取得するかってことだと思います。

ダイレクトアクセスはID名やタグ名で検索し取得。ノードウォーキングは相対的な位置関係で取得、というもんで、相対的ってのは相対パスで考えれば分かるね。


ダイレクトアクセスは文書が大きいとあまりよろしくないようで、そういうときはノードウォーキングの方法が良いみたい。逆に文書が小さい場合はダイレクトアクセスしたらいいんじゃないということらしい。まあとりあえずどっちの方法も知っておきましょうってことか。


ID値をキーにノード取得

ダイレクトアクセス1例目。タグのIDをキーに直接取得する方法。

function btn_onclick() {
  var result = document.getElementById('result');
  result.innerHTML = 'どすこいパンチョです。こんにちは' + document.fm.name.value + 'さん';
}
</script>

//html
<form name="fm">
<input type="text" id="name" name="name" size="15" />
<input type="button" value="送信" onclick="btn_onclick()" />
</form>
<div id="result"></div>

formオブジェクト経由というややこしい方法で取得しているわけですが、document.getElementById('name').valueでもできる。


タグ名をキーにノード取得

ダイレクトアクセス2例目。タグをキーに直接取得。

document.getelementsByTagNameメソッドを使うんですが、返りがNodeListオブジェクトで返ってくるみたいです。タグをキーにするのですから複数の同一タグがあったとしても大丈夫なようにということでしょう。NodeListオブジェクトはノードの集合ということですね。

onload = function() {
  var result = [];
  var list = document.getElementsByTagName('a');

  for(var i = 0; i < list.length; i++) {
    result.push(list.item(i).href);
  }
  alert(result.join('\n'));
}

//html
<a href="http://d.hatena.ne.jp/sandai/">sundai</a>
<a href="http://www.yahoo.co.jp/">yahoo</a>
<a href="http://www.google.co.jp/">google</a>

pushメソッドは配列の最後尾にさらにインデックスを加えるメソッドです。aタグのhref属性を全部ぶんどって配列にしてalert表示。

今更気づいたけど配列って普通に表示できるもんなんですね。

var arr = ['1', '2', '3'];

//1,2,3
document.write(arr);  

関係ないけどjavascriptってハッシュと配列って無いな。

var arr = [{"aho": '1'}, '2', '3'];

//1
document.write(arr[0].aho);

こんな書き方しないでしょうね(笑


相対的な位置関係でノード取得

今度はノードウォーキングでの取得。これは文書のツリー構造を把握していないと使えない方法ですね。

onload = function() {
  var result = [];
  var s = document.getElementById('food');
  var opts = s.childNodes;

  for(var i = 0; i < opts.length; i++) {
    var opt = opts.item(i);

    if(opt.nodeType == 1) {
      result.push(opts.item(i).value);
    }
  }
  alert(result.join(','));
}

//html
<form>
  <select id="food">
    <option value="ゼブラマン">ゼブラマン</option>
    <option value="ウママン">ウママン</option>
    <option value="シカマン">シカマン</option>
  </select>
  <input type="submit" value="送信" />
</form>

返りはNodeListオブジェクトによって返ってくるわけですから、for文の使い方はこうしないとだめですね。NodeListオブジェクトのメンバも確認しておかないと。


childNodesプロパティは全ての子ノードを取得するもの。というわけでfood以下のノードを取得し、valueの値をそれぞれalertしているわけでしょう。これ以外のノード取得に使うプロパティも列挙しておこう。

  • ownerDocument:文書全体
  • parentNode:親ノード
  • previousSibling:兄ノード(同階層で起点より上)
  • nextSibling:弟ノード(同階層で起点より下)
  • firstChild:最初の子ノード
  • lastChild:最後の子ノード
  • childNodes:すべての子ノード

見る限りでは、途中の子ノードはchildNodesプロパティを使ってやるっきゃないってことかな。


で、if文はnodeTypeプロパティを使ってそのノードの種類を判定しているわけで、このサンプルの場合だと要素ノードのみを取り出していることになりますね。それ以外になにがあるんや、と思っちゃうわけですが、空白はテキストノードと判定されるのでそれ取り除いてるみたい。

IEだったら空白は無視されるみたいなんですけどね。

nodeTypeプロパティの返り値は、

https://developer.mozilla.org/ja/DOM/element.nodeType

で確認。

日本語メモっとこう。

  • 要素ノード == 1
  • 属性ノード == 2
  • テキストノード == 3
  • CDATAセクション == 4
  • 実体参照ノード == 5
  • 実体宣言ノード == 6
  • 処理命令ノード == 7
  • コメントノード == 8
  • 文書ノード == 9
  • 文書型宣言ノード == 10
  • 文書の断片 == 11
  • 記法宣言ノード == 12

あまり使いそうもないものもありますが。

属性値の取得と設定

ここは忘れても使い方を調べれば分かるので簡易メモ。

属性値にアクセスする場合は、要素ノードを取得した後ドット演算子でアクセス可能。というのもプロパティだからなんでしょうね。

あと一部属性名とプロパティ名が一致しないこともあるよう。たとえばclassだとcssClassとしないとアクセスできなかったり。そういうことを意識したくないのであれば、

  • getAttribute(属性名)
  • setAttribute(属性名, 属性値)

これらを使う。


ちなみに、attributeプロパティというのがあって、それを使えば全属性のリストをNameNodeMapオブジェクトとして取得できるみたい。

アクセスは個別のノードに名前、インデックス番号を使ってもアクセスできる。forとかで順に全部取得する場合は、nodeName/nodeValueプロパティを使えばそれぞれ属性名と属性値にアクセスできる。

IEだとそのタグで使える属性全てを取得できてしまうみたいなので、if文などを使って属性が空でないのだけ取得するようにフィルタをかけておかなければいけない。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/sandai/20091026/p1