2011年3月8日火曜日

HTML5 と Ajax によるデータ主導のインタラクティブ・アプリケーション

HTML5 とは、標準化されたリッチ・メディアや対話性をはじめ、新たに登場している様々な Web 技術を総称する用語です。HTML5 はまた、堅牢なオフライン・アプリケーションの開発基盤にもなります。経験を積んだ Web 開発者にとって、新しいコンパイル言語 (Objective-C や Java™ のような言語) を学ぶよりは HTML5 を使用するほうが心惹かれるはずですが、その場合には HTML5 を使用してアプリケーションを作成する場合ならではの学習曲線があります。この記事では、オンライン・コンテンツを上手く組み合わせる一方で、ネットワークに接続していないユーザーにもリッチなエクスペリエンスを提供する方法を説明します。

サンプル・アプリケーション

この記事で用いるサンプル・アプリケーションは、広範なデスクトップ機器とモバイル機器で使用されることを意図しています。このアプリケーションが提供するのは、料理とドリンクのレシピです。そのうち 3 つのレシピは静的コンテンツで、ユーザーはネットワークに接続していなくても使用することができます。ユーザーがネットワークに接続しているときは、Ajax によってコンテンツを配信する Web サービスを介して「今日のレシピ」を表示できるようにします。

技術の再利用は、アジャイルな Web 開発の鍵です。このサンプル・アプリケーションでは、よく使われている以下の 2 つのオープンソース・ライブラリーを使用します。

  • jQuery — 特定のプラットフォームに依存することなく、JavaScript と DOM を利用できる堅牢なライブラリーです。
  • jQTouch — WebKit ブラウザーを使用した HTML5 モバイル・アプリケーション用のフレームワークです。

jQuery および jQTouch についての詳細は、「参考文献」を参照してください。

最善の結果を得るには、Apple Safari V4 またはそれ以降のバージョンを使用して HTML5 アプケーションを開発してください。ただし、Google Chrome でも機能します。

jQTouch を使用する

jQTouch を使用したアプリケーション (jQTouch アプリケーション) を扱う上で最適な方法は、単一の HTML 文書として扱うことです。その場合、アプリケーション内の各「ページ」は、それぞれに固有の id 属性を持つ個別の HTML <div> になります。このアプリケーションの基本的な構成要素は、以下のようになります。

  1. HTML ヘッダーおよびインポート
  2. 開始 <div>
  3. <div> として固有の ID が設定されたゼロまたはそれ以上の追加ページ

インポートの設定をする

サンプル・アプリケーションの先頭部分では、アプリケーションの CSS および JavaScript をインポートするとともに、HTML5 オフライン・キャッシュを構成します。リスト 1 に、そのために必要なコードを記載します。


リスト 1. jQTouch および HTML5 オフライン機能に必要なヘッダー
<!DOCTYPE html> <html manifest="sample.manifest">   <head>     <meta charset="utf-8" />     <title>Sample recipe application</title>     <style type="text/css">@import "jqtouch/jqtouch/jqtouch.min.css";</style>     <style type="text/css">@import "jqtouch/themes/jqt/theme.min.css";</style>     <style type="text/css">@import "sample.css";</style>     <script src="jqtouch/jqtouch/jquery.1.3.2.min.js"              type="text/javascript"></script>     <script src="jqtouch/jqtouch/jqtouch.min.js"              type="text/javascript"></script>     <script src="sample.js" type="text/javascript"></script>   </head> 

HTML5 を有効にする

HTML5 マークアップについて

DTD や XML を扱い慣れているプログラマーにとって、単純化された DOCTYPE は奇異に見えることでしょう。DOCTYPE には、Web ブラウザーで「標準モード」をトリガーするという目的しかありません。これまでブラウザーが DTD ベースの検証を使用した試しはないため (HTML の「タグ・スープ」のまん延が原因です)、厳格な DOCTYPE を提供しても特別なメリットはありません。XML 対応のツールを使って Web アプリケーションを構築する場合には HTML V4.01 またはXHTML V1.0 の DOCTYPE を引き続き使用できますが、HTML5 によって拡張されている文書の完全な検証が行われることはありません。

同様に、<meta charset="utf-8"> も見慣れない設定だと思いますが、これも有効な HTML5 です。HTML5 で単純化された構文については、「参考文献」を参照してください。

このサンプル・アプリケーションには、オフラインでもアクセスできる機能を組み込みます。オフライン機能を有効にするには、manifest 属性を組み込みます。以下に示すように、この属性にはキャッシュ・マニフェスト・ファイルのパスを値として設定する必要があります。

<html manifest="sample.manifest"> 

キャッシュ・マニフェストには通常、以下の 2 組のリソースが含まれます。

  • オフラインで使用するためにキャッシュしなければならないリソースのリスト
  • 文書がオンラインの場合にのみ使用可能になるリソースのリスト

リスト 2 を見るとわかるように、キャッシュ・マニフェストの構文は至って単純です。


リスト 2. サンプル・アプリケーションのキャッシュ・マニフェスト・ファイル
CACHE MANIFEST  # This is a comment and will be ignored   # Files specific to this application: sample.js sample.css  # Files that are a part of jQTouch: # (See the sample code for a complete list) jqtouch/jqtouch/jqtouch.min.css  NETWORK: # These resources will be available only when online: sample.json 

最初の行は必ず、CACHE MANIFEST となります。オフラインにできるリソース (HTML ページ、CSS、JavaScript、画像、またはその他の種類のファイル) は、それぞれ新しい行に記述されます。アプリケーションに初めてアクセスするときに、ブラウザーはキャッシュ・マニフェストを調べ、そこに記載されているすべてのリソースをダウンロードして、オフラインで使用できるように保管します。

NETWORK: 行の後に記載されたリソースはキャッシュされません。これらのリソースにアクセスできるのは、ネットワークが使用可能なときだけです。リスト 2 では 1 つのファイルが記載されていますが、パス名の一部を使用することもできます。例えば、ここに/online/ と記述して、オンライン専用のすべてのリソースがこのパスに含まれるようにアプリケーションをセットアップすることも可能です。

アプリケーションのリソースのいずれかをオフラインまたはオンラインとして記載するのを忘れると、通常はアプリケーション全体がオフライン対応としてマークされることになります。現行の実装には、この他にも混乱の原因となる細かな点があります。以下にその例を示します。

  • Web サーバーは、マニフェスト・ファイルを text/cache-manifest タイプとして提供する必要があります。
  • キャッシュ・マニフェストを指すファイル (この例の場合は sample.html) が記載されている必要はありません。
  • マニフェストに記載されている項目は、マニフェスト自体を変更した場合にだけリロードされます。リソースが変更されてもリロードされません。
  • Web サーバーは、no-cache レスポンス・ヘッダーを設定してマニフェスト・ファイルを提供しなければなりません。
  • Web ページがマニフェストではないファイルを参照する場合、アプリケーションがオフライン用にキャッシュされないことがあります。多くの場合、このエラーが発生しても症状は現れません。Safari V4 以降では、「Activity (アクティビティー)」パネルで警告メッセージを調べてください。

HTML5 オフライン・アプリケーションが適切にセットアップされていれば、ブラウザーとサーバーを使ってアプリケーションにいったんアクセスし、それからサーバーやローカル・ネットワークへアクセスできないようにして、最新の状態に更新した場合でも、コンテンツを引き続き操作することができます。サイトに到達できないというメッセージがブラウザーに表示される場合には、上記のリストを再確認して、構成に問題がないかどうかを調べてください。

jQTouch を使用した開発

jQTouch ライブラリーには以下のインポートが必要です。

  • jqtouch.min.css. — jQTouch そのものの CSS
  • theme.min.css. — 現行テーマの CSS (このサンプルではデフォルトのテーマを使用)
  • jquery.1.3.2.min.js 以降 — jQuery の本体
  • jqtouch.min.js. — jQTouch のメイン・スクリプト
  • samples.js. — アプリケーションに固有の機能を定義するカスタム JavaScript

モバイル Web のパフォーマンスに関するアドバイス

通常の Web のベスト・プラクティスに従って、JavaScript インポートは HTML 文書の終わりにある <body> の終了タグの直前に配置してください。ただし、このサンプルでは明確にするために <head> の中にインポートを含めます。

モバイル機器では、ワイヤレス接続の速度が遅いことが原因となり、HTTP トランザクションには大きなオーバーヘッドが伴います。したがって、複数の JavaScript ファイルは 1 つのライブリーに統合することをお薦めします。その際、自動ビルド/デプロイメントを利用すると、小さくて用途が明確な個々のライブラリーを使った開発作業を極めて容易なものにすることができます。

同様に、複数の画像を使う代わりに CSS スプライトを使用することを検討してください。また、スタイル・シートについても 1 つの文書にまとめてからデプロイすることをお薦めします。

jQTouch アプリケーションのコンテンツ・ページ

jQTouch アプリケーションの各ページは HTML の <div> にすぎません。したがって、以下の規約が同じく適用されます。

  • 一意の id 属性を持つ必要があります。
  • その一意の ID が、通常の HTML アンカー要素を使用してアプリケーション内のどこかにリンクされている必要があります。
  • jQTouch アプリケーションのホーム・ページの <div> は、"current" というクラス値を持ちます。

jQTouch ライブラリーには、ページからページへの遷移をアニメーション化する数々のメソッドが用意されています。デフォルトで使われるのは、CSS3 を使用した「スワイプ」による魅力的な遷移です。多くの WebKit 実装では、これらの遷移はハードウェア・アクセラレーションによる処理が行われるため、自然な動きをするアプリケーションを操作しているような感覚がもたらされます。jQTouch アプリケーションのホーム・ページに、そのようなページへのリンクが記載されています (リスト 3 を参照)。


リスト 3. "current" という名前のクラスで指定されたホーム・ページ
    <div id="home" class="current">       <div class="toolbar">         <h1>HTML5 Sample</h1>       </div>       <ul class="rounded">         <li class="arrow"><a href="#recipe1">Breakfast Circles</a></li>         <li class="arrow"><a href="#recipe2">Slowhand Jackson</a></li>         <li class="arrow"><a href="#recipe3">Potato Chip Cookies</a></li>         <li class="arrow online-required"><a href="#recipe4">Recipe of the Day</a></li>       </ul>     </div> 

jQTouch アプリケーションの大半のページは、一意の ID を持つ外側の <div> の後に、クラス属性の値が "toolbar" に設定された <div> が続きます。この <div> にはページ・タイトルが含まれています。その後にコンテンツがリスト形式、あるいは追加パラグラフという形で続くという構成になっています。

rounded クラスと arrow クラスはすべてメインの jQTouch スタイルの中で定義されます。インストールされたテーマによって、それぞれの外観は異なります。このサンプルでは、デフォルトの黒とグレーのテーマを使用します (図 1 を参照)。


図 1. サンプル・アプリケーションのホーム・ページ
サンプル・アプリケーションのホーム・ページのスクリーンショット。ここには、レシピの選択肢が表示されています。 

最初の 3 つのレシピは、同じ 1 つの HTML5 ページに定義された静的コンテンツです。それぞれのレシピには、例えば recipe1のような一意の ID が設定されています。これらの ID は、以下のようにホーム・ページから移動する新しいページを指定するために使用されます。

<a href="#recipe1">Breakfast Circles</a></li> 

リスト 4 に、最初のレシピのソース・コードを記載します。図 2 は、この HTML をレンダリングしたものです。


リスト 4. jQTouch アプリケーションに含まれる静的コンテンツ
    <div id="recipe1" class="recipe">       <div class="toolbar">         <h1>Breakfast Circles</h1>         <a class="back" href="#">Back</a>       </div>       <ul class="rounded">         <li>2C flour</li>         <li>1/2C sugar</li>         <li>1/2C confectioners sugar</li>         <li>2T Earl Grey tea leaves (about 6 bags)</li>         <li>1/2t salt</li>         <li>1t vanilla</li>         <li>1/2C butter</li>         <li>Cold water</li>       </ul>       <p>       Pulse dry ingredients in food processor to pulverize tea leaves.        Add vanilla, butter and pulse, adding as little water as        necessary to form loose dough. Divide into two 2" logs and roll        with parchment paper. Chill 30 min.</p>       <p>         Cut into 1/4"-thick wafers and bake at 375 degrees on parchment          until edges start to brown, about 12 min.       </p>     </div> 

上記の <div> には、"recipe" という新しいクラス値が含まれていることに注目してください。デフォルトの jQTouch スタイル・シートでは、このアプリケーションでレシピの手順に使用している、ネストされた <p> 要素のスタイルを適切に制御することができません。jQTouch は単なる Web アプリケーションを開発するためのプラグインなので、通常の CSS を使って任意のカスタム・スタイルを自由に追加することができます。

このサンプルでは、sample.css にいくつかの単純なカスタマイズを加えています。その 1 つは、レシピの手順に余白を与えて見やすくするための div.recipe p { margin: 1em; } です。


図 2. サンプル・アプリケーションのホーム・ページ
ブラウザーに表示された Breakfast Circles のレシピのスクリーンショット。材料のリストと、料理手順が表示されています。 

静的レシピのコンテンツは HTML ページ内に含まれるため、オフライン・ユーザーはこの 3 つの静的レシピをすべて表示することができます。ここからは、オンライン・コンテンツとオフライン・コンテンツを組み合わせて、優れたオフライン機能を提供する柔軟で拡張可能な Web アプリケーションを作成する方法を説明します。

オンラインへの対応

最後に記載されているレシピ項目 (リスト 5 を参照) には、online-required という別の HTML クラスが含まれています。


リスト 5. ユーザーがネットワークに接続している場合にのみ表示される項目
<li class="arrow online-required">   <a href="#recipe4">Recipe of the Day</a> </li>             

このアプリケーションの CSS カスタマイズ層では、.online-required  display: none に設定されます。つまり、デフォルトではアプリケーションはオフライン状態であると見なされて、オンライン・リソースは表示されないということです。

では、このアプリケーションはどのようにしてユーザーがネットワークに接続していることを認識するのでしょうか。そのためのコードは、リスト 6 に記載する JavaScript カスタマイズ・スクリプト、sample.js に含まれています。


リスト 6. オンライン・リソースを管理するための JavaScript
/* Initialize jQTouch on startup.   [ See sample code for complete listing ] */  // Standard jQuery method to run code when the browser  // has finished loading all resources jQuery(document).ready(function () {      // If online, show all online-only resources   if (window.navigator.onLine) {     jQuery('.online-required').show();   }   ... 

HTML5 では、window.navigator.onLine という JavaScript API の値を指定しています。この値が true であれば、ブラウザーはオンラインであり、ネットワークに接続されていることになります。オフラインの場合、ブラウザーがアクセスできるのはキャッシュ・マニフェスト内のオフライン・リソースだけです。このアプリケーションでは、アプリケーションがオンラインであれば、"online-required" クラスのすべての DOM 要素が表示されます。

window.navigator.onLine のテスト

HTML5 をサポートしていないデスクトップ Web ブラウザーでは、コンピューターがネットワークと接続していないとしても、window.navigator.onLine の値は常に true に設定されます。そのため、オフライン状態をエミュレートすることができるテスト用フレームワークを導入するか、モバイル機器だけを使用してテストする必要があります。

オンライン・データを受け入れる

jQTouch アプリケーションにオンライン・データを効率的に取り込む方法は、前もってそのデータを保持するスケルトン・ページを用意することです。リスト 7 に、オンライン専用レシピの <div> を記載します。


リスト 7. オンライン専用レシピのプレースホルダーとなる jQTouch ページ
<div id="recipe4" class="recipe">   <div class="toolbar">     <h1>Recipe of the Day</h1>     <a class="back" href="#">Back</a>   </div>   <!-- The recipe will be populated here --> </div> 

カスタム JavaScript 内には、レシピをリクエストして HTML ページにその結果を取り込むためのイベント・ハンドラーが必要となります。そのためには、#recipe4 の ID を対象とした onclick ハンドラーを定義するのが当然のように思えます。

ところが、jQTouch はページからページへ移動するというマジックを実現するために、通常のクリック動作を無効にします。そこで代わりに利用できるのが、CSS3 遷移によって start イベントと end イベントが発生するという事実です。これらのイベントは jQuery にネイティブではないものの、jQuery を使ってバインドすることができます。そのためのコードは以下のとおりです。

jQuery('#recipe4').bind('pageAnimationStart', function () {   ... }); 

スライド遷移、あるいは Ajax によるロードを確認できない場合

この記事を執筆している時点では、目に見える遷移が行われ、pageAnimationStart イベントが発生するのは Safari バージョン 4 とバージョン 5、および Mobile Safari だけです。これ以外の WebKit ブラウザーをサポートする必要がある場合には、別のイベントを使用してください。

pageAnimationStart イベントはクリック・イベントとほぼ同時に発生します。遷移が終了すると、pageAnimationEnd イベントが発生します。私の場合、ほとんどのアクションは、start イベントと関連付けるようにしています。そうすれば、ユーザーがアニメーションを見ている間、ブラウザーにデータを収集するための時間を与えられるからです。

Ajax によるデータの取り込み

残る作業は、通常の Ajax によるやりとりのみです。このサンプルでは、結果は JSON データ形式になることを前提とします。この場合、データは JSON ファイル (sample.json) から直接提供されます (リスト 8 を参照)。


リスト 8. 今日のレシピが含まれる JSON データ
[ { "title" : "Doggie Delight", "ingredients" :  \ ["1 cup dry kibble", "1 pound butter",  "1 beef bouillon cube", \ "2 tbsp oregano" ], "instructions": "Combine all ingredients in bowl.\  Season to taste. Serve immediately." }] 

リスト 9 に、このデータを取得してプレースホルダー <div> に入力するためのコードを記載します。


リスト 9. プレースホルダーに取り込まれる JSON データ
jQuery.ajax({ url: "sample.json",   success: function (data) {      // Set the recipe title     jQuery('#recipe4 h1').text(data[0].title);       // Create a UL and add each recipe item to it     var ul = jQuery('<ul class="rounded">');     jQuery.each(data[0].ingredients, function (index, item) {       jQuery('<li>').text(item).appendTo(ul);     });      // Add the ingredients list and the recipe instructions     jQuery('#recipe4').append(ul).append(       jQuery('<p>').text(data[0].instructions));                     

この動的データは最終的に、図 3 のようにレンダリングされます。


図 3. ブラウザーに表示された動的なレシピ
ブラウザーに表示された Breakfast Circles のレシピのスクリーンショット。材料のリストと、料理手順が表示されています。 

まとめ

市場には、新しいモバイル機器が次から次へと登場しています。新しいプラットフォームやハードウェアごとにカスタマイズしたネイティブ・アプリケーションを開発することもできますが、少人数のアジャイルなチームであれば、同じようなパフォーマンス特性を持つクロスプラットフォームのモバイル Web アプリケーションを作成することができます。モバイル Web アプリケーションは、HTML、JavaScript、および CSSの知識をすでに身に付けている開発者にとって魅力的であり、それはサイズを大きくしたネイティブ・アプリケーションのためのプロトタイプであろうと、ファースト・クラスのサイトであろうと変わりません。

HTML5 で JavaScript API を使用できるということは、Web アプリケーションがネットワークのステータスだけでなく、モバイル機器の向きや現在の位置などを始めとする、今までよりも多くのハードウェア・データにアクセスできることを意味します。これらの API はほとんどの場合、よく使われているモバイル・ブラウザーで広範にサポートされています。

Web 開発者の皆さんは、モバイル・アプリケーション開発の流れに取り残されたような気持ちになる必要はありません。皆さんはすでに、スマートフォンやネットブック、そしてタブレットの開発に必要なすべてのスキルを持っているはずです。

0 件のコメント:

コメントを投稿