Thursday, June 21, 2012

Implementing the jQuery DataTables plugin in a 'classic' Domino Web application.

Well, it's been a really long time since I posted anything here. I started a new job last year, which has involved working on traditional Notes and Domino web databases in a large company with a very old infrastructure - Note 6.5 and 7 clients, Domino 6.5 through to 8.0.1. So no recent xPages for me.

But I have been doing a lot of work with jQuery, because the company's default browser is *still* IE6, and jQuery eases the pain.

We recently started implementing the jQuery DataTables plugin for handling things like search results, because you can include features for in memory paging, filtering and sorting with very little effort. It's quick, cross browser compatible, and can use data already on the page or fetch it via AJAX.

The internal company web application I am working on is fairly typical. It is an older Domino application which has grown over time, been worked on by many developers and contains a huge variety of code styles and approaches. There are a number of databases, most of which have their own search page. These normally have a group of <select> elements used to filter the data. The user makes their choices then clicks 'Search' whereapon the form is reloaded with the search parameters appended to the URL. The form's WebQueryOpen agent would use the URL parameters to build and execute the document search, then render the data as table rows inside a rich text field, which was wrapped in pass-thru HTML. JavaScript was then used to parse the HTML and re-rendered it in a paged table.

There were problems with this approach - firstly it was slow. The round trip to the sever for a full page reload, the time it took to run the WQO agent and write the HTML into the rich text field, and the time to parse and re-render the table were noticeable. Secondly, it only worked in IE due to the way the script was loaded, and thirdly, more than about 500 results would cause the JavaScript to time out.

As jQuery had already been added to most of the databases, we decided to replace the existing system with DataTables whenever we get the chance. Firstly, the old JavaScript library needs to be removed and replaced by the DataTables plugin (download the plugin and load the .js file wherever you have your jQuery source and reference it the same way). Then we need to implement DataTables using the current page HTML. To do so you just initialize it like this:

$(document).ready( function() {
   $('#tableId').dataTable();
});

Simple, isn't it. Of course there was a bit of work to do with styling, but the plugin downloads with a sample stylesheet that gets you well under way. The immediate impact was a significant speed improvement and a much larger result set could be processed before timing out (about a 5 fold increase).

The hardest bit was cleaning up our existing HTML. The plugin is a little unforgiving. The table you target must be properly formed with both <thead>and <tbody> elements, the <thead> must contain at least one row with <th> elements and the <tbody> must contain at least one row of<td> elements. The number of th and td elements in the rows must match.

For some of the search pages, that is as far as we went. However as time and budget permit, we are also replacing the DOM source (generated by page reload + WQO agent) by an Ajax data souce. The same lotusscript agents can be re-used by simply modifying them to print JSON instead of appending HTML to a field. The existing parts of the agents which use the URL parameters to generate the search and build the document collection can be retained (including all the tested business logic). The JSON object you need to generate is defined in the DataTables API. and is basically an array of arrays in an object called aaData. the api documentation has examples. Then we remove the rich text field, create an empty table with the required number of columns using pass-through HTML and hide it with styling, then put the following in the Search button click handler:


    var sUrl = ;// create your URL along the lines of 
       //http://my server.mydomain.com/path/db.nsf/myAgant?OpenAgent&cat=xyz&p2=abc
    $('#tableId').show();

    $('#tableId').dataTable( {
        "bProcessing": true,
        "sAjaxSource": sUrl
      });

As the JSON your agent creates can contain HTML, so one of your columns can be easily configured as a link. Depending on your data you should also consider testing for and escaping invalid characters before you print your agent output. Now the search results are loaded without a page refresh, and the overall result is a faster, snappier, more modern search results table.

There are a larger number of properties you can set when initializing the table, including turning on or of the paging and filtering, controlling the sorting, defining callback functions to be called at various stages of the table rendering, adding classes to style the table, hiding columns and more.

Once you get your head around the basics of setting it up it is easy to use and very flexible. It includes support for the jQueryUI themes and is a great way to add a little 'shiny' touch to those apps not yet ready for xPages.