YUI Library Home

YUI Library Examples: DataTable Control: Integrating Browser History Manager with Server-side Pagination and Sorting

DataTable Control: Integrating Browser History Manager with Server-side Pagination and Sorting

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

Loading...

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 data

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    "pageSize":10, 
7    "records":[ 
8        {"id":"0", 
9        "name":"xmlqoyzgmykrphvyiz", 
10        "date":"13-Sep-2002", 
11        "price":"8370", 
12        "number":"8056", 
13        "address":"qdfbc", 
14        "company":"taufrid", 
15        "desc":"pppzhfhcdqcvbirw", 
16        "age":"5512", 
17        "title":"zticbcd", 
18        "phone":"hvdkltabshgakjqmfrvxo", 
19        "email":"eodnqepua", 
20        "zip":"eodnqepua", 
21        "country":"pdibxicpqipbsgnxyjumsza"}, 
22        ... 
23    ] 
24
view plain | print | ?

The markup

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

CSS

The Browser History Manager markup requires an iframe to support IE6. This is hidden via CSS 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 integrate the Browser History Manager with 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

First we set up the DataTable with server-side sorting and pagination, including creation of all dependencies, like a DataSource instance and Paginator instance.

1(function () { 
2    // Create the DataSource 
3    var myDataSource = new YAHOO.util.DataSource("assets/php/json_proxy.php?"); 
4    myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON; 
5    myDataSource.responseSchema = { 
6        resultsList: "records"
7        fields: ["id","name","date","price"], 
8        metaFields: { 
9            totalRecords: "totalRecords"
10            paginationRecordOffset : "startIndex"
11            paginationRowsPerPage : "pageSize"
12            sortKey: "sort"
13            sortDir: "dir" 
14        } 
15    }; 
16 
17    // Create the Paginator 
18    var myPaginator = new YAHOO.widget.Paginator({ 
19        containers : ["dt-pag-nav"], 
20        template : "{PreviousPageLink} {CurrentPageReport} {NextPageLink} {RowsPerPageDropdown}"
21        pageReportTemplate : "Showing items {startIndex} - {endIndex} of {totalRecords}"
22        rowsPerPageOptions : [10,25,50,100] 
23    }); 
24     
25    // Define Columns 
26    var myColumnDefs = [ 
27        {key:"id", label:"ID", sortable:true}, 
28        {key:"name", label:"Name", sortable:true}, 
29        {key:"date", label:"Date", sortable:true}, 
30        {key:"price", label:"Price", sortable:true
31    ]; 
32 
33    // DataTable configurations 
34    var myConfig = { 
35        paginator : myPaginator, 
36        dynamicData : true
37        initialLoad : false 
38    }; 
39 
40    // Instantiate DataTable 
41    var myDataTable = new YAHOO.widget.DataTable( 
42        "bhmintegration", myColumnDefs, myDataSource, myConfig 
43    ); 
44     
45    // Show loading message while page is being rendered 
46    myDataTable.showTableMessage(myDataTable.get("MSG_LOADING"), YAHOO.widget.DataTable.CLASS_LOADING); 
47 
48    // Add the instances to the YAHOO.example namespace for inspection 
49    YAHOO.example.BHMIntegration = { 
50        myPaginator  : myPaginator, 
51        myDataSource : myDataSource, 
52        myDataTable  : myDataTable 
53    }; 
view plain | print | ?

The following code integrates the DataTable with the Browser History Manager, which we'll use to remember "states". We'll use the request sent to the server script as the state indicator and custom pagination and sorting handlers to generate new states and pass them to the BHM's navigate method. The handleHistoryNavigation handler will take over from there.

1// Integrate with Browser History Manager 
2var History = YAHOO.util.History; 
3 
4// Define a custom function to route sorting through the Browser History Manager 
5var handleSorting = function (oColumn) { 
6    // Calculate next sort direction for given Column 
7    var sDir = this.getColumnSortDir(oColumn); 
8     
9    // The next state will reflect the new sort values 
10    // while preserving existing pagination rows-per-page 
11    // As a best practice, a new sort will reset to page 0 
12    var newState = generateRequest(0, oColumn.key, sDir, this.get("paginator").getRowsPerPage()); 
13 
14    // Pass the state along to the Browser History Manager 
15    History.navigate("myDataTable", newState); 
16}; 
17myDataTable.sortColumn = handleSorting; 
18 
19// Define a custom function to route pagination through the Browser History Manager 
20var handlePagination = function(state) { 
21    // The next state will reflect the new pagination values 
22    // while preserving existing sort values 
23    // Note that the sort direction needs to be converted from DataTable format to server value 
24    var sortedBy  = this.get("sortedBy"), 
25        newState = generateRequest( 
26        state.recordOffset, sortedBy.key, sortedBy.dir, state.rowsPerPage 
27    ); 
28 
29    // Pass the state along to the Browser History Manager 
30    History.navigate("myDataTable", newState); 
31}; 
32// First we must unhook the built-in mechanism... 
33myPaginator.unsubscribe("changeRequest", myDataTable.onPaginatorChangeRequest); 
34// ...then we hook up our custom function 
35myPaginator.subscribe("changeRequest", handlePagination, myDataTable, true); 
36 
37// Update payload data on the fly for tight integration with latest values from server  
38myDataTable.doBeforeLoadData = function(oRequest, oResponse, oPayload) { 
39    var meta = oResponse.meta; 
40    oPayload.totalRecords = meta.totalRecords || oPayload.totalRecords; 
41    oPayload.pagination = { 
42        rowsPerPage: meta.paginationRowsPerPage || 10, 
43        recordOffset: meta.paginationRecordOffset || 0 
44    }; 
45    oPayload.sortedBy = { 
46        key: meta.sortKey || "id"
47        dir: (meta.sortDir) ? "yui-dt-" + meta.sortDir : "yui-dt-asc" // Convert from server value to DataTable format 
48    }; 
49    return true
50}; 
51 
52// Returns a request string for consumption by the DataSource 
53var generateRequest = function(startIndex,sortKey,dir,results) { 
54    startIndex = startIndex || 0; 
55    sortKey   = sortKey || "id"
56    dir   = dir   = (dir) ? dir.substring(7) : "asc"// Converts from DataTable format "yui-dt-[dir]" to server value "[dir]" 
57    results   = results || 10; 
58    return "results="+results+"&startIndex="+startIndex+"&sort="+sortKey+"&dir="+dir; 
59}; 
60 
61// Called by Browser History Manager to trigger a new state 
62var handleHistoryNavigation = function (request) { 
63    // Sends a new request to the DataSource 
64    myDataSource.sendRequest(request,{ 
65        success : myDataTable.onDataReturnSetRows, 
66        failure : myDataTable.onDataReturnSetRows, 
67        scope : myDataTable, 
68        argument : {} // Pass in container for population at runtime via doBeforeLoadData 
69    }); 
70}; 
71 
72// Calculate the first request 
73var initialRequest = History.getBookmarkedState("myDataTable") || // Passed in via URL 
74                   generateRequest(); // Get default values 
75 
76// Register the module 
77History.register("myDataTable", initialRequest, handleHistoryNavigation); 
78 
79// Render the first view 
80History.onReady(function() { 
81    // Current state after BHM is initialized is the source of truth for what state to render 
82    var currentState = History.getCurrentState("myDataTable"); 
83    handleHistoryNavigation(currentState); 
84}); 
85 
86// Initialize the Browser History Manager. 
87YAHOO.util.History.initialize("yui-history-field""yui-history-iframe"); 
88
view plain | print | ?

Configuration for This Example

You can load the necessary JavaScript and CSS for this example from Yahoo's servers. Click here to load the YUI Dependency Configurator with all of this example's dependencies preconfigured.

Copyright © 2011 Yahoo! Inc. All rights reserved.

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