head	1.9;
access;
symbols
	TIGRIS_1_1_0RC2:1.9
	TIGRIS_1_1_0RC1:1.9
	TIGRIS_1_1:1.9.0.4
	TIGRIS_1_0_8:1.9
	TIGRIS_1_0_8RC3:1.9
	TIGRIS_1_0_8RC2:1.9
	TIGRIS_1_0_8RC1:1.9
	TIGRIS_1_0_7:1.9
	TIGRIS_1_0_7RC3:1.9
	TIGRIS_1_0_7RC2:1.9
	TIGRIS_1_0_7RC1:1.9
	TIGRIS_1_0_6:1.9
	TIGRIS_1_0_6RC5:1.9
	TIGRIS_1_0_6RC4:1.9
	TIGRIS_1_0_6RC3:1.9
	TIGRIS_1_0_6RC2:1.9
	TIGRIS_1_0_6RC1:1.9
	TIGRIS_1_0_5:1.9
	TIGRIS_1_0_5RC6:1.9
	TIGRIS_1_0_5RC5:1.9
	TIGRIS_1_0_5RC4:1.9
	TIGRIS_1_0_5RC3:1.9
	TIGRIS_1_0_5RC2:1.9
	TIGRIS_1_0_5RC1:1.9
	TIGRIS_1_0_4:1.9
	TIGRIS_1_0_3:1.9
	TIGRIS_1_0_2:1.9
	TIGRIS_1_0_1:1.9
	TIGRIS_1_0:1.9.0.6
	TIGRIS_1_0_0:1.9
	TIGRIS_1_0_0_RC1:1.9.0.2
	dlr:1.1.1
	TIGRIS_0_9_2_4:1.7
	TIGRIS_0_9_2_3:1.7
	HELM_PEER_PORT_BRANCH:1.1.1.1
	TURBINE_PEER:1.7
	TIGRIS_0_9_2_1:1.7
	TIGRIS_0_9_2:1.7.0.2;
locks; strict;
comment	@# @;


1.9
date	2001.03.26.19.45.11;	author dlr;	state Exp;
branches;
next	1.8;

1.8
date	2001.02.21.01.56.43;	author edk;	state Exp;
branches;
next	1.7;

1.7
date	2001.01.04.01.01.20;	author dlr;	state Exp;
branches;
next	1.6;

1.6
date	2001.01.04.00.25.21;	author leonardr;	state Exp;
branches;
next	1.5;

1.5
date	2001.01.04.00.23.30;	author leonardr;	state Exp;
branches;
next	1.4;

1.4
date	2001.01.04.00.19.01;	author leonardr;	state Exp;
branches;
next	1.3;

1.3
date	2001.01.04.00.17.55;	author leonardr;	state Exp;
branches;
next	1.2;

1.2
date	2001.01.04.00.15.12;	author leonardr;	state Exp;
branches;
next	1.1;

1.1
date	2001.01.04.00.04.39;	author leonardr;	state Exp;
branches
	1.1.1.1;
next	;

1.1.1.1
date	2001.02.21.00.37.08;	author dlr;	state Exp;
branches;
next	;


desc
@@


1.9
log
@Properly order closing tags.
@
text
@<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
  <head>
    <title>Pagination for Fun and Profit</title>
  </head>

  <body>
    <h1>Pagination HOWTO</h1>
    Leonard Richardson &lt;leonardr at collab dot net&gt;<br>
    January 3, 2001<br>
    <small>$Id: pagination-HOWTO.html,v 1.8 2001/02/21 01:56:43 edk Exp $</small>

<p>An oft-taboo subject, pagination is slowly but surely making its
way into Helm. This article will show off the capabilities of the
pagination system, and hopefully give you the information you need to
use and to extend the current system.

<h2>Overview</h2>

<p>Pagination in Helm is done in the template, by methods called on an
avaliable variable which is a member of a PaginatableList
subclass. There are two breeds of PaginatableList:
PaginatablePrebuiltList and
PaginatableDatabaseBackedList. PaginatableDatabaseBackedList is
abstract and has a number of subclasses; PaginatablePrebuiltList is
directly instantiatable. All further subclasses of any of these
classes should go into the package org.tigris.helm.tool.paginate.

<h3>Class hierarchy</h3>

<pre>
+--ArrayList
   +--PaginatableList
      +--PaginatableDatabaseBackedList
         +--PaginatableProjectList
         +--PaginatableUserList
         +--...
      +--PaginatablePrebuiltList
</pre>

<h2>PaginatableList</h2>

<p>PaginatableList extends ArrayList, and the objects to be paginated
come by default from the ArrayList. Subclasses may use the list for
something else by overriding <code>getPage</code>; when this happens,
you may also have to override List methods like <code>iterator</code>
and <code>size</code>. PaginatableDatabaseBackedList does this (qv).

<h3>Basic pagination</h3>

<p>A basic level of functionality is common to all PaginatableList
subclasses. First, the <code>getPage</code> method, which takes an
Integer to be the page number, and returns a List of the items which
belong on that page (the number of items per page is set in the
constructor). If there are 10 items per page, and you call
<code>getPage(new Integer(4)</code>, you will be given items 31-40
(assuming there are that many items).

<h3>The navigation bar</h3>

<p>PaginatableList also has a method for creating a navigation bar
(<code>navigationBar</code>).  A maximum of ten links are displayed at
once, and a subclass-definable guide can be displayed alongside the
page number.

<p>Example navigation bars (with links intact):

<p><a href="ProjectList?paginated_page=3">Prev</a> 
| <a href="ProjectList?paginated_page=1">1 (C-D)</a> 
| <a href="ProjectList?paginated_page=2">2 (D-P)</a> 
| <a href="ProjectList?paginated_page=3">3 (P)</a> 
| 4 (P) 
| <a href="ProjectList?paginated_page=5">5 (P-U)</a> 
| <a href="ProjectList?paginated_page=6">6 (U-W)</a> 
| <a href="ProjectList?paginated_page=5">Next</a>
</p>

<p><a href="AuditLogList?paginated_page=3">Prev</a> 
| <a href="AuditLogList?paginated_page=1">1</a> 
| <a href="AuditLogList?paginated_page=2">2</a> 
| <a href="AuditLogList?paginated_page=3">3</a> 
| 4
| Next
</p>

<p>
Prev 
| 1 (D) 
| <a href="UserList?FILTER+VALUE%2Fname=m&FILTER+MATCHTYPE%2Fname=Contains&FILTER+CHECK=TRUE&paginated_page=2">2 (D-S)</a> 
| <a href="UserList?FILTER+VALUE%2Fname=m&FILTER+MATCHTYPE%2Fname=Contains&FILTER+CHECK=TRUE&paginated_page=3">3 (T-W)</a> 
| <a href="UserList?FILTER+VALUE%2Fname=m&FILTER+MATCHTYPE%2Fname=Contains&FILTER+CHECK=TRUE&paginated_page=2">Next</a>
</p>

<p>(This last example is a list of users whose name contains the letter
"m". Note how the links to each page contain the information
neccessary to recreate this filter criterion.)
</p>

<h2>PaginatablePrebuiltList</h2>

<p>If your business object already returns a List and you want to give
it the functionality provided by PaginatableList, just pass it to a
PaginatablePrebuiltList constructor--it takes only an Integer (items
per page) and the given List. An example showing how to convert a
business object method is below.

<p>Before:

<blockquote><code><pre>
public List getBigList()
{
    List l = getFirstList();
    l.addAll(getOtherList())
    return l;
}
</pre></code></blockquote>

<p>After:

<blockquote><code><pre>
public PaginatablePrebuiltList getBigList(Integer itemsPerPage)
{
    List l = getFirstList();
    l.addAll(getOtherList())
    return new PaginatablePrebuiltList(itemsPerPage, l);
}
</pre></code></blockquote>

<p>You can then access the paginated list from within a template,
almost exactly as you would have the original list. Be sure to add the
navigation bar afterwards, or only the first page will be visible.

<blockquote><code><pre>
#set $list = $businessObject.getBigList($itemsPerPage)
#foreach $entry in $list.getPage($paginated_page)
{
 ...
}
$list.navigationBar("ThisServlet", $paginated_page);
</pre></code></blockquote>

<h2>PaginatableDatabaseBackedList</h2>

<p>PaginatableDatabaseBackedList subclasses obtain their list from the
database, rather than from an already built list. This is more
flexible in some ways and less flexible in others.

<p>In addition to any subclass-specific arguments,
PaginatableDatabaseBackedList constructors accept a <code>SELECT</code> 
statement to pass to the database, a Criterion object (user-specified) which
will be translated to SQL and made part of the <code>WHERE</code> statement, 
and a series of fields to make into the <code>ORDER BY</code> clause.

<p>The actual list is a list of database <a href="http://www.working-dogs.com/village/village-1.1/docs/apidocs/com/workingdogs/village/Record.html">Records</a>, 
re-retrieved when neccessary. A method objectifyRecords instantiates a page 
worth of business objects from the records, and it is the list of business
objects generated by this method which is returned by <code>getPage</code>.

<h3>Alphabetic navbar guides</h3>

<p>PaginatableDatabaseBackedList subclasses can override
alphabetizedByField to return a field name. The guide on the
navigation bar will be constructed according to that field. For
instance, PaginatableProjectList specifies ProjectManager.PROJECT_NAME
for its alphabetic guide field. If a particular page of the list
begins with a project named "bar" and ends with a project named "foo",
the guide for that page will be "(B-F)". Of course, your subclass can
override navigationBar and provide any kind of information you want.

<h3>The filter form</h3>

<p>PaginatableDatabaseBackedList subclasses can harness the power of
filtering by filling out the filterableFields member, a Map which maps
field descriptions ("Name") to field names
(ProjectManager.PROJECT_NAME). The filter form is in the template
Filter.wm.

<p>The filter form has some limitations: it can only search text
fields (eg., no searching by date), and it can only search fields in
the table which is being used in the DatabaseBackedList's query (eg.,
no searching for projects to which a given user belongs).

<p>The following example is for a PaginatableUserList. Three fields
are searchable: UserManager.NAME, UserManager.LOGIN_ID, and
UserManager.EMAIL.

<hr>

<form>
<TABLE CELLPADDING="3" CELLSPACING="0" BORDER="0 WIDTH="100%">
  <TR>
    <TD colspan="3"><SPAN class="ProjectDownloadHeader">You may filter this list by the following
criteria:</SPAN></TD>
  </TR>
   <TR>
    <TD class="ProjectDownloadHeader">Real Name:</TD>
    <TD>
     <SELECT SIZE="1" NAME="FILTER MATCHTYPE/name">
      <OPTION VALUE=Contains>Contains
      <OPTION VALUE=StartsWith>Starts With
      <OPTION VALUE=EndsWith>Ends With
     </SELECT>
    </TD>
    <TD WIDTH="100%"><INPUT TYPE="TEXT" NAME="FILTER VALUE/name"
      VALUE="" SIZE="20" MAXLENGTH="32">
    </TD>
   </TR>
   <TR>
    <TD class="ProjectDownloadHeader">Login ID:</TD>
    <TD>
     <SELECT SIZE="1" NAME="FILTER MATCHTYPE/loginID">
      <OPTION VALUE=Contains>Contains
      <OPTION VALUE=StartsWith>Starts With
      <OPTION VALUE=EndsWith>Ends With
     </SELECT>
    </TD>
    <TD WIDTH="100%"><INPUT TYPE="TEXT" NAME="FILTER VALUE/loginID"
      VALUE="" SIZE="20" MAXLENGTH="32">
    </TD>
   </TR>
   <TR>
    <TD class="ProjectDownloadHeader">Email:</TD>
    <TD>
     <SELECT SIZE="1" NAME="FILTER MATCHTYPE/email">
      <OPTION VALUE=Contains>Contains
      <OPTION VALUE=StartsWith>Starts With
      <OPTION VALUE=EndsWith>Ends With
     </SELECT>
    </TD>
    <TD WIDTH="100%"><INPUT TYPE="TEXT" NAME="FILTER VALUE/email"
      VALUE="" SIZE="20" MAXLENGTH="32">
    </TD>
   </TR>

  <TR>
    <TD class="PlainText" valign="top" colspan="3">
    If you do not specify any filter criteria, you will see a full (paginated) list.</TD>
  </TR>
  <TR>
    <TD></TD>
    <TD colspan="2">
      <INPUT TYPE="SUBMIT" NAME="Button" VALUE="Search" onClick="test('Search')">&nbsp;
      <INPUT TYPE="RESET" NAME="Button" VALUE="Reset"></TD>
  </TR>
</TABLE>
</form>

<hr>

<h3>Example</h3>

<p>Here is an example of a template that gets a paginated list from a
business object, iterates over the list, then prints a navigation bar
and a filter form.</p>

<blockquote><code><pre>
#set $list=$businessObject.getPaginatedList($itemsPerPage, $args)
#foreach $entry in $list.getPage($paginated_page)
{
 ...
}
$list.navigationBar("ThisServlet", $paginated_page);

&lt;hr&gt;

&lt;FORM METHOD="post" ACTION="ThisServlet"&gt;
#parse "$SERVLET_TEMPLATE_ROOT;/org/tigris/helm/tool/paginate/Filter.wm" 
&lt;/FORM&gt;
</pre></code></blockquote>

<h2>Conclusion</h2>

<p>Hopefully by now you have an idea of the capabilities of the
pagination system. If you commit some new functionality or feel that
something is missing from this document, please feel free to email
me. As the author of the pagination system, I'm also able (I hope) to
answer all your pagination questions.

  </body>
</html>
@


1.8
log
@add new files from the branch to the head (there should be only added
files, ie. no modified files).
@
text
@d11 1
a11 1
    <small>$Id: pagination-HOWTO.html,v 1.1.1.1 2001/02/21 00:37:08 dlr Exp $</small>
d116 1
a116 1
</pre></blockquote></code>
d127 1
a127 1
</pre></blockquote></code>
d140 1
a140 1
</pre></blockquote></code>
d269 1
a269 1
</pre></blockquote></code>
@


1.7
log
@* Added CVS Id tag.
* Increased indentation of method bodies.
* Added some CODE HTML tags.
* Linked to the JavaDoc for Village's Record class.
* Corrected some HTML that was supposed to show up literally.
@
text
@d11 1
a11 1
    <small>$Id: $</small>
@


1.6
log
@Added pre tags back in.
@
text
@d10 2
a11 1
    January 3, 2001
d112 3
a114 3
 List l = getFirstList();
 l.addAll(getOtherList())
 return l;
d123 3
a125 3
 List l = getFirstList();
 l.addAll(getOtherList())
 return new PaginatablePrebuiltList(itemsPerPage, l);
d149 9
a157 9
PaginatableDatabaseBackedList constructors accept a SELECT statement
to pass to the database, a Criterion object (user-specified) which
will be translated to SQL and made part of the WHERE statement, and a
series of fields to make into the ORDER BY clause.

<p>The actual list is a list of database Records, re-retrieved when
neccessary. A method objectifyRecords instantiates a page worth of
business objects from the records, and it is the list of business
objects generated by this method which is returned by getPage.
d266 1
a266 1
<FORM METHOD="post" ACTION="ThisServlet">
d268 1
a268 1
</FORM>
@


1.5
log
@Changed tags.
@
text
@d108 1
a108 1
<blockquote><code>
d115 1
a115 1
</blockquote></code>
d119 1
a119 1
<blockquote><code>
d126 1
a126 1
</blockquote></code>
d132 1
a132 1
<blockquote><code>
d139 1
a139 1
</blockquote></code>
d255 1
a255 1
<blockquote><code>
d268 1
a268 1
</blockquote></code>
@


1.4
log
@Fixed typo.
@
text
@d108 1
a108 1
<pre>
d115 1
a115 1
</pre>
d119 1
a119 1
<pre>
d126 1
a126 1
</pre>
d132 1
a132 1
<pre>
d139 1
a139 1
</pre>
d255 1
a255 1
<pre>
d268 1
a268 1
</pre>
@


1.3
log
@Minor changes.
@
text
@d261 1
a261 1
$paginatableList.navigationBar("ThisServlet", $paginated_page);
@


1.2
log
@Updates to pagination HOWTO.
@
text
@d9 1
a9 1
    Leonard Richardson &lt;leonardr at collab dor net&gt;<br>
d77 1
a77 1
<p><a href="AuditLogList?paginated_page=2">Prev</a> 
d80 3
a82 3
| 3 
| <a href="AuditLogList?paginated_page=4">4</a> 
| <a href="AuditLogList?paginated_page=4">Next</a>
d86 6
a91 1
Prev | 1 (D) | <a href="UserList?FILTER+VALUE%2Fname=m&FILTER+MATCHTYPE%2Fname=Contains&FILTER+CHECK=TRUE&paginated_page=2">2 (D-S)</a> | <a href="UserList?FILTER+VALUE%2Fname=m&FILTER+MATCHTYPE%2Fname=Contains&FILTER+CHECK=TRUE&paginated_page=3">3 (T-W)</a> | <a href="UserList?FILTER+VALUE%2Fname=m&FILTER+MATCHTYPE%2Fname=Contains&FILTER+CHECK=TRUE&paginated_page=2">Next</a><br><br>
d93 3
a95 3
(This is a list of users whose name contains the letter "m". Note how
the links to each page contain the information neccessary to recreate
this filter criterion.)
@


1.1
log
@Added pagination HOWTO
@
text
@d9 1
a9 1
    Leonard Richardson &lt;<a href="mailto:leonardr at collab dot net">leonardr@@collab.net</a>&gt;<br>
d65 1
a65 1
<p>Example navigation bars:
d67 16
a82 7
<p><a href="ProjectList?paginated_page=3">Prev</a> | <a
href="ProjectList?paginated_page=1">1 (C-D)</a> | <a
href="ProjectList?paginated_page=2">2 (D-P)</a> | <a
href="ProjectList?paginated_page=3">3 (P)</a> | 4 (P) | <a
href="ProjectList?paginated_page=5">5 (P-U)</a> | <a
href="ProjectList?paginated_page=6">6 (U-W)</a> |
<a href="ProjectList?paginated_page=5">Next</a>
d86 6
a91 2
Prev | 1 (D) | <a href="UserList??FILTER+VALUE%2Fname=m&FILTER+MATCHTYPE%2Fname=Contains&FILTER+CHECK=TRUE&paginated_page=2">2 (D-S)</a> | <a href="UserList??FILTER+VALUE%2Fname=m&FILTER+MATCHTYPE%2Fname=Contains&FILTER+CHECK=TRUE&paginated_page=3">3 (T-W)</a> | <a href="UserList??FILTER+VALUE%2Fname=m&FILTER+MATCHTYPE%2Fname=Contains&FILTER+CHECK=TRUE&paginated_page=2">Next</a>
</p>      
d181 2
d242 2
a263 1

@


1.1.1.1
log
@Replacing the HEAD with the HELM_PEER_PORT_BRANCH.
@
text
@d9 2
a10 3
    Leonard Richardson &lt;leonardr at collab dot net&gt;<br>
    January 3, 2001<br>
    <small>$Id: pagination-HOWTO.html,v 1.7 2001/01/04 01:01:20 dlr Exp $</small>
d65 1
a65 1
<p>Example navigation bars (with links intact):
d67 7
a73 16
<p><a href="ProjectList?paginated_page=3">Prev</a> 
| <a href="ProjectList?paginated_page=1">1 (C-D)</a> 
| <a href="ProjectList?paginated_page=2">2 (D-P)</a> 
| <a href="ProjectList?paginated_page=3">3 (P)</a> 
| 4 (P) 
| <a href="ProjectList?paginated_page=5">5 (P-U)</a> 
| <a href="ProjectList?paginated_page=6">6 (U-W)</a> 
| <a href="ProjectList?paginated_page=5">Next</a>
</p>

<p><a href="AuditLogList?paginated_page=3">Prev</a> 
| <a href="AuditLogList?paginated_page=1">1</a> 
| <a href="AuditLogList?paginated_page=2">2</a> 
| <a href="AuditLogList?paginated_page=3">3</a> 
| 4
| Next
d77 2
a78 11
Prev 
| 1 (D) 
| <a href="UserList?FILTER+VALUE%2Fname=m&FILTER+MATCHTYPE%2Fname=Contains&FILTER+CHECK=TRUE&paginated_page=2">2 (D-S)</a> 
| <a href="UserList?FILTER+VALUE%2Fname=m&FILTER+MATCHTYPE%2Fname=Contains&FILTER+CHECK=TRUE&paginated_page=3">3 (T-W)</a> 
| <a href="UserList?FILTER+VALUE%2Fname=m&FILTER+MATCHTYPE%2Fname=Contains&FILTER+CHECK=TRUE&paginated_page=2">Next</a>
</p>

<p>(This last example is a list of users whose name contains the letter
"m". Note how the links to each page contain the information
neccessary to recreate this filter criterion.)
</p>
d90 1
a90 1
<blockquote><code><pre>
d93 3
a95 3
    List l = getFirstList();
    l.addAll(getOtherList())
    return l;
d97 1
a97 1
</pre></blockquote></code>
d101 1
a101 1
<blockquote><code><pre>
d104 3
a106 3
    List l = getFirstList();
    l.addAll(getOtherList())
    return new PaginatablePrebuiltList(itemsPerPage, l);
d108 1
a108 1
</pre></blockquote></code>
d114 1
a114 1
<blockquote><code><pre>
d121 1
a121 1
</pre></blockquote></code>
d130 9
a138 9
PaginatableDatabaseBackedList constructors accept a <code>SELECT</code> 
statement to pass to the database, a Criterion object (user-specified) which
will be translated to SQL and made part of the <code>WHERE</code> statement, 
and a series of fields to make into the <code>ORDER BY</code> clause.

<p>The actual list is a list of database <a href="http://www.working-dogs.com/village/village-1.1/docs/apidocs/com/workingdogs/village/Record.html">Records</a>, 
re-retrieved when neccessary. A method objectifyRecords instantiates a page 
worth of business objects from the records, and it is the list of business
objects generated by this method which is returned by <code>getPage</code>.
a167 2
<hr>

a226 2
<hr>

d233 1
a233 1
<blockquote><code><pre>
d239 1
a239 1
$list.navigationBar("ThisServlet", $paginated_page);
d243 1
a243 1
&lt;FORM METHOD="post" ACTION="ThisServlet"&gt;
d245 3
a247 2
&lt;/FORM&gt;
</pre></blockquote></code>
@


