Intelligent Technology's Technical Blog

株式会社インテリジェントテクノロジーの技術情報ブログです。

jQuery Mobile の階層化リストビューが非推奨!?そんなときは

こんにちは。ふだん、何かとjQuery Mobileを使っている中山です。

先日、なにげなくjQuery Mobileの情報を探していると、以下のような記事が見つかりました。

Remove nested listview feature
Nested list alternative now that it's deprecated

な、なんだってー!!
jQuery Mobileの「階層化リストビュー」の機能が、バージョン1.3.0からは非推奨、1.4.0からは機能自体削除される、と書かれているではないですか!

jQuery Mobileの現時点(2013年9月時点)の安定版は、バージョン1.3.2です。
そろそろ、「階層化リストビュー」が使えない、ということを言い訳にして、最新版に移行しないわけにもいきません。

「・・・よし、作るか。」

かくして、「階層化リストビュー」を自作するための、挑戦がはじまったのでした。

階層化リストビューとは

jQuery Mobileの「階層化リストビュー」は、「<ul>」「<li>」のタグを階層的に並べていくだけで、サブリストを持つリストビューを簡単に実現できる、という大変便利な機能でした。(詳しくはこちら

jQuery Mobileの「階層化リストビュー」の機能を使うと、サブリストを表示する際に、jQuery Mobileが自動的に「ページ」オブジェクトを生成するようです。
その新しく生成されたページに、サブリストの内容が自動的に描画され、表示される、という仕組みのようです。

この、
「サブリストがあった場合に、動的にページを生成して、そこに内容を描画する」
という部分を、うまく再現することができれば、自作「階層化リストビュー」もスムーズに実現できるのかもしれません。

階層化リストビューを自作してみる

リストビューのデータを用意する

まずは、リストビューに表示する項目のデータを用意します。

var listitems = {
    "Animals":[ "Dog", "Cat", "Elephant" ],
    "Fruits":[ "Apple", "Orange", "Grape" ],
    "Shapes":[ "Circle", "Rectangle", "Triangle" ]
};

本来は、このようなデータは、どこからのサーバから動的に取得する、という形になるのかもしれませんね。

動的に生成するページのテンプレートを用意する

リストビューのサブ階層を表示する場合は、その時点で動的に新しいページを作成します。
この新しいページのテンプレートを、あらかじめ用意しておきます。

<!-- Sub page template -->
<div id="subpage-template" data-role="page">
    <div data-role="header">
        <a data-rel="back">Back</a>
        <h1 id="title-template">Sub page</h1>
    </div>
    <div data-role="content">
        <ul id="listview-template" data-role="listview"></ul>
    </div>
</div>

リスト項目をタップしたときの処理を実装する

リスト項目をタップしたときのイベントハンドラを用意して、タップした項目のサブ項目を、リストビュー表示させます。

// リスト項目タップ時イベントハンドラ
$(document).on('click', '.listitem', function() {
    var subPageId = this.id;

    // 新しいページをテンプレートから生成します
    createSubPage(subPageId);
    // 新しいページのタイトルに、タップした項目の名称を設定します
    $('#title-' + subPageId).text(subPageId);
    // 新しいページ内のリストビューに、サブ項目を設定します
    var subitems = listitems[subPageId];
    var html = '';
    for (var i=0; i<subitems.length; i++) {
        var subitem = escapeHtmlTags(subitems[i]);
        html += '<li>' + subitem + '</li>';
    }
    // サブ項目追加後、jQuery Mobileの「listview()」メソッドを呼び出し、リストを更新します
    $('#listview-' + subPageId).empty().append(html).listview('refresh');

    // 新しいページに遷移します
    $.mobile.changePage($('#subpage-' + subPageId), { transition:"slide" });
});

完成

意外とシンプルに実現することができました。
実際に動作するサンプルは、以下をご参照ください。
(※Chromeブラウザの場合、サブリストページからの「Back」ボタンが正しく動作しないかもしれません。フルスクリーン表示だと問題ないかも。)

感想

何事も「DIY」精神をもってすれば、必ず実現できる、かもしれません。

しかしそもそも、jQuery Mobileの「階層化リストビュー」は、自動的にサブリストを表示してくれる反面、バグがいろいろ見つかっていたり、またサブリストのレイアウトがカスタマイズしにくかったり、といったデメリットもあったようです。

今回ご紹介した、DIY版「階層化リストビュー」を用いることで、このようなデメリットもいっしょに減らすことができるかもしれませんね。