Yahoo! Developer Network Home - Help

YDN Site Search

# 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.

View example in new window.

## 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:

{"recordsReturned":25, "totalRecords":1397, "startIndex":0, "sort":null, "dir":"asc", "records":[ {"id":"0", "name":"xmlqoyzgmykrphvyiz", "date":"13-Sep-2002", "price":"8370", "number":"8056", "address":"qdfbc", "company":"taufrid", "desc":"pppzhfhcdqcvbirw", "age":"5512", "title":"zticbcd", "phone":"hvdkltabshgakjqmfrvxo", "email":"eodnqepua", "zip":"eodnqepua", "country":"pdibxicpqipbsgnxyjumsza"}, ... ] }

## The markup

<iframe id="yui-history-iframe" src="assets/html/blank.html"></iframe> <input id="yui-history-field" type="hidden"> <div id="dt-pag-nav"></div> <div id="serverintegration"></div>

## CSS

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

#yui-history-iframe { position:absolute; top:0; left:0; width:1px; height:1px; /* avoid scrollbars */ visibility:hidden; }

## 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):

## 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.

YAHOO.example.ServerIntegration = new function() { var History = YAHOO.util.History; // function to generate a query string for the DataSource. Also used // as the state indicator for the History Manager var generateStateString = function (start,key,dir) { return "results=15&startIndex="+start+"&sort="+key+"&dir="+dir; }; // function to extract the key values from the state string var parseStateString = function (state) { return { results : 15, startIndex : /\bstartIndex=(\d+)/.test(state) ? parseInt(RegExp.$1) : 0, sort : /\bsort=(\w+)/.test(state) ? RegExp.$1 : 'id', dir : /\bdir=(\w+)/.test(state) ? RegExp.$1 : 'asc' }; }; // function to handle onStateChange events from Browser History Manager var handleHistoryNavigation = function (state) { // Create a payload to pass through the DataSource request to the // handler var parsed = parseStateString(state); var oPayload = { startIndex : parsed.startIndex, pagination : { recordOffset : parsed.startIndex }, sorting : { key : parsed.sort, dir : parsed.dir } }; // Use the DataTable's baked in server-side data handler this.myDataSource.sendRequest(state,{ success : this.myDataTable.onDataReturnSetRecords, failure : this.myDataTable.onDataReturnSetRecords, scope : this.myDataTable, argument : oPayload }); }; // Support users visiting the page for the first time or from a // saved bookmark. var initialState = History.getBookmarkedState('myDataTable') || generateStateString(0,'id','asc'); // Register a 'myDataTable' module in the BHM, indicating this session's // initial state and the callback to handle onStateChange events. History.register('myDataTable',initialState, handleHistoryNavigation);

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.

// function used to intercept pagination requests var handlePagination = function (state,datatable) { var sortedBy = datatable.get('sortedBy'); var newState = generateStateString( state.recordOffset, sortedBy.key, sortedBy.dir); History.navigate("myDataTable",newState); }; // function used to intercept sorting requests var handleSorting = function (oColumn) { // Which direction var sDir = "asc"; // Already sorted? if(oColumn.key === this.get("sortedBy").key) { sDir = (this.get("sortedBy").dir === "asc") ? "desc" : "asc"; } var newBookmark = generateStateString(0, oColumn.key, sDir); YAHOO.util.History.navigate("myDataTable", newBookmark); };

Here's something a bit more cryptic. To support returning to a DataTable state that is not on the first page, we need to override the DataTable instance's `doBeforeLoadData` method to default the insertion point for the records returned from the server to their appropriate index in the larger data set. DataTable assumes during construction that its DataSource represents the complete data set, so it stores records internally from index 0 (unless we intervene).

var doBeforeLoadData = function (oRequest, oResponse, oPayload) { oPayload = oPayload || {}; if (!YAHOO.lang.isNumber(oPayload.startIndex)) { oPayload.startIndex = this.get('paginator').getStartIndex(); } return true; };

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.

History.onReady(function() { // Pull the state from the History Manager, or default from the // initial state. Parse the state string into an object literal. var initialRequest = History.getCurrentState('myDataTable') || initialState, state = parseStateString(initialRequest); // Create the DataSource this.myDataSource = new YAHOO.util.DataSource("assets/php/json_proxy.php?"); this.myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON; this.myDataSource.responseSchema = { resultsList: "records", totalRecords: "totalRecords", fields: ["id","name","date","price"] }; // Column definitions var myColumnDefs = [ {key:"id", label:"ID", sortable:true}, {key:"name", label:"Name", sortable:true}, {key:"date", label:"Date", sortable:true}, {key:"price", label:"Price", sortable:true} ]; // Create the DataTable configuration and Paginator using the state // information we pulled from the History Manager this.paginator = new YAHOO.widget.Paginator({ rowsPerPage : state.results, recordOffset : state.startIndex, containers : ['dt-pag-nav'], template : "{PreviousPageLink} {CurrentPageReport} {NextPageLink}", pageReportTemplate : "Showing items {startIndex} - {endIndex} of {totalRecords}" }); var myConfig = { paginator : this.paginator, paginationEventHandler : handlePagination, // generateRequest : generateStateString, // moot sortedBy : { key : state.sort, dir : state.dir }, initialRequest : initialRequest }; // Instantiate DataTable this.myDataTable = new YAHOO.widget.DataTable( "serverintegration", // The dom element to contain the DataTable myColumnDefs, // What columns will display this.myDataSource, // The DataSource for our records myConfig // The configuration for *this* instantiation ); // Listen to header link clicks to sort the column this.myDataTable.subscribe('theadCellClickEvent', this.myDataTable.onEventSortColumn); // Override the DataTable's sortColumn method with our intercept handler this.myDataTable.sortColumn = handleSorting; // Override the doBeforeLoadData method to make sure we initialize the // DataTable's RecordSet from the proper starting index this.myDataTable.doBeforeLoadData = doBeforeLoadData }); YAHOO.util.History.initialize("yui-history-field", "yui-history-iframe"); };

### YUI Logger Output:

Note: Logging and debugging is currently turned off for this example.

Reload with logging
and debugging enabled.

### DataTable Control (beta) Examples:

- Basic Example
- Progressive Enhancement
- Custom Cell Formatting
- Nested Headers
- JSON Data Over XHR
- XML Data Over XHR With POST
- Textual Data Over XHR
- Local XML Data
- Client-side Pagination
- Client-side Sorting
- Server-side Pagination
- Server-side Sorting
- Server-side Pagination and Sorting, with Browser History Manager
- XY-scrolling, Y-scrolling, and X-scrolling
- Row Selection
- Cell Selection
- Inline Cell Editing
- Context Menu Integration
- Showing and Hiding Columns
- Highlighting Cells, Rows, or Columns
- Complex Example of Multiple Features
- Datatable with Autocomplete
- Skinning Model
- Configuring the Paginator
- Complex Application (included with examples for Layout Manager (beta))

### More DataTable Control (beta) Resources:

- User's Guide (external)
- API Documentation
- Cheat Sheet PDF (external)

Copyright © 2008 Yahoo! Inc. All rights reserved.

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