jquery-tablesorter 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. data/README.markdown +3 -1
  2. data/lib/jquery-tablesorter/version.rb +1 -1
  3. data/vendor/assets/images/jquery-tablesorter/black-asc.gif +0 -0
  4. data/vendor/assets/images/jquery-tablesorter/black-desc.gif +0 -0
  5. data/vendor/assets/images/jquery-tablesorter/dropbox-asc-hovered.png +0 -0
  6. data/vendor/assets/images/jquery-tablesorter/dropbox-asc.png +0 -0
  7. data/vendor/assets/images/jquery-tablesorter/dropbox-desc-hovered.png +0 -0
  8. data/vendor/assets/images/jquery-tablesorter/dropbox-desc.png +0 -0
  9. data/vendor/assets/images/jquery-tablesorter/green-asc.gif +0 -0
  10. data/vendor/assets/images/jquery-tablesorter/green-desc.gif +0 -0
  11. data/vendor/assets/images/jquery-tablesorter/green-header.gif +0 -0
  12. data/vendor/assets/images/jquery-tablesorter/green-unsorted.gif +0 -0
  13. data/vendor/assets/images/jquery-tablesorter/ice-asc.gif +0 -0
  14. data/vendor/assets/images/jquery-tablesorter/ice-desc.gif +0 -0
  15. data/vendor/assets/images/jquery-tablesorter/ice-unsorted.gif +0 -0
  16. data/vendor/assets/images/jquery-tablesorter/white-asc.gif +0 -0
  17. data/vendor/assets/images/jquery-tablesorter/white-desc.gif +0 -0
  18. data/vendor/assets/javascripts/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.js +507 -507
  19. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.js +72 -63
  20. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.min.js +2 -3
  21. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets.js +17 -12
  22. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets.min.js +8 -8
  23. data/vendor/assets/stylesheets/jquery-tablesorter/theme.black-ice.css +12 -8
  24. data/vendor/assets/stylesheets/jquery-tablesorter/theme.blue.css +14 -10
  25. data/vendor/assets/stylesheets/jquery-tablesorter/theme.bootstrap.css +10 -4
  26. data/vendor/assets/stylesheets/jquery-tablesorter/theme.dark.css +12 -8
  27. data/vendor/assets/stylesheets/jquery-tablesorter/theme.default.css +9 -6
  28. data/vendor/assets/stylesheets/jquery-tablesorter/theme.dropbox.css +29 -18
  29. data/vendor/assets/stylesheets/jquery-tablesorter/theme.green.css +15 -6
  30. data/vendor/assets/stylesheets/jquery-tablesorter/theme.grey.css +12 -10
  31. data/vendor/assets/stylesheets/jquery-tablesorter/theme.ice.css +20 -10
  32. data/vendor/assets/stylesheets/jquery-tablesorter/theme.jui.css +7 -1
  33. metadata +17 -15
@@ -1,8 +1,10 @@
1
1
  # jQuery Table Sorter plugin for Rails
2
2
 
3
+ [![Still Maintained](http://stillmaintained.com/linjunpop/jquery-tablesorter-rails.png)](http://stillmaintained.com/linjunpop/jquery-tablesorter-rails)
4
+
3
5
  Simple integration of jquery-tablesorter into the asset pipeline.
4
6
 
5
- Current tablesorter version: 2.4.6 (10/25/2012), [documentation]
7
+ Current tablesorter version: 2.5.2 (11/27/2012), [documentation]
6
8
 
7
9
  Any issue associate with the js/css files, please report to [Mottie's fork].
8
10
 
@@ -1,3 +1,3 @@
1
1
  module JqueryTablesorter
2
- VERSION = "1.1.0"
2
+ VERSION = "1.2.0"
3
3
  end
@@ -1,508 +1,508 @@
1
- /*!
2
- * tablesorter pager plugin
3
- * updated 10/25/2012
4
- */
5
- /*jshint browser:true, jquery:true */
6
- ;(function($) {
7
- "use strict";
8
- $.extend({tablesorterPager: new function() {
9
-
10
- this.defaults = {
11
- // target the pager markup
12
- container: null,
13
-
14
- // use this format: "http://mydatabase.com?page={page}&size={size}&{sortList:col}"
15
- // where {page} is replaced by the page number and {size} is replaced by the number of records to show
16
- // {sortList:col} adds the sortList to the url into a "col" array.
17
- // So a sortList = [[2,0],[3,0]] becomes "&col[2]=0&col[3]=0" in the url
18
- ajaxUrl: null,
19
-
20
- // process ajax so that the following information is returned:
21
- // [ total_rows (number), rows (array of arrays), headers (array; optional) ]
22
- // example:
23
- // [
24
- // 100, // total rows
25
- // [
26
- // [ "row1cell1", "row1cell2", ... "row1cellN" ],
27
- // [ "row2cell1", "row2cell2", ... "row2cellN" ],
28
- // ...
29
- // [ "rowNcell1", "rowNcell2", ... "rowNcellN" ]
30
- // ],
31
- // [ "header1", "header2", ... "headerN" ] // optional
32
- // ]
33
- ajaxProcessing: function(ajax){ return [ 0, [], null ]; },
34
-
35
- // output default: '{page}/{totalPages}'
36
- // possible variables: {page}, {totalPages}, {filteredPages}, {startRow}, {endRow}, {filteredRows} and {totalRows}
37
- output: '{startRow} to {endRow} of {totalRows} rows', // '{page}/{totalPages}'
38
-
39
- // apply disabled classname to the pager arrows when the rows at either extreme is visible
40
- updateArrows: true,
41
-
42
- // starting page of the pager (zero based index)
43
- page: 0,
44
-
45
- // Number of visible rows
46
- size: 10,
47
-
48
- // if true, the table will remain the same height no matter how many records are displayed. The space is made up by an empty
49
- // table row set to a height to compensate; default is false
50
- fixedHeight: false,
51
-
52
- // remove rows from the table to speed up the sort of large tables.
53
- // setting this to false, only hides the non-visible rows; needed if you plan to add/remove rows with the pager enabled.
54
- removeRows: false, // removing rows in larger tables speeds up the sort
55
-
56
- // css class names of pager arrows
57
- cssFirst: '.first', // go to first page arrow
58
- cssPrev: '.prev', // previous page arrow
59
- cssNext: '.next', // next page arrow
60
- cssLast: '.last', // go to last page arrow
61
- cssGoto: '.gotoPage', // go to page selector - select dropdown that sets the current page
62
- cssPageDisplay: '.pagedisplay', // location of where the "output" is displayed
63
- cssPageSize: '.pagesize', // page size selector - select dropdown that sets the "size" option
64
-
65
- // class added to arrows when at the extremes (i.e. prev/first arrows are "disabled" when on the first page)
66
- cssDisabled: 'disabled', // Note there is no period "." in front of this class name
67
-
68
- // stuff not set by the user
69
- totalRows: 0,
70
- totalPages: 0,
71
- filteredRows: 0,
72
- filteredPages: 0
73
-
74
- };
75
-
76
- var $this = this,
77
-
78
- // hide arrows at extremes
79
- pagerArrows = function(c, disable) {
80
- var a = 'addClass',
81
- r = 'removeClass',
82
- d = c.cssDisabled,
83
- dis = !!disable,
84
- // tr = Math.min( c.totalRows, c.filteredRows ),
85
- tp = Math.min( c.totalPages, c.filteredPages );
86
- if ( c.updateArrows ) {
87
- $(c.cssFirst + ',' + c.cssPrev, c.container)[ ( dis || c.page === 0 ) ? a : r ](d);
88
- $(c.cssNext + ',' + c.cssLast, c.container)[ ( dis || c.page === tp - 1 ) ? a : r ](d);
89
- }
90
- },
91
-
92
- updatePageDisplay = function(table, c) {
93
- var i, p, s, t, out, f = $(table).hasClass('hasFilters');
94
- c.filteredRows = (f) ? $(table).find('tbody tr:not(.filtered)').length : c.totalRows;
95
- c.filteredPages = (f) ? Math.ceil( c.filteredRows / c.size ) : c.totalPages;
96
- if ( Math.min( c.totalPages, c.filteredPages ) > 0 ) {
97
- t = (c.size * c.page > c.filteredRows);
98
- c.startRow = (t) ? 1 : ( c.size * c.page ) + 1;
99
- c.page = (t) ? 0 : c.page;
100
- c.endRow = Math.min( c.filteredRows, c.totalRows, c.size * ( c.page + 1 ) );
101
- out = $(c.cssPageDisplay, c.container);
102
- // form the output string
103
- s = c.output.replace(/\{(page|filteredRows|filteredPages|totalPages|startRow|endRow|totalRows)\}/gi, function(m){
104
- return {
105
- '{page}' : c.page + 1,
106
- '{filteredRows}' : c.filteredRows,
107
- '{filteredPages}' : c.filteredPages,
108
- '{totalPages}' : c.totalPages,
109
- '{startRow}' : c.startRow,
110
- '{endRow}' : c.endRow,
111
- '{totalRows}' : c.totalRows
112
- }[m];
113
- });
114
- if (out[0]) {
115
- out[ (out[0].tagName === 'INPUT') ? 'val' : 'html' ](s);
116
- if ( $(c.cssGoto, c.container).length ) {
117
- t = '';
118
- p = Math.min( c.totalPages, c.filteredPages );
119
- for ( i = 1; i <= p; i++ ) {
120
- t += '<option>' + i + '</option>';
121
- }
122
- $(c.cssGoto, c.container).html(t).val(c.page + 1);
123
- }
124
- }
125
- }
126
- pagerArrows(c);
127
- if (c.initialized) { $(table).trigger('pagerComplete', c); }
128
- },
129
-
130
- fixHeight = function(table, c) {
131
- var d, h, $b = $(table.tBodies[0]);
132
- if (c.fixedHeight) {
133
- $b.find('tr.pagerSavedHeightSpacer').remove();
134
- h = $.data(table, 'pagerSavedHeight');
135
- if (h) {
136
- d = h - $b.height();
137
- if ( d > 5 && $.data(table, 'pagerLastSize') === c.size && $b.find('tr:visible').length < c.size ) {
138
- $b.append('<tr class="pagerSavedHeightSpacer remove-me" style="height:' + d + 'px;"></tr>');
139
- }
140
- }
141
- }
142
- },
143
-
144
- changeHeight = function(table, c) {
145
- var $b = $(table.tBodies[0]);
146
- $b.find('tr.pagerSavedHeightSpacer').remove();
147
- $.data(table, 'pagerSavedHeight', $b.height());
148
- fixHeight(table, c);
149
- $.data(table, 'pagerLastSize', c.size);
150
- },
151
-
152
- hideRows = function(table, c){
153
- if (!c.ajaxUrl) {
154
- var i,
155
- rows = $('tr:not(.' + table.config.cssChildRow + ')', table.tBodies),
156
- l = rows.length,
157
- s = ( c.page * c.size ),
158
- e = s + c.size,
159
- j = 0; // size counter
160
- for ( i = 0; i < l; i++ ){
161
- if (!/filtered/.test(rows[i].className)) {
162
- rows[i].style.display = ( j >= s && j < e ) ? '' : 'none';
163
- j++;
164
- }
165
- }
166
- }
167
- },
168
-
169
- hideRowsSetup = function(table, c){
170
- c.size = parseInt( $(c.cssPageSize, c.container).find('option[selected]').val(), 10 ) || c.size;
171
- $.data(table, 'pagerLastSize', c.size);
172
- pagerArrows(c);
173
- if ( !c.removeRows ) {
174
- hideRows(table, c);
175
- $(table).bind('sortEnd.pager filterEnd.pager', function(){
176
- hideRows(table, c);
177
- });
178
- }
179
- },
180
-
181
- renderAjax = function(data, table, c, exception){
182
- // process data
183
- if ( typeof(c.ajaxProcessing) === "function" ) {
184
- // ajaxProcessing result: [ total, rows, headers ]
185
- var i, j, hsh, $f, $sh,
186
- $t = $(table),
187
- tc = table.config,
188
- $b = $(table.tBodies).filter(':not(.' + tc.cssInfoBlock + ')'),
189
- hl = $t.find('thead th').length, tds = '',
190
- err = '<tr class="' + tc.selectorRemove + '"><td style="text-align: center;" colspan="' + hl + '">' +
191
- (exception ? exception.message + ' (' + exception.name + ')' : 'No rows found') + '</td></tr>',
192
- result = c.ajaxProcessing(data) || [ 0, [] ],
193
- d = result[1] || [],
194
- l = d.length,
195
- th = result[2];
196
- if ( l > 0 ) {
197
- for ( i = 0; i < l; i++ ) {
198
- tds += '<tr>';
199
- for ( j = 0; j < d[i].length; j++ ) {
200
- // build tbody cells
201
- tds += '<td>' + d[i][j] + '</td>';
202
- }
203
- tds += '</tr>';
204
- }
205
- }
206
- // only add new header text if the length matches
207
- if ( th && th.length === hl ) {
208
- hsh = $t.hasClass('hasStickyHeaders');
209
- $sh = $t.find('.' + ((tc.widgetOptions && tc.widgetOptions.stickyHeaders) || 'tablesorter-stickyheader'));
210
- $f = $t.find('tfoot tr:first').children();
211
- $t.find('th.' + tc.cssHeader).each(function(j){
212
- var $t = $(this), icn;
213
- // add new test within the first span it finds, or just in the header
214
- if ( $t.find('.' + tc.cssIcon).length ) {
215
- icn = $t.find('.' + tc.cssIcon).clone(true);
216
- $t.find('.tablesorter-header-inner').html( th[j] ).append(icn);
217
- if ( hsh && $sh.length ) {
218
- icn = $sh.find('th').eq(j).find('.' + tc.cssIcon).clone(true);
219
- $sh.find('th').eq(j).find('.tablesorter-header-inner').html( th[j] ).append(icn);
220
- }
221
- } else {
222
- $t.find('.tablesorter-header-inner').html( th[j] );
223
- $sh.find('th').eq(j).find('.tablesorter-header-inner').html( th[j] );
224
- }
225
- $f.eq(j).html( th[j] );
226
- });
227
- }
228
- if ( exception ) {
229
- // add error row to thead instead of tbody, or clicking on the header will result in a parser error
230
- $t.find('thead').append(err);
231
- } else {
232
- $b.html( tds ); // add tbody
233
- }
234
- c.temp.remove(); // remove loading icon
235
- $t.trigger('update');
236
- c.totalRows = result[0] || 0;
237
- c.totalPages = Math.ceil( c.totalRows / c.size );
238
- updatePageDisplay(table, c);
239
- fixHeight(table, c);
240
- if (c.initialized) { $t.trigger('pagerChange', c); }
241
- }
242
- if (!c.initialized) {
243
- c.initialized = true;
244
- $(table).trigger('pagerInitialized', c);
245
- }
246
- },
247
-
248
- getAjax = function(table, c){
249
- var $t = $(table),
250
- url = (c.ajaxUrl) ? c.ajaxUrl.replace(/\{page\}/g, c.page).replace(/\{size\}/g, c.size) : '',
251
- arry = [],
252
- sl = table.config.sortList,
253
- col = url.match(/\{sortList[\s+]?:[\s+]?(.*)\}/);
254
- if (col) {
255
- col = col[1];
256
- $.each(sl, function(i,v){
257
- arry.push(col + '[' + v[0] + ']=' + v[1]);
258
- });
259
- // if the arry is empty, just add the col parameter... "&{sortList:col}" becomes "&col"
260
- url = url.replace(/\{sortList[\s+]?:[\s+]?(.*)\}/g, arry.length ? arry.join('&') : col );
261
- }
262
- if ( url !== '' ) {
263
- // loading icon
264
- c.temp = $('<div/>', {
265
- 'class' : 'tablesorter-processing',
266
- width : $t.outerWidth(true),
267
- height: $t.outerHeight(true)
268
- });
269
- $t.before( c.temp );
270
- $(document).ajaxError(function(e, xhr, settings, exception) {
271
- renderAjax(null, table, c, exception);
272
- });
273
- $.getJSON(url, function(data) {
274
- renderAjax(data, table, c);
275
- });
276
- }
277
- },
278
-
279
- renderTable = function(table, rows, c) {
280
- var i, j, o,
281
- f = document.createDocumentFragment(),
282
- l = rows.length,
283
- s = ( c.page * c.size ),
284
- e = ( s + c.size );
285
- if ( l < 1 ) { return; } // empty table, abort!
286
- if (c.initialized) { $(table).trigger('pagerChange', c); }
287
- if ( !c.removeRows ) {
288
- hideRows(table, c);
289
- } else {
290
- if ( e > rows.length ) {
291
- e = rows.length;
292
- }
293
- $(table.tBodies[0]).addClass('tablesorter-hidden');
294
- $.tablesorter.clearTableBody(table);
295
- for ( i = s; i < e; i++ ) {
296
- o = rows[i];
297
- l = o.length;
298
- for ( j = 0; j < l; j++ ) {
299
- f.appendChild(o[j]);
300
- }
301
- }
302
- table.tBodies[0].appendChild(f);
303
- $(table.tBodies[0]).removeClass('tablesorter-hidden');
304
- }
305
- if ( c.page >= c.totalPages ) {
306
- moveToLastPage(table, c);
307
- }
308
- updatePageDisplay(table, c);
309
- if ( !c.isDisabled ) { fixHeight(table, c); }
310
- $(table).trigger('applyWidgets');
311
- },
312
-
313
- showAllRows = function(table, c){
314
- if ( c.ajax ) {
315
- pagerArrows(c, true);
316
- } else {
317
- c.isDisabled = true;
318
- $.data(table, 'pagerLastPage', c.page);
319
- $.data(table, 'pagerLastSize', c.size);
320
- c.page = 0;
321
- c.size = c.totalRows;
322
- c.totalPages = 1;
323
- $('tr.pagerSavedHeightSpacer', table.tBodies[0]).remove();
324
- renderTable(table, table.config.rowsCopy, c);
325
- }
326
- // disable size selector
327
- $(c.container).find(c.cssPageSize + ',' + c.cssGoto).each(function(){
328
- $(this).addClass(c.cssDisabled)[0].disabled = true;
329
- });
330
- },
331
-
332
- moveToPage = function(table, c) {
333
- if ( c.isDisabled ) { return; }
334
- var p = Math.min( c.totalPages, c.filteredPages );
335
- if ( c.page < 0 || c.page > ( p - 1 ) ) {
336
- c.page = 0;
337
- }
338
- $.data(table, 'pagerLastPage', c.page);
339
- if ( c.ajax ) {
340
- getAjax(table, c);
341
- } else {
342
- renderTable(table, table.config.rowsCopy, c);
343
- }
344
- if (c.initialized) { $(table).trigger('pageMoved', c); }
345
- },
346
-
347
- setPageSize = function(table, size, c) {
348
- c.size = size;
349
- $.data(table, 'pagerLastPage', c.page);
350
- $.data(table, 'pagerLastSize', c.size);
351
- c.totalPages = Math.ceil( c.totalRows / c.size );
352
- moveToPage(table, c);
353
- },
354
-
355
- moveToFirstPage = function(table, c) {
356
- c.page = 0;
357
- moveToPage(table, c);
358
- },
359
-
360
- moveToLastPage = function(table, c) {
361
- c.page = ( Math.min( c.totalPages, c.filteredPages ) - 1 );
362
- moveToPage(table, c);
363
- },
364
-
365
- moveToNextPage = function(table, c) {
366
- c.page++;
367
- if ( c.page >= ( Math.min( c.totalPages, c.filteredPages ) - 1 ) ) {
368
- c.page = ( Math.min( c.totalPages, c.filteredPages ) - 1 );
369
- }
370
- moveToPage(table, c);
371
- },
372
-
373
- moveToPrevPage = function(table, c) {
374
- c.page--;
375
- if ( c.page <= 0 ) {
376
- c.page = 0;
377
- }
378
- moveToPage(table, c);
379
- },
380
-
381
- destroyPager = function(table, c){
382
- showAllRows(table, c);
383
- $(c.container).hide(); // hide pager
384
- table.config.appender = null; // remove pager appender function
385
- $(table).unbind('destroy.pager sortEnd.pager filterEnd.pager enable.pager disable.pager');
386
- },
387
-
388
- enablePager = function(table, c, triggered){
389
- var p = $(c.cssPageSize, c.container).removeClass(c.cssDisabled).removeAttr('disabled');
390
- c.isDisabled = false;
391
- c.page = $.data(table, 'pagerLastPage') || c.page || 0;
392
- c.size = $.data(table, 'pagerLastSize') || parseInt(p.find('option[selected]').val(), 10) || c.size;
393
- p.val(c.size); // set page size
394
- c.totalPages = Math.ceil( Math.min( c.totalPages, c.filteredPages ) / c.size);
395
- if ( triggered ) {
396
- $(table).trigger('update');
397
- setPageSize(table, c.size, c);
398
- hideRowsSetup(table, c);
399
- fixHeight(table, c);
400
- }
401
- };
402
-
403
- $this.appender = function(table, rows) {
404
- var c = table.config.pager;
405
- if ( !c.ajax ) {
406
- table.config.rowsCopy = rows;
407
- c.totalRows = rows.length;
408
- c.size = $.data(table, 'pagerLastSize') || c.size;
409
- c.totalPages = Math.ceil(c.totalRows / c.size);
410
- renderTable(table, rows, c);
411
- }
412
- };
413
-
414
- $this.construct = function(settings) {
415
- return this.each(function() {
416
- var config = this.config,
417
- c = config.pager = $.extend( {}, $.tablesorterPager.defaults, settings ),
418
- table = this,
419
- $t = $(table),
420
- pager = $(c.container).addClass('tablesorter-pager').show(); // added in case the pager is reinitialized after being destroyed.
421
- config.appender = $this.appender;
422
- // clear initialized flag
423
- c.initialized = false;
424
- enablePager(table, c, false);
425
- if ( typeof(c.ajaxUrl) === 'string' ) {
426
- // ajax pager; interact with database
427
- c.ajax = true;
428
- getAjax(table, c);
429
- } else {
430
- c.ajax = false;
431
- // Regular pager; all rows stored in memory
432
- $(this).trigger("appendCache", true);
433
- hideRowsSetup(table, c);
434
- }
435
-
436
- // update pager after filter widget completes
437
- $(table)
438
- .unbind('filterEnd.pager updateComplete.pager ')
439
- .bind('filterEnd.pager updateComplete.pager', function() {
440
- c.page = 0;
441
- updatePageDisplay(table, c);
442
- moveToPage(table, c);
443
- changeHeight(table, c);
444
- });
445
-
446
- if ( $(c.cssGoto, pager).length ) {
447
- $(c.cssGoto, pager).bind('change', function(){
448
- c.page = $(this).val() - 1;
449
- moveToPage(table, c);
450
- });
451
- updatePageDisplay(table, c);
452
- }
453
- $(c.cssFirst,pager).unbind('click.pager').bind('click.pager', function() {
454
- if ( !$(this).hasClass(c.cssDisabled) ) { moveToFirstPage(table, c); }
455
- return false;
456
- });
457
- $(c.cssNext,pager).unbind('click.pager').bind('click.pager', function() {
458
- if ( !$(this).hasClass(c.cssDisabled) ) { moveToNextPage(table, c); }
459
- return false;
460
- });
461
- $(c.cssPrev,pager).unbind('click.pager').bind('click.pager', function() {
462
- if ( !$(this).hasClass(c.cssDisabled) ) { moveToPrevPage(table, c); }
463
- return false;
464
- });
465
- $(c.cssLast,pager).unbind('click.pager').bind('click.pager', function() {
466
- if ( !$(this).hasClass(c.cssDisabled) ) { moveToLastPage(table, c); }
467
- return false;
468
- });
469
- $(c.cssPageSize,pager).unbind('change.pager').bind('change.pager', function() {
470
- $(c.cssPageSize,pager).val( $(this).val() ); // in case there are more than one pagers
471
- if ( !$(this).hasClass(c.cssDisabled) ) {
472
- setPageSize(table, parseInt( $(this).val(), 10 ), c);
473
- changeHeight(table, c);
474
- }
475
- return false;
476
- });
477
-
478
- $t
479
- .unbind('disable.pager enable.pager destroy.pager update.pager')
480
- .bind('disable.pager', function(){
481
- showAllRows(table, c);
482
- })
483
- .bind('enable.pager', function(){
484
- enablePager(table, c, true);
485
- })
486
- .bind('destroy.pager', function(){
487
- destroyPager(table, c);
488
- })
489
- .bind('update.pager', function(){
490
- hideRows(table, c);
491
- });
492
-
493
- // pager initialized
494
- if (!c.ajax) {
495
- c.initialized = true;
496
- $(table).trigger('pagerInitialized', c);
497
- }
498
- });
499
- };
500
-
501
- }()
502
- });
503
- // extend plugin scope
504
- $.fn.extend({
505
- tablesorterPager: $.tablesorterPager.construct
506
- });
507
-
1
+ /*!
2
+ * tablesorter pager plugin
3
+ * updated 11/27/2012
4
+ */
5
+ /*jshint browser:true, jquery:true, unused:false */
6
+ ;(function($) {
7
+ "use strict";
8
+ $.extend({tablesorterPager: new function() {
9
+
10
+ this.defaults = {
11
+ // target the pager markup
12
+ container: null,
13
+
14
+ // use this format: "http://mydatabase.com?page={page}&size={size}&{sortList:col}"
15
+ // where {page} is replaced by the page number and {size} is replaced by the number of records to show
16
+ // {sortList:col} adds the sortList to the url into a "col" array.
17
+ // So a sortList = [[2,0],[3,0]] becomes "&col[2]=0&col[3]=0" in the url
18
+ ajaxUrl: null,
19
+
20
+ // process ajax so that the following information is returned:
21
+ // [ total_rows (number), rows (array of arrays), headers (array; optional) ]
22
+ // example:
23
+ // [
24
+ // 100, // total rows
25
+ // [
26
+ // [ "row1cell1", "row1cell2", ... "row1cellN" ],
27
+ // [ "row2cell1", "row2cell2", ... "row2cellN" ],
28
+ // ...
29
+ // [ "rowNcell1", "rowNcell2", ... "rowNcellN" ]
30
+ // ],
31
+ // [ "header1", "header2", ... "headerN" ] // optional
32
+ // ]
33
+ ajaxProcessing: function(ajax){ return [ 0, [], null ]; },
34
+
35
+ // output default: '{page}/{totalPages}'
36
+ // possible variables: {page}, {totalPages}, {filteredPages}, {startRow}, {endRow}, {filteredRows} and {totalRows}
37
+ output: '{startRow} to {endRow} of {totalRows} rows', // '{page}/{totalPages}'
38
+
39
+ // apply disabled classname to the pager arrows when the rows at either extreme is visible
40
+ updateArrows: true,
41
+
42
+ // starting page of the pager (zero based index)
43
+ page: 0,
44
+
45
+ // Number of visible rows
46
+ size: 10,
47
+
48
+ // if true, the table will remain the same height no matter how many records are displayed. The space is made up by an empty
49
+ // table row set to a height to compensate; default is false
50
+ fixedHeight: false,
51
+
52
+ // remove rows from the table to speed up the sort of large tables.
53
+ // setting this to false, only hides the non-visible rows; needed if you plan to add/remove rows with the pager enabled.
54
+ removeRows: false, // removing rows in larger tables speeds up the sort
55
+
56
+ // css class names of pager arrows
57
+ cssFirst: '.first', // go to first page arrow
58
+ cssPrev: '.prev', // previous page arrow
59
+ cssNext: '.next', // next page arrow
60
+ cssLast: '.last', // go to last page arrow
61
+ cssGoto: '.gotoPage', // go to page selector - select dropdown that sets the current page
62
+ cssPageDisplay: '.pagedisplay', // location of where the "output" is displayed
63
+ cssPageSize: '.pagesize', // page size selector - select dropdown that sets the "size" option
64
+
65
+ // class added to arrows when at the extremes (i.e. prev/first arrows are "disabled" when on the first page)
66
+ cssDisabled: 'disabled', // Note there is no period "." in front of this class name
67
+
68
+ // stuff not set by the user
69
+ totalRows: 0,
70
+ totalPages: 0,
71
+ filteredRows: 0,
72
+ filteredPages: 0
73
+
74
+ };
75
+
76
+ var $this = this,
77
+
78
+ // hide arrows at extremes
79
+ pagerArrows = function(c, disable) {
80
+ var a = 'addClass',
81
+ r = 'removeClass',
82
+ d = c.cssDisabled,
83
+ dis = !!disable,
84
+ // tr = Math.min( c.totalRows, c.filteredRows ),
85
+ tp = Math.min( c.totalPages, c.filteredPages );
86
+ if ( c.updateArrows ) {
87
+ $(c.cssFirst + ',' + c.cssPrev, c.container)[ ( dis || c.page === 0 ) ? a : r ](d);
88
+ $(c.cssNext + ',' + c.cssLast, c.container)[ ( dis || c.page === tp - 1 ) ? a : r ](d);
89
+ }
90
+ },
91
+
92
+ updatePageDisplay = function(table, c) {
93
+ var i, p, s, t, out, f = $(table).hasClass('hasFilters');
94
+ c.filteredRows = (f) ? $(table).find('tbody tr:not(.filtered)').length : c.totalRows;
95
+ c.filteredPages = (f) ? Math.ceil( c.filteredRows / c.size ) : c.totalPages;
96
+ if ( Math.min( c.totalPages, c.filteredPages ) > 0 ) {
97
+ t = (c.size * c.page > c.filteredRows);
98
+ c.startRow = (t) ? 1 : ( c.size * c.page ) + 1;
99
+ c.page = (t) ? 0 : c.page;
100
+ c.endRow = Math.min( c.filteredRows, c.totalRows, c.size * ( c.page + 1 ) );
101
+ out = $(c.cssPageDisplay, c.container);
102
+ // form the output string
103
+ s = c.output.replace(/\{(page|filteredRows|filteredPages|totalPages|startRow|endRow|totalRows)\}/gi, function(m){
104
+ return {
105
+ '{page}' : c.page + 1,
106
+ '{filteredRows}' : c.filteredRows,
107
+ '{filteredPages}' : c.filteredPages,
108
+ '{totalPages}' : c.totalPages,
109
+ '{startRow}' : c.startRow,
110
+ '{endRow}' : c.endRow,
111
+ '{totalRows}' : c.totalRows
112
+ }[m];
113
+ });
114
+ if (out[0]) {
115
+ out[ (out[0].tagName === 'INPUT') ? 'val' : 'html' ](s);
116
+ if ( $(c.cssGoto, c.container).length ) {
117
+ t = '';
118
+ p = Math.min( c.totalPages, c.filteredPages );
119
+ for ( i = 1; i <= p; i++ ) {
120
+ t += '<option>' + i + '</option>';
121
+ }
122
+ $(c.cssGoto, c.container).html(t).val(c.page + 1);
123
+ }
124
+ }
125
+ }
126
+ pagerArrows(c);
127
+ if (c.initialized) { $(table).trigger('pagerComplete', c); }
128
+ },
129
+
130
+ fixHeight = function(table, c) {
131
+ var d, h, $b = $(table.tBodies[0]);
132
+ if (c.fixedHeight) {
133
+ $b.find('tr.pagerSavedHeightSpacer').remove();
134
+ h = $.data(table, 'pagerSavedHeight');
135
+ if (h) {
136
+ d = h - $b.height();
137
+ if ( d > 5 && $.data(table, 'pagerLastSize') === c.size && $b.find('tr:visible').length < c.size ) {
138
+ $b.append('<tr class="pagerSavedHeightSpacer remove-me" style="height:' + d + 'px;"></tr>');
139
+ }
140
+ }
141
+ }
142
+ },
143
+
144
+ changeHeight = function(table, c) {
145
+ var $b = $(table.tBodies[0]);
146
+ $b.find('tr.pagerSavedHeightSpacer').remove();
147
+ $.data(table, 'pagerSavedHeight', $b.height());
148
+ fixHeight(table, c);
149
+ $.data(table, 'pagerLastSize', c.size);
150
+ },
151
+
152
+ hideRows = function(table, c){
153
+ if (!c.ajaxUrl) {
154
+ var i,
155
+ rows = $('tr:not(.' + table.config.cssChildRow + ')', table.tBodies),
156
+ l = rows.length,
157
+ s = ( c.page * c.size ),
158
+ e = s + c.size,
159
+ j = 0; // size counter
160
+ for ( i = 0; i < l; i++ ){
161
+ if (!/filtered/.test(rows[i].className)) {
162
+ rows[i].style.display = ( j >= s && j < e ) ? '' : 'none';
163
+ j++;
164
+ }
165
+ }
166
+ }
167
+ },
168
+
169
+ hideRowsSetup = function(table, c){
170
+ c.size = parseInt( $(c.cssPageSize, c.container).find('option[selected]').val(), 10 ) || c.size;
171
+ $.data(table, 'pagerLastSize', c.size);
172
+ pagerArrows(c);
173
+ if ( !c.removeRows ) {
174
+ hideRows(table, c);
175
+ $(table).bind('sortEnd.pager filterEnd.pager', function(){
176
+ hideRows(table, c);
177
+ });
178
+ }
179
+ },
180
+
181
+ renderAjax = function(data, table, c, exception){
182
+ // process data
183
+ if ( typeof(c.ajaxProcessing) === "function" ) {
184
+ // ajaxProcessing result: [ total, rows, headers ]
185
+ var i, j, hsh, $f, $sh,
186
+ $t = $(table),
187
+ tc = table.config,
188
+ $b = $(table.tBodies).filter(':not(.' + tc.cssInfoBlock + ')'),
189
+ hl = $t.find('thead th').length, tds = '',
190
+ err = '<tr class="' + tc.selectorRemove + '"><td style="text-align: center;" colspan="' + hl + '">' +
191
+ (exception ? exception.message + ' (' + exception.name + ')' : 'No rows found') + '</td></tr>',
192
+ result = c.ajaxProcessing(data) || [ 0, [] ],
193
+ d = result[1] || [],
194
+ l = d.length,
195
+ th = result[2];
196
+ if ( l > 0 ) {
197
+ for ( i = 0; i < l; i++ ) {
198
+ tds += '<tr>';
199
+ for ( j = 0; j < d[i].length; j++ ) {
200
+ // build tbody cells
201
+ tds += '<td>' + d[i][j] + '</td>';
202
+ }
203
+ tds += '</tr>';
204
+ }
205
+ }
206
+ // only add new header text if the length matches
207
+ if ( th && th.length === hl ) {
208
+ hsh = $t.hasClass('hasStickyHeaders');
209
+ $sh = $t.find('.' + ((tc.widgetOptions && tc.widgetOptions.stickyHeaders) || 'tablesorter-stickyheader'));
210
+ $f = $t.find('tfoot tr:first').children();
211
+ $t.find('th.' + tc.cssHeader).each(function(j){
212
+ var $t = $(this), icn;
213
+ // add new test within the first span it finds, or just in the header
214
+ if ( $t.find('.' + tc.cssIcon).length ) {
215
+ icn = $t.find('.' + tc.cssIcon).clone(true);
216
+ $t.find('.tablesorter-header-inner').html( th[j] ).append(icn);
217
+ if ( hsh && $sh.length ) {
218
+ icn = $sh.find('th').eq(j).find('.' + tc.cssIcon).clone(true);
219
+ $sh.find('th').eq(j).find('.tablesorter-header-inner').html( th[j] ).append(icn);
220
+ }
221
+ } else {
222
+ $t.find('.tablesorter-header-inner').html( th[j] );
223
+ $sh.find('th').eq(j).find('.tablesorter-header-inner').html( th[j] );
224
+ }
225
+ $f.eq(j).html( th[j] );
226
+ });
227
+ }
228
+ if ( exception ) {
229
+ // add error row to thead instead of tbody, or clicking on the header will result in a parser error
230
+ $t.find('thead').append(err);
231
+ } else {
232
+ $b.html( tds ); // add tbody
233
+ }
234
+ $.tablesorter.isProcessing(table); // remove loading icon
235
+ $t.trigger('update');
236
+ c.totalRows = result[0] || 0;
237
+ c.totalPages = Math.ceil( c.totalRows / c.size );
238
+ updatePageDisplay(table, c);
239
+ fixHeight(table, c);
240
+ if (c.initialized) { $t.trigger('pagerChange', c); }
241
+ }
242
+ if (!c.initialized) {
243
+ c.initialized = true;
244
+ $(table).trigger('pagerInitialized', c);
245
+ }
246
+ },
247
+
248
+ getAjax = function(table, c){
249
+ var url = (c.ajaxUrl) ? c.ajaxUrl.replace(/\{page\}/g, c.page).replace(/\{size\}/g, c.size) : '',
250
+ arry = [],
251
+ sl = table.config.sortList,
252
+ col = url.match(/\{sortList[\s+]?:[\s+]?(.*)\}/);
253
+ if (col) {
254
+ col = col[1];
255
+ $.each(sl, function(i,v){
256
+ arry.push(col + '[' + v[0] + ']=' + v[1]);
257
+ });
258
+ // if the arry is empty, just add the col parameter... "&{sortList:col}" becomes "&col"
259
+ url = url.replace(/\{sortList[\s+]?:[\s+]?(.*)\}/g, arry.length ? arry.join('&') : col );
260
+ }
261
+ if ( url !== '' ) {
262
+ // loading icon
263
+ $.tablesorter.isProcessing(table, true);
264
+ $(document).ajaxError(function(e, xhr, settings, exception) {
265
+ renderAjax(null, table, c, exception);
266
+ });
267
+ $.getJSON(url, function(data) {
268
+ renderAjax(data, table, c);
269
+ });
270
+ }
271
+ },
272
+
273
+ renderTable = function(table, rows, c) {
274
+ var i, j, o,
275
+ f = document.createDocumentFragment(),
276
+ l = rows.length,
277
+ s = ( c.page * c.size ),
278
+ e = ( s + c.size );
279
+ if ( l < 1 ) { return; } // empty table, abort!
280
+ if (c.initialized) { $(table).trigger('pagerChange', c); }
281
+ if ( !c.removeRows ) {
282
+ hideRows(table, c);
283
+ } else {
284
+ if ( e > rows.length ) {
285
+ e = rows.length;
286
+ }
287
+ $(table.tBodies[0]).addClass('tablesorter-hidden');
288
+ $.tablesorter.clearTableBody(table);
289
+ for ( i = s; i < e; i++ ) {
290
+ o = rows[i];
291
+ l = o.length;
292
+ for ( j = 0; j < l; j++ ) {
293
+ f.appendChild(o[j]);
294
+ }
295
+ }
296
+ table.tBodies[0].appendChild(f);
297
+ $(table.tBodies[0]).removeClass('tablesorter-hidden');
298
+ }
299
+ if ( c.page >= c.totalPages ) {
300
+ moveToLastPage(table, c);
301
+ }
302
+ updatePageDisplay(table, c);
303
+ if ( !c.isDisabled ) { fixHeight(table, c); }
304
+ $(table).trigger('applyWidgets');
305
+ },
306
+
307
+ showAllRows = function(table, c){
308
+ if ( c.ajax ) {
309
+ pagerArrows(c, true);
310
+ } else {
311
+ c.isDisabled = true;
312
+ $.data(table, 'pagerLastPage', c.page);
313
+ $.data(table, 'pagerLastSize', c.size);
314
+ c.page = 0;
315
+ c.size = c.totalRows;
316
+ c.totalPages = 1;
317
+ $('tr.pagerSavedHeightSpacer', table.tBodies[0]).remove();
318
+ renderTable(table, table.config.rowsCopy, c);
319
+ }
320
+ // disable size selector
321
+ $(c.container).find(c.cssPageSize + ',' + c.cssGoto).each(function(){
322
+ $(this).addClass(c.cssDisabled)[0].disabled = true;
323
+ });
324
+ },
325
+
326
+ moveToPage = function(table, c) {
327
+ if ( c.isDisabled ) { return; }
328
+ var p = Math.min( c.totalPages, c.filteredPages );
329
+ if ( c.page < 0 || c.page > ( p - 1 ) ) {
330
+ c.page = 0;
331
+ }
332
+ // change if page changed - fixes #182
333
+ if (c.ajax && $.data(table, 'pagerLastPage') !== c.page) {
334
+ getAjax(table, c);
335
+ } else if (!c.ajax) {
336
+ renderTable(table, table.config.rowsCopy, c);
337
+ }
338
+ $.data(table, 'pagerLastPage', c.page);
339
+ if (c.initialized) { $(table).trigger('pageMoved', c); }
340
+ },
341
+
342
+ setPageSize = function(table, size, c) {
343
+ c.size = size;
344
+ $.data(table, 'pagerLastPage', c.page);
345
+ $.data(table, 'pagerLastSize', c.size);
346
+ c.totalPages = Math.ceil( c.totalRows / c.size );
347
+ moveToPage(table, c);
348
+ },
349
+
350
+ moveToFirstPage = function(table, c) {
351
+ c.page = 0;
352
+ moveToPage(table, c);
353
+ },
354
+
355
+ moveToLastPage = function(table, c) {
356
+ c.page = ( Math.min( c.totalPages, c.filteredPages ) - 1 );
357
+ moveToPage(table, c);
358
+ },
359
+
360
+ moveToNextPage = function(table, c) {
361
+ c.page++;
362
+ if ( c.page >= ( Math.min( c.totalPages, c.filteredPages ) - 1 ) ) {
363
+ c.page = ( Math.min( c.totalPages, c.filteredPages ) - 1 );
364
+ }
365
+ moveToPage(table, c);
366
+ },
367
+
368
+ moveToPrevPage = function(table, c) {
369
+ c.page--;
370
+ if ( c.page <= 0 ) {
371
+ c.page = 0;
372
+ }
373
+ moveToPage(table, c);
374
+ },
375
+
376
+ destroyPager = function(table, c){
377
+ showAllRows(table, c);
378
+ $(c.container).hide(); // hide pager
379
+ table.config.appender = null; // remove pager appender function
380
+ $(table).unbind('destroy.pager sortEnd.pager filterEnd.pager enable.pager disable.pager');
381
+ },
382
+
383
+ enablePager = function(table, c, triggered){
384
+ var p = $(c.cssPageSize, c.container).removeClass(c.cssDisabled).removeAttr('disabled');
385
+ $(c.container).find(c.cssGoto).removeClass(c.cssDisabled).removeAttr('disabled');
386
+ c.isDisabled = false;
387
+ c.page = $.data(table, 'pagerLastPage') || c.page || 0;
388
+ c.size = $.data(table, 'pagerLastSize') || parseInt(p.find('option[selected]').val(), 10) || c.size;
389
+ p.val(c.size); // set page size
390
+ c.totalPages = Math.ceil( Math.min( c.totalPages, c.filteredPages ) / c.size);
391
+ if ( triggered ) {
392
+ $(table).trigger('update');
393
+ setPageSize(table, c.size, c);
394
+ hideRowsSetup(table, c);
395
+ fixHeight(table, c);
396
+ }
397
+ };
398
+
399
+ $this.appender = function(table, rows) {
400
+ var c = table.config.pager;
401
+ if ( !c.ajax ) {
402
+ table.config.rowsCopy = rows;
403
+ c.totalRows = rows.length;
404
+ c.size = $.data(table, 'pagerLastSize') || c.size;
405
+ c.totalPages = Math.ceil(c.totalRows / c.size);
406
+ renderTable(table, rows, c);
407
+ }
408
+ };
409
+
410
+ $this.construct = function(settings) {
411
+ return this.each(function() {
412
+ // check if tablesorter has initialized
413
+ if (!(this.config && this.hasInitialized)) { return; }
414
+ var config = this.config,
415
+ c = config.pager = $.extend( {}, $.tablesorterPager.defaults, settings ),
416
+ table = this,
417
+ $t = $(table),
418
+ pager = $(c.container).addClass('tablesorter-pager').show(); // added in case the pager is reinitialized after being destroyed.
419
+ config.appender = $this.appender;
420
+ // clear initialized flag
421
+ c.initialized = false;
422
+ enablePager(table, c, false);
423
+ if ( typeof(c.ajaxUrl) === 'string' ) {
424
+ // ajax pager; interact with database
425
+ c.ajax = true;
426
+ getAjax(table, c);
427
+ } else {
428
+ c.ajax = false;
429
+ // Regular pager; all rows stored in memory
430
+ $(this).trigger("appendCache", true);
431
+ hideRowsSetup(table, c);
432
+ }
433
+
434
+ // update pager after filter widget completes
435
+ $(table)
436
+ .unbind('filterEnd.pager updateComplete.pager ')
437
+ .bind('filterEnd.pager updateComplete.pager', function() {
438
+ if ($(this).hasClass('hasFilters')) {
439
+ c.page = 0;
440
+ updatePageDisplay(table, c);
441
+ moveToPage(table, c);
442
+ changeHeight(table, c);
443
+ }
444
+ });
445
+
446
+ if ( $(c.cssGoto, pager).length ) {
447
+ $(c.cssGoto, pager).bind('change', function(){
448
+ c.page = $(this).val() - 1;
449
+ moveToPage(table, c);
450
+ });
451
+ updatePageDisplay(table, c);
452
+ }
453
+ $(c.cssFirst,pager).unbind('click.pager').bind('click.pager', function() {
454
+ if ( !$(this).hasClass(c.cssDisabled) ) { moveToFirstPage(table, c); }
455
+ return false;
456
+ });
457
+ $(c.cssNext,pager).unbind('click.pager').bind('click.pager', function() {
458
+ if ( !$(this).hasClass(c.cssDisabled) ) { moveToNextPage(table, c); }
459
+ return false;
460
+ });
461
+ $(c.cssPrev,pager).unbind('click.pager').bind('click.pager', function() {
462
+ if ( !$(this).hasClass(c.cssDisabled) ) { moveToPrevPage(table, c); }
463
+ return false;
464
+ });
465
+ $(c.cssLast,pager).unbind('click.pager').bind('click.pager', function() {
466
+ if ( !$(this).hasClass(c.cssDisabled) ) { moveToLastPage(table, c); }
467
+ return false;
468
+ });
469
+ $(c.cssPageSize,pager).unbind('change.pager').bind('change.pager', function() {
470
+ $(c.cssPageSize,pager).val( $(this).val() ); // in case there are more than one pagers
471
+ if ( !$(this).hasClass(c.cssDisabled) ) {
472
+ setPageSize(table, parseInt( $(this).val(), 10 ), c);
473
+ changeHeight(table, c);
474
+ }
475
+ return false;
476
+ });
477
+
478
+ $t
479
+ .unbind('disable.pager enable.pager destroy.pager update.pager')
480
+ .bind('disable.pager', function(){
481
+ showAllRows(table, c);
482
+ })
483
+ .bind('enable.pager', function(){
484
+ enablePager(table, c, true);
485
+ })
486
+ .bind('destroy.pager', function(){
487
+ destroyPager(table, c);
488
+ })
489
+ .bind('update.pager', function(){
490
+ hideRows(table, c);
491
+ });
492
+
493
+ // pager initialized
494
+ if (!c.ajax) {
495
+ c.initialized = true;
496
+ $(table).trigger('pagerInitialized', c);
497
+ }
498
+ });
499
+ };
500
+
501
+ }()
502
+ });
503
+ // extend plugin scope
504
+ $.fn.extend({
505
+ tablesorterPager: $.tablesorterPager.construct
506
+ });
507
+
508
508
  })(jQuery);