YUI Library Home

Site Search (YDN & YUIBlog):

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

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 data

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", "pageSize":10, "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="<?php echo $assetsDirectory; ?>html/blank.html"></iframe> <input id="yui-history-field" type="hidden"> <div id="dt-pag-nav"></div> <div id="bhmintegration"></div>

## CSS

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

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

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

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

(function () { // Create the DataSource var myDataSource = new YAHOO.util.DataSource("assets/php/json_proxy.php?"); myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON; myDataSource.responseSchema = { resultsList: "records", fields: ["id","name","date","price"], metaFields: { totalRecords: "totalRecords", paginationRecordOffset : "startIndex", paginationRowsPerPage : "pageSize", sortKey: "sort", sortDir: "dir" } }; // Create the Paginator var myPaginator = new YAHOO.widget.Paginator({ containers : ["dt-pag-nav"], template : "{PreviousPageLink} {CurrentPageReport} {NextPageLink} {RowsPerPageDropdown}", pageReportTemplate : "Showing items {startIndex} - {endIndex} of {totalRecords}", rowsPerPageOptions : [10,25,50,100] }); // Define Columns 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} ]; // DataTable configurations var myConfig = { paginator : myPaginator, dynamicData : true, initialLoad : false }; // Instantiate DataTable var myDataTable = new YAHOO.widget.DataTable( "bhmintegration", myColumnDefs, myDataSource, myConfig ); // Show loading message while page is being rendered myDataTable.showTableMessage(myDataTable.get("MSG_LOADING"), YAHOO.widget.DataTable.CLASS_LOADING); // Add the instances to the YAHOO.example namespace for inspection YAHOO.example.BHMIntegration = { myPaginator : myPaginator, myDataSource : myDataSource, myDataTable : myDataTable };

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.

// Integrate with Browser History Manager var History = YAHOO.util.History; // Define a custom function to route sorting through the Browser History Manager var handleSorting = function (oColumn) { // Calculate next sort direction for given Column var sDir = this.getColumnSortDir(oColumn); // The next state will reflect the new sort values // while preserving existing pagination rows-per-page // As a best practice, a new sort will reset to page 0 var newState = generateRequest(0, oColumn.key, sDir, this.get("paginator").getRowsPerPage()); // Pass the state along to the Browser History Manager History.navigate("myDataTable", newState); }; myDataTable.sortColumn = handleSorting; // Define a custom function to route pagination through the Browser History Manager var handlePagination = function(state) { // The next state will reflect the new pagination values // while preserving existing sort values // Note that the sort direction needs to be converted from DataTable format to server value var sortedBy = this.get("sortedBy"), newState = generateRequest( state.recordOffset, sortedBy.key, sortedBy.dir, state.rowsPerPage ); // Pass the state along to the Browser History Manager History.navigate("myDataTable", newState); }; // First we must unhook the built-in mechanism... myPaginator.unsubscribe("changeRequest", myDataTable.onPaginatorChangeRequest); // ...then we hook up our custom function myPaginator.subscribe("changeRequest", handlePagination, myDataTable, true); // Update payload data on the fly for tight integration with latest values from server myDataTable.doBeforeLoadData = function(oRequest, oResponse, oPayload) { var meta = oResponse.meta; oPayload.totalRecords = meta.totalRecords || oPayload.totalRecords; oPayload.pagination = { rowsPerPage: meta.paginationRowsPerPage || 10, recordOffset: meta.paginationRecordOffset || 0 }; oPayload.sortedBy = { key: meta.sortKey || "id", dir: (meta.sortDir) ? "yui-dt-" + meta.sortDir : "yui-dt-asc" // Convert from server value to DataTable format }; return true; }; // Returns a request string for consumption by the DataSource var generateRequest = function(startIndex,sortKey,dir,results) { startIndex = startIndex || 0; sortKey = sortKey || "id"; dir = dir = (dir) ? dir.substring(7) : "asc"; // Converts from DataTable format "yui-dt-[dir]" to server value "[dir]" results = results || 10; return "results="+results+"&startIndex="+startIndex+"&sort="+sortKey+"&dir="+dir; }; // Called by Browser History Manager to trigger a new state var handleHistoryNavigation = function (request) { // Sends a new request to the DataSource myDataSource.sendRequest(request,{ success : myDataTable.onDataReturnSetRows, failure : myDataTable.onDataReturnSetRows, scope : myDataTable, argument : {} // Pass in container for population at runtime via doBeforeLoadData }); }; // Calculate the first request var initialRequest = History.getBookmarkedState("myDataTable") || // Passed in via URL generateRequest(); // Get default values // Register the module History.register("myDataTable", initialRequest, handleHistoryNavigation); // Render the first view History.onReady(function() { // Current state after BHM is initialized is the source of truth for what state to render var currentState = History.getCurrentState("myDataTable"); handleHistoryNavigation(currentState); }); // Initialize the Browser History Manager. YAHOO.util.History.initialize("yui-history-field", "yui-history-iframe"); })();

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

### YUI Logger Output:

Note: You are viewing this example in debug mode with logging enabled. This can significantly slow performance.

Reload with logging
and debugging disabled.

### DataTable Control Examples:

- Basic Example
- Progressive Enhancement
- Custom Cell Formatting
- Conditional row coloring
- Nested Headers
- JSON Data Over XHR
- XML Data Over XHR With POST
- XML Data with XPath
- Textual Data Over XHR
- Polling the DataSource
- Adding, Updating, and Deleting Rows
- Client-side Pagination
- Client-side Sorting
- Server-side Pagination and Sorting for Dynamic Data
- Integrating Browser History Manager with Server-side Pagination and Sorting
- XY-scrolling, Y-scrolling, and X-scrolling
- Row Selection
- Cell Selection
- Inline Cell Editing
- Showing, Hiding, and Reordering Columns.
- Highlighting Cells, Rows, or Columns
- Reorder Rows with Drag and Drop
- Row Expansion
- Context Menu Integration
- Configuring the Paginator (included with examples for Paginator)
- TabView Integration
- Complex Example of Multiple Features
- Client-side Filtering of Local Data
- Filtering of Dynamic Data
- Datatable with Autocomplete
- Skinning Model
- Ratings (included with examples for ProgressBar Control)
- YQLDataSource (included with examples for DataSource Utility)
- Complex Application (included with examples for Layout Manager)

### More DataTable Control Resources:

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

Copyright © 2010 Yahoo! Inc. All rights reserved.

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