Tuesday, 19 April 2011

Pagination ( Client-side HTML table pagination with JavaScript )




Most of the times, you don't need to paginate on the client side: if you have an enough small set of records to be displayed, I would suggest you to choose a scrollable <div/>.
Server-side web pagination is really needed when you have to display hundreds of records. You may fetch results from the DB using an offset and loading a single page for each HTTP request.
If your resultset is small it's possible to load it fully. Sometime I saw code loading the full resultset in session; and on each page-switch the browser refreshes displaying a different subset/page. There are many disadvantages of a server-side pagination like this:
  • You have to use the HTTP Session (and remember to clean up when it's nomore needed).
  • You have to reload the page on every page switch.
  • You cannot go forward and backward to check previous data without loosing the view on current resultset.
  • You have to write code for the server side actions handling all the page-switch work.
As I said before, everything would be solved using a table inside scrollable div but, in my current web application "GUI designers" like to persecute the users having them clicking and clicking even for few records. As in my case, I have an "editable table" (an html form) that's also paginated, in wich validation of each record depends on other records...
At least I wanted to avoid reloading the page on every page switch, and also avoid using HTTP Session when not strictly necessary. So I end up writing a JavaScript paginator object that handles the job of paginating any html table rendering also a simple pagination bar.
To use my javascript you need to:
  1. include the javascript using <script src="pager.js"> in your page header;
  2. include a small css to skin the page navigation-bar (i.e. for emphasizing the selected page using bold and underline style);
  3. define an ID on the table you want to scroll. i.e. <table id="results"> ;
  4. place an empty <div/> in the place you want to display the navigation bar. i.e. <div id="pageNavPosition"> ;
  5. include an initialization script at the bottom of your page like this:
    <script type="text/javascript"><!--
        var pager = new Pager('results', 3); 
        pager.init(); 
        pager.showPageNav('pager', 'pageNavPosition'); 
        pager.showPage(1);
    //--></script>
    Where 'results' is the id of the table (see step #3), 3 is the number of records per page, 'pager' is the name of the variable (in red... that's ugly I agree...), and pageNavPosition is the ID of the DIV inside of which the pagination bar will be placed. The showPage(1) indicates that, when loading the page, the 1st one should be displayed.
Here's a live sample:
# field
1
2
3
4
5
6
7
8
9
10
 



 pager.js


function Pager(tableName, itemsPerPage) {
    this.tableName = tableName;
    this.itemsPerPage = itemsPerPage;
    this.currentPage = 1;
    this.pages = 0;
    this.inited = false;
  
    this.showRecords = function(from, to) {      
        var rows = document.getElementById(tableName).rows;
        // i starts from 1 to skip table header row
        for (var i = 1; i < rows.length; i++) {
            if (i < from || i > to)
                rows[i].style.display = 'none';
            else
                rows[i].style.display = '';
        }
    }
  
    this.showPage = function(pageNumber) {
     if (! this.inited) {
     alert("not inited");
     return;
     }

        var oldPageAnchor = document.getElementById('pg'+this.currentPage);
        oldPageAnchor.className = 'pg-normal';
      
        this.currentPage = pageNumber;
        var newPageAnchor = document.getElementById('pg'+this.currentPage);
        newPageAnchor.className = 'pg-selected';
      
        var from = (pageNumber - 1) * itemsPerPage + 1;
        var to = from + itemsPerPage - 1;
        this.showRecords(from, to);
    }
  
    this.prev = function() {
        if (this.currentPage > 1)
            this.showPage(this.currentPage - 1);
    }
  
    this.next = function() {
        if (this.currentPage < this.pages) {
            this.showPage(this.currentPage + 1);
        }
    }                      
  
    this.init = function() {
        var rows = document.getElementById(tableName).rows;
        var records = (rows.length - 1);
        this.pages = Math.ceil(records / itemsPerPage);
        this.inited = true;
    }

    this.showPageNav = function(pagerName, positionId) {
     if (! this.inited) {
     alert("not inited");
     return;
     }
     var element = document.getElementById(positionId);
    
     var pagerHtml = '<span onclick="' + pagerName + '.prev();" class="pg-normal"> &#171 Prev </span> | ';
        for (var page = 1; page <= this.pages; page++)
            pagerHtml += '<span id="pg' + page + '" class="pg-normal" onclick="' + pagerName + '.showPage(' + page + ');">' + page + '</span> | ';
        pagerHtml += '<span onclick="'+pagerName+'.next();" class="pg-normal"> Next &#187;</span>';          
      
        element.innerHTML = pagerHtml;
    }
}
style



<style type="text/css">    
            .pg-normal {
                color: black;
                font-weight: normal;
                text-decoration: none;    
                cursor: pointer;    
            }
            .pg-selected {
                color: black;
                font-weight: bold;        
                text-decoration: underline;
                cursor: pointer;
            }
        </style>

3 comments:

  1. Thank you for such a lovely code...worked very well

    ReplyDelete
  2. ... I keep seeing this code post over and over and no credits for the author...

    ReplyDelete
  3. how if i want to add more pagination in 1 page html ? thanks please reply at my email jodytweet@gmail.com

    ReplyDelete