Me Myself & C#

Manoj Garg’s Tech Bytes – What I learned Today

Archive for the ‘JavaScript’ Category

DOM property comparison for different browsers: What Works Where?

Posted by Manoj Garg on November 25, 2009

Today, I was working on a UI enhancement task where I had to do some DOM manipulation. Basically task was changing color of some SPAN elements in DOM depending on their value like if it’s value is XXX then show in RED color and so on. As always I was using IE to test my Java script code written to do the job. In JS code, I used “innerText” property of SPAN element to get the text of that element and then did the comparison to change the color and It worked fine. When I ran same JS code on Mozilla, it didn’t run (I mean it got executed but didn’t changed color of SPAN elements to RED L) . On debugging the script, I was surprised to see value of innerText property being returned null. When googled around it and found that only Mozilla doesn’t support this property L. Mozilla has another property “textContent” which has same value as innerText in other browsers.

Solution was simple, use an ORing of both the values instead of putting if-else block in code to use textContent if the user is running Mozilla or innerText for any other browser.

var txtName = clientNameElement.innerText || clientNameElement.textContent;

I picked up this solution from here. This link provides a good comparison of various DOM properties on different browsers that is what works and what not J.

Hope it helps some of you while writing code to cater to multiple browsers J

Posted in JavaScript | Tagged: , , , , , | 1 Comment »

Pagination with JavaScript

Posted by Manoj Garg on July 17, 2009

Pagination is a must have feature when it comes to display a list of item. List could be collection of search results, a tabular display of names etc etc. When the list is small, pagination is not something we should be worried about, But imagine having a list with 100’s of items to show then displaying all of them at once on a page is not a good idea.

  • Viewer of that page have to scroll down a lot if the list if too long
  • Page becomes slower since there are lots of DOM elements on the page

So developers tend to display a small number of items at once to the viewer and then proving him/her the option of navigating to different pages. There are two ways once can implement paging

  1. Server side paging: Developer can get only a fixed number of records from the server and display then to the viewer and whenever viewer wants to navigate to a different page, a new request demanding the items from that particular page can be send to the server. In turn server can return records from that page only.
  2. Client side paging: Depending on the scenario developer can also do the job of showing pages on the client side as well i.e. he/she may request all the items at once and then showing only a set of them to the viewer and providing user with the links to other pages using any scripting language.

I had a situation where it was not possible to have server side pagination due to restriction of the framework I was coding against. So I had no choice but to go with client side paging. I was implementing a search functionality where I would be searching against the lucene index to get the results and then showing those results to the viewer. search results will be displayed a html table. each row in the result table will be used to display one search result. Each search result will have some predefined fields and a summary for that results. Viewer will have an option to show and hide the summary of the result. So one requirement was to have different number of items per page depending on whether summary is visible to the viewer or not.

I took the following approach:

After getting results from server, I used JavaScript to create DOM elements for each of the search results returned. After all the results are created on the page, pagination code was called to show the first page and the pager.

To start I created a JS class named “Pager” which will have all the methods related to the navigation among pages. Pager class had following members:

  • tableName : Name of the table on which pagination has to be applied.
  • itemsPerPage : Number of items to show when summary field is visible.
  • itemsWithoutSmry : Number of items to show when summary field is not visible to the viewer.
  • currentItemPerPage : Number of items currently visible. This value will be equal to either itemsPerPage or itemsWithoutSmry.
  • currentPage : current page in the table.
  • pages : Total number of pages in the table.

All the above field will be initialized to some default values when the Object of Pager call will be created.

Initialization of the pager

This method will initialize the pager object field pages by using the total records and items to shown on page. Following code snippet is the init() method.

//initialize the pager
  this.init = function() {
        //check if table exists in the dom
        if(document.getElementById(tableName) != null)
        {
                // get the total number of rows in the table
            var rows = document.getElementById(tableName).rows;
            var records = (rows.length - 1);
                // Calculate the number of pages
            this.pages = Math.ceil(records / this.itemsPerPage);
                // set the flag to indicate initialization is complete
            this.inited = true;
        }
   }

Showing records of a particular page

To do this I will iterate through the rows of the table to show/hide the visibility of these rows depending on the page viewer has requested. Following code snippet shows the methods that do this.

//Show record from a start index to an end index
this.showRecords = function(from, to) {
        // check if table exists in the DOM
        if(document.getElementById(tableName) != null)
        {
        //Get rows in the table and then set the visibility of the rows between 'from' and 'to'
            var rows = document.getElementById(tableName).rows;
            // i starts from 1 to skip table header row and hide rows other then the current page
            for (var i = 1; i < rows.length; i++) {
                if (i < from || i > to)
                    rows[i].style.display = 'none';
                else
                    rows[i].style.display = '';
            }
        }
    }
 
// Method to show a particular pager
 this.showPage = function(pageNumber) {
    // check if initialization is done
        if (! this.inited) {
            alert("not inited");
            return;
        }
        //change the CSS style of the old page
    //each page number indicator in the pager has a naming convention like tablename+pg+pageindex
        var oldPageAnchor = document.getElementById(this.tableName+'pg'+this.currentPage);
        if(oldPageAnchor)
        oldPageAnchor.className = 'pg-normal';
 
        //change the style of the current page
        this.currentPage = pageNumber;
        var newPageAnchor = document.getElementById(this.tableName+'pg'+this.currentPage);
        if(newPageAnchor)
        newPageAnchor.className = 'pg-selected';
 
       //calculate current page records index
        var from = (pageNumber - 1) * this.currentItemPerPage + 1;
        var to = from + this.currentItemPerPage - 1;
    //show the records
        this.showRecords(from, to);
    }   

 

Navigating to Next and Previous pages
//show previous page
    this.prev = function() {
        if (this.currentPage > 1)
            this.showPage(this.currentPage - 1);
    }
 
 
    //show next page
    this.next = function() {
        if (this.currentPage < this.pages) {
            this.showPage(this.currentPage + 1);
        }
    }

Showing the pager bar

Following code snippet contains javascript method which will create a div at the end of table containing number from 1 to the total number of pages in the table along with prev and next page links. each link will have a onclick javascript function call to the above mentioned functions.

//show the pager bar
// param : @pagerName: name of the pager object
//  param : @positionId: Id of the div in which the page has to be shown 
    this.showPageNav = function(pagerName, positionId) {
      // Check if the pager object has been initialized
      if (! this.inited) {
        alert("not inited");
        return;
      }
 
      // check if the div exisits in DOM 
      if(document.getElementById(positionId) != null)
      {
        var element = document.getElementById(positionId);
        // create prev page link with call to prev() method
        var pagerHtml = '<b><span onclick="' + pagerName + '.prev();" class="pg-normal"> &#171 Prev </span> | ';
 
        // create numeric page number links
        for (var page = 1; page <= this.pages; page++)
              pagerHtml += '<span id="'+this.tableName+'pg' + page + '" class="pg-normal" onclick="' + pagerName + '.showPage(' + page + ');">' + page + '</span> | ';
 
        // Create next page link with call to next() method
        pagerHtml += '<span onclick="'+pagerName+'.next();" class="pg-normal"> Next »</span> </b>';
 
        // chnage the inner html of the pager Div 
        element.innerHTML = pagerHtml;
        }
    }

Adjusting the record count per page with the Summary visibility

I added a method to the pager class which takes a Boolean parameter denoting the visibility status of the summary content as input and based on this parameter it changes the current page size. Following code snippet shows the same:

//adjust page according to summay div visibility
// param : @isSummaryShown = Visibility status of the summary content for the item
    this.adjustPager = function(isSummaryShown)
    {
      //change the pagesize
      if(isSummaryShown)
      {
        this.currentItemPerPage = this.itemsPerPage;
      }
      else
      {
        this.currentItemPerPage = this.itemsWithoutSmry;
      }
 
      //rebuild pager
      if(document.getElementById(tableName) != null)
      {
          var rows = document.getElementById(tableName).rows;
          var records = (rows.length - 1);
          this.pages = Math.ceil(records / this.currentItemPerPage);
        }
    this.showPageNav("pagerObj", 'pageNavPosition_Results');
    this.showPage(1);
    }

Creating and using Instance of the Pager Class

following line shows the signature for the pager class

function Pager(tableName, itemsPerPage, pageSizeWithoutSummary)

after the page object is created it must be first initialized, then the pager bar should be created followed by showing the page.

Following code snippet shows this

// create a pager obejct by passing tablename, page size
var pagerObj = new Pager('table_AllResults', 10, 15);
// init the pager object
pagerObj.init();
//show the pager bar for itens without summary
pagerObj.adjustPager(false);
//show first page
pagerObj.showPage(1);

I will be uploading a demo soon.

If you have some better way to implement the pagination then please drop a comment.  🙂

Posted in CSS, JavaScript | Tagged: | 4 Comments »