There is a famous rule out there called DRY (Don't repeat yourself), and if there is one thing I have to code once and again in Opencms is Structured Content lists and their pagination.I will postpone the DRY way explanation of making structured contents lists for any other day and I will explain how to write a reusable robust pagination mechanism for Opencms.
Imagine that we have a structured content for news, a folder full of news and a jsp that display a list of news in it. The list jsp code would be like:
">
Since our folder is full of news, I mean really full: 1001 news items, we don't want to show all of them at the same time, we need to show 10 for page. To do so, the Opencms's contentinfo tag is really useful, so we are going to change our jsp in order to get this:
">
We are going to retrieve the page number to show from a URL parameter, so we check that the parameter is set and is bigger than 0, otherwise we set it to 1. For this example we won't do further validations, but this one is mandatory to make it work.
As you can see there are three more attributes in the contentload that will be a key part of our pagination:
- pageSize: How many news we are showing in one
- page. pageIndex: The number of the page we want to display.
- pageNavLength: This parameter will help us to create our pagination links, I'll write about it soon in this article.
cms:contentinfo
tag that we have added, we have all the info we need to create our pagination links in a request attribute. Usually this attribute is stored in the page context, but as long as we want to be DRY, we are going to create the navigation links in a jsp appart so we can call it from any list jsp we may make.And what's that info that we got?? Here you have:
- info.resultSize: How many news items do we have? In our example: 1001
- info.pageSize: How many news items per page? In our example 10, as we said in the contentload attribute.
- info.pageCount: How many pages of news we have? In our examle 101, 1001/10 = 100 pages with 10 news items each plus one more with 1 item.
- info.resultIndex: What is the current item? Since we are using this data after the contentload loop, in our example this will always point to the last item of the current page, but if you use it inside the loop it will return the current item index.
- info.pageIndex: What is the current page? We have set this parameter using the contentload attribute.
- info.pageNavLength: How many navigation links we want to display? In our example we have 101 pages, but having 101 links would be too much for the user, so we will try to display just 5.
- info.pageNavStartIndex: What is the first page to display in the navigation links? Imagine that we are showing the page 10, as long as we are showing 5 links, the first page link that the navigation will display would be the 8.
- info.pageNavEndIndex: What is the last page to display in the navigation links? Imagine that we are showing the page 10, as long as we are showing 5 links, the last page link that the navigation will display would be the 12, so we will have 5 links: 8, 9, 10, 11, 12.
<%
//Store the info in the page Context
pageContext.setAttribute("info", request.getAttribute("info"));
%>
<%-- Show the first page if it is not in navigation links --%>
?page=1">1 ...
?page= ">
?page= ">
<%-- Show the last page if it is not in navigation links --%>
... ?page= ">
The code is so straight, first of all we want the navigation links to appear when there are several pages, if we only have one page we don't need the links:
We also want to show the links to the first page and the last page always, so we check if they are in the 5 visible links and if they are not we add them prefixes or sufixed by "...".
We also want to show the links to the first page and the last page always, so we check if they are in the 5 visible links and if they are not we add them prefixes or sufixed by "...".
?page=1">1 ...
...
... ?page= ">
The way to link to a page is adding the parameter "page" to the url. In a nice implementation we should check in our list jsp that the user is asking for a page that exists, this way we can avoid some indexOutOfBoundExceptions.
Here I leave the jsp file ready to download and use in your Opencms. Enjoy!