jQuery Mobile で動的ページ作成

jQuery Mobile でスマートフォン用ページを作成しているんですけど、スマートフォンからのアクセスかどうかを判断して、サーバー側で生成する HTML を切り替えるのが面倒です。PC 用ページではクライアント MVC を採用していて、PC からのアクセスのときは JSON を返すのでなおさら。サーバー側の処理は統一したいところです。

スマートフォン用ページでも、PC 用ページと同様に、サーバー側が返す JSON をテンプレートを使って描画すればいいのかも。

jQuery Mobile でやる場合、取得した JSON とテンプレートを使ってページの中身を書き変える、という実装方法が真っ先に思いつきました。ただ、今作っているアプリではデータが更新されることはほとんど無いです。毎回描画するのは
f:id:griefworker:20110224225413j:image

そこで、jQuery Mobile のページを動的に追加することにしました。これなら描画は1回で済みます。サンプルコードは次の通り。

<!DOCTYPE html>
<html>
    <head>
        <title>jQueryMobileDynamicPage</title>
        <meta charset="utf8">
        <link rel="stylesheet" href="jquery-mobile/jquery.mobile-1.0b3.css" />
        <script type="text/javascript" src="jquery-1.6.4.js"></script>
        <script type="text/javascript" src="underscore.js"></script>
        <script type="text/javascript" src="jquery.mockjax.js"></script>
        <script type="text/javascript" src="jquery-mobile/jquery.mobile-1.0b3.js"></script>
        <script type="text/javascript">
            $(function() {
                // サーバー側は jquery.mockjax で代用
                $.mockjax({
                    url: "/exams",
                    responseText: [
                        { id:1, title:"foo", content:"foo" },
                        { id:2, title:"bar", content:"bar" },
                        { id:3, title:"hoge", content:"hoge" },
                        { id:4, title:"fuga", content:"fuga" }
                    ]
                });

                $.getJSON("/exams", function(json) {
                    var listTemplate = _.template($("#entry-list-template").html());
                    var detailTemplate = _.template($("#entry-detail-template").html());
                    _.each(json, function(value) {
                        // メニューページに項目を追加
                        var html = listTemplate(value);
                        $(html).appendTo($("#entry-list"));

                        // ページを追加
                        var page = detailTemplate(value);
                        $(page).appendTo($("body")).page();
                    });

                    // メニューページのリストを再描画
                    $("#entry-list").listview("refresh");
                });
            });
        </script>
    </head>
    <body>
        <!--メニューページ-->
        <div id="menu" data-role="page">
            <div data-role="header">
                <h1>DynamicPage</h1>
            </div>

            <div data-role="content">
                <ul id="entry-list" data-role="listview">
                </ul>
            </div>
        </div>

        <!--メニュー項目を描画するためのテンプレート-->
        <script id="entry-list-template" type="text/template">
            <li><a href="#page<%= id %>"><%- title %></a></li>
        </script>

        <!--ページを描画するためのテンプレート-->
        <!--page メソッドを使っても data-url 属性が付かなかったので直接埋め込み-->
        <script id="entry-detail-template" type="text/template">
            <div id="page<%= id %>" data-url="page<%= id %>" data-role="page" data-add-back-btn="true">
                <div data-role="header">
                    <h1><%- title %></h1>
                </div>
                <div data-role="content">
                    <%- content %>
                </div>
            </div>
        </script>
    </body>
</html>

とりあえずこれで、動的に追加したページに移動できるようになりました。data-url 属性をテンプレートで記述しているけど、これに関しては正しいやり方があるのかも。ま、参考程度と思ってください。