This is mainly for my own information retrieval, but perhaps it might be useful to another Javascript developer out there who is using ExtJS.
I’ve got a list of several thousand insurance plans I need to display to the users of one of my applications. I originally implemented a standard Ext.PagingToolbar to add to the footer of my data grid, but I’ve never been a fan of that navigation pattern, and I suspect that my users wouldn’t be either.
I then thought of sites like Google Reader that automatically retrieves the next set of records as soon as it detects that you’ve scrolled to a certain place in the reading element. A quick trip to my friend Google uncovered an article on The Code Project by Jason Witty that provided an example of just this technique.
A quick adaptation to my application provided a working example:
var emptyData;
// Set default scroll variables.
var currentpos = 0;
var currentpage = 1;
// Set constants.
//itemsperpage: number of records that appear on each page of content.
var itemsperpage = 100;
// Number of pages of content to fetch when offset reached.
var pagestofetch = 1;
// Number of pixel interval to fire handler request. You'll need to adjust this value
// depending on the location and size of your data grid
var scrolloffset = 1800;
var scrolloffsetinterval = 1800;
// Create the column model to display only the data needed for the users
var InsurerColumnModel = new Ext.grid.ColumnModel([{
id: 'col1',
header: 'Abbreviation',
dataIndex: 'col1',
width: 120
},{
id: 'col2',
header: 'Name',
dataIndex: 'col2',
width: 240
},{
id: 'col3',
header: 'Group',
dataIndex: 'col3',
width: 120
}
]);
// Create a JSON Store to hold the data elements
var ScrollingProviderStore = new Ext.data.JsonStore({
data: emptyData,
root: 'data',
fields: Insurer
});
// Create the grid to display each insurer
var InsurerGrid = new Ext.grid.GridPanel({
store: ScrollingProviderStore,
sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
cm: InsurerColumnModel,
renderTo: 'insurer-display-grid',
stripeRows: true,
width:'auto',
height:350,
autoScroll: true,
autoExpandColumn:'col2',
title:'Insurance Plans',
frame:true
});
// Create an event listener for when the user scrolls the grid
InsurerGrid.addListener('bodyscroll',scrollListener);
// Fires when grid is scrolled
function scrollListener(scrollLeft, scrollTop){
// Only handle scroll downs past highest position.
if ( scrollTop > currentpos )
{
// Check if we should get more data
if ( scrollTop > scrolloffset )
{
// Store current grid scroll state.
var state = InsurerGrid.getView().getScrollState();
// Adjust scroll offset
scrolloffset = scrollTop + scrolloffsetinterval;
// Adjust current page
currentpage = currentpage + 1;
$.AjaxCFC({
url: 'ajaxCFC/ajax.cfc',
factory: 'application.framework',
bean: 'Insurance',
method: 'listProviders',
data: { 'start': currentpage },
timeout:30000,
useDefaultErrorHandler: false,
success: function(result) {
var insurers = eval('(' + result + ')');
ScrollingProviderStore.loadData(insurers,true);
// Restore the scrollbar state back to where the user
// triggered the load.
InsurerGrid.getView().restoreScroll(state);
},
error: function(results) {
Ext.MessageBox.alert('Failed', 'Failed to retrieve insurers. Please try again.');
}
});
}
currentpos=scrollTop;
}
};