pager update

This commit is contained in:
Rob Garrison 2012-03-07 11:59:39 -06:00
parent 580a3049cb
commit b85070154f
10 changed files with 1099 additions and 167 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -19,4 +19,9 @@ div.tablesorterPager input {
width: 50px;
border: 1px solid #330000;
text-align: center;
}
#tablesorterPagerLoading {
background: rgba(255,255,255,0.8) url(icons/loading.gif) center center no-repeat;
position: absolute;
z-index: 1000;
}

View File

@ -1,18 +1,69 @@
/*
* tablesorter pager plugin
* updated 2/16/2012
* updated 3/7/2012
*/
(function($) {
$.extend({tablesorterPager: new function() {
this.defaults = {
// target the pager markup
container: null,
// use this format: "http:/mydatabase.com?page={page}&size={size}"
// where {page} is replaced by the page number and {size} is replaced by the number of records to show
ajaxUrl: null,
// process ajax so that the data object is returned along with the total number of rows
ajaxProcessing: function(ajax){ return [ [{ "key" : "value" }], 100 ]; },
// output default: '{page}/{totalPages}'
output: '{startRow} to {endRow} of {totalRows} rows', // '{page}/{totalPages}'
// apply disabled classname to the pager arrows when the rows at either extreme is visible
updateArrows: true,
// starting page of the pager (zero based index)
page: 0,
// Number of visible rows
size: 10,
// if true, the table will remain the same height no matter how many records are displayed. The space is made up by an empty
// table row set to a height to compensate; default is false
fixedHeight: false,
// remove rows from the table to speed up the sort of large tables.
// setting this to false, only hides the non-visible rows; needed if you plan to add/remove rows with the pager enabled.
removeRows: true, // removing rows in larger tables speeds up the sort
// css class names of pager arrows
cssNext: '.next', // next page arrow
cssPrev: '.prev', // previous page arrow
cssFirst: '.first', // first page arrow
cssLast: '.last', // last page arrow
cssPageDisplay: '.pagedisplay', // location of where the "output" is displayed
cssPageSize: '.pagesize', // page size selector - select dropdown that sets the "size" option
// class added to arrows when at the extremes (i.e. prev/first arrows are "disabled" when on the first page)
cssDisabled: 'disabled', // Note there is no period "." in front of this class name
// stuff not set by the user
totalRows: 0,
totalPages: 0
};
var $this = this,
// hide arrows at extremes
var pagerArrows = function(c) {
var a = 'addClass', r = 'removeClass', d = c.cssDisabled;
pagerArrows = function(c, disable) {
var a = 'addClass', r = 'removeClass',
d = c.cssDisabled, dis = !!disable;
if (c.updateArrows) {
c.container[(c.totalRows < c.size) ? a : r](d);
$(c.cssFirst + ',' + c.cssPrev, c.container)[(c.page === 0) ? a : r](d);
$(c.cssNext + ',' + c.cssLast, c.container)[(c.page === c.totalPages - 1) ? a : r](d);
$(c.cssFirst + ',' + c.cssPrev, c.container)[(dis || c.page === 0) ? a : r](d);
$(c.cssNext + ',' + c.cssLast, c.container)[(dis || c.page === c.totalPages - 1) ? a : r](d);
}
},
@ -30,31 +81,37 @@
'{totalRows}' : c.totalRows
}[m];
});
if (out[0].tagName === 'INPUT') {
out.val(s);
} else {
out.html(s);
if (out[0]) {
out[ (out[0].tagName === 'INPUT') ? 'val' : 'html' ](s);
}
pagerArrows(c);
c.container.show(); // added in case the pager is reinitialized after being destroyed.
$(table).trigger('pagerComplete', c);
},
fixPosition = function(table, c) {
var o = $(table);
if (!c.pagerPositionSet && c.positionFixed) {
if (o.offset) {
c.container.css({
top: o.offset().top + o.height() + c.offset + 'px',
position: 'absolute'
});
fixHeight = function(table, c) {
var d, h, $b = $(table.tBodies[0]);
if (c.fixedHeight) {
$b.find('tr.pagerSavedHeightSpacer').remove();
h = $.data(table, 'pagerSavedHeight');
if (h) {
d = h - $b.height();
if (d > 5 && $.data(table, 'pagerLastSize') === c.size && $b.find('tr:visible').length < c.size) {
$b.append('<tr class="pagerSavedHeightSpacer remove-me" style="height:' + d + 'px;"></tr>');
}
}
c.pagerPositionSet = true;
}
},
changeHeight = function(table, c) {
var $b = $(table.tBodies[0]);
$b.find('tr.pagerSavedHeightSpacer').remove();
$.data(table, 'pagerSavedHeight', $b.height());
fixHeight(table, c);
$.data(table, 'pagerLastSize', c.size);
},
hideRows = function(table, c){
var i, rows = $('tr:not(.' + c.cssChildRow + ')', table.tBodies[0]),
var i, rows = $('tr:not(.' + table.config.cssChildRow + ')', table.tBodies[0]),
l = rows.length,
s = (c.page * c.size),
e = (s + c.size);
@ -65,7 +122,8 @@
},
hideRowsSetup = function(table, c){
c.size = c.lastSize = parseInt($(c.cssPageSize, c.container).val(), 10);
c.size = parseInt($(c.cssPageSize, c.container).val(), 10);
$.data(table, 'pagerLastSize', c.size);
pagerArrows(c);
if (!c.removeRows) {
hideRows(table, c);
@ -76,6 +134,55 @@
}
},
getAjax = function(table, c){
var i, $load, $t = $(table), $b = $(table.tBodies[0]),
url = c.ajaxUrl.replace(/\{page\}/g, c.page).replace(/\{size\}/g, c.size);
if (url !== '') {
// loading icon
$load = $('<div/>', {
id : 'tablesorterPagerLoading',
width : $t.outerWidth(true),
height: $t.outerHeight(true)
});
$t.before($load);
$.getJSON(url, function(data) {
// process data
if (typeof(c.ajaxProcessing) === "function") {
var result = c.ajaxProcessing(data), d = result[0], l = d.length,
i, k, th = [], tds = '', tf = '';
for ( i=0; i < l; i++ ) {
tds += '<tr>';
for (k in d[i]) {
if (typeof(k) === "string") {
// get new header text
if ( i === 0 ) { th.push(k); }
// build tbody cells
tds += '<td>' + d[i][k] + '</td>';
}
}
tds += '</tr>';
}
$t.find('thead th').each(function(j){
var $t = $(this),
// add new test within the first span it finds, or just in the header
tar = ($t.find('span').length) ? $t.find('span:first') : $t;
$t.html(th[j]);
tf += '<th>' + th[j] + '</th>';
});
$t.find('tfoot').html('<tr>' + tf + '</tr>');
$b.html(tds); // add tbody
$load.remove(); // remove loading icon
$t.trigger('update');
c.totalRows = result[1];
c.totalPages = Math.ceil(c.totalRows / c.size);
updatePageDisplay(table, c);
fixHeight(table, c);
$t.trigger('pagerChange', c);
}
});
}
},
renderTable = function(table, rows, c) {
var i, j, o,
tableBody = $(table.tBodies[0]),
@ -90,8 +197,7 @@
if (e > rows.length ) {
e = rows.length;
}
// clear the table body
$.tablesorter.clearTableBody(table);
$(table.tBodies[0]).empty();
for (i = s; i < e; i++) {
o = rows[i];
l = o.length;
@ -100,20 +206,29 @@
}
}
}
fixPosition(table, tableBody, c);
$(table).trigger("applyWidgets");
if ( c.page >= c.totalPages ) {
moveToLastPage(table, c);
}
updatePageDisplay(table, c);
if (!c.isDisabled) { fixHeight(table, c); }
},
showAllRows = function(table, c){
c.lastPage = c.page;
c.lastSize = c.size;
c.size = c.totalRows;
c.totalPages = 1;
renderTable(table, c.rowsCopy, c);
if (c.ajax) {
pagerArrows(c, true);
} else {
c.isDisabled = true;
$.data(table, 'pagerLastPage', c.page);
$.data(table, 'pagerLastSize', c.size);
c.page = 0;
c.size = c.totalRows;
c.totalPages = 1;
$('tr.pagerSavedHeightSpacer', table.tBodies[0]).remove();
renderTable(table, table.config.rowsCopy, c);
}
// disable size selector
$(c.cssPageSize, c.container).addClass(c.cssDisabled)[0].disabled = true;
},
moveToPage = function(table, c) {
@ -121,15 +236,20 @@
if (c.page < 0 || c.page > (c.totalPages-1)) {
c.page = 0;
}
renderTable(table, c.rowsCopy, c);
$.data(table, 'pagerLastPage', c.page);
if (c.ajax) {
getAjax(table, c);
} else {
renderTable(table, table.config.rowsCopy, c);
}
},
setPageSize = function(table, size, c) {
c.size = c.lastSize = size;
c.size = size;
$.data(table, 'pagerLastPage', c.page);
$.data(table, 'pagerLastSize', c.size);
c.totalPages = Math.ceil(c.totalRows / c.size);
c.pagerPositionSet = false;
moveToPage(table, c);
fixPosition(table, c);
},
moveToFirstPage = function(table, c) {
@ -161,112 +281,91 @@
destroyPager = function(table, c){
showAllRows(table, c);
c.container.hide(); // hide pager
c.appender = null; // remove pager appender function
table.config.appender = null; // remove pager appender function
$(table).unbind('destroy.pager sortEnd.pager enable.pager disable.pager');
},
enablePager = function(table, c){
enablePager = function(table, c, triggered){
var p = $(c.cssPageSize, c.container).removeClass(c.cssDisabled).removeAttr('disabled');
c.isDisabled = false;
$('table').trigger('update');
c.page = c.lastPage || 0;
c.page = $.data(table, 'pagerLastPage') || 0;
c.size = $.data(table, 'pagerLastSize') || parseInt(p.val(), 10);
c.totalPages = Math.ceil(c.totalRows / c.size);
hideRowsSetup(table, c);
};
this.appender = function(table, rows) {
var c = table.config;
c.rowsCopy = rows;
c.totalRows = rows.length;
c.size = c.lastSize || c.size;
c.totalPages = Math.ceil(c.totalRows / c.size);
renderTable(table, rows, c);
};
this.defaults = {
// target the pager markup
container: null,
// output default: '{page}/{totalPages}'
output: '{startRow} to {endRow} of {totalRows} rows', // '{page}/{totalPages}'
// apply disabled classname to the pager arrows when the rows at either extreme is visible
updateArrows: true,
// starting page of the pager (zero based index)
page: 0,
// Number of visible rows
size: 10,
// if true, moves the pager below the table at a fixed position; so if only 2 rows showing, the pager remains in the same place
positionFixed: true,
// offset added to the pager top, but only when "positionFixed" is true
offset: 0,
// remove rows from the table to speed up the sort of large tables.
// setting this to false, only hides the non-visible rows; needed if you plan to add/remove rows with the pager enabled.
removeRows: true, // removing rows in larger tables speeds up the sort
// css class names of pager arrows
cssNext: '.next', // next page arrow
cssPrev: '.prev', // previous page arrow
cssFirst: '.first', // first page arrow
cssLast: '.last', // last page arrow
cssPageDisplay: '.pagedisplay', // location of where the "output" is displayed
cssPageSize: '.pagesize', // page size selector - select dropdown that sets the "size" option
// class added to arrows when at the extremes (i.e. prev/first arrows are "disabled" when on the first page)
cssDisabled: 'disabled', // Note there is no period "." in front of this class name
// stuff not set by the user
totalRows: 0,
totalPages: 0,
appender: this.appender
};
this.construct = function(settings) {
return this.each(function() {
var c = $.extend(this.config, $.tablesorterPager.defaults, settings),
table = this,
pager = c.container;
$(this).trigger("appendCache");
if (triggered) {
$('table').trigger('update');
setPageSize(table, c.size, c);
hideRowsSetup(table, c);
fixHeight(table, c);
}
};
$this.appender = function(table, rows) {
var c = table.config.pager;
if (!c.ajax) {
table.config.rowsCopy = rows;
c.totalRows = rows.length;
c.size = $.data(table, 'pagerLastSize') || c.size;
c.totalPages = Math.ceil(c.totalRows / c.size);
renderTable(table, rows, c);
}
};
$this.construct = function(settings) {
return this.each(function() {
var config = this.config,
c = config.pager = $.extend({}, $.tablesorterPager.defaults, settings),
table = this,
$t = $(table),
pager = $(c.container).show(); // added in case the pager is reinitialized after being destroyed.
config.appender = $this.appender;
enablePager(table, c, false);
if (typeof(c.ajaxUrl) === 'string') {
// ajax pager; interact with database
c.ajax = true;
getAjax(table, c);
} else {
c.ajax = false;
// Regular pager; all rows stored in memory
$(this).trigger("appendCache");
hideRowsSetup(table, c);
}
$(c.cssFirst,pager).unbind('click.pager').bind('click.pager', function() {
moveToFirstPage(table, c);
if (!$(this).hasClass(c.cssDisabled)) { moveToFirstPage(table, c); }
return false;
});
$(c.cssNext,pager).unbind('click.pager').bind('click.pager', function() {
moveToNextPage(table, c);
if (!$(this).hasClass(c.cssDisabled)) { moveToNextPage(table, c); }
return false;
});
$(c.cssPrev,pager).unbind('click.pager').bind('click.pager', function() {
moveToPrevPage(table, c);
if (!$(this).hasClass(c.cssDisabled)) { moveToPrevPage(table, c); }
return false;
});
$(c.cssLast,pager).unbind('click.pager').bind('click.pager', function() {
moveToLastPage(table, c);
if (!$(this).hasClass(c.cssDisabled)) { moveToLastPage(table, c); }
return false;
});
$(c.cssPageSize,pager).unbind('change.pager').bind('change.pager', function() {
setPageSize(table, parseInt($(this).val(), 10), c);
$(c.cssPageSize,pager).val( $(this).val() ); // in case there are more than one pagers
if (!$(this).hasClass(c.cssDisabled)) {
setPageSize(table, parseInt($(this).val(), 10), c);
changeHeight(table, c);
}
return false;
});
$(this)
.unbind('disable.pager enable.pager destroy.pager')
.bind('disable.pager', function(){
c.isDisabled = true;
showAllRows(table, c);
})
.bind('enable.pager', function(){
enablePager(table, c);
})
.bind('destroy.pager', function(){
destroyPager(table, c);
});
$t
.unbind('disable.pager enable.pager destroy.pager')
.bind('disable.pager', function(){
showAllRows(table, c);
})
.bind('enable.pager', function(){
enablePager(table, c, true);
})
.bind('destroy.pager', function(){
destroyPager(table, c);
});
});
};

File diff suppressed because one or more lines are too long

155
docs/assets/City0.json Normal file
View File

@ -0,0 +1,155 @@
{
"total_rows": "80",
"data" : [{
"ID": 1,
"Name": "Kabul",
"CountryCode": "AFG",
"District": "Kabol",
"Population": 1780000
}, {
"ID": 2,
"Name": "Qandahar",
"CountryCode": "AFG",
"District": "Qandahar",
"Population": 237500
}, {
"ID": 3,
"Name": "Herat",
"CountryCode": "AFG",
"District": "Herat",
"Population": 186800
}, {
"ID": 4,
"Name": "Mazar-e-Sharif",
"CountryCode": "AFG",
"District": "Balkh",
"Population": 127800
}, {
"ID": 5,
"Name": "Amsterdam",
"CountryCode": "NLD",
"District": "Noord-Holland",
"Population": 731200
}, {
"ID": 6,
"Name": "Rotterdam",
"CountryCode": "NLD",
"District": "Zuid-Holland",
"Population": 593321
}, {
"ID": 7,
"Name": "Haag",
"CountryCode": "NLD",
"District": "Zuid-Holland",
"Population": 440900
}, {
"ID": 8,
"Name": "Utrecht",
"CountryCode": "NLD",
"District": "Utrecht",
"Population": 234323
}, {
"ID": 9,
"Name": "Eindhoven",
"CountryCode": "NLD",
"District": "Noord-Brabant",
"Population": 201843
}, {
"ID": 10,
"Name": "Tilburg",
"CountryCode": "NLD",
"District": "Noord-Brabant",
"Population": 193238
}, {
"ID": 11,
"Name": "Groningen",
"CountryCode": "NLD",
"District": "Groningen",
"Population": 172701
}, {
"ID": 12,
"Name": "Breda",
"CountryCode": "NLD",
"District": "Noord-Brabant",
"Population": 160398
}, {
"ID": 13,
"Name": "Apeldoorn",
"CountryCode": "NLD",
"District": "Gelderland",
"Population": 153491
}, {
"ID": 14,
"Name": "Nijmegen",
"CountryCode": "NLD",
"District": "Gelderland",
"Population": 152463
}, {
"ID": 15,
"Name": "Enschede",
"CountryCode": "NLD",
"District": "Overijssel",
"Population": 149544
}, {
"ID": 16,
"Name": "Haarlem",
"CountryCode": "NLD",
"District": "Noord-Holland",
"Population": 148772
}, {
"ID": 17,
"Name": "Almere",
"CountryCode": "NLD",
"District": "Flevoland",
"Population": 142465
}, {
"ID": 18,
"Name": "Arnhem",
"CountryCode": "NLD",
"District": "Gelderland",
"Population": 138020
}, {
"ID": 19,
"Name": "Zaanstad",
"CountryCode": "NLD",
"District": "Noord-Holland",
"Population": 135621
}, {
"ID": 20,
"Name": "´s-Hertogenbosch",
"CountryCode": "NLD",
"District": "Noord-Brabant",
"Population": 129170
}, {
"ID": 21,
"Name": "Amersfoort",
"CountryCode": "NLD",
"District": "Utrecht",
"Population": 126270
}, {
"ID": 22,
"Name": "Maastricht",
"CountryCode": "NLD",
"District": "Limburg",
"Population": 122087
}, {
"ID": 23,
"Name": "Dordrecht",
"CountryCode": "NLD",
"District": "Zuid-Holland",
"Population": 119811
}, {
"ID": 24,
"Name": "Leiden",
"CountryCode": "NLD",
"District": "Zuid-Holland",
"Population": 117196
}, {
"ID": 25,
"Name": "Haarlemmermeer",
"CountryCode": "NLD",
"District": "Noord-Holland",
"Population": 110722
}]
}

155
docs/assets/City1.json Normal file
View File

@ -0,0 +1,155 @@
{
"total_rows": "80",
"data" : [{
"ID": 26,
"Name": "Zoetermeer",
"CountryCode": "NLD",
"District": "Zuid-Holland",
"Population": 110214
}, {
"ID": 27,
"Name": "Emmen",
"CountryCode": "NLD",
"District": "Drenthe",
"Population": 105853
}, {
"ID": 28,
"Name": "Zwolle",
"CountryCode": "NLD",
"District": "Overijssel",
"Population": 105819
}, {
"ID": 29,
"Name": "Ede",
"CountryCode": "NLD",
"District": "Gelderland",
"Population": 101574
}, {
"ID": 30,
"Name": "Delft",
"CountryCode": "NLD",
"District": "Zuid-Holland",
"Population": 95268
}, {
"ID": 31,
"Name": "Heerlen",
"CountryCode": "NLD",
"District": "Limburg",
"Population": 95052
}, {
"ID": 32,
"Name": "Alkmaar",
"CountryCode": "NLD",
"District": "Noord-Holland",
"Population": 92713
}, {
"ID": 33,
"Name": "Willemstad",
"CountryCode": "ANT",
"District": "Curaçao",
"Population": 2345
}, {
"ID": 34,
"Name": "Tirana",
"CountryCode": "ALB",
"District": "Tirana",
"Population": 270000
}, {
"ID": 35,
"Name": "Alger",
"CountryCode": "DZA",
"District": "Alger",
"Population": 2168000
}, {
"ID": 36,
"Name": "Oran",
"CountryCode": "DZA",
"District": "Oran",
"Population": 609823
}, {
"ID": 37,
"Name": "Constantine",
"CountryCode": "DZA",
"District": "Constantine",
"Population": 443727
}, {
"ID": 38,
"Name": "Annaba",
"CountryCode": "DZA",
"District": "Annaba",
"Population": 222518
}, {
"ID": 39,
"Name": "Batna",
"CountryCode": "DZA",
"District": "Batna",
"Population": 183377
}, {
"ID": 40,
"Name": "Sétif",
"CountryCode": "DZA",
"District": "Sétif",
"Population": 179055
}, {
"ID": 41,
"Name": "Sidi Bel Abbès",
"CountryCode": "DZA",
"District": "Sidi Bel Abbès",
"Population": 153106
}, {
"ID": 42,
"Name": "Skikda",
"CountryCode": "DZA",
"District": "Skikda",
"Population": 128747
}, {
"ID": 43,
"Name": "Biskra",
"CountryCode": "DZA",
"District": "Biskra",
"Population": 128281
}, {
"ID": 44,
"Name": "Blida (el-Boulaida)",
"CountryCode": "DZA",
"District": "Blida",
"Population": 127284
}, {
"ID": 45,
"Name": "Béjaïa",
"CountryCode": "DZA",
"District": "Béjaïa",
"Population": 117162
}, {
"ID": 46,
"Name": "Mostaganem",
"CountryCode": "DZA",
"District": "Mostaganem",
"Population": 115212
}, {
"ID": 47,
"Name": "Tébessa",
"CountryCode": "DZA",
"District": "Tébessa",
"Population": 112007
}, {
"ID": 48,
"Name": "Tlemcen (Tilimsen)",
"CountryCode": "DZA",
"District": "Tlemcen",
"Population": 110242
}, {
"ID": 49,
"Name": "Béchar",
"CountryCode": "DZA",
"District": "Béchar",
"Population": 107311
}, {
"ID": 50,
"Name": "Tiaret",
"CountryCode": "DZA",
"District": "Tiaret",
"Population": 100118
}]
}

155
docs/assets/City2.json Normal file
View File

@ -0,0 +1,155 @@
{
"total_rows": "80",
"data" : [{
"ID": 51,
"Name": "Ech-Chleff (el-Asnam)",
"CountryCode": "DZA",
"District": "Chlef",
"Population": 96794
}, {
"ID": 52,
"Name": "Ghardaïa",
"CountryCode": "DZA",
"District": "Ghardaïa",
"Population": 89415
}, {
"ID": 53,
"Name": "Tafuna",
"CountryCode": "ASM",
"District": "Tutuila",
"Population": 5200
}, {
"ID": 54,
"Name": "Fagatogo",
"CountryCode": "ASM",
"District": "Tutuila",
"Population": 2323
}, {
"ID": 55,
"Name": "Andorra la Vella",
"CountryCode": "AND",
"District": "Andorra la Vella",
"Population": 21189
}, {
"ID": 56,
"Name": "Luanda",
"CountryCode": "AGO",
"District": "Luanda",
"Population": 2022000
}, {
"ID": 57,
"Name": "Huambo",
"CountryCode": "AGO",
"District": "Huambo",
"Population": 163100
}, {
"ID": 58,
"Name": "Lobito",
"CountryCode": "AGO",
"District": "Benguela",
"Population": 130000
}, {
"ID": 59,
"Name": "Benguela",
"CountryCode": "AGO",
"District": "Benguela",
"Population": 128300
}, {
"ID": 60,
"Name": "Namibe",
"CountryCode": "AGO",
"District": "Namibe",
"Population": 118200
}, {
"ID": 61,
"Name": "South Hill",
"CountryCode": "AIA",
"District": "",
"Population": 961
}, {
"ID": 62,
"Name": "The Valley",
"CountryCode": "AIA",
"District": "",
"Population": 595
}, {
"ID": 63,
"Name": "Saint John´s",
"CountryCode": "ATG",
"District": "St John",
"Population": 24000
}, {
"ID": 64,
"Name": "Dubai",
"CountryCode": "ARE",
"District": "Dubai",
"Population": 669181
}, {
"ID": 65,
"Name": "Abu Dhabi",
"CountryCode": "ARE",
"District": "Abu Dhabi",
"Population": 398695
}, {
"ID": 66,
"Name": "Sharja",
"CountryCode": "ARE",
"District": "Sharja",
"Population": 320095
}, {
"ID": 67,
"Name": "al-Ayn",
"CountryCode": "ARE",
"District": "Abu Dhabi",
"Population": 225970
}, {
"ID": 68,
"Name": "Ajman",
"CountryCode": "ARE",
"District": "Ajman",
"Population": 114395
}, {
"ID": 69,
"Name": "Buenos Aires",
"CountryCode": "ARG",
"District": "Distrito Federal",
"Population": 2982146
}, {
"ID": 70,
"Name": "La Matanza",
"CountryCode": "ARG",
"District": "Buenos Aires",
"Population": 1266461
}, {
"ID": 71,
"Name": "Córdoba",
"CountryCode": "ARG",
"District": "Córdoba",
"Population": 1157507
}, {
"ID": 72,
"Name": "Rosario",
"CountryCode": "ARG",
"District": "Santa Fé",
"Population": 907718
}, {
"ID": 73,
"Name": "Lomas de Zamora",
"CountryCode": "ARG",
"District": "Buenos Aires",
"Population": 622013
}, {
"ID": 74,
"Name": "Quilmes",
"CountryCode": "ARG",
"District": "Buenos Aires",
"Population": 559249
}, {
"ID": 75,
"Name": "Almirante Brown",
"CountryCode": "ARG",
"District": "Buenos Aires",
"Population": 538918
}]
}

35
docs/assets/City3.json Normal file
View File

@ -0,0 +1,35 @@
{
"total_rows": "80",
"data" : [{
"ID": 76,
"Name": "La Plata",
"CountryCode": "ARG",
"District": "Buenos Aires",
"Population": 521936
}, {
"ID": 77,
"Name": "Mar del Plata",
"CountryCode": "ARG",
"District": "Buenos Aires",
"Population": 512880
}, {
"ID": 78,
"Name": "San Miguel de Tucumán",
"CountryCode": "ARG",
"District": "Tucumán",
"Population": 470809
}, {
"ID": 79,
"Name": "Lanús",
"CountryCode": "ARG",
"District": "Buenos Aires",
"Population": 469735
}, {
"ID": 80,
"Name": "Merlo",
"CountryCode": "ARG",
"District": "Buenos Aires",
"Population": 463846
}]
}

View File

@ -0,0 +1,250 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>jQuery plugin: Tablesorter 2.0 - Pager plugin - Ajax</title>
<!-- jQuery -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<!-- Demo stuff -->
<link rel="stylesheet" href="css/jq.css">
<script src="js/chili/jquery.chili-2.2.js"></script>
<script src="js/chili/recipes.js"></script>
<script src="js/docs.js"></script>
<!-- Tablesorter: required -->
<link rel="stylesheet" href="../css/blue/style.css">
<script src="../js/jquery.tablesorter.js"></script>
<!-- Tablesorter: optional -->
<link rel="stylesheet" href="../addons/pager/jquery.tablesorter.pager.css">
<script src="../addons/pager/jquery.tablesorter.pager.js"></script>
<style id="css">/*** css used when "updateArrows" option is true ***/
/* the pager itself gets a disabled class when the number of rows is less than the size */
.pager.disabled {
display: none;
}
/* hide or fade out pager arrows when the first or last row is visible */
.pager img.disabled {
/* visibility: hidden */
opacity: 0.5;
filter: alpha(opacity=50);
}</style>
<script id="js">$(function(){
// Initialize tablesorter
// ***********************
$("table")
.tablesorter({
widthFixed: true,
sortLocaleCompare: true, // needed for accented characters in the data
widgets: ['zebra']
})
// initialize the pager plugin
// ****************************
.tablesorterPager({
// **********************************
// Description of ALL pager options
// **********************************
// target the pager markup - see the HTML block below
container: $(".pager"),
// use this url format "http:/mydatabase.com?page={page}&size={size}"
ajaxUrl : 'assets/City{page}.json',
// process ajax so that the data object is returned along with the total number of rows
// example: { "data" : [{ "ID": 1, "Name": "Foo", "Last": "Bar" }], "total_rows" : 100 }
ajaxProcessing: function(ajax){
if (ajax && ajax.hasOwnProperty('data')) {
// return [ "data", "total_rows" ];
return [ ajax.data, ajax.total_rows ];
}
},
// output string - default is '{page}/{totalPages}'; possible variables: {page}, {totalPages}, {startRow}, {endRow} and {totalRows}
output: '{startRow} to {endRow} ({totalRows})',
// apply disabled classname to the pager arrows when the rows at either extreme is visible - default is true
updateArrows: true,
// starting page of the pager (zero based index)
page: 0,
// Number of visible rows - default is 10
size: 25,
// if true, the table will remain the same height no matter how many records are displayed. The space is made up by an empty
// table row set to a height to compensate; default is false
fixedHeight: false,
// remove rows from the table to speed up the sort of large tables.
// setting this to false, only hides the non-visible rows; needed if you plan to add/remove rows with the pager enabled.
removeRows: false,
// css class names of pager arrows
cssNext: '.next', // next page arrow
cssPrev: '.prev', // previous page arrow
cssFirst: '.first', // go to first page arrow
cssLast: '.last', // go to last page arrow
cssPageDisplay: '.pagedisplay', // location of where the "output" is displayed
cssPageSize: '.pagesize', // page size selector - select dropdown that sets the "size" option
// class added to arrows when at the extremes (i.e. prev/first arrows are "disabled" when on the first page)
cssDisabled: 'disabled' // Note there is no period "." in front of this class name
});
});</script>
</head>
<body id="pager-demo">
<div id="banner">
<h1>table<em>sorter</em></h1>
<h2>Pager plugin - Ajax</h2>
<h3>Flexible client-side table sorting</h3>
<a href="index.html">Back to documentation</a>
</div>
<div id="main">
<p class="tip">
<em>NOTE!</em>:
<ul>
<li>This update to the pager plugin that interacts with a database via ajax was added in version 2.0.32 and can be applied to the original tablesorter.</li>
<li>The <code>ajaxUrl</code> and <code>ajaxProcessing</code> function are both required options for this interaction to work properly.</li>
<li>The <code>ajaxUrl</code> contains a replaceable string to sent the requested page (<code>{page}</code>) and block size (<code>{size}</code>).</li>
<li>The <code>ajaxProcessing</code> function must* return the data in the following format (Note that JSON is not allowed to include comments):
<pre class="js"><code>{
"data" : [
{ "header column 1": "r1c1 text", "header column 2": "r1c2 text", ... }, // row 1 of tbody (r1c1 = row 1, column 1)
{ "header column 1": "r2c1 text", "header column 2": "r2c2 text", ... }, // row 2 of tbody
...
{ "header column 1": "rNc1 text", "header column 2": "rNc2 text", ... }, // row N of tbody
],
"total_rows" : 100 // total # rows contained in the database
} </code></pre></li>
<li>The table header and footer text will be updated to match the JSON "header column #" text; but there is an issue with the table rendering improperly if the number of columns in the HTML and the number of columns in the JSON don't match.</li>
<li>Limitations of this demo:
<ul>
<li>This demo will not work in Chrome due to restrictions with browser and desktop interaction.</li>
<li>The record size is limited to 25 records because this demo is not interacting with an actual database, but with four JSON files containing 25 records each.</li>
</ul>
</li>
</ul>
<p class="small">* If you have a different JSON format and need help with the processing code, please ask the question on <a href="http://stackoverflow.com">StackOverflow</a> or message me directly (gmail; wowmotty). Please don't open an issue for help with code.</p>
</p>
<h1>Demo</h1>
<br>
<div class="pager">
<img src="../addons/pager/icons/first.png" class="first"/>
<img src="../addons/pager/icons/prev.png" class="prev"/>
<span class="pagedisplay"></span> <!-- this can be any element, including an input -->
<img src="../addons/pager/icons/next.png" class="next"/>
<img src="../addons/pager/icons/last.png" class="last"/>
<select class="pagesize">
<option value="25">25</option>
</select>
</div>
<table class="tablesorter">
<thead>
<tr>
<th>1</th>
<th>2</th>
<th>3</th>
<th>4</th>
<th>5</th>
</tr>
</thead>
<tfoot>
<tr>
<th>1</th>
<th>2</th>
<th>3</th>
<th>4</th>
<th>5</th>
</tr>
</tfoot>
<tbody>
</tbody>
</table>
<div class="pager">
<img src="../addons/pager/icons/first.png" class="first"/>
<img src="../addons/pager/icons/prev.png" class="prev"/>
<span class="pagedisplay"></span> <!-- this can be any element, including an input -->
<img src="../addons/pager/icons/next.png" class="next"/>
<img src="../addons/pager/icons/last.png" class="last"/>
<select class="pagesize">
<option value="25">25</option>
</select>
</div>
<h1>Javascript</h1>
<div id="javascript">
<pre class="js"></pre>
</div>
<h1>CSS</h1>
<div id="css">
<pre class="css"></pre>
</div>
<h1>HTML</h1>
<div id="html">
<pre class="html">&lt;!-- pager --&gt;
&lt;div id=&quot;pager&quot; class=&quot;pager&quot;&gt;
&lt;form&gt;
&lt;img src=&quot;first.png&quot; class=&quot;first&quot;/&gt;
&lt;img src=&quot;prev.png&quot; class=&quot;prev&quot;/&gt;
&lt;span class=&quot;pagedisplay&quot;&gt;&lt;/span&gt; &lt;!-- this can be any element, including an input --&gt;
&lt;img src=&quot;next.png&quot; class=&quot;next&quot;/&gt;
&lt;img src=&quot;last.png&quot; class=&quot;last&quot;/&gt;
&lt;select class=&quot;pagesize&quot;&gt;
&lt;option selected=&quot;selected&quot; value=&quot;25&quot;&gt;25&lt;/option&gt;
&lt;/select&gt;
&lt;/form&gt;
&lt;/div&gt;
&lt;table class=&quot;tablesorter&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;1&lt;/th&gt; &lt;!-- thead text will be updated from the JSON; make sure the number of columns matches the JSON data --&gt;
&lt;th&gt;2&lt;/th&gt;
&lt;th&gt;3&lt;/th&gt;
&lt;th&gt;4&lt;/th&gt;
&lt;th&gt;5&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tfoot&gt;
&lt;tr&gt;
&lt;th&gt;1&lt;/th&gt; &lt;!-- tfoot text will be updated at the same time as the thead --&gt;
&lt;th&gt;2&lt;/th&gt;
&lt;th&gt;3&lt;/th&gt;
&lt;th&gt;4&lt;/th&gt;
&lt;th&gt;5&lt;/th&gt;
&lt;/tr&gt;
&lt;/tfoot&gt;
&lt;tbody&gt; &lt;!-- tbody will be loaded via JSON --&gt;
&lt;/tbody&gt;
&lt;/table&gt;</pre>
</div>
<div class="next-up">
<hr />
Next up: <a href="example-empty-table.html">Initializing tablesorter on a empty table &rsaquo;&rsaquo;</a>
</div>
</div>
</body>
</html>

View File

@ -18,15 +18,16 @@
<script src="../js/jquery.tablesorter.js"></script>
<!-- Tablesorter: optional -->
<link rel="stylesheet" href="../addons/pager/jquery.tablesorter.pager.css">
<script src="../addons/pager/jquery.tablesorter.pager.js"></script>
<style id="css">/*** css used when "updateArrows" option is true ***/
/* the pager itself gets a disabled class when the number of rows is less than the size */
#pager.disabled {
.pager.disabled {
display: none;
}
/* hide or fade out pager arrows when the first or last row is visible */
#pager img.disabled {
.pager img.disabled {
/* visibility: hidden */
opacity: 0.5;
filter: alpha(opacity=50);
@ -40,7 +41,19 @@
var pagerOptions = {
// target the pager markup - see the HTML block below
container: $("#pager"),
container: $(".pager"),
// use this url format "http:/mydatabase.com?page={page}&size={size}"
ajaxUrl : null,
// process ajax so that the data object is returned along with the total number of rows
// example: { "data" : [{ "ID": 1, "Name": "Foo", "Last": "Bar" }], "total_rows" : 100 }
ajaxProcessing: function(ajax){
if (ajax && ajax.hasOwnProperty('data')) {
// return [ "data", "total_rows" ];
return [ ajax.data, ajax.total_rows ];
}
},
// output string - default is '{page}/{totalPages}'; possible variables: {page}, {totalPages}, {startRow}, {endRow} and {totalRows}
output: '{startRow} to {endRow} ({totalRows})',
@ -54,12 +67,9 @@
// Number of visible rows - default is 10
size: 10,
// if true, moves the pager below the table at a fixed position; so if only 2 rows showing, the pager remains in the same place
// default is true
positionFixed: false,
// offset added to the pager top, but only when "positionFixed" is true
offset: 0,
// if true, the table will remain the same height no matter how many records are displayed. The space is made up by an empty
// table row set to a height to compensate; default is false
fixedHeight: true,
// remove rows from the table to speed up the sort of large tables.
// setting this to false, only hides the non-visible rows; needed if you plan to add/remove rows with the pager enabled.
@ -126,28 +136,26 @@
t.trigger('enable.pager');
});
// Destroy pager
// Destroy pager / Restore pager
// **************
$('button:contains(Destroy)').click(function(){
// Exterminate, annhilate, destroy! http://www.youtube.com/watch?v=LOqn8FxuyFs
$('table').trigger('destroy.pager');
// fancy disable/enable buttons - not really needed
$('button:contains(Restore)').removeAttr('disabled');
$(this).attr('disabled', true);
var $t = $(this);
if (/Destroy/.test( $t.text() )){
$('table').trigger('destroy.pager');
$t.text('Restore Pager');
} else {
$('table').tablesorterPager(pagerOptions);
$t.text('Destroy Pager');
}
});
// Restore pager
// Disable / Enable
// **************
$('button:contains(Restore)').click(function(){
// initialize the pager
$('table').tablesorterPager(pagerOptions);
// fancy disable/enable buttons - not really needed
$(this).attr('disabled', true);
$('button:contains(Destroy)').removeAttr('disabled');
$('button:contains(Disable)').click(function(){
var mode = /Disable/.test( $(this).text() );
$('table').trigger( (mode ? 'disable' : 'enable') + '.pager');
$(this).text( (mode ? 'Enable' : 'Disable') + 'Pager');
});
});</script>
@ -165,14 +173,8 @@
<p class="tip">
<em>NOTE!</em> The following are not part of the original plugin:
<ul>
<li>This pager plugin can be applied to the original tablesorter, but there is one exception - setting the `removeRows` option to false will break the sort.</li>
<li>Added "pagerChange" and "pagerComplete" events in version 2.0.7.</li>
<li>Updated pager functions, removed "separator" option, and added output string formatting (e.g. "1 to 10 (50)") to version 2.0.9.</li>
<li>Added "cssDisabled" and "pagerArrows" options which controls the look of the pager and arrows when the pager is on the first or last page. Added in version 2.0.9.</li>
<li>Added a new "addRows" method to allow adding new rows while the pager is applied to a table. Using "update" would remove all non-visible rows. New in version 2.0.16.</li>
<li>New "destroy.pager" method will reveal the entire table, remove the pager functionality, and hide the actual pager. Added in version 2.0.16.</li>
<li>Reduced the number of rows in the demo from 1022 to 50, so you don't have to scroll forever (when the pager is destroyed) to see the code below the table (v2.0.16).</li>
<li>New "disable.pager" and "enable.pager" methods added to make it easier to add or delete rows from the table. Added in version 2.0.21.2.</li>
<li>This pager plugin can be applied to the original tablesorter, but there is one exception - setting the <code class="hilight">removeRows</code> option to false will break the sort.</li>
<li>There have been lots of changes made in version 2.1, please check out the <a href="#change-log">change log</a> below.</li>
</ul>
</p>
@ -185,22 +187,20 @@
<h1>Demo</h1>
<br>
<button>Add Rows</button> <button>Destroy Pager</button> <button disabled>Restore Pager</button>
<button>Add Rows</button> <button>Disable Pager</button> <button>Destroy Pager</button>
<br><br>
<div id="pager" class="pager">
<form>
<img src="../addons/pager/icons/first.png" class="first"/>
<img src="../addons/pager/icons/prev.png" class="prev"/>
<span class="pagedisplay"></span> <!-- this can be any element, including an input -->
<img src="../addons/pager/icons/next.png" class="next"/>
<img src="../addons/pager/icons/last.png" class="last"/>
<select class="pagesize">
<option selected="selected" value="10">10</option>
<option value="20">20</option>
<option value="30">30</option>
<option value="40">40</option>
</select>
</form>
<div class="pager">
<img src="../addons/pager/icons/first.png" class="first"/>
<img src="../addons/pager/icons/prev.png" class="prev"/>
<span class="pagedisplay"></span> <!-- this can be any element, including an input -->
<img src="../addons/pager/icons/next.png" class="next"/>
<img src="../addons/pager/icons/last.png" class="last"/>
<select class="pagesize">
<option selected="selected" value="10">10</option>
<option value="20">20</option>
<option value="30">30</option>
<option value="40">40</option>
</select>
</div>
<table class="tablesorter">
@ -480,6 +480,20 @@
</tbody>
</table>
<div class="pager">
<img src="../addons/pager/icons/first.png" class="first"/>
<img src="../addons/pager/icons/prev.png" class="prev"/>
<span class="pagedisplay"></span> <!-- this can be any element, including an input -->
<img src="../addons/pager/icons/next.png" class="next"/>
<img src="../addons/pager/icons/last.png" class="last"/>
<select class="pagesize">
<option selected="selected" value="10">10</option>
<option value="20">20</option>
<option value="30">30</option>
<option value="40">40</option>
</select>
</div>
<h1>Javascript</h1>
<div id="javascript">
<pre class="js"></pre>
@ -515,9 +529,72 @@
</div>
<a id="change-log"></a>
<h1>Pager Change Log</h1>
<h4>Version 2.1</h4>
<ul>
<li>Ajax:
<ul>
<li>The pager plugin will now interact with a database via JSON. See <a href="example-pager-ajax.html">demo</a> here.</li>
<li>Added <code class="hilight">ajaxUrl</code> option which contains the variables <code class="hilight">{page}</code> and <code class="hilight">{size}</code> which will be replaced by the plugin to obtain that data.
<pre class="js"><code class="hilight">ajaxUrl : "http:/mydatabase.com?page={page}&size={size}"</code></pre>
</li>
<li>Another option named <code class="hilight">ajaxProcessing</code> was included to process the data before returning it to the pager plugin. Basically the JSON needs to contain the data to match the example below. An additional required variable is the total number of records or rows needs to be returned.
<pre class="js"><code class="hilight">// process ajax so that the data object is returned along with the total number of rows
// example: { "data" : [{ "ID": 1, "Name": "Foo", "Last": "Bar" }], "total_rows" : 100 }
ajaxProcessing: function(ajax){
if (ajax && ajax.hasOwnProperty('data')) {
// return [ "data", "total_rows" ];
return [ ajax.data, ajax.total_rows ];
}
}</code></pre>
</li>
<li>I tried to make the plugin interact with a database as flexible as possible, but I'm sure I haven't covered every situation. So any and all feedback is welcome!</li>
<li>Also, much thanks to <a href="https://github.com/kachar">kachar</a> for the <a href="https://github.com/Mottie/tablesorter/issues/31">enhancement request</a> and willingness to help test it!</li>
</ul>
</li>
<li>Removed <code class="hilight">positionFixed</code> and <code class="hilight">offset</code> options.</li>
<li>Added <code class="hilight">fixedHeight</code> option which replaces the <code class="hilight">positionFixed</code> and <code class="hilight">offset</code> options.
<ul>
<li>If true, it should maintain the height of the table, even when viewing fewer than the set number of records (go to the last page to see this in action).</li>
<li>It works by adding an empty row to make up the differences in height.</li>
<li>There were some <strong>issues</strong> of the height being incorrect when this option is true. The problems occurred if you add/remove rows + change pager size, or just destroy/enable the pager. I think I fixed it, but if you should find a problem, please <a href="https://github.com/Mottie/tablesorter/issues">report the issue</a> and steps on how to duplicate it.</li>
</ul>
</li>
<li>The pager <code class="hilight">container</code> option will now accept class names. So you can add multiple container blocks to control the pager, just as this page now has two, one above and one below.</li>
<li>The pager now adds all of its options to the table configuration options within an object named "pager". Basically what this means is that instead of add all of the pager options to be mixed in with the tablesorter options, the pager options have been isolated and can be found by typing this into the browser console: <code class="hilight">$('table')[0].config.pager</code>.</li>
</ul>
<h4>Version 2.0.21.2</h4>
<ul>
<li>Added <code class="hilight">"disable.pager"</code> and <code class="hilight">"enable.pager"</code> methods added to make it easier to add or delete rows from the table.</li>
</ul>
<h4>Version 2.0.16</h4>
<ul>
<li>Reduced the number of rows in the demo from 1022 to 50, so you don't have to scroll forever (when the pager is destroyed) to see the code below the table.</li>
<li>Added <code class="hilight">"destroy.pager"</code> method will reveal the entire table, remove the pager functionality, and hide the actual pager.</li>
<li>Added a new <code class="hilight">addRows</code> method to allow adding new rows while the pager is applied to a table. Using <code class="hilight">"update"</code> would remove all non-visible rows.</li>
</ul>
<h4>Version 2.0.9</h4>
<ul>
<li>Added <code class="hilight">cssDisabled</code> and <code class="hilight">pagerArrows</code> options which controls the look of the pager and arrows when the pager is on the first or last page.</li>
<li>Updated pager functions, removed "separator" option, and added output string formatting (e.g. "1 to 10 (50)").</li>
</ul>
<h4>Version 2.0.7</h4>
<ul>
<li>Added <code class="hilight">"pagerChange"</code> and <code class="hilight">"pagerComplete"</code> events in version 2.0.7.</li>
</ul>
<div class="next-up">
<hr />
Next up: <a href="example-empty-table.html">Initializing tablesorter on a empty table &rsaquo;&rsaquo;</a>
Next up: <a href="example-pager-ajax.html">Pager plugin - Ajax &rsaquo;&rsaquo;</a>
</div>
</div>