Tuesday, January 10, 2012

Long list pagination in Java

Information on web pages is usually represented as a list e.g. search results, product list, messages. That list can be very long (hundreds of rows). You can print the whole list on the page, but it would take too long to load the page and the user would have to scroll it. That is not user friendly.

So we need to split the list into ranges and to show each range on a separate page. We have to calculate the number of pages by dividing the number of rows by the number of rows we want to show per page.

Total rows: 100; Rows per page: 20; Total pages = Total rows / Rows per page = 5.

The Pagination.java class does this calculation. To instantiate we need to pass 2 parameters: totalItems and itemsPerPage. Current page is 1 by default. To change current page number we call setter method setCurrentPage(int currentPage).

After initializaton is complete, we can query Pagination for the following data:

  • getTotalPages() 
  • hasPreviousPage()
  • hasNextPage() 
  • getPreviousPage() 
  • getNextPage()

Then we need to show available pages as hyperlinks. It is good to have liquid pagination, to show several pages before and after current page. Call method List<Integer> getPagesList(int radius) to get a list of pages. Radius is the number of pages before and after the current page.


The source code of the Pagination class is placed below. You can use it for free.





Source code

/**
 * Pagination for long lists
 * @author sergej.sizov
 */
public class Pagination {

    private int currentPage = 1;
    private int totalItems;
    private int itemsPerPage;

    private int totalPages = 0;

    public Pagination (int totalItems, int itemsPerPage) {

        this.totalItems = totalItems;
        this.itemsPerPage = itemsPerPage;
        if (this.itemsPerPage < 1) {
            this.itemsPerPage = 1;
        }

        this.totalPages = this.totalItems / this.itemsPerPage;
        if (this.totalItems % this.itemsPerPage > 0) {
            this.totalPages = this.totalPages + 1;
        }

    }

    public int getCurrentPage() {
        return currentPage;
    }
   
    public void setCurrentPage(int currentPage) {
        if (currentPage > totalPages) {
            currentPage = totalPages;
        }
        if (currentPage < 1) {
            currentPage = 1;
        }
        this.currentPage = currentPage;
    }

    public int getTotalPages() {
        return this.totalPages;
    }

    public boolean hasPreviousPage() {
        return currentPage > 1;
    }

    public boolean hasNextPage() {
        return currentPage < totalPages;
    }

    public int getPreviousPage() {
        if (hasPreviousPage()) {
            return currentPage - 1;
        } else {
            return 1;
        }
    }

    public int getNextPage() {
        if (hasNextPage()) {
            return currentPage + 1;
        } else {
            return totalPages;
        }
    }

    public int getStartIndex() {
        return (this.currentPage - 1) * this.itemsPerPage + 1;
    }

    public int getEndIndex() {
        int endIndex = this.currentPage * this.itemsPerPage;
        if (endIndex > this.totalItems) {
            endIndex = this.totalItems;
        }
        return endIndex;
    }

    public List<Integer> getPagesList(int radius) {
        List<Integer> pageList = new ArrayList<Integer>();
        
        int startPage = getCurrentPage() - radius;
        if (startPage < 1) {
            startPage = 1;
        }
        
        int endPage = getCurrentPage() + radius;
        if (endPage > getTotalPages()) {
            endPage = getTotalPages();
        }
        
        for (int page = startPage; page <= endPage; page++) {
            pageList.add(page);
        }
        
        return pageList;
    }


    public int getTotalItems() {
        return totalItems;
    }


}

3 comments: