jQuery(function()
{
// continuous scrolling //
jQuery( document ).on( 'scrollinit', '.releaf_table[data-continuous="1"]', function()
{
var table = jQuery( this );
var container = table.parent();
var thead = table.find( '.thead' );
var tbody = table.find( '.tbody' );
var search_form = table.parents( '.primary_panel' ).find( '.search_form' );
var noOfCols = thead.children().children().length;
var rowHeight = tbody.children().first().height();
var rowLoadTolerance = 15; // how many rows outside viewport to pre-load
var rowRenderTolerance = 40; // how many rows outside viewport to render (could be loaded)
var cachedRowLimit = 400 * 40;
var viewportHeight;
var noOfVisibleRows;
var setupViewport = function()
{
viewportHeight = container.height();
noOfVisibleRows = Math.ceil( viewportHeight / rowHeight );
}
setupViewport();
jQuery( window ).resize(function()
{
setupViewport();
container.scroll();
});
var total, itemsPerPage, noOfPages;
var setupTotals = function()
{
total = table.attr( 'data-total' );
itemsPerPage = table.attr( 'data-items_per_page' );
noOfPages = Math.floor( total / itemsPerPage ) + 1;
}
setupTotals();
var timeout;
var requests = {};
var abortRequests = function()
{
for( var i in requests )
{
requests[i].abort();
}
requests = {};
}
var currentTopPageNo = 1;
var currentBottomPageNo = 1;
var pages = {};
// store current results as page 1
pages[ currentTopPageNo ] = tbody.html();
var clone;
var emptyRowCells = '';
var loadingRowCells = '';
var thCellWidths = {};
// freeze column widths
var freeze = function()
{
// reset header width
if( clone )
{
clone.remove();
}
thead.children().first().children().each(function()
{
var cell = jQuery( this );
var width = cell.width() + 'px';
cell.css( 'width', '' );
cell.css( 'min-width', '' );
cell.css( 'max-width', '' );
});
// freeze it
thead.children().first().children().each(function()
{
var cell = jQuery( this );
var width = cell.width() + 'px';
cell.css( 'width', width );
cell.css( 'min-width', width );
cell.css( 'max-width', width );
});
// add fixed header
clone = thead.clone().insertAfter( thead ).css({ position: 'fixed', zIndex: 100}).addClass('fixed');
clone.css( 'margin-top', '-' + clone.height() + 'px' )
emptyRowCells = '';
loadingRowCells = '';
thCellWidths = {};
thead.children().children().each(function( i )
{
thCellWidths[ i ] = jQuery( this ).width();
});
for( var i = 0; i < noOfCols; i++ )
{
emptyRowCells += ' ';
if( thCellWidths[i] >= 100 )
{
loadingRowCells += '' + table.attr( 'data-loading' ) + '';
}
else
{
loadingRowCells += ' ';
}
}
emptyRow = '
' + emptyRowCells + '
';
loadingRow = '' + loadingRowCells + '
';
}
freeze();
var getEmptyRows = function( no )
{
var rows = [];
for( var i = 0; i < no; i++ )
{
rows.push( loadingRow );
}
return rows.join( '' );
}
// initial setup
var postHeight = total * rowHeight - tbody.children().length * rowHeight;
if( postHeight > 0 )
{
var post = jQuery( emptyRow ).addClass( 'post' ).appendTo( tbody );
post.height( postHeight );
}
container.scroll(function()
{
clearTimeout( timeout );
timeout = setTimeout(function()
{
var offsets =
{
visible:
{
top: 0,
bottom: 0
},
load:
{
top: 0,
bottom: 0
},
render:
{
top: 0,
bottom: 0
}
};
var pageNumbers =
{
load:
{
top: 0,
bottom: 0
},
render:
{
top: 0,
bottom: 0
}
}
offsets.visible.top = Math.floor( Math.max( 0, container.prop( 'scrollTop' ) - thead.height() ) / rowHeight );
offsets.visible.bottom = offsets.visible.top + noOfVisibleRows;
// adjust for loading tolerance
offsets.load.top = Math.max( 0, offsets.visible.top - rowLoadTolerance );
offsets.load.bottom = Math.min( offsets.visible.bottom + rowLoadTolerance, total );
// adjust for rendering tolerance
offsets.render.top = Math.max( 0, offsets.visible.top - rowRenderTolerance );
offsets.render.bottom = Math.min( offsets.visible.bottom + rowRenderTolerance, total );
pageNumbers.load.top = Math.floor( offsets.load.top / itemsPerPage ) + 1;
pageNumbers.load.bottom = Math.floor( offsets.load.bottom / itemsPerPage ) + 1;
pageNumbers.render.top = Math.floor( offsets.render.top / itemsPerPage ) + 1;
pageNumbers.render.bottom = Math.floor( offsets.render.bottom / itemsPerPage ) + 1;
var preOffset = ( pageNumbers.render.top - 1 ) * itemsPerPage;
var postOffset = Math.max( 0, total - pageNumbers.render.bottom * itemsPerPage );
if( pageNumbers.load.top != currentTopPageNo || pageNumbers.load.bottom != currentBottomPageNo )
{
abortRequests();
var no = 0;
for( var i in pages )
{
if( pages[i] )
{
no++;
}
}
// clear memory
if( no * itemsPerPage > cachedRowLimit )
{
pages = {};
}
var pagesToLoad = {};
for( var i = 0; i <= pageNumbers.load.bottom - pageNumbers.load.top; i++ )
{
pagesToLoad[ pageNumbers.load.top + i ] = true;
}
var pagesToRender = {};
for( var i = 0; i <= pageNumbers.render.bottom - pageNumbers.render.top; i++ )
{
pagesToRender[ pageNumbers.render.top + i ] = true;
}
var inject = function()
{
var rows = '';
for( var i in pagesToRender )
{
if( pages[ i ] === undefined )
{
if( i == noOfPages ) // last page is likely to be smaller
{
rows += getEmptyRows( total - ( noOfPages - 1 ) * itemsPerPage );
}
else
{
rows += getEmptyRows( itemsPerPage );
}
}
else
{
rows += pages[ i ];
}
}
currentTopPageNo = pageNumbers.load.top;
currentBottomPageNo = pageNumbers.load.bottom;
var pre = '';
if( preOffset > 0 )
{
var pre = '' + emptyRowCells + '
';
}
var post = '';
if( postOffset > 0 )
{
var post = '' + emptyRowCells + '
';
}
tbody.html( pre + rows + post );
// check if row width need to be recalculated
if
(
container.prop( 'clientWidth' ) > 0
&&
container.prop( 'clientWidth' ) < container.prop( 'scrollWidth' )
)
{
freeze();
}
return true;
}
for( var i in pagesToLoad )
{
if( pages[ i ] === undefined )
{
(function(){
var pageNo = i;
var key = Math.random() + '';
var searchUrl = new RequestUrl();
searchUrl.add( search_form.serializeArray() );
searchUrl.add({ ajax: 1, page: pageNo });
requests[key] = jQuery.ajax
({
url: searchUrl.getUrl(),
success: function( html, status )
{
delete requests[key];
pages[ pageNo ] = jQuery( html ).find( '.releaf_table .tbody' ).html();
inject();
}
});
})();
}
}
inject();
}
},20);
});
container.scroll();
table.bind( 'flushcache', function()
{
pages = {};
setupTotals();
});
});
jQuery( '.releaf_table[data-continuous="1"]' ).trigger( 'scrollinit' );
});