2010-10-24

ページ切り替え機構の切り替え - Blogger Glass

今回はちょっと実験。2 種類のページ切り替えの仕組みを用意し、どちらが使いやすいかを確かめる実験だ。

「ページ切り替え」と言うのは、Blogger Glass の一覧表示系の画面の下部に出てくるもののこと。リストする項目が多いときには複数のページに分割する。そのページを切り替えるための仕組みだ。

現状では、Google の検索結果に出てくるモノ(Goooooooooogle! のようになるアレだ)を真似ている。これをもっとシンプルな「Next」「Prev」ボタンのものと比較してみようと思ったのだ。

2 つの方式の比較

実験というからには、2 つを比較できなければ意味がない。旧来の方式と新しい方式を両方使えるようにしておいて、実際に使ってみて試すわけだ。

幸い、一覧表示系の画面(機能)は「一覧画面」と「検索結果画面」の 2 種類がある。このうち、「一覧画面」のみを新方式にして、「検索結果画面」の方は従来のままにしておく。そうすれば、どちらの方式も試すことができる。

まあ、配備ずみの正式版(appspot で稼動しているもの)と開発中のローカル版(SDK で動かしているもの)で比較するという手もあるんだがね。

リファクタリング

「ページ切り替え機構」を簡単に取り替えられるようにするため、src/info.py、さらに src/main.pysrc/searchview.py にも手を入れる。

具体的には、「ページ切り替え機構」そのものを ViewInfo のインスタンスで抱え、表示対象のページ番号や全ページ数は「ページ切り替え機構」の属性に押し込める。リクエストハンドラは「ページ切り替え機構」を選び、ViewInfo のインスタンスにセットすることになる。

「ページ切り替え機構」は、util.Pager クラスを基底として派生させる。旧方式は util.GlassPager と名付けた。

(src/util.py より)
class Pager(object):
    PAGESIZE = 25
    def __init__(self, page_num, total_posts):
        self.current = page_num
        self.total_pages = 0
        if total_posts > 0:
            self.total_pages = (total_posts - 1) // Pager.PAGESIZE + 1
        else:
            self.total_pages = 1

class GlassPager(Pager):
    class Page(object):
        def __init__(self, number, current=False):
            self.number = number
            self.current = current

    def __init__(self, page_num, total_posts):
        Pager.__init__(self, page_num, total_posts)
        self.pages = []
        for p in range(self.total_pages):
            self.pages.append(GlassPager.Page(p, p == page_num))

src/main.pyMainHandler で「ページ切り替え機構」をセットする付近のコードを示す。

(src/main.py)
            total_posts = int(feed.total_results.text)
            self.viewinfo.pager = util.PrevNextPager(page, total_posts)
            self.viewinfo.start_index = start_index

結果として、ページ切り替えに関する情報の生成と詰め直しを追い出したことになり、少しすっきりした。

シンプルなページ切り替え

ごく単純な「Prev」「Next」の 2 つのボタン(リンク)のある方式で、最初と最後へのショートカットを持っている。つまり、こんな感じになる。

[Top] [Prev] <current page #> [Next] [Last]

また、現在のページが最初のときは「Top」と「Prev」は表示せず、最後のときは同様に「Next」と「Last」を表示しない。

これを実現するための util.Pager の派生クラスは以下のようになる。

(src/util.py より)
class PrevNextPager(Pager):
    def __init__(self, page_num, total_posts):
        Pager.__init__(self, page_num, total_posts)

        if self.total_pages > 0:
            self.last = self.total_pages - 1

        if self.current != 0:
            self.is_top = False
            self.prev = self.current - 1
        else:
            self.is_top = True
            self.prev = 0

        if self.current != self.last:
            self.is_last = False
            self.next = self.current + 1
        else:
            self.is_last = True
            self.next = self.last

で、これを表示するテンプレートはこう。

(src/listview.html より)
{% block view_footer %}
<nav>
  <div class="pager">
    {% if not view.pager.is_top %}
    <span class="l-button"><a href="/?page=0">Top</a></span>
    <span class="l-button"><a href="/?page={{ view.pager.prev }}">Prev</a></span>
    {% endif %}
    <span id="pager-current">{{ view.pager.current }}</span>
    {% if not view.pager.is_last %}
    <span class="r-button"><a href="/?page={{ view.pager.next }}">Next</a></span>
    <span class="r-button"><a href="/?page={{ view.pager.last }}">Last</a></span>
    {% endif %}
  </div>
</nav>
{% endblock %}

info.Menu クラスと同様に、util.Pager クラス(とそのサブクラス)は info モジュールに移すべきかな。

「Goooooooooogle!」方式と「前後」方式

実際に使ってみたところ、「Goooooooooogle!」方式にはとくにメリットがないと感じた。この方式では途中のページにダイレクトに飛べるわけだが、そこに何がリストされているかがわかっていない限りほとんど意味がない。リストを順にたどって見るようなときには「前後」方式の方が切り替えやすい(マウスを動かさなくても良いから)。まとめて何ページも先を開くなら「Goooooooooogle!」方式の方が便利だが、実用上そういう場面が思い浮かばない。

特定の時期に書かれた記事を探すなら大きく前後に移動できた方が便利だが、そういう便利さを実現したいなら月や週で検索できる画面(ビュー)を用意した方が良い。

iPhone のような画面の狭いデバイスの場合も「前後」方式が適している。特定のページを直接開くというユーザ体験を実現するなら、それ専用の画面(ビュー)を作るべきだ。

「一覧」や「検索」といった機能を実行した結果が複数のページに分かれる場合、シンプルな前後方式の方が汎用性が高い(画面のサイズを選ばないから)。そもそも(大量の)複数ページに分かれているという点でユーザ体験としては減点だろう。ユーザが意識して「全部を順番に見たい」というのでない限り、適切に絞り込む手段を提供すべき。そして、適切に絞り込めるなら(ページ数にしてせいぜい 2 〜 3)「前後」方式が(ユーザに余分なことを考えさせないという意味で)直感的だ。

関連リンク

関連記事

0 件のコメント:

コメントを投稿