試しにiOS標準のメールアプリのような一覧と詳細画面を行き来できるアプリケーションを作ってみます。
一覧データや、詳細データの取得にはAjaxを使えるので、iPhoneでロードするHTMLにはデータを表示する枠のHTMLとJavaScriptコードだけの静的なHTMLでできています。
こうすることで、アプリといっても静的なHTMLになるので、「キャッシュマニフェスト」の仕組み(連載第5回で解説予定)を使って、HTML自体をiPhoneのキャッシュに載せられ、アプリの起動速度を飛躍的に向上できます。
それではまず、iUIを使って一覧ページと詳細ページからなるWebページを作ってみます。前回と同様にiUIを展開したディレクトリに、js/json2.jsとしてjson2.jsを配置して、以下の内容で「app.html」というファイルを作成してください。
<html> <head> <title>サンプルアプリ</title> <!-- 【1】 viewportの指定 --> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=0"/> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <meta name="apple-mobile-web-app-capable" content="no" /> <!-- 【2】 iUIのロード --> <link rel="stylesheet" href="iui/iui.css" type="text/css" /> <link rel="stylesheet" title="Default" href="iui/t/default/default-theme.css" type="text/css"/> <link rel="stylesheet" href="css/iui-panel-list.css" type="text/css" /> <link rel="stylesheet" href="my-iui.css" type="text/css" /> <script type="application/x-javascript" src="iui/iui.js"></script> <!-- 【3】 json2.jsのロード --> <script type="application/x-javascript" src="js/json2.js"></script> </head> <body> <!-- 【4】 画面上部のタイトルバー領域 --> <div class="toolbar"> <h1 id="pageTitle"></h1> <a id="backButton" class="button" href="#"></a> </div> <!-- 【5】 一覧ページ --> <ul id="list" title="一覧ページ" selected="true"></ul> <!-- 【6】 詳細ページ --> <div id="content" class="panel" title="詳細ページ"></div> </body> </html>
このHTMLをiPhoneで表示すると、タイトルが「一覧ページ」の真っ白なページとなるはずです。
次に、app.htmlのロード時に、サーバからAjaxで一覧ページのデータをJSONで取得して一覧ページを動的に作成してみます。
今回は、サーバ側の実装は省略して一覧ページに表示する内容をJSONを記述したテキストファイルを代わりに使います。「app.html」と同じディレクトリに、「list-ajax.txt」として以下のテキストファイルを置いてください。
[ { "id":101, "title":"タイトル1" }, { "id":102, "title":"タイトル2" } ]
このAjaxレスポンスを受け取り、一覧ページを動的に生成してみます。
<script>//<![CDATA[<!-- // 【7】 innerHTMLで動的にコンテンツを流し込むためにHTMLエスケープを行う関数を作成 function escapeHTML(str) { return str.replace(/&/ig, "&").replace(/</ig, "<").replace(/>/ig, ">").replace(/'/ig, "'").replace(/"/ig, """).replace(/ /ig, " "); } function openContent(id) { // ここは、まだ未実装 } function loadList() { var ul = document.getElementById('list'); // 【8】「読み込み中...」のメッセージを表示 if (ul.innerHTML = '') { var li = document.createElement('li'); li.innerHTML = '読み込み中...'; ul.appendChild(li); } // 【9】 Ajaxで一覧ページのコンテンツを取得してリストを生成 var xhr = new XMLHttpRequest(); xhr.open('GET', 'list-ajax.txt?rnd=' + new Date().getTime(), true); xhr.onreadystatechange = function() { if (xhr.readyState == 4) { ul.innerHTML = ''; var list = JSON.parse(xhr.responseText); for (i = 0; i < list.length; i++) { li = document.createElement('li'); li.innerHTML = '<a href="#content" onclick="openContent(' + list[i].id + ')">' + escapeHTML(list[i].title) + '</a>'; ul.appendChild(li); } } }; xhr.send(); } function initApp() { loadList(); } // 【10】 ページのロード時に「initApp()」が実行されるようにイベントリスナをセット window.addEventListener('load', initApp, false); //-->]]></script>
このコードを実行される順にたどると、まず【10】で、app.htmlのロードが完了したときに、initApp()関数を実行するようにイベントリスナをセットします。ページのロードが完了したタイミングで、initApp()を呼び出し、その中から一覧ページを更新するloadList()関数が呼び出します。
loadList()関数の中では、まず【8】で<ul>〜</ul>の中身が空のときだけ「読み込み中」というメッセージを表示します。これはネットワークが遅いときにユーザーに心配させないための配慮です。
【9】がAjaxによる処理です。JSON文字列を取得してパースしてJavaScriptの配列としてデータを取得したものを、<li>タグにして<ul>〜</ul>の中に挿入しています。
<li>タグの中身は、詳細ページを開くための<a>タグを生成しています。<a>タグはiUIの画面遷移なので、href属性として詳細画面の画面ID(ここでは「#content」)を指定します。また、詳細画面を動的にロードするために<a>タグのonclickイベントで、openContent()関数が起動するようにしておきます。
今回のサンプルでは、Ajaxでリクエストする先のサーバ側がテキストファイルなので、サーバの設定によってはキャッシュされてしまうと思います。JSONの中身を変更しながら動作を確認するときにキャッシュされないようにURLに時間を表す数値を付けています。
ここまでの作業で、一覧ページにJSONの内容が表示されて、一覧ページと詳細ページが行き来できるようになっているはずです。
長くなりましたが、いよいよ最後です。詳細ページをJSONで取得して表示してみます。
先ほどと同じように、サーバ側の実装はテキストファイルを代わりに使います。「content-ajax.txt」として以下のJSON文字列をテキストファイルとして設置してください。
[ "id": 101, "title": "タイトル1", "content": "タイトル1の内容です。" ]
そして、先ほどのJavaScript関数の中で未実装だった「openContent()」関数を以下のように実装します。
function openContent(id) { var div = document.getElementById('content'); var xhr = new XMLHttpRequest(); xhr.open('GET', 'content-ajax.txt?id=' + id + '&rnd=' + new Date().getTime(), true); xhr.onreadystatechange = function() { if (xhr.readyState == 4) { div.innerHTML = ''; var content = JSON.parse(xhr.responseText); div.innerHTML = escapeHTML(content.content); } }; xhr.send(); }
これで今回のサンプルは完成です。HTML自体は静的なコンテンツなのに、サーバのデータをJSONで取得することで動的なアプリケーションとして動作することが確認できたはずです。
是非、JSONの中身を編集してみたりして、いろいろ試してみてください。
次回以降は、HTML5で規定されてiPhoneのSafariでも実装されているLocalStorage(ローカルストレージ)を使って、データの先読みを実装してみたいと思います。それでは、また次回。
Copyright © ITmedia, Inc. All Rights Reserved.