入門 HTML5

入門 HTML5
Mark Pilgrim 著
矢倉 眞隆 監訳
水原 文 訳
オライリー・ジ
ン
本書で使用するシステム名、製品名は、それぞれ各社の商標、または登録商標です。
なお、本文中では、™、®、© マークは省略しています。
HTML5: Up and Running
Mark Pilgrim
Beijing・Cambridge・Farnham・Köln・Sebastopol・Tokyo
© 2011 O Reilly Japan, Inc. Authorized Japanese translation of the English edition of HTML5: Up and Running.
© 2010 Mark Pilgrim. This translation is published and sold by permission of O Reilly Media, Inc., the owner of all
rights to publish and sell the same.
本書は、株式会社オライリー・ジャパンが O Reilly Media, Inc. の許諾に基づき翻訳したものです。日本語版について
の権利は、株式会社オライリー・ジャパンが保有します。
日本語版の内容について、株式会社オライリー・ジャパンは最大限の努力をもって正確を期していますが、本書の内
容に基づく運用結果について責任を負いかねますので、ご了承ください。
v
監訳者まえがき
本書『入門 HTML5』は、Google で Developer Advocate を務める Mark Pilgrim による HTML5 と周辺
技術の書籍『HTML5: Up and Running』の日本語訳になります。Canvas や <video> など HTML5 として
紹介される技術の説明はもちろん、HTML5 までに至る経緯やビデオコーデックの話、ブラウザーの実装に
おける差異や注意点、バグへの対処コードなど、ページは少ないながらもカバーする範囲やトピックは広く
豊かです。また、Mark のウィットに富んだ文章や言葉遊びも、原著の魅力の一つでしょうか。
この原著、その原稿やデモすべてが Creative Commons の Attribution ライセンスのもと、Dive Into
HTML5(http://diveintohtml5.org/)というサイトで公開されています。クラシックなスタイル、茶目っ
気のある挿絵の使い方など、書籍とはまた違った楽しみもある Web サイトです。内容についても、媒体自
身が更新可能という Web の性質が活かされ、公開されてからずっと更新が続けられています。
原著が発売されたのは 2010 年の 8 月と数ヶ月も前のことです。Web は歩みの早い世界ですから、古く
なった、もしくは古さを感じさせる情報が原著には存在します。たとえば、先日リリースされたばかりの
Internet Explorer 9 の HTML5 に対応に関し、当然のことながらほとんど情報がありません。
いっぽう、Dive Into HTML5 は発売後も更新が行われており、IE9 に関する情報をはじめ、内容が大き
く変化したところもあります。ですから、監訳のお話をいただいたとき、原著をただ翻訳することは避けた
いと考えていました。今回、日本語版の出版にあたり、原著の出版以降に Dive Into HTML5 に追加・変更
された内容を反映させています。また、Dive Into HTML5 に反映されていない、古くなった情報について
も、できるだけ調べた上で文章の修正や注釈の追加を行っています。
Dive Into HTML5 はさらに発展しています。3 月 2 日には History API の章 † が追加され、編集がは
じまっています。Mark Pilgrim が年始に自身の weblog にポストした Dive Into HTML5/HTML5: Up &
Running の記事によると、改訂版に向けた話はすでに始めているようで、新しい章を追加することが示唆
されています。もともと Web Workers や WebSocket に関する章が含まれる予定でしたが、書籍や Web サ
イトには現時点で存在していません。第 2 版ではこの History API を含め、それらの章が加わるのかもしれ
ません。
いま動いている事象についてとりあげるとき、紙の書籍という媒体についてとても難しさを感じること
があります。Web での情報公開ではあまり意識することのない「時間」を考えなければいけないからです。
執筆してから出版されるまでに時間がありますから、ふだん weblog にポストするような速報性の高い情報
†
http://diveintohtml5.info/history.html を参照。
vi
監訳者まえがき
について触れることはできません。また、正誤表という仕組みはあるものの、誤りの修正や新しい情報への
更新において、コントロールの効きにくい媒体でもあるように感じます。とりあげるトピックや文章に堅牢
性やまとまりがより求められることに、なにか異質なものを憶えずにいられないのです。
もっともこれは Web において、編集という行為の重要性があまり認識されていないことに端を発するの
かもしれません。情報の質・信頼性がそこまで問われず、さらに早い者勝ちという性質が見え隠れするよう
に思うのです。この点で、まとまりのある Web サイトを作り、それを出版するという Dive Into HTML5/
HTML5: Up and Running はとても面白く感じています。電子書籍という物理媒体を伴わないコンテンツも
ふたたび注目されているなか、媒体が持つ性質の差異も今後は小さくなり、互いのよいところを取り込むよ
うに進化していってほしいと思っています。
最後に、Dive Into HTML5 を見つけたのは 2009 年 8 月。これは翻訳したいと思い、実際にとりかかった
ことがありました。しかし、彼の文体や英語の言葉遊び( Video in a Flash (Without That Other Thing)
など)をうまく訳せず断念したのでした。しかし、昨年夏に日本語版の出版に向けた評価をさせていただ
き、さらには本書の監訳という機会に恵まれました。立場は異なるものの、関われたことをとても嬉しく
思っています。
2011 年 3 月
27 歳まであと数日という週半ばの日に
矢倉 眞隆
vii
まえがき
はじめに
HTML5 と は 何 だ ろ う か。HTML5 は 次 世 代 の HTML で あ り、HTML 4.01、XHTML 1.0、 そ し て
XHTML 1.1 を置き換えるものだ。HTML5 では、最新の Web アプリケーションに必要となる数々の新機
能が提供されている。また、何年もの間 Web 開発者が使い続けてきたが、今まで標準化はおろか文書化も
されていなかった Web プラットフォームの多くの機能が標準化されている。(今まで Window オブジェクト
が公式に文書化されていなかったと聞いて、びっくりする読者も多いのではないだろうか。新機能に加え
て、HTML5 は Web ブラウザが長年サポートし続けてきた「デファクト」標準の多くを公式に文書化しよ
うという初めての試みでもある。)
HTML5 は、これまでの HTML と同様に、クロスプラットフォームでの動作を念頭に設計されている。
Windows や Mac OS X や Linux や Multics や、その他特定の OS を使わなくては HTML5 が利用できない、
などということはない。ただひとつ必要なのは、最新のウェブブラウザだ。多くの主要な OS 上では各種の
最新のブラウザがフリーで利用できる。あなたが使っているブラウザも、HTML5 の機能の一部をサポート
しているかもしれない。Apple Safari、Google Chrome、Mozilla Firefox、そして Opera の最新バージョ
ンは多くの HTML5 機能をサポートしている。(より詳しいブラウザ互換表は、以降の章で随時提供する。)
iPhone、iPad、そして Android 携帯電話にプリインストールされているモバイル Web ブラウザの HTML5
サポート状況も優秀だ。Microsoft でさえ、これから公開される Internet Explorer のバージョン 9 では
HTML5 の機能の一部をサポートするとアナウンスしているのだ。
本書では、次の 8 つの話題を取り上げる。
●
<header>、<footer>、そして <section> などの新たな意味要素(3 章)
●
JavaScript でプログラム可能な 2 次元の図形描画機能、Canvas(4 章)
●
サードパーティ製プラグインの助けを借りずに Web へ埋め込み可能なビデオ(5 章)
●
Web アプリケーションへ、自分の居る位置を通知できる位置情報通知機能(6 章)
●
サードパーティ製プラグインを必要としない永続的ローカルストレージ(7 章)
まえがき
viii
●
ネットワークアクセスが切断された後でも動作可能なオフライン Web アプリケーション(8 章)
●
改良された HTML フォーム(9 章)
●
HTML5 にはない語彙を作成し、Web ページに独自の意味づけが可能なマイクロデータ
HTML5 は、可能な限り既存の Web ブラウザとの後方互換性を考慮して設計されている。新機能は既存
の機能の上に構築されており、古いブラウザには代替コンテンツを提供できるようになっている。さらに
高度な制御が必要なら、数行の JavaScript を書くだけで各 HTML5 機能のサポート状況を検出することも
できる(2 章)。ブラウザが HTML5 をサポートしているかどうか判断するために、脆弱なブラウザスニッ
フィングに頼ってはならない。そうではなく、HTML5 そのものを使って必要な機能がサポートされている
かどうかテストすべきなのだ。
本書の表記
本書では、原則として次の表記方法を採用している。
太字(Bold)
新しい用語や重要な用語などを示す。
等幅(Constant width)
プログラムリストや、本文中でプログラム要素(変数名、関数名、データベース、データ型、環境
変数、文、キーワードなど)、ファイル名、そしてファイル拡張子を表記するために使われる。
等幅太字(Constant width bold)
ユーザが入力すべきコマンドやその他のテキストを示す。
等幅斜体(Constant width italic )
ユーザの入力する値、または文脈に依存する値で置き換えられるべきテキストを示す。
このアイコンはヒント、提案あるいは一般的な注意事項を示す。
このアイコンは警告、または注意が必要であることを示す。
サンプルコードの使用について
本書の目的はあなたの仕事の手助けをすることだ。基本的に、本書に掲載しているコードをあなたのプロ
グラムや文書に使用してもかまわない。コードの大部分を転載する場合を除き、許可を求める必要はない。
例えば、本書のコードの一部を使ったプログラムを作成するために、許可を求める必要はない。なお、オラ
イリー・ジャパンから出版されている書籍のサンプルコードを CD-ROM として販売・配布する場合には、
まえがき
ix
そのための許可が必要である。本書や本書のサンプルコードを引用して質問に答える場合にも、許可を求め
る必要はない。ただし、本書のサンプルコードのかなりの部分を製品マニュアルに転記するような場合に
は、そのための許可が必要である。
出典を明記する必要はないが、そうしていただければうれしい。出典には Mark Pilgrim 著『入門
HTML5』(オライリー・ジャパン刊)のように、著者、タイトル、出版社などを記載していただきたい。
サンプルコードの使用について、上記で許可している範囲を超えると感じる場合は、permissions@oreilly.
com まで(英語で)ご連絡をいただきたい。
本書の出版形態について
本書は、著者の管理する http://diveintohtml5.info/ 上の HTML5 のソースから作成されている。電子書
籍( http://oreilly.com/catalog/9780596806033/ ) お よ び Safari Books Online( http://my.safaribooks
online.com/9781449392154 )版にはソースにあったハイパーリンクがすべて含まれているが、書籍版には
ハイパーリンクの一部(カッコ内の URL という形で)しか含まれていない。豊富なリンクの恩恵を受ける
ため、書籍版の読者には、電子書籍版、または元のソースを参照することをおすすめする。著者は http://
diveintohtml5.info/ を HTML5 でメンテナンスしているため、このサイトには本書で説明したコードの
実例が掲載されている。これらのコードの多くは、出版のために修正せざるを得なかったものだ。http://
diveintohtml5.info/ でこれらのコード例を参照できるが、その表示はブラウザによって異なる可能性があ
ることには注意してほしい。
本書は『HTML5: Up and Running』の日本語訳であることから、http://diveintohtml5.info/ のソー
スから作成されているわけではない。また、原著をそのまま日本語訳したわけではない。日本語版出版にあ
たっては、原著の内容に適宜訳注を加えるとともに、原著の出版された 2010 年 8 月から 2011 年 3 月
初旬までに http://diveintohtml5.info/ に加えられた変更を反映し、内容を更新している。
質問と意見
本書に関する意見や質問は、以下へ送ってほしい。
株式会社オライリー・ジャパン
〒 160-0002 東京都新宿区坂町 26 番地 27 インテリジェントプラザビル 1F
電話
03-3356-5227
FAX
03-3556-5263
電子メール
[email protected]
本書に関する技術的な質問や意見は、次の宛先に電子メール(英文)を送ってほしい。
[email protected]
x
まえがき
オライリーに関するその他の情報については、次のオライリーの Web サイトを参照してほしい。
http://www.oreilly.co.jp/
http://oreilly.com/
xi
目 次
監訳者まえがき....................................................................................................................v
まえがき..............................................................................................................................vii
1 章.
ここまでの道のり................................................................................................ 1
1.1
2 章.
はじめに ......................................................................................................................1
1.2
MIME タイプ..............................................................................................................1
1.3
標準はどのように作られるか、という長い余談 ......................................................2
1.4
HTML の系譜 .............................................................................................................8
1.5
1997 年から 2004 年までの HTML 策定の歴史 ......................................................10
1.6
XHTML についての誤解 ..........................................................................................11
1.7
対立する構想 .............................................................................................................12
1.8
WHATWG とは ........................................................................................................13
1.9
W3C への復帰 ...........................................................................................................14
1.10
後日談 ........................................................................................................................15
1.11
参考文献 ....................................................................................................................15
HTML5 の機能を検出する............................................................................. 17
2.1
はじめに ....................................................................................................................17
2.2
4 つの検出テクニック ..............................................................................................17
2.3
Modernizr:HTML5 検出ライブラリ ....................................................................18
2.4
Canvas .......................................................................................................................18
2.5
Canvas テキスト .......................................................................................................20
2.6
ビデオ ........................................................................................................................21
2.7
ビデオフォーマット .................................................................................................22
2.8
ローカルストレージ .................................................................................................24
2.9
Web Workers ............................................................................................................26
2.10
オフライン Web アプリケーション .........................................................................26
xii
目次
2.11
3 章.
2.12
input タイプ ..............................................................................................................28
2.13
プレースホルダ .........................................................................................................30
2.14
フォームのオートフォーカス ..................................................................................31
2.15
マイクロデータ .........................................................................................................32
2.16
参考文献 ....................................................................................................................33
HTML 文書の構造と意味付け......................................................................... 35
3.1
5 章.
はじめに ....................................................................................................................35
3.2
DOCTYPE ................................................................................................................35
3.3
ルート要素 ................................................................................................................37
3.4
<head> 要素 ..............................................................................................................38
3.5
4 章.
Geolocation ...............................................................................................................27
3.4.1
文字エンコーティング ................................................................................39
3.4.2
リンクタイプ ...............................................................................................40
HTML5 の新しい意味要素.......................................................................................45
3.6
ブラウザが不明な要素を取り扱う方法についての長い余談 .................................47
3.7
ヘッダ ........................................................................................................................51
3.8
Article 要素 ...............................................................................................................54
3.9
日付と時間 ................................................................................................................56
3.10
ナビゲーション .........................................................................................................58
3.11
フッタ ........................................................................................................................60
3.12
参考文献 ....................................................................................................................62
Canvas による描画........................................................................................ 65
4.1
はじめに ....................................................................................................................65
4.2
単純なシェープ .........................................................................................................66
4.3
Canvas の座標...........................................................................................................68
4.4
パス ............................................................................................................................69
4.5
テキスト ....................................................................................................................73
4.6
グラデーション .........................................................................................................77
4.7
画像 ............................................................................................................................80
4.8
IE の場合 ...................................................................................................................83
4.9
総合的な実例 .............................................................................................................84
4.10
参考文献 ....................................................................................................................89
Web のビデオ................................................................................................... 91
5.1
はじめに ....................................................................................................................91
5.2
ビデオのコンテナ .....................................................................................................91
目次
5.3
5.4
xiii
ビデオコーデック .....................................................................................................93
5.3.1
H.264 ...........................................................................................................94
5.3.2
Theora .........................................................................................................94
5.3.3
VP8 ..............................................................................................................95
オーディオコーデック..............................................................................................95
5.4.1
MPEG-1 Audio Layer 3 ..............................................................................96
5.4.2
Advanced Audio Coding ............................................................................97
5.4.3
Vorbis ..........................................................................................................98
5.5
Web 上で利用可能な組み合わせ .............................................................................98
5.6
H.264 ビデオのライセンス事情 .............................................................................100
5.7
Miro Video Converter によるビデオのエンコード .............................................102
5.8
Firefogg による Ogg ビデオのエンコード ...........................................................106
5.9
ffmpeg2theora を使った Ogg ビデオのバッチエンコード .................................114
5.10
HandBrake を使った H.264 ビデオのエンコード................................................115
5.11
HandBrake を使った H.264 ビデオのバッチエンコード ....................................121
5.12
ffmpeg を使った WebM のエンコード .................................................................122
5.13
そして、マークアップへ ........................................................................................124
5.13.1 MIME タイプが引き起こす可能性のある問題 .......................................127
6 章.
5.14
IE の場合 .................................................................................................................128
5.15
iPhone と iPad の問題 ............................................................................................129
5.16
Android 端末の問題 ...............................................................................................129
5.17
総合的な実例 ...........................................................................................................130
5.18
参考文献 ..................................................................................................................131
Geolocation.API による位置情報通知..................................................... 133
6.1
7 章.
.
はじめに ..................................................................................................................133
6.2
Geolocation API .....................................................................................................133
6.3
実際のコード ...........................................................................................................134
6.4
エラー処理 ..............................................................................................................136
6.5
選択の自由 ..............................................................................................................137
6.6
IE の場合 .................................................................................................................138
6.7
geo.js に助けを求める ............................................................................................140
6.8
総合的な実例 ...........................................................................................................141
6.9
参考文献 ..................................................................................................................142
Web アプリケーションのローカルストレージ:その過去・現在・未来
..................................................................................................................... 145
7.1
はじめに ..................................................................................................................145
xiv
目次
7.2
8 章.
9 章.
HTML5 以前のローカルストレージハック ..........................................................146
7.3
HTML5 ストレージ入門 ........................................................................................147
7.4
HTML5 ストレージの使用.....................................................................................148
7.4.1
HTML5 ストレージ領域の変化を検出する ............................................149
7.4.2
現在のブラウザによる制限 ......................................................................150
7.5
HTML5 ストレージの実例.....................................................................................150
7.6
名前付きキーと値のペアを超えて:競合する構想 ..............................................152
7.7
参考文献 ..................................................................................................................154
オフライン状態での動作............................................................................... 157
8.1
はじめに ..................................................................................................................157
8.2
キャッシュマニフェスト ........................................................................................158
8.2.1
NETWORK セクション ...........................................................................160
8.2.2
FALLBACK セクション ...........................................................................160
8.3
イベントの流れ .......................................................................................................162
8.4
デバッグの手法 .......................................................................................................163
8.5
実際に作ってみる ...................................................................................................166
8.6
参考文献 ..................................................................................................................167
Web フォーム................................................................................................ 169
9.1
はじめに ..................................................................................................................169
9.2
プレースホルダ .......................................................................................................169
9.3
フィールドへのオートフォーカス .........................................................................170
9.3.1
できるだけ早くフォーカスを設定する ...................................................172
9.4
メールアドレス .......................................................................................................174
9.5
Web アドレス..........................................................................................................175
9.6
スピンボックスによる数値の入力 .........................................................................176
9.7
スライダによる数値の入力 ....................................................................................179
9.8
デートピッカー .......................................................................................................179
9.9
検索ボックス ...........................................................................................................182
9.10
カラーピッカー .......................................................................................................183
9.11
フォームの検証 .......................................................................................................184
9.12
入力必須フィールド ...............................................................................................186
9.13
参考文献 ..................................................................................................................187
10 章. マイクロデータによるマークアップの拡張................................................ 189
10.1
はじめに ..................................................................................................................189
10.2
マイクロデータとは ...............................................................................................190
目次
xv
10.3
マイクロデータのデータモデル.............................................................................191
10.4
人物のマークアップ ...............................................................................................194
10.4.1 Google リッチスニペットの紹介.............................................................200
10.5
会社や組織のマークアップ ....................................................................................202
10.6
イベントのマークアップ ........................................................................................207
10.7
レビューをマークアップする ................................................................................213
10.8
参考文献 ..................................................................................................................217
10.6.1 Google リッチスニペット、ふたたび .....................................................211
付録 A. (ほぼ)アルファベット順の HTML5 機能検出方法................................. 219
A.1
要素の一覧 ..............................................................................................................219
A.2
参考文献 ..................................................................................................................227
索引................................................................................................................................. 229
1
1章
ここまでの道のり
1.1 はじめに
以下は、標準規格の策定に付きまとうある種の緊張関係について Mozilla の開発者が書いた文章だ†。
実装と仕様との間には、微妙な関係を保つ必要がある。仕様が完成する前に実装が行われることは望ま
しくない。なぜならば、既存の実装の詳細に引きずられ、仕様が制約されてしまうからだ。しかし、実
装されたものが利用されないまま仕様が完成することもまた望ましくない。なぜならば、利用者から
のフィードバックが必要だからだ。このような緊張関係は避けられないものだが、いずれにしろ何とか
やって行くしかない。
この言葉を、心の片隅に留めておいてほしい。さあ、HTML5 が出現するまでの道のりについて説明して
行こう。
1.2 MIME タイプ
本書は HTML5 について書いている。それ以前のバージョンの HTML や、XHTML は範囲外だ。しかし
HTML5 の歴史とその背後にある動機を理解するためにはまず、いくつかの技術的な概念を知っておく必要
がある。そのひとつが、MIME タイプだ。
Web ブラウザがページを要求するたびに、Web サーバは実際のページを送信する前に大量のヘッダを送
信してくる。これらのヘッダは通常ユーザの目に触れることはないが、興味があれば目に見えるようにして
くれる Web 開発ツールも数多くある。このヘッダが重要なのは、その後に続くページを解釈する方法をブ
ラウザに教えてくれるからだ。最も重要なヘッダは Content-Type と呼ばれるものであり、具体的には以下
のようなかたちをしている。
Content-Type: text/html
text/html は、このページの「コンテントタイプ」または「MIME タイプ」と呼ばれる。このヘッダは、
そのリソースが実際には何であって、したがってどのように表示されるべきかを指し示す、唯一のものだ。
†
http://lists.w3.org/Archives/Public/public-html/2010Jan/0107.html を参照。
2
1 章 ここまでの道のり
画像にはそれ特有の MIME タイプ(JPEG 画像には image/jpeg、PNG 画像には image/png など)がある。
JavaScript ファイルにもそれ特有の MIME タイプがある。CSS スタイルシートにもそれ特有の MIME タ
イプがある。すべてのものに、それ特有の MIME タイプがある。Web は MIME タイプによって動いてい
るのだ。
もちろん、現実はこれよりももっと複雑にできている。ごく初期の Web サーバ(ここで私が言っている
のは 1993 年頃の Web サーバだ)は、Content-Type ヘッダを送信していなかった。まだ存在していなかっ
たからだ(ヘッダが誕生したのは 1994 年のことだ)。1993 年にまでさかのぼる互換性の問題のため、よ
く使われている Web ブラウザの中には一定の条件下で Content-Type ヘッダを無視するものがある(これ
を「コンテントスニッフィング」という)。しかし、たいていは Web 上で見かけるすべてのもの、つまり
HTML ページ、画像、スクリプト、ビデオ、PDF など URL の付いたすべてのものは、Content-Type ヘッ
ダにそれ特有の MIME タイプが設定されていると思って間違いない。
このことを、よく覚えておいてほしい。後でまた、ここへ戻ってくることになるからだ。
1.3 標準はどのように作られるか、という長い余談
なぜ <img> 要素は存在するのだろうか。聞くこともめったにない疑問だろうが、もちろん、誰かが考え出
したはずだ。何もないところから生まれてくるわけはない。すべての要素、すべての属性、そして今まで使
われてきたすべての HTML の機能は、誰かが考え出し、使い方を決め、そしてそれを文書にしたから存在
するのだ。そういう人たちだって神様ではないから、間違うことだってある。彼らも人間だ。賢い人間であ
ることは確かだ。しかし、ただの人間なのだ。
「開かれた形で」決められる標準のすばらしい点のひとつは、時間をさかのぼってこのような質問に答え
ることができるということだ。メーリングリストで行われた議論は、たいていアーカイブされ、誰でも検
索できるようになっている。そこで私は、<img> 要素の疑問に答えるために、一種の「電子メール考古学」
を行ってみることにした。<img> 要素の起源を知るためには、W3C(World Wide Web Consortium)と呼
ばれる組織が誕生するよりも前までさかのぼらなくてはならなかった。そうして、私は Web のごく初期、
Web サーバが両手の指(もしかすると足の指も必要かもしれない)で数えられるほどの時代にたどり着い
た。
1993 年 2 月 25 日、Marc Andreessen は以下のように書いている†。
新しい HTML タグを提案したい。
名前は IMG。
引数として SRC="url" を必要とする。
このタグはビットマップまたは pixmap ファイルをネットワーク経由で取得し、それを画像として解釈
してテキスト中のタグが記述された場所に埋め込むことをブラウザに指示する。
使用例は以下のとおり。
<IMG SRC="file://foobar.com/foo/bar/blargh.xbm">
†
http://1997.webhistory.org/www.lists/www-talk.1993q1/0182.html。 以 下 の 数 ペ ー ジ で 解 説 す る ス レ ッ ド は、「Next
message」と「Previous Message」というリンクをクリックして表示できる。
1.3 標準はどのように作られるか、という長い余談
3
(終了タグは存在しない。これは独立タグだ。)
このタグは、他と同じようにリンクの中へ埋め込むことができる。その場合、通常のテキストリンクと
同じような反応を示すアイコンとなる。
ブラウザは、サポートする画像フォーマットについて柔軟であるべきだ。例えば、Xbm と Xpm はサ
ポートすることが望ましい。渡されたフォーマットをブラウザが解釈できなかった場合、その代わり
にどんなことをしてもよい(X Mosaic は代替情報として、デフォルトで持っているプレースホルダの
ビットマップを表示する)。
これは X Mosaic に必要とされた機能だ。われわれはこの機能をすでに実装し、少なくとも内部では使
うつもりでいる。HTML でこの要素がどのように扱われるべきか、ぜひ意見を聞かせてほしい。私の
提案よりもよいアイディアがあれば、教えてほしい。画像フォーマットについて曖昧なところがあるの
は承知しているが、私には「ブラウザにできることをしてもらう」以外のことを思いつかなかった。完
璧なソリューションが登場するのを待っている(MIME になるかもしれないね)。
このメールについて、多少の説明が必要だろう。Xbm と Xpm は、当時の Unix システム上の一般的な画
像フォーマットだった。
「Mosaic」とは、最も初期の Web ブラウザのひとつだ。(「X Mosaic」は Unix システム上で動作するバー
ジョン。)Marc がこのメッセージを書いた 1993 年初頭には、彼を有名にした Mosaic Communications
Corporation はまだ創立されておらず、またこの会社の主力商品である「Mosaic Netscape」の開発も行わ
れていなかった。(後の「Netscape Corporation」や「Netscape Navigator」という名前に聞き覚えがある
人の方が多いだろうか。)
「MIME になるかもしれないね」という発言は、コンテントネゴシエーションのことを指している。こ
れは、(Web ブラウザのような)クライアントが、(Web サーバのような)サーバに、サポートしているリ
ソースの種類(例えば image/jpeg)を通知するための HTTP の機能だ。これによってサーバはクライアン
トが望む形式のものを返すことができる。1991 年に定義されたオリジナルの HTTP(1993 年 2 月時点で実
装されていた唯一のバージョン)では、クライアントがサポートしている画像の種類をサーバに通知する手
段は存在しなかったので、Marc はこのような設計上のジレンマに直面したわけだ。
数時間後、Tony Johnson が以下のように返信した。
よく似たことを Midas 2.0 でも行っている(ここ SLAC ではすでに使われていて、数週間のうちに公
開する予定だ)。ただしタグや引数の名前は違うし、NAME="name" という引数が追加されている。機能
的には、君の提案した IMG タグとほとんど同じだ。
<ICON name="NoEntry" href="http://note/foo/bar/NoEntry.xbm">
name 引数は、ブラウザが「組み込み」画像を使えるようにするためのものだ。name が「組み込み」
画像と一致した場合には、外部に画像を取りに行くことなく、組み込み画像を使えばよい。また name
は、「ラインモード」ブラウザ†が画像の代わりにどのシンボルを使うか決める際のヒントにもなる。
†
訳注:ラインモードブラウザ(Line-mode browser)はコマンドラインから操作するウェブブラウザ。
4
1 章 ここまでの道のり
私は引数やタグの名前にこだわらないが、統一することには意味があるだろう。タグの名前を略すかに
もこだわらないので、IMAGE= とか SOURCE= になっても構わない。私がなんとなく ICON という名前を気
に入っているのは IMAGE より小ぶりの画像を想定させるからなのだが、ICON という言葉は使われすぎ
かも知れないね。
Midas は、X Mosaic と同時期の、もうひとつの初期の Web ブラウザだ。クロスプラットフォームで、
Unix と VMS の両方で動作した。「SLAC」は Stanford Linear Accelerator Center(スタンフォード線形加
速器センター、現在の SLAC 国立加速器研究所)のことで、米国内で最初の(というより、ヨーロッパ以
外で最初の)Web サーバをホストしていた。Tony がこのメッセージを書いたとき、SLAC は WWW の長
老格だった。Web サーバ上で 5 つのページを、なんと 441 日間もホストし続けていたのだ。
Tony は以下のように続けている。
新しいタグという話では、私は Midas 2.0 でもうひとつ、似たようなタグをサポートしようと思ってい
る。基本的には次のようなものだ。
<INCLUDE HREF="...">
これは、2 番目の文書が最初の文書へ、タグが記述された場所に挿入されるという意味になる。基
本的には参照される文書は何でもよいが、主な目的は画像(この場合には任意の大きさ)を文書
に埋め込むことだ。また HTTP2 が制定された際には、挿入される文書の形式は別個にネゴシエー
ションされることになるだろう。
「HTTP2」とは、1992 年に定義された Basic HTTP のことを指している。1993 年初頭のこの時点では、
まだほとんど実装はされていなかった。この「HTTP2」という名前だったドラフトは、最終的に「HTTP
1.0」として標準化されることになる。HTTP 1.0 にはコンテントネゴシエーションのための要求ヘッダ、つ
まり「MIME になるかもしれないね」が含まれていた。
Tony はさらに続ける。
INCLUDE の代わりに、私が考えていた形式は次のようなものだ。
<A HREF="..." INCLUDE>See photo</A>
<A> タグに機能を詰め込みすぎることには気が進まないが、こうするのは INCLUDE 引数をサポートしな
いブラウザとの互換性を保つためだ。つまり、INCLUDE を理解するブラウザはリンクテキスト(この場
合には「See photo」)を挿入される文書(画像)で置き換える一方で、古いブラウザや低機能のブラ
ウザは INCLUDE タグを完全に無視することになる。
この提案が実装されることはなかったが、画像がない場合にテキストを表示するというアイディアはアク
セシビリティ上重要な仕組みであり、Marc の最初の <IMG> の提案には欠けていたものだ。何年も後になっ
1.3 標準はどのように作られるか、という長い余談
5
てこの機能は <img alt> 属性として追加されたが、Netscape はこれを誤ってツールチップとして扱ったた
め、混乱を招くこととなった。
Tony がメッセージを投稿してから数時間後、Tim Berners-Lee がこう応じた。
私は、以下のように図を表示できたらいいのに、と思っていた。
<a name=fig1 href="fghjkdfghj" REL="EMBED, PRESENT">Figure </a>
REL の値は、以下のような意味だ。
EMBED
表示する際にこれを埋め込む
PRESENT
ソース文書を表示する際には必ずこれを表示する
いろいろな組み合わせが考えられるが、ブラウザがそのうちどれかをサポートしていなかったとして
も、混乱は生じない。
アイコンを選択する方法としてこれを使うと、アンカーが入れ子になってしまうな。うーん。でも特別
なタグを増やしたくはない。
この提案が実装されることはなかったが、rel 属性は今でも使われている(「3.4.2 フレンドと(リンクの)
関連」を参照)。
Jim Davis も続く。
コンテントタイプを指定する方法があればいいと思う。例えば次のように。
<IMG HREF="http://nsa.gov/pub/sounds/gorby.au" CONTENT-TYPE=audio/basic>
でも、コンテントタイプをファイル拡張子で指定するというんだったら、それでもいい。
この提案もまた実装されることはなかったが、Netscape は後に任意のメディアオブジェクトの埋め込み
を <embed> 要素でサポートすることになった。
Jay C. Weber が質問する。
画像は WWW ブラウザでサポートしてほしいメディアタイプの筆頭だが、メディアごとに独自のフッ
クを追加するべきではないと思う。MIME タイプの仕組みを使うという話はどうなったんだ?
Marc Andreessen の回答。
これは、標準的な文書の仕組みとして MIME をこれから使って行こうという話に取って代わるもので
はない。MIME とは関係なく、必要となる機能を簡単に実装するためのものだ。
6
1 章 ここまでの道のり
Jay C. Weber が応酬する。
話がややこしくなりそうなので、いったん MIME のことは忘れよう。私が言いたかったのは、「画像
の埋め込みをどうやってサポートするか」という議論ではなく、「各種のメディアでオブジェクトの埋
め込みをどうやってサポートするか」という議論をしようということだ。
さもないと、来週誰かが音声用に「新しいタグ <AUD SRC="file://foobar.com/foo/bar/blargh.snd">
を追加しよう」などと言い出しかねない。
一般化しても、大してコストはかからないはずだ。
後になってみると、Jay のコメントは核心を突いていた。このメールの翌週ではなかったが、HTML5 で
は結局、新しい <video> 要素と <audio> 要素が追加されることになったからだ。
Jay の元のメッセージへの返信として、Dave Raggett が次のように発言した。
全くそのとおりだ。あり得るすべての画像やラインアートのタイプと、フォーマットネゴシエーション
の可能性を検討してみたい。画像中のクリック可能な領域をサポートする Tim のコメントも重要だ。
1993 年の後半になって、Dave は HTML 標準の進化形として HTML+ を提案した。この提案もまた実装
されることはなく、HTML 2.0 で置き換えられることになった。HTML 2.0 は「レトロスペック」、つまり
すでに一般に使われていた機能を公認したものだった。HTML 2.0 仕様書には「この規格は 1994 年 6 月以
前に、広く使われていた HTML の機能を取りまとめ、明確化し、公認したものだ」と書かれている。
その後、Dave は HTML+ のドラフトをベースとして、HTML 3.0 を書いた。しかし、W3C 自身の参考
実装である Arena を除き、HTML 3.0 が実装されることはなく、仕様も HTML 3.2 によって置き換えられ
ることになった。HTML 3.2 もまた、「レトロスペック」だった。仕様書には「HTML 3.2 はテーブル、ア
プレット、画像の周りへのテキストの流し込みなどの広く使われている機能を追加し、既存の標準である
HTML 2.0 との完全な後方互換性を提供する」と書かれている。
その後 Dave は HTML 4.0 の共著者となり、HTML Tidy を開発し、XHTML、XForms、MathML をは
じめ、その他の新しい W3C 規格にも関わることになった。
1993 年に戻ろう。Marc は Dave に以下のように返答している。
そうだな。アイコンや画像、またはテキスト、あるいはその他何にでもハイパーリンクを付加して埋め
込むことができる、汎用手続き型グラフィックス言語について考えるべきなのかもしれない。これに関
する Intermedia の機能を知っている人はいるかい?
Intermedia とは、ブラウン大学のハイパーテキストプロジェクトだ。1985 年から 1991 年まで開発され、
初期のマッキントッシュで動く A/UX という Unix ライクな OS 上で動作していた。
「汎用手続き型グラフィックス言語」というアイディアは、最終的に受け入れられることになった。最近
のブラウザは SVG(埋め込みスクリプトによる宣言型マークアップ)および <canvas>(手続き型ダイレク
トモードグラフィックス API)をサポートしている。後者は、WHATWG で「レトロスペック」化される
1.3 標準はどのように作られるか、という長い余談
7
以前より、独自拡張として存在していたものだ。
Bill Janssen の返信はこうだ。
こ の( か な り 有 用 な ) 概 念 を 持 つ シ ス テ ム と し て、 他 に も Andrew と Slate を 見 て お く べ き だ。
Andrew は「インセット」から構築されていて、それぞれのインセットは、テキスト、ビットマップ、
線画、アニメーション、メッセージ、スプレッドシートなどのタイプを持っている。任意の再帰的埋め
込みという概念があり、どんな種類のインセットでも、埋め込みをサポートしたどんな別の種類のイン
セットにも埋め込むことができる。例えば、インセットはテキストウィジェットのテキスト中のどこに
でも、または線画ウィジェットのどんな矩形領域にも、あるいはスプレッドシートのどのセルにも、埋
め込むことができる。
「Andrew」とは Andrew User Interface System のことで、当時は単に Andrew Project として知られて
いた。
一方、Thomas Fine がまた別のアイディアを提案している。
これは私の意見だ。WWW で画像を扱う最善の方法は、MIME を使うことだ。確か postscript は
MIME のサブタイプをすでにサポートしていたはずだし、テキストとグラフィックスを一緒に取り扱
うことを得意としている。
でもクリック可能ではないだろう、だって?確かにそのとおりだ。でもすでにその答えは、display
postscript の中にあるんじゃないかと思う。仮になかったとしても、標準的な postscript に追加するこ
とは簡単だ。URL を指定し、閉領域をなす現在のパスをボタンとして使用するアンカーコマンドを定
義すればいい。postscript はパスの取り扱いに長けているので、どんな形のボタンも簡単に作れる。
Display PostScript は、Adobe と NeXT によって共同開発された画面表示技術だ。
この提案が実装されることもなかったが、HTML を改良する最善の方法は何か別のもので完全に置き換
えてしまうことだ、というアイディアはその後もたびたび提案されている。
1993 年 3 月 2 日、Tim Berners-Lee が以下のようにコメントしている。
HTTP2 は、登録済みの MIME タイプだけではなく、ユーザが取り扱えると宣言した任意のタイプを
文書が含むことを許している。だから、実験してみればいい。もちろん、postscript をハイパーテキス
トと一緒に使うこともできるだろう。display postscript に十分な機能があるかどうかはよく知らない。
Adobe は postscript をベースとして、リンク機能を持ち、彼らが提供する専用の表示ソフトを使って
読むことができる独自の「PDF」を作り上げようとしているらしい。
アンカーをオーバレイする一般的な言語(HyTime ベースか?)を使えば、ハイパーテキスト標準とグ
ラフィックスやビデオの標準を別々に進化させることができるし、それは両方にとってよいことだと思
う。
IMG タグは INCLUDE として、任意の文書タイプを参照できるようにしよう。INCLUDE が C プリプロセッ
サの include 文と紛らわしいなら、EMBED でもいい。SGML ソースコードがインラインでパースされる
1 章 ここまでの道のり
8
なんてことを期待してほしくないからだ。
HyTime は初期の SGML ベースのハイパーテキスト文書システムで、HTML の初期の議論や、その後の
XML の議論によく登場する。
Tim の <INCLUDE> タグに関する提案が実装されることはなかったが、その影響は <object>、<embed>、
<iframe> 要素に見て取ることができる。
さて、1993 年 3 月 12 日、Marc Andreessen がこのスレッドに舞い戻り、以下のように述べた。
インライン画像の話に戻ろう。もうすぐリリースする予定の Mosaic v0.10 では、前に話したとおり、
インライン GIF 画像と XBM ビットマップがサポートされている。(中略)
今のところ、INCLUDE や EMBED をサポートする準備はできていない。(中略)したがって、<IMG SRC=”
url”> を使うことになる(すべてのインライン画像がアイコンと呼べるわけではないので、ICON は採用
しなかった)。現時点では、インライン画像へ明示的にコンテントタイプを指定することはできない。
将来はサポート予定だ(MIME の一般的な採用とあわせるだろう)。実は、現在使っている画像読み込
みルーチンは画像フォーマットをその場で判断するので、ファイル拡張子は意味を持たない。
1.4 HTML の系譜
これら 17 年前のやり取りのすべてが、今までに公開された Web ページのほぼすべてに使われているで
あろう HTML 要素の成り立ちを伝えている。このことが私をひきつけてやまない。次のことを考えてみて
ほしい。
●
HTTP は今でも使われている。0.9 から 1.0 へ、そして 1.1 へと進化し、今でも進化は続いてい
る†。
●
HTML は今でも使われている。この、単純なデータ形式(当初はインライン画像すらサポートし
ていなかったのだ!)は 2.0 へ、3.2 へ、そして 4.0 へと進化して行った。HTML の系譜は、脈々
と受け継がれている。確かにそれは途中でねじれたり、からんだり、もつれたりしているし、その
系統樹の中には「枯れ枝」もたくさんある。そこは標準化を進めていた人々が、(ページ作成者や
実装者を差し置いて)ちょっと先走りすぎてしまった場所だ。しかし 2010 年の現在でも、1990 年
に作成された Web ページは最近のブラウザで表示できる。試しに最先端の Android 携帯電話のブ
ラウザで表示させてみたが、「古い形式のファイルを読み込んでいます」などというメッセージが
表示されることもない。
●
HTML は常にブラウザメーカーとページ作成者、標準化マニア、そしてたまたまそこへ居合わせ
てマークアップについて意見を言いたくなった人々の、話し合いから作られてきた。HTML の成
功したバージョンはほとんど「レトロスペック」で、現実に追従すると同時に正しい方向へ導こ
うとする努力の賜物だ。HTML は「純粋」でなくてはいけないと主張する人々(おそらくブラウ
ザメーカーかページ作成者、あるいはその両方を無視することになる)は、単純に間違っている。
†
http://www.ietf.org/dyn/wg/charter/httpbis-charter.html を参照。
1.4 HTML の系譜
9
HTML は今まで一度も純粋であったためしはないし、純粋にしようという試みはすべてとんでも
ない失敗で、後続によって置き換えられるだけに終わっている。
●
1993 年に使われていたブラウザで、現在もそれとわかる姿で生き残っているものはひとつもな
い。Netscape Navigator は 1998 年に廃棄され、ゼロから書き直され Mozilla Suite となり、そこ
から Firefox が派生した。Internet Explorer は「Microsoft Plus! for Windows 95」として慎まし
やかな「始まり」にあって、デスクトップテーマやピンボールゲームとバンドルされていた。もち
ろんさらにその先祖をたどることもできる。
●
1993 年から現在まで使われ続けている OS はいくつかある。しかしどれも最近の Web とは関係
ない。現在では Web を「経験」する人々の大部分が Windows 2000 以降の PC や Mac OS X、
Linux のディストリビューションのどれか、あるいは iPhone のような携帯端末を使っている。
1993 年には Windows のバージョンは 3.1 だった(そして OS/2 と覇権を争っていた)し、Mac
は System 7 だったし、Linux は Usenet から配布されていたのだ。(面白い話を聞きたかったら、
当時の生き残りを探して耳元で「Trumpet Winsock」とか「Mac PPP」とか、ささやいてみると
いい。)
●
当時活躍していた人々の一部は今でも活動を続けていて、いわゆる「Web 標準」と呼ばれるもの
に関わり続けている。およそ 20 年の年月を隔てた現在でもだ。また、HTML のさらに前身に、
1980 年代やそれ以前から関わってきた人々もいる。
●
HTML の前身について言えば…。HTML と Web がこれほど普及した現在では、これらに影響
を与えた同時代のフォーマットやシステムは忘れられてしまいがちだ。この章を読む前に、
Andrew、Intermedia、あるいは HyTime を知っていた読者はどれだけいるだろうか。HyTime は、
カビの生えた学術研究プロジェクトなんてものではなかった。軍事利用目的で ISO 標準に採用さ
れ、大きな影響力を持っていたのだ。これ(http://www.sgmlsource.com/history/hthist.htm)
を読んで自分で確かめてみるといい。
しかし、上記のどれを取っても、なぜ <img> 要素があるのか、という質問の答えにはなっていない。なぜ
<icon> 要素でも <include> 要素でも、ハイパーリンクに include 属性や rel の値の組み合わせを指定する
方法でもなく、<img> 要素なのだろうか。答えはごく簡単だ。Marc Andreessen がそれを製品としてリリー
スしたからだ。コードをリリースしたもの勝ちなのだ。
もちろん、製品としてリリースされたすべてのコードが勝つ、と言っているわけではない。結局、
Andrew や Intermedia や HyTime もリリースされた製品だったわけだ。成功のために製品は必要だが、そ
れだけで十分ではない。また私は決して、標準が形成される前に製品としてリリースすることが最善の解決
策だ、と言っているわけではない。Marc の <img> 要素は共通のグラフィックス形式を要求しなかったし、
その周りにどうテキストが回りこむかも定義していなかったし、代替テキストや古いブラウザのための代替
コンテンツもサポートしていなかった。そして 17 年後の今、われわれはいまだにコンテントスニッフィン
グにてこずっており、思いもしなかったようなセキュリティ脆弱性の源ともなっている。これらの現況は
すべて、大ブラウザ戦争の時代をさかのぼり、1993 年 2 月 25 日に Marc Andreessen がいみじくも語った
1 章 ここまでの道のり
10
「MIME になるかもしれないね」という言葉と、その後とにかくコードを出荷したことに、結局は行き着く
のだ。
1.5 1997 年から 2004 年までの HTML 策定の歴史
1997 年 12 月、W3C は HTML 4.0 を公開し、その直後に HTML ワーキンググループを終了した。2 か
月もたたないうちに、別の W3C ワーキンググループが XML 1.0 を公開した。それからわずか 3 か月後、
W3C は「W3C は HTML をやめてしまうのか?」という疑問に答えるため、「HTML の将来を形作る」と
題したワークショップを開催した。これがその答えだ。
議論の中で、HTML 4.0 をさらに拡張することも、4.0 を XML アプリケーションに変換することも困
難だという合意に至った。これらの制約から逃れるために提案された方法は、XML タグセットのス
イートをベースとして、次世代の HTML を新しく作り上げるというものだった。
W3C は、この「XML タグセットのスイート」を作成するため、HTML ワーキンググループの再設立を
認可した。1998 年 12 月には活動の第一歩として、HTML を XML で再定義した暫定仕様が公開された。
この仕様は新しい要素や属性を一切追加せず単純な再定義に徹しており、後に「XHTML 1.0」として知ら
れることになる。また、この仕様では、XHTML 文書のための新しい MIME タイプとして application/
xhtml+xml を定義していた。しかし、既存の HTML 4 で書かれたページの移行を容易にするため、同時に
「既存の HTML ユーザエージェント上で XHTML 文書を表示させるためのページ作成者向けデザインの
手引きを要約」した附属書 C も含まれていた。附属書 C には、いわゆる「XHTML」ページを作成しても
text/html MIME タイプを使ってよい、と書かれていた。
次の目標はフォームの改訂だった。1999 年 8 月、同じ HTML ワーキンググループが XHTML 拡張
フォームの最初のドラフトを発行した。この文書(http://www.w3.org/TR/1999/WD-xhtml-forms-req-
19990830#intro)の最初の文章に、メンバーの期待が記されている。
熟慮の結果、HTML ワーキンググループは、次世代フォームの目標と、以前のバージョンの HTML 用
に設計されたブラウザとの後方互換性を維持することとは相容れない、という結論に達した。適切に定
義された要求条件を元に、クリーンな新しいフォームのモデル(「XHTML 拡張フォーム」)を提供する
ことが、われわれの目的である。この文書に記述された要求条件は、幅広いフォームアプリケーション
の経験に基づいている。
数ヵ月後、「XHTML 拡張フォーム」は「XForms」と改名され、独自のワーキンググループで議論され
ることになった。このグループは HTML ワーキンググループと並行して作業を進め、2003 年 10 月には
XForms 1.0 の初版が公開された。
一方、XML への移行を終えた HTML ワーキンググループのメンバーは、「次世代 HTML」の作成に目を
向けた。2001 年 5 月に初版が発行された XHTML 1.1 は、XHTML 1.0 に少数の小さな機能を付け加えただ
けのものだったが、「附属書 C」という抜け道はふさがれていた。バージョン 1.1 以降、すべての XHTML
文書は MIME タイプ application/xhtml+xml を使うこととなったのだ。
1.6 XHTML についての誤解
11
1.6 XHTML についての誤解
なぜ MIME タイプは重要なのだろうか。なぜ私は、MIME タイプの話ばかりしているのだろうか。それ
は、ドラコニアン(厳格な)エラー処理のためだ。ブラウザは、HTML に関しては間違いに「寛容」だっ
た。うっかり </head> なしの HTML ページを作成しても、ブラウザはそのページをちゃんと表示してくれ
る。(いくつかのタグは、暗黙的に <head> 要素の終了と <body> 要素の開始を行うようになっている。)タグ
は最後に現れたものをまず閉じて階層構造を保たなければならないが、例えば <b><i></b></i> と書いてし
まっても、ブラウザはエラーメッセージを出すことなく、(どうにかして)それを処理している。
気付いている人は多いと思うが、「問題のある」HTML マークアップでも Web ブラウザで表示できてし
まうという事実が、ページ作成者に問題のある HTML ページを作らせてしまう原因となっている。それも
並大抵の数ではない。現在 Web 上の HTML ページの 99 パーセント以上が、少なくともひとつのエラーを
含んでいるという推測もある。しかしそのようなエラーがあってもブラウザは目に見えるエラーメッセージ
を表示することはないため、誰もそれを直そうとはしない。
W3C はこれを Web に関する根本的な問題ととらえ、その修正に乗り出した。1997 年に発行された XML
は、寛容なクライアントという伝統に終止符を打ち、XML を処理するすべてのプログラムはいわゆる「整
形式」に関わるエラーを致命的なエラーとして取り扱うことを定めた。エラーがひとつでもあれば失敗する
というこの考え方は、比較的軽微な法律違反に対しても死刑を課した古代ギリシャの執政官ドラコの名前
をとって、「ドラコニアン(厳格な)エラー処理」と呼ばれるようになった。W3C が HTML を XML の表
現形式で再定義したとき、それに携わった人々は、新しい application/xhtml+xml MIME タイプを使うす
べての文書は厳格なエラー処理をされなくてはならないと定めたのだ。あなたの書いた XHTML ページに
</head> の書き忘れや開始タグと終了タグの書き間違いといったエラーがひとつでもあれば、Web ブラウ
ザはそこで処理を中止し、エンドユーザにエラーメッセージを表示しなくてはならない。
この考えは、広く受け入れられたわけではなかった。既存のページの 99 パーセントがエラーを含んで
いるという推測から、またエンドユーザにエラーを表示してしまう可能性から、さらには XHTML 1.0
と 1.1 にはコストに見合うだけの新機能が欠如していたこともあって、Web ページ作成者は基本的に
application/xhtml+xml を無視したのだ。しかしこれは、彼らが XHTML を完全に無視していたとい
うわけではない。むしろその反対だ。XHTML 1.0 規格の附属書 C が、世界中の Web ページ作成者に
抜け道を用意してくれていたのだ。「文法は XHTML に似せて、でも使う MIME タイプは相変わらず
text/html」というわけだ。またこれは、何千人もの Web 開発者たちが実際にしたことでもある。彼
らは文法を XHTML に「アップグレード」しても、相変わらず text/html MIME タイプを使っていた
のだ。
現在でも、XHTML を称する Web ページは数多くある(最初の行が XHTML 文書タイプ宣言で始まり、
小文字のタグ名を使い、属性値の前後には引用符を付け、そして <br /> や <hr /> などのように空の要素
の後にはスラッシュを付けている)が、XML の厳格なエラー処理を引き起こす application/xhtml+xml
MIME タイプを使っているページはほんのわずかだ。どのような文書タイプ宣言、文法、またはコーディ
ングスタイルを使っていても、text/html MIME タイプを使っているページは「寛容な」HTML パーザに
よってパースされるため、たとえそのページが技術的な問題を含んでいたとしても、マークアップに関する
12
1 章 ここまでの道のり
エラーは静かに無視され、エンドユーザへ(あるいは他の誰にも)通知されることはない。
XHTML 1.0 はこの抜け道を用意していたが、XHTML 1.1 はこれをふさぎ、そしてついに完成されなかっ
た XHTML 2.0 にも、厳格なエラー処理を要求するという伝統は引き継がれた。そしてこれが、XHTML 1.0
を称するページは何十億もあるのに、XHTML 1.1(あるいは XHTML 2.0)を称するページがほんのわず
かしかないことの理由でもある。だから、あなたが本当に XHTML を使っているかどうか、MIME タイプ
をチェックしてみてほしい。(あなたが自分の使っている MIME タイプを知らなかったとしたら、きっと
text/html を使っているはずだ。)MIME タイプ application/xhtml+xml を使っているのでない限り、いわ
ゆる「XHTML」は名前だけの XML なのだ。
1.7 対立する構想
2004 年 6 月に、W3C は Web アプリケーションと複合文書のワークショップを開催した。このワーク
ショップに参加したのは、いくつかのブラウザメーカー、Web 開発会社、そしてその他の W3C のメンバー
だった。Mozilla Foundation と Opera Software を含む関係者のグループは、彼らの考える Web の将来に
ついてプレゼンテーションを行った。それは、既存の HTML 4 標準を進化させ、最新の Web アプリケー
ション開発者向けの機能を追加するという点で、W3C の構想とは対立するものだった†。
以下の 7 つの原則が、最も重要な要求条件だとわれわれは考えている。
後方互換性と明確な移行手段
Web アプリケーション技術は、HTML、CSS、DOM、JavaScript など、ページ作成者にとっ
てなじみ深い技術に基づいているべきである。
基本的な Web アプリケーションの機能は、ページ作成者に明確な移行手段が与えられるよう
に、ビヘイビア、スクリプティング、およびスタイルシートを使って現在の IE6 に実装可能
であるべきだ。どのようなソリューションも、現在高い市場シェアを持つユーザエージェント
でバイナリのプラグインを必要とせずに利用できなければ、成功はおぼつかない。
適切に定義されたエラー処理
Web アプリケーションのエラー処理は、ユーザエージェント(UA)が独自のエラー処理機構
を発明したり、他のユーザエージェントをリバースエンジニアリングする必要がないほどに、
詳細なレベルで定義されなくてはならない。
ユーザがオーサリングエラーに直面しないこと
規格には、起こりうるエラーのすべてに対して、そのエラーからの明確な回復手順が記述され
ていなくてはならない。エラー処理はおおむね、(CSS のように)エラーから回復できるよう
な寛容なものが定義されるべきであり、(XML のように)あからさまに破滅的な失敗を引き
起こすべきではない。
実用性
Web アプリケーション仕様に採用されるすべての機能は、実用的なユースケースをふまえて
†
http://www.w3.org/2004/04/webapps-cdf-ws/papers/opera.html を参照。
1.7 対立する構想
13
盛り込まれなければならない。その逆は必ずしも真ではない。すべてのユースケースが、必ず
しも新しい機能を盛り込む根拠となるわけではない。
ユースケースは、ページ作成者が制限を回避するために苦しまぎれのソリューションを以前使
用していた現実のサイトに基づいていることが望ましい。
スクリプティングは定着している
しかし、もっと便利な宣言的なマークアップが利用できる場合には避けるべきである。
スクリプティングは、機器特有の方法に限定されていない限りは(例えば XBL に含まれてい
ない場合)、機器およびプレゼンテーションから中立であること。
機器固有のプロファイリングは避けるべき
ページ作成者が、同一 UA のデスクトップバージョンとモバイルバージョンとで同じ機能が実
装されていると当てにできるべきである。
オープンなプロセス
今まで Web はオープンな環境で開発されることで利益を得てきた。Web アプリケーションは
Web の中核となるものであり、その仕様策定もまたオープンに行われるべきである。メーリ
ングリスト、アーカイブ、そして仕様の草案は常に公開されるべきである。
非公式投票が行われ、ワークショップの参加者には次のような質問が投げかけられた。「W3C は、中間レ
ベルの Web アプリケーションの要求条件に対処するため、洗練された本格的な OS レベルの API ではなく、
HTML および CSS への宣言的な拡張ならびに必要となる DOM への拡張を開発すべきか?」投票の結果は、
11 対 8 で否決だった。ワークショップのまとめ†の中で、W3C のメンバーは次のように書いている。「3 番
目の非公式投票で触れられた内容に関して、今のところ W3C は、現在の W3C ワーキンググループで開発
されている技術以外に、Web アプリケーション向けの HTML および CSS への拡張のためにリソースを割
くことは全く考えていない。」
この決定に直面して、HTML と HTML フォームの進化を提案してきた人々には、2 つの選択肢しか残
されていなかった。あきらめるか、それとも W3C の枠組みの外で作業を続けるか。彼らは後者を選択し、
whatwg.org というドメインを登録した。そして 2004 年 6 月に、WHATWG が誕生したのだ。
1.8 WHATWG とは
WHATWG とは、いったいなんだろうか? 彼ら自身に説明してもらうことにしよう††。
Web Hypertext Application Technology Working Group (WHATWG) は、緩やかで、非公式で、オー
プンな、Web ブラウザメーカーと関心のある人々の共同作業の場だ。このグループは、互換性のある
Web アプリケーションを容易に展開できるようにするための、HTML をベースとした規格と関連技術
の策定を目的としている。策定する仕様は、標準化団体への提案を考えており、標準化の手続きにした
†
http://www.w3.org/2004/04/webapps-cdf-ws/summary を参照。
††
http://www.whatwg.org/news/start を参照。
14
1 章 ここまでの道のり
がって、公式に HTML を拡張する作業の基礎となるだろう。
このフォーラムは、Web アプリケーション開発技術の策定に関し、過去数ヶ月の間プライベートなメー
ルで行われたものの延長にある。現時点までの議論の中心は、HTML4 フォームを拡張して、既存コン
テンツとの後方互換性を失うことなく、ページ作成者によって必要とされる機能をサポートすること
だった。このグループが設立されたのは、これらの規格の今後の開発が完全にオープンな形で、公開
アーカイブされたオープンなメーリングリストを通して行われることを確約するためだ。
ここで重要なのは、「後方互換性を失うことなく」というフレーズだ。(附属書 C の抜け穴なしの)
XHTML は、HTML と後方互換ではない。全く新しい MIME タイプを必要とし、またその MIME タイプ
を使うすべてのコンテンツに厳格なエラー処理を要求するからだ。XForms も HTML のフォームと後方互
換ではない。新たな XHTML MIME タイプを使う文書の中でのみ使うことができ、したがって同様に厳格
なエラー処理を要求するからだ。すべての道は MIME に通じているのだ。
10 年に及ぶ HTML への投資を無駄にし、また既存 Web ページの 99 パーセントを使えなくする代わり
に、WHATWG は別のアプローチを取ることにした。ブラウザが実際に利用している「寛容な」エラー処
理アルゴリズムを文書化することだ。Web ブラウザは今までもずっと HTML エラーに寛容だったが、その
処理を正確に記述しようとする試みは行われてこなかった。NCSA Mosaic は壊れたページを取り扱うため
の独自のアルゴリズムを持ち、Netscape が追随した。次に Internet Explorer が Netscape に追随した。続
いて Opera と Firefox が Internet Explorer に追随した。さらに Safari が Firefox に追随した。こんな状況
が今まで続いてきたわけだ。その間、開発者たちは自分たちの製品に競合製品と互換性を持たせるため、何
千時間もの時を費やしてきた。
正気の沙汰ではない作業量に聞こえるかもしれない。実際、そうなのだ。いや、そうだった、と言うべき
だろう。何年もの時間がかかったが、
(少数のめったにない極端な場合を除いて)WHATWG は既存の Web
コンテンツと互換性のある形で HTML をパースする方法を文書化することに成功したのだ。結果として得
られたアルゴリズムのどこにも、HTML の消費者が処理を中断してエンドユーザにエラーメッセージを表
示することが要求されている箇所はない。
このリバースエンジニアリングを進めると同時に、WHATWG はひそかに他の作業も進めていた。ひと
つは、HTML フォームに新たなコントロールを追加する、当初 Web Forms 2.0 と命名されていた規格だ。
(フォームについては 9 章で詳しく説明する。)もうひとつは、ダイレクトモードな図形描画機能 Canvas(4
章を参照のこと)やプラグインを必要としないオーディオとビデオのネイティブなサポート(5 章を参照の
こと)などの主要な新機能を含む、「Web Applications 1.0」と呼ばれたドラフト標準だ。
1.9 W3C への復帰
2 年半の間、W3C と WHATWG は互いに無視しあっていた。WHATWG はフォームと HTML の新機能
に注力していたのに対し、W3C の HTML ワーキンググループは XHTML 2.0 に取り組んでいたのだ。しか
し次第に、WHATWG が支持を集める一方で、XHTML 2 はドラフトの状態にとどまり、主要なブラウザ
ではサポートされていないことが誰の目にも明らかになってきた。そして、2006 年 10 月、ついに W3C の
創設者である Tim Berners-Lee が、HTML の進化のために W3C が WHATWG と共同で作業を進めること
を発表した†。
1.11 参考文献
15
ここ数年を振り返って、いくつかのことが明らかになった。HTML を漸進的に進化させることが必要
ということだ。属性値を引用符で囲むことや空のタグにスラッシュを付けることや名前空間など、すべ
てを一度に XML に切り替えようという試みは、うまく行かなかった。HTML を作成している一般の
人々は、動こうとしない。ブラウザが文句を言わないからだ。一部の大きなコミュニティは移行を行
い、適格なシステムの成果を享受したが、すべてが移行したわけではない。HTML を漸進的に継続し
つつ、適格な世界への移行を続け、その世界でさらに大きな力を蓄えることが重要だ。
そのため、全く新しい HTML グループの設立を計画している。今までとは違って、このグループは
XHTML と並行して HTML を漸進的に改善する目的で設立される。議長や事務局も異なる者が担当す
る。新しいグループは HTML と XHTML の両方を取り扱うことになるだろう。ブラウザのメーカーを
含め、われわれが今まで話した多くの人々は、このグループを強く支持してくれている。
また、フォームに関する作業もある。この分野には、既存の HTML フォームと XForms という 2 つ
のフォーム言語が存在し、複雑な問題を抱えている。HTML フォームはあまねく普及しているし、
XForms にも数多くの実装とユーザが存在する。一方で、Webforms 提案からは HTML フォームの賢
明な拡張が提案されている。今後は Webforms を参考にして、HTML フォームを拡張して行く計画だ。
再設立され、生まれ変わった W3C HTML ワーキンググループが最初に行った決定のひとつは、「Web
Applications 1.0」を「HTML5」と改名することだった。そして今、われわれは HTML5 へ飛び込もうとし
ている。
1.10 後日談
2009 年 10 月、W3C は XHTML 2 ワーキンググループを終了し、以下の声明を出してこの決定を説明し
た††。
W3C が HTML と XHTML 2 ワーキンググループの設立を 2007 年 3 月に発表した際、われわれは
XHTML 2 の需要を継続することを明言していた。W3C は、HTML の将来に関して、コミュニティに
はっきりとしたメッセージを伝える重要性について認識している。
われわれはここ数年間の XHTML 2 ワーキンググループの貢献は重要だったと認識しているが、参加
者との議論の末、W3C 事務局は 2009 年の末をもってこのワーキンググループの設置期間を満了し、
延長は行わないことを決定した。
リリースされたものが、勝利するのだ。
1.11 参考文献
●
Ian Hickson による古いドラフト、「The History of the Web」
http://hixie.ch/commentary/web/history
†
††
http://dig.csail.mit.edu/breadcrumbs/node/166 を参照。
原文(http://www.w3.org/2009/06/xhtml-faq.html)の他、監訳者による翻訳もある(http://standards.mitsue.co.jp/reso
urces/w3c/2009/06/xhtml-faq.html)。
1 章 ここまでの道のり
16
●
Michael Smith、Henri Sivonen 他、「History - HTML WG Wiki」
http://esw.w3.org/topic/HTML/history
●
Scott Reynen、「A Brief History of HTML」
http://atendesigngroup.com/blog/brief-history-html
17
2章
HTML5 の機能を検出する
2.1 はじめに
「HTML5 をサポートしていない古いブラウザがあるのに、どうすれば HTML5 を使い始められるの?」
という疑問があるかもしれない。しかしこの疑問は、的外れだ。HTML5 はひとつの大きなものではなく、
個別の機能が集まったものなのだ。したがって「HTML5 のサポート」という言葉は意味を成さないので、
それを検出することはできない。しかし、例えば Canvas、ビデオ、あるいは Geolocation といった個々の
機能のサポートを検出することは可能だ。
2.2 4 つの検出テクニック
ブラウザは Web ページを表示する際、DOM(Document Object Model)を構築する。これは、ページ
上の HTML 要素を表現するオブジェクトの集まりだ。それぞれの要素、つまり <p> や <div> や <span> の
ひとつひとつは、DOM の中で異なるオブジェクトとして表現される。(他にも window や document などの
グローバルオブジェクトも存在するが、これらは特定の要素とは関連していない。)
すべての DOM オブジェクトには、どの要素にも共通するプロパティがいくらか存在している。しかし、
一部のオブジェクトはこれに加え他よりも多くのプロパティを持っている。HTML5 の機能をサポートする
ブラウザでは、特定のオブジェクトはユニークなプロパティを持っているので、DOM をちょっと覗いてみ
れば、どの機能がサポートされているかがわかるのだ。
ブラウザが特定の機能をサポートしているかどうかを検出するための、基本的なテクニックは 4 つある。
単純なものから複雑なものへと並べると、以下のとおりだ。
1.
グローバルオブジェクト(window や navigator など)に、特定のプロパティが存在するかどうか
チェックする。
例えば、Geolocation API のサポートをテストするには「2.11 Geolocation」を見てほしい。
2.
要素を作成し、次にその要素に特定のプロパティが存在するかどうかチェックする。
例えば、Canvas のサポートをテストするには「2.4 Canvas」を見てほしい。
3.
要素を作成し、その要素に特定のメソッドが存在するかどうかチェックし、次にそのメソッドを呼
んで戻り値をチェックする。
2 章 HTML5 の機能を検出する
18
例えば、どのビデオフォーマットがサポートされているかテストするには「2.7 ビデオフォーマッ
ト」を見てほしい。
4.
要素を作成し、プロパティを特定の値に設定し、次にそのプロパティが設定した値を保持している
かどうかチェックする。
例えば、どの <input> タイプがサポートされているかテストするには、「2.12 input タイプ」を見
てほしい。
2.3 Modernizr:HTML5 検出ライブラリ
Modernizr(http://www.modernizr.com/) は、 オ ー プ ン ソ ー ス で MIT ラ イ セ ン ス の、 数 多 く の
HTML5 と CSS3 機能のサポートを検出してくれる JavaScript ライブラリだ。いつも最新のバージョンを使
うのが良いだろう。Modernizr を使うには、ページの最初に以下のような <script> 要素を書けばよい。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Dive into HTML5</title>
<script src="modernizr.min.js"></script>
</head>
<body>
...
</body>
</html>
Modernizr は自動的に実行される。実行するための modernizr_init() 関数といったものは存在しな
い。起動すると、Modernizr という名前のグローバルオブジェクトが作成され、これに含まれる一連の論
理値プロパティが各機能の検出に対応している。例えば、ブラウザが Canvas API(4 章を参照)をサポー
トしていれば、Modernizr.canvas が true となる。ブラウザが Canvas API をサポートしていなければ、
Modernizr.canvas は false となる。
if (Modernizr.canvas) {
// 図形を描く
} else {
// Canvas のネイティブなサポートはないようだ :(
}
2.4 Canvas
HTML5 は、「解像度に依存するビットマップ描画機能で、グラフ、ゲームのグラフィックス、あるいは
その他のビジュアル画像をオンザフライで表示できる」と <canvas> を定義している†。Canvas はページ中
†
http://whatwg.org/html5#the-canvas-element を参照。
2.4 Canvas
19
の矩形領域に JavaScript を使って何でも好きなものを描くことができる。HTML5 では一連の関数(「Canvas
API」)が定義されており、これらを使ってシェープを描いたり、パスを定義したり、グラデーションを描
いたり、変形を行ったりできる。
Canvas API をチェックするには、2 番目のテクニックを使う(「2.2 4 つの検出テクニック」を参照)。
ブラウザが Canvas API をサポートしていれば、<canvas> 要素として作成された DOM オブジェクトは
getContext() メソッドを持っているはずだ(「4.2 単純なシェープ」を参照)。ブラウザが Canvas API をサ
ポートしていない場合には、<canvas> 要素として作成された DOM オブジェクトは共通プロパティのみを
持っていて、Canvas 特有のプロパティは持っていないはずだ。次の関数を使って、Canvas のサポートを
チェックできる。
function supports_canvas() {
return !!document.createElement('canvas').getContext;
}
この関数は、まずダミーの <canvas> 要素を作成する。
return !!document.createElement('canvas').getContext;
この要素はページに関連付けられることはないので、誰も見ることはない。メモリの中にだけ存在し、ど
こにも現れず何もしない。よどんだ川に浮かぶカヌーのようなものだ。
ダミーの <canvas> 要素を作成した直後に、getContext() メソッドの存在をテストする。このメソッドは、
ブラウザが Canvas API をサポートしている場合にだけ存在する。
return !!document. createElement('canvas').getContext;
最後に、二重否定を使い、結果を論理値(true または false)として返す。
return !!document. createElement('canvas'). getContext;
この関数は Canvas API の大部分、シェープ(「4.2 単純なシェープ」を参照)、パス(「4.4 パス」を参照)、
グラデーション(「4.6 グラデーション」を参照)、パターンなどについてのサポートを検出できる。ただし、
Microsoft Internet Explorer に Canvas API を実装するサードパーティの explorercanvas ライブラリ(「4.8
IE の場合」を参照)は、検出できない。
この関数を自分で書く代わりに、Modernizr(前のセクションで紹介した)を使って Canvas API のサ
ポートを検出することもできる。
if (Modernizr.canvas) {
// 図形を描く
} else {
// Canvas のネイティブなサポートはないようだ :(
}
20
2 章 HTML5 の機能を検出する
Canvas テキスト API には別のテストが存在する。これについては次に説明する。
2.5 Canvas テキスト
ブラウザが Canvas API をサポートしていたとしても、Canvas テキスト API をサポートしているとは限
らない。Canvas API は時間とともに成長してきており、テキスト機能は最近になって付け加えられたもの
だからだ。一部のブラウザは、テキスト API 確定以前の Canvas をサポートしている。
Canvas テキスト API のサポートをチェックするにも、2 番目のテクニックを使う(「2.2 4 つの検出テク
ニック」を参照)。ブラウザが Canvas API をサポートしていれば、<canvas> 要素として作成された DOM
オブジェクトは getContext() メソッドを持っているはずだ(「4.2 単純なシェープ」を参照)。ブラウザが
Canvas API をサポートしていない場合には、<canvas> 要素として作成された DOM オブジェクトは共通プ
ロパティのみを持っていて、Canvas 特有のプロパティは持っていないはずだ。次の関数を使って、Canvas
テキストのサポートをチェックできる。
function supports_canvas_text() {
if (!supports_canvas()) { return false; }
var dummy_canvas = document.createElement('canvas');
var context = dummy_canvas.getContext('2d');
return typeof context.fillText == 'function';
}
この関数はまず、前のセクションで紹介した supports_canvas() 関数を使って、Canvas のサポートを
チェックする。
if (!supports_canvas()) { return false; }
ブラウザで Canvas API がサポートされていなければ、Canvas テキスト API もサポートされていないこ
とは明らかだ。
次に、ダミーの <canvas> 要素を作成し、その描画コンテキストを取得する。これは動作することが保証
されている。supports_canvas() 関数で、getContext() メソッドがすべての Canvas オブジェクト上に存在
することをすでにチェックしているからだ。
var dummy_canvas = document.createElement('canvas');
var context = dummy_canvas.getContext('2d');
最後に、描画コンテキストが fillText() 関数を持っているかどうかをチェックする。持っていれば、
Canvas テキスト API が利用できる。
return typeof context.fillText == 'function';
2.6 ビデオ
21
この関数を自分で書く代わりに、Modernizr(「2.3 Modernizr:HTML5 検出ライブラリ」を参照)を
使って Canvas テキスト API のサポートを検出することもできる。
if (Modernizr.canvastext) {
// テキストを描く
} else {
// Canvas テキストのネイティブなサポートはないようだ :(
}
2.6 ビデオ
HTML5 では、Web ページにビデオを埋め込むための <video> という新しい要素が定義されている。こ
れまでビデオの埋め込みは、Apple QuickTime® や Adobe Flash® などのサードパーティ製プラグインを使
わなくては不可能だった。
<video> 要素は、検出スクリプトなしでも使えるように設計されている。複数のビデオファイルを指定で
き、HTML5 ビデオをサポートするブラウザは自分のサポートしているビデオフォーマットをその中から選
ぶようになっている。
HTML5 をサポートしていないブラウザは <video> 要素を完全に無視するが、このことを利用して、サー
ドパーティのプラグインを代わりに使ってビデオを再生させることができる。Kroc Camen が提供する
Video for Everybody! †では、利用できる場合は HTML5 ビデオを使い、古いブラウザでは QuickTime や
Flash にフォールバックするような仕組みになっている。JavaScript は一切使われていないので、モバイル
ブラウザを含む、事実上すべてのブラウザで動作する。
ただビデオをページに埋め込み再生するといった以上のことをしたければ、JavaScript を使う必要がある。
ビデオのサポートをチェックするには、2 番目のテクニックを使う(「2.2 4 つの検出テクニック」を参照)。
ブラウザが HTML5 ビデオをサポートしていれば、<video> 要素として作成された DOM オブジェクトは
canPlayType() メソッドを持っているはずだ。ブラウザが HTML5 ビデオをサポートしていない場合には、
<video> 要素として作成された DOM オブジェクトは共通プロパティのみを持っているはずだ。次の関数を
使って、ビデオのサポートをチェックできる。
function supports_video() {
return !!document.createElement('video').canPlayType;
}
この関数を自分で書く代わりに、Modernizr(「2.3 Modernizr:HTML5 検出ライブラリ」を参照)を
使って HTML5 ビデオのサポートを検出することもできる。
if (Modernizr.video) {
// ビデオを再生
} else {
// ビデオのネイティブなサポートはないようだ :(
†
http://camendesign.com/code/video_for_everybody を参照。
22
2 章 HTML5 の機能を検出する
// QuickTime か Flash を代わりに使えるかチェックしよう
}
5 章では、HTML5 ビデオをサポートしないブラウザのため、<video> 要素を Flash ベースのビ
デオプレイヤーに置き換えるという別の仕組みを取り上げている。
ブラウザで再生できるビデオフォーマットを検出するには、別のテストが必要だ。これについては次に説
明する。
2.7 ビデオフォーマット
ビデオフォーマットとは、書き言葉のようなものだ。同じ情報を伝える英語の新聞とスペイン語の新聞が
あったとしても、あなたが英語しか読めないなら、片方しか役に立たない。ビデオを再生するには、そのビ
デオが書かれている「言葉」をブラウザが理解する必要がある。
ビデオでこの「言葉」に当たるものは、「コーデック」と呼ばれる。ビデオをビットストリームへエン
コードする際に使われるアルゴリズムのことだ。世の中には何十ものコーデックがある。では、その中のど
れを使うべきだろうか。残念なことに HTML5 ビデオでは、すべてのブラウザでサポートされているコー
デックは存在しない。しかし、2 種類にまで絞り込むことはできる。ひとつはお金がかかる(特許ライセン
スのため)が、Safari と iPhone で使えるものだ(Video for Everybody! のようなソリューションを使えば、
Adobe Flash でも使える)。もうひとつはフリーで、Chromium や Mozilla Firefox のようなオープンソー
スのブラウザで使える。
ビデオフォーマットのサポート状況をチェックするには、3 番目の検出テクニックを使う(「2.2 4 つの検
出テクニック」を参照)。ブラウザが HTML5 ビデオをサポートしていれば、<video> 要素として作成され
た DOM オブジェクトは canPlayType() メソッドを持っているはずだ。このメソッドを使って、ブラウザ
が特定のビデオフォーマットをサポートしているかどうか知ることができる。
次の関数は、Mac や iPhone でサポートされている、特許に縛られたフォーマットをチェックするもの
だ。
function supports_h264_baseline_video() {
if (!supports_video()) { return false; }
var v = document.createElement("video");
return v.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"');
}
この関数は、まず前のセクションの supports_video() 関数を使って、HTML5 ビデオのサポートをチェッ
クする。ブラウザが HTML5 ビデオをサポートしていなければ、どんなビデオフォーマットもサポートし
ていないことは明白だからだ。
if (!supports_video()) { return false; }
2.7 ビデオフォーマット
23
次にこの関数は、ダミーの <video> 要素を作成し(しかしページに関連付けられることはないので、
目に見えることもない)、canPlayType() メソッドを呼び出す。このメソッドは存在が保証されている。
supports_video() 関数でチェックしたばかりだからだ。
var v = document.createElement("video");
「ビデオフォーマット」とは、実際にはいくつかの異なるものの組み合わせだ。専門用語を使って言えば、
ここではブラウザに MPEG-4 コンテナ中の H.264 ベースラインプロファイルのビデオと AAC LC オーディ
オを再生できるかどうかをたずねている†。
var v = document.createElement("video");
return v.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"');
canPlayType() は、true や false を返さない。ビデオフォーマットの複雑さに対応して、文字列を返す
のだ。
"probably"
ブラウザがこのフォーマットを再生できることがかなり確実な場合
"maybe"
ブラウザがこのフォーマットを再生できるかもしれない場合
""(空文字列)
ブラウザがこのフォーマットを再生できないことが確実な場合
次に、下記の関数は、Mozilla Firefox やその他のオープンソースブラウザでサポートされている、オー
プンなビデオフォーマットをチェックする。手順は全く同じだが、唯一の違いは、canPlayType() に渡す
文字列だ。専門用語を使って言えば、ここではブラウザに Ogg コンテナ中の Theora ビデオと Vorbis オー
ディオを再生できるかどうかをたずねている。
function supports_ogg_theora_video() {
if (!supports_video()) { return false; }
var v = document.createElement("video");
return v.canPlayType('video/ogg; codecs="theora, vorbis"');
}
最後に、WebM(http://www.webmproject.org/)は、Chrome、Firefox、そして Opera など主要なブ
ラウザの次のバージョンでサポートされる予定の、新しいオープンソースの(そして特許に縛られない)ビ
デオコーデックだ。オープン WebM ビデオのサポートを検出するには、同じテクニックが使える。
†
これらの専門用語の意味は、5 章で説明する。
2 章 HTML5 の機能を検出する
24
function supports_webm_video() {
if (!supports_video()) { return false; }
var v = document.createElement("video");
return v.canPlayType('video/webm; codecs="vp8, vorbis"');
}
これらの関数を自分で書く代わりに、Modernizr(1.5 以降)を使って HTML5 ビデオフォーマットのサ
ポート状況を検出することもできる。
if (Modernizr.video) {
// ビデオを再生、でも種類は?
if (Modernizr.video.webm) {
// WebM
} else if (Modernizr.video.ogg) {
// Ogg コンテナ中の Ogg Theora + Vorbis
} else if (Modernizr.video.h264) {
// MP4 コンテナ中の H.264 ビデオ + AAC オーディオ
}
}
2.8 ローカルストレージ
HTML5 のストレージ†は、ウェブサイトがコンピュータに情報を保存して後で使うための手段を提供す
る。概念としてはクッキーに似ているが、より大きな情報量を取り扱えるよう設計されている。クッキーは
大きさに制限があり、Web ブラウザが新しいページを要求するたびに Web サーバへ送り返される(時間や
貴重な帯域幅を消費してしまう)。HTML5 ストレージはコンピュータ上に存在し、Web サイトからはその
ページがロードされた後に JavaScript を使ってアクセスできる。
マークアップ教授に質問
Q:ローカルストレージは本当に HTML5 の一部なのですか? 別個の規格になっているのはなぜですか?
A:短い答は、イエス。ローカルストレージは HTML5 の一部だ。もう少し長い答をすると、ローカルス
トレージはかつて HTML5 規格本体の一部だったが、HTML ワーキンググループの一部の人が HTML5 は
大きすぎると文句を言ったため、別個の規格として分離されたのだ。1 個のパイをいくつに切り分けても全
体のカロリーは減らないはずだが、これが規格の世界のおかしなところなのだ††。
†
http://dev.w3.org/html5/webstorage/ を参照。
††
W3C の HTML5 仕様において、Canvas API は別の仕様(Canvas 2D Context)に分離されている(詳しくは 4 章を参照)。
2.7 ビデオフォーマット
25
HTML5 ストレージのサポートをチェックするには、1 番目の検出テクニックを使う(「2.2 4 つの検出
テクニック」を参照)。ブラウザが HTML5 ストレージをサポートしていれば、window オブジェクトに
localStorage プロパティが存在するはずだ。ブラウザが HTML5 ストレージをサポートしていない場合に
は、localStorage プロパティは未定義になっているはずだ。以下の関数を使って、ローカルストレージの
サポートをチェックできる。
function supports_local_storage() {
try {
return ('localStorage' in window) && window['localStorage'] !== null;
} catch(e) {
return false;
}
}
この関数を自分で書く代わりに、Modernizr(1.1 以降)を使って HTML5 ローカルストレージのサポー
トを検出することもできる。
if (Modernizr.localstorage) {
// window.localStorage が利用できる
} else {
// ローカルストレージのネイティブなサポートはないようだ :(
// Gears やその他のサードパーティのソリューションを試してみよう
}
JavaScript は大文字と小文字を区別することに注意してほしい。Modernizr の属性は localstorage(す
べて小文字)だが、DOM のプロパティは window.localStorage(大文字と小文字が混ざっている)となっ
ている。
マークアップ教授に質問
Q:HTML5 ストレージのデータベースのセキュリティはどうなっているのですか? 誰でも読めてしま
うのですか?
A:コンピュータへ物理的にアクセスできれば、誰でもあなたの HTML5 ストレージのデータベースを読
むことはできる(変更すらできてしまう)だろう。ブラウザの中では、どの Web サイトも自身が保存した
値を読んだり変更したりできるが、別のサイトが保存した値へのアクセスはできない。このことは、同一生
成元制限(same-origin restriction)と呼ばれている†。
†
http://whatwg.org/html5#origin-0 を参照。
26
2 章 HTML5 の機能を検出する
2.9 Web Workers
Web Workers †(http://whatwg.org/ww)は、ブラウザが JavaScript をバックグラウンドで動作させ
るための標準的な方法を提供する。Web Workers を使えば、程度の差こそあれ同時に動作する複数の「ス
レッド」を生成することができる。(コンピュータ上で複数のアプリケーションが同時に動作する様子を考
えてみてほしい。Web Workers も大体同じようなものだ。)これらの「バックグラウンドスレッド」は、メ
インのウェブページがユーザのスクロールやクリックや入力に応答している裏で、複雑な数学演算やネット
ワークへの要求やローカルストレージへのアクセスを行うことができる。
Web Workers をチェックするには、1 番目の検出テクニックを使う(「2.2 4 つの検出テクニック」を参
照)。ブラウザが Web Worker API をサポートしていれば、window オブジェクトに Worker プロパティが存
在するはずだ。ブラウザが Web Worker API をサポートしていない場合には、Worker プロパティは未定義
になっているはずだ。以下の関数を使って、Web Workers のサポートをチェックできる。
function supports_web_workers() {
return !!window.Worker;
}
この関数を自分で書く代わりに、Modernizr(1.1 以降)を使って Web Workers のサポートを検出する
こともできる。
if (Modernizr.webworkers) {
// window.Worker が利用できる
} else {
// Web Workers のネイティブなサポートはないようだ :(
// Gears やその他のサードパーティのソリューションを試してみよう
}
JavaScript は大文字と小文字を区別することに注意してほしい。Modernizr の属性は webworkers(すべ
て小文字)だが、DOM のプロパティは window.Worker(「Worker」の「W」が大文字)となっている。
2.10 オフライン Web アプリケーション
静的な Web ページをオフラインで読むことは簡単にできる。インターネットに接続し、Web ページを
ロードし、Internet から切断し、人里離れた小屋へ車を飛ばし、好きなだけその Web ページを読めばよ
い。(時間の節約のために、小屋へ行く手順を飛ばしてもいいだろう。)しかし、オフラインの際に Gmail
や Google Docs などの Web アプリケーションを使うにはどうすればよいだろうか。そこで HTML5 だ。
HTML5 のおかげで、誰でも(Google だけではなく!)オフラインで動作する Web アプリケーションを構
築できるようになったのだ。
オフライン Web アプリケーション††は、まずオンラインの Web アプリケーションとして実行される。
†
監訳注:Web Workers も HTML5 仕様の一部ではないが、HTML5 ストレージと同じように HTML5 関連技術の 1 つとして
数えられることが多い。
††
http://whatwg.org/html5#offline を参照。
2.11 Geolocation
27
オフラインで利用可能な Web サイトへ最初にアクセスする際に、Web サーバはオフラインでの動作にはど
のファイルが必要かをブラウザに教える。これらのファイルは、HTML、JavaScript、画像、あるいはビデ
オ(「2.6 ビデオ」を参照)など、何でもかまわない。ブラウザが必要なファイルをすべてダウンロードし
てしまえば、インターネットに接続していなくてもその Web サイトにまたアクセスできるようになる。ブ
ラウザはオフラインであることを知り、すでにダウンロードしてあるファイルを使うからだ。オンラインに
戻ったとき、オフラインの間に行われた変更はリモートの Web サーバへアップロードされる。
オフライン Web アプリケーションのサポートをチェックするには、1 番目の検出テクニックを使う(「2.2
4 つの検出テクニック」を参照)。ブラウザがオフライン Web アプリケーションをサポートしていれば、
window オブジェクトには applicationCache プロパティが存在するはずだ。ブラウザがオフライン Web ア
プリケーションをサポートしていない場合には、applicationCache プロパティは未定義になっているはず
だ。以下の関数を使って、オフラインのサポートをチェックできる。
function supports_offline() {
return !!window.applicationCache;
}
この関数を自分で書く代わりに、Modernizr(1.1 以降)を使ってオフライン Web アプリケーションの
サポートを検出することもできる。
if (Modernizr.applicationcache) {
// window.applicationCache が利用できる
} else {
// オフライン Web アプリケーションのネイティブなサポートはないようだ :(
// Gears やその他のサードパーティのソリューションを試してみよう
}
JavaScript は大文字と小文字を区別することに注意してほしい。Modernizr の属性は applicationcache
(すべて小文字)だが、DOM のプロパティは window.applicationCache(大文字と小文字が混ざっている)
となっている。
2.11 Geolocation
Geolocation は、あなたがこの世界の中のどこにいるかを検出しする機能で、さらにその情報をあなたが
信頼する人々と共有することもできる。あなたがどこにいるかを検出する方法としては、IP アドレス、無
線ネットワーク接続、携帯電話が通信している基地局、あるいは専用の GPS ハードウェアを使ってはるか
上空の衛星からの緯度・経度情報を受信する方法など、たくさんある。
マークアップ教授に質問
Q:Geolocation は HTML5 の一部なのですか? ここで取り上げたのはなぜですか?
28
2 章 HTML5 の機能を検出する
A:Geolocation のサポートは、新たな HTML5 機能のサポートとともに、まさに今ブラウザへ追加され
ようとしている。厳密に言えば、Geolocation は HTML5 ワーキンググループとは別の、Geolocation
ワーキンググループ(http://www.w3.org/2008/geolocation/)によって標準化が行われている。し
かし、いずれにしろこの本では Geolocation について取り上げる。なぜならこの機能もまた、現在 Web
の世界で起こっている進化のひとつだからだ。
Geolocation のサポートをチェックするには、1 番目の検出テクニックを使う(「2.2 4 つの検出テクニッ
ク」を参照)。ブラウザが Geolocation API をサポートしていれば、navigator オブジェクトに geolocation
プロパティが存在するはずだ。ブラウザが Geolocation API をサポートしていない場合には、geolocation
プロパティは未定義になっているはずだ。以下の関数を使って、Geolocation のサポートをチェックできる。
function supports_geolocation() {
return !!navigator.geolocation;
}
この関数を自分で書く代わりに、Modernizr(「2.3 Modernizr:HTML5 検出ライブラリ」を参照)を
使って Geolocation API のサポートを検出することもできる。
if (Modernizr.geolocation) {
// これでどこに居るのか探せるよ!
} else {
// Geolocation のネイティブなサポートはないようだ :(
// Gears やその他のサードパーティのソリューションを試してみよう
}
ブラウザが Geolocation API をネイティブにサポートしていなかったとしても、まだ望みはある。Gears
(http://tools.google.com/gears/)は Google から提供されているオープンソースのブラウザプラグイン
で、Windows、Mac、Linux、Windows Mobile、そして Android 上で動作する。これは、本章で説明した
新しい機能をサポートしていない古いブラウザに、数々の機能を追加してくれるものだ。Gears の提供する
機能には、Geolocation も含まれている。navigator.geolocation と全く同じではないが、同様の目的を果
たすことができる。
また、BlackBerry、Nokia、Palm、そして OMTP BONDI など、いくつかの携帯電話プラットフォーム
には、デバイス特有の Geolocation API が存在する。
6 章では、これらの異なる API の使い方について、うんざりするほど詳しく説明する。
2.12 input タイプ
読者の皆さんはフォームについてよく知っていると思う。<form> を作成し、数個の <input type="text">
と、必要なら <input type="password"> も追加し、最後に <input type="submit"> ボタンを付けて完成す
る、あれのことだ。
2.12 input タイプ
29
でもそれだけでは、半分しか知っていることにならない。HTML5 では、フォームで使える input タイプ
が数多く定義されているからだ。
<input type="search">
検索ボックス。http://whatwg.org/html5#text-state-and-search-state を参照
<input type="number">
スピンボックス。http://whatwg.org/html5#number-state を参照
<input type="range">
スライダ。http://whatwg.org/html5#range-state を参照
<input type="color">
カラーピッカー。http://whatwg.org/html5#color-state を参照
<input type="tel">
電話番号。http://whatwg.org/html5#telephone-state を参照
<input type="url">
Web ページのアドレス。http://whatwg.org/html5#url-state を参照
<input type="email">
メールアドレス。http://whatwg.org/html5#e-mail-state を参照
<input type="date">
カレンダーやデートピッカー。http://whatwg.org/html5#date-state を参照
<input type="month">
月の入力。http://whatwg.org/html5#month-state を参照
<input type="week">
週の入力。http://whatwg.org/html5#week-state を参照
<input type="time">
時刻の入力。http://whatwg.org/html5#time-state を参照
<input type="datetime">
詳細な日時や時刻。http://whatwg.org/html5#date-and-time-state を参照
<input type="datetime-local">
自分のいる地域の日付と時刻。http://whatwg.org/html5#local-date-and-time-state を参照
HTML5 の新しい input タイプをチェックするには、4 番目の検出テクニックを使う(「2.2 4 つの検出テ
クニック」を参照)。まず、メモリ中にダミーの <input> 要素を作成する。
30
2 章 HTML5 の機能を検出する
var i = document.createElement("input");
すべての <input> 要素のデフォルトタイプは、"text" となる。後でわかるが、このことは非常に重要だ。
次に、ダミーの <input> 要素の type 属性を、検出したいタイプに設定する。
i.setAttribute("type", "color");
ブラウザがそのタイプをサポートしていれば、type プロパティは設定した値を保持しているはずだ。ブ
ラウザがそのタイプをサポートしていない場合には、設定された値は無視され、type プロパティは "text"
のままになっているはずだ。
return i.type !== "text";
13 個の関数を自分で書く代わりに、Modernizr を使ってすべての新しく HTML5 で定義されたタイプの
サポートを検出することもできる。Modernizr は、1 個の <input> 要素を使い回して、効率よく 13 個の入
力形式すべてのサポートを検出してくれる。そして、作成される Modernizr.inputtypes という名前のハッ
シュには、13 個のキー(HTML5 の type 属性)と 13 個の論理値(サポートされていれば true、されてい
なければ false)が含まれている。
if (!Modernizr.inputtypes.date) {
// <input type="date"> のネイティブなサポートはないようだ :(
// Dojo や jQueryUI を使い自分で作ることを考えよう
}
2.13 プレースホルダ
新しい入力形式の他にも、HTML5 には既存のフォームに使えるちょっとした機能が追加されている。そ
のひとつは、入力フィールドのプレースホルダ†を設定できる機能だ。プレースホルダは、そのフィールド
が空で、かつそこにフォーカスがない場合に入力フィールド中に表示される。その入力フィールドをクリッ
ク(またはそこにタブで移動)すると、プレースホルダは消えてしまう。ピンと来ない人は、「9.2 プレー
スホルダ」にスクリーンショットがあるので参考にしてほしい。
プレースホルダのサポートをチェックするには、2 番目のテクニックを使う(「2.2 4 つの検出テクニック」
を参照)。ブラウザが入力フィールド中のプレースホルダをサポートしていれば、<input> 要素として作成
された DOM オブジェクトは placeholder プロパティを持っているはずだ(HTML 中に placeholder 属性
が存在しない場合でも)。ブラウザがプレースホルダをサポートしていない場合には、<input> 要素として
作成された DOM オブジェクトは placeholder プロパティを持っていないはずだ。次の関数を使って、プ
レースホルダのサポートをチェックできる。
function supports_input_placeholder() {
var i = document.createElement('input');
†
http://whatwg.org/html5#the-placeholder-attribute を参照。
2.14 フォームのオートフォーカス
31
return 'placeholder' in i;
}
この関数を自分で書く代わりに、Modernizr を使ってプレースホルダのサポートを検出することもでき
る。
if (Modernizr.input.placeholder) {
// プレースホルダが見えるはずだ
} else {
// プレースホルダはサポートされていない :(
// スクリプトを使った実現方法に頼ることになる
}
2.14 フォームのオートフォーカス
JavaScript を使って、自動的にフォームの最初の入力フィールドにフォーカスを設定するサイトがある。
例えば Google.com のホームページでは検索入力ボックスに自動的にフォーカスが設定されるので、カー
ソルを検索入力ボックスに移動する手間なく検索キーワードが入力できるようになっている。大部分の人
にとってこれは便利な機能だが、パワーユーザや特別なニーズのある人々にとっては邪魔になる場合があ
る。例えばページをスクロールしようとしてスペースバーを押しても、フォーカスがすでにフォームの入力
フィールドにあるため、ページはスクロールせず、代わりにそのフィールドにスペースが入力されてしま
う。またページがまだロードされている途中で別の入力フィールドにフォーカスを移動した場合、サイトの
オートフォーカススクリプトが「親切にも」ロード完了時に元の入力フィールドにフォーカスを戻してしま
うかもしれず、そうすると作業の流れが中断されたり、間違った場所に入力をしてしまったりする破目にな
る。
オートフォーカスは JavaScript を使って行われるので、これらの特別な場合すべてに対応するのは難し
い。またページにフォーカスが「奪われる」ことを嫌う人々が取れる対策も限られている。
この問題を解決するため、HTML5 はすべてのフォームコントロールに autofocus 属性†を導入した。こ
の autofocus 属性は、フォーカスを特定の入力フィールドへ移動するという、文字通りの働きをする。しか
しこれはスクリプトではなく単なるマークアップなので、その振る舞いはすべてのウェブサイトにわたって
統一されることになる。また、ブラウザメーカー(あるいは拡張機能の作者)が、オートフォーカスを無効
にする手段をユーザに提供することも可能となるのだ。
オートフォーカスのサポートをチェックするには、2 番目のテクニックを使う(「2.2 4 つの検出テクニッ
ク」を参照)。ブラウザがフォームコントロールへのオートフォーカスをサポートしていれば、<input>
要素として作成された DOM オブジェクトは autofocus プロパティを持っているはずだ(HTML 中に
autofocus 属性が存在しない場合でも)。ブラウザがオートフォーカスをサポートしていない場合には、
<input> 要素として作成された DOM オブジェクトは autofocus プロパティを持っていないはずだ。次の関
数を使って、オートフォーカスのサポートをチェックできる。
†
http://whatwg.org/html5#autofocusing-a-form-control を参照。
32
2 章 HTML5 の機能を検出する
function supports_input_autofocus() {
var i = document.createElement('input');
return 'autofocus' in i;
}
この関数を自分で書く代わりに、Modernizr(1.1 以降)を使ってオートフォーカスのサポートを検出す
ることもできる。
if (Modernizr.input.autofocus) {
// オートフォーカスが使える
} else {
// オートフォーカスはサポートされていない :(
// スクリプトを使った実現方法に頼ることになる
}
2.15 マイクロデータ
マイクロデータ†は、Web ページに意味付けを追加するための標準的な方法だ。例えば、マイクロデー
タを使ってある写真が特定のクリエイティブコモンズライセンスで利用できることを宣言できる。10 章で
説明するが、自己紹介のページをマークアップする際にもマイクロデータが使える。ブラウザやブラウザの
拡張機能、そしてサーチエンジンは、そのマイクロデータによるマークアップを、アドレス帳の標準的な
フォーマットである vCard に変換できるのだ。またマイクロデータで使う独自のフォーマットを定義する
こともできる。
マイクロデータには、HTML マークアップ(主にサーチエンジンのため)と、一連の DOM 関数(主に
ブラウザのため)の両方が含まれている。マイクロデータのマークアップはページに埋め込んでも、悪いこ
とは何も起こらない。ただの属性に過ぎないからだ。また、マイクロデータ属性を理解しないサーチエンジ
ンは、単にそれを無視する。しかし、DOM を介してマイクロデータへのアクセスや操作を行う必要があれ
ば、ブラウザがマイクロデータ DOM API をサポートしているかどうかをチェックする必要がある。
マイクロデータのサポートをチェックするには、1 番目の検出テクニックを使う(「2.2 4 つの検出テ
クニック」を参照)。ブラウザがマイクロデータ API をサポートしていれば、document オブジェクト
に getItems() メソッドが存在するはずだ。ブラウザがマイクロデータをサポートしていない場合には、
getItems() メソッドは未定義になっているはずだ。以下の関数を使って、ローカルストレージのサポート
をチェックできる。
function supports_microdata_api() {
return !!document.getItems;
}
Modernizr はまだマイクロデータ API のチェックをサポートしていないので、上記のような関数を使う
必要があるだろう。
†
http://whatwg.org/html5#microdata を参照(監訳注:Microdata 仕様も W3C では HTML5 から分離されている)。
2.16 参考文献
2.16 参考文献
規格および標準:
●
<canvas> 要素
http://whatwg.org/html5#the-canvas-element
●
<video> 要素
http://whatwg.org/html5#video
●
<input> タイプ
http://whatwg.org/html5#states-of-the-type-attribute
●
<input placeholder> 属性
http://whatwg.org/html5#the-placeholder-attribute
●
<input autofocus> 属性
http://whatwg.org/html5#autofocusing-a-form-control
●
HTML5 ストレージ
http://dev.w3.org/html5/webstorage/
●
Web Workers
http://whatwg.org/ww
●
オフライン Web アプリケーション
http://whatwg.org/html5#offline
●
Geolocation API
http://dev.w3.org/geo/api/spec-source.html
JavaScript ライブラリ:
●
Modernizr HTML5 検出ライブラリ
http://www.modernizr.com/
●
Geolocation API のラッパ geo.js
http://code.google.com/p/geo-location-javascript/
その他の記事とチュートリアル:
●
Video for Everybody!
http://camendesign.com/code/video_for_everybody
33
2 章 HTML5 の機能を検出する
34
●
「ビデオ形式パラメータ」
http://wiki.whatwg.org/wiki/Video_type_parameters
●
本書の付録
●
Internet Explorer 9 Guide for Developers
http://msdn.microsoft.com/en-us/ie/ff468705.aspx
35
3章
HTML 文書の構造と意味付け
3.1 はじめに
この章では、とある全く問題のない HTML ページを取り上げ、それを改良してみる。短くなる部分もあ
るし、長くなる部分もあるが、すべてがより明確な意味を持つようになる。実例を通して多くのことが学べ
るはずだ。
これ(http://diveintohtml5.info/examples/blog-original.html)が、サンプルにするページだ。よく学
び、慣れ親しみ、愛着を持ってほしい。ブラウザの新しいタブに表示して、少なくとも一度は「ソースを表
示」してみてから、この先を読み進めてほしい。
3.2 DOCTYPE
最初の行から説明しよう。
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
これは、DOCTYPE と呼ばれるものだ。DOCTYPE には長い歴史が、そして黒魔術が付きまとってい
る。かつて Microsoft が Mac 版の Internet Explorer 5 を開発していた最中に、思いがけない問題が発生し
た。この次期バージョンで標準のサポートを大幅に改善した結果、古いページが適切に表示されなくなっ
てしまったのだ。正確に言うと、(標準への準拠という意味では)適切な表示だったのだが、人々が期待し
ていたのは不適切な表示だったのだ。これらのページは当時支配的だったブラウザ、特に Netscape 4 と
Internet Explorer 4 の癖(quirks)にあわせて作成されていた。Mac IE5 はあまりにも先進的だったため、
Web を壊してしまうところだったのだ。
Microsoft は、斬新な解決策を採用した。ページを表示する前に、Mac IE5 は「DOCTYPE」を見る。こ
れは通常 HTML ソースの最初の行(<html> 要素よりも前)にある。古いページ(古いブラウザの表示の癖
にあわせて作られていた)は、DOCTYPE のないものが普通だった。Mac IE5 はこのようなページについ
ては、古いブラウザと同じように表示した。新しい標準のサポートを「発動」するには、Web ページ作成
者が <html> 要素よりも前に正しい DOCTYPE を書く必要があった。
このアイデアは燎原の火のように広がり、すぐに主要なブラウザはすべて「後方互換(quirks)モード」
36
3 章 HTML 文書の構造と意味付け
と「標準(standards)モード」という 2 つのモードを備えるようになった。もちろん、何事もすぐに手に
負えなくなってしまうのが Web の世界だ。Mozilla はバージョン 1.1 のブラウザを出荷しようとして、標
準モードで表示されていたページの中に、実際にはある特定の癖に依存していたものがあることに気が付
いた。Mozilla が表示エンジンからこの癖を取り除く修正をしたところ、何千ものページの表示がおかしく
なってしまった。その結果、「ほぼ標準(almost standards)モード」が作り出された(断っておくが、こ
れはつくり話ではない)。
Henri Sivonen は、「DOCTYPE によって発動されるブラウザモードについて」と題する重要な記事†の
中で、これらのモードの違いについて以下のようにまとめている。
後方互換(quirks)モード
後方互換モードでは、1990 年後半に一般的だった慣習に従って作成されたページが「壊れる」の
を防ぐため、ブラウザは現在の Web フォーマット規格に違反した動作をする。
標準(standards)モード
標準モードでは、ブラウザはそのブラウザに実装された範囲内で、規格に準拠した文書に対して、
規格に従った正しい取り扱いを行おうとする。HTML5 ではこのモードを「no quirks モード」と
呼ぶ。
ほぼ標準(almost standards)モード
Firefox、Safari、Chrome、Opera(7.5 以降)そして IE8 には、「ほぼ標準モード」として知られ
るモードがある。これは、表のセルの高さ方向の調節を、CSS2 規格には厳密には準拠していない
従来の方法で行うものだ。HTML5 ではこのモードを「limited quirks モード」と呼ぶ。
ぜひ Henri の記事をひととおり読んでみてほしい。ここでの私の説明は、大幅に単純化したものだ
からだ。Mac IE5 にさえ、標準をサポートしていないとされる古い DOCTYPE がいくつか存在し
ていた。時間とともにブラウザの癖のリストは長くなり、後方互換モードを発動する DOCTYPE
のリストもまた長くなっていったのだ。私が最後に数えたときには、ほぼ標準モードを発動する
DOCTYPE は 5 種類、後方互換モードを発動する DOCTYPE は 73 種類あった。これ以外にも私
が見逃しているものはあるだろうし、Internet Explorer 8 が持っている 4 種類(!)もの表示モー
ドについてはまだ触れてもいない。そのフローチャートは http://hsivonen.iki.fi/doctype/ie8mode.png にある。爆発しろ!
それでだ。何の話をしていたんだっけ。そうそう、DOCTYPE だ。
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
これはたまたま、すべてのモダンブラウザが「ほぼ」ではない「標準モード」を発動する 15 種類の
DOCTYPE のひとつになっている。これ自体には何も悪い点はないので、このままにしておくほうが好み
†
http://hsivonen.iki.fi/doctype/ を参照。
3.3 ルート要素
37
なら、それでもかまわない。しかしこれを、より短くて簡単で、すべてのモダンブラウザが標準モードを発
動する HTML5 の DOCTYPE に変更することもできる。
これがその、HTML5 の DOCTYPE だ。
<!DOCTYPE html>
これだけ。たった 15 文字だ。手で打つのも簡単だし、間違えることもないだろう。
マークアップ教授から一言
DOCTYPE は、HTML ファイルの最初の行に存在する必要がある。その前に何か他のものがあれば(たと
えそれが空白行であっても)、一部のブラウザは DOCTYPE が存在しないものとしてそのページを取り扱
う。DOCTYPE がない場合、ブラウザはページを後方互換モードで表示する。これは非常に検出が難しい
エラーだ。通常、HTML は余分な空白文字があっても問題ないため見過ごされがちだが、この場合に限っ
て言えば非常に重要なのだ。
3.3 ルート要素
HTML ページは、要素が入れ子になってできている。ページ全体の構造は、木に似ている。「兄弟」要素
とは、つまり同じ木の幹から伸びる 2 本の枝のことだ。ある要素が他の要素の「子」要素であるとは、つ
まり大きな枝から伸びる小さな枝だということだ。(この逆もまた言える。ある要素が別の要素を含んでい
るとき、その要素は直接の子要素の「親」ノードと呼ばれ、また孫要素の「先祖」となる。)子要素を持た
ない要素は「リーフ」ノードと呼ばれる。最も根源の要素、つまりページ上のすべてのほかの要素の先祖で
ある要素は、「ルート要素」と呼ばれる。HTML ページのルート要素は常に <html> だ。
サンプルページ(http://diveintohtml5.info/examples/blog-original.html)では、ルート要素は以下の
ようになっている。
<html xmlns="http://www.w3.org/1999/xhtml"
lang="en"
xml:lang="en">
これ自体には何も悪い点はない。さっきと同じように、このままにしておくほうが好みなら、それでもか
まわない。しかしこの一部は HTML5 ではもう必要ないため、その部分を削ることによってバイト数が多
少節約できる。
まず xmlns 属性から手を付けてみよう。これは XHTML 1.0 の残滓で、このページに使われている要素は
XHTML 名前空間 http://www.w3.org/1999/xhtml に属する、という意味だ。しかし、HTML5 の要素は常
にこの名前空間に属するので、明示的にこの宣言を行う必要はない。この属性があってもなくても、すべて
の最近のブラウザは HTML5 のページを全く同じように表示してくれる。
xmlns 属性を削除すると、ルート要素は以下のようになる。
38
3 章 HTML 文書の構造と意味付け
<html lang="en" xml:lang="en">
ここにある lang と xml:lang という 2 つの属性は、両方ともこの HTML ページの言語を定義している。
en は「英語」を意味する†。なぜ 2 つの属性が同じことを示しているのだろう?これもまた、XHTML の
残滓なのだ。HTML5 では、lang のみが意味を持つ。xml:lang を残しておきたければそれでもかまわない
が、その場合には lang 属性と同一の値を持つように注意する必要がある。
XHTML への、あるいは XHTML からの移行を容易にするため、ページ作成者は HTML 文書中の
HTML 要素に、「xml:lang」を持つ、名前空間に属さない接頭辞なしの属性を指定できるが、その属性
は名前空間に属さない lang 属性とともに指定しなくてはならず、かつ ASCII で大文字と小文字を区別
せずに比較した場合に両方の属性が同一の値を持たなくてはならない。この、ローカル名「xml:lang」
というローカル名を持つ、名前空間に属さない接頭辞なしの属性は、言語処理に影響を与えない。
心の準備はできただろうか。それでは、消しますよ…はい、消えました。すると、ルート要素は以下のよ
うになる。
<html lang="en">
これで完成。これ以上、手を入れる箇所はない。
3.4 <head> 要素
ルート要素の最初の子要素は、普通 <head> 要素だ。この <head> 要素はメタデータ、つまりページの
本体そのものではなく、ページに関する情報を含んでいる。(ページの本体は、<body> 要素に含まれてい
る。)<head> 要素自体は退屈なものだし、HTML5 でも大して面白くはなっていない。見てもらいたいのは、
<head> 要素の中身だ。もう一度、サンプルページを見てみよう。
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>My Weblog</title>
<link rel="stylesheet" type="text/css" href="style-original.css" />
<link rel="alternate" type="application/atom+xml"
title="My Weblog feed"
href="/feed/" />
<link rel="search" type="application/opensearchdescription+xml"
title="My Weblog search"
href="opensearch.xml" />
<link rel="shortcut icon" href="/favicon.ico" />
</head>
まずは <meta> 要素だ。
†
英語以外の言語コードについては、http://www.w3.org/International/questions/qa-choosing-language-tags を参照。
3.4 <head> 要素
39
3.4.1 文字エンコーティング
「テキスト」と聞いて、「コンピュータ画面に表示される文字や記号」を思い浮かべる人が多いだろう。し
かしコンピュータは文字や記号を処理しているわけではない。ビットやバイトを処理しているのだ。コン
ピュータ画面に表示されるテキストはすべて、実際には特定の文字エンコーティングを使って保存されてい
る。文字エンコーディングにはたくさんの種類があり、特定の言語、例えばロシア語や中国語や英語に最適
化されているものもあれば、複数の言語を扱えるものもある。非常に大雑把に言えば、文字エンコーディン
グとは、画面上に見えるモノと、コンピュータがメモリやディスクに実際に保存するモノとの間の対応付け
のことだ。
しかし現実は、もうちょっと複雑だ。多くの文字は複数のエンコーディングで共通して使われるが、これ
らの文字をメモリやディスクに実際に保存する際に使われるバイト列は、エンコーディングごとに違ってい
るかもしれない。したがって、文字エンコーディングはテキストを解読するための一種の復号鍵とみなせ
る。誰かがあるバイト列を「テキスト」だと主張した場合、どのような文字エンコーディングが使われてい
るかを知らなくては、そのバイト列を文字としてデコードし、表示(または処理)することはできない。
それでは、ブラウザは Web サーバから送られてきたバイトストリームの文字エンコーディングを、実際
にはどうやって決定するのだろうか。これはいい質問だ。HTTP ヘッダに興味がある人は、次のようなヘッ
ダに見覚えがあると思う。
Content-Type: text/html; charset="utf-8"
簡単に言うと、これは Web サーバが HTML 文書を送信しているつもりであること、またその文書が
UTF-8 文字エンコーディングを使っているつもりであることを示している。残念なことに、Web という広
い世界の中で、本当の意味で HTTP サーバをコントロールできるページ作成者は非常に少ない。例えば
Blogger(http://www.blogger.com/)では、コンテンツを提供するのは各個人だが、サーバは Google が
運営している。そのため HTML4 では、HTML 文書そのものの中で文字エンコーディングを指定する方法
を提供していた。たぶん、これにも見覚えがあるはずだ。
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
簡単に言うと、これはその Web の作成者が UTF-8 文字エンコーディングを使って HTML 文書を作成し
たつもりであることを示している。
これらのテクニックは、両方とも HTML5 で使える。HTTP ヘッダを使うことが望ましく、これが存
在する場合には <meta> タグを置き換える。しかし誰もが HTTP ヘッダを設定できるわけではないので、
<meta> タグも使えるようになっている。実は、HTML5 ではその使い方も少しやさしくなっている。以下
のように書けるのだ。
<meta charset="utf-8" />
これは、すべてのブラウザで動作する。この短い構文はどうやって生まれたのだろうか。以下は今まで私
3 章 HTML 文書の構造と意味付け
40
が見た中で、一番わかりやすい説明だ†。
この <meta charset=""> 属性の組み合わせを採用した理由は、UA ですでに実装されているためだ。以
下のように引用符を入れ忘れる人が多いからだ。
<META HTTP-EQUIV=Content-Type CONTENT=text/html; charset=ISO-8859-1>
ここ(http://simon.html5.org/test/html/parsing/encoding)には <meta charset> のテストケースもいく
つかあるので、疑い深い人は試してみればよいだろう。
マークアップ教授に質問
Q:私は変わった文字を使わないのですが、それでも文字エンコーディングを宣言する必要がありますか?
A:そのとおり! すべての HTML ページには、常に文字エンコーディングを指定するべきだ。エンコー
ディングを指定しないと、セキュリティの脆弱性を引き起こす場合もある††。
まとめると、文字エンコーディングは複雑なものであり、コピーアンドペーストに慣れたページ作成者
が使うような出来の悪いソフトウェアでは取り扱いが難しい。だから、すべての HTML 文書には常に文字
エンコーディングを指定すべきであり、そうしないといろいろとまずいことが起こるだろう。方法として
は HTTP の Content-Type ヘッダを使う方法、<meta http-equiv> 宣言を使う方法、あるいはより短い <meta
charset> 宣言を使う方法があるが、どの方法でもいいから確実に行ってほしい。Web に代わってお願いする。
3.4.2 リンクタイプ
普通のリンク(<a href>)は、単純に別のページを参照する。リンクタイプは、別のページを参照する理
由を説明するためのものだ。「私がここで別のページを参照しているそのわけは…」に続く文章を作ってい
ると考えればよい。
●
…ブラウザがこの文書へ適用すべき、CSS を含むスタイルシートだから。
●
…このページと同じ内容を持つフィードフォーマットだから。
●
…このページの翻訳だから。
●
…このページの PDF 版だから。
●
…このページはオンラインブックの一部で、参照先のページは次の章だから。
†
http://lists.w3.org/Archives/Public/public-html/2007Jul/0550.html を参照。
††
http://code.google.com/p/doctype/wiki/ArticleUtf7 を参照。
3.4 <head> 要素
41
などなど。HTML5 は、リンクによる関連付けを 2 つのカテゴリに分類している†。
link 要素によって作られるリンクには 2 種類ある。ひとつは外部リソースへのリンクで、これは現在の
文書を補強するために使われるリソースへのリンクである。もうひとつはハイパーリンクとしてのリン
クで、別の文書へのリンクである。(後略)
外部リソースへのリンクの正確な振る舞いは、まさにその関連性によって決定され、関連するリンクタ
イプごとに定義されている。
先ほど挙げた例の中では、最初(rel="stylesheet")だけが外部リソースへのリンクになる。それ以外
は、別の文書へのハイパーリンクになる。後者については、そのリンクをたどるかどうかは自由だし、現在
のページを見るために必要なものではない。
リンクタイプは、ページの <head> の中の <link> 要素で使われる場合が最も多い。一部のリンクタイプ
は <a> 要素にも使えるが、可能ではあってもめったに行われることはない。HTML5 はまた <area> 要素に
よる関連付けも許しているが、この例はさらに少ない。(HTML 4 では <area> 要素が rel 属性を持つこと
を許していなかった。)特定の rel の値がどこで使えるかチェックするには、リンクタイプをまとめた表
(http://whatwg.org/html5#linkTypes)を見てほしい。
マークアップ教授に質問
Q:リンクタイプを独自に作成することはできますか?
A:新しいリンクタイプを作成したいというアイデアが尽きることはないようだ。しかし、むやみに作られ
ることのないよう、WHATWG は提案された rel の値のレジストリ††を管理しており、またそれらを採用
するプロセス‡も定義している‡‡。
rel = stylesheet
サンプルページに最初に出てくるリンクタイプを見てみよう。
<link rel="stylesheet" href="style-original.css" type="text/css" />
これは、世界中で最もよく使われているリンクタイプだ。<link rel="stylesheet"> は、別の CSS ファ
イルに保存されている CSS 規則を参照するためのものだ。HTML5 では、type 属性を省略するという、さ
†
http://whatwg.org/html5#attr-link-rel を参照。
††
http://wiki.whatwg.org/wiki/RelExtensions を参照。
‡
http://whatwg.org/html5#other-link-types を参照。
‡‡
監訳注:このリンクタイプレジストリについては、Wiki での管理やその集中性について異論がでているため、ここで言われ
ているレジストリや採用プロセスが今後も残り続けるかは定かではない。W3C HTML WG では本件に関する議論をイシュー
トラッカーで管理しており、その一部始終を読むことができる(http://www.w3.org/html/wg/tracker/issues/27 を参照)。
42
3 章 HTML 文書の構造と意味付け
さやかな最適化が可能となっている。CSS は Web で使われている唯一のスタイルシート言語なので、type
属性のデフォルト値となっているからだ。(いつかは誰かが別の新しいスタイルシート言語を発明するかも
しれないが、そのときは type 属性をまた付ければいいだけの話だ。)
<link rel="stylesheet" href="style-original.css" />
rel = alternate
サンプルページで次に出てくるのはこれだ。
<link rel="alternate"
type="application/atom+xml"
title="My Weblog feed"
href="/feed/" />
このリンクタイプも、よく使われる。<link rel="alternate"> と、type 属性への RSS または Atom メ
ディアタイプの指定を組み合わせることによって、「フィードの自動通知(feed autodiscovery)」と呼ば
れる機能が有効になる。Google Reader のようなフィードリーダーは、これを使ってサイトの新着記事の
ニュースフィードを見つけている。たいていのブラウザは、URL の横に特別なアイコンを表示してフィー
ドの自動通知を示す機能もサポートしている†。(rel = "stylesheet" と違い、type 属性はここでは必須だ。
省略しないように!)
この rel="alternate" リンクタイプには、今までずっと(HTML 4 の時代から)異なるユースケースが
混在していた。HTML5 では、定義が明確化されるとともに既存の Web コンテンツをより正確に説明でき
るよう拡張されている。さっきの例のように、rel="alternate" と type="application/atom+xml" の組み合
わせは、現在のページの Atom フィードを意味する。しかし同じ rel="alternate" を別の type 属性と組み
合わせると、別のフォーマット(例えば PDF)の同じコンテンツを意味することになる。
また HTML5 では、翻訳へのリンクに関する積年の混乱にも決着が付けられた。HTML 4 仕様書では、
翻訳版の言語情報を指定するには lang 属性を rel="alternate" と組み合わせて使うと書かれていたが、実
はこれは間違いだ。HTML 4 の正誤表には、HTML 4 仕様の明白な 4 つの誤り(といくつかの編集上の小
さな間違い)が掲載されているが、この明白な誤りのひとつに rel="alternate" と組み合わせて文書の言
語を指定する方法が含まれている。(HTML 4 の正誤表や現在の HTML5 に記載されている正しい方法は、
hreflang 属性を使うことになる。)残念なことに、この正誤表が HTML 4 の仕様に反映されることはなかっ
た。当時の W3C HTML ワーキンググループに HTML の作業を行っている人が誰もいなかったからだ。
HTML5 にあるその他のリンクタイプ
rel="archives"(http://whatwg.org/html5#rel-archives)
「参照された文書が、歴史的な興味を引く記録や文書、その他の情報であることを示している。た
とえば、ブログの索引ページから、rel="archives" を使ってそのブログの過去記事の索引へリン
†
監訳注:Chrome や Firefox 4 ではこのアイコンがデフォルトではアドレスバーに表示されない。拡張をインストールして表
示することはできる。
3.4 <head> 要素
43
クを張ることができる」と定義されている。
rel="author"
そのページの著者に関する情報へリンクするために使われる。これは mailto: アドレスであって
もよいが、そうでなくてはいけないわけではない。単純に問い合わせフォームや「著者について」
ページへのリンクであってもよい。
rel="external"(http://whatwg.org/html5#link-type-external)
「リンク先が、現在の文書が属しているサイトに含まれない文書を指していることを示す」と定義
されている。私見だが、これがよく使われるようになったのは WordPress がコメント内のリンク
に使い始めたからだと考えている。
rel="start"、rel="prev"、rel="next"(http://www.w3.org/TR/html401/types.html#type-links)
HTML 4 ではこれらの、一連のページ(本の章やブログの記事など)の間の関連を示すリンクタ
イプが定義されていた。しかしこの中で、今までに正しく使われてきたのは rel="next" だけだ。
人々は rel="prev" の代わりに rel="previous" を使い、rel="start" の代わりに rel="begin" や
rel="first" を、rel="last" の代わりに rel="end" を使っていたのだ。また、これらとは関係な
く、rel="up" が「親」ページを示すためにも使われていた。
HTML5 では、「一連のページの中の最初のページ」を示すさまざまな方法のうち、最もよく使わ
れていた rel="first" が採用された。(rel="start" は、後方互換性のために提供されている、仕
様外の同義語だ。)また HTML 4 と同様に rel="prev" と rel="next" も採用された(そして後方互
換性のために rel="previous" もサポートされている)。さらには rel="last"(rel="first" の逆
で、一連のページのうちの最後を示す)や、rel="up" も含まれている。
rel="up"
これを理解するには、パンくずリストのナビゲーションを見てみるのが一番だ(手近になければ想
像してみてほしい)。パンくずリストでは、おそらくホームページが最初のページとなり、現在の
ページが最後になっているだろう。rel="up" は、パンくずリストで最後から 2 番目のページを指
すことになる。
rel="icon"(http://whatwg.org/html5#rel-icon)
これは、リンクタイプのうち、rel="stylesheet" に次いで 2 番目によく使われているものだ
(http://code.google.com/webstats/2005-12/linkrels.html)。通常は、以下のように shortcut と
ともに使われる。
<link rel="shortcut icon" href="/favicon.ico">
これは、すべての主要なブラウザでサポートされていて、小さなアイコンをページに関連付けてく
れる。通常、アイコンはブラウザのロケーションバーの中の URL の隣に、またはブラウザのタブ
に、あるいはその両方に表示される。
また、HTML5 で新しく導入されたものに sizes 属性がある。これは、参照されるアイコンの大き
44
3 章 HTML 文書の構造と意味付け
さを示すため、icon とともに使われる(http://whatwg.org/html5#attr-link-sizes)。
rel="license"(http://whatwg.org/html5#link-type-license)
マイクロフォーマットのコミュニティによって発明されたリンクタイプだ。仕様書には「参照され
た文書が、どのライセンスのもと著作権の利用許諾を提供しているかを示す」とある。
rel="nofollow"(http://whatwg.org/html5#link-type-nofollow)
「このリンクが元の作成者やページの発行者によって承認されていないか、または参照された文書
へのリンクが主にこれらのページに利害関係のある人々の商業的な関心のために作成されたことを
示す」と定義されている。このリンクタイプは Google によって発明され、マイクロフォーマット
のコミュニティ内で標準化された。WordPress はコメント内のリンクに rel="nofollow" を自動的
に付加している。元になった考えは、「nofollow」リンクが PageRank に影響を与えないのであれ
ば、スパマーたちはブログにスパムコメントを投稿するのをあきらめるだろう、というものだっ
た。実際には効果はなかったが、rel="nofollow" は使われ続けている。
rel="noreferrer"(http://whatwg.org/html5#link-type-noreferrer)
「リンクをたどる際に referrer 情報を伝えるべきでないことを示す」と定義されている。現在リ
リースされているブラウザでこれをサポートしているものはないが、最近になって WebKit の夜間
ビルドにサポートが追加されたため、そのうち Safari や Google Chrome などの WebKit ベースの
ブラウザでは使えるようになるだろう。rel="noreferrer" のテストケースは http://wearehugh.
com/public/2009/04/rel-noreferrer.html にある。
rel="pingback"(http://whatwg.org/html5#link-type-pingback)
「pingback」サーバのアドレスを指定する。pingback の仕様(http://hixie.ch/specs/pingback/
pingback-1.0)には、「pingback システムは、ブログが他の Web サイトからリンクされた際に自
動的に通知を受けることを可能とする。(中略)これは逆方向リンク、つまり、リンクの連鎖を順
方向にたどるだけではなく、反対の向きにもたどることを可能とする」とある。WordPress など
のブログシステムでは、新たなブログ記事が投稿された際、リンクしたブログの作者へ通知するた
めにこの pingback 機構を利用している。
rel="prefetch"(http://whatwg.org/html5#link-type-prefetch)
「指定されたリソースをユーザが必要とする可能性が高いため、このリソースをあらかじめ取得し、
キャッシュしておくことが望ましいことを示す」と定義されている。サーチエンジンは、最初の検
索結果がその他の結果よりもはるかに高い関連性を示すと考えられるとき、検索結果のページに
<link rel="prefetch" href=" 最初の検索結果の URL"> を追加することがある。例えば、Firefox
を使って Google で CNN を検索し、ページのソースを表示してその中で prefetch を探してみて
ほしい。Mozilla Firefox は現在のところ rel="prefetch" をサポートしている唯一のブラウザだ†。
rel="search"(http://whatwg.org/html5#link-type-search)
「参照される文書が、文書と関連リソースの検索に特化したインタフェースを提供していることを
†
監訳注:Chrome もサポートに向け動いている。
3.5 HTML5 の新しい意味要素
45
示す」と定義されている。具体的に言うと、rel="search" を有効に活用するには OpenSearch 文
書にリンクする必要がある。OpenSearch 文書とは、与えられたキーワードで現在のサイトを検索
するための URL の構築方法を説明したものだ。OpenSearch(および rel="search" からリンクさ
れる OpenSearchDescription 文書)は、Microsoft Internet Explorer のバージョン 7 以降、およ
び Mozilla Firefox のバージョン 2 以降でサポートされている†。
rel="sidebar"(http://whatwg.org/html5#link-type-sidebar)
「参照される文書が取得された際に、現在のブラウジングコンテキストに代わる、二次的なブラウ
ジングコンテキストでの表示(可能な場合には)が意図されていることを示す」と定義されてい
る。これはどういう意味だろうか。Opera や Mozilla Firefox で説明すると、
「このリンクをクリッ
クした場合にはそれをブックマークするようプロンプトを出し、ブックマークメニューからそのリ
ンクを選択した場合にはリンク先をブラウザのサイドバーで開く」という意味になる。(Opera で
は「サイドバー」ではなく「パネル」と呼ばれる。)Internet Explorer、Safari、そして Chrome
では rel="sidebar" は無視され、単に通常のリンクとして取り扱われる。rel="sidebar" のテスト
ケースは http://wearehugh.com/public/2009/04/rel-sidebar.html にある。
rel="tag"(http://whatwg.org/html5#link-type-tag)
「参照された文書に与えられたタグを示す」と定義されている。rel 属性を使った「タグ」(カテ
ゴリキーワード)のマークアップは、ブログ記事の分類を手助けする目的で Technorati によって
発明された。そのため、初期のブログやチュートリアルでは「Technorati タグ」と呼ばれていた。
(信じられないだろうが本当の話だ。営利企業が、自分たちの仕事を楽にするために、全世界を説
得してメタデータを付加させたのだ。よくやったものだ!)その後、その構文はマイクロフォー
マットコミュニティで標準化され、単に rel="tag" と呼ばれるようになった。カテゴリやキーワー
ド、あるいはタグを個々の記事に関連付けられるようになっている多くのブログシステムでは、
rel="tag" リンクを使ってマークアップを行っている。ブラウザは、これらに関して何も特別なこ
とはしない。これらは、どんなページなのかを知るために検索エンジンが使うことを想定して設計
されているからだ。
3.5 HTML5 の新しい意味要素
HTML5 は、既存のマークアップを短くするためだけのものではない(それはそれで十分に役立つのだ
が)。いくつもの新しい意味要素が定義されている。HTML5 の仕様書で定義されている要素は以下のとお
りだ。
<section>
<section> 要素は、文書またはアプリケーションの汎用的なセクションを示す。この文脈でのセク
ションとは、主題ごとにまとめられたコンテンツ、通常は見出しを伴う。セクションの例として
は、章、タブインタフェース中の各タブ、論文中の番号付きセクションなどがある。Web サイト
のホームページも、例えば導入部、ニュース記事、連絡先などのいくつかのセクションに分割でき
†
監訳注:現在は Chrome もサポートしている。
46
3 章 HTML 文書の構造と意味付け
るだろう。
<nav>
<nav> 要素は、別のページまたはページ内の別の場所にリンクするセクション、つまりナビゲー
ションリンクのセクションだ。ページ上のリンクの集まりが、すべて <nav> 要素中にある必要は
ない。主要なナビゲーションブロックから構成されるセクションだけが <nav> 要素にふさわしい
のだ。例えば、Web サイトの多くが、サイトの利用条件、ホームページ、著作権に関するペー
ジなど短いリンクをフッタに設けていることが多い。このようなリンクは、<nav> 要素ではなく
<footer> 要素だけで十分だ。
<article>
<article> 要素は、例えばフィードなどで独立して配布または再利用されることを意図した文書、
ページ、アプリケーションまたはサイト中の自己完結した構成物を示す。例えばフォーラムへの投
稿、雑誌や新聞の記事、ブログ記事、ユーザの投稿したコメント、ポータルサイトやブログのサイ
ドバーによく見られるウィジェットやガジェットなど、どんな項目であっても自己完結していれば
よい。
<aside>
<aside> 要素は、その周りのコンテンツにあまり関係のないコンテンツから構成されるページのセ
クションであって、周りのコンテンツから離れていると見なされるものを示す。そのようなセク
ションは、印刷物の版面では囲み記事として表現されることが多い。この要素は、印刷物での抜粋
見出しや囲み記事のような効果を与えるために、広告、nav 要素の集まりなど、そのページの主要
なコンテンツとは離れていると考えられるコンテンツに対して使うことができる。
<hgroup>
<hgroup> 要素は、セクションの見出しを示す。この要素は、小見出し、副題、キャッチフレーズ
などの複数のレベルからなる見出しの h1 ∼ h6 要素をグループ化するために使われる。
<header>
<header> 要素は、導入またはナビゲーションの助けとなるグループを示す。<header> 要素は通常、
セクションの見出し(h1 ∼ h6 要素または hgroup 要素)を含むことが多いが、必ずしもそうとは
限らない。<header> 要素は、セクションの目次、検索フォーム、関連のあるロゴなどをグループ
化するために使うこともできる。
<footer>
<footer> 要素は、その一番近い祖先のセクションを構成するコンテンツまたはセクションを構成
するルート要素のフッタを示す。フッタは通常、そのセクションの著者、関連する文書へのリン
ク、著作権情報など、そのセクションに関する情報を含んでいる。フッタは必ずしもそのセクショ
ンの最後に表示されるとは限らないが、そうなっているのが普通だ。<footer> 要素がセクション
全体を含んでいる場合、それは付録や索引、長大な奥付、複雑な使用許諾契約などを表す。
3.6 ブラウザが不明な要素を取り扱う方法についての長い余談
47
<time>
<time> 要素は、24 時間表示の時刻、または補外グレゴリオ暦(proleptic Gregorian calendar)に
よる日付(時刻とタイムゾーンを含むこともできる)を示す。
<mark>
<mark> 要素は、参照目的でマークまたはハイライトされた文章を示す。
読者の皆さんがこれらの新しい要素を使い始めたくてうずうずしていることはよくわかっている。そうで
なければ、この章を読んでいるわけがないからだ。しかし、その前にちょっと寄り道をしておく必要がある。
3.6 ブラウザが不明な要素を取り扱う方法についての長い余談
すべてのブラウザは、サポートしている HTML 要素のマスターリストを持っている。例えば Mozilla
Firefox がサポートする要素は nsElementTable.cpp で定義されている†。このリストにない要素は、「不明
な要素」として取り扱われる。不明な要素については 2 つの基本的な質問がある。
その要素のスタイルはどうあるべきか?
デフォルトでは <p> は上下に空白があり、<blockquote> は左からインデントされ、<h1> は大きな
フォントで表示される。では、不明な要素はどのようなスタイルが当てられるべきだろうか。
その要素の DOM はどうあるべきか?
Mozilla の nsElementTable.cpp には、各要素が他のどの種類の要素を包含できるかという情報が
含まれている。例えば <p><p> のようなマークアップをしたとき、2 番目のパラグラフ要素は暗黙
に最初のパラグラフ要素を閉じることになるので、これらの要素は親子ではなく、兄弟要素とな
る。しかし例えば <p><span> と書いたときには、span はパラグラフを閉じない。Firefox は <p> が
ブロック要素であって、インライン要素である <span> を包含できることを知っているからだ。し
たがって、DOM では <span> は <p> の子要素となる。
ブラウザが異なれば、これらの質問に対する答も違ってくる。(衝撃的だが、これは事実だ。)主要なブラ
ウザの中では、Microsoft Internet Explorer の両方の質問に対する答が、最も問題を引き起こしやすい。
最初の質問は、比較的答えるのが簡単だ。不明な要素には一切特別なスタイルを適用しないこと。ページ
上のどこに現れようとも、そこで有効な CSS プロパティをすべて継承させ、ページ作成者が CSS ですべて
のスタイルを指定できること。ほとんどの場合これで大丈夫だが、ここにひとつ気を付けておくべき小さな
落とし穴がある。
†
http://mxr.mozilla.org/mozilla-central/source/parser/htmlparser/src/nsElementTable.cpp を参照。
48
3 章 HTML 文書の構造と意味付け
マークアップ教授から一言
すべてのブラウザは不明な要素をインラインレベル要素として表示する。つまり、display: inline という
CSS ルールを指定したのと同じように表示されるのだ。
HTML5 の新しい要素のいくつかは、ブロックレベル要素として定義されている。これはそれらの要素
が他のブロックレベル要素を含むことが許され、HTML5 に対応したブラウザはそれらをデフォルトで
display: block としてスタイル付けるのだ。これらの要素を古いブラウザでも使いたければ、スタイルを
自前で定義するしかない。
article,aside,details,figcaption,figure,
footer,header,hgroup,menu,nav,section {
display:block;
}
(このコードは Rich Clark による「HTML5 リセットスタイルシート)より抜粋したものだ。Rich のスタ
イルシートでは、この章の範囲を超えることも多く行っている。)
しかし、状況はさらに悪くなる。IE9 よりも前の Internet Explorer では、不明な要素に対するスタイル
指定が何ら適用されない。例えば、次のマークアップがあったとしよう。
<style type="text/css">
article { display: block; border: 1px solid red }
</style>
...
<article>
<h1>Welcome to Initech</h1>
<p>This is your <span>first day</span>.</p>
</article>
Internet Explorer(IE8 まで)は、<article> をブロックレベル要素と解釈せず、周りに赤い境界も表示
しない。すべてのスタイル規則が無視されてしまうのだ。Internet Explorer 9 ではこの問題が修正されて
いる†。
2 番目の問題は、ブラウザが不明な要素に出会ったときに生成される DOM の件だ。ここでも、最も問題
となるのは古いバージョンの Internet Explorer だ(バージョン 9 ではこの問題が修正されている)。IE8 ま
では、明示的に要素を認識できない場合には、その要素を子要素を持たない空ノードとして DOM に挿入
†
http://msdn.microsoft.com/en-us/ie/ff468705.aspx#_HTML_Parsing を 参 照。( 監 訳 注:IE9 で は 上 記 の <article> に 加
えいくつかの新しいブロックレベル要素について、デフォルトのスタイルが定義されている。詳細は開発者向け Internet
Explorer 9 ベータガイド ( http://msdn.microsoft.com/en-us/ie/ff468705.aspx#_HTML5_Semantic_Elements ) を参照さ
れたい。)
3.6 ブラウザが不明な要素を取り扱う方法についての長い余談
49
する。このため、その不明な要素の直接の子要素となってほしいすべての要素は、子要素ではなく兄弟要素
となってしまう。
ここで ASCII アートを使って違いを説明しよう。これは、HTML5 が規定する DOM だ。
article
|
+--h1 (article の子要素 )
| |
| +--text node "Welcome to Initech"
|
+--p (article の子要素、h1 の兄弟要素 )
|
+--text node "This is your "
|
+--span
| |
| +--text node "first day"
|
+--text node "."
しかし、Internet Explorer が生成する DOM は、次のようになる。
article ( 子要素を持たない )
h1 (article の兄弟要素 )
|
+--text node "Welcome to Initech"
p (h1 の兄弟要素 )
|
+--text node "This is your "
|
+--span
| |
| +--text node "first day"
|
+--text node "."
実はこの問題には、すばらしい回避策がある。実際に使う前に、JavaScript を使ってダミーの <article>
要素を生成しておけば、魔法のように Internet Explorer は <article> 要素を認識し、CSS を使ってスタイ
ル指定ができるようになるのだ。このダミー要素を DOM に挿入する必要は全くない。単純に、(ページご
とに)その要素を生成しさえすれば、IE が認識しない要素にもスタイルが指定できるようになるのだ。例
を示そう。
50
3 章 HTML 文書の構造と意味付け
<html>
<head>
<style>
article { display: block; border: 1px solid red }
</style>
<script>document.createElement("article");</script>
</head>
<body>
<article>
<h1>Welcome to Initech</h1>
<p>This is your <span>first day</span>.</p>
</article>
</body>
</html>
これは、すべてのバージョンの Internet Explorer で(なんと IE6 でも!)動作する。このテクニックを
さらに拡張して、すべての新しい HTML5 要素についてダミーを一度に生成しておけば(ここでも DOM
に挿入する必要は一切ないのでダミー要素が目に触れることはない)、HTML5 に対応していないブラウザ
のことをほとんど気にせず、これらの要素を使い始めることができる。
Remy Sharp は、これを行ってくれる「HTML5 有効化スクリプト」というぴったりな名前のスクリプト
を作成した(http://remysharp.com/2009/01/07/html5-enabling-script)。このスクリプトは執筆を開始し
てから幾度ものリビジョンを重ねているが、基本的なアイデアはこのようなものだ。
<!--[if lt IE 9]>
<script>
var e = ("abbr,article,aside,audio,canvas,datalist,details," +
"figure,footer,header,hgroup,mark,menu,meter,nav,output," +
"progress,section,time,video").split(',');
for (var i = 0; i < e.length; i++) {
document.createElement(e[i]);
}
</script>
<![endif]-->
<!--[if lt IE 9]> と <![endif]--> の 部 分 は、 条 件 コ メ ン ト だ。Internet Explorer は、 こ れ ら を if
文と同じように解釈する。つまり「現在のブラウザがバージョン 9 よりも前のバージョンの Internet
Explorer であれば、このブロックを実行せよ」という意味になる。他のすべてのブラウザは、ブロック全
体を HTML コメントとして取り扱う。つまり、このスクリプトを Internet Explorer(IE8 まで)は実行す
るが、他のブラウザは完全に無視するという結果になるのだ。これによって、このようなハックを必要とし
ないブラウザではページのロードが早くなることが期待できる。
JavaScript コード自体は、比較的わかりやすいだろう。変数 e に、"abbr"、"article"、"aside" などの
文字列からなる配列が代入される。その後、この配列上でループして、document.createElement() を呼
3.7 ヘッダ
51
んでそれぞれの名前の要素を生成する。しかし、戻り値を無視しているので、作成された要素が DOM に
挿入されることはない。それでも、これらの要素がページ中に後で現れたときに、望ましい形で Internet
Explorer に取り扱ってもらうためには十分なのだ。
「後で」という点が重要だ。このスクリプトは、ページの最後ではなく、ページの最初、なるべくなら
<head> 要素の中になければならない。そうすることによって、Internet Explorer はタグや属性をパースす
る前に、このスクリプトを実行することになる。もしこのスクリプトをページの最後に置いたとすると、手
遅れになってしまう。Internet Explorer はすでにマークアップを間違って解釈し、間違った DOM を構築
してしまっている。このスクリプトを実行したからといって、そこまで戻って手直ししてくれるわけではな
いのだ。
Remy Sharp は、このスクリプトの「縮小化バージョン」を作って Google Project Hosting(http://
code.google.com/p/html5shiv/)で公開している。(疑問に思った人のために説明しておくと、このスクリ
プト自体はオープンソースで MIT ライセンスされているので、どんなプロジェクトに使ってもよい。)お
望みなら、このスクリプトを「ホットリンク」することさえ可能だ。以下のように、公開されているバー
ジョンを直接参照すればよい。
<head>
<meta charset="utf-8" />
<title>My Weblog</title>
<!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
これで、HTML5 の新しい意味要素を使い始める準備ができたわけだ。
3.7 ヘッダ
サンプルページへ戻ろう。具体的に、ヘッダについて見てみる。
<div id="header">
<h1>My Weblog</h1>
<p class="tagline">A lot of effort went into making this effortless.</p>
</div>
...
<div class="entry">
<h2>Travel day</h2>
</div>
...
<div class="entry">
<h2>I'm going to Prague!</h2>
</div>
52
3 章 HTML 文書の構造と意味付け
このマークアップには、何も悪い点はない。このままにしておくほうが好みなら、それでもかまわない。
妥当な HTML5 だ。しかし HTML5 では、ヘッダやセクションに使える意味要素が追加されている。
まず、<div id="header"> をなくしてみよう。これはとてもよく使われているが、それ自体に意味は何
もない。div 要素には何の意味も定義されておらず、id 属性にも何の意味も定義されていない。(ユーザ
エージェントは、id 属性の値から何らかの意味を推測することを許されていない。)これを例えば <div
id="shazbot"> と変更しても、意味的には全く同じだ。もともと何の意味もないからだ。
HTML5 では、<header> 要素がこの目的のために定義されている。HTML5 の仕様には、<header> 要素
の使い方の実例がいくつも載っている。われわれのサンプルページに適用するなら、このようになるだろ
う。
<header>
<h1>My Weblog</h1>
<p class="tagline">A lot of effort went into making this effortless.</p>
...
</header>
これはよい。これを見た人は、誰でもこれがヘッダだということがわかるだろう。しかし、キャッチフ
レーズ(tagline)についてはどうだろう。これもまたよく使われているが、今までは標準的なマークアッ
プがなかったのだ。これをマークアップするのは、なかなか難しい。キャッチフレーズは小見出しのような
ものだが、本来の見出しとくっついている。つまり、セクションを作成しない小見出しのようなものなの
だ。
<h1> や <h2> のような見出し要素は、ページを構造付けしてくれる。ページ全体を見渡す(あるいはナ
ビゲートする)際に使えるアウトラインを作り出してくれる。スクリーンリーダーは、文書のアウトライ
ンを使って目の見えないユーザがページをナビゲートする手助けをしてくれる。文書のアウトラインを
視覚化するオンラインツール(http://gsnedders.html5.org/outliner/)やブラウザの拡張機能(http://
chrispederick.com/work/web-developer/)もある。
HTML 4 では、文書のアウトラインを作成する方法が <h1> ∼ <h6> 要素だけしかなかった。サンプルペー
ジのアウトラインは、次のようなものになる。
My Weblog (h1)
|
+--Travel day (h2)
|
+--I'm going to Prague! (h2)
ここまではよいのだが、「A lot of effort went into making this effortless」をマークアップする適当な方
法がない。もしこれを <h2> でマークアップしてしまうと、文書のアウトラインにあるべきでないノードが
できてしまうことになる。
3.7 ヘッダ
53
My Weblog (h1)
|
+--A lot of effort went into making this effortless. (h2)
|
+--Travel day (h2)
|
+--I'm going to Prague! (h2)
しかし、これはサンプルページの文書構造とは違う。キャッチフレーズはセクションを表すわけではな
い。単なる小見出しなのだ。
それでは、キャッチフレーズを <h2> でマークアップし、各記事は <h3> でマークアップしてみてはどうだ
ろう。いや、それではかえって悪くなる。
My Weblog (h1)
|
+--A lot of effort went into making this effortless. (h2)
|
+--Travel day (h3)
|
+--I'm going to Prague! (h3)
文書アウトライン中にあるべきでないノードは残っているし、さらに悪いことに、本来ルートノードに属
すべき子要素を「奪って」しまっている。問題はまさにここにあるのだ。HTML 4 では、小見出しを文書
アウトラインに追加せずにマークアップする方法がなかった。どんなに工夫しても、「A lot of effort went
into making this effortless」はアウトラインに現れてしまう。これが <p class="tagline"> のように意味
のないマークアップをしていた理由なのだ。
HTML5 では、この問題への解決策が提供されている。それが <hgroup> 要素だ。<hgroup> 要素は、2 個
またはそれ以上の関連する見出し要素をグループ化する働きをする。ここで「関連する」とは、全体として
文書アウトライン中で単一のノードを形成するという意味だ。
このマークアップを行うと、
<header>
<hgroup>
<h1>My Weblog</h1>
<h2>A lot of effort went into making this effortless.</h2>
</hgroup>
...
</header>
...
<div class="entry">
<h2>Travel day</h2>
</div>
54
3 章 HTML 文書の構造と意味付け
...
<div class="entry">
<h2>I'm going to Prague!</h2>
</div>
以下のような文書アウトラインが作成される。
My Weblog (hgroup の h1)
|
+--Travel day (h2)
|
+--I'm going to Prague! (h2)
HTML5 Outliner で自分の作成したページをテストして、見出し要素を正しく使えているかどうか確かめ
ることができる。
3.8 Article 要素
サンプルページをさらに見ていこう。このマークアップは、どうすればよいだろうか。
<div class="entry">
<p class="post-date">October 22, 2009</p>
<h2>
<a href="#"
rel="bookmark"
title="link to this post">
Travel day
</a>
</h2>
...
</div>
これも妥当な HTML5 だ。しかし HTML5 では、ページ上の記事をマークアップするというよくあるケー
スによりふさわしい要素が用意されている。それが <article> という、目的通りの名前を持つ要素だ。
<article>
<p class="post-date">October 22, 2009</p>
<h2>
<a href="#"
rel="bookmark"
title="link to this post">
Travel day
</a>
3.8 Article 要素
55
</h2>
...
</article>
おっと、こんなに簡単ではなかった。もうひとつ、変更しなくてはならない点があるのだ。説明は後です
ることにして、まず結果をお見せしよう。
<article>
<header>
<p class="post-date">October 22, 2009</p>
<h1>
<a href="#"
rel="bookmark"
title="link to this post">
Travel day
</a>
</h1>
</header>
...
</article>
お分かりだろうか。<h2> 要素が <h1> に変更され、<header> 要素の中に取り込まれている。<header> 要
素についてはついさっき説明したとおり、記事のヘッダを構成するすべての要素(この場合、記事の発行
日とタイトル)をグループ化することが目的だ。しかし、「<h1> はページに 1 つしか使えないんじゃなかっ
たっけ? こんなことをして、文書のアウトラインがおかしくなってしまわないの?」と思うかもしれな
い。大丈夫だ、でもそれを理解するためには、少し戻って説明する必要がある。
HTML 4 では、文書のアウトラインを構成する手がかりは <h1> ∼ <h6> 要素だけしかなかった。アウト
ラインの中に 1 個だけルートノードが現れてほしければ、マークアップ中には 1 個の <h1> しか使えない。
しかし HTML5 の仕様には、HTML5 の新しい意味要素を取り込んだ、文書アウトラインを生成するアルゴ
リズムが定義されている。この HTML5 のアルゴリズムでは、<article> 要素は新しいセクション、つまり
新しいノードを文書アウトラインに作成することになっている。そして HTML5 では、セクションごとに
<h1> 要素が持てるのだ。
これは HTML 4 からの大きな変更点だが、この変更の理由は以下のとおりだ。多くの Web ページは、実
際にはテンプレートから生成される。ひとつのソースから取ってきたコンテンツの一部がページ上に挿入さ
れ、また別のソースから取ってきたコンテンツの一部がページ上の別の場所に挿入される。多くのチュート
リアルは、このような説明をしている。「ここに HTML マークアップがありますから、コピーペーストし
て自分のページを作ってください。」これはコンテンツが小さいうちはいいが、ペーストしようとしたマー
クアップがセクション全体だったらどうなるだろう。その場合には、チュートリアルは以下のように説明こ
とになるだろう。「ここに HTML マークアップがありますから、コピーして、テキストエディタへペース
トし、そしてペーストする先のページの対応する見出しタグのレベルに合うように、見出しのタグを修正し
てください。」
3 章 HTML 文書の構造と意味付け
56
別の言い方をすれば、HTML 4 には汎用の見出し要素が存在しないのだ。<h1> ∼ <h6> という、固定した
番号の 6 種類の見出し要素はあるが、厳密にこの順序にしたがって入れ子にする必要がある。これは、特
にページを「書く」のではなく、「集めて来る」場合には、なかなか厄介だ。そこで HTML5 では、新しい
セクション要素と、既存の見出し要素に対する新しい規則を導入することによって、この問題を解決したと
いうわけだ。新しいセクション要素を使っているのなら、以下のマークアップをページのどこにでも修正せ
ずにコピーペーストできる。
<article>
<header>
<h1>A syndicated post</h1>
</header>
<p>Lorem ipsum blah blah...</p>
</article>
<h1> 要 素 を 含 ん で い る こ と は 問 題 と は な ら な い。 全 体 が <article> に 囲 ま れ て い る か ら だ。 こ の
<article> 要素は、文書アウトライン中に自己完結したノードを定義し、<h1> 要素はそのアウトラインノー
ドへタイトルを与える。ページ上のその他すべてのセクション要素は前のままのレベルを保つことができ
る。
マークアップ教授から一言
Web 上の出来事はすべて、私の説明よりも多少込み入っている。新しい「明示的な」セクション要素
(<article> の中に取り込まれた <h1> など)は、古い「暗黙の」セクション要素(単独で使われる <h1> 〜
<h6>)と、予想もしなかったような形で干渉する可能性がある。問題を起こしたくなければ、両方ではな
く、片方だけを使ったほうがいい。同じページ上で両方を使わなくてはならない場合には、必ずその結果を
HTML5 Outliner でチェックし、文書アウトラインが正常に構成されていることを検証してほしい。
3.9 日付と時間
わくわくするじゃないか。と言っても、「アメリカ国歌を逆回しで歌いながらエベレストからスキーで降
りてくる」という類の「わくわく」ではなく、意味的なマークアップに関しての話だが。サンプルページを
さらに見ていこう。次に注目すべきは、この部分だ。
<div class="entry">
<p class="post-date">October 22, 2009</p>
<h2>Travel day</h2>
</div>
どこかで見たような気がしないだろうか。記事が公開された日付を示す、よくあるパターンだが、裏付け
となる意味的なマークアップが存在しないため、ページ作成者は汎用的なマークアップにそれらしい class
3.9 日付と時間
57
属性を付加するという手法に頼ってきた。これもまた妥当な HTML5 だ。これを変更する必要は、ない。
しかし HTML5 には、この場合にぴったりのソリューションが用意されている。それが <time> 要素だ。
<time datetime="2009-10-22" pubdate>October 22, 2009</time>
<time> 要素は、3 つの部分に分けられる。
●
機械可読なタイムスタンプ
●
人間が読むためのテキスト
●
オプションの pubdate フラグ
この例では、datetime 属性には時刻は含まれず、日付だけが指定されている。日付のフォーマットは数
字 4 桁の年、2 桁の月、そして 2 桁の日をハイフンでつなげたものだ。
<time datetime="2009-10-22" pubdate>October 22, 2009</time>
時刻も含めたければ、日付の後に T を付加し、その後に時間を 24 時間形式で指定し、その後にタイム
ゾーンを指定する。
<time datetime="2009-10-22T13:59:47-04:00" pubdate>
October 22, 2009 1:59pm EDT
</time>
日付と時刻のフォーマットにはかなりの柔軟性がある。HTML5 の仕様書には有効な日付と時刻の文字列
の例がいくつも掲載されている。
上記の例で、テキスト、つまり <time> と </time> に挟まれた部分が、機械可読なタイムスタンプと一致
するように変更されていることに気付いただろうか。実は、そうする必要があるわけではない。機械可読な
日付やタイムスタンプが datetime 属性に指定されている限り、テキストは何でもよいのだ。したがって、
これも妥当な HTML5 となる。
<time datetime="2009-10-22">last Thursday</time>
これだって妥当な HTML5 だ。
<time datetime="2009-10-22"></time>
最後に残ったパズルのピースが、pubdate 属性だ。これは論理型の属性で、必要な場合にそれだけを付加
すればよい。
<time datetime="2009-10-22" pubdate>October 22, 2009</time>
58
3 章 HTML 文書の構造と意味付け
もし「裸の」属性が気に入らないなら、こう書いても同じ意味になる。
<time datetime="2009-10-22" pubdate="pubdate">October 22, 2009</time>
この pubdate 属性の意味するところは、以下の 2 つのどちらかだ。まず <time> 要素が <article> 要素の
中にある場合、このタイムスタンプはその記事が公開された日付であることを意味する。また <time> 要素
が <article> 要素の中にない場合、このタイムスタンプは文書が公開された日付であることを意味する。
ここで、HTML5 をフルに活用して書き直した後の記事全体を示しておこう。
<article>
<header>
<time datetime="2009-10-22" pubdate>
October 22, 2009
</time>
<h1>
<a href="#"
rel="bookmark"
title="link to this post">
Travel day
</a>
</h1>
</header>
<p>Lorem ipsum dolor sit amet...</p>
</article>
3.10 ナビゲーション
どの Web サイトでも、最も重要な部分のひとつがナビゲーションバーだ。CNN.com には、「Tech」
「Health」「Sports」など、別のニュースのセクションへリンクする「タブ」が、各ページの上部に表示さ
れている。Google の検索結果ページにはページの上部に同様のバーがあり、「画像」「動画」「地図」など、
Google の別のサービスで検索ができる。そして、われわれのサンプルページにもヘッダ部分にナビゲー
ションバーがあり、「home」「blog」「gallery」そして「about」という、この仮想サイトの別のセクション
へリンクしている。
このナビゲーションバーは、以下のようにマークアップされていた。
<div id="nav">
<ul>
<li><a href="#">home</a></li>
<li><a href="#">blog</a></li>
<li><a href="#">gallery</a></li>
<li><a href="#">about</a></li>
</ul>
</div>
3.10 ナビゲーション
59
これもまた妥当な HTML5 だ。しかし、4 つの項目のリストとしてマークアップされているこのリスト
が、サイトナビゲーションを構成するということは何も表現されてない。視覚的には、これがページのヘッ
ダ部分にあるということ、またリンクのテキストを読むことから、推測することは可能だ。しかし意味的に
は、このリンクのリストを他のリストから区別するものは何もない。
誰がサイトナビゲーションの意味について心配するか、だって? ひとつには、障害を持つ人たちだ
(http://diveintoaccessibility.org/)。なぜか? このようなシナリオを考えてみてほしい。あなたに運動障
害がある場合、マウスを使うことは困難か、あるいは全く不可能だ。だからマウスの代わりに、主要なナビ
ゲーションリンクに飛ぶ(あるいは、それをスキップする)ブラウザの拡張機能を使っている。また、こう
いう場合も考えられる。あなたには視覚障害があり、「スクリーンリーダー」と呼ばれる、Web ページを要
約して読み上げてくれる専用のプログラムを使っている。ページのタイトルを読み上げた後、次に重要な情
報が載っている場所は、ナビゲーションリンクになる。すばやくコンテンツにアクセスしたい場合には、ナ
ビゲーションバーへ飛び、そこから読み上げるようスクリーンリーダーに指示する。すばやくブラウズした
い場合には、ナビゲーションバーをスキップして主要なコンテンツを読み上げるようスクリーンリーダーに
指示する。どちらの場合でも、プログラムからナビゲーションリンクを認識できることが重要となる。
したがって、<div id="nav"> を使ってサイトナビゲーションをマークアップすることは何も悪くないの
だが、全く正しいことだとも言えない。現実に人々と対話する方法として、最適な方法ではないからだ。
HTML5 では、ナビゲーションのセクションをマークアップするための意味的な方法が用意されている。そ
れが、<nav> 要素だ。
<nav>
<ul>
<li><a
<li><a
<li><a
<li><a
</ul>
</nav>
href="#">home</a></li>
href="#">blog</a></li>
href="#">gallery</a></li>
href="#">about</a></li>
マークアップ教授に質問
Q:スキップリンクは <nav> 要素と互換性があるのでしょうか。HTML5 でもスキップリンクは必要です
か?
A:スキップリンクは、ナビゲーションのセクションをスキップして読むためのものだ。マウスを使わず
に Web ページの音読やナビゲートをしてくれるサードパーティのソフトウェアを使う、障害を持つユー
ザの助けとなる。スキップリンクを提供する方法やその理由については、http://www.webaim.org/
techniques/skipnav で学ぶことができる。
スクリーンリーダーが <nav> 要素を認識できるようにバージョンアップされれば、スキップリンクは廃れた
機能となるだろう。スクリーンリーダーが自動的に <nav> 要素でマークアップされたナビゲーションのセク
ションを飛び越えられるようになるからだ。しかし、Web 上のすべての障害を持つユーザが HTML5 対応
3 章 HTML 文書の構造と意味付け
60
のスクリーンリーダーソフトウェアにアップグレードするのはまだ先のことだろうから、<nav> セクション
を飛び越えるためのスキップリンクも提供し続けるべきだ。
3.11 フッタ
ついにわれわれは、サンプルページの終わりにたどり着いた。最後に話しておきたいことは、このページ
の最後にある。つまりフッタだ。フッタは以下のようにマークアップされていた。
<div id="footer">
<p>&#167;</p>
<p>&#169; 2001&#8211;9 <a href="#">Mark Pilgrim</a></p>
</div>
これは妥当な HTML5 だ。このままにしておくほうが好みなら、それでもかまわない。だが HTML5 に
は、これにぴったりな要素が用意されている。それが <footer> 要素だ。
<footer>
<p>&#167;</p>
<p>&#169; 2001&#8211;9 <a href="#">Mark Pilgrim</a></p>
</footer>
<footer> 要素を使うのにふさわしい場所はどこだろうか。おそらく、現在 <div id="footer"> としてい
る場所すべてだろう。循環論法のようだが、それが答だ。HTML5 の仕様書には次のように書かれている。
「フッタは通常、そのセクションの著者、関連文書へのリンク、著作権情報など、そのセクションに関する
情報を含んでいる。」このサンプルページのフッタは、まさにこれに該当する。短い著作権表記、「著者につ
いて」ページへのリンク。有名なサイトをいくつか見てみたところ、フッタの候補がたくさん見つかった。
●
CNN には、著作権表記、各国語サイトへのリンク、そしてサイト利用条件、プライバシー、CNN
について、問い合わせ、ヘルプなどのページへのリンクを含んだフッタがある。これらはすべて、
<footer> の材料としてふさわしいものだ。
●
Google のホームページはシンプルなことで有名だが、一番下には「広告掲載」、「Google につい
て」、著作権表記、そして Google のプライバシーポリシーへのリンクがある。これらすべてを
<footer> に取り込むことができる。
●
私のブログには、私のその他のサイトへのリンクと、著作権表記からなるフッタがある。<footer>
要素には最適だ。(これらのリンク自体は <nav> 要素に取り込むべきではないことに注意してほし
い。これらはサイトナビゲーションリンクではなく、別のサイトにある私の別のプロジェクトへの
リンクを集めたものに過ぎないからだ。)
最 近 流 行 し て い る の が 巨 大 な フ ッ タ(http://ui-patterns.com/pattern/FatFooter) だ。W3C の サ
3.11 フッタ
61
イト(http://www.w3.org/)のフッタを見てみよう。このフッタには 3 つのカラムがあり、それぞれ
「Navigation」、「Contact W3C」、そして「W3C Updates」とラベルが付いている。このマークアップは、
おおよそ次のようなものだ。
<div id="w3c_footer">
<div class="w3c_footer-nav">
<h3>Navigation</h3>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/standards/">Standards</a></li>
<li><a href="/participate/">Participate</a></li>
<li><a href="/Consortium/membership">Membership</a></li>
<li><a href="/Consortium/">About W3C</a></li>
</ul>
</div>
<div class="w3c_footer-nav">
<h3>Contact W3C</h3>
<ul>
<li><a href="/Consortium/contact">Contact</a></li>
<li><a href="/Help/">Help and FAQ</a></li>
<li><a href="/Consortium/sup">Donate</a></li>
<li><a href="/Consortium/siteindex">Site Map</a></li>
</ul>
</div>
<div class="w3c_footer-nav">
<h3>W3C Updates</h3>
<ul>
<li><a href="http://twitter.com/W3C">Twitter</a></li>
<li><a href="http://identi.ca/w3c">Identi.ca</a></li>
</ul>
</div>
<p class="copyright">Copyright © 2009 W3C</p>
</div>
これを意味的な HTML5 に変換するには、以下の変更を行うことになるだろう。
●
●
一番外側の <div id="w3c_footer"> を、<footer> 要素に変換。
最初と 2 個目の <div class="w3c_footer-nav"> のインスタンスを <nav> 要素に変換し、3 個目は
<section> 要素に変換。
●
<h3> ヘ ッ ダ は す べ て セ ク シ ョ ン 要 素 内 に 含 ま れ る た め、 こ れ を <h1> に 変 換。<nav> 要 素 は、
<article> 要素と同じように文書アウトライン中でセクションを形成するのだ(「3.8 Article 要素」
3 章 HTML 文書の構造と意味付け
62
を参照)。
最終的なマークアップは、次のようなものになるだろう。
<footer>
<nav>
<h1>Navigation</h1>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/standards/">Standards</a></li>
<li><a href="/participate/">Participate</a></li>
<li><a href="/Consortium/membership">Membership</a></li>
<li><a href="/Consortium/">About W3C</a></li>
</ul>
</nav>
<nav>
<h1>Contact W3C</h1>
<ul>
<li><a href="/Consortium/contact">Contact</a></li>
<li><a href="/Help/">Help and FAQ</a></li>
<li><a href="/Consortium/sup">Donate</a></li>
<li><a href="/Consortium/siteindex">Site Map</a></li>
</ul>
</nav>
<section>
<h1>W3C Updates</h1>
<ul>
<li><a href="http://twitter.com/W3C">Twitter</a></li>
<li><a href="http://identi.ca/w3c">Identi.ca</a></li>
</ul>
</section>
<p class="copyright">Copyright © 2009 W3C</p>
</footer>
3.12 参考文献
この章全体で使用したサンプルページ:
●
変更前(HTML 4)
http://diveintohtml5.info/examples/blog-original.html
●
変更後(HTML5)
http://diveintohtml5.info/examples/blog-html5.html
3.12 参考文献
63
文字エンコーディングについて:
●
Joel Spolsky による「すべてのソフトウェア開発者が、Unicode と文字セットについて絶対に(言
い訳なしに)知っておかなくてはならない最低限の知識」(http://www.joelonsoftware.com/
articles/Unicode.html)
●
Tim Bray による「Unicode の利点について」(http://www.tbray.org/ongoing/When/200x/2003
「文字列について」(http://www.tbray.org/ongoing/When/200x/2003/04/13
/04/06/Unicode)、
/Strings)、および「文字とバイトの違いについて」(http://www.tbray.org/ongoing/When/200x
/2003/04/26/UTF)
Internet Explorer で HTML5 の新機能を使う方法について:
●
Sjoerd Visscher による「IE で不明な要素にスタイルを設定する方法」
http://xopus.com/devblog/2008/style-unknown-elements.html
●
John Resig による HTML5 shiv
http://ejohn.org/blog/html5-shiv/
●
Remy Sharp による HTML5 有効化スクリプト
http://remysharp.com/2009/01/07/html5-enabling-script/
標準モードと DOCTYPE のスニッフィングについて:
●
Henri Sivonen による「DOCTYPE で発動されるブラウザモードについて」(http://hsivonen.iki.
fi/doctype/)。これは、この話題について読むべき唯一の記事だ。他にもたくさんの記事があるが、
それらは内容が古かったり、不完全だったり、あるいは間違っていたりする。
HTML5 対応バリデーションツール:
●
Validator.nu (X)HTML5 バリデーションツール
http://html5.validator.nu
65
4章
Canvas による描画
4.1 はじめに
HTML5 は <canvas> を「解像度に依存するビットマップ描画機能で、グラフ、ゲームのグラフィックス、
あるいはその他のビジュアル画像をオンザフライで表示できる」と定義している†。Canvas はページ中の
矩形領域で、その中に JavaScript を使って何でも好きなものを描き込める。以下の表は、本書の執筆時点
でのブラウザの基本的な Canvas のサポート状況を示したものだ。
表 4-1 Canvas のサポート状況
IEa
Firefox
Safari
Chrome
Opera
iPhone
Android
7.0 ∼
3.0 ∼
3.0 ∼
3.0 ∼
10.0 ∼
1.0 ∼
1.0 ∼
a:Internet Explorer 7 と 8 ではサードパーティ製の explorercanvas ライブラリが必要。Internet Explorer 9 は <canvas> をサポー
トしている。
Canvas そのものは目には見えない。<canvas> 要素自身は何の内容も持たず、またボーダーも指定されて
ないからだ。マークアップは以下のようになる。
<canvas width="300" height="225"></canvas>
図 4-1 では、わかりやすさのために Canvas に点線のボーダーを与えている。
<canvas> 要素はひとつのページに複数個置くことができる。この場合、各 Canvas は別個に DOM 中に
現れ、それぞれ独自に状態を保持する。各 Canvas に id 属性を付与すれば、他の要素と同じようにアクセ
スできる。
id 属性を付与したマークアップは以下のようになる。
<canvas id="a" width="300" height="225"></canvas>
こうすると、DOM 中で容易に <canvas> 要素を取り扱えるようになる。
†
http://whatwg.org/html5#the-canvas-element を参照。
66
4 章 Canvas による描画
図 4-1 ボーダーを与えた Canvas
var a_canvas = document.getElementById("a");
4.2 単純なシェープ
表 4-2 シェープのサポート状況
IEa
Firefox
Safari
Chrome
Opera
iPhone
Android
7.0 ∼
3.0 ∼
3.0 ∼
3.0 ∼
10.0 ∼
1.0 ∼
1.0 ∼
a:Internet Explorer 7 と 8 ではサードパーティ製の explorercanvas ライブラリが必要。Internet Explorer 9 は <canvas> シェープ
をサポートしている。
すべての Canvas は初期状態で空白だ。これでは面白くないので、何か描いてみよう。onclick ハンド
ラを使って、矩形を描画する関数を呼ぶことにする(実際に試してみたければ http://diveintohtml5.info/
canvas.html を見てほしい)。
function draw_b() {
var b_canvas = document.getElementById("b");
var b_context = b_canvas.getContext("2d");
b_context.fillRect(50, 25, 150, 100);
}
この関数の最初の行は、DOM 中の <canvas> 要素を見つけているだけで、何も特別なことはしていない。
重要なのは 2 行目だ。すべての Canvas には描画コンテキストが存在し、Canvas に対する操作はすべてこ
の描画コンテキストに対して行う。DOM 中の <canvas> 要素を(document.getElementById() あるいはお
好みのメソッドを使って)見つけたら、その getContext() メソッドを呼び出す。getContext() メソッドに
は、必ず文字列 "2d" を渡さなくてはならない。
function draw_b() {
var b_canvas = document.getElementById("b");
var b_context = b_canvas.getContext("2d");
4.2 単純なシェープ
67
b_context.fillRect(50, 25, 150, 100);
}
マークアップ教授に質問
Q:3D の Canvas は存在するのですか?
A:まだ、ない。独自の 3D Canvas API を実験的に提供しているベンダもあるが、標準化はされていな
い。HTML5 仕様の注には、「この仕様の将来のバージョンには、おそらく 3d コンテキストが定義される
ことになるだろう。」と書かれている†。
さて、<canvas> 要素を作成し、その描画コンテキストが取得できた。この描画コンテキストに、すべて
の描画メソッドとプロパティが定義されている。矩形を描画する際に関係するプロパティとメソッドは、以
下のとおりだ。
●
fillStyle プロパティは、CSS の色指定、パターン、またはグラデーションによる塗りつぶしのス
タイルを指定する。(グラデーションについては、後で説明する。)fillStyle プロパティのデフォ
ルトは単色の黒だが、設定すれば変えられる。ページが開いていて、リセットされない限り、各描
画コンテキストは自分のプロパティを保持している。
●
fillRect(x, y, width, height) は矩形を描画する。描画した矩形は、現在の塗りつぶしスタイル
を使って塗りつぶされる。
●
strokeStyle プロパティは、fillStyle と同じように CSS の色指定、パターン、またはグラデー
ションで線のスタイルを指定する。
●
strokeRect(x, y, width, height) は、現在の線のスタイルで矩形を描画する。strokeRect は塗
りつぶしを行わない。輪郭線を描くだけだ。
●
clearRect(x, y, width, height) は、指定された矩形領域中のピクセルをクリアする。
マークアップ教授に質問
Q:Canvas を「リセット」できますか?
†
監 訳 注 : 現 在 は OpenGL を 管 理 す る 非 営 利 の 業 界 団 体 Khronos Group に よ っ て、WebGL(http://www.khronos.org/
webgl/)という 3D コンテキスト API 仕様が策定されている。Khronos には Apple、Google、Mozilla、Opera が参加して
おり、WebGL の実装も Chrome、Firefox、Webkit で進められている。
4 章 Canvas による描画
68
A:できる。<canvas> 要素の幅や高さを設定すると、その内容は消去され、その描画コンテキストのすべ
てのプロパティはデフォルト値にリセットされる。実際に幅を変更する必要はない。以下のように、現在の
値に再設定するだけでいいのだ。
var b_canvas = document.getElementById("b");
b_canvas.width = b_canvas.width;
先ほどのコードに戻ろう。
var b_canvas = document.getElementById("b");
var b_context = b_canvas.getContext("2d");
b_context.fillRect(50, 25, 150, 100);
fillRect() メソッドを呼ぶと矩形が描画され、現在の塗りつぶしスタイル(変更していなければ黒)で
塗りつぶされる。この矩形の左上隅の座標は (50, 25)、幅は 150、高さは 100 だ。ここで、理解を助ける
ために、Canvas の座標系について説明しよう。
4.3 Canvas の座標
Canvas は 2 次元のグリッドだ。座標 (0, 0) は Canvas の左上隅に対応する。X 軸の値は、Canvas の右端
に近付くにしたがって増加する。Y 軸の値は、Canvas の下端に近付くにしたがって増加する。
図 4-2 に示す座標の説明図は、<canvas> 要素を使って描いたものだ。これは以下のものから成り立って
いる。
●
一連の灰色の垂直線
●
一連の灰色の水平線
●
2 本の黒い水平線
●
矢印を構成する、2 本の短くて黒い斜めの線
●
2 本の黒い垂直線
●
もうひとつの矢印を構成する、2 本の短くて黒い斜めの線
●
文字「x」
●
文字「y」
●
左上隅近くのテキスト「(0, 0)」
●
右下隅近くのテキスト「(500, 375)」
●
左上隅のドットと、右下隅のドット
4.4 パス
69
図 4-2 Canvas の座標の説明図
以下のセクションでは、これらを作成する方法について調べていく。それにはまず、<canvas> 要素それ
自体を定義する必要がある。<canvas> 要素には矩形領域の幅 width と高さ height、そしてこの Canvas を
識別するための id を指定する。
<canvas id="c" width="500" height="375"></canvas>
次に、DOM 中の <canvas> 要素を見つけるためのスクリプトと、その描画コンテキストを得るためのス
クリプトが必要だ。
var c_canvas = document.getElementById("c");
var context = c_canvas.getContext("2d");
これで、線を描く準備ができた。
4.4 パス
表 4-3 パスのサポート状況
IEa
Firefox
Safari
Chrome
Opera
iPhone
Android
7.0 ∼
3.0 ∼
3.0 ∼
3.0 ∼
10.0 ∼
1.0 ∼
1.0 ∼
a:Internet Explorer 7 と 8 ではサードパーティ製の explorercanvas ライブラリが必要。Internet Explorer 9 は <canvas> パスをサ
ポートしている。
インクで絵を描くことを想像してみよう。間違えるかもしれないので、いきなり最初から描くことはしな
いはずだ。そうではなく、まず鉛筆で直線や曲線をスケッチし、できばえを確かめてからそのスケッチをイ
4 章 Canvas による描画
70
ンクでトレースしていくことになるだろう。
すべての Canvas にはパスがある。パスを定義することは、鉛筆で下書きをするようなものだ。思うまま
に描いてよいが、インクをつけたペンでパスをトレースしなければ最終的な作品に表れることはない。
鉛筆で直線を描くには、以下の 2 つのメソッドを使う。
●
moveTo(x, y) は、指定された始点へ鉛筆を移動する。
●
lineTo(x, y) は、指定された終点まで線を描く。
moveTo() と lineTo() を何度も呼ぶと、それだけパスは複雑になっていく。これらは「鉛筆」メソッドな
ので、何度呼んだとしてもインクメソッドのどれかを呼ぶまでは、Canvas には何も表示されない。
灰色のグリッドを描くことから始めてみよう。
for (var x = 0.5; x < 500; x += 10) {
context.moveTo(x, 0);
context.lineTo(x, 375);
}
for (var y = 0.5; y < 375; y += 10) {
context.moveTo(0, y);
context.lineTo(500, y);
}
マークアップ教授に質問
Q:x と y を 0.5 から始めたのはなぜですか?どうして 0 じゃだめなんですか?
A:ピクセルを、大きな正方形だと思ってほしい。整数の座標(0、1、2…)はその正方形の辺に相当する。
整数座標の点の間に 1 単位幅の線を描くと、その線は隣り合う正方形のピクセルにまたがることになるの
で、結果として線は 2 ピクセルの幅となる。1 ピクセルだけの幅の線を描くには、線と垂直の方向に 0.5
だけ座標をずらす必要があるのだ。
(1, 0) から (1, 3) まで線を引くことを考えてみよう。ブラウザは x=1 な箇所の両側に 0.5 ピクセルの線
を引くだろう。しかし、画面は 0.5 ピクセルを表示することができないので、結果として 2 ピクセルの幅
に線がまたがってしまう。
4.4 パス
71
しかし、(1.5, 0) から (1.5, 3) まで線を引くとしたらどうだろうか。ブラウザは x=1.5 な箇所の両端に
0.5 ピクセルの線を引くことになる。結果はそう、ちょうど 1 ピクセルの線が引かれることになるのだ。
(図を提供してくれた Jason Johnson に感謝する。)
これらはすべて「鉛筆」メソッドだ。まだ何も Canvas 上には表示されない。表示するには「インク」メ
ソッドが必要だ。
context.strokeStyle = "#eee";
context.stroke();
図 4-3 Canvas 上に描かれたグリッド
72
4 章 Canvas による描画
stroke() は「インク」メソッドのひとつで、これらの moveTo() と lineTo() によって定義された複雑なパ
スを、実際に Canvas へ描くという働きをする。strokeStyle によって線の色が決まる。図 4-3 がその結果
だ。
次に、水平の矢印を描こう。パス上の直線と曲線は、すべて同じ色(またはグラデーション)で描かれ
る。矢印は別の色のインク、つまり灰色ではなく黒で描きたいので、新しくパスを始める必要がある。
context.beginPath();
context.moveTo(0, 40);
context.lineTo(240, 40);
context.moveTo(260, 40);
context.lineTo(500, 40);
context.moveTo(495, 35);
context.lineTo(500, 40);
context.lineTo(495, 45);
垂直の矢印も、全く同じ要領だ。垂直の矢印はさっき引いた水平の矢印と同じ色なので、また新しいパス
を始める必要はない。2 本の矢印は、同一のパスに含まれることになる。
context.moveTo(60,
context.lineTo(60,
context.moveTo(60,
context.lineTo(60,
context.moveTo(65,
context.lineTo(60,
context.lineTo(55,
0);
153);
173);
375);
370);
375);
370);
さっき矢印は黒で描くと言ったが、strokeStyle はまだ灰色のままだ。(新しいパスを始めても fillStyle
と strokeStyle はリセットされない。)大丈夫だ、問題ない。さっき実行したのは「鉛筆」メソッドだから
だ。しかし実際に線を「インク」で描く前に、strokeStyle を黒に設定する必要がある。そうしないと 2 本
の矢印は灰色になってしまい、ほとんど見分けが付かなくなってしまう。色を黒に変更して Canvas に 2 本
の矢印を描くには、以下のようにすればよい。
context.strokeStyle = "#000";
context.stroke();
図 4-4 が、その結果だ。
4.5 テキスト
73
図 4-4 Canvas 上に描かれたラベルなしの矢印
4.5 テキスト
表 4-4 テキストのサポート状況
IEa
Firefoxb
Safari
Chrome
Opera
iPhone
Android
7.0 ∼
3.0 ∼
3.0 ∼
3.0 ∼
10.0 ∼
1.0 ∼
1.0 ∼
a:Internet Explorer 7 と 8 ではサードパーティ製の explorercanvas ライブラリが必要。Internet Explorer 9 は <canvas> テキスト
をサポートしている。
b:Mozilla Firefox 3.0 では互換性シムが必要。
Canvas には線だけではなく、テキストを描くこともできる。Web ページにテキストを描く場合とは違っ
て、ボックスモデルは存在しない。つまり、フロート、マージン、パディング、文字送りなど、おなじみの
CSS レイアウトのテクニックは一切使えないのだ。(そのほうがいいという人もいるだろう。)Canvas では、
フォントの属性を設定し、Canvas 上の座標にテキストを描くことはできる。
描画コンテキスト(「4.2 単純なシェープ」を参照)で利用できるフォント属性は以下のとおりだ。
●
font には、CSS の font 規則に指定できるものなら何でも指定できる。これにはフォントスタイ
ル、スモールキャップス、フォントのウェイト、フォントサイズ、行の高さ、そしてフォントファ
ミリが含まれる。
●
textAlign は、テキスト揃えを指定する。これは CSS の text-align 規則と(全く同じではないが)
同様のものだ。指定できる値は start、end、left、right、および center だ。
●
textBaseline は、テキストが描かれる位置を、始点から相対的に指定する。指定できる値は top、
74
4 章 Canvas による描画
hanging、middle、alphabetic、ideographic、および bottom だ。
textBaseline はちょっと複雑だ。テキストとは複雑なものだからだ。(英語のテキストは別に複雑ではな
いが、Canvas には任意の Unicode 文字を描くことができ、Unicode は複雑なのだ。)HTML5 仕様は、テ
キストのベースラインの違いを以下のように説明している†。
em square の 上 端(top) は フ ォ ン ト グ リ フ の 上 端 と ほ ぼ 一 致 し、 吊 り ベ ー ス ラ イ ン(hanging
baseline)は「
」などのグリフが揃えられる位置であり、中心線(middle)は em square の上端
と em square の下端との中間であり、アルファベットベースライン(alphabetic baseline)は「Á」、
「ÿ」、「ƒ」、および「Ω」などの文字が揃えられる位置であり、表意文字ベースライン(ideographic
baseline)は「私」や「達」などのグリフが揃えられる位置であり、そして em square の下端(bottom)
はフォント中のグリフの下端にほぼ一致する。em square から大きく飛び出しているグリフがあるた
め、バウンディングボックスの上端と下端はこれらのベースラインから遠く離れている場合がある(図
4-5 を参照)。
英語などの単純なアルファベットの場合は、textBaseline プロパティには top、middle、bottom だけを
使っているのが安全だ。
それではテキストを描いてみよう。Canvas 内に描かれたテキストは <canvas> 要素そのもののフォント
のサイズとスタイルを継承するが、描画コンテキストの font プロパティを設定して変更できる。
context.font = "bold 12px sans-serif";
context.fillText("x", 248, 43);
context.fillText("y", 58, 165);
実際にテキストを描くには、fillText() メソッドを使う。
バウンディングボックスの上端
em squareの上端
吊りベースライン
中心線
アルファベット 表意文字
ベースライン ベースライン
em squareの下端
バウンディングボックスの下端
図 4-5 テキストのベースライン
†
http://whatwg.org/html5#dom-context-2d-textbaseline を参照。
4.5 テキスト
75
context.font = "bold 12px sans-serif";
context.fillText("x", 248, 43);
context.fillText("y", 58, 165);
マークアップ教授に質問
Q:Canvas にテキストを描くとき、相対フォントサイズを指定できますか?
A:できる。ページ上の他の HTML 要素と同じように、<canvas> 要素自体にもページの CSS 規則に基づ
いてフォントサイズが計算されている。context.font プロパティに 1.5em や 150% のように相対フォントサ
イズを指定すると、ブラウザはこれを <canvas> 要素自体のフォントサイズ(計算値)と掛け合わせて設定
するのだ。
左上隅のテキストは、上端を y=5 にあわせることにしよう。だが、テキストの高さを測ってベースライン
の位置を計算するのは面倒だ。代わりに、textBaseline を top に設定して、テキストのバウンディングボッ
クスの左上隅の座標を指定すればよい。
context.textBaseline = "top";
context.fillText("( 0 , 0 )", 8, 5);
次は右下隅のテキストだ。テキストの右下隅を、Canvas の右下隅から数ピクセル離れた座標 (492,
370) にあわせることにしよう。ここでも、テキストの幅や高さを測るのは面倒だ。textAlign を right
に、textBaseline を bottom に設定して、テキストのバウンディングボックスの右下隅の座標を指定して
fillText() を呼べばよい。
context.textAlign = "right";
context.textBaseline = "bottom";
context.fillText("( 500 , 375 )", 492, 370);
図 4-6 が、その結果だ。
おっと、隅のドットを忘れていた。円を描く方法については後で説明するが、ここではちょっとずるをし
て矩形を描いて済ませることにしよう(「4.2 単純なシェープ」を参照)。
context.fillRect(0, 0, 3, 3);
context.fillRect(497, 372, 3, 3);
これでおしまい。図 4-7 が完成した作品だ。
76
4 章 Canvas による描画
図 4-6 Canvas 上に描かれたラベル付きの矢印
図 4-7 Canvas 上に描かれた Canvas の座標の説明図
4.6 グラデーション
77
4.6 グラデーション
表 4-5 グラデーションのサポート状況
IEa
Firefox
Safari
Chrome
Opera
iPhone
Android
線形グラデーション
7.0 ∼
3.0 ∼
3.0 ∼
3.0 ∼
10.0 ∼
1.0 ∼
1.0 ∼
円形グラデーション
9.0 ∼
3.0 ∼
3.0 ∼
3.0 ∼
10.0 ∼
1.0 ∼
1.0 ∼
a:Internet Explorer 7 と 8 ではサードパーティ製の explorercanvas ライブラリが必要。Internet Explorer 9 は <canvas> グラデー
ションをサポートしている。
この章では、単色で塗りつぶした矩形を描く方法(「4.2 単純なシェープ」を参照)および単色で線を描
く方法(「4.4 パス」を参照)について、すでに説明した。しかし、シェープや線は単色以外で描くことも
できる。グラデーションを使えば、いろいろな効果が楽しめる。図 4-8 は、グラデーションの一例だ。
マークアップは、他の Canvas と同じだ。
<canvas id="d" width="300" height="225"></canvas>
まず、<canvas> 要素を見つけ、その描画コンテキストを得る。
var d_canvas = document.getElementById("d");
var context = d_canvas.getContext("2d");
描画コンテキストが得られれば、グラデーションを定義することができる。グラデーションとは、2 色ま
たはそれ以上の色の間のスムーズな移り変わりのことだ。Canvas の描画コンテキストは 2 種類のグラデー
ションをサポートしている。
●
createLinearGradient(x0, y0, x1, y1) は、(x0, y0) から (x1, y1) への直線に沿って色が移り
変わる。
●
createRadialGradient(x0, y0, r0, x1, y1, r1) は、2 個の円の間で放射状に色が移り変わる。
最初の 3 個の引数は、原点 (x0, y0) および半径 r0 で表現される、開始側の円を表す。最後の 3
図 4-8 左側から右側への、線形グラデーション
78
4 章 Canvas による描画
個の引数は、原点 (x1, y1) および半径 r1 で表現される、終了側の円を表す。
線形グラデーションを作成してみよう。グラデーションはどんなサイズでも作れるが、Canvas と同じ
300 ピクセル幅にしておく。
var my_gradient = context.createLinearGradient(0, 0, 300, 0);
2 個の y の値(2 番目と 4 番目の引数)が両方とも 0 なので、このグラデーションは左側から右側へ一様
に色が移り変わる。
グラデーションのオブジェクトを作成したら、次はグラデーションの色を定義する。グラデーションに
は、2 種類またはそれ以上の基準色を指定する。基準色は、グラデーションの中のどの位置に指定してもよ
い。基準色を追加するには、グラデーションの中での位置を指定する必要がある。グラデーションの中での
位置は、0 と 1 の間で指定する。
黒から白へと移り変わるグラデーションを定義してみよう。
my_gradient.addColorStop(0, "black");
my_gradient.addColorStop(1, "white");
グラデーションを定義しただけでは、Canvas 上には何も描かれない。メモリのどこかにオブジェクトが
存在するだけだからだ。グラデーションを描くには、fillStyle をグラデーションに設定し、矩形や直線な
どのシェープを描けばよい。
context.fillStyle = my_gradient;
context.fillRect(0, 0, 300, 225);
図 4-9 が、その結果だ。
上側から下側へと色が移り変わるグラデーションがほしければ、グラデーションのオブジェクトを作成す
る際、x の値(1 番目と 3 番目の引数)を一定に保ち、y の値(2 番目と 4 番目の引数)を 0 から Canvas の
図 4-9 左から右への線形グラデーション
4.6 グラデーション
高さまで変化させればよい。
var my_gradient = context.createLinearGradient(0, 0, 0, 225);
my_gradient.addColorStop(0, "black");
my_gradient.addColorStop(1, "white");
context.fillStyle = my_gradient;
context.fillRect(0, 0, 300, 225);
図 4-10 が、その結果だ。
また、例えば以下のように、斜めのグラデーションを作成することもできる。
var my_gradient = context.createLinearGradient(0, 0, 300, 225);
my_gradient.addColorStop(0, "black");
my_gradient.addColorStop(1, "white");
context.fillStyle = my_gradient;
context.fillRect(0, 0, 300, 225);
図 4-11 が、その結果だ。
図 4-10 上から下への線形グラデーション
図 4-11 斜めの線形グラデーション
79
4 章 Canvas による描画
80
4.7 画像
表 4-6 Canvas 画像のサポート状況
IEa
Firefox
Safari
Chrome
Opera
iPhone
Android
7.0 ∼
3.0 ∼
3.0 ∼
3.0 ∼
10.0 ∼
1.0 ∼
1.0 ∼
a:Internet Explorer 7 と 8 ではサードパーティ製の explorercanvas ライブラリが必要。Internet Explorer 9 は <canvas> イメージ
をサポートしている。
図 4-12 は、<img> 要素を使って表示した猫の画像だ。
図 4-13 は、同じ猫の画像を Canvas 上に表示したものだ。
Canvas の描画コンテキストには、Canvas 上に画像を描くための下記のメソッドが定義されている。
●
drawImage(image, dx, dy) は、画像を Canvas 上に描く。与えられた座標 (dx, dy) が画像の左
上隅になる。座標 (0, 0) を与えれば、画像は Canvas の左上隅に描かれることになる。
●
drawImage(image, dx, dy, dw, dh) は、画像を幅 dw と高さ dh に拡大もしくは縮小し、Canvas
上の座標 (dx, dy) に描く。
●
drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh) は、画像の矩形領域 (sx, sy, sw, sh) を
クリッピングし、大きさ (dw, dh) に拡大もしくは縮小し、Canvas 上の座標 (dx, dy) に描く。
HTML5 の仕様書は、drawImage() の引数について以下のように説明している†。
コピー元の領域は、四隅の座標が (sx, sy)、(sx+sw, sy)、(sx+sw, sy+sh)、(sx, sy+sh) であるよう
な(コピー元画像中の)領域である。
図 4-12 <img> 要素を使って表示した猫の画像
図 4-13 <canvas> 要素を使って表示した猫の画像
†
http://whatwg.org/html5#images を参照。
4.7 画像
81
コピー先の領域は、四隅の座標が (dx, dy)、(dx+dw, dy)、(dx+dw, dy+dh)、(dx, dy+dh) であるよう
な(Canvas 内の)領域である。
図 4-14 に、これらの引数を図示した。
Canvas に画像を描くには、まず画像が必要だ。画像は既存の <img> 要素でもいいし、JavaScript を使っ
て作成した Image() オブジェクトでもよい。いずれにしても、Canvas に描く前に画像が完全にロードされ
ている必要がある。
既存の <img> 要素を使う場合には、window.onload イベント内で Canvas にその画像を描くのが安全だ。
<img id="cat" src="images/cat.png"
alt="sleeping cat" width="177" height="113">
<canvas id="e" width="177" height="113"></canvas>
<script>
window.onload = function() {
var canvas = document.getElementById("e");
var context = canvas.getContext("2d");
var cat = document.getElementById("cat");
context.drawImage(cat, 0, 0);
};
</script>
JavaScript で画像オブジェクトを作成する場合には、Image.onload イベント内で Canvas にその画像を描
コピー元の画像
sy
コピー先のCanvas
sx
sh
dy
sw
dx
dh
dw
図 4-14 drawImage() による画像から Canvas へのマッピング
82
4 章 Canvas による描画
くのが安全だ。
<canvas id="e" width="177" height="113"></canvas>
<script>
var canvas = document.getElementById("e");
var context = canvas.getContext("2d");
var cat = new Image();
cat.src = "images/cat.png";
cat.onload = function() {
context.drawImage(cat, 0, 0);
};
</script>
オプションである drawImage() の 4 番目と 5 番目の引数は、画像のスケーリングを行う。図 4-15 は、同
じ猫の画像を幅・高さとも半分に縮小し、ひとつの Canvas 内の異なる座標に繰り返し描いたものだ。
この「マルチキャット効果」は、以下のスクリプトで作成した。
cat.onload = function() {
for (var x = 0, y = 0;
x < 500 && y < 375;
x += 50, y += 37) {
context.drawImage(cat, x, y, 88, 56);
}
};
図 4-15 マルチキャット!
4.8 IE の場合
83
ここまで読み進んで、こんな疑問を持たなかっただろうか。「そもそも、なぜ Canvas に画像を描く必要
があるんだ? <img> 要素と CSS 規則を使えば済む話なのに、わざわざ話を複雑にする意味はあるのか?」
この「マルチキャット」にしても、<img> 要素を 10 個オーバーラップさせれば同じ効果が得られる。
単純な答としては、Canvas にテキストを描く(「4.5 テキスト」を参照)理由と同じことが言える。さっ
き作成した Canvas の座標の説明図(「4.3 Canvas の座標」を参照)には、テキスト、直線、そしてシェー
プが含まれている。Canvas 上のテキスト要素は、より大きな作品の一部となっているのだ。drawImage()
を使えば、アイコン、スプライト、あるいはその他のグラフィックスを含む、より複雑な図を簡単に作成で
きる。
4.8 IE の場合
バージョン 9.0 より前の Internet Explorer は、Canvas API をサポートしていない。(IE9 は Canvas API
をサポートしている †。)古いバージョンの Internet Explorer では VML と呼ばれる Microsoft 独自の技
術がサポートされており、これを使って <canvas> 要素とほぼ同じことができる。そして誕生したのが、
excanvas.js だ。
ExplorerCanvas(excanvas.js)††とは、Canvas API を Internet Explorer に実装する、オープンソース
の Apache ライセンスされた JavaScript ライブラリだ。これを使うには、以下のような <script> 要素を
ページの最初に書けばよい。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Dive Into HTML 5</title>
<!--[if lt IE 9]>
<script src="excanvas.js"></script>
<![endif]-->
</head>
<body>
...
</body>
</html>
<!--[if lt IE 9]> と <![endif]--> の部分は、条件付きコメントだ。Internet Explorer はこれらを if
文として解釈する。つまり、「もし現在のブラウザがバージョン 9 より前の Internet Explorer ならば、こ
のブロックを実行せよ」という意味になる。他のすべてのブラウザは、このブロック全体を HTML のコメ
ントとして取り扱う。つまり、Internet Explorer 7 と 8 は excanvas.js をダウンロードして実行するが、他
のブラウザはスクリプト全体を無視する(ダウンロードも実行もしない)という結果になる。これによっ
て、Canvas API をネイティブに実装しているブラウザでは、ページのロードが早くなることが期待できる。
†
http://msdn.microsoft.com/en-us/ie/ff468705.aspx#_HTML5_canvas を参照。
††
http://code.google.com/p/explorercanvas/ を参照。
4 章 Canvas による描画
84
ページの <head> に excanvas.js を書きさえすればば、後は何もしなくても Internet Explorer で Canvas
API が使える。<canvas> 要素をマークアップに追加したり、JavaScript で動的に作成したりできるのだ。
この章の説明にしたがって <canvas> 要素の描画コンテキストを取得すれば、シェープやテキスト、それに
パターンが描けるようになる。
いや…、正直に言うと、いくつか制限がある。
●
グラデーション(「4.6 グラデーション」を参照のこと)は、線形に限られる。円形グラデーショ
ンはサポートされていない。
●
パターンは、両方向に反復するものに限られる。
●
領域のクリッピングはサポートされていない。
●
一様でないスケーリングを行うと、輪郭が正しくスケーリングされない。
●
遅い。これはそれほどひどいショックではないだろう。もともと Internet Explorer の JavaScript
パーザは他のブラウザよりも遅いからだ。JavaScript ライブラリがコマンドを全く異なる技術に翻
訳しているわけなので、複雑なシェープを描くと速度は劇的に低下する。線を数本描いたり画像
を変形したりといった単純な例では性能の低下に気付くことはないだろうが、Canvas によるアニ
メーションなど、難しいことをやり始めればすぐわかるはずだ。
もうひとつ、excanvas.js を使う上で気を付けておかなくてはならないことがある。これは私自身がこの
章の実例を作る過程で出くわした問題だ。ExplorerCanvas は、HTML ページに excanvas.js スクリプト
が現れた際に、自分自身の擬似 Canvas インタフェースを自動的に初期化する。しかしこれは、Internet
Explorer がすぐにそれを使える状態になっているという意味ではない。状況によっては、擬似 Canvas イ
ンタフェースの準備はほとんどできているが、完全に使える状態にはなっていないという競合条件が生じる
可能性がある。このような状況が生じると、例えば描画コンテキストの取得など、<canvas> 要素に対して
何かをしようとすると、Internet Explorer は「オブジェクトはこのプロパティまたはメソッドをサポート
していません」というメッセージを表示して動作しなくなってしまう。
この問題を最も簡単に解決する方法は、onload イベントが発生するまで Canvas 関連の操作を遅らせる
ことだ。これには多少の時間がかかる(ページに含まれる画像やビデオは onload イベントを遅らせる)が、
ExplorerCanvas が魔法のように動作するための時間を稼いでくれる。
4.9 総合的な実例
ハルマ(Halma)は、100 年以上の歴史を持つボードゲームだ。多くの変種が存在するが、今回は、9 ×
9 のボード上と 9 個のコマを使う、一人遊び用のハルマを作成した。ゲームの初期状態では、ボードの左下
隅の 3 × 3 の正方形にコマが配置されている。ゲームの目的は、すべてのコマをボードの右上隅の 3 × 3
の正方形の中へなるべく少ない手数で動かすことだ。
ハルマには、2 種類のコマの動かし方がある。
4.9 総合的な実例
●
85
1 個のコマを、隣接する空のマスに移動する。「空の」マスとは、現在コマが存在しないマスのこ
とだ。「隣接する」マスとは、コマの現在位置の前後左右および右斜め前、左斜め前、右斜め後、
左斜め後の方向の、すぐ隣のマスのことだ。(ボードの端は反対側とはつながっていない。最も左
の列にいるコマは、左、左斜め前、および左斜め後には動けない。最も後の列にいるコマは、後、
右斜め後、および左斜め後には動けない。)
●
1 個のコマを、隣接するコマを飛び越して動かす。可能であれば連続して飛び越すことができる。
つまり、隣接するコマを飛び越した場合、新しい位置に隣接する別のコマを飛び越しても 1 手と
数える。さらに何度連続して飛び越しても、1 手と数える。(このゲームの目的は手数を最小にす
ることなので、ハルマを上手にプレイするコツは、なるべく多く連続して飛び越せるようにコマを
配置し、飛び越すことだと言える。)
図 4-16 が、このゲームのスクリーンショットだ。オンラインでプレイすることもできる†し、ブラウザ
の開発ツールでいじってみることもできる。
これはどうやって動作しているのだろう? いい質問だ。ここではすべてのコードを示すことはしない
(http://diveintohtml5.info/examples/halma.js で見ることができる)。ゲームのプレイに関するコードは大
Moves: 0
図 4-16 ハルマゲームの初期配置
†
http://diveintohtml5.info/examples/canvas-halma.html を参照。
86
4 章 Canvas による描画
部分省略し、実際の Canvas への描画と <canvas> 要素上のマウスのクリックへの応答を行うコードの部分
について主に説明する。
ページのロード中に、<canvas> そのものの寸法を設定し、描画コンテキストへの参照を保存してゲーム
の初期化を行う。
gCanvasElement.width = kPixelWidth;
gCanvasElement.height = kPixelHeight;
gDrawingContext = gCanvasElement.getContext("2d");
次に、<canvas> 要素がクリックイベントを感知できるように、イベントリスナを追加する。これについ
ては今まで説明していなかったはずだ。
gCanvasElement.addEventListener("click", halmaOnClick, false);
halmaOnClick() 関 数 は、 ユ ー ザ が Canvas 内 の ど こ か を ク リ ッ ク し た 際 に 呼 び 出 さ れ る。 引 数 は
MouseEvent オブジェクトで、これにはユーザがクリックした場所に関する情報が含まれている。
function halmaOnClick(e) {
var cell = getCursorPosition(e);
// ここにはゲームプレイに関するコードが入る
for (var i = 0; i < gNumPieces; i++) {
if ((gPieces[i].row == cell.row) &&
(gPieces[i].column == cell.column)) {
clickOnPiece(i);
return;
}
}
clickOnEmptyCell(cell);
}
次いで、MouseEvent オブジェクトからハルマボードのどのマスがクリックされたかを計算する関数につ
いて説明する。ハルマボードは Canvas 全体を占めるので、ボードのどこかがクリックされたことは最初か
らわかっている。クリックされた場所さえ突き止めればよいのだが、実は、マウスイベントはブラウザに
よって異なる実装がされているので、これはなかなか難しいことなのだ。
function getCursorPosition(e) {
var x;
var y;
if (e.pageX || e.pageY) {
x = e.pageX;
y = e.pageY;
4.9 総合的な実例
87
}
else {
x = e.clientX + document.body.scrollLeft +
document.documentElement.scrollLeft;
y = e.clientY + document.body.scrollTop +
document.documentElement.scrollTop;
}
この時点で、x と y には文書(つまり HTML ページ全体)に対する相対的な座標が入っている。しかし、
必要なのは Canvas に対する相対的な座標だ。これは、以下のようにして求められる。
x -= gCanvasElement.offsetLeft;
y -= gCanvasElement.offsetTop;
これで、Canvas に対する相対的な座標 x と y が得られた(「4.3 Canvas の座標」を参照)。つまり、もし
ここで x と y がともに 0 だったとすると、ユーザが Canvas の左上隅のピクセルをクリックしたことがわか
る。
ここから、ユーザがハルマのどのコマをクリックしたかを計算し、それに従った処理を行うことができ
る。
var cell = new Cell(Math.floor(y/kPieceWidth),
Math.floor(x/kPieceHeight));
return cell;
}
ふう。マウスイベントを取り扱うのは、なかなか大変だ。しかし同じロジック(つまり、このコードその
もの)は、読者が Canvas ベースのアプリケーションを作成する際に使うことができる。「マウスクリック」
→「文書の相対座標」→「Canvas 相対座標」→「アプリケーション特有のコード」という流れになること
は覚えておいてほしい。
さて、メイン描画ルーチンを見ていくことにしよう。今回はグラフィックスが単純なので、ゲーム中で
何かが変化するごとにボードをすべて消去して描画し直すことにした。これは厳密に言えば必要ない。仮
にユーザが Canvas を見えない位置までスクロールしたり別のタブに移動したりしてからまた戻ってきた
場合でも、Canvas の描画コンテキストは保存されているからだ。もっと複雑なグラフィックスを使った
Canvas ベースのアプリケーション(例えばアーケードゲームなど)を開発する場合は、性能を向上させる
ために Canvas のどの領域が変化したのかを把握してその部分だけを再描画するのがよいだろう。しかしそ
れは本書の取り扱う範囲を超えてしまう。ボードを消去するコードは以下のとおりだ。
gDrawingContext.clearRect(0, 0, kPixelWidth, kPixelHeight);
以下のボードの描画ルーチンには見覚えがあると思う。これは、Canvas の座標の説明図を作成した方法
とよく似ているからだ(「4.3 Canvas の座標」を参照)。
88
4 章 Canvas による描画
gDrawingContext.beginPath();
/* 縦の線 */
for (var x = 0; x <= kPixelWidth; x += kPieceWidth) {
gDrawingContext.moveTo(0.5 + x, 0);
gDrawingContext.lineTo(0.5 + x, kPixelHeight);
}
/* 横の線 */
for (var y = 0; y <= kPixelHeight; y += kPieceHeight) {
gDrawingContext.moveTo(0, 0.5 + y);
gDrawingContext.lineTo(kPixelWidth, 0.5 + y);
}
/* 描画する */
gDrawingContext.strokeStyle = "#ccc";
gDrawingContext.stroke();
ここから、コマをひとつずつ描いていく。コマは円形だが、円の描画についてはまだ説明していなかった
はずだ。さらに、ユーザがコマを動かそうとして選択した場合には、そのコマを塗りつぶした円として描
きたい。ここでは、引数 p はコマを表し、そのプロパティである row と column はそのコマのボード上の現
在位置を表すものとする。まず、このゲーム内で定義した定数を使って (column, row) を Canvas 相対座標
(x, y) に変換し、円を描画し、それから(そのコマが選択されていれば)円を塗りつぶす。
function drawPiece(p, selected) {
var column = p.column;
var row = p.row;
var x = (column * kPieceWidth) + (kPieceWidth/2);
var y = (row * kPieceHeight) + (kPieceHeight/2);
var radius = (kPieceWidth/2) - (kPieceWidth/10);
ここまでが、ゲーム特有のロジックだ。これによって、描きたい円の中心の Canvas 相対座標 (x, y) が
求められている。実は、Canvas API には円を描く circle() メソッドは存在しないが、円弧を描く arc() メ
ソッドは存在する。幾何学の基本を思い出してほしい。この arc() メソッドは、引数として中心点 (x, y)、
半径、開始角度および終了角度(単位はラジアン)、そして方向フラグ(false は時計回り、true は反時計
回りを表す)を取る。ラジアンは、JavaScript に組み込まれている Math モジュールを使って計算できる。
gDrawingContext.beginPath();
gDrawingContext.arc(x, y, radius, 0, Math.PI * 2, false);
gDrawingContext.closePath();
ここで注意!実際にはまだ何も描画されていない。moveto() や lineto() と同じように、この arc() メ
ソッドも「鉛筆」メソッドなのだ(「4.4 パス」を参照)。実際に円を描くには、strokeStyle を設定して
4.10 参考文献
89
stroke() を呼び出し、「インク」でトレースする必要がある。
gDrawingContext.strokeStyle = "#000";
gDrawingContext.stroke();
ピースが選択されていた場合はどうすればよいだろうか。コマの輪郭を描くために作成したパスを再利用
して、円を塗りつぶせばよい。
if (selected) {
gDrawingContext.fillStyle = "#000";
gDrawingContext.fill();
}
これでおしまい、と言いたいところだが、描画に関する部分はここまでだ。プログラムの残りはゲーム
のプレイに関するロジック、つまりコマの許される動きと許されない動きを判定したり、手数を数えた
り、ゲームの終了を判定したりすることだ。9 個の円と、数本の直線、そして onclick ハンドラを使って、
<canvas> でゲームが作れたわけだ。万歳!
4.10 参考文献
●
Mozilla Development Center にある、Canvas のチュートリアル
https://developer.mozilla.org/ja/Canvas_tutorial
●
Mihai Sucan による、「HTML5 canvas―その基本」
http://dev.opera.com/articles/view/html-5-canvas-the-basics/
●
Canvas Demos:HTML <canvas> 要素のデモ、ツール、チュートリアル
http://www.canvasdemos.com/
●
HTML5 ドラフト標準の「canvas 要素」
http://whatwg.org/html5#the-canvas-element
●
Internet Explorer 9 Guide for Developers の「canvas 要素」
http://msdn.microsoft.com/en-us/ie/ff468705.aspx#_HTML5_canvas
●
HTML5.JP の Canvas チュートリアル
http://html5.jp/canvas/
91
5章
Web のビデオ
5.1 はじめに
ここ 4 年ほどの間に YouTube を見たことがある人なら、Web ページにビデオを埋め込めることは知って
いるはずだ。しかし HTML5 以前は、ビデオを埋め込む方法が標準化されていなかった。今まで「Web 上
で」見ていたビデオはすべて、QuickTime、RealPlayer、あるいは Flash などのサードパーティ製のプラ
グインを使っていたのだ。(YouTube は Flash を使っている。)これらのプラグインはブラウザに統合され
ているので、使っていることすら意識していないかもしれない。しかしプラグインをサポートしないプラッ
トフォームでビデオを見ようとすると、いやおうなしに気付くことになる。
HTML5 では、<video> 要素を使って Web ページにビデオを埋め込む標準的な方法が定義されている。
<video> 要素のサポートはまだ進化途上、つまりはっきり言えば、まだ使えない(少なくとも、どんな場合
でも使えるわけではない)というのが現実だ。しかし、代替手段や選択肢はたくさん用意されているので、
あきらめないでほしい。表 5-1 は、本書の執筆時点での各ブラウザの <video> 要素のサポート状況だ。
表 5-1 <video> 要素のサポート
IE
Firefox
Safari
Chrome
Opera
iPhone
Android
9.0 ∼
3.5 ∼
3.0 ∼
3.0 ∼
10.5 ∼
1.0 ∼
2.0 ∼
現実には、<video> 要素そのもののサポートは、問題のごく一部に過ぎない。HTML5 ビデオについて語
る前に、ビデオそのものについて多少の理解をしておく必要がある。(もうビデオについてはよく知ってい
るよ、という読者は「5.5 Web で利用可能な組み合わせ」から読み始めてほしい。)
5.2 ビデオのコンテナ
ビデオファイルとは「AVI ファイル」や「MP4 ファイル」のことだと思っている人もいるだろう。実は、
「AVI」や「MP4」はコンテナフォーマットに過ぎないのだ。ZIP ファイルがどんな種類のファイルでも圧
縮できるように、コンテナフォーマットはその中にデータを格納する方法を定義しているだけで、データの
種類については規定していない。(実際には、すべてのビデオストリームがすべてのコンテナフォーマット
と互換性があるわけではないので、もう少し話は複雑だ。しかし、ここでは気にしなくても構わない。)
ビデオファイルには通常、複数のトラックがある。1 本のビデオトラック(オーディオは入っていない)
92
5 章 Web のビデオ
と、1 本以上のオーディオトラック(ビデオは入っていない)だ。トラックは通常、互いに関連しあってい
る。オーディオトラックには、オーディオをビデオと同期させるためのマーカが入っている。各トラックに
はメタデータ、つまりビデオトラックのアスペクト比やオーディオトラックの言語などの情報が含まれる場
合がある。コンテナにも、ビデオのタイトル名やジャケット写真、エピソード番号(テレビ番組の場合)な
どのメタデータが含まれる場合がある。
コンテナフォーマットは多数存在するが、以下のものが代表的だ。
MPEG-4
通 常、 拡 張 子 .mp4 ま た は .m4v を 持 つ。MPEG-4 コ ン テ ナ は Apple の 古 い QuickTime コ ン テ
ナ(.mov)をベースにしている。Apple の Web サイト上にある映画の予告編は、いまだに古い
QuickTime コンテナを使っているが、iTunes で見られる映画は MPEG-4 コンテナで配信されて
いる。
Flash ビデオ
通常、拡張子 .flv を持つ。Flash ビデオは、当然のことながら Adobe Flash で使われている。
Flash 9.0.60.184(別名 Flash Player 9 Update 3)よりも前の Flash では、これがサポートされて
いる唯一のコンテナフォーマットだった。最近の Flash では MPEG-4 コンテナもサポートされて
いる。
Ogg
通常、拡張子 .ogv を持つ。Ogg はオープンソースで開発されるオープン標準で、既知のどんな特
許にも縛られていない。Firefox 3.5、Chrome 4、そして Opera 10.5 では、Ogg コンテナフォー
マット、Ogg ビデオ(「Theora」と呼ばれる)、そして Ogg オーディオ(「Vorbis」と呼ばれる)
へのネイティブサポートが行われており、再生にプラグインを必要としない。デスクトップにお
いて、Ogg はすべての主要な Linux ディストリビューションで出荷時からサポートされており、
Mac や Windows でも QuickTime コンポーネントや DirectShow フィルタをインストールすれば
使えるようになる。また、VLC †を使えばすべてのプラットフォーム上で再生が可能だ。
WebM
拡張子 .webm を持つ。WebM は 2010 年 5 月に発表された新しいコンテナフォーマットだ。技
術的には Matroska と呼ばれる別のフォーマットと非常によく似ており、VP8 ビデオコーデッ
クと Vorbis オーディオコーデック専用に設計されている。(後で詳しく説明する。)Chromium、
Google Chrome、Mozilla Firefox、および Opera の最新バージョンでは、ネイティブサポートが
行われており、再生にプラグインを必要としない。Adobe もまた将来の Flash で WebM ビデオを
サポートすることを表明している。
Audio Video Interleave
通常、拡張子 .avi を持つ。この AVI コンテナフォーマットは、コンピュータでビデオが再生でき
るということ自体が驚くべきことだった時代に、Microsoft によって発明された。なので、埋め込
†
http://www.videolan.org/vlc/ を参照。
5.3 ビデオコーデック
93
みメタデータをはじめ最近のコンテナフォーマットが持つ機能の多くが公式にはサポートされてい
ない。最近使われているビデオコーデックやオーディオコーデックの多くも、公式にはサポートさ
れていない。AVI はさまざまな会社によって互換性のない方法で拡張され、種々のサポートが追加
されており、今日においても MEncoder †のような人気のあるエンコーダでデフォルトのコンテ
ナフォーマットとして使われている。
5.3 ビデオコーデック
「ビデオを見る」と言ったとき、それは 1 つのビデオストリームと 1 つのオーディオストリームの組み合
わせを意味しているのが普通だ。しかし 2 つの別々のファイルがあるわけではない。それは AVI ファイル
かもしれないし、もしくは MP4 ファイルかもしれないが、それでも 1 個の「ビデオ」だ。前のセクション
で説明したように、これらは ZIP ファイルと同じように、異なる種類のファイルを格納するコンテナフォー
マットだ。このコンテナフォーマットが、ビデオとオーディオのストリームを単一のファイルに保存する方
法を定義している。
「ビデオを見る」とき、ビデオプレイヤーは少なくとも 3 つの仕事を一度にこなしている。
1.
コンテナフォーマットを解釈し、どのビデオやオーディオトラックが利用できるかを調べ、ファイ
ルの中にどのような形で保存されているかを調べ、次にデコードする必要のあるデータを見つける
2.
ビデオストリームをデコードし、画面上に一連の画像を表示する
3.
オーディオストリームをデコードし、スピーカーに音を出す
ビデオコーデックとは、ビデオストリームがエンコードされる際に使われるアルゴリズムのことだ。つ
まり、2 番目の仕事のやり方を規定しているわけだ。(「コーデック(codec)」とは、「コーダ(coder)」と
「デコーダ(decoder)」の合成語だ。)ビデオプレイヤーはビデオコーデックにしたがってビデオストリー
ムをデコードし、一連の画像、つまり「フレーム」を画面上に表示する。最近のビデオコーデックは、連続
してフレームを表示する際に必要となる情報量を減らすために、いろいろなトリックを使っている。例え
ば、(スクリーンショットのように)フレームをひとつずつ別々に保存する代わりに、フレーム間の差分だ
けを保存するのだ。ビデオではフレームから次のフレームへの変化量は少ないことが多いので、これによっ
て圧縮率を高め、ファイルサイズを小さくできる。
ビデオコーデックには、不可逆(lossy)と可逆(lossless)の種類がある。可逆圧縮されたビデオは巨
大で Web では使いづらいので、ここでは不可逆なコーデックについてだけ説明する。不可逆なビデオコー
デックでは、情報はエンコード時に失われ、取り戻すことはできない。オーディオカセットテープをコピー
したときのように、エンコードするたびに元のビデオにあった情報は失われて行き、品質が低下するのだ。
オーディオカセットではヒスノイズが増加するが、ビデオのエンコードの場合、特に動きの多い場面でブ
ロックノイズが増加する。(元の映像から直接エンコードした場合でも、ビデオコーデックの選択を間違っ
たり、パラメータの設定が悪かったりすると同じことが起こる。)不可逆コーデックの利点は、非常に高い
圧縮率が得られることがあげられる。また、再生時に人間の目をだましてブロックノイズを平滑化し、失わ
†
http://www.mplayerhq.hu/DOCS/HTML/en/encoding-guide.html を参照。
94
5 章 Web のビデオ
れた情報を目立たなくしているものも多い。
ビデオコーデックには膨大な種類がある。有力なのは H.264、Theora、そして VP8 の 3 種類だ。
5.3.1 H.264
H.264 † は、「MPEG-4 part 10」、「MPEG-4 AVC」、「MPEG-4 Advanced Video Coding」などの別名で
も知られている。H.264 は MPEG グループによって開発され、2003 年に標準化された。低帯域幅と低速
な CPU 搭載機器(携帯電話)でも、広帯域幅と高速な CPU 搭載機器(最近のデスクトップコンピュータ)
でも、あるいはその中間に位置するどんな機器でも使える単一のコーデックを提供することが目標だ。この
ため、H.264 標準は複数の「プロファイル」に分割され、それぞれに複雑さとファイルサイズに影響するオ
プション機能が定義されている。高度なプロファイルほど多くのオプション機能を使用し、よい画質と小
さなファイルサイズが得られる一方で、エンコードには長い時間が、リアルタイムのデコードには多くの
CPU パワーが必要となる。
どんなプロファイルが使われているかというと、Apple の iPhone(3GS まで)はベースラインプロファ
イルを、iPhone 4 と iPad, Apple TV はベースラインとメインプロファイルを、そして Adobe Flash はベー
スライン、メイン、それにハイプロファイルをサポートしている。YouTube は HD ビデオのエンコード
に H.264 を使っている(Adobe Flash で再生可能)。YouTube ではまた、Apple の iPhone や Google の
Android OS を搭載した携帯電話などのモバイル機器向けにも H.264 でエンコードされたビデオを提供して
いる。また、H.264 はブルーレイ規格で要求されているビデオコーデックのひとつでもあり、ブルーレイ
ディスクは通常ハイプロファイルを使用している。
H.264 ビデオが再生できる PC 以外の機器(iPhone やブルーレイ再生専用機を含む)では、たいてい専
用のチップでデコードを行っている。メイン CPU に、リアルタイムでビデオをデコードできるほどのパ
ワーがないからだ。デスクトップにおいては、低価格なモデルに搭載されたグラフィックカードでも、ハー
ドウェアによる H.264 のデコードをサポートしている。H.264 のエンコーダはオープンソースの x264 ライ
ブラリをはじめ多数存在する。そして、H.264 標準は、特許に縛られている。特許のライセンスは MPEG
LA グループを通して行われている。H.264 ビデオは、MP4(主に Apple の iTunes Store で使われている)
や MKV(主にアマチュアのビデオ愛好家に使われている)など、よく使われているコンテナフォーマット
(「5.2 ビデオのコンテナ」を参照)のほとんどに埋め込むことが可能だ。
5.3.2 Theora
Theora †† は、VP3 コーデックから発展し、それ以降 Xiph.org Foundation によって開発されている。
Theora はロイヤリティフリーのコーデックで、ロイヤリティフリーでライセンスされている元の VP3 特許
以外に、知られている限りどんな特許にも縛られていない。2004 年にこの標準は「確定」されているが、
それ以来 Theora プロジェクト(オープンソースの参照エンコーダおよびデコーダを含む)は 2008 年 11 月
にバージョン 1.0 を、2009 年 9 月にバージョン 1.1 をリリースしたのみだ。
Theora ビデオはどんなコンテナフォーマットにも埋め込むことができるが、Ogg コンテナとともに使わ
れることが多い。主要な Linux ディストリビューションは出荷時から Theora をサポートしており、また
†
http://ja.wikipedia.org/wiki/H.264 も参照。
††
http://ja.wikipedia.org/wiki/Theora も参照。
5.4 オーディオコーデック
95
Mozilla Firefox はバージョン 3.5 より Ogg コンテナ中の Theora ビデオをネイティブでサポートしている。
ここで「ネイティブ」とは、「すべてのプラットフォーム上で、プラグインなしで利用できる」という意味
だ。Xiph.org のオープンソースのデコーダソフトウェアをインストールすれば、Windows や Mac OS X 上
でも Theora ビデオが再生できる。
5.3.3 VP8
VP8 †は、もともと VP3(後に Theora のもとになる)を開発していた会社である On2 のビデオコーデッ
クだ。技術的には、H.264 ハイプロファイルと同程度の品質を持ちながら、デコードの複雑性はベースライ
ンプロファイルと同程度にとどめている。
2010 年、Google が On2 を買収し、ビデオコーデックの仕様とサンプルエンコーダおよびデコーダをオー
プンソースとして公開した。それに伴い、Google は On2 が VP8 に関して申請していたすべての特許を
「オープン」にし、ロイヤリティフリーでライセンスしている。(特許に関しては、これが望む限り最上の手
段だ。一度発行された特許は「放棄」したり、無効にしたりはできないからだ。オープンソースで使われる
ためには、ロイヤリティフリーでライセンスすれば、対価の支払いや特許のライセンス交渉なしに、その特
許がカバーする技術を誰もが使えるようになる。)2010 年 5 月 19 日に、On2(現在の Google)がすでにロ
イヤリティフリーでライセンスしている特許を除き、VP8 は知られている限りどんな特許にも縛られてい
ない、ロイヤリティフリーの最新のコーデックとなった。
5.4 オーディオコーデック
1927 年ころよりも前に製作された映画しか見ない人ならともかく、ほとんどの人はビデオにオーディオ
トラックが必要だろう。ビデオコーデックと同じく、オーディオコーデックもエンコーディングのアルゴリ
ズムだが、対象がオーディオという点だけが違っている。ビデオコーデックと同じく、オーディオコーデッ
クにも可逆と不可逆の別がある。可逆圧縮されたビデオと同じく、可逆圧縮されたオーディオは Web で使
うには大きすぎるので、ここでも不可逆なオーディオコーデックについてのみ説明する。
現実には、さらに候補を絞り込むことができる。不可逆オーディオコーデックにもいくつかのカテゴリが
存在するからだ。オーディオの場合はビデオとともに使われない場合(例えば電話など)も多く、また会話
のエンコードに特化したオーディオコーデックのカテゴリが存在する。この種のコーデックで音楽 CD を
リッピングしたいとは思わないだろう。まるで 4 歳児が電話口で歌っているような音質しか得られないか
らだ。しかしそのようなコーデックでも、例えば Asterisk PBX では使用に耐える。帯域幅が重要な用途で
は、汎用コーデックよりもはるかに小さいサイズに人間の会話を圧縮できる利点が大きいからだ。しかし、
ブラウザでのネイティブなサポートやサードパーティ製のプラグインが提供されていないため、会話品質の
オーディオコーデックは Web 上で広く使われるようにはなっていない。したがって、ここでは汎用の不可
逆オーディオコーデックに話を絞ることにする。
「5.3 ビデオコーデック」で述べたように、「ビデオを見る」といった場合、コンピュータはいくつかの仕
事を一度にこなしている。
†
http://ja.wikipedia.org/wiki/VP8 も参照。
5 章 Web のビデオ
96
1.
コンテナフォーマットの解釈
2.
ビデオストリームのデコード
3.
オーディオストリームのデコードと、スピーカーへの出力
オーディオコーデックは、このうち 3 番目を規定している。つまり、オーディオストリームをデコード
し、最終的にスピーカーから音として出力されるディジタル波形に変換する部分だ。ビデオコーデックと同
じく、オーディオストリーム中の情報量を最小化するための仕掛けはいろいろと存在する。ここでは不可逆
オーディオコーデックについて述べているので、録音→エンコード→デコード→再生というライフサイクル
の中で、情報は失われて行く。オーディオコーデックが違えば失われる情報も異なるが、やっていることは
どれも同じだ。あなたの耳をだまして、失われた部分に気付かないようにしているのだ。
ビデオにはない概念がオーディオにはある。それはチャンネルだ。音はスピーカーに出力される。あなた
はスピーカーをいくつ使っているだろうか。コンピュータには、左右に 2 つのスピーカーしかないことが
多い。筆者のデスクトップには 3 つ、左右と床の上にもうひとつある。いわゆる「サラウンド」システム
では、6 個以上のスピーカーを使い、それらを部屋の中に効果的に配置する。ひとつひとつのスピーカーは、
録音された特定のチャンネルを再生する。理論的には、6 個のスピーカーの中央に座り、6 個の異なる音の
チャンネルに取り囲まれると、脳がそれらを合成してあたかも映画の場面の中にいるように感じさせてくれ
るはずだ。そんなにうまく行くのかって? 業界の人たちは、うまく行くと思っているらしい。
大部分の汎用オーディオコーデックは、2 個の音声チャンネルを取り扱える。録音の際、音は左右のチャ
ンネルに振り分けられる。エンコードの際、両チャンネルは同一のオーディオストリームに保存される。そ
してデコードの際には、両チャンネルがデコードされ、それぞれ対応するスピーカーへ送られるのだ。2 個
以上のチャンネルを取り扱えるオーディオコーデックも存在し、その場合はどのチャンネルの音がどのス
ピーカーで再生されるべきかをちゃんと把握できるようになっている。
オーディオコーデックは多数存在する。さっきビデオコーデックはたくさんあると言ったと思うが、そ
のことはもう忘れてほしい。オーディオコーデックには本当にたくさんの種類がある。しかし Web では
MP3、AAC、そして Vorbis の 3 種類さえ知っておけばよい。
5.4.1 MPEG-1 Audio Layer 3
MPEG-1 Audio Layer 3 †は、一般には「MP3」として知られている。今まで MP3 という言葉を聞いた
ことのない人は、少なくともこの本の読者にはいないだろう。ウォールマート††でもポータブル音楽プレ
イヤーを「MP3 プレイヤー」という名前で売っているくらいだ。
MP3 は、音のチャンネルを 2 個まで持てる。64kbps、128kbps、192kbps など、32kbps から 320kbps
までの間のさまざまなビットレートでエンコードが可能だ。ビットレートが高くなるほどファイルサイズは
大きくなり、音質は向上する。しかし音質とビットレートとは線形比例するわけではない。(128kbps の音
質は 64kbps よりも 2 倍以上優れているが、256kbps は 128kbps の 2 倍優れているわけではない。)さらに、
MP3 フォーマットは可変ビットレートエンコーディングが可能で、これはつまりエンコード時の圧縮率が
†
http://ja.wikipedia.org/wiki/MP3 も参照。
††
訳注:アメリカの最大手スーパーマーケット。
5.4 オーディオコーデック
97
動的に変えられるという意味だ。例えば、音符と音符の間の無音の部分は非常に低いビットレートでエン
コードし、たくさんの楽器が複雑な和音を奏で始めたとたんにビットレートを高めることができる。MP3
は固定されたビットレートでのエンコードも可能で、これは(当たり前の話だが)固定ビットレートエン
コーディングと呼ばれる。
MP3 標準では、MP3 のエンコード方法について厳密な定義は行っていない(その一方で、デコード方法
については厳密に定義している)。エンコーダが違えば使う音響心理モデルも違い、結果も大きく異なる可
能性があるが、それらはすべて同じプレイヤーでデコードできる。オープンソースの LAME プロジェクト
は、非常に低いビットレート以外では、フリーのエンコーダとしては最良であり、議論の余地はあるがすべ
てのエンコーダの中でも最良と言われている。
MP3 フォーマット(1991 年に標準化)は特許に縛られている。Linux が出荷時の状態では MP3 ファイ
ルを再生できないのは、これが理由だ。ほとんどすべてのポータブル音楽プレイヤーはスタンドアローンの
MP3 ファイルをサポートしており、MP3 オーディオストリームはどんなビデオコンテナにも埋め込むこと
ができる。Adobe Flash はスタンドアローンの MP3 ファイルと、MP4 ビデオコンテナ中の MP3 オーディ
オストリームの両方を再生可能だ。
5.4.2 Advanced Audio Coding
Advanced Audio Coding †は、「AAC」の愛称で知られている。1997 年に標準化され、Apple が iTunes
Store のデフォルトフォーマットとして選択したのをきっかけに、脚光を浴びるようになった。もともと、
iTunes Store から「購入」されたすべての AAC ファイルは、FairPlay と呼ばれる Apple 独自の DRM 技術
で暗号化されていた。現在では、iTunes Store の多くの楽曲はプロテクトされていない AAC ファイルとし
て入手できるようになっており、これを Apple は「iTunes Plus」と呼んでいる。それ以外の楽曲を「iTunes
Minus」と呼ぶよりは聞こえがよいからだろう。AAC フォーマットは特許に縛られている。ライセンス価
格の詳細はオンラインで入手できる。
AAC は同じビットレートの MP3 よりも優れた音質が得られるよう設計されていて、さらに任意のビッ
トレートでオーディオをエンコードできる。(MP3 は特定のビットレートでしかエンコードできず、しか
も 320kbps の上限がある。)AAC は音声チャンネルを 48 個までエンコードできるが、実際に試した人は誰
もいないだろう。MP3 とのもうひとつの違いは、AAC フォーマットには H.264 と同じように(そして同じ
理由から)複数のプロファイルが定義されている点だ。AAC-LC(AAC Low Complexity)プロファイルは
CPU パワーに制限のある機器でもリアルタイムの再生が行えるように設計されているが、より高度なプロ
ファイルを使えば、エンコードやデコードに時間はかかるものの、同じビットレートでよりよい音質が得ら
れる。
iPod、AppleTV、それに QuickTime など、すべての Apple の現行製品では、スタンドアローンのオー
ディオファイルと MP4 ビデオコンテナ中のオーディオストリームで、何らかの AAC プロファイルがサポー
トされている。Adobe Flash は MP4 中のすべての AAC プロファイルをサポートしており、オープンソー
スの MPlayer や VLC ビデオプレイヤーも同様だ。エンコーディングには、オープンソースの FAAC ライ
ブラリがあり、mencoder や ffmpeg でコンパイル時のオプションとしてサポートされている。
†
http://ja.wikipedia.org/wiki/AAC も参照。
5 章 Web のビデオ
98
5.4.3 Vorbis
Vorbis †は、よく「Ogg Vorbis」と呼ばれるが、これは技術的には正しい呼び名ではない。「Ogg」はコ
ンテナフォーマットに過ぎず(「5.2 ビデオのコンテナ」を参照)、Vorbis オーディオストリームはその他
のコンテナにも埋め込むことができるからだ。Vorbis は知られている限りどんな特許にも縛られていない。
したがって、主要な Linux ディストリビューションやオープンソースの Rockbox ファームウェアを使っ
たポータブル機器では出荷時からサポートされている。Mozilla Firefox はバージョン 3.5 から Ogg コンテ
ナ中の Vorbis オーディオファイルや、Vorbis オーディオトラックを持つ Ogg ビデオをサポートしている。
Android 携帯電話もまた、スタンドアローンの Vorbis オーディオファイルが再生可能だ。Vorbis オーディ
オストリームは通常 Ogg または WebM コンテナに埋め込まれるが、MP4 や MKV コンテナ、あるいは多
少のハックは必要だが、AVI に埋め込むこともできる。Vorbis は、任意の数の音声チャンネルをサポート
している。
OggConvert エンコーダ、ffmpeg デコーダ、aoTuV エンコーダ、そして libvorbis デコーダなど、オー
プンソースの Vorbis エンコーダおよびデコーダが存在する。また Mac OS X 用の QuickTime コンポーネ
ントや Windows 用の DirectShow フィルタも存在する。
5.5 Web 上で利用可能な組み合わせ
ここまで読み進めてもまだ目がくらんでいなかったとすれば、たいしたものだ。お分かりのように、ビ
デオ(そしてオーディオも)は複雑な題材だ。そして今までの説明は、ごくかいつまんだ内容に過ぎない
のだ。たぶん読者の皆さんは、これらがどう HTML5 と関係しているのか、疑問に思っていることだろう。
HTML5 には、Web ページにビデオを埋め込むための <video> 要素が含まれている。ビデオを埋め込む際
に使えるビデオコーデック、オーディオコーデック、あるいはコンテナフォーマットには制限がない。ひと
つの <video> 要素は複数のビデオファイルにリンクすることができ、ブラウザは自分が再生可能な最初のビ
デオファイルを選択する。どのブラウザがどのコンテナやコーデックをサポートしているかどうかを理解す
るのは、あなたの責任なのだ。
本書の執筆時点で、HTML5 ビデオのサポート状況は以下のようになっている。
●
Mozilla Firefox(3.5 以降)は、Ogg コンテナ中の Theora ビデオと Vorbis オーディオをサポート
している。Firefox 4 からは WebM もサポートする。
●
Opera(10.5 以降)は、Ogg コンテナ中の Theora ビデオと Vorbis オーディオをサポートしてい
る。Opera 10.60 からは WebM もサポートする。
●
Google Chrome(3.0 以降)は、Ogg コンテナ中の Theora ビデオと Vorbis オーディオをサポー
トしている。Google Chrome 6.0 からは WebM もサポートする。
●
Mac および Windows PC 上の Safari(3.0 以降)は、QuickTime のサポートしている組み合わせ
をすべてサポートしている。理論的には、ユーザにサードパーティの QuickTime プラグインをイ
ンストールしてもらえば、何でも再生できることになる。しかし実際にそれをしてくれるユーザは
†
http://ja.wikipedia.org/wiki/Vorbis も参照。
5.5 Web 上で利用可能な組み合わせ
99
ほとんどいない。したがって、QuickTime が「出荷時から」サポートしているフォーマットに限
られることになる。これには多くの組み合わせがあるが、Theora ビデオや Vorbis オーディオ、あ
るいは Ogg コンテナは含まれない。しかし、QuickTime は MP4 コンテナ中の H.264 ビデオ(メ
インプロファイル)と AAC オーディオをサポートしている。
Apple の iPhone や Google の Android などのモバイル機器は、MP4 コンテナ中の H.264 ビデオ
●
(ベースラインプロファイル)と AAC オーディオ(AAC-LC プロファイル)をサポートしている。
●
Adobe Flash(9.0.60.184 以降)は、MP4 コンテナ中の H.264 ビデオ(全プロファイル)と AAC
オーディオ(全プロファイル)をサポートしている。
●
Internet Explorer 9 は、MP4 コンテナ中の H.264 ビデオと AAC オーディオもしくは MP3 オー
ディオをサポートする。WebM ビデオについても、サードパーティのコーデックをインストール
すると再生可能だが、どのバージョンの Windows にもデフォルトでインストールされていない。
IE9 は Safari とは異なり、WebM 以外のサードパーティコーデックをサポートしない(Safari は
QuickTime が再生可能なものすべてが再生できる)。
●
Internet Explorer 8 は、全く HTML5 ビデオをサポートしていないが、実質的にすべての Internet
Explorer ユ ー ザ は Adobe Flash プ ラ グ イ ン を イ ン ス ト ー ル し て い る。 こ の 章 の 後 の ほ う で、
HTML5 ビデオを使いつつ、サポートしていないブラウザでは自動的に Flash を利用し再生する方
法を説明する。
表 5-2 は、以上の情報をわかりやすくまとめたものだ。
表 5-2 現在出荷されているブラウザのビデオコーデックサポート状況
コーデック/コンテナ
IE
Firefox
Safari
Chrome
Opera
iPhone
Android
Theora + Vorbis + Ogg
×
3.5 ∼
a
5.0 ∼
10.50 ∼
×
×
H.264 + AAC + MP4
×
×
3.0 ∼
5.0 ∼?b
×
3.0 ∼
2.0 ∼
WebM
×
×
a
6.0 ∼
10.60 ∼
×
×
a:Safari は QuickTime がサポートするものは何でも再生可能だ。QuickTime は出荷時から H.264 / AAC / MP4 をサポートして
いる。Theora、WebM サポートを追加するサードパーティの QuickTime プラグインも存在するが、ユーザが個別にインストール
しなければ、Safari はこれらを認識しない。
b:Google Chrome はもうすぐ H.264 のサポートを打ち切る(http://blog.chromium.org/2011/01/html-video-codec-support-inchrome.html)。理由も参照されたい(http://blog.chromium.org/2011/01/more-about-chrome-html-video-codec.html)。
今後数年のうちに、状況は大きく変化するだろう。WebM は複数のブラウザに実装されるようになり、
それらのブラウザは実験の域を脱した WebM をサポートして出荷され、ユーザはこれらの新しいバージョ
ンへアップグレードすることになるはずだ。今後予測されるコーデックのサポートを表 5-3 に示す。
5 章 Web のビデオ
100
表 5-3 今後のブラウザのビデオコーデックサポート状況
コーデック/コンテナ
IE
Firefox
Safari
Chrome
Opera
iPhone
Android
Theora + Vorbis + Ogg
×
3.5 ∼
b
5.0 ∼
10.50 ∼
×
×
H.264 + AAC + MP4
9.0 ∼
×
3.0 ∼
×
×
3.0 ∼
2.0 ∼
WebM
9.0 ∼ a
4.0 ∼
b
6.0 ∼
10.60 ∼
×
2.3 ∼ c
a:Internet Explorer 9 は、「ユーザが VP8 コーデックをインストールしている場合」にのみ WebM をサポートする。つまり
Microsoft 自身はコーデックを出荷しないという意味だ。
b:Safari は QuickTime がサポートするものは何でも再生可能だが、QuickTime は出荷時において H.264/AAC/MP4 しかサポー
トしていない。
c:Android 2.3 は WebM をサポートしているが、ハードウェアデコーダはまだ存在しない。そのためバッテリーの持ちが懸念され
る。
そして、これがとどめの一撃だ。
マークアップ教授から一言
すべての HTML5 ブラウザで動作する、コンテナとコーデックの単一の組み合わせは存在しない。
この状況が、近い将来において変化する見込みはない。つまり、すべての機器とプラットフォーム上でビデ
オが見られるようにするには、複数の方式でビデオをエンコードする必要があるのだ。
互換性を最大とするための作業手順は、以下のようなものになるだろう。
1.
2.
最初のバージョンを、WebM(VP8 + Vorbis)を使って作成する。
次のバージョンを、H.264 ベースラインビデオと AAC-LC オーディオを MP4 コンテナに入れて作
成する。
3.
4.
3 番目のバージョンを、Theora ビデオと Vorbis オーディオを Ogg コンテナに入れて作成する。
これら 3 つのビデオファイルを単一の <video> 要素からリンクし、代替手段として Flash ベース
のビデオプレイヤーを起動する。
5.6 H.264 ビデオのライセンス事情
先へ進む前に、ビデオを複数の方式でエンコードすることにはコストがかかるということを指摘しておく
必要がある。ビデオを複数回エンコードするため余計に必要となるコンピュータと時間以外に、H.264 ビデ
オに関してはライセンス料という実際のコストが発生するのだ。
H.264 ビデオについて(「5.3.1 H.264」を参照)、このビデオコーデックは特許に縛られていてライセン
スは MPEG LA コンソーシアムを通して行われる、と説明したことを覚えているだろうか。この点が非常
に重要となってくる。なぜ重要なのかを理解してもらうため、読者の皆さんを H.264 ライセンスの迷宮へ
5.6 H.264 ビデオのライセンス事情
101
ご案内しよう†。
MPEG LA では、H.264 のライセンスポートフォリオを 2 つのサブライセンスに分割している。ひとつ
はエンコーダやデコーダのメーカー向けのもので、もうひとつはコンテンツの配信に使用するためのも
のだ。(後略)
コンテンツの配信に関するサブライセンスは、さらに 4 つの主要なサブカテゴリに分割される。うち 2
つ(サブスクリプションと、タイトルごとの購入もしくは有料使用)は、エンドユーザがビデオサービ
スに直接支払うことになり、残りの 2 つ(「フリー」のテレビおよびインターネット放送)は、視聴者
ではなく供給側が支払うことになる。(後略)
「フリー」のテレビ放送のライセンス料は、2 つのロイヤリティオプションのどちらかに基づいて行わ
れる。ひとつは AVC 送信エンコーダあたり 2,500 ドルの 1 回限りの支払いであり、これは番組をデ
コードして視聴する「エンドユーザへ AVC ビデオを送信するライセンス受領者によって、またはライ
センス受領者に代わって使用される」1 台の AVC エンコーダに適用される。これが料金の二重徴収で
はないかと疑問に思う人もいるかもしれないが、そのとおりだ。ライセンス料はすでにエンコーダの
メーカーから徴収されており、その上で放送事業者は 2 つのロイヤリティオプションのうちから 1 つ
を選択するのだ。
2 つ目のライセンス料は、年間放送料となる。(中略)年間放送料は、視聴者数によって以下のように
決定される。
●
世帯数 100,000 ∼ 499,999 の放送市場については、暦年 1 年あたり 2,500 ドル
●
世帯数 500,000 ∼ 999,999 の放送市場については、暦年 1 年あたり 5,000 ドル
●
世帯数 1,000,000 以上の放送市場については、暦年 1 年あたり 10,000 ドル
(中略)これら「フリー」のテレビ放送に関する事項を、放送以外の手段で配信する際にも考慮する必
要があるのはなぜだろうか。先ほど触れたように、利用料はコンテンツの任意の配信手段に適用され
る。MPEG LA は「フリー」のテレビ放送が「電波での放送」以外も意味すると定義した上で、イン
ターネット放送の利用料を「受信または視聴の権利に対して支払いを行わないエンドユーザへインター
ネットを介して配信される AVC ビデオ」として定義した。別の言い方をすると、電波、ケーブル、衛
星、あるいはインターネットなどの手段を問わず、すべての公共放送について利用料が徴収されるの
だ。(後略)
この利用料は、インターネット放送については高額となる可能性がある。インターネットによる配信
は、電波あるいはケーブルまたは衛星を介した「フリー」のテレビ放送よりもはるかに早く成長すると
予想されているからだ。追加料金に「フリーのテレビ」放送市場料金を追加する一方で、MPEG LA は
2010 年 12 月 31 日に終了する最初のライセンス期間の間は料金の徴収を猶予し、「この期間が経過した
†
http://www.streamingmedia.com/Articles/Editorial/Featured-Articles/The-H.264-Licensing-Labyrinth-65403.aspx を 参
照。
5 章 Web のビデオ
102
後のロイヤリティは、同時期のフリーのテレビ放送に請求されるロイヤリティ以下とする」と表明して
いる。
上記の最後の部分、つまりインターネット放送に関する料金体系については、すでに修正が行われてい
る。MPEG LA は最近、インターネットストリーミングにはライセンス料を徴収しないと発表した。しか
しこれは、H.264 がすべてのユーザに対しロイヤリティフリーであることを意味しない。例えば、エンコー
ダ(YouTube にアップロードするビデオを処理するものなど)、デコーダ(Microsoft Internet Explorer 9
に搭載されているものなど)には引き続きライセンス料が徴収される。詳しくは Mike Shaver による Free
as in smokescreen (http://shaver.off.net/diary/2010/08/27/free-as-in-smokescreen/)を参照されたい。
5.7 Miro Video Converter によるビデオのエンコード
ビデオをエンコードするツールは数多くある。また、ビデオの品質に影響するエンコード設定も数多くあ
る。このセクションは、ビデオのエンコードに関して何も知りたくない人のためのものだ。
Miro Video Converter は GPL のもとライセンスされたオープンソースなプログラムで、ビデオを複数
のフォーマットにエンコードしてくれる。Mac OS X 版と Windows 版が Web サイトから提供されている
†。このソフトウェアはこの章で説明するすべてのフォーマットをサポートしている。とてもシンプルで、
フォーマットの指定とファイルの選択以外に設定項目は存在しない。多くの家庭用ビデオカメラで作成でき
る DV ビデオを始め、実質的にどんなビデオファイルでも受け付けられる。エンコードされたビデオは多く
の場合問題のない品質だが、品質を設定できないため、その結果に満足できない場合は別のプログラムを使
うしかない。
では Miro Video Converter でビデオをエンコードしよう。まずはアプリケーションを起動する(図
5-1)。
図 5-1 Miro Video Converter のメイン画面
†
http://www.mirovideoconverter.com/ を参照。
5.7 Miro Video Converter によるビデオのエンコード
103
図 5-2 「choose file」からファイルを選択
図 5-3 WebM での出力
「choose file」をクリックし、エンコードしたいビデオの元ファイルを選択する(図 5-2)。
「Pick a Device or Video Format」というドロップダウンメニューは、再生させたいデバイスや変換した
いフォーマットを選択するためのものだ。この章の目的において、選ぶのは次の 3 つになる。
1.
WebM(vp8)は WebM ビデオ(WebM コンテナ中の VP8 ビデオと Vorbis オーディオ)になる。
2.
Theora は Ogg コンテナ中の Theora ビデオと Vorbis オーディオになる。
3.
iPhone は MP4 コンテナ中の H.264 ベースラインプロファイルと AAC-LC オーディオになる。
104
5 章 Web のビデオ
図 5-4 エンコード画面を長い時間眺めることになるだろう
図 5-5 Theora での出力
まず「WebM」を選択しよう(図 5-3)。
「Convert」ボタンを押すと、Miro Video Converter はすぐビデオをエンコードし始める。出力される
ファイルは元ファイル名 .webm となり、元ファイルのあるディレクトリに保存される(図 5-4)。
エンコードが完了すると、最初の画面に戻ってくる。では次にデバイスとフォーマットのリストから
「Theora」を選択しよう(図 5-5)。
よし。「Convert」ボタンを押して、今度は Theora ビデオにエンコードしよう。出力されるファイルは元
ファイル名 .theora.ogv となり、元ファイルのあるディレクトリに保存される(図 5-6)。
最後に、iPhone 互換な H.264 ビデオにエンコード仕様。デバイスとフォーマットのリストから「iPhone」
5.7 Miro Video Converter によるビデオのエンコード
105
図 5-6 コーヒーの時間だ
図 5-7 iPhone 4 ではなく iPhone を選択しよう
を選択する(図 5-7)。
iPhone 互換のビデオについて、Miro Video Converter はエンコードしたファイルを iTunes library に送
るかどうかを尋ねてくる。どちらを選んでも構わないが、Web に公開するためにビデオを iTunes に送る必
要は特にない(図 5-8)。
魔法の「Convert」ボタンを押して、エンコードが終わるのを待とう。出力されるファイルは元ファイル
名 .iphone.mp4 となり、元ファイルのあるディレクトリに保存される(図 5-9)。
これで、元となるビデオファイルに加えて 3 つのビデオファイルができた。ビデオの品質に満足であれ
ば、この先で説明するマークアップのセクションまで読み飛ばしても構わない。マークアップのセクション
106
5 章 Web のビデオ
図 5-8 iTunes には送らなくてよい
図 5-9 ヨガなどをして時間をつぶそう
では複数のブラウザで <video> を表示させる書き方について説明する。他のエンコードツールやビデオのエ
ンコード設定に興味があるなら、このまま読み続けてほしい。
5.8 Firefogg による Ogg ビデオのエンコード
(このセクションでは、「Ogg ビデオ」という用語を「Ogg コンテナ中の Theora ビデオと Vorbis オーディ
オ」の略として使用する。これは、Mozilla Firefox と Google Chrome でネイティブに動作するコーデック
とコンテナの組み合わせだ。)
Firefogg は、Ogg ビデオをエンコードするための Firefox の拡張機能で、GPL のもとライセンスされた
5.8 Firefogg による Ogg ビデオのエンコード
107
オープンソースなソフトウェアだ。拡張機能ということもあり、使うには Firefox 3.5 以降がインストール
されている必要がある。図 5-10 に示す Firefogg の Web サイトへアクセスしよう。
「Install Firefogg」をクリックすると、「このサイトからは Firefox にソフトウェアをインストールできな
い設定になっています」という警告が表示されるはずだ。「許可」をクリックして続行する(図 5-11)。
Firefox は標準的な「ソフトウェアのインストール」ウィンドウを表示する。「今すぐインストール」を
図 5-10 Firefogg のホームページ
図 5-11 Firefogg のインストールを許可する
108
5 章 Web のビデオ
図 5-12 Firefogg をインストールする
図 5-13 Firefox を再起動する
クリックして続行する(図 5-12)。
「Firefox を再起動」ボタンをクリックして、インストールを完了する(図 5-13)。
Firefox が再起動したら Firefogg の Web サイトへアクセスし、正しくインストールできていることを確認
する(図 5-14)。
エンコード処理を開始するには、「Make web video」をクリックし(図 5-15)、次に「ファイルを選択」を
5.8 Firefogg による Ogg ビデオのエンコード
図 5-14 インストールの確認
図 5-15 ビデオの作成
クリックしてビデオの元ファイルを選択する(図 5-16)†。
Firefogg のメイン画面には 6 個の「タブ」がある(図 5-17 参照)。
†
ここで表示される言語メニューで「日本語」を選べば、以降のメニューが日本語で表示される。
109
110
5 章 Web のビデオ
図 5-16 ビデオファイルを選択
図 5-17 ビデオのエンコード
プリセット
デフォルトのプリセットは「カスタム設定」これは元のビデオを大きさはそのまま Ogg に変換す
る設定となっている。他にも「ウェブビデオ Theora、Vorbis」「低帯域幅 Theora、Vorbis」「高品
質 Theora、Vorbis」「WebM ウェブ動画 VP8」「WebM 高品質 VP8」といったプリセットがある
ので、目的に応じたプリセットを使えばよいだろう。
5.8 Firefogg による Ogg ビデオのエンコード
111
エンコーディング範囲
ビデオのエンコードには、長い時間がかかる。最初にやってみるときには、気に入った設定が見つ
かるまで、ビデオの一部(例えば最初の 30 秒)だけをエンコードするのがいいかもしれない。
基本品質と解像度コントロール
後で説明するように、いろいろと重要なオプションが設定できる。
クリップのメタデータ
ここでは説明しないが、エンコードするビデオにタイトルや作者名などのメタデータを設定でき
る。iTunes やその他の音楽管理ソフトで、音楽にメタデータを設定した経験があると思う。考え
方としては、あれと同じだ。
高度な動画変換コントロール
使い方がわかるまで、ここは触らないほうがよい。(Firefogg では、これらのオプションの大部分
に対話的ヘルプ機能が提供されている。オプションの隣にある「i」をクリックすれば説明が表示
される。)
高度な声変換コントロール
ここも、使い方がわかるまでは触らないほうがよい。
ここでは、「基本品質と解像度コントロール」タブ(図 5-18)だけを説明する。これには重要なオプショ
ンがすべて含まれているからだ。
図 5-18 基本品質と解像度コントロール
112
5 章 Web のビデオ
動画品質
これは、0(最低品質)から 10(最高品質)までの段階で設定する。数字が大きくなるほどファイ
ルのサイズも大きくなるので、最適なサイズと品質の組み合わせを得るにはいろいろと実験してみ
る必要があるだろう。
オーディオ品質
これは、0(最低品質)から 10(最高品質)までの段階で設定する。ビデオと同じく、数字が大き
くなるほどファイルのサイズも大きくなる。
動画コーデック
「theora」と「vp8」を選ぶことができる。今回は Ogg ビデオを作成するため「theora」を選ぶ。
「vp8」を選ぶと、作成されるファイルは WebM ビデオになる。
オーディオコーデック
これは常に「vorbis」だ。
動画の横幅と動画の縦幅
これらのデフォルトは、元のビデオの横幅と縦幅に設定されている。ビデオの大きさを変えてエン
コードしたいなら、ここで横幅または縦幅を変更できる。Firefogg はアスペクト比を保つように
もう一方の幅を自動的に調整するので、ビデオがつぶれたり引き伸ばされたりすることはない。
図 5-19 では、ビデオの横幅を元の半分に変更している。Firefogg が、自動的に縦幅を変更してくれてい
ることに注意してほしい。
図 5-19 ビデオの横幅と縦幅の調整
5.8 Firefogg による Ogg ビデオのエンコード
113
図 5-20 「Ogg を保存」をクリックしてエンコード処理を開始
すべて設定し終わったら、「Ogg を保存」をクリックすると、Firefogg はエンコード後のビデオのファイ
ル名を尋ねてくる。保存ダイアログが開かれるので、そこでファイル名を決定し実行すると、実際にエン
コードが開始する(図 5-20)†。
図 5-21 エンコード処理中
†
監訳注:プリセットを WebM のものに変更しても「Ogg を保存」というラベルはそのままだが、保存されるファイルはちゃ
んと WebM になる。
5 章 Web のビデオ
114
Firefogg は、ビデオをエンコードする間、素敵なプログレスバーを表示してくれる。後は(待って、待っ
て、)待つだけだ(図 5-21)。
5.9 ffmpeg2theora を使った Ogg ビデオのバッチエンコード
(前のセクションと同じく、「Ogg ビデオ」という用語を「Ogg コンテナ中の Theora ビデオと Vorbis
オーディオ」の略として使用する。これは、Mozilla Firefox と Google Chrome でネイティブに動作する
コーデックとコンテナの組み合わせだ。)
Ogg ビデオのオフラインエンコーダは数多く存在する。多数のビデオファイルをバッチエンコードする
つもりで、しかも処理を自動化したいなら、ぜひ ffmpeg2theora(http://v2v.cc/~j/ffmpeg2theora/)を
チェックしてみてほしい。
ffmpeg2theora は、GPL のもとライセンスされた、Ogg ビデオをエンコードするオープンソースのアプ
リケーションだ。Mac OS X、Windows、そして最近の Linux ディストリビューション向けに、ビルド済み
のバイナリが用意されている。多くの家庭用ビデオカメラで作成できる DV ビデオを始め、実質的にどんな
ビデオファイルでも受け付けられる。
ffmpeg2theora を使うには、コマンドラインから呼び出す必要がある。(Windows では、スタート→すべ
てのプログラム→アクセサリ→コマンドプロンプト。Mac OS X では、Macintosh HD →アプリケーション
→ユーティリティ→ターミナル。)
ffmpeg2theora では、コマンドラインオプションが多数設定できる。(ffmpeg2theora --help と入力する
と、すべてのオプションが表示される。)ここでは、以下の 3 つについてのみ説明する。
●
--video-quality Q 、ここで Q は 0 ∼ 10 の数字。
●
--audio-quality Q 、ここで Q は -2 ∼ 10 の数字。
●
--max_size=W xH 、ここで W と H はビデオに設定したい最大の横幅と縦幅。(間にある x は、文字
「x」そのものだ。)ffmpeg2theora は、元となるビデオのアスペクト比を保ってビデオをリサイズ
する。したがって、エンコードされたビデオは W xH よりも小さくなる場合がある。例えば、720 ×
480 ピクセルのビデオを --max_size=320x240 でエンコードすると、横幅 320 ピクセルと縦幅 213
ピクセルのビデオが作成される。
したがって、前のセクションと同じ設定(「5.8 Firefogg による Ogg ビデオのエンコード」を参照)でビ
デオをエンコードするには、以下のようにすればよい。
you@localhost$ ffmpeg2theora --videoquality 5
--audioquality 1
--max_size 320x240
pr6.dv
エンコードされたビデオは、元のビデオと同じディレクトリに、拡張子 .ogv を付けて保存される。
ffmpeg2theora へのコマンドラインオプションとして --output=/path/to/encoded/video を指定すれば、別
5.10 HandBrake を使った H.264 ビデオのエンコード
115
のディレクトリやファイル名を指定できる。
5.10 HandBrake を使った H.264 ビデオのエンコード
(このセクションでは、「H.264 ビデオ」という用語を「MPEG-4 コンテナ中の H.264 ベースラインプロ
ファイルビデオと AAC-LC プロファイルオーディオ」の略として使用する。これは、Safari、Adobe Flash、
iPhone、そして Google Android 機器上でネイティブに動作するコーデックとコンテナの組み合わせだ。)
ライセンスの問題はさておき(「5.6 H.264 ビデオのライセンス事情」を参照)、H.264 ビデオをエンコー
ドする最も簡単な方法は、HandBrake(http://handbrake.fr/)†を使うことだ。HandBrake は GPL のも
とライセンスされた、H.264 ビデオをエンコードするオープンソースのアプリケーションだ。(かつては他
のビデオフォーマットもサポートしていたが、開発者は最新バージョンで他のフォーマットのサポートを
廃止し、H.264 ビデオに専念するようになった。)Windows、Mac OS X、そして最近の Linux ディストリ
ビューション向けのビルド済みバイナリが入手できる(http://handbrake.fr/downloads.php)。
HandBrake は、GUI 版とコマンドライン版の 2 種類が利用できる。まず GUI 版を使って流れを説明し、
その後私のおすすめする設定をコマンドライン版で実行する方法について見て行くことにしよう。
HandBrake アプリケーションを開いた後、最初にすべきことはソースのビデオの選択だ(図 5-22)。
「Source」をクリックし、ドロップダウンメニューから「Video File」を選択してファイルを指定する。
HandBrake は、多くの家庭用ビデオカメラで作成できる DV ビデオを含め、実質的にどんなビデオファイ
図 5-22 元となるビデオの選択
†
監 訳 注: 有 志 に よ っ て 日 本 語 化 も 行 わ れ て い る。HandBrake 日 本 語 化 プ ロ ジ ェ ク ト http://sourceforge.jp/projects/
handbrake-jp/wiki/FrontPage から Windows 向けの最新ビルドを入手できる。
116
5 章 Web のビデオ
図 5-23 この警告は無視できる
図 5-24 iPhone プリセットを選択する
5.10 HandBrake を使った H.264 ビデオのエンコード
117
ルも受け付けられる。
エンコードされたビデオを保存するデフォルトディレクトリを設定していないと、HandBrake は警告
メッセージを出力する(図 5-23)。この警告は無視しても安全だが、Options ウィンドウ(「Tools」メニュー
の下にある)を開いてデフォルト出力ディレクトリを設定することもできる。
右側には、プリセットのリストが表示される。図 5-24 のように「iPhone & iPod Touch」プリセットを
選択すれば、大部分の必要なオプションが設定される。
デフォルトでオフになっているオプションのうち、重要なのは「Web optimized」オプションだ。図 5-25
のようにこのオプションを選択すると、エンコードされたビデオのメタデータが再構成され、ビデオをバッ
クグラウンドでダウンロードしながら再生を開始できるようになる。このオプションは、常にチェックして
おくことをおすすめする。エンコードされたビデオの品質やサイズには影響しないので、チェックしない理
由はないはずだ。
「Picture」タブで、エンコードされたビデオの最大の横幅(width)と縦幅(height)が設定できる(図
5-26)。HandBrake にビデオをつぶしたり引き伸ばしたりされたくなければ、「Keep Aspect Ratio」オプ
ションも忘れずに選択しておこう。
図 5-27 の「Video」タブでは、いくつかの重要なオプションが設定できる。
Video Codec(ビデオコーデック)
これが「H.264 (x264)」になっていることを確認。
図 5-25 常に Web optimized を選択する
118
5 章 Web のビデオ
図 5-26 横幅と縦幅を設定する
図 5-27 ビデオ品質のオプション
5.10 HandBrake を使った H.264 ビデオのエンコード
119
2-Pass Encoding(2 パスエンコーディング)
これをチェックすると、HandBrake はビデオエンコーダを 2 回実行する。最初はただ単にビデオ
を解析し、色の構成、動き、場面の転換点などを記録する。次のパスで、最初のパスで得られた情
報を使って実際にビデオをエンコードするのだ。ご想像どおり、1 パスでのエンコーディングと比
べて 2 倍近い時間がかかるが、ファイルサイズを増やさずにビデオの画質が向上できるという利
点がある。筆者は、H.264 ビデオでは常に 2 パスエンコーディングを行っている。YouTube のよ
うなサービスを構築していて一日中ビデオをエンコードし続けているのでなければ、たぶん 2 パ
スエンコードを使うのがよいだろう。
Turbo First Pass(ターボファーストパス)
2 パスエンコーディングを行う場合、このオプションを選択すると多少時間が節約できる。最初の
パスで行われる仕事(ビデオの解析)の量を減らすが、画質の低下はごくわずかだ。筆者は通常こ
のオプションを選択しているが、最高の画質を求めるなら選択しないほうがよいだろう。
Quality(画質)
エンコードされたビデオの「品質」を指定するには、いくつか方法がある。目標ファイルサイズ
(Target Size)を設定すれば、HandBrake はエンコード後のビデオの大きさがそれ以下になるよ
うにしてくれる。平均「ビットレート」(Avg Bitrate)を指定することもでき、これは文字通り、
(1 秒当たり必要なビッ
1 秒分のエンコードされたビデオを保存するのに必要なビット数の意味だ。
ト数は一定ではないので、「平均」ビットレートと呼ばれる。)また、0 ∼ 100%の尺度で固定品質
を設定することもでき、数字が大きいほど品質はよくなるが、ファイルは大きくなる。どの方法で
品質を指定すべきかは、場合によって異なる。
マークアップ教授に質問
Q:Ogg ビデオでも、2 パスエンコーディングはできますか?
A:可能だが、エンコーダの動作が基本的に異なるため、その必要はないだろう。H.264 を 2 パスでエン
コードすると、ほぼ確実に高品質のビデオが得られる。Ogg を 2 パスでエンコードしても、それが有効と
なるのはエンコード後のビデオを特定のファイルサイズにしたい場合だけだ。(そうしたい人もいるかもし
れないが、ここで説明した実例には当てはまらないし、また Web ビデオをエンコードするためにかかる余
計な時間には見合わないだろう。)Ogg ビデオで最高の品質を得るには、ビデオ品質の設定を使うべきで、
2 パスエンコーディングについては気にしないほうがいい。
この例では、平均ビットレート 600kbps を選択した。これは 320 × 240 でエンコードされるビデオにし
ては、かなり高いビットレートだ。また、2 パスエンコーディングと、「ターボ」ファーストパスも設定し
た。
図 5-28 の「Audio」タブでは、何も変更しないほうがよいだろう。元となるビデオに複数のオーディオ
120
5 章 Web のビデオ
図 5-28 オーディオ品質のオプション
図 5-29 保存するファイル名を指定する
5.11 HandBrake を使った H.264 ビデオのバッチエンコード
121
図 5-30 ビデオの作成
図 5-31 あとは待つのみ
トラックが存在する場合には、エンコードされたビデオにどれを入れるか選択する必要があるかもしれな
い。ビデオが主に人の会話(音楽や一般的な背景音ではなく)から成り立っている場合には、オーディオ
ビットレートを 96kbps 程度まで落とすことができるだろう。それ以外の場合には、「iPhone」プリセット
から継承したデフォルト値で十分なはずだ。
次に、「Browse」ボタンをクリックし、エンコードされたビデオを保存するディレクトリとファイル名を
指定する(図 5-29)。
最後に、「Start」をクリックすればエンコードが始まる(図 5-30)。
HandBrake は、ビデオをエンコードしながら進捗状況を表示してくれる(図 5-31)。
5.11 HandBrake を使った H.264 ビデオのバッチエンコード
(前のセクションと同じく、「H.264 ビデオ」という用語を「MPEG-4 コンテナ中の H.264 ベースライン
プロファイルビデオと AAC-LC プロファイルオーディオ」の略として使用する。これは、Safari、Adobe
Flash、iPhone、そして Google Android 機器上でネイティブに動作するコーデックとコンテナの組み合わ
5 章 Web のビデオ
122
せだ。)
前のセクションで説明したとおり、HandBrake にはコマンドライン版もある。ffmpeg2theora(「5.9
ffmpeg2theora を 使 っ た Ogg ビ デ オ の バ ッ チ エ ン コ ー ド 」 を 参 照 ) と 同 様 に、 コ マ ン ド ラ イ ン 版 の
HandBrake には膨大なオプションが指定できる。(ターミナルウィンドウまたはコマンドプロンプトで
HandBrakeCLI --help と入力すれば一覧が表示される。)ここでは、そのごく一部について説明する。
●
--preset "X" 、ここで "X" は HandBrake のプリセット名だ(プリセット名の前後に引用符が必
要)。H.264 Web ビデオには、"iPhone & iPod Touch" プリセットを指定する。
●
--width W 、ここで W はエンコードされたビデオの横幅だ。HandBrake は自動的に縦幅を調整して
元のビデオの比率を保ってくれる。
●
--vb Q 、ここで Q は平均ビットレートだ(kbps 単位で指定する)。
●
--two-pass は、2 パスエンコーディングを指示する。
●
--turbo は、2 パスエンコーディングでターボファーストパスを指示する。
●
--input F 、ここで F は元となるビデオのファイル名。
●
--output E 、ここで E はエンコードされたビデオを保存するファイル名。
以下は、GUI 版の HandBrake で選択したものと同じ設定のコマンドラインオプションを指定した、コマ
ンドライン版の HandBrake の実行例だ。
you@localhost$ HandBrakeCLI --preset "iPhone & iPod Touch"
--width 320
--vb 600
--two-pass
--turbo
--input pr6.dv
--output pr6.mp4
上から順に、このコマンドは "iPhone & iPod Touch" プリセットを使用し、ビデオを 320 × 240 にリサ
イズし、平均ビットレートを 600kbps に設定し、2 パスエンコーディングとターボファーストパスを行い、
ファイルを pr6.dv から読み、エンコード結果を pr6.mp4 に保存して HandBrake を実行する、という意味
になる。ふぅ。
5.12 ffmpeg を使った WebM のエンコード
WebM は ffmpeg 0.6 以降でサポートされている。では、まずコマンドラインで ffmpeg をパラメータな
しで実行し、VP8 サポートがコンパイルされていることを確認する。
5.12 fmpeg を使った WebM のエンコード
123
you@localhost$ ffmpeg
FFmpeg version SVN-r23197, Copyright (c) 2000-2010 the FFmpeg developers
built on May 19 2010 22:32:20 with gcc 4.4.3
configuration: --enable-gpl --enable-version3 --enable-nonfree --enable-postproc
--enable-pthreads --enable-libfaac --enable-libfaad --enable-libmp3lame
--enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libtheora
--enable-libx264 --enable-libxvid --enable-x11grab
--enable-libvorbis --enable-libvpx
--enable-libvorbis と --enable-libvpx というキーワードが見つからなかった場合には、ffmpeg のバー
ジョンが違っている。(自身で ffmpeg をコンパイルした場合は、2 つのバージョンがインストールされて
いないかどうか確かめてみてほしい。複数のバージョンが互いに干渉することはないので、そのこと自体は
問題ないのだが、VP8 を扱えるバージョンの ffmpeg のフルパスを入力する必要があるだろう。)
2 パスエンコード(「5.10 HandBrake を使った H.264 ビデオのバッチエンコーディング」を参照)を行
う方法をこれから説明する。ファーストパスは入力ビデオファイルをスキャンし(-i pr6.dv)統計情報を
ログファイル(自動的に pr6.dv-0.log という名前が与えられる)へ書き出すだけだ。ビデオコーデックは
-vcodec パラメータで指定する。
you@localhost$ ffmpeg -pass 1 -passlogfile pr6.dv -threads 16 -keyint_min 0 -g 250 -skip_threshold
0 -qmin 1 -qmax 51 -i pr6.dv -vcodec libvpx -b 614400 -s 320x240 -aspect 4:3 -an -y NUL
ffmpeg コマンドラインの大部分は、VP8 や WebM とは関係ない。libvpx は、VP8 特有のオプションを
いくつかサポートしていて、それを ffmpeg に渡すこともできるはずだが、筆者自身はまだ試したことはな
い。これらのオプションについてよい説明が見つかったら、この本のウェブサイトにリンクを張っておくこ
とにする。
セカンドパスで、ffmpeg はファーストパスで作成した統計情報を読み込み、ビデオとオーディオのエン
コードを行う。こうして、エンコードされた .webm ファイルが書き出される。
you@localhost$ ffmpeg -pass 2 -passlogfile pr6.dv -threads 16 -keyint_min 0 -g 250 -skip_threshold
0 -qmin 1 -qmax 51 -i pr6.dv -vcodec libvpx -b 614400 -s 320x240 -aspect 4:3 -acodec libvorbis -y
pr6.webm
5 つの重要なパラメータについて、説明しておこう。
-vcodec libvpx
VP8 ビデオコーデックを使ったエンコードを指示する。WebM は常に VP8 ビデオを使用する。
-b 614400
ビットレートを指定する。他のフォーマットとは異なり、libvp8 にはキロビットではなく、実際の
値をそのまま指定する。つまり 600kbps のビデオが欲しければ、600 に 1024 を掛けて 614400 を
指定することになる。
124
5 章 Web のビデオ
-s 320x240
出力ビデオのサイズを、横幅と縦幅で指定する。
-aspect 4:3
ビデオのアスペクト比を指定する。標準的なビデオでは通常 4:3 だが、高解像度ビデオでは 16:9
あるいは 16:10 のものが大部分だ。筆者が試験したところでは、ffmpeg に自動検出させるのでは
なく、コマンドライン上で明示的に指定する必要があった。
-acodec libvorbis
Vorbis オーディオコーデックを使ったエンコードを指定する。WebM は常に Vorbis オーディオを
使用する。
5.13 そして、マークアップへ
私の記憶が正しければ、これは HTML の本だったはずだ。マークアップについて説明しよう。
HTML5 では、ビデオを Web ページに埋め込む方法が 2 種類用意されている。両方とも <video> 要素
を使う。ビデオファイルが 1 個しかなければ、それを単に src 属性へリンクすればよい。これは、画像を
<img src=”…”> タグへ埋め込む方法ときわめてよく似ている。
<video src="pr6.webm"></video>
技術的には、これだけでよい。しかし <img> タグと同様に、<video> タグにも常に width と height 属性
を付け加えるべきだ。この width と height 属性は、エンコード時に指定した最大の横幅と縦幅と同じもの
でよい。
実際のビデオのどちらかの寸法が、これより小さくても構わない。ブラウザは <video> タグで指定した
ボックス内の中央にビデオを表示してくれる。勝手に比率が変更されて、つぶれたり引き伸ばされたりする
ことはない。
<video src="pr6.webm" width="320" height="240"></video>
デフォルトでは <video> 要素は再生コントロールの類を何も提供しない。おなじみの HTML、CSS、
そして JavaScript を使って、自分でコントロールを作成することができる。<video> 要素は play() や
pause() などのメソッドや、currentTime と呼ばれる読み書き可能なプロパティを持っている。他にも、
volume や muted という読み書き可能なプロパティもある。自分でインタフェースを構築するために必要な
道具は揃っているわけだ。
自分でインタフェースを作るつもりがなければ、ブラウザに組み込みのコントロールを表示させることも
できる。これを行うには、<video> タグに controls 属性を追加するだけでよい。
<video src="pr6.webm" width="320" height="240" controls></video>
先へ進む前に、preload と autoplay というあと 2 個のオプション属性について説明させてほしい。ちょっ
5.13 そして、マークアップへ
125
と待って、この 2 つがどんなに役に立つか今説明するから…。preload 属性は、ページがロードされたらす
ぐにビデオファイルのダウンロードを開始するようにブラウザへ指示するためのものだ。これは、例えばビ
デオだけが表示されるページに設定するのがよいだろう。一方、一部のビジターしか見ないような補助的な
資料であれば、preload を none に設定することによって、ネットワークのトラフィックを最小限に抑える
ことができる。
この例では、ページがロードされたらすぐにビデオのダウンロードが開始される(再生はしない)。
<video src="pr6.webm" width="320" height="240" preload></video>
この例では、ページがロードされてもビデオのダウンロードは開始されない。
<video src="pr6.webm" width="320" height="240" preload="none"></video>
autoplay 属性は、まさにその名のとおりの働きをする。ページがロードされたらすぐにビデオファイル
のダウンロードを開始し、そして自動的にビデオの再生をなるべく早く開始するよう、ブラウザに指示する
のだ。このような機能が好ましいと思う人もいるが、大嫌いな人もいる。しかし、HTML5 にこの属性が存
在することの重要性を、説明させてほしい。たとえビジターが気に入らなくても、ビデオを自動的に再生し
たいと考える人々がいる。もし HTML5 でビデオを自動的に再生する標準的な方法を定義していなかった
としても、その手の人々はいずれにしろ JavaScript のハックを使って(例えばウィンドウの load イベント
中にビデオの play() メソッドを呼び出して)同じことをやってのけてしまうだろう。これは、ビジターの
側からすると、ずっと対策が難しい。一方、ブラウザに拡張機能を追加して(あるいは、必要ならコードを
書いて)「私は自動的にビデオを再生してほしくないから、autoplay 属性を無視せよ」と指示するのは簡単
なことだ。
この例では、ページがロードされるとすぐにビデオのダウンロードと再生が開始される。
<video src="pr6.webm" width="320" height="240" autoplay></video>
そ し て こ れ が、Firefox に イ ン ス ト ー ル す る と HTML5 ビ デ オ の 自 動 再 生 を 禁 止 し て く れ る
Greasemonkey †スクリプトだ。ここでは、HTML5 で定義された autoplay DOM プロパティ(JavaScript
中で HTML マークアップの autoplay 属性に対応する)を使っている。
//
//
//
//
//
//
†
==UserScript==
@name Disable video autoplay
@namespace http://diveintomark.org/projects/greasemonkey/
@description Ensures that HTML5 video elements do not autoplay
@include *
==/UserScript==
http://www.greasespot.net を参照。
126
5 章 Web のビデオ
var arVideos = document.getElementsByTagName('video');
for (var i = arVideos.length - 1; i >= 0; i--) {
var elmVideo = arVideos[i];
elmVideo.autoplay = false;
}
しかし、ちょっと待ってほしい。この章をここまで読んできた読者なら、ビデオファイルは 1 種類では
なく、3 種類必要なことを知っているはずだ。ひとつは Firefogg(「5.8 Firefogg を使った Ogg ビデオのエ
ンコード」を参照)または ffmpeg2theora(「5.9 ffmpeg2theora を使った Ogg ビデオのバッチエンコード」
を参照)を使って作成した .ogv ファイルだ。もうひとつは HandBrake(「5.10 HandBrake を使った H.264
ビデオのエンコード」を参照)を使って作成した .mp4 ファイルだ。3 つ目は ffmpeg(「5.12 ffmpeg を使っ
た WebM のエンコード」を参照)を使って作成した .webm ファイルだ。HTML5 では、<source> 要素を
使ってこれら 3 つのファイルをすべてリンクする方法を提供している。各 <video> 要素は、必要なだけの
数の <source> 要素を含むことができる。ブラウザはこのビデオソースのリストを順番に調べて、再生可能
な最初のものを再生するのだ。
ここで、もうひとつの疑問が浮かび上がる。どうやってブラウザは、ビデオが再生可能だと判断するのだ
ろうか。最悪の状況では、ビデオをひとつひとつロードして再生を試みることになる。しかしこれは帯域幅
の大幅な無駄遣いだ。もしブラウザに前もってビデオの形式を教えておくことができれば、ネットワークト
ラフィックを大幅に節約できる。これは、<source> 要素の type 属性を使って行う。
以下がその例だ。
<video width="320" height="240" controls>
<source src="pr6.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'>
<source src="pr6.webm" type='video/webm; codecs="vp8, vorbis"'>
<source src="pr6.ogv" type='video/ogg; codecs="theora, vorbis"'>
</video>
順を追って説明しよう。<video> 要素はビデオの横幅と縦幅を指定しているが、実際のビデオファイルへ
のリンクはしていない。<video> 要素の内部には、3 個の <source> 要素が存在する。各 <source> 要素は、
それぞれ 1 個のビデオファイルに(src 属性によって)リンクしており、ビデオフォーマットに関する情報
を(type 属性中で)与えている。
type 属性は複雑に見える。実際、複雑なのだ。ここには 3 種類の情報が含まれている。コンテナフォー
マット(「5.2 ビデオのコンテナ」を参照)、ビデオコーデック(「5.3 ビデオコーデック」を参照)、そして
オーディオコーデック(「5.4 オーディオコーデック」を参照)だ。後のほうから説明しよう。.ogv ビデオ
ファイルでは、コンテナフォーマットは Ogg で、ここでは vido/ogg で表現されている。(技術的に言うと、
これは Ogg ビデオファイルの MIME タイプだ。)ビデオコーデックは Theora で、オーディオコーデック
は Vorbis だ。これ自体は単純なのだが、属性値の記述方法はちょっとやっかいだ。codecs の値自身が引用
符を含んでいるので、別の種類の引用符を使って type 属性値全体を囲んでやる必要があるのだ。
<source src="pr6.ogv" type='video/ogg; codecs="theora, vorbis"'>
5.13 そして、マークアップへ
127
WebM 用 の <source> 要 素 も ほ ぼ 同 じ だ が、MIME タ イ プ(video/ogg の 代 わ り に video/webm) と、
codecs パラメータ内のビデオコーデック(theora の代わりに vp8)が違っている。
<source src="pr6.webm" type='video/webm; codecs="vp8, vorbis"'>
H.264 ファイル用の <source> 要素は、さらに複雑だ。以前、H.264 ビデオ(「5.3.1 H.264」を参照)と
AAC オーディオ(「5.4.2 Advanced Audio Coding」を参照)の両方に、各種の「プロファイル」が存在す
ると説明したことを覚えているだろうか。この例では H.264 ベースラインプロファイルと AAC-LC プロファ
イルを使ってエンコードを行い、全体を MPEG-4 コンテナに格納した。この情報すべてが、type 属性に含
まれている。
<source src="pr6.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'>
ここまで面倒なことをするのは、ブラウザが最初に type 属性を見てそのビデオファイルを再生できるか
どうか判断できるようにするためだ。ブラウザがそのビデオを再生できないと判断したら、そのファイルは
ダウンロードしない。ファイルの一部分さえもだ。帯域幅は節約できるし、ビジターは自分の見たいビデオ
をより早く見ることができる。
この章で説明した方法でビデオをエンコードした場合は、上記の type 属性をコピーするだけでよい。そ
うでなければ、自分で正しい type 属性の値を設定する必要がある。
マークアップ教授から一言
iOS 3.x 搭載の iPad にはリストされたビデオソースの最初しか認識されないというバグがあった。iOS 4
(すべての iPad が無償でアップグレードできる最新バージョン)はこのバグが修正されている。もし iOS
4 にアップグレードしていないユーザにもビデオを届けたい場合、MP4 ファイルをリストの最初に置き、
その後にフリーのビデオフォーマットをおく必要がある。なんてこったい。
5.13.1 MIME タイプが引き起こす可能性のある問題
ビデオというパズルには、あまりにも多くのピースがありすぎるので、できれば私はこの件には触れた
くなかった。しかしこれは重要な話だ。Web サーバの設定が間違っていると、ローカルなコンピュータ上
では問題なく再生できるビデオを実際のサイトへアップロードすると再生できない、などという問題のデ
バッグに頭を悩ますことになりかねないからだ。もしこのような問題が発生したら、その原因はおそらく
MIME タイプだろう。
MIME タイプについては、1 章で説明した(「1.2 MIME タイプ」を参照)が、軽く見過ごしてしまって
その重要性に気付かなかった読者がほとんどだろう。だからここで強調しておく。
128
5 章 Web のビデオ
マークアップ教授の叫び
ビデオファイルは、正しい MIME タイプとともに使われなくてはならない!
正しい MIME タイプとは何だろうか。賢明なる読者の皆さんは、もうわかっているはずだ。それは
<source> 要素の type 属性の値の一部として指定されている。しかし、HTML マークアップで type 属性を
設定するだけでは不十分だ。Web サーバが、正しい MIME タイプを Content-Type HTTP ヘッダに指定し
ていることも確認しなくてはならない。
Web サーバとして Apache やその派生品を使っている場合には、サイト全体の httpd.conf 設定ファイ
ル、またはビデオファイルのあるディレクトリの .htaccess ファイルの中で、AddType ディレクティブを
使って指定すればよい。(それ以外の Web サーバを使っている場合には、特定のファイルタイプに対して
Content-Type HTTP ヘッダを指定する方法をサーバの文書で調べてほしい。)設定が必要な AddType ディ
レクティブは、以下のとおりだ。
AddType video/ogg .ogv
AddType video/mp4 .mp4
AddType video/webm .webm
最初の行は、Ogg コンテナ中のビデオのもの。2 行目は、MPEG-4 コンテナ中のビデオのもの。3 行目
は、WebM のものだ。これらの設定を行ってしまえば、後は忘れてしまってもよい。これらの設定を行わ
ないと、HTML マークアップの type 属性に MIME タイプを設定しても、一部のブラウザではビデオが再
生できなくなるかもしれない。
Web サーバの設定に関するもっと生々しい実例については、Mozilla Developer Center のすばらしい
記事「Ogg メディアのためのサーバ設定」† を参照することをおすすめする。(この記事のアドバイスは、
MP4 や WebM ビデオについても当てはまる。)
5.14 IE の場合
Internet Explorer 9 は <video> 要素をサポートする ††。Microsoft は以前から IE9 の最終版では Safari
や iPhone などと同様に、MPEG-4 コンテナ中の H.264 ビデオと AAC オーディオをサポートすると公式に
約束していた‡。
しかし、古いバージョンの Internet Explorer についてはどうなるのだろうか。つまり、今まで出荷され
た IE 8 以前のバージョンのことだ。Internet Explorer を使っている人の大部分は、Adobe Flash プラグイ
ンもインストールしている。最近のバージョンの Adobe Flash(9.0.60.184 以降)は、MPEG-4 コンテナ中
†
https://developer.mozilla.org/en/Configuring_servers_for_Ogg_media を参照。
††
http://msdn.microsoft.com/en-us/ie/ff468705.aspx#_HTML5_video_audio を参照。
‡
http://blogs.msdn.com/ie/archive/2010/03/16/html5-hardware-accelerated-first-ie9-platform-preview-available-fordevelopers.aspx
5.16 Android 端末の問題
129
の H.264 ビデオと AAC オーディオをサポートしている。ビジターが HTML5 互換ブラウザを使っていない
ことを検出したら、Safari 用にエンコードした H.264 ビデオを(「5.10 HandBrake を使った H.264 ビデオ
のエンコード」を参照)、Flash ベースのビデオプレイヤーで再生すればよい。
FlowPlayer(http://flowplayer.org/)は、GPL のもとライセンスされた、オープンソースで開発される
Flash ベースのビデオプレイヤーだ†。FlowPlayer は <video> 要素のことは何も知らないので、<video> タ
グを魔法のように Flash オブジェクトへ変換してくれるわけではない。しかし HTML5 はうまくできてい
て、<video> 要素の中に <object> 要素を入れ子にできるので、この問題に十分対応できる。HTML5 ビデ
オをサポートしないブラウザは <video> 要素を無視して入れ子になった <object> 要素を単純に表示するた
め、Flash プラグインを起動して FlowPlayer で動画を再生することが可能だ。HTML5 ビデオをサポート
するブラウザは再生可能なビデオソースを見つけて再生し、入れ子になった <object> 要素を完全に無視す
る。
この最後の点が、パズル全体の中で最も重要なポイントだ。HTML5 では、<video> 要素の子要素である
すべての要素(<source> 要素以外)は完全に無視されなくてはならない、と規定されている。これによっ
て、JavaScript によるハックを必要とせずに、新しいブラウザでは HTML5 ビデオを使用し、古いブラウ
ザではスムーズに Flash で代替することが可能となる。このテクニックに関しては、Video for Everybody!
のサイト(http://camendesign.com/code/video_for_everybody)に詳しい情報がある。
5.15 iPhone と iPad の問題
iOS は Apple が開発する iPhone、iPod touch、iPad のオペレーティングシステムだ。このうち iOS 3.2
には HTML5 ビデオに関し多くの問題がある。
1.
poster 属性を video 要素に記述すると、iOS はそのビデオを認識しなくなる。poster 属性はビデ
オのロード中や、ユーザが「再生」を押すまでの間に表示される画像を提供するものだ。iOS 4.0
でこのバグは修正されたが、ユーザが OS をアップデートするまでにはしばらくかかるだろう。
2.
複数の <source> 要素がある場合、iOS は最初に記述された要素以外を認識しない。iOS 搭載デバ
イスは H.264+AAC+MP4 しかサポートしないので、<source> を書く際には MP4 を一番最初にし
なければいけない。このバグも iOS 4.0 では修正されている。
5.16 Android 端末の問題
Android は Google が提供するオペレーティングシステムで、多くの携帯電話やその他の携帯デバイスで
利用されている。そして、Android 2.3 より前のバージョンにも HTML5 ビデオに関し多くの問題がある。
1.
<source> 要素の type 属性は Android をひどく混乱させる。ビデオを認識させるには、皮肉にも
type 属性を省略し、かつ H.264 + AAC + MP4 なビデオの拡張子を .mp4 としなければいけない。
Android 2.2 までは H.264 のみをサポートしていることから、他の <source> については type 属性
を書いてもよいだろう。なお、Android 2.3 ではこのバグは修正されている。
†
商用ライセンスも利用可能。http://flowplayer.org/download/ を参照のこと。
5 章 Web のビデオ
130
2.
controls 属性がサポートされていない。type 属性のように書くと問題になるものではないので安
心だが、Android ではビデオのユーザインタフェースが現れない。このため、独自にユーザインタ
フェースを提供する必要がある。最低限、ユーザがビデオをクリックしたらビデオを再生するスク
リプトを提供すべきだろう。Android 2.3 ではこのバグは修正されている。
5.17 総合的な実例
今までに説明したテクニックを使った実例をお見せしよう。これは、Video for Everybody! のコードに
WebM フォーマットビデオを付け加えて作製したものだ。まず、以下のコマンドを使って、同じソースビ
デオから 3 つのフォーマットを作成する。
## Theora/Vorbis/Ogg
you@localhost$ ffmpeg2theora --videobitrate 200 --max_size 320x240 --output pr6.ogv pr6.dv
## H.264/AAC/MP4
you@localhost$ HandBrakeCLI --preset "iPhone & iPod Touch" --vb 200 --width 320 --two-pass --turbo
--optimize --input pr6.dv --output pr6.mp4
## VP8/Vorbis/WebM
you@localhost$ ffmpeg
0 -qmin 1 -qmax 51 -i
you@localhost$ ffmpeg
0 -qmin 1 -qmax 51 -i
-y pr6.webm
-pass 1 -passlogfile pr6.dv -threads 16 -keyint_min 0 -g 250 -skip_threshold
pr6.dv -vcodec libvpx -b 204800 -s 320x240 -aspect 4:3 -an -f webm -y NUL
-pass 2 -passlogfile pr6.dv -threads 16 -keyint_min 0 -g 250 -skip_threshold
pr6.dv -vcodec libvpx -b 204800 -s 320x240 -aspect 4:3 -acodec libvorbis -ac 2
最終的なマークアップは、HTML5 ビデオに <video> 要素を使い、代替手段としての Flash には入れ子に
なった <object> を使っている。また、Android のため簡易なスクリプトを提供している。
<video id="movie" width="320" height="240" preload controls>
<source src="pr6.webm" type='video/webm; codecs="vp8, vorbis"' />
<source src="pr6.ogv" type='video/ogg; codecs="theora, vorbis"' />
<source src="pr6.mp4" />
<object width="320" height="240" type="application/x-shockwave-flash"
data="flowplayer-3.2.1.swf">
<param name="movie" value="flowplayer-3.2.1.swf" />
<param name="allowfullscreen" value="true" />
<param name="flashvars" value='config={"clip": {"url": "http://wearehugh.com/dih5/pr6.mp4",
"autoPlay":false, "autoBuffering":true}}' />
<p>Download video as <a href="pr6.mp4">MP4</a>, <a href="pr6.webm">WebM</a>, or <a href="pr6.
ogv">Ogg</a>.</p>
</object>
</video>
<script>
5.18 参考文献
131
var v = document.getElementById("movie");
v.onclick = function() {
if (v.paused) {
v.play();
} else {
v.pause();
}
};
</script>
このように HTML5 と Flash を組み合わせれば、ほとんどすべてのブラウザと機器でこのビデオを見ら
れるようにできるはずだ。
5.18 参考文献
●
HTML5 仕様の「<video> 要素」
http://whatwg.org/html5#video
●
Video for Everybody!
http://camendesign.com/code/video_for_everybody
●
Christopher Blizzard による「Theora 1.1 のリリースに際して、知っておくべきこと」
http://hacks.mozilla.org/2009/09/theora-1-1-released/
●
「Ogg メディアのためのサーバ設定」
https://developer.mozilla.org/en/Configuring_servers_for_Ogg_media
●
「x264 コーデックによるエンコード」
http://www.mplayerhq.hu/DOCS/HTML/en/menc-feat-x264.html
●
「ビデオ形式パラメータ」
http://wiki.whatwg.org/wiki/Video_type_parameters
●
HTML5 ビデオのカスタムコントロール集、Zencoder Video JS
http://videojs.com/
●
Simon Pieters による「HTML5 のオーディオとビデオについて知っておくべきすべてのこと」
http://dev.opera.com/articles/view/everything-you-need-to-know-about-html5-video-and-audio/
●
Peter Gasston による「Android で HTML5 ビデオを再生する方法」
http://www.broken-links.com/2010/07/08/making-html5-video-work-on-android-phones/
●
Internet Explorer 9 Guide for Developers の「HTML5 の video 要素と audio 要素」
http://msdn.microsoft.com/en-us/ie/ff468705.aspx#_HTML5_video_audio
5 章 Web のビデオ
132
ブラウザの UI ではなく、独自の HTML5 ビデオプレイヤー UI を提供するライブラリ。
●
VideoJS
http://videojs.com/
●
MediaElement.js
http://mediaelementjs.com/
●
Kaltura HTML5 Video & Media JavaScript Library
http://www.kaltura.org/project/HTML5_Video_Media_JavaScript_Library
133
6章
Geolocation API による
位置情報通知
6.1 はじめに
Geolocation(位置情報通知機能)は、あなたが地球上のどこにいるかを調べる機能で、そしてその情報
をあなたの信頼する人々に知らせることができる。位置の検出には、いろいろな方法がある。いくつか例を
挙げれば、IP アドレス、無線ネットワークへの接続状況、携帯電話が通信している基地局、あるいは人工
衛星からの緯度・経度情報を受信する GPS 専用ハードウェアなどだ。
マークアップ教授に質問
Q:自分のいる場所を知らせるなんて、ちょっとこわい気がします。禁止できますか?
A:リモートの Web サーバに物理的な位置情報を通知する際、プライバシーについて心配するのは当然
のことだ。Geolocation API の仕様には、明確に以下のように書かれている†。「ユーザエージェントは、
ユーザからの明確な許可の表明がない限り、Web サイトへ情報を送出してはならない。」別の言い方をすれ
ば、位置情報を通知したくなければ、通知する必要はないということだ。
6.2 Geolocation API
Geolocation API を使って、あなたの位置情報を信頼する Web サイトへ通知することができる。緯度と
経度がページの JavaScript によって取得され、次にその情報がリモートの Web サーバへ送信され、例えば
自分の近くにある店を見つけたり、地図上に自分の居る位置を表示したりといった、位置情報を利用した
サービスが利用できるようになる。
表 6-1 を見てわかるとおり、Geolocation API は多くのデスクトップおよびモバイル機器上のブラウザで、
すでにサポートされている。また、この章の後のほうで説明するように、古いブラウザや機器であっても
ラッパライブラリによるサポートが可能な場合もある。
†
http://www.w3.org/TR/geolocation-API/#security を参照。
134
6 章 Geolocation API による位置情報通知
表 6-1 Geolocation API のサポート状況
IE
Firefox
Safari
Chrome
Opera
iPhone
Android
9.0 ∼
3.5 ∼
5.0 ∼
5.0 ∼
10.6 ∼
3.0 ∼
2.0 ∼
標準的な Geolocation API をサポートしている機器以外にも、さまざまなモバイルプラットフォームで機
器依存の API が提供されている。これについてはこの章で後に説明する。
6.3 実際のコード
Geolocation API は、navigator オブジェクトの navigator.geolocation という新しいプロパティを利用
する。
Geolocation API の最も単純な利用方法は、以下のようなものだ。
function get_location() {
navigator.geolocation.getCurrentPosition(show_map);
}
このコードは、機能の検出もエラー処理も行っていないし、何のオプションも指定していない。しかし実
際の Web アプリケーションには、少なくとも機能の検出とエラー処理は必要となるだろう。Geolocation
API がサポートされているかどうかを検出するには(「2.11 Geolocation」を参照)、Modernizr を使えばよ
い。
function get_location() {
if (Modernizr.geolocation) {
navigator.geolocation.getCurrentPosition(show_map);
} else {
// Geolocation API のネイティブサポートはないようだ。
// Gears を試してみようか?
}
}
Geolocation API がサポートされていなかった場合にどうするかはあなたの自由だ。この後に Gears を
使った代替手段について説明するが、その前にここでは getCurrentPosition() への呼び出し中に何が起こ
るのかを見てみよう。この章の最初で述べたように、Geolocation のサポートはオプトインだ。これはつま
り、ブラウザがあなたの物理的な現在位置をリモートのサーバへ勝手に通知するようなことがあってはなら
ない、という意味だ。実際のユーザ体験は、ブラウザによって異なる。Mozilla Firefox では、Geolocation
API の getCurrentPosition() 関数を呼び出すことによって、ブラウザウィンドウの上部に「情報バー」が
表示される。この情報バーは、図 6-1 のようなものだ。
図 6-1 Geolocation 情報バー
6.3 実際のコード
135
ここでは、いろいろなことができる。エンドユーザは、
●
Web サイトがあなたの位置情報を知ろうとしていることがわかる。
●
どの Web サイトがあなたの位置情報を知ろうとしているかがわかる。
●
「詳細を表示…」をクリックして Mozilla の「位置情報通知機能」ヘルプページを表示し、これが
いったいどういうことなのかを知ることができる。
●
位置情報の通知を選択できる。
●
位置情報の非通知を選択できる。
●
今の選択(通知か非通知か)をブラウザに覚えさせ、この Web サイトではこの情報バーが二度と
表示されないようにできる。
さらに、この情報バーは、
●
ノンモーダルなので、別のブラウザウィンドウやタブへの切り替えは自由に行える。
●
タブ特有なので、別のブラウザウィンドウやタブへ切り替えると消え、元のタブに戻ると再び現れ
る。
●
無条件なので、Web サイトがこれをバイパスすることはできない。
●
先の処理をブロックするので、Web サイトがユーザの返答を待たずに位置情報を得るといったこ
とはない。
さっき見た、この情報バーが現れる JavaScript を思い出してほしい。そこでは、1 個の関数を呼んでいて、
その引数にはコールバック関数(show_map という名前だった)が指定されていた。getCurrentPosition()
への呼び出しはすぐにリターンするが、それはユーザの位置情報へアクセスできるようになったという意味
ではない。位置情報が得られたことを保証するのは、引数に与えたコールバック関数なのだ。このコール
バック関数は、例えば以下のようになるだろう。
function show_map(position) {
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
// 地図の表示など、いろいろ面白いことをしてみよう!
}
このコールバック関数は 1 個のパラメータとともに呼ばれ、それは coords と timestamp という 2 つのプ
ロパティを持つオブジェクトだ。timestamp はまさにタイムスタンプで、位置情報が取得された日付と時
間を示す。(位置情報の取得は非同期的に行われるので、前もっていつ呼び出されるかを知ることはできな
136
6 章 Geolocation API による位置情報通知
い。ユーザが情報バーを読んで位置情報の通知に同意するには時間がかかるかもしれないし、GPS 専用ハー
ドウェアを装備した機器が GPS 衛星と接続を確立するには、さらに時間がかかるかもしれない。)coords
オブジェクトは latitude や longitude などのプロパティを持ち、ユーザの地球上の物理的な位置を示す。
position オブジェクトのプロパティは、表 6-2 のとおりだ。
表 6-2 position オブジェクトのプロパティ
プロパティ
型
説明
coords.latitude
double
十進数で緯度を示す
coords.longitude
double
十進数で経度を示す
coords.altitude
double または null
地球楕円体からの高度(メートル)
coords.accuracy
double
精度(メートル)
coords.altitudeAccuracy
double または null
高さの精度(メートル)
coords.heading
double または null
真北から時計回りに計測した進行方向(度)
coords.speed
double または null
速度(メートル / 秒)
timestamp
DOMTimeStamp
Date() オブジェクトと同様
こ れ ら の う ち、 存 在 が 保 証 さ れ て い る も の は 3 つ(coords.latitude、coords.longitude、 お よ び
coords.accuracy)だけだ。それ以外については、機器やバックエンドの測位サーバの能力によっては null
が返される場合がある。heading と speed の各プロパティは、可能な場合にはユーザの直前の位置に基づい
て計算される。
6.4 エラー処理
Geolocation は複雑なので、さまざまな部分で問題が起こる可能性がある。すでに「ユーザの承認」とい
う側面については説明した。Web アプリケーションがユーザの位置情報を要求し、ユーザが通知を拒んだ
場合にはどうなるだろう。ユーザの意思はいつでも優先される。しかし、それをコードにどう反映すべきだ
ろうか。実は getCurrentPosition() の 2 番目の引数はそのためにある。ここにエラー処理用のコールバッ
ク関数を指定するのだ。
navigator.geolocation.getCurrentPosition(
show_map, handle_error)
何か問題が起きたときには、エラーコールバック関数が PositionError オブジェクトとともに呼び出され
る。このオブジェクトは、表 6-3 に示すプロパティを持っている。
表 6-3 PositionError オブジェクトのプロパティ
プロパティ
型
説明
code
short
列挙型の値
message
DOMString
エンドユーザ向けではない
6.5 選択の自由
137
code プロパティは、以下のいずれかになる。
●
PERMISSION_DENIED(1)は、ユーザが「非通知」ボタンをクリックしたか、あるいはその他の方
法で位置情報へのアクセスを拒否したことを示す。
●
POSITION_UNAVAILABLE(2)は、ネットワークがダウンしているか、衛星と通信できなかったこと
を示す。
●
TIMEOUT(3)は、ネットワークは生きていてもユーザの位置の算出に時間がかかりすぎていること
を示す。どのくらい時間がかかれば「かかりすぎる」と判断するのかは、次のセクションで説明す
る。
使用例を以下に示す。
function handle_error(err) {
if (err.code == 1) {
// ユーザが拒否した!
}
}
マークアップ教授に質問
Q:Geolocation API は、国際宇宙ステーションや月、あるいは他の惑星上でも使えるのですか?
A:位置情報通知の仕様には、以下のように書かれている†。「このインタフェース中の属性で使用される
地理座標基準系は、世界測地系(World Geodetic System)(2d) [WGS84] である。その他の基準系
はサポートされない。」国際宇宙ステーションは地球を周回しているので、ステーション上の宇宙飛行士
(http://twitter.com/Astro_TJ)は自分の位置を緯度、経度、そして高度で表現することができる。しか
し、世界測地系は地球を基準としているので、月や他の惑星上での位置を記述するためには使うことができ
ない††。
6.5 選択の自由
iPhone や Android 携帯電話など、一部のモバイル機器は、あなたがいる位置を検出するのに 2 通りの方
法をサポートしている。ひとつは、携帯電話会社が運用する複数の基地局からの相対的な距離に基づいて、
三角測量によって位置を求める方法だ。この手法は高速で専用の GPS ハードウェアを必要としないが、大
まかな場所しかわからない。通信圏内にいくつ基地局が存在するかによって、「大まかな場所」は 1 街区ま
で絞り込める場合もあれば、1 キロ四方になってしまう場合もある。
†
http://www.w3.org/TR/geolocation-API/#coordinates_interface を参照。
††
監訳注:前述の注記にあるとおり、Geolocation API の返す座標系は WGS84 に基づく。このため、日本測地系(Tokyo)や
その他の測地系を利用するサービスと組み合わせる場合には、WGS84 測地系に合うよう座標を変換する必要がある。
138
6 章 Geolocation API による位置情報通知
もうひとつの方法は、モバイル機器上の専用 GPS ハードウェアを使って、地球を周回している GPS 測位
衛星と通信する方法だ。GPS を使えば、通常は数メートルの誤差で位置を特定できる。欠点は、モバイル
機器上の専用 GPS チップが大量の電力を消費することで、そのため携帯電話やその他の汎用モバイル機器
は、必要のないときはチップの電源をオフにしているのが普通だ。このため、起動時にはチップが初期化を
行い、軌道上の GPS 衛星と接続するまでの遅延が発生する。iPhone やその他のスマートフォンで Google
Maps を使うと、両方の手法が使われているのがわかる。最初に大まかな位置を示す大きな円が表示され
(最も近い基地局を発見)、その後より小さな円(複数の基地局からの三角測量)、そして正確な位置を示す
1 個の点(GPS 衛星からの情報)となる。
ここでこういう話をした理由は、Web アプリケーションによっては高い精度が必要ない場合もあるから
だ。例えば、近所で上映中の映画を知りたければ、「低精度」の位置情報でもおそらく十分だろう。繁華街
であっても近くにそれほど多くの映画館はないだろうし、そのうちいくつか表示できれば十分なことが多い
からだ。一方、リアルタイムでナビゲーションをしているような場合には、
「20 メートル先を右に曲がって」
などと指示するためにユーザの正確な位置を知る必要があるはずだ。
getCurrentPosition() 関数には、3 番目のオプション引数として PositionOptions オブジェクトが指定
できる。PositionOptions オブジェクトには 3 個のプロパティが設定できる(表 6-4 を参照)。すべてのプ
ロパティはオプションだ。どれを設定してもいいし、全く何も設定しなくてもよい。
表 6-4 PositionOptions オブジェクトのプロパティ
プロパティ
型
デフォルト値
備考
enableHighAccuracy
Boolean
false
true を指定すると低速になるかも
timeout
long
maximumAge
long
(デフォルト値なし)
0
ミリ秒単位で指定
ミリ秒単位で指定
enableHighAccuracy プロパティは、その名前どおりの働きをする。true を指定した場合、機器がサポー
トしていて、かつユーザが正確な位置情報の通知に同意すれば、その機器は正確な位置情報を提供しよう
とする。iPhone も Android 携帯電話も、低精度の測位と高精度の測位には別々の許可を必要とするので、
getCurrentPosition() の enableHighAccuracy:true での呼び出しは失敗するが enableHighAccuracy:false
での呼び出しは成功する、といったことが起こり得る。
timeout プロパティは、Web アプリケーションが測位のために待てる時間をミリ秒単位で指定する。こ
のタイマは、ユーザが位置の測定を許可した後で、カウントダウンを開始する。測定すべきはユーザの応答
時間ではなく、ネットワークの応答時間だからだ。
maximumAge プロパティは、キャッシュされた位置情報を即座に返すことを許す。例えば、getCurrentPo
sition() を初めて呼び出したとき、ユーザが同意し、取得された位置情報とともに成功時のコールバッ
ク関数が呼び出されたのが午前 10:00 だったとしよう。それからちょうど 1 分後、つまり午前 10:01 に、
maximumAge プロパティを 75000 に設定してもう一度 getCurrentPosition() を呼び出したとする。
navigator.geolocation.getCurrentPosition(
success_callback, error_callback, {maximumAge: 75000});
6.6 IE の場合
139
この意味は、必ずしもユーザの現在の位置は必要ではない、ということだ。75 秒(75000 ミリ秒)前に
いた場所がわかれば十分なのだ。この場合、モバイル機器はユーザが 60 秒(60000 ミリ秒)前にいた場所
を知っている。最初に getCurrentPosition() を呼び出した際に位置を取得済みだからだ。この時間は要求
を満たしているので、あえてユーザの現在位置の再測定は行わず、最初に返した値と全く同じ情報を返す。
つまり同一の緯度・経度と精度、そしてタイムスタンプ(午前 10:00)だ。
ユーザの位置を求めようとする前に、どれだけの精度が必要なのかを考慮して、それにしたがって
enableHighAccuracy を設定すべきだ。ユーザの位置を複数回求める必要があるのなら、どれだけ古い情報
でも役立つかを考慮して、それにしたがって maximumAge を設定すべきだ。また、ユーザの位置を継続的に
知る必要があるのなら、getCurrentPosition() は不適当だ。代わりに watchPosition() を使う必要がある。
watchPosition() 関数は、getCurrentPosition() と同じ構造をしている。引数には 2 個のコールバッ
ク関数(ひとつは成功時に呼ばれ、もうひとつはオプションでエラー時に呼ばれる)と、オプションの
PositionOptions オブジェクトを指定できる。PositionOptions オブジェクトは、今説明したとおりのプロ
パティを持つ。違いは、ユーザが位置を変えるごとにコールバック関数が呼び出されることだ。能動的に位
置をポーリングする必要はない。モバイル機器が最適なポーリング間隔を決めて、ユーザの位置が変わった
と判断した場合にコールバック関数を呼び出してくれるのだ。その情報を使って、地図上に表示したマーカ
を更新したり、次にどこで曲がるのかを指示したり、その他いろいろなことができる。使い方は、あなた次
第だ。
watchPosition() 関数自身は、数値を返す。この数字は、どこかに保存しておく必要があるだろう。ユー
ザの位置の変化の監視をやめたくなったときに、この数字を指定して clearWatch() メソッドを呼び出せば、
モバイル機器はコールバック関数を呼び出すことをやめてくれるからだ。JavaScript で setInterval() や
clearInterval() 関数を使ったことがあれば、それと同様の動作をすると考えればよい。
6.6 IE の場合
バージョン 9(さらに詳しく言えば 9.0 RC)より前の Internet Explorer は、今まで説明してきた W3C
の Geolocation API(「6.2 Geolocation API」を参照)をサポートしていない。しかし、あきらめることは
ない。Gears † という、Windows、Mac、Linux、Windows Mobile、そして Android プラットフォーム
上で動作する、Google のオープンソースのブラウザプラグインがあるからだ。Gears は古いブラウザに、
Geolocation API を含めた多くの機能を追加してくれる。W3C の Geolocation API と全く同じというわけ
ではないが、同じ目的を達成するためのものだ。
レガシーなプラットフォームという話題で言えば、携帯電話プラットフォーム上には数多くの機器固有
な Geolocation API が存在するという事実にも触れておかなくてはならない。BlackBerry、Nokia、Palm、
そして OMTP BONDI などはすべて、独自の geolocation API を提供している。もちろん、それらはすべ
て Gears とは違った動作をするし、W3C の Geolocation API とも違った動作をするのだ。なんてことだ!
†
http://tools.google.com/gears/ を参照。
140
6 章 Geolocation API による位置情報通知
6.7 geo.js に助けを求める
geo.js †は W3C の Geolocation API や Gears の API、そして各種のモバイルプラットフォームの提供す
る API の間の違いを吸収してくれる、MIT のもとライセンスされたオープンソースの JavaScript ライブラ
リだ。これを使うには、ページの最後に 2 個の <script> 要素を追加する必要がある。(理論的にはどこに
書いてもかまわないのだが、<head> にスクリプトを書くとページのロードが遅くなるので、そうはしない
ほうがよい。)
最初のスクリプトは、gears_init.js ††だ。これは Gears がインストールされている場合にそれを初期
化してくれる。次のスクリプトは geo.js ‡だ。これらを以下のように、ページ中に挿入する。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Dive Into HTML 5</title>
</head>
<body>
...
<script src="gears_init.js"></script>
<script src="geo.js"></script>
</body>
</html>
これで、どんな geolocation API がインストールされていようとも、それを使うことができるようになる。
if (geo_position_js.init()) {
geo_position_js.getCurrentPosition(geo_success, geo_error);
}
ひとつずつ説明して行こう。まず、明示的に init() 関数を呼ぶ必要がある。この init() 関数は、サポー
トされている geolocation API のどれかが利用できる場合に true を返す。
if (geo_position_js.init()) {
init() 関数を呼ぶだけでは、ユーザの位置情報は得られない。位置情報の取得が可能だということがわ
かるだけだ。実際にユーザの位置情報を得るには、getCurrentPosition() 関数を呼ぶ必要がある。
geo_position_js.getCurrentPosition(geo_success, geo_error);
getCurrentPosition() 関数はブラウザに、ユーザの位置情報を取得し通知する許可を得るための動作を
†
http://code.google.com/p/geo-location-javascript/ を参照。
††
http://code.google.com/apis/gears/gears_init.js を参照。
‡
http://geo-location-javascript.googlecode.com/svn/trunk/js/geo.js を参照。
6.8 総合的な実例
141
させる。位置情報が Gears によって提供される場合には、ユーザがその Web サイトを信頼して Gears を使
う許可を与えるか、と尋ねるダイアログがポップアップする。ブラウザがネイティブに Geolocation API を
サポートしている場合には、また違ったダイアログが表示される。例えば Firefox 3.5 では、その Web サイ
トに位置情報を通知してよいかとユーザに尋ねる情報バーがページの上部に表示される。
getCurrentPosition() 関数には、引数として 2 個のコールバック関数を指定する。getCurrentPositi
on() 関数が位置情報の取得に成功した場合、つまりユーザが許可を与えて Geolocation API が有効な答を
返してきた場合には、最初の引数として渡された関数をコールバックする。この例では、成功時のコール
バック関数は geo_success という名前だ。
geo_position_js.getCurrentPosition(geo_success, geo_error);
成功時のコールバック関数は 1 個の引数を取り、この引数に位置情報が含まれている。
function geo_success(p) {
alert("Found you at latitude " + p.coords.latitude +
", longitude " + p.coords.longitude);
}
getCurrentPosition() 関数が位置情報を取得できなかった場合、つまりユーザが許可を与えなかったか
Geolocation API が何らかの理由で失敗した場合には、2 番目の引数として渡された関数をコールバックす
る。この例では、失敗時のコールバック関数は geo_error という名前だ。
geo_position_js.getCurrentPosition(geo_success, geo_error);
失敗時のコールバック関数は引数を取らない。
function geo_error() {
alert("Could not find you!");
}
現在のところ geo.js は watchPosition() 関数をサポートしていない†。継続的に位置情報が必要となる
場合には、自分で getCurrentPosition() を能動的にポーリングする必要がある。
6.8 総合的な実例
geo.js を使って、ユーザの位置情報を取得し、近所の地図を表示するという実例を見て行こう。
まずページが読み込まれた際に geo_position_js.init() を呼び、geo.js がサポートしているインタ
フェースのどれかを使った位置情報通知機能が利用できるかどうかを判断する。利用できるようであれば、
ユーザが自分の位置情報を取得するためのリンクを表示する。このリンクをクリックすると、以下に示す
lookup_location() 関数が呼び出される。
†
監訳注:2010 年末時点の最新版では、watchPosition() 関数がサポートされている。
6 章 Geolocation API による位置情報通知
142
function lookup_location() {
geo_position_js.getCurrentPosition(show_map, show_map_error);
}
ユーザが自分の位置情報の把握を許可し、かつバックエンドのサービスが実際に位置情報を取得できた場
合には、geo.js は最初のコールバック関数 show_map() を 1 個の引数 loc とともに呼び出す。この loc オブ
ジェクトは coord プロパティを持ち、そこには緯度、経度、および精度情報が格納されている。(この実例
では精度情報は使用しない。)show_map() 関数の残りの部分は、Google Maps API を使って地図を埋め込
むためのものだ。
function show_map(loc) {
$("#geo-wrapper").css({'width':'320px','height':'350px'});
var map = new GMap2(document.getElementById("geo-wrapper"));
var center = new GLatLng(loc.coords.latitude, loc.coords.longitude);
map.setCenter(center, 14);
map.addControl(new GSmallMapControl());
map.addControl(new GMapTypeControl());
map.addOverlay(new GMarker(center, {draggable: false,
title: "You are here (more or less)"}));
}
geo.js が位置情報を取得できなかった場合には、2 番目のコールバック関数 show_map_error() を呼び出
すことになる。
function show_map_error() {
$("#live-geolocation").html('Unable to determine your location.');
}
6.9 参考文献
●
W3C Geolocation API
http://www.w3.org/TR/geolocation-API/
●
Gears
http://tools.google.com/gears/
●
BlackBerry の geolocation API
http://www.tonybunce.com/2008/05/08/Blackberry-Browser-Amp-GPS.aspx
●
Nokia の geolocation API
http://library.forum.nokia.com/index.jsp?topic=/Web_Developers_Library/GUID-4DDE31C7EC0D-4EEC-BC3A-A0B0351154F8.html
●
Palm の geolocation API
6.9 参考文献
143
http://developer.palm.com/index.php?option=com_content&view=ar ticle&id=1673#GPSgetCurrentPosition
●
OMTP BONDI の geolocation API
http://bondi.omtp.org/1.0/apis/geolocation.html
●
各種 geolocation API のラッパスクリプト、geo.js
http://code.google.com/p/geo-location-javascript/
●
Internet Explorer 9 Guide for Developers の「Geolocation」
http://msdn.microsoft.com/en-us/ie/ff468705.aspx#_HTML5_geolocation
145
7章
Web アプリケーションのローカル
ストレージ:その過去・現在・未来
7.1 はじめに
永続的なローカルストレージは、ネイティブなクライアントアプリケーションが Web アプリケーション
に対する優位を保ってきた分野のひとつだ。ネイティブアプリケーションでは、設定や実行時の状態など、
アプリケーションに特有のデータの保存や取り出しを行うため、オペレーティングシステムによって抽象化
されたレイヤが提供されているのが普通だ。これらのデータはプラットフォームのやり方にしたがって、レ
ジストリ、INI ファイル、XML ファイル、あるいはその他の場所に保存される。ネイティブクライアント
アプリケーションに key/value ストア以上のローカルストレージが必要なら、独自のデータベースを埋め
込んだり、独自のファイルフォーマットを考案したり、その他数多くの解決法が実装可能だ。
歴史的に、Web アプリケーションにはこのような贅沢は許されていなかった。Web の初期に考案された
Cookie は、少量のデータであれば実際に永続的なローカルストレージとして使うことも可能だ。しかし、
Cookie にはローカルストレージとして利用するには欠点がある。
●
Cookie はすべての HTTP リクエストに含まれるので、必要のない同一のデータを何度も何度も送
信することになり、Web アプリケーションの速度を低下させる。
●
Cookie はすべての HTTP リクエストに含まれるので、データを暗号化せずにインターネット上で
送信することになる(Web アプリケーション全体が SSL 上で通信していない限りは)。
●
Cookie のデータには 4KB という制限がある。アプリケーションの速度を低下させるには十分(最
初の項を参照)だが、実用的な用途には不十分だ。
Web アプリケーションに必要なのは、
●
ページを更新しても消えず、
●
サーバに送信されることのない、
●
クライアント上に設けられた、
7 章 Web アプリケーションのローカルストレージ:その過去・現在・未来
146
●
大量のストレージ領域
なのだ。
これを実現しようという試みは数多くなされてきたが、さまざまな理由で最終的に満足できるものはな
かった。
7.2 HTML5 以前のローカルストレージハック
はじめに、Internet Explorer だけがあった。いや、少なくとも Microsoft は世界中の人にそう思ってほ
しかったらしい。そのため、大ブラウザ戦争の初期に Microsoft はすばらしい機能をたくさん考案し、それ
らを「大ブラウザ戦争を終結させるための最終兵器」つまり Internet Explorer に搭載したのだ。この中に
DHTML ビヘイビアと呼ばれる一連の機能があり、そのひとつに userData というものがあった。
userData を使えば、Web ページから XML ベースの階層構造の中へ、ドメインごとに 64KB のデータを
保存できる。(さらに、イントラネットのサイトなど信頼されたドメインであれば、その 10 倍のデータを
保存できた。640KB もあれば誰でも十分だよね!†)IE は許可を求めるダイアログを一切表示せず、また
利用できるストレージの大きさを増やす方法もなかった。
2002 年、Adobe は「Flash Cookie」という、不適当で誤解を招く名前の機能を Flash 6 に導入した。
Flash 環境内では、この機能はローカル共有オブジェクト(LSO)という適切な名前で呼ばれている。簡
単に言うと、これは Flash オブジェクトがドメインごとに 100KB までのデータを保存できるようにする
機 能 だ。2005 年、Brad Neuberg が AJAX Massive Storage System(AMASS) と い う 名 前 で Flash と
JavaScript を橋渡しする機能の初期のプロトタイプを開発したが、Flash の設計の癖のため機能は制限され
ていた。2006 年には、Flash 8 での ExternalInterface の登場によって、JavaScript からの LSO へのアク
セスははるかに容易かつ高速になっていた。Brad は AMASS を書き直し、有名な Dojo Toolkit に dojox.
storage という名前で統合した。このソリューションによって、ドメインごとに通常 100KB のストレージ
を「無料で」手に入れることができる。それを超えると、データストレージが一桁(1MB、10MB、…)
増えるごとにユーザにプロンプトが出力される。
そして 2007 年に、Google が Gears を発表した。これはブラウザに付加機能を提供するための、オープ
ンソースのプラグインだ。(以前、Internet Explorer に geolocation API を提供する話題(「6.6 IE の場合」
を参照)の中で Gears に言及した。)Gears は、SQLite ベースの組み込み SQL データベースへの API を提
供している。一度ユーザから許可を得た後は、Gears はドメインごとに無制限のデータを SQL データベー
ステーブルへ保存できる。
その間、Brad Neuberg とその仲間たちは dojox.storage をハックして、これらすべての異なるプラグイ
ンや API への統合インタフェースを提供する作業を続けていた。2009 年までに、dojox.storage は Adobe
Flash、Gears、Adobe AIR、そして Firefox の古いバージョンにのみ実装されていた HTML5 ストレージ
の初期プロトタイプを自動検出(およびその上で統合インタフェースを提供)できていた。
これらのソリューションを振り返ってみると、ひとつのパターンが浮かび上がる。すべて特定のブラウザ
に特有の機能か、またはサードパーティのプラグインに依存するのだ。違いを覆い隠そうとする(dojox.
storage での)英雄的な努力にもかかわらず、すべては根本的に異なるインタフェースと、異なるストレー
†
訳注:これはビル・ゲイツ氏が MS-DOS のメモリの大きさについて語ったとされる言葉だが、本人は否定している。
7.3 HTML5 ストレージ入門
147
ジ容量と、そして異なるユーザ体験を提供しているのだ。したがって、これが HTML5 によって解決され
るべき問題となる。サードパーティのプラグインに依存することなく、複数のブラウザでネイティブかつ統
一的に実装された、標準化された API を提供することだ。
7.3 HTML5 ストレージ入門
ここで「HTML5 ストレージ」と呼んでいるのは、実際には Web Storage という名前の仕様のことだ。
これはかつて HTML5 仕様自体の一部だったが、くだらない政治的理由によって別個の仕様に分割されて
しまった。「ローカルストレージ」や「DOM ストレージ」と呼んでいるブラウザメーカーもある。名前に
関する状況は、関連する同じような名前の新興の標準規格(後で紹介する)のせいで、さらに複雑になって
いる。
そもそも HTML5 ストレージとは何だろうか。簡単に言うと、Web ページがクライアント Web ブラウザ
の中から、キーと値のペアに名前を付けてローカルに保存するための方法だ。Cookie に保存されるデータ
と同様に、このデータはその Web サイトを離れたり、ブラウザタブを閉じたり、ブラウザを終了したり、
その他どんなことをした後でも保持される。しかし Cookie とは違って、このデータはリモートの Web サー
バへ送信されることはない(わざわざ手作業で送信しようとしない限りは)。そして、永続的なローカルス
トレージを提供しようという以前のすべての試み(前のセクションを参照)とは違い、Web ブラウザ内で
ネイティブに実装されているため、サードパーティのブラウザプラグインがなくても利用できるのだ。
どのブラウザで利用できるのかと言うと、表 7-1 を見てわかるように、ほとんどすべてのブラウザの最新
バージョンで HTML5 ストレージはサポートされている。なんと、Internet Explorer でさえ使えるのだ!
表 7-1 HTML5 ストレージのサポート状況
IE
Firefox
Safari
Chrome
Opera
iPhone
Android
8.0 ∼
3.5 ∼
4.0 ∼
4.0 ∼
10.5 ∼
2.0 ∼
2.0 ∼
JavaScript のコードからは、window オブジェクト上の localStorage オブジェクトを介して HTML5 スト
レージへアクセスする。使う前に、ブラウザがサポートしているかどうかを検出する必要がある(「2.8 ロー
カルストレージ」を参照)。
function supports_html5_storage() {
try {
return ('localStorage' in window) && window['localStorage'] !== null;
} catch (e) {
return false;
}
}
あるいは、この関数を自分で書く代わりに Modernizr(「2.3 Modernizr:HTML5 検出ライブラリ」を
参照)を使って HTML5 ストレージのサポートを検出することもできる。
148
7 章 Web アプリケーションのローカルストレージ:その過去・現在・未来
if (Modernizr.localstorage) {
// window.localStorage が利用できる
} else {
// ローカルストレージのネイティブサポートはないようだ :(
// Gears やその他のサードパーティのソリューションを試してみよう
}
7.4 HTML5 ストレージの使用
HTML5 ストレージは、名前付きキーと値のペアを基本としている。データを名前付きキーに紐付けて
保存しておけば、後で同じキーを使ってそのデータを取り出すことができるのだ。名前付きキーは文字列
だ。データは、文字列、論理型、整数型、浮動小数点型など JavaScript でサポートされるどんな型でもよ
い。しかし、データは実際には文字列として保存される。文字列以外を保存して取り出そうとする場合に
は、parseInt() や parseFloat() などの関数を使って取り出したデータを元の JavaScript データ型へ型変換
する必要があるのだ。
interface Storage {
getter any getItem(in DOMString key);
setter creator void setItem(in DOMString key, in any data);
};
既存の名前付きキーに対して setItem() を呼ぶと、警告なしに前の値が上書きされる。存在しないキーに
対して getItem() を呼ぶと、例外は発生せず、null が返される。
他の JavaScript オブジェクトと同様に、localStorage オブジェクトは連想配列として取り扱うことが可
能だ。getItem() や setItem() メソッドを使う代わりに、角カッコを使うことができる。例えば、以下の
コード断片を見てみよう。
var foo = localStorage.getItem("bar");
// ...
localStorage.setItem("bar", foo);
これは、角カッコを使って以下のように書き直せる。
var foo = localStorage["bar"];
// ...
localStorage["bar"] = foo;
また、与えられた名前付きキーの値を削除するメソッドや、ストレージ領域全体をクリアする(つまり、
一度にすべてのキーと値を削除する)メソッドもある。
interface Storage {
deleter void removeItem(in DOMString key);
void clear();
};
7.4 HTML5 ストレージの使用
149
存在しないキーに対して removeItem() を呼ぶと、何も起こらない。
最後に、ストレージ領域中の値の総数を保持しているプロパティと、インデックスによってすべてのキー
について(キーの名前の取得を)繰り返すメソッドも存在する。
interface Storage {
readonly attribute unsigned long length;
getter DOMString key(in unsigned long index);
};
0 から (length-1) 以外のインデックスに対して key() を呼ぶと、null が返される。
7.4.1 HTML5 ストレージ領域の変化を検出する
ストレージ領域が変化したことをプログラムから検出したければ、storage イベントをトラップすればよ
い。storage イベントは、setItem()、removeItem()、または clear() が呼ばれ、かつ、実際に何かが変化
した場合に window オブジェクト上で発生する。例えば、既存の値と同じ値をセットしたり、名前付きキー
が存在しない状態で clear() を呼んだりしても、storage イベントは発生しない。ストレージ領域では、実
際には何も変化していないからだ。
localStorage がサポートされていれば、必ず storage イベントもサポートされている。これは、Internet
Explorer 8 についても当てはまる。しかし、IE 8 は W3C 標準の addEventListener をサポートしていない
(IE 9 ではついにサポートされる)。したがって、storage イベントをフックするには、どのイベントメカニ
ズムをブラウザがサポートしているのかをチェックする必要がある。(他のイベントについて同様の経験が
ある読者は、このセクションを飛ばしてしまってかまわない。storage イベントのトラップは、他のイベン
トのトラップと同じ方法でできるからだ。読者が jQuery やその他の JavaScript ライブラリを使ってイベン
トハンドラを登録するのが好みなら、storage イベントでも同じことができる。)その方法を説明しよう。
if (window.addEventListener) {
window.addEventListener("storage", handle_storage, false);
} else {
window.attachEvent("onstorage", handle_storage);
};
Internet Explorer 以外では、handle_storage() コールバック関数は StorageEvent オブジェクトを伴っ
てコールバックされる。Internet Explorer の場合、イベントオブジェクトは window.event に保存されてい
る。
function handle_storage(e) {
if (!e) { e = window.event; }
}
150
7 章 Web アプリケーションのローカルストレージ:その過去・現在・未来
この時点で、変数 e には StorageEvent オブジェクトが代入されている。このオブジェクトは表 7-2 に示
すような役に立つプロパティを持っている。
表 7-2 StorageEvent オブジェクトのプロパティ
プロパティ
型
説明
key
String
追加、削除、あるいは変更された名前付きキー
oldValue
任意
上書きの場合は以前の値、新しいアイテムの追加の場合は null
newValue
任意
新しい値。削除の場合には null
urla
String
この変化を引き起こしたメソッドを呼び出したページ
a:url プロパティは、当初 uri と呼ばれていた。仕様変更の前に出荷されたブラウザは uri プロパティを持っている場合がある。
最大限の互換性を保つため、url プロパティの存在をチェックし、存在しない場合には uri プロパティをチェックするのがよい。
storage イベントはキャンセルできない。handle_storage() コールバック関数の中からは、変化が生じ
ることを阻止する方法はない。これは単に、ブラウザから「こういうことが起こったよ。あなたにできるこ
とは何もないけど、知らせておくね」と通知してもらうための方法なのだ。
7.4.2 現在のブラウザによる制限
サードパーティのプラグインを使ったローカルストレージハックの歴史を説明した際(「7.2 HTML5 以前
のローカルストレージハックの簡単な歴史」を参照)、ストレージ量の制限など、それぞれのテクニックの
制限事項について触れた。しかし、いまや標準となった HTML5 ストレージの制限については、まだ何も
説明していなかった。ではまず答えを先に言ってから、それぞれについて説明しようか。重要度の高い順か
ら答えを言うと「5MB」、「QUOTA_EXCEEDED_ERR」、そして「ノー」だ。
「5MB」とは、生成元ごとにストレージ領域が持てるデフォルトの容量だ。この値は、HTML5 ストレー
ジの仕様で単なる提案に過ぎないと記述されているにもかかわらず、ブラウザが違っても驚くほど一致して
いる。ただし、保存されるのは文字列であって、元のフォーマットのデータではない、ということは気に留
めておく必要がある。大量の整数や浮動小数点数を文字として保存する場合、表現形式の違いによって全体
の大きさは違ってくる。浮動小数点数は、浮動小数点数としての通常の表現形式ではなく、その各数字が文
字として保存されるからだ。
「QUOTA_EXCEEDED_ERR」とは、5MB のストレージの制限を超えた場合に発生する例外だ。そして「ノー」
とは、ここで当然出てくるであろう「ストレージ空間を増やすことはできるか?」という質問に対する答え
だ。本書の執筆時点(2011 年 2 月)で、ストレージ空間の拡大要求が行えるメカニズムを Web 開発者に提
供しているブラウザは存在しない。Opera など、一部のブラウザでは各サイトのストレージ制限をユーザ
が管理することを許しているが、その場合でも純粋にユーザ主導の操作であるため、Web 開発者が Web ア
プリケーションに組み込むことができる性質のものではない。
7.5 HTML5 ストレージの実例
HTML5 ストレージの実例を見て行こう。4 章で作成した、ハルマゲームを思い出してほしい(「4.9 総合
的な実例」を参照)。実はこのゲームには、小さな問題があった。ゲームの途中でブラウザウィンドウを閉
7.5 HTML5 ストレージの実例
151
じると、それまでの結果が失われてしまうのだ。しかし HTML5 ストレージを使えば、ゲームの途中経過
をローカルに、ブラウザ自身の中で記憶できる。http://diveintohtml5.info/examples/localstorage-halma.
html で、実際に確かめることができる。いくつかコマを動かし、ブラウザのタブを閉じ、そして再度開い
てみてほしい。ブラウザが HTML5 ストレージをサポートしていれば、このページは魔法のようにゲーム
の途中経過を記憶しているはずだ。動かした手数、ボード上のひとつひとつのコマの配置、そしてコマの選
択状態さえ再現されている。
これはどのように実現されているのだろうか。ゲーム内で変化が起こるたびに、この関数が呼ばれる。
function saveGameState() {
if (!supportsLocalStorage()) { return false; }
localStorage["halma.game.in.progress"] = gGameInProgress;
for (var i = 0; i < kNumPieces; i++) {
localStorage["halma.piece." + i + ".row"] = gPieces[i].row;
localStorage["halma.piece." + i + ".column"] = gPieces[i].column;
}
localStorage["halma.selectedpiece"] = gSelectedPieceIndex;
localStorage["halma.selectedpiecehasmoved"] = gSelectedPieceHasMoved;
localStorage["halma.movecount"] = gMoveCount;
return true;
}
見てわかるとおり、まず localStorage オブジェクトを使ってゲームが進行中であるかどうか(真偽値の
gGameInProgress)を保存している。次にすべてのコマについて(JavaScript の Array である gPieces)繰
り返し各コマの行番号と列番号を保存する。そして、その他のゲームの状態を保存する。これはコマの選
択状態(整数型の gSelectedPieceIndex)、コマが連続飛び越しの途中の可能性があるかどうか(真偽値の
gSelectedPieceHasMoved)、そして今までの総手数(整数型の gMoveCount)だ。
ページの読み込み時には、自動的に newGame() 関数を呼んでこれらの変数を固定値にリセットするので
はなく、resumeGame() 関数を呼び出す。この関数は、HTML5 ストレージを使ってゲームの途中経過がロー
カルに保存されているかどうかをチェックする。もし保存されていれば、その値を localStorage オブジェ
クトを使って読み込む。
function resumeGame() {
if (!supportsLocalStorage()) { return false;
gGameInProgress =
(localStorage["halma.game.in.progress"] ==
if (!gGameInProgress) { return false; }
gPieces = new Array(kNumPieces);
for (var i = 0; i < kNumPieces; i++) {
var row =
parseInt(localStorage["halma.piece." + i
var column =
parseInt(localStorage["halma.piece." + i
}
"true");
+ ".row"]);
+ ".column"]);
152
7 章 Web アプリケーションのローカルストレージ:その過去・現在・未来
gPieces[i] = new Cell(row, column);
}
gNumPieces = kNumPieces;
gSelectedPieceIndex =
parseInt(localStorage["halma.selectedpiece"]);
gSelectedPieceHasMoved =
localStorage["halma.selectedpiecehasmoved"] == "true";
gMoveCount = parseInt(localStorage["halma.movecount"]);
drawBoard();
return true;
}
この関数で最も気を付けなくてはならないのは、すでにこの章で先ほど説明したことだが、念のためもう
一度書いておく。データは文字列として保存される。文字列以外のものを保存する場合には、それを読み出
す際に型変換する必要がある。例えば、ゲームが進行中であるかどうかを示すフラグ(gGameInProgress)
は論理型だ。saveGameState() 関数の中では、単に保存するだけでデータ型については何も気にしていな
かった。
localStorage["halma.game.in.progress"] = gGameInProgress;
しかし resumeGame() 関数の中では、ローカルストレージ領域から読み出した値を文字列として扱い、自
分で正しい論理型の値に戻してやる必要があるのだ。
gGameInProgress =
(localStorage["halma.game.in.progress"] == "true");
同様に、総手数も gMoveCount に整数として保存されている。saveGameState() 関数の中では、単に保存
するだけでよかった。
localStorage["halma.movecount"] = gMoveCount;
しかし resumeGame() 関数の中では、JavaScript の組み込み関数 parseInt() を使って、読み出した値を整
数型に変換してやる必要がある。
gMoveCount = parseInt(localStorage["halma.movecount"]);
7.6 名前付きキーと値のペアを超えて:競合する構想
ハックや回避策だらけだった過去とは異なり(「7.2 HTML5 以前のローカルストレージハック」を参照)、
HTML5 ストレージの現状は驚くほど明るい。新たな API が標準化され、すべての主要なブラウザ、プラッ
トフォーム、機器に実装されているのだ。Web 開発者であれば、このような状況はなかなかあるものでは
ないということは知っているだろう。しかし、5MB の名前付き key/value ペアでは足りない場合もあるし、
永続的なローカルストレージの今後はどうなって行くのだろうか。実は、いくつもの構想が競合しあってい
7.6 名前付きキーと値のペアを超えて:競合する構想
153
るのだ。
ひとつの構想は、たぶんもう読者の皆さんもおなじみの SQL だ。2007 年、Google は Gears を立ち上げ
たが、このオープンソースのクロスブラウザのプラグインには SQLite ベースのデータベースが組み込まれ
ていた。この初期のプロトタイプが、後になって Web SQL Database の仕様作成に影響を与えることにな
る。Web SQL Database(以前は「WebDB」と呼ばれていた)は SQL データベースのラッパで、これを使
うと次のようなことが JavaScript からできるようになる。
openDatabase('documents', '1.0', 'Local document storage', 5*1024*1024,
function (db) {
db.changeVersion('', '1.0', function (t) {
t.executeSql('CREATE TABLE docids (id, name)');
}, error);
});
見てわかるように、操作の大部分は executeSql() メソッドへ渡す文字列の中に記述されている。この文
字列は、SELECT、UPDATE、INSERT、DELETE など、サポートされている SQL 文であれば何でもよい。バック
エンドのデータベースのプログラミングと全く同じようなことが、JavaScript からもできるというわけだ。
面白いじゃないか!
表 7-3 は、どのブラウザが Web SQL Database 仕様を実装しているかを示したものだ。
表 7-3 Web SQL Database のサポート状況
IE
Firefox
Safari
Chrome
Opera
iPhone
Android
×
×
4.0 ∼
4.0 ∼
10.5 ∼
3.0 ∼
2.0 ∼
もちろん、複数のデータベース製品を実際に使ったことのある人なら、「SQL」は厳密な標準というより
は、マーケティング用語に近いことを知っているはずだ。(「HTML5」についても同じことを言う人がいる
かもしれないが、気にしてはいけない。)確かに、SQL-92 という名前の SQL 仕様は実在する。しかし、世
界中を探しても、この仕様にそっくりそのまま準拠しているデータベースサーバなど存在しない。存在する
のは、Oracle の SQL、Microsoft の SQL、MySQL の SQL、PostgreSQL の SQL、そして SQLite の SQL
だ。そして、これらの製品はそれぞれ、長年にわたって新たな SQL 機能を追加してきたので、「SQLite の
SQL」だけでは何について話しているかを正確に示すことにはならない。「SQLite バージョン X.Y.Z ととも
に出荷されたバージョンの SQL」と言う必要があるのだ。
現在 Web SQL Database 仕様の最初に掲げられている以下の免責事項は、今まで述べたような状況を反
映している†。
この仕様は行き詰まっている。今まで関連するすべての実装者が同一の SQL バックエンド(Sqlite)
†
監訳注:2011 年 11 月に、Web SQL Database の策定は停止されたため、ここで引用された注釈には「この仕様は W3C 勧告
トラックにあったが、策定は停止された」という一文が書き加えられている。最終的に公開された仕様の W3C ノートという
文書には、本章で説明した Web Storage や、これから紹介する Indexed Database API が紹介されている。
7 章 Web アプリケーションのローカルストレージ:その過去・現在・未来
154
を使ってきたが、標準化を進めるに当たって複数の独立した実装が必要なのだ。この仕様を実装しよう
という新たな実装者が現れない限り、SQL の方言に関する記述は単に Sqlite を参照しているに過ぎな
い。これでは標準として受け入れられない。
このような背景から、もうひとつの競合する先進的で永続的な Web アプリケーション向けのローカルス
トレージ構想を紹介しておきたい。それは Indexed Database API で、以前は「WebSimpleDB」と呼ばれ、
現在では「IndexedDB」の愛称で知られている。
この Indexed Database API は、いわゆるオブジェクトストアを表現したものだ。オブジェクトストアに
は、SQL データベースと共通の概念が数多く存在する。「データベース」は「レコード」から構成され、レ
コードにはそれぞれ決まった数の「フィールド」がある。各フィールドは特定のデータ型を持ち、それは
データベース作成の際に定義される。レコードのサブセットを選択し、それを「カーソル」で数え上げるこ
とができる。オブジェクトストアへの変更は、「トランザクション」を単位として行われる。
SQL データベースのプログラミングの経験があれば、これらの用語はなじみ深いものだろう。主な違い
は、オブジェクトストアには構造化されたクエリ言語が存在しないことだ。例えば、"SELECT * from USERS
where ACTIVE = 'Y'" のような文を作成することはできない。その代わりに、オブジェクトストアから提供
されているメソッドを使って USERS という名前のデータベース上のカーソルをオープンし、レコードを数
え上げ、非アクティブユーザのレコードを除外し、そしてアクセサメソッドを使って残りのレコードの各
フィールドから値を取得するのだ。IndexedDB の初期のウォークスルー†は IndexedDB の動作に関する
よいチュートリアルで、IndexedDB と Web SQL Database を逐一比較できる。
本書の執筆時点で、IndexedDB は Firefox 4 のベータ版でのみ実装されている。(対照的に、Mozilla は
Web SQL Database を実装するつもりがないことを明言している。)Google は IndexedDB のサポートを考
慮中だと発言している†† し、Microsoft でさえ IndexedDB は「Web のすばらしいソリューションだ」と
言っている。
それでは Web 開発者として、IndexedDB について何かできることはあるだろうか。現時点では、全く
何もない。1 年後には、何らかの動きがあるかもしれない。「参考文献」のセクションには、初心者にもわ
かりやすいチュートリアルをいくつか掲載してある。
7.7 参考文献
HTML5 ストレージについて:
●
HTML5 ストレージ仕様
http://dev.w3.org/html5/webstorage/
●
MSDN の「DOM ストレージ入門」
http://msdn.microsoft.com/en-us/library/cc197062(VS.85).aspx
†
http://hacks.mozilla.org/2010/06/comparing-indexeddb-and-webdatabase/ を参照。
††
監訳注:Chrome はバージョン 8 より IndexedDB のサポートを開始している。
7.7 参考文献
●
155
Shwetank Dixit による「Web ストレージ:容易かつ強力なクライアントサイドのデータストレー
ジ」
http://dev.opera.com/articles/view/web-storage/
●
Mozilla Developer Center「DOM ストレージ入門」
https://developer.mozilla.org/en/dom/storage
注意:このページの大部分は、Firefox での localStorage の非標準な先駆者である globalStorage
オブジェクトの実装に割かれている。Mozilla は標準の localStorage インタフェースを Firefox
3.5 でサポートした。
●
IBM DeveloperWorks のチュートリアル、「HTML5 を使ってモバイル Web アプリケーションか
らローカルストレージを利用する」
http://www.ibm.com/developerworks/xml/library/x-html5mobile2/
Brad Neuberg らによる初期の開発(HTML5 以前):
●
「Internet Explorer は永続性をネイティブにサポートしているか?!」(IE の userData オブジェ
クトに関して)
http://codinginparadise.org/weblog/2005/08/ajax-internet-explorer-has-native.html
●
Dojo ストレージ(現在は機能していない Dojo Offline ライブラリに関する大規模なチュートリア
ルの一部)
http://docs.google.com/View?docid=dhkhksk4_8gdp9gr#dojo_storage
●
dojox.storage.manager の API レファレンス
http://api.dojotoolkit.org/jsdoc/HEAD/dojox.storage.manager
●
dojox.storage の Subversion リポジトリ
http://svn.dojotoolkit.org/src/dojox/trunk/storage/
Web SQL Database:
●
Web SQL Database 仕様
http://www.w3.org/TR/2010/NOTE-webdatabase-20101118/
●
Remy Sharp による、「Web SQL Database 入門」
http://html5doctor.com/introducing-web-sql-databases/
●
Web Database のデモ
http://html5demos.com/database
7 章 Web アプリケーションのローカルストレージ:その過去・現在・未来
156
●
Web SQL Database と Gears 上に構築された「非同期 JavaScript ORM」、persistence.js
http://zef.me/2774/persistence-js-an-asynchronous-javascript-orm-for-html5gears
IndexedDB:
●
Indexed Database API 仕様
http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html
●
Arun Ranganathan と Shawn Wilsher による、「HTML5 を超えて:データベース API と Indexed
DB への道」
http://hacks.mozilla.org/2010/06/beyond-html5-database-apis-and-the-road-to-indexeddb/
●
Arun Ranganathan による、「Firefox 4 の Indexed Database API を先取り紹介」(日本語訳)
https://dev.mozilla.jp/hacksmozillaorg/firefox-4-an-early-walk-through-of-indexeddb/
157
8章
オフライン状態での動作
8.1 はじめに
オフライン Web アプリケーションとは何だろうか。この言葉は一見、自己矛盾しているようにも思える。
Web ページはダウンロードして表示するものだ。ダウンロードするためにはネットワーク接続が必要だ。
オフライン時にどうやってダウンロードするというのだろうか。もちろん、それは不可能だ。しかし、オン
ラインになっている間にダウンロードを済ませておくことはできる。そしてこれが、HTML5 オフラインア
プリケーションの仕組みなのだ。
最も単純なオフライン Web アプリケーションは、HTML、CSS、あるいは JavaScript ファイル、画像、
もしくはその他の種類のリソースを指し示す URL のリストに過ぎない。オフライン Web アプリケーショ
ンのホームページは、マニフェストファイルと呼ばれるこのリストを参照している。これは、Web サーバ
のどこか別のところにある、単なるテキストファイルだ。HTML5 オフラインアプリケーションを実装して
いる Web ブラウザは、マニフェストファイルから URL のリストを読み込み、リソースをダウンロードし、
ローカルにキャッシュし、そして変更が生じるたびにローカルのコピーを自動的に最新の状態に保つ。ネッ
トワーク接続なしに Web アプリケーションへアクセスしようとしたとき、Web ブラウザは自動的にローカ
ルコピーを参照するように切り替わる。
これ以降の作業の大部分は、あなた、つまり Web 開発者の仕事だ。DOM には現在オンラインかオフラ
インかを示すフラグがあり、状態が変化した際に発生するイベントがある(オフラインからオンラインへ切
り替わった際、またはその逆)。しかし、それだけだ。アプリケーションがデータの作成や状態の保存を行
うのなら、オフラインの間にそのデータをローカルに保存し(7 章を参照)、オンラインへ戻った際にリモー
トサーバと同期させるのは、あなたの仕事だ。別の言い方をすれば、HTML5 は Web アプリケーションを
オフラインにはしてくれるが、その状態で何をするかはあなた次第なのだ。表 8-1 に、どのブラウザがオフ
ライン Web アプリケーションをサポートしているかを示す。
表 8-1 オフラインのサポート状況
IE
Firefox
Safari
Chrome
Opera
iPhone
Android
×
3.5 ∼
4.0 ∼
5.0 ∼
10.6 ∼
2.1 ∼
2.0 ∼
158
8 章 オフライン状態での動作
8.2 キャッシュマニフェスト
オフライン Web アプリケーションは、キャッシュマニフェストファイルを中心として動作する。すでに
述べたように、マニフェストファイルは、Web アプリケーションがネットワークから切断されている間に
アクセスする可能性のある、すべてのリソースのリストだ。これらのリソースをダウンロードしキャッシュ
するプロセスを開始させるには、<html> 要素の manifest 属性†を使ってマニフェストファイルを指定する
必要がある。
<!DOCTYPE HTML>
<html manifest="/cache.manifest">
<body>
...
</body>
</html>
キャッシュマニフェストファイルは Web サーバのどこに置いてもよいが、MIME タイプ text/cache-
manifest を使って送信されなくてはならない。Apache ベースの Web サーバを使っている場合には、おそ
らく Web ディレクトリのルートにある .htaccess ファイルに AddType ディレクティブを追加するだけでい
いはずだ。
AddType text/cache-manifest .manifest
そして、キャッシュマニフェストファイルの名前の最後が .manifest となっていることを確認する。別の
Web サーバを使っている場合や、Apache でも別の設定をしている場合には、Content-Type ヘッダを指定
する方法をサーバの文書で調べてほしい。
マークアップ教授に質問
Q:私の Web アプリケーションは、いくつかのページにまたがっています。manifest 属性は各ページに
書く必要がありますか。それとも、ホームページだけでいいのでしょうか?
A:Web アプリケーションのすべてのページに manifest 属性が必要だ。これらはすべて、アプリケーショ
ン全体のキャッシュマニフェストを指し示している必要がある。
オーケー、すべての HTML ページがキャッシュマニフェストファイルを参照し、キャッシュマニフェス
トファイルは適切な Content-Type ヘッダを使って送信されるようになった。しかし、マニフェストファイ
†
監訳注:2011 年 2 月に仕様が改訂され、現在は .manifest ではなく .appcache という拡張子が推奨されるようになった。し
かし、下記の AddType ディレクティブ指定で MIME タイプが正しければ、拡張子は .manifest や .appcache はおろか、ど
のようなものでも構わない。
8.2 キャッシュマニフェスト
159
ルの中身はどうすればいいのだろうか。この辺から話は面白くなってくる。
すべてのキャッシュマニフェストファイルの最初の行は、こうなっている。
CACHE MANIFEST
それ以降のマニフェストファイルは、3 つの部分に分けられる。「明示リスト」セクション、
「FALLBACK
(代替)」セクション、そして「NETWORK(オンライン指定リスト)」セクションだ。各セクションには、
それ専用のヘッダがある。マニフェストファイル中にセクションヘッダがない場合には、すべてのリスト中
のリソースは暗黙に「明示リスト」セクションにあるものとみなされる。読者の頭が爆発するといけないか
ら、用語の解説はこのくらいにしておこう。
以下は、有効なマニフェストファイルだ。このリストには、CSS ファイル、JavaScript ファイル、そして
JPEG 画像という、3 つのリソースが記載されている。
CACHE MANIFEST
/clock.css
/clock.js
/clock-face.jpg
このキャッシュマニフェストファイルにはセクションヘッダがないので、リスト中のすべてのリソースは
デフォルトの「明示リスト」セクションにある。「明示リスト」セクション中のリソースはダウンロードさ
れてローカルにキャッシュされ、ネットワークから切断されている間はいつでもオンラインのファイルの代
わりに使われる。したがって、ブラウザはこのキャッシュマニフェストファイルをロードした後、Web サー
バのルートディレクトリから clock.css、clock.js、そして clock-face.jpg という 3 個のファイルをダウ
ンロードする。その後ネットワークケーブルを抜いてページを更新しても、これらすべてのリソースはオフ
ラインで利用できるわけだ。
マークアップ教授に質問
Q:HTML ページをキャッシュマニフェストのリストに記載する必要はありますか?
A:答はイエスでもあり、ノーでもある。Web アプリケーション全体が単一のページに収まっているの
なら、そのページが manifest 属性を使ってキャッシュマニフェストを参照するようにするだけでよい。
manifest 属性を持つ HTML ページに行き当たると、そのページ自体も Web アプリケーションの一部であ
るとみなされるので、マニフェストファイルのリストにそれ自身を記載する必要はない。しかし、Web ア
プリケーションが複数のページにまたがっている場合には、すべての HTML ページをマニフェストファイ
ルのリストに記載する必要がある。そうしないと、ブラウザはダウンロードしてキャッシュする必要のある
HTML ページが他にも存在することがわからないからだ。
160
8 章 オフライン状態での動作
8.2.1 NETWORK セクション
次に、少し複雑な例をお目にかけよう。<img src> 属性から動的にロードされる tracking.cgi スクリプ
トを使って、時計アプリケーションからビジターを追跡しようとしているとしよう。このリソースをキャッ
シュしてしまうと追跡の目的が達成できないので、このリソースはキャッシュしてはいけないし、オフライ
ンで利用できてもいけない。これを指定するには、以下のようにする。
CACHE MANIFEST
NETWORK:
/tracking.cgi
CACHE:
/clock.css
/clock.js
/clock-face.jpg
このキャッシュマニフェストには、セクションヘッダがある。NETWORK: の行が「オンライン指定リスト」
セクションの始まりを示している。このセクションのリソースは、キャッシュされることはなく、オフライ
ンで利用可能になることもない。(オフライン中にこのようなリソースをロードしようとすると、エラーと
なる。)CACHE: の行は「明示リスト」セクションの始まりを示している。キャッシュマニフェストファイル
の残りの部分は、前の例と同じだ。リスト中の 3 個のリソースはキャッシュされ、オフラインで利用可能
となる。
8.2.2 FALLBACK セクション
キャッシュマニフェストファイルには、もう 1 種類のセクションがある。それが FALLBACK セクション
だ。FALLBACK セクションでは、オンラインリソースが何らかの理由でキャッシュできない場合、あるい
はキャッシュに失敗した場合の代替リソースを指定できる。HTML5 の仕様では、FALLBACK セクション
を賢く使った以下のような実例を挙げている。
CACHE MANIFEST
FALLBACK:
/ /offline.html
NETWORK:
*
これは、どんな動作をするのだろうか。まず、Wikipedia のように何百万ものページを含むサイトを考え
てみよう。サイト全体をダウンロードすることは不可能だし、そうしたいとも思わないはずだ。しかし、そ
の一部分をオフラインで使いたいとしよう。その場合、どのページをキャッシュするか、どうやって決めれ
ばよいだろうか。例えば、こんなやり方はどうだろう。この仮定上のオフライン機能付き Wikipedia では、
あなたが閲覧したページをダウンロードしてキャッシュする。これには、それまでに訪れたすべての項目の
本文、ノート(特定の項目に関して会話するためのページ)、そして編集(特定の項目へ実際に変更を加え
るためのページ)が含まれる。
8.2 キャッシュマニフェスト
161
これが、上記のキャッシュマニフェストの動作だ。Wikipedia 上のすべての HTML ページ(本文、ノー
ト、編集、履歴)が、このキャッシュマニフェストファイルを参照しているとしよう。キャッシュマニフェ
ストを参照しているページを訪れた際、ブラウザは「このページはオフライン Web アプリケーションの一
部らしいぞ、今まで見たことがあったかな」と考える。ブラウザがまだこのキャッシュマニフェストファイ
ルをダウンロードしていなければ、オフラインの「AppCache」
(「アプリケーションキャッシュ(Application
Cache)」の略)を新規に作成し、キャッシュマニフェストのリストに記載されているすべてのリソースを
ダウンロードし、そして現在のページを AppCache へ追加する。ブラウザが今までこのキャッシュマニフェ
ストを見たことがある場合には、単に現在のページを既存の AppCache へ追加する。いずれにしろ、今訪
れたページは AppCache に入ることになる。この点は重要だ。つまり、ページを訪れるたびにそのページ
を追加して行くオフライン Web アプリケーションが作れるからだ。キャッシュマニフェストに、HTML
ページをいちいち記載する必要はない。
ここで、もう一度 FALLBACK セクションを見てみよう。このキャッシュマニフェスト中の FALLBACK
セクションには、1 行しかない。この行の前半(スペースの前)は、URL ではない。実はこれは、URL の
パターンなのだ。1 文字「/」とだけ書くと、ホームページだけではなく、サイトのすべてのページにマッ
チする。オフラインの間にページを見ようとすると、ブラウザは AppCache にそのページを探しにいく。
そのページが AppCache に見つかれば(オンラインの間にそのページを見たことがあり、そのとき暗黙の
うちにそのページが AppCache へ追加されたため)、そのページのキャッシュされたコピーが表示される。
もし AppCache 中にそのページが見つからなければ、エラーメッセージを表示する代わりに、FALLBACK
セクションの行の後半に指定されている offline.html ページを表示する。
最後に、NETWORK セクションを見てみよう。このキャッシュマニフェスト中の NETWORK セクショ
ンも 1 行だけで、その行には「*」の 1 文字だけが書かれている。この文字は、NETWORK セクションで
は特別な意味を持つ。これは「オンライン指定リストのワイルドカードフラグ」と呼ばれ、インターネット
に接続している限り、AppCache にないページは元の Web アドレスからダウンロードしてよい、という意
味になる。これは「オープンエンド」のオフライン Web アプリケーションにとっては重要なことだ。この
例でいうと、オンラインでこの仮定上のオフライン機能付き Wikipedia 上でブラウズしている間は、ブラ
ウザは画像やビデオやその他埋め込まれたリソースを、たとえ別のドメインに存在するものであっても、変
わりなく取り込むことになる。(このような状況は、オフライン Web アプリケーションに限らず、大規模
な Web サイトでは非常によくあることだ。HTML ページはローカルで生成され送信されるが、画像やビデ
オは別ドメイン上の CDN から送られる。)このワイルドカードフラグがないと、この仮定上のオフライン
機能付き Wikipedia はオンライン時の挙動がおかしくなってしまう。具体的には、外部でホストされてい
る画像やビデオをロードしなくなるのだ。
この実例は、これで完成だろうか。答はノーだ。Wikipedia は HTML ファイルだけで構成されているの
ではなく、各ページに共通の CSS、JavaScript、それに画像が使われている。オフライン時にページが表示
されて適切な振る舞いをするためには、これらのリソースはすべて、マニフェストファイルの CACHE: セク
ションに明示的に記載する必要がある。しかし、FALLBACK セクションの重要性は、マニフェストファイ
ルに明示的に記載したリソースに限らず、それを超えて広がる「オープンエンド」のオフライン Web アプ
リケーションが実現できる、という点にあるのだ。
8 章 オフライン状態での動作
162
8.3 イベントの流れ
ここまで、オフライン Web アプリケーション、キャッシュマニフェスト、そしてオフラインアプリケー
ションキャッシュ(「AppCache」)について、曖昧で半ば魔術的な用語を使って説明してきた。いろいろな
ものがダウンロードされ、ブラウザが判断し、後はすべて「何となくうまく動いている」というわけだ。皆
さんがこの説明で満足するような読者でないことは、私もよく知っている。Web 開発の話をしているのだ。
「何となくうまく動いている」なんてことはあり得ない。
まず、イベントの流れ、特に DOM イベントについて説明しよう。キャッシュマニフェストを参照して
いるページをブラウザが訪れた際、以下に説明するような一連のイベントが window.applicationCache オ
ブジェクト上で発生する。複雑に思えるかもしれないが、これは私が知る限り、重要な情報をすべて含んだ
最も簡単な説明だ。以下、そのプロセスを説明する。
1.
<html> 要素に manifest 属性を検知すると、ブラウザは checking イベントを発生させる。(ここで
列挙するすべてのイベントは、window.applicationCache オブジェクト上で発生する。)checking
イベントは、このページを前に訪れたことがあろうと、あるいは同じキャッシュマニフェストを指
し示す別のページを訪れたことがあろうと、常に発生する。
2.
ブラウザがこのキャッシュマニフェストを初めて見る場合は、以下を実行する。
●
downloading イベントを発生させ、続いてキャッシュマニフェストのリストに記載されている
リソースのダウンロードを開始する。
●
ダウンロード中、ブラウザは定期的に progress イベントを発生させる。このイベントには、
今までにダウンロードしたファイルの数と、ダウンロードを待っているファイルの数が含まれ
ている。
●
キャッシュマニフェストのリストに記載されているすべてのリソースのダウンロードが成功し
たら、ブラウザは最後に cached イベントを発生させる。これは、オフライン Web アプリケー
ションが完全にキャッシュされ、オフラインで使う準備ができたことを示す。これで終わり
だ。お疲れさま。
3.
一方、このページを前に訪れたことがあるか、同じキャッシュマニフェストを指し示している別の
ページを訪れたことがある場合には、ブラウザはすでにこのキャッシュマニフェストを知ってい
て、AppCache には一部のリソースが入っている可能性がある。それどころか、すでに AppCache
には完全に動作するオフライン Web アプリケーションが出来上がっている可能性もある。した
がってここでは、最後にブラウザがチェックしたときからキャッシュマニフェストが変化している
かどうか、ということが問題だ。
●
もしその答がノー、つまりキャッシュマニフェストが変化していない場合には、ブラウザは即
座に noupdate イベントを発生させる。これで終わりだ。お疲れさま。
●
もしその答がイエス、つまりキャッシュマニフェストが変化していた場合には、ブラウザは
8.4 デバッグの手法
163
downloading イベントを発生させ、キャッシュマニフェストのリストに記載されているすべて
のリソースを再度ダウンロードし始める。
ダウンロード中、ブラウザは定期的に progress イベントを発生させる。このイベントには、今ま
でにダウンロードしたファイルの数と、ダウンロードを待っているファイルの数が含まれている。
キャッシュマニフェストのリストに記載されているすべてのリソースのダウンロードが成功した
ら、ブラウザは最後に updateready イベントを発生させる。これは、オフライン Web アプリケー
ションの新しいバージョンが完全にキャッシュされ、オフラインで使う準備ができたことを示す。
この新しいバージョンは、まだ使われてはいない。ユーザにページを再ロードさせることなく新し
いバージョンへ「ホットスワップ」するには、手動で window.applicationCache.swapCache() 関
数を呼べばよい。
上記のプロセスのどこかで致命的なエラーが生じた場合には、ブラウザは error イベントを発生させ、停
止する。以下に示すのは、エラーを発生させる状況のほんの一例だ。
●
キャッシュマニフェストが HTTP 404(Not Found)または 410(Gone)エラーを返した場合。
●
キャッシュマニフェストが見つかり、変更されてもいないが、それを参照している HTML ページ
が正しくダウンロードできなかった場合。
●
キャッシュマニフェストがアップデートの実行中に変更された場合。
●
キャッシュマニフェストが見つかり、変更されていたが、そのキャッシュマニフェストのリストに
記載されているリソースのどれかがダウンロードできなかった場合。
8.4 デバッグの手法
ここでは、2 個の重要なポイントを指摘しておきたい。ひとつはついさっき説明したことだが、たぶんま
だ本当には理解してもらえていないだろうから、ここでもう一度言っておく。たとえ 1 個でも、キャッシュ
マニフェストファイルのリストに記載されたリソースがダウンロードに失敗すれば、オフライン Web アプ
リケーションをキャッシュするというプロセス全体が失敗してしまう。ブラウザは error イベントを発生さ
せるが、どこに本当の問題があるのかを突き止める手がかりにはならない。このため、オフライン Web ア
プリケーションのデバッグ作業は、きわめていらだたしいものになる。
もうひとつの重要なポイントは、技術的にはエラーではないが、何が起こっているか理解するまではブラ
ウザに深刻なバグがあるように見える場合がある、ということだ。これは、キャッシュマニフェストファイ
ルが変更されたかどうかをブラウザがチェックする方法と関係している。これから 3 段階のプロセスを説
明する。面倒だとは思うが重要なので、注意して読んでほしい。
1.
通常の HTTP の手続きにしたがって、ブラウザはキャッシュマニフェストが期限切れになってい
るかどうかをチェックする。HTTP を使って送られてくる他のファイルと全く同じように、Web
サーバはたいてい HTTP 応答ヘッダにそのファイルについてのメタ情報を入れて送ってくる。こ
8 章 オフライン状態での動作
164
れらの HTTP ヘッダの一部(Expires および Cache-Control)が、そのファイルをキャッシュでき
るかどうかをブラウザに教えてくれ、変更されたかどうかをサーバへ問い合わせる必要をなくして
くれる。こういった手続きは、オフライン Web アプリケーションとは関係なく、ほとんどすべて
の HTML ページ、スタイルシート、スクリプト、画像、あるいはその他の Web 上のリソースに
ついて行われる。
2.
キャッシュマニフェストが(HTTP ヘッダによれば)期限切れになっている場合、ブラウザはサー
バに新しいバージョンがあるかどうかを問い合わせ、あった場合にはそれをダウンロードする。こ
れを行うため、ブラウザはキャッシュマニフェストファイルの最終更新日時を含む HTTP 要求を
発行する。この最終更新日時は、最後にそのファイルをダウンロードしたときに Web サーバから
HTTP 応答ヘッダに入れて送られてきたものだ。Web サーバがマニフェストファイルはその時刻
から変更されていないと判断すると、単純に 304(Not Modified)ステータスコードを返してくる。
これもまたオフライン Web アプリケーションとは関係なく、実質的に Web 上のすべてのリソー
スについて行われることだ。
3.
Web サーバがマニフェストファイルはその時刻以降変更されたと判断した場合、HTTP 200(OK)
ステータスコードを返し、続いて新しい最終更新日時の付いた新しい Cache-Control ヘッダととも
に新しいファイルの内容を送ってくる。これによって、上記のステップ 1 および 2 が次回も正し
く動作することが保証される。(HTTP はうまくできていて、Web サーバは常に将来のことを考え
て動作している。Web サーバがファイルを送る必要があるときには、理由もなしに 2 度送らなく
てもいいように、いろいろなことをしているのだ。)新しいキャッシュマニフェストファイルがダ
ウンロードされると、ブラウザはその内容を最後にダウンロードしたものと比較する。キャッシュ
マニフェストファイルの内容が同じなら、ブラウザはマニフェストのリストに記載されているリ
ソースの再ダウンロードは一切しない。
オフライン Web アプリケーションの開発やテストの際には、これらのステップのどれもが問題を引き起
こす可能性がある。例えば、あるバージョンのキャッシュマニフェストファイルを配置した後で、10 分後
にもうひとつリソースを追加する必要があることに気付いたとしよう。問題ない、一行追加して再配置す
ればいい、と思う人は手を上げて。ブブー。何が起こるか説明しよう。ページをリロードすると、ブラウ
ザは manifest 属性があることに気付き、checking イベントを発生させ、そして…、何もしない。ブラウザ
は、頑固にキャッシュマニフェストファイルは変更されていない、と言い張るのだ。なぜだろうか。それ
は、Web サーバがブラウザに、静的なファイルは数時間キャッシュしておけと指示する(HTTP によって、
Cache-Control ヘッダを使って)ようにデフォルトで構成されているからだ。つまり、ブラウザは上記の 3
段階のプロセスのステップ 1 から先に進まないことになる。確かに Web サーバはファイルが変更されたこ
とを知っているが、ブラウザはわざわざ Web サーバへ問い合わせようとはしない。どうしてかというと、
最後にブラウザがキャッシュマニフェストファイルをダウンロードしたとき、そのリソースを数時間キャッ
シュしておくようにと Web サーバから指示されている(HTTP によって、Cache-Control ヘッダを使って)
からだ。そして、10 分後の今、ブラウザは正確にそのとおりの動作をしているというわけだ。
念のために言っておくと、これは仕様であって、バグではない。すべては想定どおりに働いているの
8.4 デバッグの手法
165
だ。Web サーバがブラウザ(と、中間にあるプロキシ)にキャッシュするよう指示できなかったとしたら、
Web 全体が一夜のうちに崩壊してしまうだろう。しかしそのことも、なぜブラウザがキャッシュマニフェ
ストの更新に気付かないのか悩んで過ごした数時間を埋め合わせてはくれないだろう。(そして皮肉なこと
に、十分長い時間だけ悩んだ後になって、不可解なことにまたちゃんと動き始めるのだ。HTTP キャッシュ
が期限切れになったからだ。全く想定どおりの動作だ。ああ、なんて私は馬鹿なんだ!)
したがって、絶対にやっておくべきことがひとつある。Web サーバの設定を変更して、キャッシュマ
ニフェストファイルが HTTP によってキャッシュされないようにしておくことだ。Apache ベースの Web
サーバを使っているのなら、.htaccess ファイルに次の 2 行を追加すればいいはずだ。
ExpiresActive On
ExpiresDefault "access"
これによって、そのディレクトリとすべてのサブディレクトリに存在する、すべてのファイルのキャッ
シュが禁止される。実運用では、たぶんそれは望ましい動作ではないので、<Files> ディレクティブを使っ
てキャッシュマニフェストファイルにだけ適用されるようにするか、この .htaccess ファイルとキャッシュ
マニフェストファイルだけを含むサブディレクトリを作成するのがよいだろう。他の場合と同じように、設
定方法は Web サーバによって異なるので、HTTP キャッシングヘッダを操作する方法についてサーバの文
書を調べてほしい。
キャッシュマニフェストファイル自身について HTTP のキャッシュを禁止しても、問題はすべて解決し
たわけではない。AppCache 内のリソースのどれかが変更されているのに、Web サーバ上の URL は変化し
ていない場合があるからだ。このとき、3 段階のプロセスのうち、ステップ 2 が問題となる。キャッシュマ
ニフェストファイルが変更されていなければ、キャッシュされたリソースの変化にブラウザは気付かないか
らだ。以下の例を考えてみてほしい。
CACHE MANIFEST
# rev 42
clock.js
clock.css
clock.css を変更して再配置しても、変更は反映されない。キャッシュマニフェストファイル自身が変
更されていないからだ。オフライン Web アプリケーションのリソースのどれかを変更したら、必ずキャッ
シュマニフェストファイル自身も変更しなくてはならない。これは、単に 1 文字変更するだけでもよい。
筆者の経験から言えば、マニフェストファイルにリビジョン番号をコメント行として入れておくのが一番簡
単な方法だ。リソースのどれかを変更したら、コメントのリビジョン番号も変更しておくのだ。Web サー
バは新しく変更されたキャッシュマニフェストファイルを返すので、ブラウザはファイルの内容が変更され
たことを知り、マニフェストに記載されたすべてのリソースを再ダウンロードし始めるのだ。
CACHE MANIFEST
# rev 43
clock.js
clock.css
166
8 章 オフライン状態での動作
8.5 実際に作ってみる
4 章で作成(「4.9 総合的な実例」を参照)し、その後永続的ローカルストレージで状態を保存する改良を
施した(「7.5 HTML5 ストレージの実例」を参照)ハルマゲームを覚えているだろうか。このゲームをオフ
ラインで動かせるようにしてみよう。
そのためには、ゲームに必要なすべてのリソースを記載したマニフェストが必要だ。ええと、必要なのは
メインの HTML ページと、すべてのゲームのコードを含む 1 個の JavaScript ファイル、…それだけだ。す
べての描画は Canvas API(4 章を参照)を介してプログラムから行っているので画像はいらないし、必要
なすべての CSS スタイルは HTML ページの最初に <style> 要素として記述してある。したがって、キャッ
シュマニフェストはこうなる。
CACHE MANIFEST
halma.html
../halma-localstorage.js
パスについて一言。examples/ ディレクトリの中に offline/ サブディレクトリを作成し、キャッシュマ
ニフェストファイルはこのサブディレクトリの中に置いた。HTML ページには、オフラインで動作させる
ために少々追加が必要なので(詳しくは、この後すぐに説明する)、元の HTML ファイルのコピーを作成
し、これも offline/ サブディレクトリに置くことにした。しかしローカルストレージのサポートを追加し
た(「7.5 HTML5 ストレージの実例」を参照)後の JavaScript コードはそのまま使うので、親ディレクト
リ(examples/)にある同じ .js ファイルを、文字通り再利用している。すべてのファイルを示すと、次の
ようになる。
/examples/localstorage-halma.html
/examples/halma-localstorage.js
/examples/offline/halma.manifest
/examples/offline/halma.html
キャッシュマニフェストファイル(/examples/offline/halma.manifest)からは、2 つのファイルを参照
する。ひとつはオフライン版の HTML ファイル(/examples/offline/halma.html)で、これはマニフェス
トファイルにパスプレフィックスなしで記載されている。2 つのファイルは同じディレクトリにあるからだ。
もうひとつは JavaScript ファイルだが、これは親ディレクトリ(/examples/halma-localstorage.js)にあ
るので、相対 URL 記法を用いて ../halma-localstorage.js と記載してある。これは、<img src> 属性での
相対 URL の使い方と同じだ。絶対パス(現在のドメインのルートから始まる)を使うこともできるし、絶
対 URL(別ドメインのリソースを参照する)を使うこともできる。
さて、HTML ファイルには、キャッシュマニフェストファイルを参照する manifest 属性を追加する必要
がある。
<!DOCTYPE html>
<html lang="en" manifest="halma.manifest">
8.6 参考文献
167
これで完成だ。オフライン機能を持つブラウザがオフライン版の HTML ページをロードすると、リンク
されたキャッシュマニフェストをダウンロードし、すべての参照されたリソースのダウンロードとオフライ
ンアプリケーションキャッシュへの保存を開始する。その後このページを再度開くと、オフラインアプリ
ケーションのアルゴリズムが起動する。ゲームをオフラインでプレイすることができ、また状態をローカル
に保存しているので、何度でもゲームの中断と再開を繰り返すことができる。
8.6 参考文献
標準:
●
HTML5 仕様の中の、オフライン Web アプリケーション
http://whatwg.org/html5#offline
ブラウザメーカーの文書:
●
Mozilla Developer Center の「Firefox のオフラインリソース」
https://developer.mozilla.org/En/Offline_resources_in_Firefox
●
「HTML5 オフラインアプリケーションキャッシュ
http://developer.apple.com/safari/librar y/documentation/iPhone/Conceptual/
SafariJSDatabaseGuide/OfflineApplicationCache/OfflineApplicationCache.html
これは「Safari のクライアントサイドストレージとオフラインアプリケーションプログラミングガ
イ ド 」(http://developer.apple.com/safari/library/documentation/iPhone/Conceptual/SafariJS
DatabaseGuide/Introduction/Introduction.html)の一部だ。
チュートリアルとデモ:
●
Andrew Grieve による「Gmail for Mobile HTML5 シリーズ:AppCache を使ってオフラインアプ
リケーションを起動する(第 1 部)」
http://googlecode.blogspot.com/2009/04/gmail-for-mobile-html5-series-using.html
●
Andrew Grieve による「Gmail for Mobile HTML5 シリーズ:AppCache を使ってオフラインアプ
リケーションを起動する(第 2 部)」
http://googlecode.blogspot.com/2009/05/gmail-for-mobile-html5-series-part-2.html
●
Andrew Grieve による「Gmail for Mobile HTML5 シリーズ:AppCache を使ってオフラインアプ
リケーションを起動する(第 3 部)」
http://googlecode.blogspot.com/2009/05/gmail-for-mobile-html5-series-part-3.html
●
Jonathan Stark による「HTML5 オフラインアプリケーションキャッシュのデバッグ」
http://jonathanstark.com/blog/2009/09/27/debugging-html-5-offline-application-cache/
8 章 オフライン状態での動作
168
●
Paul Rouget による「HTML5 オフライン画像エディタおよびアップローダアプリケーション」
http://hacks.mozilla.org/2010/02/an-html5-offline-image-editor-and-uploader-application/
169
9章
Web フォーム
9.1 はじめに
読者の皆さんは Web フォームについてよく知っていると思う。<form> を作成し、数個の <input type=”
text”> と、必要なら <input type=”password”> も追加し、最後に input type=”submit”> ボタンを付けて完
成する、あれのことだ。
でもそれだけでは、半分しか知っていることにならない。HTML5 では、フォーム中に使える入力形式が
多数定義されているからだ。しかも、ここで私が「使える」と言ったのは、何の仕掛けもハックも回避策も
必要とせず、今すぐに使えるという意味だ。ただ、あまり期待しすぎないでほしい。これらの新たな機能が
実際にすべてのブラウザでサポートされている、という意味でもないからだ。もちろん新しいブラウザで
は、いろいろな種類のフォームが使えるし、その能力を十分に発揮できる。レガシーなブラウザでも使える
が、その能力を十分には発揮できない。つまりすべてのブラウザで(IE6 でさえ)、これらの機能はブラウ
ザに応じた能力を発揮できるというわけなのだ。
9.2 プレースホルダ
HTML5 で Web フォームに行われた最初の改良は、入力フィールドにプレースホルダを設定する機能だ。
プレースホルダは、入力フィールドが空白でフォーカスされていない場合、そのフィールドに表示される。
その入力フィールドをクリック(またはタブで移動)すると、プレースホルダは消えてしまう。
読者の皆さんは、きっともうプレースホルダを見たことがあるはずだ。例えば Mozilla Firefox では、図
9-1 に示すように「履歴とブックマークを検索」というプレースホルダがロケーションバーに表示される。
ロケーションバーをクリック(またはタブで移動)すると、プレースホルダは消える(図 9-2)。
図 9-1 Firefox のロケーションバー中のプレースホルダ
図 9-2 フォーカスがあるとプレースホルダは消える
170
9 章 Web フォーム
ブラウザごとのプレースホルダのサポート状況を表 9-1 に示す。
表 9-1 プレースホルダのサポート状況
IE
Firefox
Safari
Chrome
Opera
iPhone
Android
×
4.0 ∼
4.0 ∼
4.0 ∼
11.00 ∼
4.0 ∼
×
Web フォームにプレースホルダを表示させるには、以下のようにすればよい。
<form>
<input name="q" placeholder=" 履歴とブックマークを検索 ">
<input type="submit" value=" 検索 ">
</form>
placeholder 属性をサポートしていないブラウザは、単純にそれを無視する。無害で安全だ。
マークアップ教授に質問
Q:placeholder 属性に HTML マークアップを適用することはできますか?画像を入れたり、色を変えた
りしたいのです。
A:placeholder 属性は、テキストだけを設定でき、HTML マークアップは設定できない。しかし一部の
ブラウザでプレースホルダにスタイルを指定できる、ベンダ独自の CSS 拡張†も存在する。
9.3 フィールドへのオートフォーカス
JavaScript を使って、自動的にフォームの最初の入力フィールドにフォーカスを設定するサイトがある。
例えば Google.com のホームページでは検索入力ボックスに自動的にフォーカスが設定されるので、カー
ソルを検索入力ボックスに移動する手間なく検索キーワードが入力できるようになっている。大部分の人
にとってこれは便利な機能だが、パワーユーザや特別なニーズのある人々にとっては邪魔になる場合があ
る。例えばページをスクロールしようとしてスペースバーを押しても、フォーカスがすでにフォームの入力
フィールドにあるため、ページはスクロールせず、代わりにそのフィールドにスペースが入力されてしま
う。またページがまだロードされている途中で別の入力フィールドにフォーカスを移動した場合、サイトの
オートフォーカススクリプトが「親切にも」ロード完了時に元の入力フィールドにフォーカスを戻してしま
うかもしれず、そうすると作業の流れが中断されたり、間違った場所に入力をしてしまったりする破目にな
る。
オートフォーカスは JavaScript を使って行われるので、これらの特別な場合すべてに対応するのは難し
い。またページにフォーカスが「奪われる」ことを嫌う人々が取れる対策も限られている。
†
http://trac.webkit.org/export/37527/trunk/LayoutTests/fast/forms/placeholder-pseudo-style.html と https://developer.
mozilla.org/ja/CSS/:-moz-placeholder を参照。
9.3 フィールドへのオートフォーカス
171
この問題を解決するため、HTML5 はすべてのフォームコントロールに autofocus 属性を導入した。この
autofocus 属性は、ページのロードが完了した時点でフォーカスを特定の入力フィールドへ移動するという、
文字通りの働きをする。しかしこれはスクリプトではなく単なるマークアップなので、その振る舞いはすべ
ての Web サイトにわたって統一されることになる。また、ブラウザメーカー(あるいは拡張機能の作者)
が、オートフォーカスを無効にする手段をユーザに提供することも可能となるのだ。表 9-2 に、ブラウザご
とのオートフォーカスへの対応状況を示す。
表 9-2 オートフォーカスのサポート状況
IE
Firefox
Safari
Chrome
Opera
iPhone
Android
×
4.0 ∼
4.0 ∼
3.0 ∼
10.0 ∼
○
○
フォームにオートフォーカスを設定するには、以下のようにすればよい。
<form>
<input name="q" autofocus>
<input type="submit" value="Search">
</form>
autofocus 属性をサポートしていないブラウザは、単純にそれを無視する。
HTML5 ブラウザだけではなく、すべてのブラウザでフィールドへオートフォーカスさせたい時にはどう
するか、だって? 今あるオートフォーカススクリプトは、そのまま残しておけばよい。その上で、以下に
示す 2 点の変更を行う。
1.
2.
autofocus 属性を HTML マークアップへ加える。
ブラウザが autofocus 属性をサポートしているかどうかを検出(「2.14 フォームのオートフォーカ
ス」を参照)し、ブラウザがネイティブにオートフォーカスをサポートしていない場合にだけ、
オートフォーカススクリプトが実行されるようにする。
<form name="f">
<input id="q" autofocus>
<script>
if (!("autofocus" in document.createElement("input"))) {
document.getElementById("q").focus();
}
</script>
<input type="submit" value="Go">
</form>
...
http://diveintohtml5.info/examples/input-autofocus-with-fallback.html に は、 こ の 代 替 手 段 付 き auto
172
9 章 Web フォーム
focus の例が掲載してある。
9.3.1 できるだけ早くフォーカスを設定する
多くの Web ページは、window.onload イベントが発生するのを待って、フォーカスを設定している。し
かし window.onload イベントは、画像がロードされた後でないと発生しない。ページに画像がたくさんあ
る場合には、そのような(あまり考えずに作られた)スクリプトには、ユーザがページの別の部分で作業を
始めた後で、フィールドのフォーカスを再設定してしまう危険性がある。(これが、パワーユーザがオート
フォーカススクリプトを嫌う理由だ。)先ほどの実例は、参照するフォームフィールドの直後にオートフォー
カススクリプトを置いていた。これは最適なやり方だが、<body> 内に JavaScript を書くやり方が気に入ら
ない人もいるかもしれない。(もしくは、バックエンドシステムによってはそのような柔軟性を許していな
いかもしれない。)もしスクリプトをページの途中に挿入できない場合には、window.onload イベントの代
わりに、例えば jQuery の $(document).ready() のような、カスタムイベント中にフォーカスを設定するの
がよいだろう。
<head>
<script src=jquery.min.js></script>
<script>
$(document).ready(function() {
if (!("autofocus" in document.createElement("input"))) {
$("#q").focus();
}
});
</script>
</head>
<body>
<form name="f">
<input id="q" autofocus>
<input type="submit" value="Go">
</form>
jQuery は独自の ready イベントを DOM が構築された時、すなわちページ内の画像すべてがロードされ
た時ではなく、ページ内のテキストがロードされた直後に発火する。これは最適なやり方ではない。異常に
大きなページや遅いネットワークから接続している場合、この自動フォーカススクリプトが実行される前
にユーザがページを操作できてしまうからだ。しかし、window.onload イベントが発火するのを待つよりは
ずっと良いだろう。
<body> 内にスクリプトを書けるならば、最初に紹介したページ内にスクリプトを書くやり方よりは
<body> を汚さず、かつ今紹介したやり方よりもよい方法がある。jQuery のカスタムイベントを使って独
自のイベントを定義するのだ。ここでは、autofocus_ready といった名前のカスタムイベントを定義して、
オートフォーカスを指定したフィールドが現れた時点で発火するように設定している。このやり方を教えて
くれた E. M. Sternberg に感謝したい。
9.3 フィールドへのオートフォーカス
173
<head>
<script src=jquery.min.js></script>
<script>
$(document).bind('autofocus_ready', function() {
if (!("autofocus" in document.createElement("input"))) {
$("#q").focus();
}
});
</script>
</head>
<body>
<form name="f">
<input id="q" autofocus>
<script>$(document).trigger('autofocus_ready');</script>
<input type="submit" value="Go">
</form>
これは最初に紹介したものと同様に望ましい動作をしてくれる。ページがまだロード中であっても、技術
的に可能になった段階でフォームフィールドにフォーカスを設定してくれるからだ。それに加えて、このや
り方はフォームフィールドへのフォーカスというアプリケーションロジックの大部分を <body> 内ではなく
文書の <head> 内に移動してしまう。この例は jQuery に依存しているが、カスタムイベントという概念は
jQuery だけのものではない。YUI や Dojo など別の JavaScript ライブラリも同様の機能を備えている。
まとめよう。
●
フォーカスを適切に設定することが重要だ。
●
フォーカスを設定したい場合、まずはブラウザの autofocus 属性を使ってフォームフィールドに
フォーカスを設定しよう。
●
古いブラウザにフォールバックを与える場合、まずは autofocus 属性のサポートを検出し、その
フォールバックが古いブラウザのみで実行されるようにしよう。
●
フォーカスはできるだけ早く設定しよう。フォーカス用スクリプトはフォームフィールドのマーク
アップ直後に挿入しよう。<body> 内にスクリプトを書きたくない場合は、JavaScript のカスタム
イベントを利用し、そのイベントを trigger するマークアップをフォームフィールドのマークアッ
プ直後に記述しよう。もしスクリプトを <body> 内に書けない場合は、jQuery の $(document).
ready() イベントなどを利用しよう。
●
どんなことがあっても、window.onload を待ってフォーカスを設定するべきではない。
174
9 章 Web フォーム
9.4 メールアドレス
10 年以上にわたって、フォームには限られた種類のフィールドしかなかった。よく使われるものを表 9-3
に示す。
表 9-3 HTML 4 の入力形式
フィールド形式
HTML コード
備考
チェックボックス
<input type="checkbox">
オンとオフが選べる
ラジオボタン
<input type="radio">
グループの中からひとつを選択
パスワード
<input type="password">
入力した文字の代わりにドットを表示
ドロップダウンリスト
<select><option>...
ファイル選択
<input type="file">
送信ボタン
<input type="submit">
テキスト入力
<input type="text">
「ファイルを開く」ダイアログをポップアップ
type 属性は省略可能
これらの入力形式は、HTML5 でも使用できる。「HTML5 へアップグレード」(DOCTYPE の変更につ
いては、「3.2 DOCTYPE」を参照)する際にも、フォームのコードを 1 文字も変更する必要がないのだ。
すばらしい後方互換性だ!
しかし、HTML5 では新しいフィールド形式がいくつか定義されており、理由はこの後すぐ説明するが、
今すぐ使い始めることができる。
新しい入力形式のひとつが、メールアドレスだ。以下のように指定する。
<form>
<input type="email">
<input type="submit" value="Go">
</form>
ここで私は、「type="email" をサポートしていないブラウザでは…」という文章を書きかけてやめた。な
ぜかと言うと、それが何を意味するのかはっきりしないからだ。何も特別な挙動をしないとしても(特別な
挙動については、この後すぐ説明する)、type="email" を認識しないブラウザはそれを type="text" として
取り扱い、普通のテキストフィールドを表示する。
今言ったことの重要さは、いくら強調してもしすぎることはない。Web には電子メールアドレスを入
力するよう促すフォームが何百万と存在し、そのすべてが <input type="text"> を使っている。テキス
トボックスを表示し、そこに電子メールアドレスを入力してもらうためだ。そこへ HTML5 が登場し、
type="email" を定義した。ブラウザは何かおかしな挙動を示すだろうか。答はノーだ。地球上に存在する
すべてのブラウザは、たとえ IE6 であっても、不明な type 属性を type="text" として取り扱う。だから、
type="email" を使ってフォームを今すぐアップグレードできるのだ。
それでは type="email" をサポートするブラウザとは、どういう意味になるのだろうか。その答はさまざ
まだ。HTML5 の仕様では、新しい入力形式について何も特別なユーザインタフェースを要求していない。
HTML5 ブラウザでは、単にテキストボックスとして(type="text" と全く同じように)表示するだけなの
9.5 Web アドレス
175
図 9-3 電子メールアドレスの入力に適したキーボード
で、ユーザは全く違いに気付かないだろう(ページのソースを見ない限りは)。
それでは、iPhone の場合はどうだろうか。
iPhone は、物理的なキーボードを持たない。すべての入力は、必要に応じて(例えば Web ページの
フォームフィールドにフォーカスがある場合に)ポップアップするオンスクリーンキーボードをタップする
ことによって行われる。Apple は、非常に賢い機能を iPhone の Web ブラウザに実装した。いくつかの新
しい HTML5 入力形式を認識し、そして入力の種類に応じて動的にオンスクリーンキーボードを変更する
という機能だ。
例えば、電子メールはテキストだが、特別な種類のテキストだ。つまり、実質的にすべての電子メールア
ドレスは @ マークと少なくとも 1 個のピリオド(.)を含むが、スペースが含まれることはまずない。した
がって、iPhone ユーザが <input type="email"> 要素にフォーカスすると、図 9-3 に示すように通常よりも
小さなスペースバーと @ および . 専用のキーを持つオンスクリーンキーボードが表示される。
まとめると、今すぐ電子メールアドレスの入力フィールドを type="email" に変更しても悪影響は全くな
い。iPhone ユーザであっても違いに気付くユーザは少ないだろうし、それ以外のユーザは誰も気付かない
だろう。しかし、違いに気付いたユーザは、にっこり笑ってあなたが Web を少しだけ使いやすくしてくれ
たことに感謝してくれるはずだ。
9.5 Web アドレス
Web アドレス(多くの人には URL として、一部のうるさ型には URI として知られている)は、もうひ
とつの種類の特別なテキストだ。Web アドレスの文法は、関連するインターネット標準によって決めら
176
9 章 Web フォーム
図 9-4 URL の入力に適したキーボード
れている。Web アドレスをフォームへ入力するよう求める場合には、「新宿区坂町 26 番地 27」ではなく、
http://www.google.com のような入力が期待されているはずだ。スラッシュとピリオドが多用される一方
で、スペースは禁止されている。またすべての Web アドレスには「.com」や「.org」のようなドメインサ
フィックスがある。
そこで、<input type="url"> の登場だ。iPhone では、図 9-4 のように表示される。
電子メールアドレスフィールドと同じように、iPhone では Web アドレスの入力に適した特別な仮想キー
ボードが表示される。スペースバーは消え、代わりにピリオド、スラッシュ、そして「.com」ボタンが表
示される。「.com」ボタンを長押しすると、「.co.jp」や「.jp」などのよく使われるサフィックスを選ぶこと
ができる。
HTML5 をサポートしていないブラウザは type="url" を type="text" と全く同じように取り扱うので、
Web アドレスの入力をすべてこれに置き換えても悪影響は生じない。
9.6 スピンボックスによる数値の入力
次に登場するのは、数値だ。数値の入力は、いろいろな意味で電子メールや Web アドレスの入力よりも
面倒な点がある。まず、数値というものは意外に複雑なものだ。例えば、数値をひとつ選んでほしい。-1 ?
いや、私がほしいのは 1 から 10 までの間の数だ。7½ ?いや、分数じゃなくって。π?無理数なんて無理を
言うのはやめてほしい。
つまり、数値なら何でもいい、という場合はあまりないのだ。ある特定の範囲の数値を要求する場合が多
いし、その範囲の中でも特定の種類の数(分数や小数ではなく整数、あるいは 10 で割り切れる数など)が
9.6 スピンボックスによる数値の入力
177
必要なことが多い。HTML5 は、このような要望をカバーしている。次の例を見てほしい。
<input type="number"
min="0"
max="10"
step="2"
value="6">
これらの属性をひとつずつ見て行こう†。
●
type="number" は、これが数値フィールドであることを示す。
●
min="0" は、このフィールドが受け付ける最小値を示す。
●
max="10" は、受け付ける最大値を示す。
●
step="2" は、min から max までの間で入力可能な数値(0、2、4…)を示す。
●
value="6" は、デフォルト値だ。これについては見覚えのある人も多いだろう。フォームフィール
ドで値を指定する際には、いつもこの属性を使うからだ。(ここでは、HTML5 が HTML の以前の
バージョンの上に構築されていることを明確に示すため、わざわざこのことに触れた。今までに覚
えたことを再学習する必要はないのだ。)
これが数値フィールドのマークアップだ。これらの属性はすべてオプションであることに注意してほし
い。下限はあるが上限はない場合、min 属性だけを指定して max 属性は指定しなくてもよい。デフォルトの
ステップは 1 なので、それでよければ step 属性は省略できる。デフォルト値がない場合、value 属性は空
文字列を指定するか、あるいは完全に省略することができる。
しかも HTML5 には、さらに便利な機能がある。以下のような便利な JavaScript メソッドが使えるのだ。
input.stepUp(n )
フィールドの値を n だけ増加させる
input.stepDown(n )
フィールドの値を n だけ減少させる
input.valueAsNumber
現在の値を浮動小数点数として返す(input.value プロパティは常に文字列)
具体的にイメージしづらいだろうか。実は、数値コントロールの具体的なインタフェースはブラウザに任
されており、さまざまなブラウザメーカーがさまざまな方法でサポートを実装している。iPhone では、そ
もそも入力が困難を伴うため、ここでもブラウザは図 9-5 に示すような数値入力に適した仮想キーボードを
†
http://diveintohtml5.info/examples/input-type-number-min-max-step.html で実際に試してみることもできる。
178
9 章 Web フォーム
図 9-5 数値の入力に適したキーボード
図 9-6 スピンボックス
図 9-7 上限値に達したスピンボックス
表示する。
デスクトップバージョンの Opera や Chrome では、同じ type="number" のフィールドが「スピンボック
ス」のコントロールとして表示される。上下の小さな矢印をクリックすると、数値が変更できる(図 9-6)。
Opera、Chrome は min、max そして step 属性を見ているので、正しい数値しか入力できないようなスピ
ンボックスが表示される。Opera では上限値(もしくは下限値)に達したとき、スピンボックスの上向き
9.8 デートピッカー
179
(下向き)矢印はグレーアウトする(図 9-7)。
こ の 章 で 説 明 し た 他 の 入 力 形 式 と 同 様 に、type="number" を サ ポ ー ト し な い ブ ラ ウ ザ は そ れ を
type="text" として取り扱う。デフォルト値はフィールド内に表示される(value 属性に指定されているか
ら)が、min や max などのその他の属性は無視される。スピンボックスコントロールは自分で実装しても
かまわないし、すでに多くの JavaScript フレームワークで実装されているので、それを再利用してもよい。
ただ、以下のようにまず HTML5 をネイティブにサポートしているかどうかをチェックしてほしい(「2.12
入力形式」を参照)。
if (!Modernizr.inputtypes.number) {
// type="number" フィールドはネイティブにはサポートされていないようだ。
// Dojo などの JavaScript フレームワークを使う手もある。
}
9.7 スライダによる数値の入力
数値の入力を行う方法は、前のセクションで説明したスピンボックスだけではない。図 9-8 のような「ス
ライダ」コントロールを見たことがある人も多いだろう。
図 9-8 スライダ
Web フォームからスライダコントロールを表示させることもできる。そのマークアップは、スピンボッ
クスコントロールのマークアップとびっくりするほどよく似ている。
<input type="range"
min="0"
max="10"
step="2"
value="6">
利用できる属性は、type="number" の場合と同一だ。つまり min、max、step、value が利用でき、全く同
じ意味を持つ。唯一の違いは、ユーザインタフェースだ。入力フィールドではなく、スライダコントロー
ルとして type="range" を表示することがブラウザには期待される。Safari、Chrome、そして Opera の最
新バージョンではそのように表示される。(残念なことに、iPhone では単なるテキストボックスが表示され
る。数値入力に適したオンスクリーンキーボードの表示すらしてくれない。)その他のすべてのブラウザで
はこのフィールドを type="text" として取り扱う。したがって、今すぐ type="range" を使い始めない理由
は何もない。
9.8 デートピッカー
HTML 4 では、デートピッカーが提供されていなかった。さまざまな JavaScript フレームワーク、例え
180
9 章 Web フォーム
ば Dojo、jQuery UI、YUI そして Closure Library などでその隙間を埋めることはできるが、これらのソ
リューションを採用すれば、同時にそのフレームワークに縛り付けられることにもなってしまう。
HTML5 では、ついにネイティブなデートピッカーを表示する方法が定義された。もう自分でスクリプト
を書く必要はない。実際には 6 種類のコントロールが定義されている。日付、月、週、時刻、日付+時刻、
そして日付+時刻+タイムゾーンだ。
現在のところ、表 9-4 に示すように、サポート状況はあまり芳しくない†。
表 9-4 デートピッカーのサポート状況
入力形式
Opera
その他すべてのブラウザ
type="date"
9.0 ∼
×
type="month"
9.0 ∼
×
type="week"
9.0 ∼
×
type="time"
9.0 ∼
×
type="datetime"
9.0 ∼
×
type="datetime-local"
9.0 ∼
×
図 9-9 日付の選択
図 9-10 日付と時刻の選択
†
監訳注:2011 年 2 月時点において、Chrome ではこれらの値に対し簡易な実装が行われている。しかしながら <input
type="number"> と同じスピンボックスによる UI であり、Opera の実装や各種ライブラリで提供されるデートピッカーのよ
うなものではない。
9.8 デートピッカー
181
図 9-11 月の選択
図 9-12 週の選択
図 9-13 時刻の選択
図 9-9 に、Opera での表示を示す。
日付とともに時間も必要な場合には、図 9-10 に示すような <input type=" datetime"> も Opera はサポー
トしている。
クレジットカードの有効期限など、年と月だけが必要な場合には、<input type="month"> を使えば Opera
は図 9-11 に示すような表示をしてくれる。
実際に使う機会は少ないだろうが、<input type="week"> を使って一年のうちの特定の週を選ぶこともで
きる。図 9-12 を見てほしい。
最後になったが、図 9-13 に示すように、<input type="time"> を使って時刻を選ぶこともできる。
最終的には Opera 以外のブラウザでもこれらの入力形式はサポートされるだろう †。それまでの間、
type="email"(「9.4 電子メールアドレス」を参照)などの入力形式と同じように、type="date" などを認識
しないブラウザではこれらのフォームフィールドは単なるテキストボックスとして表示されることになる。
単純に <input type="date"> などと書いて、とりあえず Opera ユーザを幸せにし、その他のブラウザが追
†
監訳注:2011 年 3 月時点において、Chrome のデートピッカーは実装中の段階にある。Opera の様なデートピッカーが表示
されないが、script 要素中のコードは「サポートしている」と判断されるため注意が必要だ。
182
9 章 Web フォーム
いつくのを待ってもよい。あるいは、<input type="date"> を使い、ブラウザが日付選択をネイティブにサ
ポートしているかどうかを検出し(「2.12 入力形式」を参照)、サポートしていない場合にはお好みのスク
リプトを使った代替ソリューションを使うこともできる。
<form>
<input type="date">
</form>
...
<script>
var i = document.createElement("input");
i.setAttribute("type", "date");
if (i.type == "text") {
// 日付の選択はサポートされていないようだ :(
// Dojo/jQueryUI/YUI/Closure などのソリューションで
// コントロールを作成し、動的に <input> 要素を置き換える。
}
</script>
9.9 検索ボックス
さて、今度のやつはちょっと微妙だ。アイディアはシンプルなのだが、実装には多少の説明が必要だ。
問題は、Google 検索や Yahoo! 検索だけではなく(それも含むが)、一般の検索だ。どんなサイトで
も、どんなページでもいいから、検索ボックスを想像してみてほしい。Amazon には検索ボックスがある。
Newegg(オンラインの家電量販店)にも検索ボックスがある。たいていのブログにも検索ボックスがある。
マークアップはというと、Web 上の他のすべてのテキストボックスと同じく、<input type="text"> となっ
ているはずだ。HTML5 では、このように書ける。
<form>
<input name="q" type="search">
<input type="submit" value="Go">
</form>
ブラウザによっては、通常のテキストボックスと全く区別が付かないかもしれない。しかし Mac OS X
上で Safari を使っている場合には、図 9-14 のように見えるはずだ。
図 9-14 検索ボックス
9.10 カラーピッカー
183
図 9-15 フォーカスのある検索ボックス
違いがわかるだろうか。この入力ボックスは、角が丸くなっている! わかった、わかった、興奮する
のも無理はない。しかし実は、もっとすごいことがあるのだ! type="search" ボックスに実際に入力を
し始めると、Safari はそのボックスの右側に小さな「x」ボタンを表示する。この「x」をクリックすると、
フィールドの内容が消去される。(Google Chrome も、内部では多くの技術を Safari と共有しているので、
同じ挙動を示す。)これらの細かい仕掛けは、iTunes やその他の Mac OS X のクライアントアプリケーショ
ンのネイティブ検索ボックスのルックアンドフィールに合わせたものだ(図 9-15)。
Apple の Web サイトの検索ボックスは <input type="search"> を使っており、サイトに「Mac ライク」
な感じを与えるのに役立っている。しかしこれは、Mac に特有のものではない。これは単なるマークアッ
プなので、各プラットフォームのブラウザがそのプラットフォーム特有の約束に合わせて検索ボックスを表
示することも可能だ。他のすべての新しい入力形式と同じく、type="search" を認識しないブラウザはそれ
を type="text" として取り扱うので、今日からすべての検索ボックスで type="search" を使い始めない理
由は何もない。
マークアップ教授から一言
いや、実はひとつだけ、<input type="search"> を使わないほうがいい理由がある。Safari は、検索フィー
ルドに通常の CSS スタイルを適用してくれないのだ。(ここで「通常のスタイル」というのは、ボーダー、
背景色、背景画像、パディングなど基本的なものすべてを意味する。)Safari でこの検索フィールドを通常
のテキストフィールドと同じように見せたい場合(そして自分で CSS スタイルを適用したい場合)、次の
コードをスタイルシートに書けばよい。
input[type="search"] {
-webkit-appearance: textfield;
}
このやり方を教えてくれた John Lein に感謝する。
9.10 カラーピッカー
HTML5 では、<input type="color"> も定義されている。これはユーザに色を選択させ、その結果を色
の 16 進表現で返すものだ。これをサポートしているブラウザは存在せず、Mac OS の色選択が大好きな私
184
9 章 Web フォーム
図 9-16 Opera の <input type="color"> フィールドの表示はプラットフォームごとに異なる
は残念に思っていた。
し か し 良 い ニ ュ ー ス が あ る。Opera 11.00 が <input type="color"> を サ ポ ー ト し た の だ †。Mac と
Windows では、ネイティブのカラーピッカーと統合している。Linux ではシンプルなカラーピッカーが現
れる。すべてのプラットフォームにおいて、このコントロールは 6 桁の 16 進数による RGB 値を返す。
この図 9-16 を本書に掲載できるようにするため、図をライセンスしてくれた Patrick Lauke と Chris
Mills に感謝したい。彼らが公開した Opera 11 のサポートする新しいフォーム機能に関する記事(http://
dev.opera.com/articles/view/new-form-features-in-html5/#input-color)を是非読んでほしい。
9.11 フォームの検証
表 9-5 フォーム検証のサポート状況
IE
Firefox
Safari
Chrome
Opera
iPhone
Android
×
4.0 ∼
5.0 ∼
6.0 ∼
9.0 ∼
×
×
この章では、新しい入力形式やフォームフィールドへのオートフォーカスなどの新しい機能について説
明してきた。しかし、HTML5 のフォームの、おそらく最もエキサイティングな機能についてはまだ説明し
ていなかったと思う。それは、フォームに入力された内容の自動検証機能だ。電子メールアドレスを Web
フォームへ入力するという、よくある状況を考えてみてほしい。おそらくクライアント側で JavaScript に
よる何らかの検証を行った後で、サーバ側では PHP や Python、あるいはその他のサーバサイドスクリプ
ト言語による検証を行うことになるはずだ。しかし、JavaScript で電子メールアドレスの検証を行うことに
は、2 つの大きな問題がある。
†
http://dev.opera.com/articles/view/new-form-features-in-html5/#input-color を参照。
9.11 フォームの検証
●
驚くほど多くの訪問者(おそらく 10%近く)が、JavaScript を無効に設定している
●
検証に失敗するおそれがある
185
まじめな話、検証に失敗してしまうおそれは、おおいにあるのだ。ランダムな文字列が有効な電子メール
アドレスであるかどうかを判断する方法は、信じられないほど複雑だ†。調べれば調べるほど、どんどん複
雑になって行く††。本当に、ものすごく複雑なのだ‡。このような頭痛の種をブラウザに任せてしまえた
ら、どんなに楽になることだろう。
図 9-17 は Opera 10 のスクリーンショットだが、この機能は Opera 9 から存在している。これに関連す
るマークアップは、type 属性を "email" に設定するだけだ(「9.4 電子メールアドレス」を参照)。Opera
ユーザが <input type="email"> を含むフォームを送信しようとすると、たとえスクリプトが無効に設定さ
れていても、Opera は自動的に RFC に従った電子メールアドレスの検証を行ってくれる。
Opera はまた、<input type="url"> フィールドへ入力された Web アドレスや、<input type="number">
へ入力された数値の検証も行ってくれる。数値の検証は min や max 属性も考慮に入れた上で行われるので、
ユーザが大きすぎる数値を入力した場合にはそのフォームを送信できないようにしてくれる(図 9-18)。
フォーム検証機能を有効にするために特別なマークアップは必要ない。なぜなら、デフォルトで有効だか
らだ。逆に検証を無効にしたい場合は、novalidate 属性を使う。
<form novalidate>
<input type="email" id="addr">
<input type="submit" value="Subscribe">
</form>
ブラウザは HTML5 フォーム検証を少しずつ実装している。Firefox 4 ではサポートが行われる ‡‡。
Safari と Chrome の実装は現時点で残念ながら不完全であるため、それに惑わされることがあるかもしれ
図 9-17 Opera が type="email" を検証している様子
図 9-18 Opera が type="number" を検証している様子
†
http://www.regular-expressions.info/email.html を参照。
††
さらに、http://www.ex-parrot.com/pdw/Mail-RFC822-Address.html を参照。
‡
さらに、http://haacked.com/archive/2007/08/21/i-knew-how-to-validate-an-email-address-until-i.aspx を参照。
‡‡
https://developer.mozilla.org/ja/HTML/HTML5/Forms_in_HTML5 を参照。
186
9 章 Web フォーム
ない。フォームの検証は行ってくれるが、妥当ではない箇所を視覚的に示してくれないのだ。例えば、妥当
ではない(あるいは、正しい形式で書かれていない)日付を type="date" の付いたフィールドに入力したと
き、Safari と Chrome はフォームの送信を禁止するが、送信できない理由は教えてくれないのだ(不適当
な値のフィールドにフォーカスを移動するが、Opera や Firefox 4 のようにエラーメッセージを表示しては
くれない)。
9.12 入力必須フィールド
HTML5 のフォーム検証はフィールドに入力された値の形式だけを対象とするものではない。特定の
フィールドへの入力を必須とさせることも可能だ。入力必須フィールドに何も入力されていない場合、
フォームを送信することはできない。表 9-6 に、ブラウザごとの <input required> のサポート状況を示す。
表 9-6 <input required> のサポート状況
IE
Firefox
Safari
Chrome
Opera
iPhone
Android
×
4.0 ∼
×
10.0 ∼
9.0 ∼
×
×
入力必須フィールドのマークアップは次のようにシンプルだ。
<form>
<input id="q" required>
<input type="submit" value="Search">
</form>
ブラウザは入力必須フィールドの見た目を変更することがある。Mozilla Firefox 4.0 では、入力必須
フィールドに値が入力されていない場合、そのフィールドの周りを赤くする(図 9-19)。
Firefox ではさらに、入力必須フィールドに何も入力しないままフォームを送信しようとすると、その
フィールドが入力必須であり空にできないというポップアップを表示する。
図 9-19 Mozilla Firefox 4.0 の入力必須フィールド
9.13 参考文献
9.13 参考文献
仕様および標準:
●
<input> 要素の type 属性一覧
http://whatwg.org/html5#states-of-the-type-attribute
●
<input placeholder> 属性
http://whatwg.org/html5#the-placeholder-attribute
●
<input autofocus> 属性
http://whatwg.org/html5#autofocusing-a-form-control
●
<input novalidate 属性
http://whatwg.org/html5#attr-fs-novalidate
●
<input required> 属性
http://whatwg.org/html5#the-required-attribute
JavaScript ライブラリ:
●
HTML5 検出ライブラリ、Modernizr
http://www.modernizr.com/
その他の記事:
●
先進志向のフォーム検証
http://www.alistapart.com/articles/forward-thinking-form-validation/
●
Firefox 4 以降の HTML5 フォームサポート
https://developer.mozilla.org/ja/HTML/HTML5/Forms_in_HTML5
●
Opera 11 でサポートされた新しいフォーム機能
http://dev.opera.com/articles/view/new-form-features-in-html5/
187
189
10 章
マイクロデータによる
マークアップの拡張
10.1 はじめに
HTML5 には、100 を超える要素†が定義されている。純粋に意味的なものもあり(3 章を参照)、スクリ
プト用 API の単なるコンテナとして使われるものもある(4 章を参照)。HTML の歴史を通じて(1 章を参
照)、標準化マニアたちはどの要素を HTML 言語に採用すべきかについて議論し続けてきた。HTML には
<figure> 要素や <person> 要素は必要だろうか。<rant> 要素††についてはどうだろう。数々の決定がなさ
れ、仕様が作成され、Web 制作者はページを作成し、実装者は実装を行い、Web は前進し続けてきた。
もちろん、HTML はすべての人々を満足させることはできない。どんな標準でも、それは不可能だ。日
の目を見なかったアイディアもある。例えば、HTML5 には <person> 要素は存在しない(<rant> 要素もだ、
なんてこったい!)。誰も Web ページに <person> を書いてはいけないと言っているわけではないが、妥当
な要素とは見なされないし、すべてのブラウザにわたって一貫性のある挙動もとらない(「3.6 ブラウザが
不明な要素を取り扱う方法についての長い余談」を参照)し、もし同じ名前の要素が将来 HTML 仕様に追
加された場合にはそれと衝突してしまうおそれもある。
独自の要素を作り上げることが無理なら、Web に意味を持たせたい Web 制作者はどうすればよいだろ
うか。言語を拡張する試みは、以前のバージョンの HTML から行われてきた。その中では、HTML 4 の
class および rel 属性を使用するマイクロフォーマット‡が最もよく知られているだろう。もうひとつの選
択肢として RDFa ‡‡がある。これはもともと XHTML(「1.11 後日談」を参照)で使われるために設計さ
れたものだが、現在では HTML でも使えるようになっている *。
マイクロフォーマットも RDFa も、それぞれ長所と短所がある。この 2 つは、HTML 仕様に含まれない
意味を追加することによって Web ページを拡張するという同じ目的を持っているが、それを達成するため
のアプローチは根本的に異なっている。この章では、フォーマットに関して、ののしりあいをするつもりは
ない(それには <rant> 要素が必要だ!)。その代わりに、HTML5 自体の一部であり緊密に HTML5 へ組み
込まれた第三の選択肢について説明したい。それがマイクロデータだ。
†
http://simon.html5.org/html5-elements を参照。
††
訳注:rant は「わめき散らす」という意味。
‡
http://microformats.org/ を参照。
‡‡
http://www.w3.org/TR/rdfa-syntax/ を参照。
*
http://www.w3.org/TR/rdfa-in-html/ を参照。
190
10 章 マイクロデータによるマークアップの拡張
10.2 マイクロデータとは
以下の文章の単語ひとつひとつが重要な意味を持つので、注意して読んでほしい。
マークアップ教授から一言
マイクロデータは、独自の語彙から構成される名前と値のペアによって、あるスコープ(範囲)内の DOM
を意味付けする仕組みだ。
これはどういう意味だろうか。ひとつひとつ説明していこう。マイクロデータは、独自の語彙を中心とし
て機能する。「すべての HTML5 要素」を、ひとつの語彙と考えてほしい。この語彙には、セクションや記
事を表現する要素(「3.5 HTML5 の新しい意味要素」を参照)が含まれているが、人物やイベントを表現す
る要素は含まれていない。Web ページ上で人物を表現したければ、独自の語彙を定義する必要がある。マ
イクロデータはこれを可能とするものだ。誰でもマイクロデータ語彙を定義し、自分の Web ページに好き
な情報を埋め込むことができる。
マイクロデータについて知っておくべき次の事実は、名前と値のペアによって機能するということだ。す
べてのマイクロデータ語彙は、名前付きプロパティを定義する。例えば、「人物」に関する語彙は name や
photo などのプロパティを定義することになるだろう。特定のマイクロデータのプロパティを Web ページ
に含めるには、特定の場所にそのプロパティ名を与えることによって行う。プロパティの値をどうやって抽
出するかは、プロパティ名を与えた場所によって変わる。これはマイクロデータの処理規則で定義されてい
る。(詳しくは次のセクションで説明する。)
名前付きプロパティに加えて、マイクロデータは「スコープ」という概念に強く依存している。マイク
ロデータのスコープを理解するには、DOM 中の要素間の自然な親子関係を考えてもらうとわかりやすい。
<html> 要素(「3.3 ルート要素」を参照)は、通常 <head>(「3.4 <head> 要素」を参照)と <body> という 2
個の子要素を持つ。<body> 要素は通常複数の子要素を持ち、それぞれの子要素はさらにその子要素を持つ
ことができる。例えば、ページの <body> 要素の中には <header> 要素が含まれ、その中に <hgroup> 要素が
含まれ、さらにその中に <h1> 要素が含まれているだろう(「3.7 ヘッダ」を参照)。同様に、(<body> 要素の
中の)<table> 要素の中には <tr> 要素が含まれ、さらにその中には <td> 要素が含まれているだろう。マイ
クロデータはこの DOM 自体の階層構造を再利用して、「この要素中のすべてのプロパティはこの語彙から
成り立っている」と指定する方法を提供している。これによって、同一のページで複数のマイクロデータ語
彙を利用することができる。さらに、DOM の自然な構造を再利用して、マイクロデータ語彙の中に別の語
彙を入れ子にすることもできる。(この章の中で、入れ子になった語彙の例を複数お見せする。)
すでに DOM については触れたが、もうすこし詳しく説明させてほしい。マイクロデータは、Web ペー
ジにすでに表示されているデータに意味を追加するものだ。マイクロデータは、独立したデータフォーマッ
トではなく、HTML を補完するものとして設計されている。次のセクションで説明するように、マイクロ
データが最も威力を発揮するのは、すでに HTML が正しく使われていて、しかし HTML の語彙では意味
が十分に表現できない場合だ。マイクロデータは、すでに DOM に存在するデータの意味付けを微調整す
10.3 マイクロデータのデータモデル
191
る方法として、非常に有効だ。意味付けをすべきデータが DOM にない場合には、いったん距離を置いて、
マイクロデータが正しいソリューションなのかをもう一度考え直してみてほしい。
マークアップ教授の一言がわかってきただろうか。そうであれば私もうれしい。それでは、実際に使われ
ているところを見ていくことにしよう。
10.3 マイクロデータのデータモデル
マイクロデータ語彙は、自分で簡単に定義できる。まず必要となるのは名前空間で、これは単純な
URL だ。名前空間 URL は実在する Web ページを参照してもよいが、厳密にそうすることが要求されて
いるわけではない。例えば、人物を記述するマイクロデータ語彙を作成していると考えてみよう。data-
vocabulary.org というドメインを保有しているなら、マイクロデータ語彙の名前空間として http://datavocabulary.org/Person という URL を使えばよい。このように、自分が管理しているドメインの URL を使
えば、簡単にグローバルにユニークな識別子が作成できる。
この語彙には、いくつかの名前付きプロパティを定義する必要がある。まず、3 個の基本的なプロパティ
から始めよう。
●
name(ユーザのフルネーム)
●
photo(ユーザの写真へのリンク)
●
url(例えばブログや Google profile など、ユーザに関連したサイトへのリンク)
これらのプロパティのうち 2 個は URL で、残りの 1 個はプレーンテキストだ。これらにはすべて、マイ
クロデータや語彙について考えなくても、自然な形で適切にマークアップできる。あなたがプロフィール
ページや「about」といった名前のページを持っていると想像してみてほしい。おそらく、あなたの名前は
(<h1> 要素などの)見出しとしてマークアップされているだろう。あなたの写真は <img> 要素になっている
だろう。そうすれば、みんなに見てもらえるからだ。そしてあなたのプロフィールに関連した URL は、ハ
イパーリンクとしてマークアップされているだろう。そうすれば、みんなにクリックしてもらえるからだ。
ここで議論のため、あなたのプロフィール全体がさらに <section> 要素で囲まれ、その他のページの内容か
ら分離されているとしよう。こんな具合だ。
<section>
<h1>Mark Pilgrim</h1>
<p><img src="http://www.example.com/photo.jpg" alt="[me smiling]"></p>
<p><a href="http://diveintomark.org/">weblog</a></p>
</section>
マイクロデータのデータモデルは、名前と値のペアだ。マイクロデータのプロパティ名(この例では
name、photo、あるいは url)は、常に HTML 要素上に宣言される。多くの HTML 要素の場合、その要素
内のテキストがそのままプロパティの値となる。しかし表 10-1 に示すように、いくつかの例外がある。
192
10 章 マイクロデータによるマークアップの拡張
表 10-1 マイクロデータでプロパティの値となるもの
要素
値
<meta>
content 属性
<audio>
src 属性
<embed>
<iframe>
<img>
<source>
<video>
<a>
href 属性
<area>
<link>
<object>
data 属性
<time>
datetime 属性
その他すべての要素
要素内のテキスト
ページに「マイクロデータを追加する」ことは、すでに存在する HTML 要素に数個の属性を追加するこ
とによって行われる。最初にしなければならないのは、itemtype 属性を追加し、使用するマイクロデータ
語彙を宣言することだ。次にしなければならないのは、itemscope 属性を使って、語彙のスコープを宣言す
ることだ。この例では、意味付けしたいすべてのデータは <section> 要素中にあるので、<section> 要素上
に itemtype 属性と itemscope 属性を宣言することになる。
<section itemscope itemtype="http://data-vocabulary.org/Person">
section 要素の中で最初に出てくるデータはあなたの名前で、それは <h1> 要素に囲まれている。この
<h1> 要素は特別な取り扱いは必要ないので、表 10-1 の「その他すべての要素」の値、つまり要素内のテキ
ストがそのままプロパティの値となる(あなたの名前が <p>、<div>、または <span> 要素に包まれている場
合も同様だ)。
<h1 itemprop="name">Mark Pilgrim</h1>
日本語で言うと、「これは http://data-vocabulary.org/Person 語彙の中の name プロパティで、その値
は Mark Pilgrim だ」という意味になる。
次は photo プロパティだ。これには URL を指定したい。表 10-1 によれば、<img> 要素の「値」はその
src 属性となる。なんと、あなたのプロフィール写真の URL は、すでに <img src> 属性に設定されている
ではないか! したがって、<img> 要素が photo プロパティであると宣言するだけでよい。
<p><img itemprop="photo"
src="http://www.example.com/photo.jpg"
alt="[me smiling]"></p>
10.3 マイクロデータのデータモデル
193
日本語で言うと、「これは、http://data-vocabulary.org/Person 語彙の中の photo プロパティで、その
値は http://www.example.com/photo.jpg だ」という意味になる。
最後に url プロパティだが、これもまた URL だ。表 10-1 によれば、<a> 要素の「値」は、その href 属
性となる。ここでも、これは既存のマークアップとぴったり一致しているので、既存の <a> 要素が url プロ
パティであると宣言するだけでよい。
<a itemprop="url" href="http://diveintomark.org/">dive into mark</a>
日本語で言うと、「これは、http://data-vocabulary.org/Person 語彙の中の url プロパティで、その値
は http://diveintomark.org/ だ」という意味になる。
もちろん、実際のマークアップが多少違っていたとしても問題はない。どんな HTML マークアップへも
(たとえそれが前世紀的でひどい <table> 要素でレイアウトされた、とてつもなく保守しづらいマークアッ
プであっても)、マイクロデータは追加できるからだ。もちろん私はそのようなマークアップはお勧めしな
いが、今でもよく見かけるのは確かだし、ちゃんと以下のようにマイクロデータは追加できる。
<TABLE>
<TR><TD>Name<TD>Mark Pilgrim
<TR><TD>Link<TD>
<A href=# onclick=goExternalLink()>http://diveintomark.org/</A>
</TABLE>
name プロパティをマークアップするには、その名前を含む表のセルに itemprop 属性を追加するだけでよ
い。マイクロデータのプロパティと値の表によれば、表のセルには特別な取り扱いはされないので、プロパ
ティの値は要素内のテキストとなる。
<TR><TD>Name<TD itemprop="name">Mark Pilgrim
url プロパティの追加は、ちょっと面倒に思える。このマークアップには <a> 要素が正しく使われていな
いからだ。href 属性にリンク先を指定するのではなく、href 属性には無意味な値を設定し、onclick 属性
から JavaScript を使って関数(ここには明示していない)を呼び出して抽出した URL へ移動している。つ
いでだからここでは、さらにこの関数がこのリンクをスクロールバーの付いていない小さなポップアップ
ウィンドウで開くと想像してみよう。いやはや、前世紀のインターネットときたら…。
それでも、これをマイクロデータのプロパティへと変換することは可能だ。ちょっとだけ創造力を働かせ
ればよい。<a> 要素を直接使うことはできない。リンク先は href 属性に指定されておらず、「<a> 要素では
href 属性がプロパティの値として使われる」という仕組みを上書きする方法はないからだ。しかし、この
混乱のきわみのマークアップ全体を何かの要素で囲み、そこに url マイクロデータのプロパティを追加する
ことはできる。
<TABLE itemscope itemtype="http://data-vocabulary.org/Person">
<TR><TD>Name<TD>Mark Pilgrim
194
10 章 マイクロデータによるマークアップの拡張
<TR><TD>Link<TD>
<span itemprop="url">
<A href=# onclick=goExternalLink()>http://diveintomark.org/</A>
</span>
</TABLE>
<span> 要素には特別な取り扱いはされないので、「プロパティの値は要素内のテキスト」というデフォル
トのルールにしたがう。「要素内のテキスト」とは、「この要素の中にあるすべてのマークアップ」(例えば
innerHTML DOM プロパティで取得されるような)を意味するわけではない。それは、「テキストだけ」を
意味するのだ。この場合には http://diveintomark.org/ が <span> 要素に含まれる <a> 要素の内容テキス
トとなる。
まとめると、どのようなマークアップにもマイクロデータを追加することは可能だ。もちろん、適切に書
かれた HTML の方が、ひどい HTML マークアップよりも簡単にマイクロデータを追加できるが、どんな
場合でも方法はある。
10.4 人物のマークアップ
前のセクションで説明に使ったサンプルは、まだ完成していない。人物に関する情報をマークアップする
マイクロデータ語彙は実在するし、簡単に使える。詳しく見ていこう。
マイクロデータを個人の Web サイトへ取り入れるには、「about me」ページで行うのが最も簡単だ。読
者の皆さんも、「about me」ページは持っていると思う。もしなければ、サンプルの「about me」ペー
ジ(http://diveintohtml5.info/examples/person.html )にセマンティクスを追加する方法をこれから説
明するので、それにしたがって作ってみてほしい。マイクロデータを組み込んだサンプルはここ(http://
diveintohtml5.info/examples/person-plus-microdata.html)にある。
まず、マイクロデータを追加する前のマークアップを見てみよう。
<section>
<img width="204" height="250"
src="http://diveintohtml5.info/examples/2000_05_mark.jpg"
alt="[Mark Pilgrim, circa 2000]">
<h1>Contact Information</h1>
<dl>
<dt>Name</dt>
<dd>Mark Pilgrim</dd>
<dt>Position</dt>
<dd>Developer advocate for Google, Inc.</dd>
<dt>Mailing address</dt>
<dd>
100 Main Street<br>
Anytown, PA 19999<br>
10.4 人物のマークアップ
195
USA
</dd>
</dl>
<h1>My Digital Footprints</h1>
<ul>
<li><a href="http://diveintomark.org/">weblog</a></li>
<li><a href="http://www.google.com/profiles/pilgrim">Google profile</a></li>
<li><a href="http://www.reddit.com/user/MarkPilgrim">Reddit.com profile</a></li>
<li><a href="http://www.twitter.com/diveintomark">Twitter</a></li>
</ul>
</section>
常に最初にしなければならないのは、これから使う語彙と、追加したいプロパティのスコープを宣言する
ことだ。これは、itemtype 属性と itemscope 属性を、実際のデータが含まれる要素をすべて含む最も外側
の要素に追加することによって行う。この場合、それに相当するのは <section> 要素だ。
<section itemscope itemtype="http://data-vocabulary.org/Person">
このセクションで行う変更はすべて、オンラインで確認することができる。変更前が http://
diveintohtml5.info/examples/person.html 、変更後が http://diveintohtml5.info/examples
/person-plus-microdata.html だ。
これで、http://data-vocabulary.org/Person の語彙からマイクロデータを付加できるようになった。し
かし、どういうプロパティがあるのだろうか。実は http://data-vocabulary.org/Person へ行けば、プロパ
ティの一覧を見ることができる。マイクロデータの仕様はそこまで要求していないが、確かにこれは「ベス
トプラクティス」だと言えるだろう。要するに、自分の作ったマイクロデータ語彙を Web 開発者に使って
もらいたければ、文書を作る必要がある。その文書を置く場所として最適なのは、語彙の URL それ自身だ
ろう。表 10-2 に、Person の語彙を示す。
サンプルの「about me」ページの最初にあるのは私の写真だ。当然、<img> 要素でマークアップされてい
る。この <img> 要素が私のプロフィール写真であると宣言するには、itemprop="photo" を追加するだけで
よい。
<img itemprop="photo" width="204" height="250"
src="http://diveintohtml5.info/examples/2000_05_mark.jpg"
alt="[Mark Pilgrim, circa 2000]">
プロパティの値はどうなるだろう。それはすでに、src 属性の中にある。表 10-1 を思い出してもらえば
わかるように、<img> 要素の「値」は src 属性だからだ。すべての <img> 要素には src 属性がある。そうで
なくては画像が表示されない。そして src は常に URL だ。理解してもらえただろうか。HTML を正しく
使っていれば、マイクロデータは簡単なのだ。
しかも、このページにはこの <img> 要素だけがあるわけではない。これは <section> 要素の子要素となっ
10 章 マイクロデータによるマークアップの拡張
196
表 10-2 Person 語彙
プロパティ
説明
name
名前
nickname
ニックネーム
photo
画像リンク
title
人物の肩書き(例えば「経理課長」)
role
人物の役割(例えば「会計士」)
url
例えばその人物のホームページなど、Web ページへのリンク
affiliation
人物が関係している組織(例えば勤務先)の名前
friend
人物と別の人物との間の社会的関係を示す
contact
人物と別の人物との間の社会的関係を示す
acquaintance
人物と別の人物との間の社会的関係を示す
address
人物の住所(サブプロパティとして street-address、locality、region、postal-code、
および country-name を持つことができる)
ていて、そこにはついさっき itemscope 属性を宣言した。マイクロデータはページ上の要素間の親子関係を
再利用してマイクロデータのプロパティのスコープを定義する。普通の日本語で言うと、「この <section>
要素はひとりの人物を表現しており、この <section> 要素の子要素に現れるマイクロデータのプロパティ
は、すべてその人物のプロパティである」という意味だ。別の言い方をすると、<section> 要素が文章の主
語に当たると考えることもできる。itemprop 属性は文章の動詞に当たり、「∼の写真は…だ」という意味に
なる。そしてマイクロデータのプロパティ値は、文章の目的語に当たるというわけだ。
この人物(<section itemscope itemtype="..."> によって明示的に指定)
の写真は(<img itemprop="photo"> によって明示的に指定)
http://diveintohtml5.info/examples/2000_05_mark.jpg(img src 属性によって暗黙に指定)にある。
「主語」は、最も外側の <section> 要素に itemscope 属性と itemtype 属性を指定することによって、一
度だけ定義される。「動詞」は、<img> 要素に itemprop="photo" 属性を指定することによって定義される。
文章の「目的語」は特別なマークアップを一切必要としない。表 10-1 によれば、<img> 要素のプロパティ
値は src 属性だからだ。
マークアップの次の部分へ進むと、<h1> 見出しがあり、<dl> リストが開始されている。<h1> も <dl> も、
両方ともマイクロデータでマークアップする必要はない。HTML のすべての部分がマイクロデータとなる
わけではないのだ。マイクロデータはプロパティそのものを定義するものであり、そのプロパティを取り巻
くマークアップやヘッダに定義されるものではない。この <h1> はプロパティではなく、単なる見出しだ。
同様に、<dt> は「Name」がラベルであることを示しているだけで、プロパティではない。
<h1>Contact Information</h1>
<dl>
<dt>Name</dt>
<dd>Mark Pilgrim</dd>
10.4 人物のマークアップ
197
では、実際の情報はどこにあるのだろうか。答は <dd> 要素であり、したがってここに itemprop 属性を設
定する必要がある。どのプロパティを設定すればいいだろうか。答は name プロパティだ。値はどこにある
だろうか。答は <dd> 要素のテキストだ。それをマークアップする必要はあるだろうか。表 10-1 によれば、
答はノーだ。<dd> 要素は特別な取り扱いを必要としないので、値はその要素中のテキストそのものになる。
<dd itemprop="name">Mark Pilgrim</dd>
これは「この人物の名前は Mark Pilgrim だ」という意味になる。よろしい。先へ進もう。
次の 2 つのプロパティは、ちょっと面倒だ。マイクロデータを付加する以前のマークアップは、次のよ
うになっている。
<dt>Position</dt>
<dd>Developer advocate for Google, Inc.</dd>
Person 語彙の定義を参照すると、「Developer advocate for Google, Inc.」の部分は実際には 2 つのプロ
パティにまたがっていることがわかる。title(「Developer advocate」)と affiliation(「Google, Inc.」)
だ。これは、マイクロデータではどのように表現すればよいだろうか。「それはできない」というのが短い
答だ。マイクロデータは、一連のテキストを個別のプロパティへ分割する方法を持っていない。「最初の 18
文字はひとつのプロパティへ、残りの 12 文字は別のプロパティへ」などと指定することはできないのだ。
しかし、方法がないわけではない。CSS にもそのような機能はないが、「Developer advocate」というテ
キストを、「Google, Inc.」というテキストとは別のフォントにしたい場合にはどうするだろうか。<span>
要素を使うことになるだろう。同じように、それぞれの箇所をダミーの <span> 要素で囲えば、それぞれの
<span> に別個のプロパティを宣言できる。
<dt>Position</dt>
<dd><span itemprop="title">Developer advocate</span> for
<span itemprop="affiliation">Google, Inc.</span></dd>
ほら、このとおり。日本語で言うと、「この人物の肩書きは『Developer advocate』だ。この人物の勤務
先は『Google, Inc.』だ。」という意味になる。2 つの文章が、2 つのマイクロデータに対応している。多少
マークアップは複雑になったが、許容できる範囲だろう。
同じテクニックが、住所のマークアップにも使える。Person 語彙には address プロパティが定義されて
おり、これ自身がマイクロデータのアイテムとなっている。どういうことかというと、住所は独自の語彙†
を持っており、独自のプロパティ(street-address、locality、region、postal-code、および country-
name)を定義しているのだ。
あなたがプログラマなら、オブジェクトとそのプロパティを定義する際に使われるドット記法になじみが
あると思う。以下のような関係があると考えてほしい。
†
http://data-vocabulary.org/Address を参照。
10 章 マイクロデータによるマークアップの拡張
198
●
Person
●
Person.address
●
Person.address.street-address
●
Person.address.locality
●
Person.address.region
●
Person.address.postal-code
●
Person.address.country-name
この例では、住所全体がひとつの <dd> 要素に含まれている。(もう一度言っておくと、<dt> 要素は単な
るラベルで、マイクロデータに意味を付け加える役割は持っていない。)address プロパティの記述は簡単
だ。<dd> 要素に itemprop 属性を追加すればよい。
<dt>Mailing address</dt>
<dd itemprop="address">
しかし、address プロパティそれ自身がマイクロデータのアイテムであることを忘れないでほしい。つま
り、itemscope 属性と itemtype 属性も追加する必要があるのだ。
<dt>Mailing address</dt>
<dd itemprop="address" itemscope
itemtype="http://data-vocabulary.org/Address">
以前にも同様のことをしたが、そのときはトップレベルのアイテムに対してだけだった。<section> 要素
に itemtype と itemscope が宣言され、その <section> 要素の中にある、プロパティが宣言されるすべての
要素は、その特定の語彙のスコープ内にある。しかし、ここで初めてわれわれは、入れ子になったスコープ
を目にしている。既存の(<section> 要素で宣言された)スコープ内で、新しい itemtype と itemscope が
(<dd> 要素で)宣言されているのだ。この入れ子になったスコープは、HTML DOM とまったく同じように
振る舞う。<dd> 要素はいくつかの子要素を持つが、それらはすべて <dd> 要素上に宣言された語彙のスコー
プ内にあるのだ。<dd> 要素が対応する </dd> タグによって閉じられると、スコープは親要素(この場合に
は <section> 要素)で宣言された語彙に戻ることになる。
Address 語彙のプロパティには、先ほどの title や affiliation プロパティと同じ問題がある。一連の
長いテキストを、分割して別々のマイクロデータのプロパティとしたいのだ。解決法は先ほどと同じで、
個々の情報をダミーの <span> 要素で囲い、そして各 <span> 要素上でマイクロデータのプロパティを宣言す
ればよい。
10.4 人物のマークアップ
199
<dd itemprop="address" itemscope
itemtype="http://data-vocabulary.org/Address">
<span itemprop="street-address">100 Main Street</span><br>
<span itemprop="locality">Anytown</span>,
<span itemprop="region">PA</span>
<span itemprop="postal-code">19999</span>
<span itemprop="country-name">USA</span>
</dd>
</dl>
日本語で言うと、次のような意味になる。「この人物には住所がある。町名と番地は『100 Main Street』
だ。市町村名は『Anytown』だ。州名は『PA』だ。郵便番号は『19999』だ。国名は『USA』だ。」
マークアップ教授に質問
Q:この住所フォーマットは、米国特有のものですか?
A:いや、そうではない。Address 語彙のプロパティは一般的にできているので、世界中の住所の大部分
を記述することができる。値を持たないプロパティがあっても、問題ない。また、ひとつのプロパティに複
数の「行」を書かざるを得ない場合もあるが、それも問題ない。例えば、住所に番地と部屋番号が含まれて
いる場合、両方を street-address に記述することになるだろう†。
<p itemprop="address" itemscope
itemtype="http://data-vocabulary.org/Address">
<span itemprop="street-address">
100 Main Street
Suite 415
</span>
...
</p>
このサンプルの「about me」ページに関して、もうひとつ触れておきたいことがある。URL のリストだ。
Person 語彙にはそのための url という名前のプロパティがある。url プロパティは、実際には何であって
もよい。(もちろん URL である必要はあるが、それは言わなくてもわかるだろう。)つまり、url プロパティ
†
監訳注:日本の住所表記と各プロパティの対照表を次に記す。
プロパティ
説明
country-name
postal-code
region
locality
street-address
国名
郵便番号
都道府県
市区町村
町名と番地
10 章 マイクロデータによるマークアップの拡張
200
は非常にゆるく定義されているのだ。このプロパティは、人物と関連付けたい URL なら何でもよい。ブロ
グ、フォトギャラリー、あるいは Facebook や Twitter などの別のサイト上のプロフィールでもよいのだ。
もうひとつ重要なことは、ひとつの Person が複数の url プロパティを持てるということだ。理論的には、
すべてのプロパティは複数回現れてもよいのだが、今までそれを利用したことはなかった。例えば、それぞ
れ別の画像 URL を参照する 2 つの photo プロパティを持ってもよいのだ。しかしここでは、4 つの異なる
URL を掲載したい。私のブログ、私の Google プロフィールページ、Reddit 上の私のユーザプロフィール、
そして私の Twitter アカウントだ。HTML では、これはリンクのリストになっており、4 つの <a> 要素が、
それぞれ <li> 要素の中にある。マイクロデータでは、各 <a> 要素に itemprop="url" 属性を指定すること
になる。
<h1>My Digital Footprints</h1>
<ul>
<li><a href="http://diveintomark.org/"
itemprop="url">weblog</a></li>
<li><a href="http://www.google.com/profiles/pilgrim"
itemprop="url">Google profile</a></li>
<li><a href="http://www.reddit.com/user/MarkPilgrim"
itemprop="url">Reddit.com profile</a></li>
<li><a href="http://www.twitter.com/diveintomark"
itemprop="url">Twitter</a></li>
</ul>
表 10-1 によれば、<a> 要素には特別な取り扱いが行われる。プロパティの値は href 属性であって、要素
内のテキストではない。各リンクのテキストは、マイクロデータプロセッサによって無視されるのだ。し
たがって、日本語で言うと次のような意味になる。「この人物は、http://diveintomark.org/ という URL
を持っている。この人物は、http://www.google.com/profiles/pilgrim という URL も持っている。この人
物は、http://www.reddit.com/user/MarkPilgrim という URL も持っている。この人物は、http://www.
twitter.com/diveintomark という URL も持っている。」
10.4.1 Google リッチスニペットの紹介
ここでいったん距離を置いて、「何のためにこういうことをしているのか?」という質問を投げかけてみ
たい。セマンティクスを追加するということそれ自体のために、こんなことをしているのだろうか。悪く取
らないでほしい。私だってマークアップをいじくりまわすのは大好きだ。でもなぜマイクロデータを、わざ
わざ使う意味があるのだろうか。
HTML と、それを拡張する HTML5 マイクロデータを消費する主要なアプリケーションには、大きく分
けて 2 種類ある。
●
Web ブラウザ
●
検索エンジン
10.4 人物のマークアップ
201
ブラウザのために、HTML5 は Web ページからマイクロデータのアイテム、プロパティ、そして値を抽
出するための一連の DOM API を定義している。しかし本書の執筆時点(2011 年 2 月)で、この API をサ
ポートしているブラウザはない。ひとつもないのだ。つまり、少なくともマイクロデータのクライアントサ
イド API を実装したブラウザが出現するまでは、こちらの道は行き止まりということになる。
HTML を消費するもうひとつの主要なアプリケーションは、検索エンジンだ。検索エンジンが、人物に
関するマイクロデータのプロパティで何ができるというのだろう。次のようなことを想像してみてほしい。
サーチエンジンがページのタイトルとテキストの抜粋を表示するだけでなく、マイクロデータのような構造
化された情報を統合して表示できたらどうだろう。フルネーム、役職、勤務先、住所、そしてプロフィール
写真の小さなサムネイルも。読者の皆さんは、興味をそそられないだろうか。私は、とても興味がある。
Google は、リッチスニペット † の一環としてマイクロデータをサポートしている。Google の Web ク
ローラがページを解析し、http://data-vocabulary.org/Person 語彙のプロパティを見付けると、それらの
プロパティを解析してそれ以外のページデータとともに保存する。マイクロデータのプロパティが Google
からどのように「見える」のかを教えてくれる便利なツールも提供されている。先ほどの、マイクロデータ
を採用したサンプルの「about me」ページ(http://diveintohtml5.info/examples/person-plus-microdata.
html)でテストすると、以下の出力が得られる。
Item
Type: http://data-vocabulary.org/person
photo = http://diveintohtml5.info/examples/2000_05_mark.jpg
name = Mark Pilgrim
title = Developer advocate
affiliation = Google, Inc.
address = Item( 1 )
url = http://diveintomark.org/
url = http://www.google.com/profiles/pilgrim
url = http://www.reddit.com/user/MarkPilgrim
url = http://www.twitter.com/diveintomark
Item 1
Type: http://data-vocabulary.org/address
street-address = 100 Main Street
locality = Anytown
region = PA
postal-code = 19999
country-name = USA
ここには、すべての情報が揃っている。<img src> 属性から得られた photo プロパティ、<a href> 属性
のリストから得られた 4 つの URL すべて、そして住所のオブジェクト(「Item 1」としてリストされてい
る)と、その 5 つのサブプロパティすべてが表示されている。
では、Google はこの情報を何に使うのだろうか。それは場合によりけりだ。マイクロデータの表示方法
†
http://www.google.com/support/webmasters/bin/answer.py?hl=ja&answer=99170 を参照。
202
10 章 マイクロデータによるマークアップの拡張
図 10-1 マイクロデータで拡張された人物の検索結果のサンプル
に関して厳密な規則は存在しない。どのプロパティを表示するかは決まっていないし、まったく何も表示し
ないことだってあり得る。誰かが「Mark Pilgrim」を検索し、かつ Google がこの「about me」ページを
検索結果に含めようと判断し、かつ Google がそのページにもともとあったマイクロデータが表示する価値
のあるものだと判断した場合には、検索結果の表示は図 10-1 のようなものになるだろう。
最初の行、「About Mark Pilgrim」は、実際には <title> 要素に指定されていたページタイトルだ。これ
はそれほど驚くことでもない。Google はすべてのページについて同じことをしているからだ。しかし次の
行はすべて、われわれがこのページに追加したマイクロデータの注釈から直接得られた情報だ。「Anytowns
PA」 は、http://data-vocabulary.org/Address 語 彙 に し た が っ て マ ー ク ア ッ プ さ れ た 住 所 の 一 部 だ。
「Developer advocate」と「Google, Inc.」は http://data-vocabulary.org/Person 語彙の中の 2 つのプロ
パティ(それぞれ title と affiliation)になる。
これは、本当にすごいことだ。検索エンジンの会社と特別契約を結べるような大企業でなくても、検索エ
ンジンの結果表示をカスタマイズできるのだ。10 分もあれば、いくつか HTML 属性を追加して、すでに公
開しているデータに注釈を加えることができる。
マークアップ教授に質問
Q:ここに書いてあることを全部やりましたが、Google 検索の結果表示に反映されません。どうしてです
か?
A:「Google は、特定のページまたはサイトのマークアップが検索結果に使われることを保証していな
い†」。しかし、Google があなたの作成したマイクロデータの注釈を使わないと決めたとしても、別の検
索エンジンは使うかもしれない。その他の HTML5 の機能と同様に、マイクロデータは誰もが実装できる
オープンな標準だ。可能な限り多くのデータを提供するのは、あなたの仕事だ。それを使って何をするか
は、世界中のほかの人に決めてもらおう。びっくりするような結果が待っているかもしれない。
10.5 会社や組織のマークアップ
マイクロデータは、ひとつの語彙しか使えないわけではない。「about me」ページはいいものだが、たぶ
ん 1 ページだけあれば十分だろう。さらにマイクロデータを活用するために、会社や会社をマークアップ
してみよう。
私が作った、会社の一覧のサンプルページが、ここ(http://diveintohtml5.info/examples/organization.
†
http://www.google.com/support/webmas ters/bin/answer.py?hl=ja&answer=99170 を参照。
10.5 会社や組織のマークアップ
203
html)にある。まずはマイクロデータなしの、元の HTML マークアップを見てみよう。
<article>
<h1>Google, Inc.</h1>
<p>
1600 Amphitheatre Parkway<br>
Mountain View, CA 94043<br>
USA
</p>
<p>650-253-0000</p>
<p><a href="http://www.google.com/">Google.com</a></p>
</article>
このセクションで行う変更はすべて、オンラインで確認することができる。変更前が http://
diveintohtml5.info/examples/organization.html 、 変 更 後 が http://diveintohtml5.info/
examples/organization-plus-microdata.html だ。
短いが、これで十分だ。この会社に関するすべての情報は <article> 要素に含まれているので、まずそこ
から始めよう。
<article itemscope itemtype="http://data-vocabulary.org/Organization">
人物のマークアップと同じく、最も外側にある要素に itemscope 属性と itemtype 属性を設定する必要が
ある。この例では、最も外側の要素は <article> 要素だ。itemtype 属性は、これから使うマイクロデータ
語彙(この例では http://data-vocabulary.org/Organization)を宣言し、itemscope 属性は、子要素に設
定するプロパティはすべて、この語彙と関連付けられることを宣言している。
では、Organization 語彙には何が含まれているのだろうか。これは非常に単純明快だ。中にはすでに見
覚えのあるものも含まれている。表 10-3 に、関連するプロパティを示す。
最も外側の <article> 要素の中にある、マークアップの最初の部分は <h1> だ。この <h1> 要素には会社
名が含まれているので、ここに直接 itemprop="name" 属性を設定しよう。
表 10-3 Organization 語彙
プロパティ
説明
name
会社や組織の名前(例えば、「Initech」)
url
会社や組織のホームページへのリンク
address
会社や組織の所在地。サブプロパティとして street-address、locality、region、postalcode、および country-name を持つことができる。
tel
会社や組織の電話番号
geo
会社や組織の所在地の地理座標。常に latitude と longitude という、2 つのサブプロパ
ティを含む。
204
10 章 マイクロデータによるマークアップの拡張
<h1 itemprop="name">Google, Inc.</h1>
表 10-1 によれば、<h1> 要素には特別な取り扱いは必要ない。値は単純に <h1> 要素の内容となる。日本
語で言うと、「この会社の名前は『Google, Inc.』だ」という意味になる。
次に来るのは、住所だ。会社の住所をマークアップする方法は、人物の住所をマークアップした際とまっ
たく同じだ。まず、住所の最も外側の要素(この例では、<p> 要素)に itemprop="address" 属性を設定す
る。これで、これがこの組織の address プロパティであるという意味になる。しかし、この住所自体のプロ
パティはどうすればいいだろうか。これが独自のプロパティを持つ Address アイテムであることを示すた
めに、itemtype 属性と itemscope 属性を定義しておく必要がある。
<p itemprop="address" itemscope
itemtype="http://data-vocabulary.org/Address">
そして、ひとつひとつの情報のかたまりをダミーの <span> 要素で囲めば、それぞれの <span> 要素に適切
なプロパティ名(street-address、locality、region、postal-code、および country-name)を追加できる。
<p itemprop="address" itemscope
itemtype="http://data-vocabulary.org/Address">
<span itemprop="street-address">1600 Amphitheatre Parkway</span><br>
<span itemprop="locality">Mountain View</span>,
<span itemprop="region">CA</span>
<span itemprop="postal-code">94043</span><br>
<span itemprop="country-name">USA</span>
</p>
日本語で言うと、次のような意味になる。「この会社には所在地がある。番地は『1600 Amphitheatre
Parkway』だ。市町村名は『Mountain View』だ。州名は『CA』だ。郵便番号は『94043』だ。国名は
『USA』だ。」
次は、電話番号だ。電話番号は面倒なことで有名で、正確な構文は国によって違う。(さらに、別の国に
電話をかける場合には、話はもっと面倒になる。)この例では、米国の電話番号、つまり米国のどこかから
電話する場合の形式になっている。
<p itemprop="tel">650-253-0000</p>
(念のため注意しておくと、Address 語彙はその <p> 要素が閉じられたときにスコープ外になっている。
Organization 語彙で定義されたプロパティの世界に戻っているのだ。)
複数の電話番号(例えば、ひとつは米国内の顧客用、もうひとつはそれ以外の顧客用)を記述したいな
ら、それも可能だ。すべてのプロパティは、繰り返し指定できるからだ。ただ、ラベルを除く各電話番号が
それぞれ別の HTML 要素で囲まれるように気を付けてほしい。
10.5 会社や組織のマークアップ
205
<p>
US customers: <span itemprop="tel">650-253-0000</span><br>
UK customers: <span itemprop="tel">00 + 1* + 6502530000</span>
</p>
表 10-1 によれば、<p> 要素も <span> 要素も特別な取り扱いはされない。tel プロパティの値は、要素の
内容そのままになる。Organization マイクロデータ語彙は、電話番号をさらに部分部分に分割することは
しない。tel プロパティ全体は、単純なフリーフォームのテキストだ。エリアコードをカッコに入れて表示
したり、番号の区切りにダッシュではなくスペースを使ったりしたければ、そうしてもよい。マイクロデー
タを消費するクライアントが電話番号を解析する際には、完全に自力で行うことになる。
次は、これもなじみのあるプロパティ url だ。前のセクションで説明した、人物に URL を関連付ける場
合とまったく同じように、会社と URL を関連付けることができる。これはその会社のホームページでも、
連絡先ページでも、製品ページでも、何でもよい。その組織に関する、またはその組織からの、またはその
組織に属する URL であれば、itemprop="url" 属性でマークアップできる。
<p><a itemprop="url" href="http://www.google.com/">Google.com</a></p>
表 10-1 によれば、<a> 要素は特別な取り扱いをされる。値は href 属性であり、リンクテキストではない。
日本語で言うと、「この会社は http://www.google.com/ という URL と関連付けられている」という意味
になる。その関連がどのようなものであるかについては何も言っていないし、リンクテキスト「 Google.
com 」は含まれない。
最後に、位置情報についても触れておこう。いや、W3C の Geolocation API(6 章参照)のことではな
く、マイクロデータを使って会社の物理的な位置をマークアップする方法のことだ。
今までの実例はすべて、見えるデータのみを取り扱ってきた。つまり、会社名をマークアップしている
<h1> 要素に itemprop 属性を付加し、その見出しテキストが、会社の名前であると宣言した。あるいは、写
真を参照している <img> 要素に itemprop 属性を付加し、その画像が人物の写真であると宣言した。
しかし、位置情報を同じように取り扱うことはできない。その組織の正確な緯度と経度が(小数点以下第
4 位まで)書かれているテキストが存在しないからだ。実際には、マイクロデータを付加する前のサンプル
の組織ページには、まったく位置情報に関する記述が存在しない。Google Maps へのリンクはあるが、そ
のリンクの URL にも緯度と経度の座標は含まれていない。(同様の情報が、Google 独自のフォーマットで
含まれている。)たとえ、URL パラメータとして緯度と経度の座標を取るオンライン地図サービスが仮に
あったとしても、マイクロデータはその URL から緯度と経度を抽出する機能は持っていない。最初の URL
クエリパラメータが緯度で、2 番目の URL クエリパラメータが経度で、残りのクエリパラメータは無関係
だ、などと宣言することはできないのだ。
このような特殊な場合を取り扱うため、HTML5 では不可視データを注釈としてマイクロデータに加える
方法が提供されている。このテクニックは、あくまでも最後の手段として使用してほしい。必要なデータを
ページ上に表示できるなら、そのデータは人にも見えるように記すべきだ。機械のみが可読な不可視データ
は、すぐに陳腐化してしまう。どういうことかというと、可視テキストは更新しても、不可視データは更新
し忘れてしまいがちなのだ。これは思った以上によく起こることだし、あなた自身もそういう覚えがあるの
206
10 章 マイクロデータによるマークアップの拡張
ではないだろうか。
それでも、不可視データが必要となる場合はある。あなたの上司が本当に機械可読な位置情報を必要とし
ているが、理解不能な 6 桁の数字をページ上に置いて雑然とさせたくはないと思っているとしよう。その
場合、不可視データが唯一の選択肢になる。幸いなことに、不可視データは記述するテキストの直後に配置
することができる。そのため、後でこのページを見て表示されているテキストを更新した人が、その直後に
ある不可視データも更新する必要があることに気付いてくれるかもしれない。
この例では、その他すべての Organization プロパティが含まれるのと同じ <article> 要素の中にダミー
の <span> 要素を作成し、その <span> 要素の中に不可視の位置情報データを設定することになる。
<span itemprop="geo" itemscope
itemtype="http://data-vocabulary.org/Geo">
<meta itemprop="latitude" content="37.4149" />
<meta itemprop="longitude" content="-122.078" />
</span>
</article>
人物や組織の住所と同様に、位置情報はそれ独自の語彙の中で定義されている。したがって、この
<span> 要素には 3 つの属性が必要となる。
itemprop="geo"
この要素が、それを取り囲む組織の geo プロパティを表現していることを示している。
itemtype="http://data-vocabulary.org/Geo"
この要素のプロパティが準拠するマイクロデータ語彙を示している。
itemscope
この要素が、(itemtype 属性によって与えられる)独自の語彙を持つマイクロデータアイテムを
含む要素であることを示している。この要素のすべてのプロパティは、Geo 語彙(http://data-
vocabulary.org/Geo)のプロパティであって、それを取り囲んでいる Organization 語彙(http://
data-vocabulary.org/Organization)ではない。
この例は、「不可視データに注釈を加える方法は?」という質問の答にもなっている。そう、<meta> 要素
を使うのだ。HTML の以前のバージョンでは、ページの <head>(「3.4 <head> 要素」を参照)の中でしか
<meta> 要素は使えなかった。HTML5 では、どこでも <meta> 要素が使えるのだ。そして、これがその実例
だ。
<meta itemprop="latitude" content="37.4149" />
表 10-1 によれば、<meta> 要素は特別に取り扱われる。プロパティの値は、その content 属性となるのだ。
この属性が視覚的に表示されることはないので、どんな大量の不可視データがあっても完璧に対応できる。
10.6 イベントのマークアップ
207
しかし、大きな権限は大きな責任を伴う。この例での責任とは、この不可視データをその周りにある、表示
されているテキストと確実に合致させることだ。
Google リッチスニペットでは Organization 語彙を直接にはサポートしていないので、見栄えのよい検索
結果の表示をお見せできないのは残念だ。しかし、次に説明するイベントとレビューでは組織や会社の情報
が重要な意味を持つ。そして、Google リッチスニペットはイベントとレビューをサポートしているのだ。
10.6 イベントのマークアップ
いろいろな出来事のうち、前もって日時がわかっている出来事もある。その時間を正確に検索エンジンへ
伝えたくはないだろうか。そのためのマークアップがあるのだ。
まず、私の講演予定のサンプルスケジュール(http://diveintohtml5.info/examples/event.html)を見て
いくことにしよう。
<article>
<h1>Google Developer Day 2009</h1>
<img width="300" height="200"
src="http://diveintohtml5.info/examples/gdd-2009-prague-pilgrim.jpg"
alt="[Mark Pilgrim at podium]">
<p>
Google Developer Days are a chance to learn about Google
developer products from the engineers who built them. This
one-day conference includes seminars and "office hours"
on web technologies like Google Maps, OpenSocial, Android,
AJAX APIs, Chrome, and Google Web Toolkit.
</p>
<p>
<time datetime="2009-11-06T08:30+01:00">2009 November 6, 8:30</time>
&ndash;
<time datetime="2009-11-06T20:30+01:00">20:30</time>
</p>
<p>
Congress Center<br>
5th května 65<br>
140 21 Praha 4<br>
Czech Republic
</p>
<p><a href="http://code.google.com/intl/cs/events/developerday/2009/home.html">GDD/Prague home
page</a></p>
</article>
このセクションで行う変更はすべて、オンラインで確認することができる。変更前が http://
diveintohtml5.info/examples/event.html 、変更後が http://diveintohtml5.info/examples/
event-plus-microdata.html だ。
208
10 章 マイクロデータによるマークアップの拡張
イ ベ ン ト に 関 す る す べ て の 情 報 は <article> 要 素 に 含 ま れ て い る の で、 そ こ に itemtype 属 性 と
itemscope 属性を設定すればよい。
<article itemscope itemtype="http://data-vocabulary.org/Event">
Event 語彙の URL は http://data-vocabulary.org/Event で、ここには語彙のプロパティを説明する表も
掲載されている。定義されているプロパティは、表 10-4 のとおりだ。
表 10-4 Event 語彙
プロパティ
説明
summary
イベントの名前
url
イベントの詳細ページへのリンク
location
イベントの場所。オプションとして、組織(「10.5 組織のマークアップ」を参照)または
人物(「10.4 人物のマークアップ」を参照)を入れ子にして表現することもできる。
description
イベントの説明
startDate
イベントの開始日時(ISO 日付フォーマット)
endDate
イベントの終了日時(ISO 日付フォーマット)
duration
イベントの期間(ISO 日付フォーマット)
eventType
イベントの種類(例えば、「コンサート」や「講演」)。これはフリーフォームの文字列で、
列挙型の属性ではない。
geo
場所の地理座標。常に latitude と longitude という、2 つのサブプロパティを含む。
photo
イベントに関係する写真または画像へのリンク。
イベントの名前は <h1> 要素に含まれている。表 10-1 によれば、<h1> 要素には特別な取り扱いは必要な
い。プロパティの値は単純に <h1> 要素の内容テキストとなる。したがって、この <h1> 要素にイベントの名
前が含まれていると宣言するには、itemprop 属性を追加するだけでよい。
<h1 itemprop="summary">Google Developer Day 2009</h1>
日本語で言うと、「このイベントの名前は『Google Developer Day 2009』だ」という意味になる。
このイベントの記述には写真が含まれていて、これは photo プロパティによってマークアップできる。期
待通り、その写真はすでに <img> 要素によってマークアップされている。Person 語彙の photo プロパティ
(「10.3 マイクロデータのデータモデル」を参照)と同様に、Event の photo プロパティも URL だ。表 10-1
によれば、<img> 要素に指定されたプロパティの値はその src 属性なので、この <img> 要素に itemprop 属
性を設定するだけでよい。
<img itemprop="photo" width="300" height="200"
src="http://diveintohtml5.info/examples/gdd-2009-prague-pilgrim.jpg"
alt="[Mark Pilgrim at podium]">
10.6 イベントのマークアップ
209
日 本 語 で 言 う と、「 こ の イ ベ ン ト の 写 真 は http://diveintohtml5.info/examples/gdd-2009-prague-
pilgrim.jpg にある」という意味になる。
次は、イベントについての長い説明文で、これは 1 パラグラフ分のフリーフォームのテキストだ。
<p itemprop="description">Google Developer Days are a chance to learn about Google developer
products from the engineers who built them. This one-day conference includes seminars and "office
hours" on web technologies like Google Maps, OpenSocial, Android, AJAX APIs, Chrome, and Google Web
Toolkit.</p>
次はちょっと目新しいものだ。イベントは通常、特定の日付と時間に始まり、終わる。HTML5 では、日
付と時刻は <time> 要素によってマークアップされる(「3.9 日付と時間」を参照)ので、すでにここではそ
うなっている。問題は、これらの <time> 要素にどうやってマイクロデータを与えればいいのか、というこ
とだ。表 10-1 をもう一度見てみると、<time> 要素は特別に取り扱われることがわかる。<time> 要素に指
定されたプロパティの値は、datetime 属性の値だ。そして Event 語彙の startDate および endDate プロパ
ティは、<time> 要素の datetime 属性と同じく、ISO 形式の日時なのだ。ここでも、HTML の要素が持つ
意味と、このマイクロデータ語彙の意味とがうまくかみ合っていることがわかる。開始日時と終了日時をマ
イクロデータとしてマークアップする方法は、以下のとおり簡単だ。
1.
まず、HTML を正しく使う(<time> 要素を使って日付と時間をマークアップする)。
2.
itemprop 属性を追加する。
<p>
<time itemprop="startDate" datetime="2009-11-06T08:30+01:00">2009 November 6, 8:30</time>
&ndash;
<time itemprop="endDate" datetime="2009-11-06T20:30+01:00">20:30</time>
</p>
日本語で言うと、「このイベントは 2009 年 11 月 6 日の午前 8 時 30 分に始まり、2009 年 11 月 6 日の 20
時 30 分に終わる(プラハ時間、GMT+1)」という意味になる。
次は location プロパティだ。Event 語彙の定義によれば、これは Organization か Address のどちら
かだ。この例では、イベントはプラハの Congress Center という会議専門の施設で行われる。これを
Organization としてマークアップすれば、施設の名前と住所をいっぺんに指定できるわけだ。
まず、住所を含む <p> 要素をイベントの location プロパティとして宣言し、そしてこの要素自体が
http://data-vocabulary.org/Organization 語彙に準拠したマイクロデータのアイテムでもあることを宣言
する。
<p itemprop="location" itemscope
itemtype="http://data-vocabulary.org/Organization">
次に、組織の名前をダミーの <span> 要素で囲み、その <span> 要素に itemprop 属性を設定することによ
210
10 章 マイクロデータによるマークアップの拡張
り、組織の名前をマークアップする。
<span itemprop="name">Congress Center</span><br>
"name" は、Event 語 彙 で は な く、Organization 語 彙 中 の プ ロ パ テ ィ を 定 義 し て い る。<p> 要 素 が
Organization プロパティのスコープの始まりを定義しており、その <p> 要素はまだ </p> タグによって閉じ
られていないからだ。ここで定義するマイクロデータのプロパティはすべて、最も近いスコープが設定され
た語彙のものになる。入れ子になった語彙は、スタックに似ている。まだスタックをポップしていないの
で、まだ Organization のプロパティが生きているわけだ。
それどころかさらに、3 番目の語彙をスタックにつむことになる。Event の、Organization の、Address
だ。
<span itemprop="address" itemscope
itemtype="http://data-vocabulary.org/Address">
ここでも、アドレスの部分部分を別個のマイクロデータのプロパティとしてマークアップしたいので、そ
の数だけ itemprop 属性を付加するためのダミーの <span> 要素が必要となる(もう一度説明を読み返した
い人は、人物の住所をマークアップする方法(「10.4 人物のマークアップ」を参照)や、組織の住所をマー
クアップする方法(「10.5 組織のマークアップ」を参照)に戻ってみてほしい)。
<span
<span
<span
<span
itemprop="street-address">5th května 65</span><br>
itemprop="postal-code">140 21</span>
itemprop="locality">Praha 4</span><br>
itemprop="country-name">Czech Republic</span>
これで住所のプロパティは終わりなので、Address スコープを開始した <span> 要素を閉じて、スタック
をポップする。
</span>
また、組織のプロパティも終わりなので、Organization スコープを開始した <p> 要素を閉じて、再度ス
タックをポップする。
</p>
これで、Event のプロパティ定義に戻ってきた。次のプロパティは、イベントの物理的な位置を示す
geo だ。これは前のセクションで組織の物理的な位置をマークアップする際に使ったのと同じ Geo 語彙を
使用する。コンテナとして <span> 要素を挿入し、これに itemtype 属性と itemscope 属性を設定する。こ
の <span> 要素の内部には 2 個の <meta> 要素を挿入する。1 個は latitude プロパティのため、もう 1 個は
longitude プロパティのためだ。
10.6 イベントのマークアップ
211
<span itemprop="geo" itemscope itemtype="http://data-vocabulary.org/Geo">
<meta itemprop="latitude" content="50.047893" />
<meta itemprop="longitude" content="14.4491" />
</span>
Geo プロパティを含む <span> を閉じたので、ここで Event のプロパティ定義に戻った。最後のプロパ
ティは url プロパティで、これはもうおなじみだろう。イベントに URL を関連付ける方法は、人物に URL
を関連付ける方法(「10.4 人物のマークアップ」を参照)や組織に URL を関連付ける方法(「10.5 組織の
マークアップ」を参照)と同じだ。HTML を正しく使っていれば(ハイパーリンクを <a href> でマーク
アップしていれば)、単純に itemprop 属性を設定するだけで、そのハイパーリンクをマイクロデータの url
プロパティであると宣言できることになる。
<p>
<a itemprop="url" href="http://code.google.com/intl/cs/events/developerday/2009/home.html">
GDD/Prague home page
</a>
</p>
</article>
サンプルのイベントページ(http://diveintohtml5.info/examples/event.html)には、モントリオールの
ConFoo カンファレンスでの筆者の講演予定という、もうひとつのイベントが載っている。繰り返しになる
ので、そのマークアップを 1 行ずつ説明することは控えておく。基本的にはプラハでのイベントとまった
く同じで、Geo アイテムと Address アイテムが入れ子になった Event アイテムだ。ここで 2 番目のイベン
トについて触れたのは、ひとつのページに複数のイベントを載せて、それぞれマイクロデータでマークアッ
プできることを示すためだ。
10.6.1 Google リッチスニペット、ふたたび
Google リ ッ チ ス ニ ペ ッ ト テ ス ト ツ ー ル に よ れ ば、 こ の サ ン プ ル の イ ベ ン ト 一 覧 ペ ー ジ(http://
diveintohtml5.info/examples/event-plus-microdata.html)から Google のクローラが取り込む情報は、以
下のとおりだ。
Item
Type: http://data-vocabulary.org/Event
summary = Google Developer Day 2009
eventType = conference
photo = http://diveintohtml5.info/examples/gdd-2009-prague-pilgrim.jpg
description = Google Developer Days are a chance to learn about
Google developer products from the engineers who built them.
This one-day conference includes seminars and office hours
on web technologies
like Goo...
10 章 マイクロデータによるマークアップの拡張
212
startDate = 2009-11-06T08:30+01:00
endDate = 2009-11-06T20:30+01:00
location = Item(__1)
geo = Item(__3)
url = http://code.google.com/intl/cs/events/developerday/2009/home.html
Item
Id: __1
Type: http://data-vocabulary.org/Organization
name = Congress Center
address = Item(__2)
Item
Id: __2
Type: http://data-vocabulary.org/Address
street-address = 5th května 65
postal-code = 140 21
locality = Praha 4
country-name = Czech Republic
Item
Id: __3
Type: http://data-vocabulary.org/Geo
latitude = 50.047893
longitude = 14.4491
これを見てわかるように、マイクロデータとして追加した情報はすべて表示されている。異なるアイテム
のプロパティには内部 ID(Item(__1)、Item(__2) など)が付与されているが、これはマイクロデータの仕
様の一部ではない。入れ子になったアイテムとそのプロパティのグループを示しつつ、サンプル出力をリニ
アライズするために Google のテストツールが採用している、ただの仕組みだ。
それでは、このサンプルページは Google の検索結果にどのように反映されるのだろうか。(もう一度言っ
ておくが、これは単なる例だ。Google はいかなるときにもその検索結果のフォーマットを変更する可能性
があり、そして Google がマイクロデータのマークアップに留意するということにすら何の保証もない。)
たぶん図 10-2 のように見えるだろう。
ページタイトルと自動生成された要約テキストの後に、先ほどページに追加したマイクロデータマーク
図 10-2 マイクロデータで拡張されたイベント一覧の検索結果のサンプル
10.7 レビューをマークアップする
213
アップを使い、Google はイベントの小さな表を表示する。「Fri, Nov 6」という日付のフォーマットに注目
してほしい。先ほど使ったのは、2009-11-06T08:30+01:00 と 2009-11-06T20:30+01:00 という、2 個の完全
修飾(fully qualified)された ISO フォーマットの文字列だった。Google はこれらの日時が同じ日付である
と認識し、わかりやすく 1 個の日付で表示している。
次に、物理的な住所を見てほしい。Google は詳細な番地を表示せず、施設名+市町村名+国名だけを表
示している。これは、先ほど住所を 5 個のサブプロパティ(name、street-address、locality、region、
および country-name)に分割し、それぞれ別のマイクロデータプロパティとしてマークアップしたために
可能となったことだ。Google はこれを利用して、短縮したアドレスを表示しているのだ。同じマイクロ
データのマークアップでも、受け手が違うと表示する項目や表示方法に違った選択を行う可能性がある。そ
の選択にはよいも悪いもない。あなたの仕事は、可能な限りたくさんのデータを、可能な限り正確に提供す
ることだ。それをどう解釈するかは、世界中のほかの人に決めてもらおう。
10.7 レビューをマークアップする
Web を(そして検索結果の一覧も)よりよくマークアップする、もうひとつの例をお見せしよう。店舗
や製品のレビューだ。
この短いレビューは、私の家の近くのお気に入りのピザ屋について書いたものだ。(ちなみに、これは実
在するレストランなので、ノースカロライナ州の Apex に来たときにはぜひ行ってみてほしい。)元のマー
クアップ(http://diveintohtml5.info/examples/review.html)を見てみよう。
<article>
<h1>Anna's Pizzeria</h1>
<p> ★★★★☆ (4 stars out of 5)</p>
<p>New York-style pizza right in historic downtown Apex</p>
<p>
Food is top-notch. Atmosphere is just right for a "neighborhood
pizza joint." The restaurant itself is a bit cramped; if you're
overweight, you may have difficulty getting in and out of your
seat and navigating between other tables. Used to give free
garlic knots when you sat down; now they give you plain bread
and you have to pay for the good stuff. Overall, it's a winner.
</p>
<p>
100 North Salem Street<br>
Apex, NC 27502<br>
USA
</p>
<p>- reviewed by Mark Pilgrim, last updated March 31, 2010</p>
</article>
214
10 章 マイクロデータによるマークアップの拡張
このセクションで行う変更はすべて、オンラインで確認することができる。変更前が http://
diveintohtml5.info/examples/review.html 、変更後が http://diveintohtml5.info/examples/
review-plus-microdata.html だ。
このレビューは <article> 要素に囲まれているので、そこに itemtype 属性と itemscope 属性を設定すれ
ばよい。これが、ここで使う語彙の名前空間の URL だ。
<article itemscope itemtype="http://data-vocabulary.org/Review">
Review 語彙ではどのようなプロパティが使えるのだろうか。表 10-5 を見てほしい。
表 10-5 Review 語彙
プロパティ
説明
itemreviewed
レビューされるアイテムの名前。製品、サービス、店舗など。
rating
そ の ア イ テ ム の 品 質 を 1 ∼ 5 の 数 値 で 評 価 し た 結 果。http://data-vocabulary.org/
Rating を使った Rating 語彙を入れ子にすれば、非標準的な尺度で評価できる。
reviewer
レビューを書いた人の名前
dtreviewed
そのアイテムがレビューされた日付(ISO 日付フォーマット)
summary
レビューの短いまとめ
description
レビュー本体。
最初のプロパティは簡単だ。itemreviewed は単なるテキストで、<h1> 要素で囲まれているので、そこに
itemprop 属性を設定すればよい。
<h1 itemprop="itemreviewed">Anna's Pizzeria</h1>
実際の評価についてはいったん飛ばして、最後に説明することにする。
次の 2 つのプロパティも単純明快だ。summary プロパティはレビューの短い説明で、description プロパ
ティはレビュー本体だ。
<p itemprop="summary">New York-style pizza right in historic downtown Apex</p>
<p itemprop="description">
Food is top-notch. Atmosphere is just right for a "neighborhood
pizza joint." The restaurant itself is a bit cramped; if you're
overweight, you may have difficulty getting in and out of your
seat and navigating between other tables. Used to give free
garlic knots when you sat down; now they give you plain bread
and you have to pay for the good stuff. Overall, it's a winner.
</p>
location および geo プロパティについては、前に説明したとおりだ(人物の住所をマークアップするセ
10.7 レビューをマークアップする
215
クション、組織の住所をマークアップするセクション、そして位置情報をマークアップするセクションを読
み返してほしい)。
<p itemprop="location" itemscope
itemtype="http://data-vocabulary.org/Address">
<span itemprop="street-address">100 North Salem Street</span><br>
<span itemprop="locality">Apex</span>,
<span itemprop="region">NC</span>
<span itemprop="postal-code">27502</span><br>
<span itemprop="country-name">USA</span>
</p>
<span itemprop="geo" itemscope
itemtype="http://data-vocabulary.org/Geo">
<meta itemprop="latitude" content="35.730796" />
<meta itemprop="longitude" content="-78.851426" />
</span>
最後の行は、おなじみの問題を含んでいる。ひとつの要素に、2 種類の情報が含まれているのだ。レビュ
アーの名前は Mark Pilgrim で、レビューの日付は March 31, 2010 だ。これを 2 つの異なるプロパティと
してマークアップするには、どうすればよいだろうか。いつものように、これらをそれぞれ独自の要素で囲
み(「10.4 人物のマークアップ」を参照)、そして各要素に itemprop 属性を設定すればよい。実際には、こ
の例の日付はそもそも <time> 要素でマークアップすべきなので、そこへ itemprop 属性を設定するのが自
然だ。レビュアーの名前は、ダミーの <span> 要素で囲めばよい。
<p>
<span itemprop="reviewer">Mark Pilgrim</span>, last updated
<time itemprop="dtreviewed" datetime="2010-03-31">
March 31, 2010
</time>
</p>
</article>
さて、評価のところへ戻ろう。レビューをマークアップする際、最も面倒なのが評価だ。デフォルトで
は、Review 語彙の評価は 1 ∼ 5 の尺度になっていて、1 が「最低」、5 が「最高」だ。別の尺度を使いたけ
れば、もちろんそれも可能だ。しかしまず、デフォルトの尺度について説明しよう。
<p> ★★★★☆ (<span itemprop="rating">4</span> stars out of 5)</p>
デフォルトと同じ 1 ∼ 5 の尺度を使っていれば、マークアップする必要のあるプロパティは尺度そのも
の(この例では 4)だけだ。しかし、別の尺度を使いたい場合はどうするかというと、実際に使う尺度の上
限と下限を宣言する必要が出てくる。例えば、0 ∼ 10 の尺度を使いたかったとすると、itemprop="rating"
を宣言するところまでは同じだが、評価の値を直接書くのではなく、http://data-vocabulary.org/Rating
216
10 章 マイクロデータによるマークアップの拡張
を使った Rating 語彙を入れ子にしてカスタム尺度の上限と下限、そしてその尺度での実際の評価を宣言す
ることになる。
<p itemprop="rating" itemscope
itemtype="http://data-vocabulary.org/Rating">
★★★★★★★★★☆
(<span itemprop="value">9</span> on a scale of
<span itemprop="worst">0</span> to
<span itemprop="best">10</span>)
</p>
日本語で言うと、「私がレビューしたこの製品は、0 ∼ 10 段階で 9 の評価だ」という意味になる。
レビューのマイクロデータが検索結果の一覧に影響を与える可能性については、まだ説明していなかっ
たと思う。実際、その可能性はあるのだ。以下に示すのは、マイクロデータで拡張された私のレビュー
(http://www.google.com/webmasters/tools/richsnippets?url=//diveintohtml5.info/examples/review-
plus-microdata.html)から、Google リッチスニペットツールが抽出した「生データ」だ。
Item
Type: http://data-vocabulary.org/Review
itemreviewed = Anna's Pizzeria
rating = 4
summary = New York-style pizza right in historic downtown Apex
description = Food is top-notch. Atmosphere is just right ...
address = Item(__1)
geo = Item(__2)
reviewer = Mark Pilgrim
dtreviewed = 2010-03-31
Item
Id: __1
Type: http://data-vocabulary.org/Organization
street-address = 100 North Salem Street
locality = Apex
region = NC
postal-code = 27502
country-name = USA
Item
Id: __2
Type: http://data-vocabulary.org/Geo
latitude = 35.730796
longitude = -78.851426
10.8 参考文献
217
図 10-3 マイクロデータで拡張されたレビューの検索結果のサンプル
図 10-3 に、私のレビューが検索結果の一覧にどのように表示されるか(Google の気まぐれや、月の満ち
欠けなどなどによって異なる可能性はあるが)を示す。
マークアップはあまり感心したものではないが、しかしクールなものであることは確かだ。
10.8 参考文献
マイクロデータ関連:
●
マイクロデータのライブな遊び場
http://foolip.org/microdatajs/live/
●
HTML5 マイクロデータの仕様
http://whatwg.org/html5#microdata
Google リッチスニペット関連:
●
「リッチ スニペットと構造化データについて」
http://www.google.com/support/webmasters/bin/answer.py?hl=ja&answer=99170
●
「人物」
http://www.google.com/support/webmasters/bin/answer.py?hl=ja&answer=146646
●
「会社や組織」
http://www.google.com/support/webmasters/bin/answer.py?hl=ja&answer=146861
●
「イベント」
http://www.google.com/support/webmasters/bin/answer.py?hl=ja&answer=164506
●
「レビュー」
http://www.google.com/support/webmasters/bin/answer.py?hl=ja&answer=146645
●
「レビューの評価」
http://www.google.com/support/webmasters/bin/answer.py?hl=ja&answer=172705
●
Google リッチスニペットテストツール
http://www.google.com/webmasters/tools/richsnippets
10 章 マイクロデータによるマークアップの拡張
218
●
Google リッチスニペットに関するコツと技
http://knol.google.com/k/google-rich-snippets-tips-and-tricks
219
付録
(ほぼ)アルファベット順の
HTML5 機能検出方法
当惑している人は、2 章へ戻って概念の紹介をもう一度読み直してほしい。また、すべてを識別してくれ
るライブラリが必要なら、Modernizr(http://www.modernizr.com)をお勧めする。
A.1 要素の一覧
<audio>
http://whatwg.org/html5#audio
return !!document.createElement('audio').canPlayType;
<audio> MP3 フォーマット
http://en.wikipedia.org/wiki/MP3
var a = document.createElement('audio');
return !!(a.canPlayType && a.canPlayType('audio/mpeg;').replace(/no/, ''));
<audio> Vorbis フォーマット
http://en.wikipedia.org/wiki/Vorbis
var a = document.createElement('audio');
return !!(a.canPlayType && a.canPlayType('audio/ogg;
codecs="vorbis"').replace(/no/, ''));
<audio> WAV フォーマット
var a = document.createElement('audio');
return !!(a.canPlayType && a.canPlayType('audio/wav;
codecs="1"').replace(/no/, ''));
http://en.wikipedia.org/wiki/WAV
220
付録 (ほぼ)アルファベット順の HTML5 機能検出方法
<audio> AAC フォーマット
http://en.wikipedia.org/wiki/Advanced_Audio_Coding
var a = document.createElement('audio');
return !!(a.canPlayType && a.canPlayType('audio/mp4;
codecs="mp4a.40.2"').replace(/no/, ''));
<canvas>
4 章を参照
return !!document.createElement('canvas').getContext;
<canvas> テキスト API
「4.5 テキスト」を参照
var c = document.createElement('canvas');
return c.getContext && typeof c.getContext('2d').fillText == 'function';
<command>
http://whatwg.org/html5#the-command
return 'type' in document.createElement('command');
<datalist>
http://whatwg.org/html5#the-datalist-element
return 'options' in document.createElement('datalist');
<details>
http://whatwg.org/html5#the-details-element
return 'open' in document.createElement('details');
<device>
http://whatwg.org/html5#devices
return 'type' in document.createElement('device');
<form> 制約バリデーション
http://whatwg.org/html5#constraints
return 'noValidate' in document.createElement('form');
<iframe sandbox>
return 'sandbox' in document.createElement('iframe');
http://blog.whatwg.org/whats-next-in-html-episode-2-sandbox
A.1 要素の一覧
<iframe srcdoc>
221
http://blog.whatwg.org/whats-next-in-html-episode-2-sandbox
return 'srcdoc' in document.createElement('iframe');
<input autofocus>
「9.3 フィールドへのオートフォーカス」を参照
return 'autofocus' in document.createElement('input');
<input placeholder>
「9.2 プレースホルダ」を参照
return 'placeholder' in document.createElement('input');
<input type="color">
「9.10 カラーピッカー」を参照
var i = document.createElement('input');
i.setAttribute('type', 'color');
return i.type !== 'text';
<input type="email">
「9.4 メールアドレス」を参照
var i = document.createElement('input');
i.setAttribute('type', 'email');
return i.type !== 'text';
<input type="number">
「9.6 スピンボックスによる数値の入力」を参照
var i = document.createElement('input');
i.setAttribute('type', 'number');
return i.type !== 'text';
<input type="range">
「9.7 スライダによる数値の入力」を参照
var i = document.createElement('input');
i.setAttribute('type', 'range');
return i.type !== 'text';
<input type="search">
var i = document.createElement('input');
i.setAttribute('type', 'search');
return i.type !== 'text';
「9.9 検索ボックス」を参照
222
付録 (ほぼ)アルファベット順の HTML5 機能検出方法
<input type="tel">
http://whatwg.org/html5#telephone-state
var i = document.createElement('input');
i.setAttribute('type', 'tel');
return i.type !== 'text';
<input type="url">
「9.5 Web アドレス」を参照
var i = document.createElement('input');
i.setAttribute('type', 'url');
return i.type !== 'text';
<input type="date">
「9.8 デートピッカー」を参照
var i = document.createElement('input');
i.setAttribute('type', 'date');
return i.type !== 'text';
<input type="time">
「9.8 デートピッカー」を参照
var i = document.createElement('input');
i.setAttribute('type', 'time');
return i.type !== 'text';
<input type="datetime">
「9.8 デートピッカー」を参照
var i = document.createElement('input');
i.setAttribute('type', 'datetime');
return i.type !== 'text';
<input type="datetime-local">
「9.8 デートピッカー」を参照
var i = document.createElement('input');
i.setAttribute('type', 'datetime-local);
return i.type !== 'text';
<input type="month">
var i = document.createElement('input');
i.setAttribute('type', 'month');
return i.type !== 'text';
「9.8 デートピッカー」を参照
A.1 要素の一覧
<input type="week">
223
「9.8 デートピッカー」を参照
var i = document.createElement('input');
i.setAttribute('type', 'week');
return i.type !== 'text';
<meter>
http://whatwg.org/html5#the-meter-element
return 'value' in document.createElement('meter');
<output>
http://whatwg.org/html5#the-output-element
return 'value' in document.createElement('output');
<progress>
http://whatwg.org/html5#the-progress-element
return 'value' in document.createElement('progress');
<time>
http://whatwg.org/html5#the-time-element-0
return 'valueAsDate' in document.createElement('time');
<video>
5 章を参照
return !!document.createElement('video').canPlayType;
<video> キャプション
http://whatwg.org/html5#websrt
return 'track' in document.createElement('track');
<video poster>
http://whatwg.org/html5#attr-video-poster
return 'poster' in document.createElement('video');
<video> WebM フォーマット
http://www.webmproject.org
var v = document.createElement('video');
return !!(v.canPlayType && v.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/no/, ''));
<video> H.264 フォーマット
「5.3.1 H.264」を参照
var v = document.createElement('video');
return !!(v.canPlayType && v.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"').replace(/no/, ''));
224
付録 (ほぼ)アルファベット順の HTML5 機能検出方法
<video> Theora フォーマット
「5.3.2 Theora」を参照
var v = document.createElement('video');
return !!(v.canPlayType && v.canPlayType('video/ogg; codecs="theora, vorbis"').replace(/no/, ''));
contentEditable
http://whatwg.org/html5#contenteditable
return 'isContentEditable' in document.createElement('span');
Cross-document messaging
→クロスドキュメントメッセージング
Drag and Drop
→ドラッグアンドドロップ
File API
http://dev.w3.org/2006/webapi/FileAPI/
return typeof FileReader != 'undefined';
Geolocation
6 章を参照
return !!navigator.geolocation;
History
http://whatwg.org/html5#the-history-interface
return !!(window.history && window.history.pushState &&
window.history.popState);
IndexedDB
http://www.w3.org/TR/IndexedDB/
return !!window.indexedDB;
Local Strage
→ローカルストレージ
Microdata(マイクロデータ)
return !!document.getItems;
http://bit.ly/dBGnqr
A.1 要素の一覧
225
Offline Web Application
→オフライン Web アプリケーション
Server-sent イベント
http://dev.w3.org/html5/eventsource/
return typeof EventSource !== 'undefined';
Session Strage(セッションストレージ)
http://dev.w3.org/html5/webstorage/
try {
return ('sessionStorage' in window) && window['sessionStorage'] !== null;
} catch(e) {
return false;
}
SVG
http://www.w3.org/TR/SVG/
return !!(document.createElementNS && document.createElementNS
('http://www.w3.org/2000/svg', 'svg').createSVGRect);
SVG text/html
→インライン SVG
Undo
http://whatwg.org/html5#undo
return typeof UndoManager !== 'undefined';
WebSocket API
http://dev.w3.org/html5/websockets/
return !!window.WebSocket;
Web SQL データベース
http://dev.w3.org/html5/webdatabase/
return !!window.openDatabase;
Web Workers
return !!window.Worker;
http://www.whatwg.org/specs/web-workers/current-work/
226
付録 (ほぼ)アルファベット順の HTML5 機能検出方法
W3C Widgets
return typeof widget !== 'undefined';
XMLHttpRequest: クロスドメインリクエスト
return "withCredentials" in new XMLHttpRequest;
XMLHttpRequest: フォームデータ送信
return !!window.FormData;
XMLHttpRequest: "upload" progress イベント
return "upload" in new XMLHttpRequest;
インライン SVG
http://hacks.mozilla.org/2010/05/firefox-4-the-html5-parser-inline-svg-speed-and-more/
var e = document.createElement('div');
e.innerHTML = '<svg></svg>';
return !!(window.SVGSVGElement && e.firstChild instanceof window.SVGSVGElement);
オフライン Web アプリケーション
8 章を参照
return !!window.applicationCache;
クロスドキュメントメッセージング
http://whatwg.org/html5#web-messaging
return !!window.postMessage;
ドラッグアンドドロップ
http://whatwg.org/html5#dnd
return 'draggable' in document.createElement('span');
ローカルストレージ
try {
return 'localStorage' in window && window['localStorage'] !== null;
} catch(e) {
return false;
}
http://dev.w3.org/html5/webstorage/
A.2 参考文献
A.2 参考文献
仕様および標準:
●
HTML5
http://whatwg.org/html5
●
Geolocation API
http://www.w3.org/TR/geolocation-API/
●
Server-sent Events
http://dev.w3.org/html5/eventsource/
●
Indexed Database API
http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html
●
WebSocket API
http://dev.w3.org/html5/websockets/
●
Web SQL Database
http://www.w3.org/TR/webdatabase/
●
Web Storage
http://dev.w3.org/html5/webstorage/
●
Web Workers
http://whatwg.org/ww
●
Widgets
http://www.w3.org/TR/widgets/
●
XMLHttpRequest Level 2
http://www.w3.org/TR/XMLHttpRequest2/
JavaScript ライブラリ:
●
HTML5 検出ライブラリ、Modernizr
http://www.modernizr.com
227
229
索 引
数字・記号
<form> .............................................................................169, 220
200............................................................................................164
<head> .......................................................................................38
304............................................................................................164
<header>..............................................................................46, 52
404............................................................................................163
<hgroup> .............................................................................46, 53
410............................................................................................163
<html>......................................................................................190
5MB .........................................................................................150
manifest 属性 ...................................................................158
.appcache ................................................................................158
ルート要素 .........................................................................37
.avi ..............................................................................................92
<iframe>
.flv ..............................................................................................92
<iframe sandbox> ...........................................................220
.htaccess ..................................................................................158
<iframe srcdoc> ..............................................................221
デバッグ ...........................................................................165
<input> .................................................................................29, 30
.m4v ...........................................................................................92
<input autofocus>............................................................221
.manifest ..................................................................................158
<input placeholder> ........................................................221
.mp4 ...........................................................................................92
<input required> .............................................................186
.ogv ............................................................................................92
<input type=" ">
.webm ........................................................................................92
<input type="color"> .......................................................221
<!DOCTYPE html>...................................................................37
<input type="date"> ........................................................222
<a>............................................................................................200
<input type="datetime"> .................................................222
<article>...............................................................................46, 54
<input type="datetime-local"> ........................................222
ダミーの要素 .....................................................................49
<input type="email"> ......................................................221
<aside>.......................................................................................46
<input type="month"> ....................................................222
<audio> ....................................................................................219
<input type="number"> ..................................................221
<body> .....................................................................................190
<input type="range"> ......................................................221
<canvas> ............................................................................65, 220
<input type="search"> ....................................................221
テキスト API....................................................................220
<input type="tel"> ...........................................................222
→ Canvas も参照
<input type="time"> ........................................................222
<command> ............................................................................220
<input type="url"> ...........................................................222
<datalist> .................................................................................220
<input type="week">.......................................................223
<details> ..................................................................................220
<link> .........................................................................................41
<device>...................................................................................220
<mark> ......................................................................................47
<footer> ...............................................................................46, 60
<meta> .......................................................................................39
230
索引
<nav>....................................................................................46, 59
D
<section> ...................................................................................45
datetime 属性 ............................................................................57
<source> ..................................................................................126
display: inline ............................................................................48
<time> ..................................................................................47, 57
DOCTYPE.................................................................................35
<video> ..............................................................................21, 223
Document Object Model → DOM
サポート状況 .....................................................................91
dojox.storage ..........................................................................146
ビデオの埋め込み ............................................................124
DOM..........................................................................................17
A
DOM ストレージ ............................................................147
DOM イベント ................................................................162
AAC............................................................................................97
Drag and Drop →ドラッグアンドドロップ
AAC-LC プロファイル ..............................................................97
drawImage() メソッド .............................................................80
AAC フォーマット ..................................................................220
Advanced Audio Coding ..........................................................97
E
almost standards ......................................................................36
enableHighAccuracy プロパティ ..........................................138
Andrew ........................................................................................7
excanvas.js ................................................................................83
Android............................................................................129, 137
ExplorerCanvas ........................................................................83
application/xhtml+xml ............................................................10
applicationCache プロパティ ..................................................27
F
Atom フィード ..........................................................................42
FALLBACK セクション .................................................160, 161
Audio Video Interleave ............................................................92
feed autodiscovery ...................................................................42
autofocus 属性 ..................................................................31, 171
ffmpeg .....................................................................................122
autoplay 属性...........................................................................125
ffmpeg2theora.................................................................114
fillStyle プロパティ ...................................................................67
C
Firefogg ...................................................................................106
Canvas
Firefox .............................................................................9, 12, 14
Canvas API ........................................................................19
Geolocation API ..............................................................134
Canvas テキスト API ........................................................20
IndexedDB ......................................................................154
画像のサポート状況 ..........................................................80
localStorage インタフェース .........................................155
座標 ....................................................................................68
OpenSearch 文書 ..............................................................45
サポート状況 .....................................................................65
WebM.................................................................................23
シェープ .............................................................................66
不明な要素 .........................................................................47
テキスト .............................................................................73
Flash
パス ....................................................................................69
Flash ストレージ .............................................................146
リセット .............................................................................67
Flash ビデオ ......................................................................92
Chrome
font プロパティ .........................................................................74
IndexedDB ......................................................................154
Ogg ビデオ ......................................................................114
G
WebM...........................................................................23, 98
Gears .......................................................................................139
ビデオ .................................................................................98
ストレージ .......................................................................146
Content-Type ..............................................................................1
geo.js .......................................................................................140
Cookie .....................................................................................145
実例 ..................................................................................141
Cross-document messaging
Geolocation ...............................................................27, 133, 224
→クロスドキュメントメッセージング
ワーキンググループ ..........................................................28
CSS ............................................................................................48
Geolocation API................................................................28, 133
索引
231
エラー処理 .......................................................................136
HTTP1.0 ......................................................................................4
サポート状況 ...................................................................134
HyTime .......................................................................................9
利用方法 ...........................................................................134
getContext() メソッド .......................................................19, 20
I
getCurrentPosition() 関数 .....................................134, 138, 141
image/jpeg..................................................................................2
エラー処理 .......................................................................136
image/png ..................................................................................2
getItem() メソッド .................................................................148
Indexed Database API ...........................................................154
getItems() メソッド .................................................................32
IndexedDB..............................................................................154
Google リッチスニペットテストツール ...............................211
input タイプ ..............................................................................29
GPS ..........................................................................................138
Intermedia...................................................................................6
Internet Explorer .......................................................................9
H
<article> .............................................................................49
H.264..........................................................................................94
Canvas API のサポート ....................................................83
<source> 要素 ..................................................................127
HTML5 ビデオ ..................................................................99
H.264 フォーマット ........................................................223
Mac IE5 .............................................................................35
MPEG LA ........................................................................101
位置情報通知 ...................................................................139
ビデオのエンコード ........................................................115
癖 ........................................................................................35
ライセンス事情................................................................100
ストレージ .......................................................................146
HandBrake ..............................................................................115
不明な要素 .........................................................................48
HTML
iPhone .....................................................................................137
策定の歴史 .........................................................................10
iPhone と iPad.................................................................129
その系譜 ...............................................................................8
フォーム入力 ...................................................................175
HTML 2.0 ....................................................................................6
HTML 4.0 ..................................................................................10
J
入力形式 ...........................................................................174
jQuery .....................................................................................172
文書のアウトライン ..........................................................55
リンクタイプ .....................................................................42
L
HTML5 ......................................................................................15
lang 属性 ....................................................................................38
DOCTYPE .........................................................................37
lineTo() メソッド......................................................................70
DOM と HTML5 の機能 ..................................................17
Local Strage ......................................................................25, 226
機能 ....................................................................................17
localStorage プロパティ...........................................................25
ストレージ .................................................................24, 147
ストレージの実例 ............................................................150
M
ストレージの使用 ............................................................148
manifest 属性 ..........................................................................158
ストレージの制限 ............................................................150
Matroska ...................................................................................92
セキュリティ .....................................................................25
maximumAge プロパティ......................................................138
名前空間 .............................................................................37
Microdata →マイクロデータ
日付と時刻 .........................................................................57
MIME タイプ ..............................................................................1
ビデオのサポート状況 ......................................................98
「MIME になるかもしれないね」........................................3
文書のアウトライン ..........................................................55
text/cache-manifest........................................................158
ヘッダ .................................................................................52
XHTML 文書 .....................................................................10
要素 ..................................................................................189
画像 ......................................................................................2
リンクタイプ .....................................................................42
ビデオ ...............................................................................127
HTML5 有効化スクリプト .......................................................50
問題 ..................................................................................127
232
索引
Miro Video Converter ...........................................................102
電子メールアドレス ........................................................185
Modernizr .................................................................................18
日付と時刻 .......................................................................181
Geolocation API ................................................................28
HTML5 のタイプ ..............................................................30
P
Web Workers.....................................................................26
parseInt() 関数 ........................................................................152
オートフォーカス ..............................................................32
PERMISSION_DENIED .......................................................137
オフライン Web アプリケーション .................................27
pingback 機構 ...........................................................................44
ストレージ .......................................................................147
placeholder プロパティ............................................................30
テキスト描画 .....................................................................21
POSITION_UNAVAILABLE .................................................137
ビデオ ...........................................................................21, 24
PositionError オブジェクト ..................................................136
プレースホルダ..................................................................31
PositionOptions オブジェクト ..............................................138
ローカルストレージ ..........................................................25
position オブジェクト ............................................................136
Mosaic .........................................................................................3
quirks ........................................................................................36
moveTo() メソッド ..................................................................70
Mozilla ...................................................................................9, 36
Q
nsElementTable.cpp .........................................................47
QUOTA_EXCEEDED_ERR ..................................................150
Theora ビデオ ...................................................................95
MP3 ...........................................................................................96
R
MP3 フォーマット ..........................................................219
RDFa........................................................................................189
MPEG LA ................................................................................101
MPEG-1 Audio Layer 3 → MP3
MPEG-4 .....................................................................................92
S
Safari ..........................................................................................14
検索ボックス ...........................................................182, 183
N
ビデオフォーマット ..........................................................22
navigator.geolocation プロパティ .........................................134
Server-sent イベント ..............................................................225
Netscape Navigator....................................................................9
Session Strage →セッションストレージ
NETWORK セクション .................................................160, 161
setItem() メソッド .................................................................148
novalidate 属性........................................................................185
sizes 属性...................................................................................43
nsElementTable.cpp ................................................................47
standards...................................................................................36
stepDown() メソッド .............................................................177
O
Offline Web Application
stepUp() メソッド ..................................................................177
storage イベント .....................................................................149
→オフライン Web アプリケーション
stroke() メソッド .....................................................................72
Ogg ............................................................................................92
strokeStyle プロパティ ............................................................67
Ogg Vorbis ........................................................................98
supports_canvas() 関数 ...........................................................20
ビデオのエンコード ........................................................106
supports_video() 関数 .......................................................21, 23
ビデオのバッチエンコード .............................................114
SVG ..........................................................................................226
OpenSearch 文書 ......................................................................45
Opera ...................................................................................12, 14
T
<input type="color"> .......................................................184
tagline ........................................................................................52
Ogg.....................................................................................92
text/html .....................................................................................1
WebM.................................................................................23
textBaseline ..............................................................................74
ストレージ .......................................................................150
Theora .......................................................................................94
スピンボックス................................................................178
Theora フォーマット ......................................................224
索引
TIMEOUT ...............................................................................137
233
Web 標準 .....................................................................................9
timeout プロパティ.................................................................138
WGS84 測地系 ........................................................................137
type 属性 ....................................................................................42
WHATWG .................................................................................13
Web アドレス ..................................................................176
W3C ...................................................................................14
検索ボックス ...................................................................182
whatwg.org ...............................................................................13
電子メールアドレス ........................................................174
window.applicationCache.swapCache() 関数 ......................163
ビデオ ...............................................................................126
window.onload イベント ........................................................172
フォームの検証................................................................185
X
U
X Mosaic .....................................................................................3
upload progress イベント......................................................226
XForms......................................................................................10
URI → Web アドレス
XHTML
XHTML 1.0 ........................................................................10
V
XHTML 1.1 ........................................................................12
VLC ............................................................................................92
XHTML 拡張フォーム ......................................................10
Vorbis.........................................................................................98
XML ...........................................................................................10
Vorbis オーディオコーデック ..........................................92
xml:lang 属性 ............................................................................38
Vorbis フォーマット .......................................................219
XMLHttpRequest ...................................................................226
VP3 コーデック .........................................................................94
xmlns 属性.................................................................................37
VP8.............................................................................................95
あ行
VP8 ビデオコーデック ......................................................92
アウトライン .............................................................................52
W
アドレス ..................................................................................222
W3C ...........................................................................................10
移行手段 ....................................................................................12
WHATWG .........................................................................14
位置検出 ....................................................................................27
XHTML 2 ワーキンググループ ........................................15
位置情報
W3C Widgets..........................................................................226
位置情報通知機能→ Geolocation
watchPosition() 関数 ..............................................................139
精度 ..................................................................................139
WAV フォーマット .................................................................219
イベント
Web Hypertext Application Technology Working Group
DOM イベント ................................................................162
→ WHATWG
オフライン Web アプリケーション ...............................162
Web SQL データベース ..........................................................225
意味要素 ....................................................................................45
Web Storage............................................................................147
インライン SVG ......................................................................226
Web Worker API ......................................................................26
インラインレベル要素 ..............................................................48
Web Workers ............................................................................26
エラー処理 .................................................................................12
WebM ..................................................................................23, 92
Geolocation .....................................................................136
<source> ..........................................................................127
オーサリングエラー ..........................................................12
WebM フォーマット .......................................................223
キャッシュマニフェスト.................................................163
エンコード .......................................................................122
ドラコニアンな..................................................................11
WebSimpleDB ........................................................................154
エンコード .................................................................................22
Web アドレス ..........................................................................175
エンコードツール ............................102, 106, 114, 115, 122
Web ページのアドレス .....................................................29
オーサリングエラー..................................................................12
Web アプリケーション ...........................................................157
オーディオコーデック ..............................................................95
Web サーバ..................................................................................2
種類 ....................................................................................96
234
索引
オートフォーカス ...........................................................170, 221
Canvas..........................................................................65, 80
サポート状況 ...................................................................171
Geolocation API ..............................................................134
オフライン Web アプリケーション .........................26, 157, 226
IE と Canvas API ..............................................................83
サポート状況 ...................................................................157
オートフォーカス ............................................................171
デバッグ ...........................................................................163
オフライン Web アプリケーション ...............................157
画像 ....................................................................................80
か行
グラデーション..................................................................77
可逆 ............................................................................................93
シェープ .............................................................................66
画像 ............................................................................................80
ストレージ .......................................................................147
サポート状況 .....................................................................80
デートピッカー................................................................180
カラーピッカー .........................................................29, 183, 221
テキスト .............................................................................73
カレンダー .................................................................................29
パス ....................................................................................69
キャッシュマニフェスト
ビデオ .................................................................................98
DOM イベント ................................................................162
ビデオコーデック ..............................................................99
キャッシュマニフェストファイル .................................158
プレースホルダ................................................................170
デバッグ ...........................................................................163
参考文献 ...........15, 33, 62, 89, 131,142, 154, 167, 187, 217, 227
キャッチフレーズ .....................................................................52
シェープ ....................................................................................66
キャプション ...........................................................................223
サポート状況 .....................................................................66
矩形 ............................................................................................67
時間 ............................................................................................56
グラデーション ...................................................................67, 77
数値 ..........................................................................................176
サポート状況 .....................................................................77
数値入力 ...........................................................................221
グリッド ....................................................................................68
スキップリンク .........................................................................59
グローバルオブジェクト ..........................................................17
スクリーンリーダー..................................................................59
クロスドキュメントメッセージング .....................................226
スコープ ..........................................................................190, 195
クロスドメインリクエスト ....................................................226
入れ子の ...........................................................................198
携帯電話 ..................................................................................137
ストレージ
検索ボックス .............................................................29, 182, 221
Cookie の欠点..................................................................145
語彙 ..................................................................................191, 195
Flash.................................................................................146
後方互換性 ...........................................................................12, 14
Gears ................................................................................146
後方互換モード .........................................................................36
HTML5 ............................................................................147
コーデック ...........................................................................22, 93
HTML5 以前 ....................................................................146
コールバック関数 ...........................................................135, 139
IE ......................................................................................146
geo.js ................................................................................142
セッションストレージ ....................................................225
getCurrentPosition() 関数 .............................................141
データベース ...................................................................154
エラー ...............................................................................136
ローカルストレージ ..................................................24, 226
互換性 ......................................................................................100
スピンボックス .................................................29, 176, 178, 221
コンテナフォーマット ..............................................................91
スライダ ....................................................................29, 179, 221
コンテントタイプ→ MIME タイプ
制約バリデーション................................................................220
世界測地系 ...............................................................................137
さ行
セッションストレージ ............................................................225
座標 ............................................................................................68
セマンティクス ...............................................................194, 200
サポート状況
相対フォントサイズ..................................................................75
<input required> .............................................................186
<video> ...............................................................................91
索引
235
た行
標準 ......................................................................................2, 189
データベース ...........................................................................154
Web 標準 ..............................................................................9
Web SQL データベース ..................................................225
標準モード .................................................................................36
デートピッカー .........................................................29, 179, 222
フィードの自動通知..................................................................42
サポート状況 ...................................................................180
フィールド ...............................................................................170
テキスト ....................................................................................39
フォーカス .........................................................................31, 172
Canvas................................................................................73
jQuery ..............................................................................172
サポート状況 .....................................................................73
フォーマット
デバッグ ..................................................................................163
H.264 ................................................................................223
電話番号 ....................................................................................29
MP3 ..................................................................................219
動画 ............................................................................................91
Theora..............................................................................224
ドット記法 ...............................................................................197
Vorbis ...............................................................................219
ドラコニアン .............................................................................11
WAV..................................................................................219
ドラッグアンドドロップ ........................................................226
WebM...............................................................................223
ビデオ ...........................................................................22, 91
な行
フォーム ..................................................................................169
ナビゲーション .........................................................................58
検証 ..................................................................................184
名前空間 ....................................................................................37
数値の入力 ...............................................................176, 179
マイクロデータ................................................................191
入力必須フィールド ........................................................186
名前付きプロパティ........................................................190, 191
フォームデータ送信 ........................................................226
入力フィールド .................................................................30, 169
フォント
フォーカス .........................................................................31
Canvas................................................................................73
塗りつぶし .................................................................................67
相対フォントサイズ ..........................................................75
不可逆 ........................................................................................93
は行
不可視データ ...........................................................................205
パス ............................................................................................69
フッタ ..................................................................................46, 60
キャッシュマニフェストファイル .................................166
不明な要素 .................................................................................47
サポート状況 .....................................................................69
ブラウザ ......................................................................................9
パンくずリスト .........................................................................43
DOM ..................................................................................17
日付と時刻 ...................................................................47, 56, 179
Mosaic .................................................................................3
ビデオ ..................................................................................21, 91
Mozilla ...........................................................................9, 36
<source> ..........................................................................126
ビデオコーデックサポート状況 .......................................99
Android ............................................................................129
ビデオソースの判定 ........................................................126
iPhone と iPad.................................................................129
不明な要素の扱い ..............................................................47
type 属性 ..........................................................................126
マイクロデータ................................................................201
キャプション ...................................................................223
プレースホルダ .........................................................30, 169, 221
コンテナフォーマット ......................................................92
サポート状況 ...................................................................170
サポート状況 .....................................................................98
プロパティ
ビデオコーデック ..............................................................93
マイクロデータ................................................................197
ビデオフォーマット ..........................................................22
ページ ........................................................................................43
互換性 ...............................................................................100
ベースライン .............................................................................74
ビデオコーデック
ヘッダ ....................................................................................1, 51
サポート状況 .....................................................................99
ほぼ標準モード .........................................................................36
種類 ....................................................................................94
236
索引
ま行
や行
マイクロデータ .........................................................32, 190, 224
要素 ..........................................................................................189
語彙 ..........................................................................191, 195
DOM ..................................................................................17
スコープ ...........................................................................195
一覧 ..................................................................................219
注釈 ..................................................................................205
追加 ..................................................................................193
ら行
名前空間 ...........................................................................191
リーフノード .............................................................................37
プロパティ .......................................................................197
リッチスニペット ...........................................................201, 211
マイクロフォーマット ............................................................189
Google リッチスニペットテストツール ........................211
マニフェストファイル
リンクタイプ .............................................................................40
キャッシュマニフェストファイル .................................158
ページ .................................................................................43
リスト ...............................................................................159
ルート要素 .................................................................................37
マルチキャット効果..................................................................82
レトロスペック ...........................................................................6
メールアドレス .................................................................29, 221
ローカルストレージ..........................................................24, 226
文字エンコーティング ..............................................................39
セキュリティ .....................................................................25
モバイル機器 ...........................................................................137
→ストレージも参照
●
.著者紹介
Mark Pilgrim(マーク・ピルグリム)
Google のシニアディベロッパーアドボケートで、オープンソースとオープン標準の専門家。Web アクセシ
ビリティに関するフリーのオンラインチュートリアル『Dive Into Accessibility』や、『Dive Into Python』
(Apress)などの技術書の著者でもある。妻、二人の息子、それに甘えん坊の大型犬と一緒に、ノースカロ
ライナ州に住んでいる。
●
.監訳者紹介
矢倉 眞隆(やくら まさたか)
1984 年生まれ。1995 年頃より Web に親しむ。現在は HTML5 や CSS3 を始めとする Web 技術について、
株式会社ミツエーリンクスが運営する「Web 標準 Blog」(http://standards.mitsue.co.jp/)より情報提供
や普及啓蒙を行う。また雑誌・オンラインメディアでの執筆、イベントでの講演も行う。各種 Web サービ
スやソーシャルメディアでは主に myakura というエイリアスで活動している。
●
.訳者紹介
水原 文(みずはら ぶん)
技術者として情報通信機器メーカーや通信キャリアなどに勤務した後、フリーの翻訳者となる。訳書
『Making Things Talk』、『組み込み Linux システム構築 第 2 版』(いずれもオライリー・ジャパン)。趣味
は広く浅く、フランス車(シトロエン)、カードゲーム(コントラクトブリッジ)、茶道(表千家)など。ブ
リッジのパートナーと、お茶の弟子を募集中。日夜ツイッター(@bmizuhara)に出没している。
●
.カバーの説明
本書の表紙の動物はシャモア(別名アルプスカモシカ、学名:Rupicapra rupicapra)です。カルパチア、
アペニン、タトラ、バルカン、コーカサス、そしてアルプスなど、ヨーロッパの山地に固有のヤギやアンテ
ロープに似た動物です。シャモアはニュージーランドでも見られますが、これは 1907 年にオーストリア皇
帝フランツ・ヨーゼフ 1 世によって持ち込まれたものです。
シャモアは比較的標高の高い場所に生息しており、急峻で険しい岩場に適応しています。成長すると体高
75cm、体重 20 ∼ 30kg になります(ニュージーランドに生息する個体は、ヨーロッパのものよりも 20%
ほど体重が少ない傾向にあります)。雄にも雌にも、短くて先端が後ろにカーブした角があり、また毛皮は
夏には暗褐色で冬には明るい灰色になります。シャモアの特徴として、顔とお尻が白く、目の下から背中に
沿って黒い縞模様があるのが普通です。
成獣の雄のシャモアはほとんど単独で生活していますが、年に一度だけ、つがいのいない雌の気を引くため
に集まって競い合います。それに対して雌は、幼獣と一緒に群れで生活します。シャモアの亜種はすべて、
狩猟の対象となっています。肉は味がよく、皮は非常にしなやかで吸収力に富むことで知られています。ま
たシャモアの首の後ろから取った毛の房は gamsbart と呼ばれ、アルプスの国々で伝統的に帽子の飾りとし
て使われてきました。しかし最近では、シャモアの一部の亜種がヨーロッパ連合によって保護されるように
なったため、この慣習は多少の困難を迎えています。対照的にニュージーランドでは、固有の生態系への影
響を防ぐため、自然保護局によってシャモアの狩猟はむしろ奨励されています。
入門.HTML5
2011 年 4 月 21 日
初版第 1 刷発行
2012 年 3 月 14 日
初版第 3 刷発行
著
監
訳
訳
発
行
印
者
Mark Pilgrim(マーク・ピルグリム)
者
矢倉 眞隆(やくら まさたか)
者
水原 文(みずはら ぶん)
人
ティム・オライリー
刷
株式会社平河工業社
発
行
所
株式会社オライリー・ジャパン
〒 160-0002 東京都新宿区坂町 26 番地 27 インテリジェントプラザビル 1F
Tel (03)3356-5227
Fax(03)3356-5263
電子メール [email protected]
発
売
元
株式会社オーム社
〒 101-8460 東京都千代田区神田錦町 3-1
Tel (03)3233-0641(代表)
Fax(03)3233-3440
Printed in Japan(ISBN978-4-87311-482-8)
乱丁、落丁の際はお取り替えいたします。
本書は著作権上の保護を受けています。本書の一部あるいは全部について、株式会社オライリー・ジャパンから文書
による許諾を得ずに、いかなる方法においても無断で複写、複製することは禁じられています。