これでできる! クロスブラウザJavaScript入門

第6回 JavaScriptとHTMLとDOMの基本#1

この記事を読むのに必要な時間:およそ 4 分

HTMLの解釈

HTMLは,タグによっては終了タグを省略することや,開始タグすら省略することが可能な場合があります。終了タグを省略可能なタグとしては,pタグやliタグなどがあります。pタグは内部にインライン要素(spanタグなど)しか持つことができないため,ブロック要素が現れたところでpタグを終了します。つまり,pタグの中にdivタグを入れることはできません。うっかり間違ったHTMLを書いてしまうとJavaScriptからHTMLを操作する際にブラウザによって構造が異なることになって苦労してしまうかもしれません。

タグの省略でよく問題となるのがtbodyタグです。tableタグはcaption,colgroup,thead,tfoot,tbody,col(ただしcolはHTML5でcolgroupの子要素に限定されています)しか子要素に持つことができません。tableタグの直下にtrタグを書いた場合,ブラウザはtbodyタグがあるものとして解釈します。よって,tr要素の親がtableタグだと思ってJavaScriptを書いてしまうとバグを発生させかねません。ほかにもbodyタグを省略したとき,headに含めることができないタグが現れたところにbodyタグが省略されているものとして解釈します。

とはいえ,HTMLを正しく書けていればブラウザ間の差に悩まされることはまずありません。一方,間違ったHTMLを書いてしまうとブラウザの解釈の違いに悩まされることになります。具体例としては,script要素は閉じタグを省略することはできませんが(<script src="~" />のような書き方も不可⁠⁠,うっかり省略してしまっても問題ないブラウザもあるため,すぐに気が付かないこともあるので注意が必要です。

Document Object Model

Document Object Model(DOM)とは,HTMLやXMLなどのマークアップ言語をアプリケーションから扱うためのAPIです。HTML上の要素やテキストを取得したり,新しく作ったり,書き換えたりといった操作が定義されています。HTML上で実行されるJavaScriptはこのDOMを介してHTMLを扱います。そのため,DOMはJavaScriptでアプリケーションを作る際には避けては通れない重要なAPIです。

DOMについて背景知識を簡単に紹介しておきましょう。DOMはW3Cによって定義・勧告されており,2010年5月時点でDOM Level 1からLevel 3まで存在し,さらにその中にいくつもの仕様があるというように,かなり大きな仕様群です。そのうち,IEはDOM Level 1まで,Firefox,Chrome,Safari,OperaなどはDOM Level 2とLevel 3の一部を実装しています。IE 9はDOM Level 2,DOM Level 3をサポートする予定です。

また,DOM Level 1が定義される前にブラウザが実装していて,標準化はされていないがある程度互換性がある部分をDOM Level 0と(慣例で)呼びます。DOM Level 0はHTML5やCSSOMなどで再定義されようとしている部分も多く,標準化が進められています。

IEはDOM Level 2をサポートしていませんが,独自の実装でDOM Level 2に近いAPIが提供されています。この独自の実装が非常にやっかいで,IE以外のブラウザもDOM周りには非互換な部分があるため,クロスブラウザなJavaScriptとはすなわちDOMを扱うことだと言っても過言ではありません。逆に言えば,DOMの扱い方を覚えれば,クロスブラウザは全く難しくなくなります。

DOM Level 1

前述の通り,DOM Level 1まではIEもサポートしているので,同じソースコードでJavaScriptを動かすことができます。例えば,この連載の中でも何度か登場している document.getElementById はDOM Level 1なので下準備や分岐などせずにそのまま使用できます。一方 addEventListener はDOM Level 2 Eventsなので,IE対策でaddEvent関数を定義しました。よって,DOM Level 1を把握することで共通のソースコードでよい部分,IE用に処理を分ける必要がある部分が見えてくるので,DOM Level 1を知っておくことは重要です。

DOM Level 1の範囲で書いたJavaScript

var element = document.getElementById('ID');
var divs = element.getElementsByTagName('div');
for (var i  = 0, len = divs.length;i < len;i++){
  var div = divs[i];
  if (div.className === 'CLASS'){
    div.appendChild(document.createTextNode('TEXT'));
  }
}

document.getElementById, ELEMENT.getElementsByTagName, ELEMENT.className, ELEMENT.appendChild, document.createTextNodeなどはどれもDOM Level 1で定義されているため,このままでクロスブラウザなコードとして動作します。これら一つ一つを把握するのは楽ではありませんが,DOM Level 1 仕様書から,IDL Definitionの部分だけでもざっくり眺めておくとよいと思います(10年前の仕様書なので,それ以上読み込むのはおすすめしません。もし読み込むならその後にDOM Level 2,3も読み込むべきでしょう⁠⁠。

まとめ

今回はJavaScriptのためのHTMLを中心に解説しました。次回からはDOMについて実用的なコードを解説していきたいと思います。

著者プロフィール

太田昌吾(おおたしょうご,ハンドルネーム:os0x)

1983年生まれ。JavaScriptをメインに,HTML/CSSにFlashなどのクライアントサイドを得意とするウェブエンジニア。2009年12月より、Google Chrome ExtensionsのAPI Expertとして活動を開始。

URLhttp://d.hatena.ne.jp/os0x/