Yahoo! Developer Network Home - Help

YUI Library Examples: DataTable Control (beta): Server-side Pagination and Sorting, with Browser History Manager

DataTable Control (beta): Server-side Pagination and Sorting, with Browser History Manager

This example combines server-side pagination and sorting with the Browser History Manager for managing states.

ID
Name
Date
Price
Loading data...

Code for this example

This example contacts a server side script to get the records appropriate for display in the DataTable according to the requested sort order and page. Additionally, each change of page or sort order will be added to the Browser History Manager, allowing bookmarking and the use of the browser's back/forward buttons to navigate through states of the DataTable.

The server-side script delivering the DataTable's records will send the data in the following JSON format:

1{"recordsReturned":25, 
2    "totalRecords":1397, 
3    "startIndex":0, 
4    "sort":null, 
5    "dir":"asc", 
6    "records":[ 
7        {"id":"0", 
8        "name":"xmlqoyzgmykrphvyiz", 
9        "date":"13-Sep-2002", 
10        "price":"8370", 
11        "number":"8056", 
12        "address":"qdfbc", 
13        "company":"taufrid", 
14        "desc":"pppzhfhcdqcvbirw", 
15        "age":"5512", 
16        "title":"zticbcd", 
17        "phone":"hvdkltabshgakjqmfrvxo", 
18        "email":"eodnqepua", 
19        "zip":"eodnqepua", 
20        "country":"pdibxicpqipbsgnxyjumsza"}, 
21        ... 
22    ] 
23
view plain | print | ?

The markup

1<iframe id="yui-history-iframe" src="assets/html/blank.html"></iframe> 
2<input id="yui-history-field" type="hidden"
3 
4<div id="dt-pag-nav"></div> 
5<div id="serverintegration"></div> 
view plain | print | ?

CSS

The Browser History Manager markup requires an iframe to support IE6. This is hidden per the recommendation.

1#yui-history-iframe { 
2  position:absolute
3  top:0left:0
4  width:1pxheight:1px/* avoid scrollbars */ 
5  visibility:hidden
6} 
view plain | print | ?

Workflow

To inject the Browser History Manager into DataTable pagination and sorting, we need to create a few custom functions and insert them into the normal flow of operations. Here's a diagram of how the code below will operate (note the methods in floating boxes are our custom functions):

Flowchart of the DataTable interaction with BHM updating

Javascript

The Browser History Manager remembers "states". For this example, we'll use the query string sent to the server script as the state indicator. First we create a couple functions to generate and parse the query/state string, then set up the onStateChange function for the BHM to use when calls to History.navigate(...) are made.

1(function () { 
2    var History = YAHOO.util.History, 
3        myPaginator,  // to hold the Paginator instance 
4        myDataSource, // to hold the DataSource instance 
5        myDataTable;  // to hold the DataTable instance 
6 
7    // function to generate a query string for the DataSource.  Also used 
8    // as the state indicator for the History Manager 
9    var generateStateString = function (start,key,dir) { 
10        start = start || 0; 
11        key   = key || 'id'
12        dir   = dir || 'asc'
13        return "results=15&startIndex="+start+"&sort="+key+"&dir="+dir; 
14    }; 
15 
16    // function to extract the key values from the state string 
17    var parseStateString = function (state) { 
18        return { 
19            results    : 15, 
20            startIndex : /\bstartIndex=(\d+)/.test(state) ? parseInt(RegExp.$1) : 0, 
21            sort       : /\bsort=(\w+)/.test(state)       ? RegExp.$1 : 'id'
22            dir        : /\bdir=(\w+)/.test(state)        ? RegExp.$1 : 'asc' 
23        }; 
24    }; 
25 
26    // function to handle onStateChange events from Browser History Manager 
27    var handleHistoryNavigation = function (state) { 
28        // Create a payload to pass through the DataSource request to the 
29        // handler 
30        var parsed = parseStateString(state); 
31 
32        // Use the DataTable's baked in server-side pagination handler 
33        myDataSource.sendRequest(state,{ 
34                success  : myDataTable.onDataReturnSetRows, 
35                failure  : myDataTable.onDataReturnSetRows, 
36                scope    : myDataTable 
37        }); 
38    }; 
39 
40    // Support users visiting the page for the first time or from a 
41    // saved bookmark. 
42    var initialState = History.getBookmarkedState('myDataTable') || 
43                       generateStateString(0,'id','asc'); 
44 
45    // Register a 'myDataTable' module in the BHM, indicating this session's 
46    // initial state and the callback to handle onStateChange events. 
47    History.register('myDataTable',initialState, handleHistoryNavigation); 
view plain | print | ?

To facilitate the Browser History Manager remembering pagination and sorting states, we'll need to use custom pagination and sorting handlers. Each will generate a new state and simply call the BHM's navigate method. The onStateChange handler will take over from there.

1// function used to intercept pagination requests 
2var handlePagination = function (state,datatable) { 
3    var sortedBy  = datatable.get('sortedBy'); 
4 
5    var newState = generateStateString( 
6                        state.recordOffset, 
7                        sortedBy.key, 
8                        sortedBy.dir); 
9 
10    History.navigate("myDataTable",newState); 
11}; 
12 
13// function used to intercept sorting requests 
14var handleSorting = function (oColumn) { 
15    // Which direction 
16    var sDir = "asc"
17 
18    // Already sorted? 
19    if(oColumn.key === this.get("sortedBy").key) { 
20        sDir = (this.get("sortedBy").dir === "asc") ? 
21                "desc" : "asc"
22    } 
23 
24    var newBookmark = generateStateString(0, oColumn.key, sDir); 
25 
26    YAHOO.util.History.navigate("myDataTable", newBookmark); 
27}; 
view plain | print | ?

Finally, we create the DataTable instance and the supporting class instances in the History Manager's onReady handler. This guarantees that whether users arrive at the page fresh, from a bookmark, or from navigating via the browser's back/forward buttons, the DataTable will display the appropriate state.

Note the DataSource is configured with a number of metaFields, which are processed by the DataTable to automatically update sorting and pagination information. See the note on magic meta in the DataTable docs for more information.

1    History.onReady(function() { 
2        // Pull the state from the History Manager, or default from the 
3        // initial state.  Parse the state string into an object literal. 
4        var initialRequest = History.getCurrentState('myDataTable') || 
5                             initialState, 
6            state          = parseStateString(initialRequest); 
7 
8        // Create the DataSource 
9        myDataSource = new YAHOO.util.DataSource("assets/php/json_proxy.php?"); 
10        myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON; 
11        myDataSource.responseSchema = { 
12            resultsList: "records"
13            fields: ["id","name","date","price"], 
14            metaFields: { 
15                totalRecords: "totalRecords"
16                paginationRecordOffset : "startIndex"
17                sortKey: "sort"
18                sortDir: "dir" 
19            } 
20        }; 
21 
22        // Column definitions 
23        var myColumnDefs = [ 
24            {key:"id", label:"ID", sortable:true}, 
25            {key:"name", label:"Name", sortable:true}, 
26            {key:"date", label:"Date", sortable:true}, 
27            {key:"price", label:"Price", sortable:true
28        ]; 
29 
30        // Create the DataTable configuration and Paginator using the state 
31        // information we pulled from the History Manager 
32        myPaginator = new YAHOO.widget.Paginator({ 
33            rowsPerPage : state.results, 
34            recordOffset : state.startIndex, 
35            containers : ['dt-pag-nav'], 
36            template : "{PreviousPageLink} {CurrentPageReport} {NextPageLink}"
37            pageReportTemplate : "Showing items {startIndex} - {endIndex} of {totalRecords}" 
38        }); 
39 
40        var myConfig = { 
41            paginator : myPaginator, 
42            paginationEventHandler : handlePagination, 
43            // generateRequest : generateStateString, // moot 
44            sortedBy : { 
45                key : state.sort, 
46                dir : state.dir 
47            }, 
48            initialRequest : initialRequest 
49        }; 
50 
51        // Instantiate DataTable 
52        myDataTable = new YAHOO.widget.DataTable( 
53            "serverintegration"// The dom element to contain the DataTable 
54            myColumnDefs,        // What columns will display 
55            myDataSource,        // The DataSource for our records 
56            myConfig             // Other configurations 
57        ); 
58 
59        // Listen to header link clicks to sort the column 
60        myDataTable.subscribe('theadCellClickEvent', myDataTable.onEventSortColumn); 
61 
62        // Override the DataTable's sortColumn method with our intercept handler 
63        myDataTable.sortColumn = handleSorting; 
64         
65        // Add the example objects to the YAHOO.example namespace for inspection 
66        YAHOO.example.ServerIntegration = { 
67            myPaginator  : myPaginator, 
68            myDataSource : myDataSource, 
69            myDataTable  : myDataTable 
70        }; 
71    }); 
72 
73    YAHOO.util.History.initialize("yui-history-field""yui-history-iframe"); 
74})(); 
view plain | print | ?

Copyright © 2008 Yahoo! Inc. All rights reserved.

Privacy Policy - Terms of Service - Copyright Policy - Job Openings