mirror of
https://github.com/Mottie/tablesorter.git
synced 2024-11-15 23:54:22 +00:00
AJAX paging updates. This patch fixes issues with update events being re-triggered continuously and AJAX error handling being bound too many times. It also adds support for passing filtering parameters with the AJAX request.
This commit is contained in:
parent
351e3ad699
commit
3d415333cc
@ -11,10 +11,12 @@
|
||||
// target the pager markup
|
||||
container: null,
|
||||
|
||||
// use this format: "http://mydatabase.com?page={page}&size={size}&{sortList:col}"
|
||||
// where {page} is replaced by the page number and {size} is replaced by the number of records to show
|
||||
// {sortList:col} adds the sortList to the url into a "col" array.
|
||||
// use this format: "http://mydatabase.com?page={page}&size={size}&{sortList:col}&{filterList:fcol}"
|
||||
// where {page} is replaced by the page number, {size} is replaced by the number of records to show,
|
||||
// {sortList:col} adds the sortList to the url into a "col" array, and {filterList:fcol} adds
|
||||
// the filterList to the url into an "fcol" array.
|
||||
// So a sortList = [[2,0],[3,0]] becomes "&col[2]=0&col[3]=0" in the url
|
||||
// and a filterList = [[2,Blue],[3,13]] becomes "&fcol[2]=Blue&fcol[3]=13" in the url
|
||||
ajaxUrl: null,
|
||||
|
||||
// process ajax so that the following information is returned:
|
||||
@ -69,7 +71,8 @@
|
||||
totalRows: 0,
|
||||
totalPages: 0,
|
||||
filteredRows: 0,
|
||||
filteredPages: 0
|
||||
filteredPages: 0,
|
||||
cssErrorRow: 'tablesorter-errorRow'
|
||||
|
||||
};
|
||||
|
||||
@ -81,7 +84,6 @@
|
||||
r = 'removeClass',
|
||||
d = c.cssDisabled,
|
||||
dis = !!disable,
|
||||
// tr = Math.min( c.totalRows, c.filteredRows ),
|
||||
tp = Math.min( c.totalPages, c.filteredPages );
|
||||
if ( c.updateArrows ) {
|
||||
$(c.cssFirst + ',' + c.cssPrev, c.container)[ ( dis || c.page === 0 ) ? a : r ](d);
|
||||
@ -90,7 +92,7 @@
|
||||
},
|
||||
|
||||
updatePageDisplay = function(table, c) {
|
||||
var i, p, s, t, out, f = $(table).hasClass('hasFilters');
|
||||
var i, p, s, t, out, f = $(table).hasClass('hasFilters') && !c.ajaxUrl;
|
||||
c.filteredRows = (f) ? $(table).find('tbody tr:not(.filtered)').length : c.totalRows;
|
||||
c.filteredPages = (f) ? Math.ceil( c.filteredRows / c.size ) : c.totalPages;
|
||||
if ( Math.min( c.totalPages, c.filteredPages ) > 0 ) {
|
||||
@ -187,7 +189,7 @@
|
||||
tc = table.config,
|
||||
$b = $(table.tBodies).filter(':not(.' + tc.cssInfoBlock + ')'),
|
||||
hl = $t.find('thead th').length, tds = '',
|
||||
err = '<tr class="' + tc.selectorRemove + '"><td style="text-align: center;" colspan="' + hl + '">' +
|
||||
err = '<tr class="' + c.cssErrorRow + '"><td style="text-align: center;" colspan="' + hl + '">' +
|
||||
(exception ? exception.message + ' (' + exception.name + ')' : 'No rows found') + '</td></tr>',
|
||||
result = c.ajaxProcessing(data) || [ 0, [] ],
|
||||
d = result[1] || [],
|
||||
@ -225,13 +227,17 @@
|
||||
$f.eq(j).html( th[j] );
|
||||
});
|
||||
}
|
||||
|
||||
$t.find('thead tr.' + c.cssErrorRow).remove(); //Clean up any previous error.
|
||||
if ( exception ) {
|
||||
// add error row to thead instead of tbody, or clicking on the header will result in a parser error
|
||||
$t.find('thead').append(err);
|
||||
} else {
|
||||
$b.html( tds ); // add tbody
|
||||
}
|
||||
$.tablesorter.isProcessing(table); // remove loading icon
|
||||
if (tc.showProcessing) {
|
||||
$.tablesorter.isProcessing(table); // remove loading icon
|
||||
}
|
||||
$t.trigger('update');
|
||||
c.totalRows = result[0] || 0;
|
||||
c.totalPages = Math.ceil( c.totalRows / c.size );
|
||||
@ -246,29 +252,53 @@
|
||||
},
|
||||
|
||||
getAjax = function(table, c){
|
||||
var url = (c.ajaxUrl) ? c.ajaxUrl.replace(/\{page\}/g, c.page).replace(/\{size\}/g, c.size) : '',
|
||||
arry = [],
|
||||
sl = table.config.sortList,
|
||||
col = url.match(/\{sortList[\s+]?:[\s+]?(.*)\}/);
|
||||
if (col) {
|
||||
col = col[1];
|
||||
$.each(sl, function(i,v){
|
||||
arry.push(col + '[' + v[0] + ']=' + v[1]);
|
||||
});
|
||||
// if the arry is empty, just add the col parameter... "&{sortList:col}" becomes "&col"
|
||||
url = url.replace(/\{sortList[\s+]?:[\s+]?(.*)\}/g, arry.length ? arry.join('&') : col );
|
||||
}
|
||||
var url = getAjaxUrl(table, c),
|
||||
tc = table.config;
|
||||
if ( url !== '' ) {
|
||||
// loading icon
|
||||
$.tablesorter.isProcessing(table, true);
|
||||
$(document).ajaxError(function(e, xhr, settings, exception) {
|
||||
renderAjax(null, table, c, exception);
|
||||
if (tc.showProcessing) {
|
||||
$.tablesorter.isProcessing(table, true); // show loading icon
|
||||
}
|
||||
$(document).bind('ajaxError.pager', function(e, xhr, settings, exception) {
|
||||
if (settings.url == url) {
|
||||
renderAjax(null, table, c, exception);
|
||||
$(document).unbind('ajaxError.pager');
|
||||
}
|
||||
});
|
||||
$.getJSON(url, function(data) {
|
||||
renderAjax(data, table, c);
|
||||
$(document).unbind('ajaxError.pager');
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
getAjaxUrl = function(table, c) {
|
||||
var url = (c.ajaxUrl) ? c.ajaxUrl.replace(/\{page\}/g, c.page).replace(/\{size\}/g, c.size) : '',
|
||||
sl = table.config.sortList,
|
||||
fl = c.currentFilters || [],
|
||||
sortCol = url.match(/\{sortList[\s+]?:[\s+]?([^}]*)\}/),
|
||||
filterCol = url.match(/\{filterList[\s+]?:[\s+]?([^}]*)\}/),
|
||||
arry = [];
|
||||
if (sortCol) {
|
||||
sortCol = sortCol[1];
|
||||
$.each(sl, function(i,v){
|
||||
arry.push(sortCol + '[' + v[0] + ']=' + v[1]);
|
||||
});
|
||||
// if the arry is empty, just add the col parameter... "&{sortList:col}" becomes "&col"
|
||||
url = url.replace(/\{sortList[\s+]?:[\s+]?([^}]*)\}/g, arry.length ? arry.join('&') : sortCol );
|
||||
}
|
||||
if (filterCol) {
|
||||
filterCol = filterCol[1];
|
||||
$.each(fl, function(i,v){
|
||||
if (v) {
|
||||
arry.push(filterCol + '[' + i + ']=' + encodeURIComponent(v));
|
||||
}
|
||||
});
|
||||
// if the arry is empty, just add the fcol parameter... "&{filterList:fcol}" becomes "&fcol"
|
||||
url = url.replace(/\{filterList[\s+]?:[\s+]?([^}]*)\}/g, arry.length ? arry.join('&') : filterCol );
|
||||
}
|
||||
|
||||
return url;
|
||||
},
|
||||
|
||||
renderTable = function(table, rows, c) {
|
||||
var i, j, o,
|
||||
@ -329,13 +359,13 @@
|
||||
if ( c.page < 0 || c.page > ( p - 1 ) ) {
|
||||
c.page = 0;
|
||||
}
|
||||
// change if page changed - fixes #182
|
||||
if (c.ajax && $.data(table, 'pagerLastPage') !== c.page) {
|
||||
if (c.ajax) {
|
||||
getAjax(table, c);
|
||||
} else if (!c.ajax) {
|
||||
renderTable(table, table.config.rowsCopy, c);
|
||||
}
|
||||
$.data(table, 'pagerLastPage', c.page);
|
||||
$.data(table, 'pagerUpdateTriggered', true);
|
||||
if (c.initialized) { $(table).trigger('pageMoved', c); }
|
||||
},
|
||||
|
||||
@ -414,6 +444,7 @@
|
||||
var config = this.config,
|
||||
c = config.pager = $.extend( {}, $.tablesorterPager.defaults, settings ),
|
||||
table = this,
|
||||
tc = table.config,
|
||||
$t = $(table),
|
||||
pager = $(c.container).addClass('tablesorter-pager').show(); // added in case the pager is reinitialized after being destroyed.
|
||||
config.appender = $this.appender;
|
||||
@ -423,6 +454,9 @@
|
||||
if ( typeof(c.ajaxUrl) === 'string' ) {
|
||||
// ajax pager; interact with database
|
||||
c.ajax = true;
|
||||
//When filtering with ajax, allow only custom filtering function, disable default filtering since it will be done server side.
|
||||
tc.widgetOptions.filter_serversideFiltering = true;
|
||||
tc.serverSideSorting = true;
|
||||
getAjax(table, c);
|
||||
} else {
|
||||
c.ajax = false;
|
||||
@ -430,17 +464,27 @@
|
||||
$(this).trigger("appendCache", true);
|
||||
hideRowsSetup(table, c);
|
||||
}
|
||||
|
||||
|
||||
$(table)
|
||||
.unbind('filterStart.pager')
|
||||
.bind('filterStart.pager', function(e, filters) {
|
||||
c.currentFilters = filters;
|
||||
});
|
||||
|
||||
// update pager after filter widget completes
|
||||
$(table)
|
||||
.unbind('filterEnd.pager updateComplete.pager ')
|
||||
.bind('filterEnd.pager updateComplete.pager', function() {
|
||||
if ($(this).hasClass('hasFilters')) {
|
||||
c.page = 0;
|
||||
updatePageDisplay(table, c);
|
||||
moveToPage(table, c);
|
||||
changeHeight(table, c);
|
||||
.unbind('filterEnd.pager sortEnd.pager')
|
||||
.bind('filterEnd.pager sortEnd.pager', function() {
|
||||
//Prevent infinite event loops from occuring by setting this in all moveToPage calls and catching it here.
|
||||
if ($.data(table, 'pagerUpdateTriggered')) {
|
||||
$.data(table, 'pagerUpdateTriggered', false);
|
||||
return;
|
||||
}
|
||||
|
||||
c.page = 0;
|
||||
updatePageDisplay(table, c);
|
||||
moveToPage(table, c);
|
||||
changeHeight(table, c);
|
||||
});
|
||||
|
||||
if ( $(c.cssGoto, pager).length ) {
|
||||
|
@ -40,6 +40,7 @@
|
||||
sortMultiSortKey : 'shiftKey', // key used to select additional columns
|
||||
usNumberFormat : true, // false for German "1.234.567,89" or French "1 234 567,89"
|
||||
delayInit : false, // if false, the parsed table contents will not update until the first sort
|
||||
serverSideSorting : false, // if true, server-side sorting should be performed because client-side sorting will be disabled, but the ui and events will still be used.
|
||||
|
||||
// sort options
|
||||
headers : {}, // set sorter, string, empty, locked order, sortInitialOrder, filter, etc.
|
||||
@ -459,6 +460,9 @@
|
||||
var dynamicExp, sortWrapper, col, mx = 0, dir = 0, tc = table.config,
|
||||
sortList = tc.sortList, l = sortList.length, bl = table.tBodies.length,
|
||||
sortTime, i, j, k, c, colMax, cache, lc, s, e, order, orgOrderCol;
|
||||
if (tc.serverSideSorting) {
|
||||
return;
|
||||
}
|
||||
if (tc.debug) { sortTime = new Date(); }
|
||||
for (k = 0; k < bl; k++) {
|
||||
colMax = tc.cache[k].colMax;
|
||||
|
@ -282,6 +282,7 @@ $.tablesorter.addWidget({
|
||||
filter_searchDelay : 300 // typing delay in milliseconds before starting a search
|
||||
filter_startsWith : false // if true, filter start from the beginning of the cell contents
|
||||
filter_useParsedData : false // filter all data using parsed content
|
||||
filter_serversideFiltering : false // if true, server-side filtering should be performed because client-side filtering will be disabled, but the ui and events will still be used.
|
||||
**************************/
|
||||
$.tablesorter.addWidget({
|
||||
id: "filter",
|
||||
@ -353,7 +354,7 @@ $.tablesorter.addWidget({
|
||||
$tb = $.tablesorter.processTbody(table, $(b[k]), true);
|
||||
$tr = $tb.children('tr');
|
||||
l = $tr.length;
|
||||
if (cv === ''){
|
||||
if (cv === '' || wo.filter_serversideFiltering){
|
||||
$tr.show().removeClass('filtered');
|
||||
} else {
|
||||
// loop through the rows
|
||||
|
Loading…
Reference in New Issue
Block a user