はじめに
Webページを実用に耐えないものにする方法はいくつもあります。雑然としたコンテンツ、お粗末なページレイアウト、明暗の差がない色遣いなどさまざまです。ページをすぐにも実用に耐えないものにする簡単な方法の1つは、「データの詰めすぎ」の状態を作り出すことです。データの詰めすぎの問題を抱えるページでは、1つのページに過剰な量の情報が表示されます。たとえば、多数のフィールドから成るデータベースレコードが何十件も表示されるようなページです。
データの詰めすぎを緩和する方法は、いくつもあります。データをページに分けて参照できるようにする方法や、データベースフィールドの一部のみを表示して、各レコードに「詳細」リンクを設け、リンクをクリックするとそのレコードの全フィールドが表示されるようにする方法などがあります。もう1つの――驚くほど簡単なうえ、私見ではとても本格的に見える――方法は、データを折りたたみ可能な形式で表示することです。具体的には、各データベースレコードの短い見出しだけを表示して、詳細は隠しておきます。詳細を表示するには、この見出しをクリックします。すると、詳細が自動的に表示されるというしくみです。これを実現するのに必要なものは、小さな気の利いたDHTMLと、クライアント側のJavaScriptだけです。どのようなものができるかをこっそり覗いてみたい方は、このライブデモをご覧ください。
本稿では、Repeaterを使ってデータを折りたたみ可能な形で表示する方法について説明します。本稿を読み終わるころには、データの詰めすぎを起こさない、しゃれたユーザーインターフェイスを作成するために必要な考え方が身についているでしょう。
クライアント側の操作でコンテンツの表示/非表示を切り替える
何年も前、まだブラウザのバージョンが4.xだったころから、クライアント側の操作に応じてWebページのコンテンツを表示したり非表示にしたりすることは、かなり簡単にできるようになっています。たとえば、ボタンがクリックされたときに<div>
タグのコンテンツを動的に非表示にすることや、マウスが別のコンテンツ領域に移動したときに段落の内容(つまり<p>
タグ内のコンテンツ)を表示することができます。
Webページのデータの表示/非表示を切り替えるトリックの「タネ」は、要素のdisplay
およびvisibility
スタイル設定です。次のHTMLコードは、ボタンがクリックされたときに特定のHTML要素のスタイル設定を切り替えて、コンテンツを表示したり非表示にしたりする方法を示しています。コードに続くインタラクティブデモで、このHTMLを試すことができます。
<script language="JavaScript"> function showHideContent(id, show) { var elem = document.getElementById(id); if (elem) { if (show) { elem.style.display = 'block'; elem.style.visibility = 'visible'; } else { elem.style.display = 'none'; elem.style.visibility = 'hidden'; } } } </script> <div id="someRegion"> This text will be displayed or hidden when clicking the appropriate button below... </div> <input type="button" value = "Hide Content" onclick="showHideContent('someRegion', false);"> <input type="button" value = "Show Content" onclick="showHideContent('someRegion', true);">
このインタラクティブデモを見るとわかるように、わずかなクライアント側スクリプトを使うだけで、HTML要素のdisplay
およびvisiblity
スタイル設定を変更し、それによって要素の表示/非表示を動的に切り替えることができます。これはすべてクライアント側で行われ、ポストバックは必要ありません。要素のスタイルを変更するために、document.getElementById(id)
メソッドを使って要素をIDで取得していることに注意してください。その後、取得した要素に適切なプロパティを設定しています。DHTMLの詳細に関しては、本稿では説明しません。DHTMLに関する参考資料はWeb上で数多く公開されているので、そちらを参照してください。
折りたたみ可能なインターフェイスで詳細データを表示する
ちょっとした手間をかければ、この概念をASP.NET Webページに表示されるデータに適用することができます。多数のフィールドから成るレコードを表示するページがあると、そのページはたちまち手に負えなくなってしまいます。たとえば、ASPFAQs.comにあるFAQについての情報を表示するとします。各FAQはtblFAQs
テーブルのレコードとして格納されており、レコードにはFAQ、回答、FAQの参照回数、FAQの投稿者、その他の関連情報が含まれています。この情報をRepeaterを使ってASP.NET Webページに表示するとしましょう。そのためには、次のようなRepeater構文を使います。
<asp:Repeater id="rptFAQs" runat="server"> <ItemTemplate> <h2><%# DataBinder.Eval(Container.DataItem, "Description") %> </h2><br /> <b>Submitted By:</b> <%# DataBinder.Eval(Container.DataItem, "SubmittedByName") %> <br /> <b>Views:</b> <%# DataBinder.Eval(Container.DataItem, "ViewCount", "{0:d}") %> <br /> <b>FAQ:</b><br /> <%# DataBinder.Eval(Container.DataItem, "Answer") %> </ItemTemplate> </asp:Repeater>
ライブデモを見るとわかるように、これでは少し情報の詰めすぎです。その主な原因は、各FAQの回答がかなり長くなる場合があるからです。
ユーザーインターフェイスをもっと扱いやすくするには、すべてのFAQでこの大量のデータを表示するのではなく、個々のFAQをクリックして、目的のFAQの詳細だけを表示できるようにします。ユーザーが質問の見出しをクリックすると、クライアント側のDHTML/JavaScriptによって見出しが展開され、FAQの詳細が表示されます。これを実現するには、RepeaterのItemTemplate
内でちょっと気の利いたマークアップを使います。
まず、各レコードに対して2つの<div>
を作成します。1つはFAQの質問を表示するため、もう1つは詳細情報(回答、参照数など)を表示するために使います。1つ目の<div>
はすべてのレコードで必ず表示され、クリックされると、関連付けられた詳細情報の<div>
の表示/非表示を切り替えます。これを行うには、各<div>
に一意のid値を与える必要があります。このid値は、表示/非表示を切り替えるクライアント側のJavaScript関数で参照されます。具体的には、各FAQの質問<div>
に「hindex」というidを割り当てます。このindexには、RepeaterアイテムのItemIndex
が入ります。個々の詳細情報<div>
には「dindex」というidを割り当てます。
次に示すのは、折りたたみ可能なRepeaterのItemTemplate
と、見栄えを良くするCSSクラス、および表示を切り替えるクライアント側のJavaScript関数です。
<script language="JavaScript"> function ToggleDisplay(id) { var elem = document.getElementById('d' + id); if (elem) { if (elem.style.display != 'block') { elem.style.display = 'block'; elem.style.visibility = 'visible'; } else { elem.style.display = 'none'; elem.style.visibility = 'hidden'; } } } </script> <style> .header { font-size: larger; font-weight: bold; cursor: hand; cursor:pointer; background-color:#cccccc; font-family: Verdana; } .details { display:none; visibility:hidden; background-color:#eeeeee; font-family: Verdana; } </style> <asp:Repeater id="rptFAQs" runat="server"> <ItemTemplate> <div id='h<%# DataBinder.Eval(Container, "ItemIndex") %>' class="header" onclick='ToggleDisplay( <%# DataBinder.Eval(Container, "ItemIndex") %>);'> <%# DataBinder.Eval(Container.DataItem, "Description") %> </div> <div id='d<%# DataBinder.Eval(Container, "ItemIndex") %>' class="details"> <b>Submitted By:</b> <%# DataBinder.Eval(Container.DataItem, "SubmittedByName") %> <br /> <b>Views:</b> <%# DataBinder.Eval(Container.DataItem, "ViewCount", "{0:d}") %> <br /> <b>FAQ:</b><br /> <%# DataBinder.Eval(Container.DataItem, "Answer") %> </div> </ItemTemplate> </asp:Repeater>
このコードには、いくつかの留意点があります。まず、各ItemTemplate
の2つの<div>
要素に、RepeaterItem
のインデックス値を含むidを割り当てている点に注目してください。このインデックス値は、ItemIndex
プロパティから取得されます。さらに、質問<div>
のクライアント側onclickイベントでは、ToggleDisplay()
というJavaScript関数を呼び出して、クリックされた質問行のインデックスを渡しています。このToggleDisplay()
関数は、その行の詳細情報<div>
のdisplay
およびvisibility
のスタイル設定を切り替えます。
折りたたみ可能なRepeaterの実際の動作を確認するために、ぜひライブデモをご覧ください。おそらく、ページがはるかに簡潔になり、情報の詰めすぎが解消されているということに同意していただけるでしょう。
それでは、ハッピープログラミング!