Locked History Actions

Diff for "wicket/BreadCrumbs"

Differences between revisions 8 and 9
Deletions are marked like this. Additions are marked like this.
Line 2: Line 2:

'''※このページは考慮中です。'''
Line 9: Line 6:
== パンくずリストの要件 == == パンくずリストのそもそもの問題 ==
Line 11: Line 8:
=== 目標とする形 === パンくずリストを使って、一つの同じページに到達するのに別々のルートを通った場合の表現を行うのは非常に困難である。
また、経路途中の特定の状態を保持するのも困難である。以下の二つのパンくずリストを考えてみる。
{{{
トップ / 顧客一覧 / 顧客A
}}}
{{{
トップ / 製品一覧 / 製品B / 製品B購入者一覧 / 顧客A
}}}
いずれの場合も、現在顧客Aのページを表示しているが、そこにいたるまでの経路はそれぞれ異なる。このパンくずリストのいずれかのエントリをクリックすると、そのページを表示したいとする。
Line 13: Line 18:
パンくずリストは以下のような構成となる。 しかしこれは非常に難しい、例えば、今現在表示中の顧客Aのページがブックマーク可能であるとすると、そのブックマークは
Line 15: Line 20:
トップ / 顧客グループ一覧 / A店顧客一覧 / 顧客X
~~~~ ~~~~~~~~~~~~~~ ~~~~~~~~~~
http://localhost/customer?id=1234
Line 18: Line 22:
現在ページをトップからのパスで示し、現在ページ以外のページ名はそのページへのリンクとする。これらのリンクをクリックすることで、そのページへの遷移を行う。 ではありえない。なぜなら、これでは顧客Aのページということはわかるのだが、その途中の経路情報が一切無いからである。これをあえて表示しようとすれば、
{{{
トップ / 顧客A
}}}
となるしかない。もし前者の経路を表現しようとするなら、
{{{
http://localhost/?path0=top&path1=customerList&path2=customer&id=1234
}}}
などとしなければならないだろうし、後者の経路は
{{{{
http://localhost/?path0=top&path1=products&path2=product&path3=buyers&path4=customer?id=1234
}}}
などという情報が必要である(パラメータはかなり適当)。これらの情報があって初めてブックマークされたページのパンくずリストが再現可能になる。
Line 20: Line 36:
=== 構成ページの要件 === しかし、これを実現するのは極めて煩雑である。ページ遷移のたびに、そのパラメータとして前のページに与えられたパラメータを積み重ねていかなければならない。また、そこまでの必要性があるかどうかは疑問である。
Line 22: Line 38:
==== 要件1 ==== もし、以下のように購入者一覧ページを表示中にその中から顧客Aが選択されたら、
{{{
トップ / 製品一覧 / 製品B / 製品B購入者一覧
}}}
以下のように顧客Aの「ごく普通のパス」に変更されてしまっても問題は無いと思われる。
{{{
トップ / 顧客一覧 / 顧客A
}}}
さらに、
{{{
トップ / 製品一覧 / 製品B / 製品B購入者一覧
}}}
のパンくずリストでは、途中の「製品B」というパスが再現されなければならないが、これもパンくずリストの記述を省略することによって対応すべきであろう。つまり、
{{{
トップ / 製品一覧
}}}
の状態で製品Bが選択されたら
{{{
トップ / 製品一覧 / 製品B
}}}
となるが、このページにおいて、製品Bの購入者一覧がクリックされたら、
{{{
トップ / 製品一覧 / 製品B購入者一覧
}}}
などと省略することにする。
Line 24: Line 64:
当然のことながら、パンくずリストに表示されるページは「右端ページ」(この場合は顧客X)を除いてブックマーク可能でなくてはいけない。でなければ、リンクをクリックした時にそのページに戻ることができない。 == ページの木構造 ==
Line 26: Line 66:
もちろん、Wicketの場合は、ブックマーク不可能なページでもページキャッシュに格納されているため、何らかの方法でそのページを「再生」することはできると思われるが、しかしページキャッシュはいつクリアされるかわからない。リンクをクリックされた時に「ページキャッシュに格納されたであろう個別状態」を再生するには、ページキャッシュから取得するか、それができなければそのページが作成された時の条件(ページパラメータ)を指定して再作成するしかない。 上に述べたように、ユーザの通った経路をパンくずリストとして逐一記録していくのは困難であるため、途中経路については以下の方針でいくしかない。
Line 28: Line 68:
結局のところ、ページキャッシュに依存することはできないので、そのページを再生成可能なように、ページパラメータ付のコンストラクタを用意し、生成時のページパラメータ自体をパンくずリストに保持しなければならない。もちろん、ページパラメータ不要な場合は、引数無しコンストラクタがあればよい。  * 各ページは一つの木構造の中の固定的な位置を占める。
Line 30: Line 70:
したがって、この場合にもし顧客Xがブックマーク可能であるならば、以下の二つのうちいずれかを実現しなくてはならない。

 * ブックマークされた顧客Xページのパラメータとして、顧客Xを示すパラメータのほかにその上位すべてのページ(顧客グループ一覧、A店顧客一覧)を再生できるようなパラメータが付加されていなければならない。
 * 上位すべてのページのパラメータが付加できないのであれば、顧客Xページにいたるパスが固定されていなければならない。

==== 要件2 ====

ページ階層は「右端ページ」を除いて、固定していなければならない。逆に言えば、階層の固定していないページは、「右端ページ」以外には現れることができない。これは純粋にユーザビリティ上の問題である。

例としたパンくずリストでは、以下のようになっているが、
{{{
トップ / 顧客グループ一覧 / A店顧客一覧 / 顧客X
~~~~ ~~~~~~~~~~~~~~ ~~~~~~~~~~
}}}
以下のようなパンくずが作成できてしまってはいけない。
{{{
トップ / A店詳細 / A店顧客一覧 / 顧客X
~~~~ ~~~~~~~ ~~~~~~~~~~
}}}

なぜなら、いずれの場合でも「A店顧客一覧」をクリックすると、その顧客一覧ページが表示されるが、このときのパンくずは、
{{{
トップ / 顧客グループ一覧 / A店顧客一覧
~~~~ ~~~~~~~~~~~~~~
}}}
とすべきか、
{{{
トップ / A店詳細 / A店顧客一覧
~~~~ ~~~~~~~
}}}
とすべきか決定することができないからである。「パンくずの内容を見て、それぞれの階層として表示すればいいではないか」と思うかもしれないが、それではうまくいかない。
もしユーザがA店顧客一覧を表示中にそれをブックマークしたとする。それを後で表示した場合、パンくずとしてどちらの階層を表示すべきかは決定できない。

したがって、パンくずリストに現れる右端ページ以外は、以下のようなきれいな木構造となっていなければならない。
つまり、ページの構成は以下のようになり、
Line 67: Line 74:
| +- C
Line 68: Line 76:
| +- E
+- C
+- E
Line 71: Line 78:
   +- G     +- G
Line 73: Line 80:
あるページを表示すると、そこからトップにいたるまでのパスが固定的にパンくずリストとして表示されるということである。また、
Line 74: Line 82:
=== 右端ページについて ===  * ただし、途中のページについてはパラメータ付であってはならない(パラメータによって表示内容が変わってはいけない)が、最後のページ(パンくずリストの右端)については、パラメータ付でもよいものとする。
Line 76: Line 84:
右端ページについては、もしブックマーク可能でないならば、複数の階層に現れることができる。 途中のページのパラメータについては(不可能ではないものの)保持するのは非常に煩雑になる。これに対して最後のページ(現在表示中のページ)についてはパラメータ付でもよい。これをブックマークして再生するとこのページを完全に再生できるし、途中のページのリンクもまた完全に再生することができる(パスが固定しており、パラメータが存在しない)。
Line 78: Line 86:
{{{
トップ / 顧客グループ一覧 / A店顧客一覧 / 顧客X
~~~~ ~~~~~~~~~~~~~~ ~~~~~~~~~~
}}}
この場合、顧客Xのページはブックマークされないので、後からこのパンくずを再生する必要はない。したがって、
{{{
トップ / 製品一覧 / 購入者一覧 / 顧客X
~~~~ ~~~~~~~~ ~~~~~~~~~
}}}

のいずれのパンくずにも現れることが可能である。もちろんこれに対してブックマーク可能な場合は、階層を固定しなくてはいけない。

=== 要件のまとめ ===

 * 基本的にパンくずとして表示されるページはブックマーク可能でなければならないが、ただし
  * 右端だけにはブックマーク不可能なページが現れても問題ない。
  * 右端以外にブックマーク不可能なページが現れた場合には、そのページのリンクは表示できない。
 * ブックマーク可能なページが表示されたときに、何らかのページパラメータが指定されているのであれば、パンくずをクリックした時もそのページパラメータを指定して再作成できなければならない。

== 実装の方針 ==

=== ページパラメータの再生問題 ===

パンくずリスト上にあるリンクをクリックされた時には、それがページパラメータ付である場合は、そのページをページパラメータ付で作成したい。逆にいえば、あらかじめリンクにはこれらのパラメータを仕込んでおく必要がある。

しかし、これは非常に難しい。以下のようなパンくずリストがあり、

{{{
トップ / 製品一覧 / 購入者一覧 / 顧客X
~~~~ ~~~~~~~~ ~~~~~~~~~
}}}

この中の「製品一覧」ページが実は「group=冬物」というパラメータ指定がされている冬物製品の一覧であったとすると、このパンくずのリンクには、そのパラメータが含まれていなければならない。そして、「製品一覧」をクリックされたら、その冬物製品一覧を表示しなければならない。

さらに、元のパンくずリストで「購入者一覧」をクリックされた場合は、
{{{
トップ / 製品一覧 / 購入者一覧
~~~~ ~~~~~~~~
}}}
というパンくずを表示しなければならないが、この場合にも製品一覧には冬物指定がなければいけない。つまり、「購入者一覧」のリンクには(もしあれば)購入者一覧ページのパラメータだけではなく、その上位の製品一覧ページのパラメータも含まれていなければならない。これは非常に面倒である。

おそらく、このような仕様の実現は複雑な割にメリットはあまりないと思われるので、ブックマーク可能ページのパラメータは今回の実装では諦めることにする。

=== その他の実装上の決定 ===

 * あるページがブックマーク可能であり、どのようなURLにマウントし、どのようなタイトルを持ち、どのページが木構造の親であるかを示すには、そのページクラス自体にアノテーションをつけることによって示す。この情報は以下の場所で使われる。
  * あるページのパンくずを作成するためのパスリストの作成。
  * メニューページに表示されるそのページのタイトル。
  * Application初期化時にそのページをマウントするURLの取得
 * ブックマーク可能ページの表示あるいは他の可能ページへの遷移時には、パンくずのためのパスリストは上の情報から自動的に取得することができる。ブックマーク不能ページへの遷移時には、そのページ生成時に親ページのパスを明示的に与えることにより、そのページ自体のパスリストを作成するようにする。

パンくずリストの実現

wicket-extensionsにパンくずリストパネルが用意されているが、これは使い物にならない。 ここでは独自のパンくずリストの実装について考えてみる。

パンくずリストのそもそもの問題

パンくずリストを使って、一つの同じページに到達するのに別々のルートを通った場合の表現を行うのは非常に困難である。 また、経路途中の特定の状態を保持するのも困難である。以下の二つのパンくずリストを考えてみる。

トップ / 顧客一覧 / 顧客A

トップ / 製品一覧 / 製品B / 製品B購入者一覧 / 顧客A

いずれの場合も、現在顧客Aのページを表示しているが、そこにいたるまでの経路はそれぞれ異なる。このパンくずリストのいずれかのエントリをクリックすると、そのページを表示したいとする。

しかしこれは非常に難しい、例えば、今現在表示中の顧客Aのページがブックマーク可能であるとすると、そのブックマークは

http://localhost/customer?id=1234

ではありえない。なぜなら、これでは顧客Aのページということはわかるのだが、その途中の経路情報が一切無いからである。これをあえて表示しようとすれば、

トップ / 顧客A

となるしかない。もし前者の経路を表現しようとするなら、

http://localhost/?path0=top&path1=customerList&path2=customer&id=1234

などとしなければならないだろうし、後者の経路は