Tuesday, July 17, 2007

Paginate your Lists

Pagination is a bare necessity when it comes to handling lists in your web applications. And a good pagination always makes your application more user friendly. Google, the foremost search engine has one of the best Pagination for it. So this article helps you work out a pagination for your lists. Sit tight.



In this article, we will discuss the logic around paginating a list with the Google-Pagination like Look and Feel. As you would have noticed there in Google, the current page is always displayed at the centre of the links, unless otherwise it can't be so.



The scope of the article is just to give you a brief idea on how you can go about working a pagination around your data, and this does not cover retrieval of data and/or caching your data from the database. Right, Having known this let's make a list of requirements that our pagination has to meet.





Feature Analysis:



  • Links to show on the page
  • Showing previous and next Buttons when needed
  • Highlighting of current page number
  • Handling a random selection of page
  • Showing the current page link at the centre


(i) Defining the Properties:

Let's say right now we will allow only a maximum of 10 links to be displayed on a page. Clicking a link gets a page with say, 10 rows of data. So at a stretch a user can see 10 links/pages of 10 rows each. Doesn't matter if the total number of results is less than 100 rows of data. We will show them all. But if we get some 500 results as an example, we will not be showing 500/10=50 links. Rather we will show only the first 10 links. We will hold this in a global variable and this is a final one. Here goes the snippet:









public final static int TOTAL_LINKS = 5;



Deduce the total number of result pages to be listed. This in fact we will pre-determine at the beginning. Although we may have to change this at the later course. We will come back to that shortly, be rest assured.









public static int TOTAL_RESULT_PAGES = 9;


We also need to initialize certain variables like Current Page, Page to Start :the first link to show up on the page, Page to Finish :the last link to show up on the page, MidPosition :the middle link position.










private int CURR_PAGE = 1;

private int PAGE_TO_START = 1;

private final int MID_LINK_POSITION = (int) Math
.ceil((double) TOTAL_LINKS / 2);

private int PAGE_TO_FINISH = (TOTAL_RESULT_PAGES < TOTAL_LINKS) ? TOTAL_RESULT_PAGES
: PAGE_TO_START + (TOTAL_LINKS - 1);



Create the accessors/mutators for the above said variables.



(ii) Links to show on the page:

At the client side you have to know the starting-link/ending-link to display. You have to highlight the current page number while showing the links. The values for these variables have to be updated whenever you access any page links. The following code snippet demonstrates this.










public void getPagesToDisplay() {
if (TOTAL_RESULT_PAGES > TOTAL_LINKS) {
if (CURR_PAGE - MID_LINK_POSITION > 0) {
PAGE_TO_START = (CURR_PAGE - MID_LINK_POSITION) + 1;
PAGE_TO_FINISH = (PAGE_TO_START + TOTAL_LINKS) - 1;

while (PAGE_TO_FINISH > TOTAL_RESULT_PAGES) {
PAGE_TO_FINISH--;
PAGE_TO_START--;
}//end while
}//end if
if (CURR_PAGE <= MID_LINK_POSITION) {
PAGE_TO_START = 1;
PAGE_TO_FINISH = (PAGE_TO_START + TOTAL_LINKS) - 1;
}// end if
}//end if
}



(iii) Navigating through the Links

You need to track back one page on 'previous' action, and go forward one page from the current page for 'next' action. Then you have to update the links to display.











public void next() {
if (CURR_PAGE < TOTAL_RESULT_PAGES) {
CURR_PAGE++;
}
getPagesToDisplay();
}

public void previous() {
if (CURR_PAGE > 1) {
CURR_PAGE--;
}
getPagesToDisplay();
}



What if you want to access a page directly? Its so simple! Just set the current page number to the page you are going to access. Then don't forget to update the links to display.









public void gotoPage(int pageNumber) {
if (CURR_PAGE <= TOTAL_RESULT_PAGES) {
CURR_PAGE = pageNumber;
}// end if
getPagesToDisplay();
}



Before displaying Next/Previous links on your page, make sure they are available for you. This is a best practice.








public boolean hasNextPage() {
if (CURR_PAGE < TOTAL_RESULT_PAGES)
return true;
return false;
}

public boolean hasPreviousPage() {
if (CURR_PAGE > 1)
return true;
return false;
}



(iv) Handling page results

Using the currentPageNumber and pageSize, show the records on the page. I leave this as an exercise for you!



While this article guides you through a way of paginating your data, hundreds of open-source & commercial paging tools and tag libraries are available online. My favorite one is the Pager Tag Library. Other tools include the Display Tag Library among several others. Hope this helps and is of use to you.




EDIT:
JSP Part of the code.






<%
Pagination pagination = (Pagination) session.getAttribute("paginationCollection");

/**
* Display the Search results here
*
* <param> currentPageNumber
*
*
*/

// { //write the records here };



/**
* Displaying page navigation Links
*
*/

//get the value of PAGE_TO_START
int startPageNo = patientPage.getStartPageNumber();

//get the value of PAGE_TO_FINISH
int endPageNo = patientPage.getEndPageNumber();

//get the value of CURR_PAGE
int currentPageNo = patientPage.getCurrentPage();

//Variable that holds the total search result pages
int lastPageNo= patientPage.getTotalNoOfPages();


if (currentPageNo>1) {
%>
<a href='list!NavigateToPage.action?pageNumber=1' style="text-decoration:none">[Previous] </a>   
<%
}//end if showPreviousPageLink

for (int i = startPageNo; i <= endPageNo; i++) {
if (i==currentPageNo){
%>
<b><%= i %></b>    //Set the current page to BOLD. Not a Link.
<%
} else {
%>
//Pages with Links
<a href='list!NavigateToPage.action?pageNumber=<%=i%>' style="text-decoration:none"><%= i%></a>   
<%
}//end if else
}//end for : display the page Links

if (currentPageNo<lastPageNo) {
%>
<a href='list!NavigateToPage.action?pageNumber=<%= lastPageNo%>' style="text-decoration:none">[Next] </a>   
<%
}//end if showNextPageLink
%>



samjosh...

No comments: