2015年9月26日土曜日

JQueryMobile listview サンプル

jQuery Mobileのlistviewを使ったサンプルです。

自前で作ったメニュー表示/画面スライドをJQueryMobileで作り直したものです。
デモサイト
日本語/英語の言語切り替え付きもあります。

メインメニュー/サブメニュー/コンテンツといった多階層の画面遷移を組み込んでいます。
メニューのlistviewをjsonデータからjavascriptで動的に生成し、コンテンツ表示部分は各項目で共有し、コンテンツはiframeに外部のhtmlを読み込む構成になっています。
これにより画面遷移に関わる部分のhtmlがシンプルになり、コンテンツのメンテナンスも容易になります。

iframeを使っているため、backボタンの動作に手を加えています。これが最善かどうかはわかりませんが、ともかくも期待通りに動作しています。

HTML一式ダウンロードできます。

index.html のタグ構造

<body onload="init();">
        <div data-role="page" id="topPage">
            <div data-role="header">
                <h1 class="headerText">ホームページ</h1>
            </div>
            <!-- メインメニューを埋め込むdiv -->
            <div id="topMenu"></div>
            <div data-role="footer" class="footer">
                <h6 class="footerText">Footer Text</h6>
            </div>
        </div>
        
        <!-- メインメニューのページ1をタップしときに遷移するpage。サブメニューを表示する。 -->
        <div data-role="page" id="subMenuPage">
            <div data-role="header" data-add-back-btn="true" data-back-btn-text="戻る" onclick="return backClicked(this);">
                <h1 class="headerText">subMenuPage</h1>
            </div>
            <!-- サブメニューを埋め込むdiv -->
            <div id="subMenu"></div>
            <div data-role="footer" class="footer">
                <h6 class="footerText">Footer Text</h6>
            </div>
        </div>

        <!-- コンテンツ表示。メインメニューのページ3、およびサブメニューをタップしときに遷移しコンテンツを表示するpage。 -->
        <div data-role="page" id="contentPage" >
            <div data-role="header" data-add-back-btn="true" data-back-btn-text="戻る" onclick="return backClicked(this);">
                <h1 class="headerText">contentPage</h1>
            </div>
            <div data-role="main" class="ui-content" id="iframeDiv">
                <!-- コンテンツをロードするiframe -->
               <iframe id="iframe"></iframe>
            </div>
            <div data-role="footer" class="footer">
                <h6 class="footerText">Footer Text</h6>
            </div>
        </div>
    </body>

index.htmlのonloadイベントハンドラ
//body.onloadで呼ばれる。iframeのheight設定。
            //ブラウザのreloadボタンクリック時はindex.htmlをリロードする。
            function init() {
                if (document.getElementById("topMenuList") == null || $('#topMenuList').length == 0) {
                    location = "index.html";
                } else {
                    var h = $(window).height() - 20;
                    $('#iframe').css("height", h + "px");
                }
            }

メインメニューを生成するjavascript
//メインメニューのデータ。
            //text: リスト表示名
            //page: 遷移先ページ ID
            //src: iframeにロードするhtml、またはサブメニューのjson変数名。
            var topMenuList = [
                    {"text":"ページ1 - サブメニュー", "page":"#subMenuPage", "src":"subMenuList1"},
                    {"text":"ページ2 - サブメニュー", "page":"#subMenuPage", "src":"subMenuList2"},
                    {"text":"ページ3 - コンテンツ", "page":"#contentPage", "src":"Contents/page3.html"}
                    ];

            //index.htmlロード時に呼ばれ、メインメニューを生成。
            $(document).on('pagebeforeshow', '#topPage', function(){
                if ($('#topMenuList').length == 0) {
                    var ul = $('<ul>').attr({'id':'topMenuList','data-role':'listview'}).appendTo('#topMenu');
                    for(var i=0; i < topMenuList.length; i++) {
                    var li = $('<li>').appendTo('#topMenuList');
                    var item = topMenuList[i];
                    $('<a data-transition="slide" href="' + item.page + '">')
                        .attr('onclick', 'linkClicked("' + item.page + '","' + item.text + '","' + item.src + '")')
                        .text(item.text).appendTo(li);
                    }
                    $('#topMenuList').listview().listview('refresh');
                }
            });


メインメニュータップ/クリックで呼ばれサブメニューを生成するjavascript
//サブメニューのデータ。項目はメインメニューと同じ。
            var subMenuList1 = [
                   {"text":"1. 項目11", "page":"#contentPage", "src":"Contents/item11.html"},
                   {"text":"2. 項目12", "page":"#contentPage", "src":"Contents/item12.html"},
                   {"text":"3. 項目13", "page":"#contentPage", "src":"Contents/item13.html"}
                   ];

            //サブメニューのデータ。項目はメインメニューと同じ。
            var subMenuList2 = [
                   {"text":"1. 項目21", "page":"#contentPage", "src":"Contents/item21.html"},
                   {"text":"2. 項目22", "page":"#contentPage", "src":"Contents/item22.html"},
                   {"text":"3. 項目23", "page":"#contentPage", "src":"Contents/item23.html"}
                   ];

            //サブメニュー生成。異なるサブメニューで同じDIV構成を共用するため、表示のたびにlistviewを作り直す。
            function setMenu(name) {
                var ul = $('#subMenuList');
                if (ul.length > 0) {
                    ul.empty();
                } else {
                    ul = $('<ul>').attr({'id':'subMenuList','data-role':'listview'}).appendTo('#subMenu');
                }
                var menuList = eval(name);
                for(var i=0; i < menuList.length; i++) {
                    var li = $('<li>').appendTo('#subMenuList');
                    var item = menuList[i];
                    $('<a data-transition="slide" href="' + item.page + '">')
                    .attr('onclick', 'linkClicked("' + item.page + '","' + item.text + '","' + item.src  + '")')
                    .text(item.text).appendTo(li);
                }
                $('#subMenuList').listview().listview('refresh');
            }

メニュー項目タップ/クリックで呼ばれ画面遷移を行うjavascript
            //サブメニューのデータ。項目はメインメニューと同じ。
            //画面遷移の履歴。
            //iframeを使用するとBackボタンを二度クリック/タップしないと画面遷移しなくなるため、独自に履歴を管理する。
            var pageArray = new Array("");
            
            //listviewの項目がクリック/タップされたときに呼ばれる。
            //遷移先のヘッダのタイトル設定。現在のページをpageArrayにpushする。
            function linkClicked(page, title, src, backTo) {
                if (page == "#subMenuPage") {
                    setMenu(src);
                } else if (src.length > 0) {
                    $('#iframe').attr('src', src);
                }
                $(page).find('.headerText').text(title);
                pageArray.push(findParentPage($(event.srcElement)));
            }
        
            //paretnElementを辿り、data-role="page"の要素を返す。見つからない場合はnullを返す。
            function findParentPage(elm) {
                if (elm == null || elm.attr('data-role') == 'page') return elm;
                return findParentPage(elm.parent());
            }

戻るボタンで画面遷移を行うjavascript
            //Backボタンタップ/クリック。
            //戻り先pageIdがあればchangePageをよびfalseを返す。さもなけばtrueを返し、frameworkに任せる。
            function backClicked(elm) {
                var page = pageArray.pop();
                if (page == null) return true;
                var pageId = page.attr('id');
                if (pageId.length == 0) return true;

                $.mobile.changePage('#'+pageId, { transition: "slide", changeHash: true, reverse: true } );
                return false;
            }

参照
JQueryMobile listview サンプル 言語切り替え付き
HTML5+JavaScriptで画面をスライドさせて切り替える方法

0 件のコメント: