jquery-tablesorter 1.15.0 → 1.16.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 (22) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/jquery-tablesorter/version.rb +1 -1
  4. data/vendor/assets/javascripts/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.js +71 -30
  5. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.js +109 -65
  6. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets.js +83 -62
  7. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-range.js +93 -0
  8. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-input-select.js +6 -4
  9. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-metric.js +1 -1
  10. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-columnSelector.js +4 -2
  11. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter-formatter-html5.js +2 -2
  12. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter-formatter-jui.js +2 -3
  13. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter-formatter-select2.js +1 -1
  14. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter-type-insideRange.js +42 -0
  15. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter.js +57 -45
  16. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-formatter.js +1 -1
  17. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-grouping.js +9 -7
  18. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-output.js +9 -1
  19. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-pager.js +68 -30
  20. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-scroller.js +41 -41
  21. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-stickyHeaders.js +25 -16
  22. metadata +4 -2
@@ -1,5 +1,5 @@
1
1
  /*! input & select parsers for jQuery 1.7+ & tablesorter 2.7.11+
2
- * Updated 2/7/2015 (v2.19.0)
2
+ * Updated 3/5/2015 (v2.21.0)
3
3
  * Demo: http://mottie.github.com/tablesorter/docs/example-widget-grouping.html
4
4
  */
5
5
  /*jshint browser: true, jquery:true, unused:false */
@@ -36,14 +36,16 @@
36
36
  },
37
37
  format: function(s, table, cell, cellIndex) {
38
38
  var $c = $(cell),
39
+ wo = table.config.widgetOptions,
40
+ // returning plain language here because this is what is shown in the
41
+ // group headers - change it as desired
42
+ txt = wo.group_checkbox ? wo.group_checkbox : [ 'checked', 'unchecked' ],
39
43
  $input = $c.find('input[type="checkbox"]'),
40
44
  isChecked = $input.length ? $input[0].checked : '';
41
45
  // adding class to row, indicating that a checkbox is checked; includes
42
46
  // a column index in case more than one checkbox happens to be in a row
43
47
  $c.closest('tr').toggleClass('checked-' + cellIndex, isChecked);
44
- // returning plain language here because this is what is shown in the
45
- // group headers - change it as desired
46
- return $input.length ? isChecked ? 'checked' : 'unchecked' : s;
48
+ return $input.length ? txt[ isChecked ? 0 : 1 ] : s;
47
49
  },
48
50
  parsed : true, // filter widget flag
49
51
  type: "text"
@@ -47,7 +47,7 @@
47
47
  b, t,
48
48
  // process number here to get a numerical format (us or eu)
49
49
  n = $.tablesorter.formatFloat(s.replace(/[^\w,. \-()]/g, ""), table),
50
- $t = table.config.$headers.filter('[data-column="' + cellIndex + '"]'),
50
+ $t = table.config.$headerIndexed[cellIndex],
51
51
  m = $t.data('metric');
52
52
  if (!m) {
53
53
  // stored values
@@ -1,4 +1,4 @@
1
- /* Column Selector/Responsive table widget for TableSorter - 2/7/2015 (v2.19.0)
1
+ /* Column Selector/Responsive table widget for TableSorter - 3/5/2015 (v2.21.0)
2
2
  * Requires tablesorter v2.8+ and jQuery 1.7+
3
3
  * by Justin Hallett & Rob Garrison
4
4
  */
@@ -21,7 +21,7 @@ tsColSel = ts.columnSelector = {
21
21
  $t = $(wo.columnSelector_layout);
22
22
  if (!$t.find('input').add( $t.filter('input') ).length) {
23
23
  if (c.debug) {
24
- ts.log('*** ERROR: Column Selector aborting, no input found in the layout! ***');
24
+ ts.log('ColumnSelector: >> ERROR: Column Selector aborting, no input found in the layout! ***');
25
25
  }
26
26
  return;
27
27
  }
@@ -45,6 +45,8 @@ tsColSel = ts.columnSelector = {
45
45
  colSel.isInitializing = false;
46
46
  if (colSel.$container.length) {
47
47
  tsColSel.updateCols(c, wo);
48
+ } else if (c.debug) {
49
+ ts.log('ColumnSelector: >> container not found');
48
50
  }
49
51
 
50
52
  c.$table
@@ -16,7 +16,7 @@ var ts = $.tablesorter || {},
16
16
  compareSelect = '.compare-select',
17
17
 
18
18
 
19
- tsff = ts.filterFormatter = {
19
+ tsff = ts.filterFormatter = $.extend( {}, ts.filterFormatter, {
20
20
 
21
21
  addCompare: function($cell, indx, options){
22
22
  if (options.compare && $.isArray(options.compare) && options.compare.length > 1) {
@@ -424,6 +424,6 @@ tsff = ts.filterFormatter = {
424
424
  return colorSupported ? $cell.find('input[type="hidden"]') : $('<input type="search">');
425
425
  }
426
426
 
427
- };
427
+ });
428
428
 
429
429
  })(jQuery);
@@ -17,8 +17,7 @@ var ts = $.tablesorter || {},
17
17
  // compare option selector class name (jQuery selector)
18
18
  compareSelect = '.compare-select',
19
19
 
20
-
21
- tsff = ts.filterFormatter = {
20
+ tsff = ts.filterFormatter = $.extend( {}, ts.filterFormatter, {
22
21
 
23
22
  addCompare: function($cell, indx, options){
24
23
  if (options.compare && $.isArray(options.compare) && options.compare.length > 1) {
@@ -760,6 +759,6 @@ tsff = ts.filterFormatter = {
760
759
  return $input.val( o.from ? ( o.to ? o.from + ' - ' + o.to : '>=' + o.from ) : (o.to ? '<=' + o.to : '') );
761
760
  }
762
761
 
763
- };
762
+ });
764
763
 
765
764
  })(jQuery);
@@ -36,7 +36,7 @@ ts.filterFormatter.select2 = function($cell, indx, select2Def) {
36
36
  $cell.find('.select2').select2('val', val);
37
37
  updateSelect2();
38
38
  }),
39
- $header = c.$headers.filter('[data-column="' + indx + '"]:last'),
39
+ $header = c.$headerIndexed[indx],
40
40
  onlyAvail = $header.hasClass(wo.filter_onlyAvail),
41
41
  $shcell = [],
42
42
  matchPrefix = o.match ? '' : '^',
@@ -0,0 +1,42 @@
1
+ /*!
2
+ * insideRange filter type
3
+ * 2/23/2015 (v2.21.0)
4
+ */
5
+ ;(function($){
6
+ 'use strict';
7
+
8
+ // Add insideRange filter type
9
+ // ============================
10
+ // This allows you to enter a number (e.g. 8) and show the
11
+ // resulting rows that will have that query within it's range
12
+ // demo at http://mottie.github.io/tablesorter/docs/example-widget-filter-custom-search2.html
13
+ var ts = $.tablesorter,
14
+ isDigit = /\d+/,
15
+ range = /\s+-\s+/,
16
+ parseNumber = function(num) {
17
+ return isNaN(num) ? num : parseFloat(num);
18
+ };
19
+
20
+ ts.filter.types.insideRange = function( c, data ) {
21
+ if ( isDigit.test( data.iFilter ) && range.test( data.iExact ) ) {
22
+ var t, val, low, high,
23
+ parts = data.iExact.split( range ),
24
+ format = c.parsers[data.index].format;
25
+ // the cell does not contain a range
26
+ if ( parts && parts.length < 2 ) {
27
+ return null;
28
+ }
29
+ // format each side part of the range using the assigned parser
30
+ low = parseNumber( format( parts[0], c.table ) );
31
+ high = parseNumber( format( parts[1], c.table ) );
32
+ val = parseNumber( format( data.iFilter, c.table ) );
33
+ if ( high < low ) {
34
+ // swap high & low
35
+ t = high; high = low; low = t;
36
+ }
37
+ return low <= val && val <= high;
38
+ }
39
+ return null;
40
+ };
41
+
42
+ })(jQuery);
@@ -1,4 +1,7 @@
1
- /*! Widget: filter */
1
+ /*! Widget: filter - updated 3/5/2015 (v2.21.0) *//*
2
+ * Requires tablesorter v2.8+ and jQuery 1.7+
3
+ * by Rob Garrison
4
+ */
2
5
  ;(function ($) {
3
6
  'use strict';
4
7
  var ts = $.tablesorter = $.tablesorter || {};
@@ -209,7 +212,7 @@ ts.filter = {
209
212
  parsed = data.parsed[index],
210
213
  query = ts.filter.parseFilter(c, data.iFilter.replace(ts.filter.regex.orReplace, "|"), index, parsed);
211
214
  // look for an exact match with the "or" unless the "filter-match" class is found
212
- if (!c.$headers.filter('[data-column="' + index + '"]:last').hasClass('filter-match') && /\|/.test(query)) {
215
+ if (!c.$headerIndexed[index].hasClass('filter-match') && /\|/.test(query)) {
213
216
  // show all results while using filter match. Fixes #727
214
217
  if (query[ query.length - 1 ] === '|') { query += '*'; }
215
218
  query = data.anyMatch && $.isArray(data.rowArray) ? '(' + query + ')' : '^(' + query + ')$';
@@ -330,7 +333,7 @@ ts.filter = {
330
333
  fxn = ts.getColumnData( table, wo.filter_functions, column );
331
334
  if (fxn) {
332
335
  // remove "filter-select" from header otherwise the options added here are replaced with all options
333
- $header = c.$headers.filter('[data-column="' + column + '"]:last').removeClass('filter-select');
336
+ $header = c.$headerIndexed[column].removeClass('filter-select');
334
337
  // don't build select if "filter-false" or "parser-false" set
335
338
  noSelect = !($header.hasClass('filter-false') || $header.hasClass('parser-false'));
336
339
  options = '';
@@ -426,7 +429,8 @@ ts.filter = {
426
429
  }
427
430
  },
428
431
  filterInitComplete: function(c){
429
- var wo = c.widgetOptions,
432
+ var indx, len,
433
+ wo = c.widgetOptions,
430
434
  count = 0,
431
435
  completed = function(){
432
436
  wo.filter_initialized = true;
@@ -436,11 +440,12 @@ ts.filter = {
436
440
  if ( $.isEmptyObject( wo.filter_formatter ) ) {
437
441
  completed();
438
442
  } else {
439
- $.each( wo.filter_formatterInit, function(i, val) {
440
- if (val === 1) {
443
+ len = wo.filter_formatterInit.length;
444
+ for (indx = 0; indx < len; indx++) {
445
+ if (wo.filter_formatterInit[indx] === 1) {
441
446
  count++;
442
447
  }
443
- });
448
+ }
444
449
  clearTimeout(wo.filter_initTimer);
445
450
  if (!wo.filter_initialized && count === wo.filter_formatterCount) {
446
451
  // filter widget initialized
@@ -456,7 +461,7 @@ ts.filter = {
456
461
  },
457
462
 
458
463
  setDefaults: function(table, c, wo) {
459
- var isArray, saved, indx,
464
+ var isArray, saved, indx, col, $filters,
460
465
  // get current (default) filters
461
466
  filters = ts.getFilters(table) || [];
462
467
  if (wo.filter_saveFilters && ts.storage) {
@@ -467,8 +472,12 @@ ts.filter = {
467
472
  }
468
473
  // if no filters saved, then check default settings
469
474
  if (filters.join('') === '') {
470
- for (indx = 0; indx < c.columns; indx++) {
471
- filters[indx] = c.$headers.filter('[data-column="' + indx + '"]:last').attr(wo.filter_defaultAttrib) || filters[indx];
475
+ // allow adding default setting to external filters
476
+ $filters = c.$headers.add( wo.filter_$externalFilters ).filter('[' + wo.filter_defaultAttrib + ']');
477
+ for (indx = 0; indx <= c.columns; indx++) {
478
+ // include data-column="all" external filters
479
+ col = indx === c.columns ? 'all' : indx;
480
+ filters[indx] = $filters.filter('[data-column="' + col + '"]').attr(wo.filter_defaultAttrib) || filters[indx] || '';
472
481
  }
473
482
  }
474
483
  c.$table.data('lastSearch', filters);
@@ -497,7 +506,7 @@ ts.filter = {
497
506
  for (column = 0; column < columns; column++) {
498
507
  disabled = false;
499
508
  // assuming last cell of a column is the main column
500
- $header = c.$headers.filter('[data-column="' + column + '"]:last');
509
+ $header = c.$headerIndexed[column];
501
510
  ffxn = ts.getColumnData( table, wo.filter_functions, column );
502
511
  buildSelect = (wo.filter_functions && ffxn && typeof ffxn !== "function" ) ||
503
512
  $header.hasClass('filter-select');
@@ -722,7 +731,7 @@ ts.filter = {
722
731
  },
723
732
  multipleColumns: function( c, $input ) {
724
733
  // look for multiple columns "1-3,4-6,8" in data-column
725
- var ranges, singles, indx,
734
+ var temp, ranges, range, start, end, singles, i, indx, len,
726
735
  wo = c.widgetOptions,
727
736
  // only target "all" column inputs on initialization
728
737
  // & don't target "all" column inputs if they don't exist
@@ -732,31 +741,32 @@ ts.filter = {
732
741
  // process column range
733
742
  if ( targets && /-/.test( val ) ) {
734
743
  ranges = val.match( /(\d+)\s*-\s*(\d+)/g );
735
- $.each(ranges, function(i,v){
736
- var t,
737
- range = v.split( /\s*-\s*/ ),
738
- start = parseInt( range[0], 10 ) || 0,
739
- end = parseInt( range[1], 10 ) || ( c.columns - 1 );
740
- if ( start > end ) { t = start; start = end; end = t; } // swap
744
+ len = ranges.length;
745
+ for (indx = 0; indx < len; indx++) {
746
+ range = ranges[indx].split( /\s*-\s*/ );
747
+ start = parseInt( range[0], 10 ) || 0;
748
+ end = parseInt( range[1], 10 ) || ( c.columns - 1 );
749
+ if ( start > end ) { temp = start; start = end; end = temp; } // swap
741
750
  if ( end >= c.columns ) { end = c.columns - 1; }
742
751
  for ( ; start <= end; start++ ) {
743
752
  columns.push(start);
744
753
  }
745
754
  // remove processed range from val
746
- val = val.replace( v, '' );
747
- });
755
+ val = val.replace( ranges[indx], '' );
756
+ }
748
757
  }
749
758
  // process single columns
750
759
  if ( targets && /,/.test( val ) ) {
751
760
  singles = val.split( /\s*,\s*/ );
752
- $.each( singles, function(i,v) {
753
- if (v !== '') {
754
- indx = parseInt( v, 10 );
761
+ len = singles.length;
762
+ for (i = 0; i < len; i++) {
763
+ if (singles[i] !== '') {
764
+ indx = parseInt( singles[i], 10 );
755
765
  if ( indx < c.columns ) {
756
766
  columns.push( indx );
757
767
  }
758
768
  }
759
- });
769
+ }
760
770
  }
761
771
  // return all columns
762
772
  if (!columns.length) {
@@ -784,12 +794,12 @@ ts.filter = {
784
794
  data.parsed = c.$headers.map(function(columnIndex) {
785
795
  return c.parsers && c.parsers[columnIndex] && c.parsers[columnIndex].parsed ||
786
796
  // getData won't return "parsed" if other "filter-" class names exist (e.g. <th class="filter-select filter-parsed">)
787
- ts.getData && ts.getData(c.$headers.filter('[data-column="' + columnIndex + '"]:last'), ts.getColumnData( table, c.headers, columnIndex ), 'filter') === 'parsed' ||
797
+ ts.getData && ts.getData(c.$headerIndexed[columnIndex], ts.getColumnData( table, c.headers, columnIndex ), 'filter') === 'parsed' ||
788
798
  $(this).hasClass('filter-parsed');
789
799
  }).get();
790
800
 
791
801
  if (c.debug) {
792
- ts.log('Starting filter widget search', filters);
802
+ ts.log('Filter: Starting filter widget search', filters);
793
803
  time = new Date();
794
804
  }
795
805
  // filtered rows count
@@ -808,7 +818,7 @@ ts.filter = {
808
818
  $rows = $( $.map(norm_rows, function(el){ return el[columnIndex].$row.get(); }) );
809
819
 
810
820
  if (combinedFilters === '' || wo.filter_serversideFiltering) {
811
- $rows.removeClass(wo.filter_filteredRow).not('.' + c.cssChildRow).show();
821
+ $rows.removeClass(wo.filter_filteredRow).not('.' + c.cssChildRow).css('display', '');
812
822
  } else {
813
823
  // filter out child rows
814
824
  $rows = $rows.not('.' + c.cssChildRow);
@@ -860,14 +870,14 @@ ts.filter = {
860
870
  // don't search only filtered if the value is negative ('> -10' => '> -100' will ignore hidden rows)
861
871
  !(/(>=?\s*-\d)/.test(val) || /(<=?\s*\d)/.test(val)) &&
862
872
  // if filtering using a select without a "filter-match" class (exact match) - fixes #593
863
- !( val !== '' && c.$filters && c.$filters.eq(indx).find('select').length && !c.$headers.filter('[data-column="' + indx + '"]:last').hasClass('filter-match') );
873
+ !( val !== '' && c.$filters && c.$filters.eq(indx).find('select').length && !c.$headerIndexed[indx].hasClass('filter-match') );
864
874
  }
865
875
  }
866
876
  notFiltered = $rows.not('.' + wo.filter_filteredRow).length;
867
877
  // can't search when all rows are hidden - this happens when looking for exact matches
868
878
  if (searchFiltered && notFiltered === 0) { searchFiltered = false; }
869
879
  if (c.debug) {
870
- ts.log( "Searching through " + ( searchFiltered && notFiltered < len ? notFiltered : "all" ) + " rows" );
880
+ ts.log( 'Filter: Searching through ' + ( searchFiltered && notFiltered < len ? notFiltered : 'all' ) + ' rows' );
871
881
  }
872
882
  if (data.anyMatchFlag) {
873
883
  if (c.sortLocaleCompare) {
@@ -990,7 +1000,7 @@ ts.filter = {
990
1000
  // data.iFilter = case insensitive (if wo.filter_ignoreCase is true), data.filter = case sensitive
991
1001
  data.iFilter = wo.filter_ignoreCase ? (data.filter || '').toLocaleLowerCase() : data.filter;
992
1002
  fxn = ts.getColumnData( table, wo.filter_functions, columnIndex );
993
- $cell = c.$headers.filter('[data-column="' + columnIndex + '"]:last');
1003
+ $cell = c.$headerIndexed[columnIndex];
994
1004
  hasSelect = $cell.hasClass('filter-select');
995
1005
  if ( fxn || ( hasSelect && val ) ) {
996
1006
  if (fxn === true || hasSelect) {
@@ -998,10 +1008,10 @@ ts.filter = {
998
1008
  result = ($cell.hasClass('filter-match')) ? data.iExact.search(data.iFilter) >= 0 : data.filter === data.exact;
999
1009
  } else if (typeof fxn === 'function') {
1000
1010
  // filter callback( exact cell content, parser normalized content, filter input value, column index, jQuery row object )
1001
- result = fxn(data.exact, data.cache, data.filter, columnIndex, $rows.eq(rowIndex));
1011
+ result = fxn(data.exact, data.cache, data.filter, columnIndex, $rows.eq(rowIndex), c);
1002
1012
  } else if (typeof fxn[ffxn || data.filter] === 'function') {
1003
1013
  // selector option function
1004
- result = fxn[ffxn || data.filter](data.exact, data.cache, data.filter, columnIndex, $rows.eq(rowIndex));
1014
+ result = fxn[ffxn || data.filter](data.exact, data.cache, data.filter, columnIndex, $rows.eq(rowIndex), c);
1005
1015
  }
1006
1016
  } else {
1007
1017
  filterMatched = null;
@@ -1028,8 +1038,8 @@ ts.filter = {
1028
1038
  }
1029
1039
  }
1030
1040
  $rows.eq(rowIndex)
1031
- .toggle(showRow)
1032
- .toggleClass(wo.filter_filteredRow, !showRow);
1041
+ .toggleClass(wo.filter_filteredRow, !showRow)[0]
1042
+ .display = showRow ? '' : 'none';
1033
1043
  if (childRow.length) {
1034
1044
  childRow.toggleClass(wo.filter_filteredRow, !showRow);
1035
1045
  }
@@ -1055,7 +1065,7 @@ ts.filter = {
1055
1065
  },
1056
1066
  getOptionSource: function(table, column, onlyAvail) {
1057
1067
  table = $(table)[0];
1058
- var cts,
1068
+ var cts, indx, len,
1059
1069
  c = table.config,
1060
1070
  wo = c.widgetOptions,
1061
1071
  parsed = [],
@@ -1093,16 +1103,17 @@ ts.filter = {
1093
1103
  return $.inArray(value, arry) === indx;
1094
1104
  });
1095
1105
 
1096
- if (c.$headers.filter('[data-column="' + column + '"]:last').hasClass('filter-select-nosort')) {
1106
+ if (c.$headerIndexed[column].hasClass('filter-select-nosort')) {
1097
1107
  // unsorted select options
1098
1108
  return arry;
1099
1109
  } else {
1110
+ len = arry.length;
1100
1111
  // parse select option values
1101
- $.each(arry, function(i, v){
1112
+ for (indx = 0; indx < len; indx++) {
1102
1113
  // parse array data using set column parser; this DOES NOT pass the original
1103
1114
  // table cell to the parser format function
1104
- parsed.push({ t : v, p : c.parsers && c.parsers[column].format( v, table, [], column ) });
1105
- });
1115
+ parsed.push({ t : arry[indx], p : c.parsers && c.parsers[column].format( arry[indx], table, [], column ) });
1116
+ }
1106
1117
 
1107
1118
  // sort parsed select options
1108
1119
  cts = c.textSorter || '';
@@ -1124,9 +1135,10 @@ ts.filter = {
1124
1135
  });
1125
1136
  // rebuild arry from sorted parsed data
1126
1137
  arry = [];
1127
- $.each(parsed, function(i, v){
1128
- arry.push(v.t);
1129
- });
1138
+ len = parsed.length;
1139
+ for (indx = 0; indx < len; indx++) {
1140
+ arry.push( parsed[indx].t );
1141
+ }
1130
1142
  return arry;
1131
1143
  }
1132
1144
  },
@@ -1146,7 +1158,7 @@ ts.filter = {
1146
1158
  // check if has class filtered
1147
1159
  if (onlyAvail && row.className.match(wo.filter_filteredRow)) { continue; }
1148
1160
  // get non-normalized cell content
1149
- if (wo.filter_useParsedData || c.parsers[column].parsed || c.$headers.filter('[data-column="' + column + '"]:last').hasClass('filter-parsed')) {
1161
+ if (wo.filter_useParsedData || c.parsers[column].parsed || c.$headerIndexed[column].hasClass('filter-parsed')) {
1150
1162
  arry.push( '' + cache.normalized[rowIndex][column] );
1151
1163
  } else {
1152
1164
  cell = row.cells[column];
@@ -1165,7 +1177,7 @@ ts.filter = {
1165
1177
  var indx, val, txt, t, $filters, $filter,
1166
1178
  c = table.config,
1167
1179
  wo = c.widgetOptions,
1168
- node = c.$headers.filter('[data-column="' + column + '"]:last'),
1180
+ node = c.$headerIndexed[column],
1169
1181
  // t.data('placeholder') won't work in jQuery older than 1.4.3
1170
1182
  options = '<option value="">' + ( node.data('placeholder') || node.attr('data-placeholder') || wo.filter_placeholder.select || '' ) + '</option>',
1171
1183
  // Get curent filter value
@@ -1220,7 +1232,7 @@ ts.filter = {
1220
1232
  columns = c.columns;
1221
1233
  // build default select dropdown
1222
1234
  for (columnIndex = 0; columnIndex < columns; columnIndex++) {
1223
- $header = c.$headers.filter('[data-column="' + columnIndex + '"]:last');
1235
+ $header = c.$headerIndexed[columnIndex];
1224
1236
  noSelect = !($header.hasClass('filter-false') || $header.hasClass('parser-false'));
1225
1237
  // look for the filter-select class; build/update it if found
1226
1238
  if (($header.hasClass('filter-select') || ts.getColumnData( table, wo.filter_functions, columnIndex ) === true) && noSelect) {
@@ -29,7 +29,7 @@
29
29
  $headers = [];
30
30
  // set up variables
31
31
  for ( column = 0; column < c.columns; column++ ) {
32
- $headers[ column ] = c.$headers.filter('[data-column="' + column + '"]:last');
32
+ $headers[ column ] = c.$headerIndexed[ column ];
33
33
  formatter[ column ] = ts.getColumnData( c.table, wo.formatter_column, column ) || false;
34
34
  }
35
35
  // main loop
@@ -1,4 +1,4 @@
1
- /*! tablesorter Grouping widget - updated 10/26/2014 (v2.18.0)
1
+ /*! tablesorter Grouping widget - updated 3/5/2015 (v2.21.0) *//*
2
2
  * Requires tablesorter v2.8+ and jQuery 1.7+
3
3
  * by Rob Garrison
4
4
  */
@@ -66,12 +66,12 @@ ts.grouping = {
66
66
  // clear pager saved spacer height (in case the rows are collapsed)
67
67
  c.$table.data('pagerSavedHeight', 0);
68
68
  }
69
- if (column >= 0 && !c.$headers.filter('[data-column="' + column + '"]:last').hasClass('group-false')) {
69
+ if (column >= 0 && !c.$headerIndexed[column].hasClass('group-false')) {
70
70
  wo.group_currentGroup = ''; // save current groups
71
71
  wo.group_currentGroups = {};
72
72
 
73
73
  // group class finds "group-{word/separator/letter/number/date/false}-{optional:#/year/month/day/week/time}"
74
- groupClass = (c.$headers.filter('[data-column="' + column + '"]:last').attr('class') || '').match(/(group-\w+(-\w+)?)/g);
74
+ groupClass = (c.$headerIndexed[column].attr('class') || '').match(/(group-\w+(-\w+)?)/g);
75
75
  // grouping = [ 'group', '{word/separator/letter/number/date/false}', '{#/year/month/day/week/time}' ]
76
76
  grouping = groupClass ? groupClass[0].split('-') : ['group','letter',1]; // default to letter 1
77
77
 
@@ -96,15 +96,15 @@ ts.grouping = {
96
96
  if ( $rows.eq(rowIndex).is(':visible') ) {
97
97
  // fixes #438
98
98
  if (ts.grouping.types[grouping[1]]) {
99
- currentGroup = norm_rows[rowIndex] ?
100
- ts.grouping.types[grouping[1]]( c, c.$headers.filter('[data-column="' + column + '"]:last'), norm_rows[rowIndex][column], /date/.test(groupClass) ?
99
+ currentGroup = norm_rows[rowIndex] ?
100
+ ts.grouping.types[grouping[1]]( c, c.$headerIndexed[column], norm_rows[rowIndex][column], /date/.test(groupClass) ?
101
101
  grouping[2] : parseInt(grouping[2] || 1, 10) || 1, group, lang ) : currentGroup;
102
102
  if (group !== currentGroup) {
103
103
  group = currentGroup;
104
104
  // show range if number > 1
105
105
  if (grouping[1] === 'number' && grouping[2] > 1 && currentGroup !== '') {
106
106
  currentGroup += ' - ' + (parseInt(currentGroup, 10) +
107
- ((parseInt(grouping[2],10) - 1) * (c.$headers.filter('[data-column="' + column + '"]:last').hasClass(ts.css.sortAsc) ? 1 : -1)));
107
+ ((parseInt(grouping[2],10) - 1) * (c.$headerIndexed[column].hasClass(ts.css.sortAsc) ? 1 : -1)));
108
108
  }
109
109
  if ($.isFunction(wo.group_formatter)) {
110
110
  currentGroup = wo.group_formatter((currentGroup || '').toString(), column, table, c, wo) || currentGroup;
@@ -139,7 +139,7 @@ ts.grouping = {
139
139
  }
140
140
  }
141
141
  }
142
- if (wo.group_saveGroups && wo.group_currentGroups[wo.group_currentGroup].length) {
142
+ if (wo.group_saveGroups && wo.group_currentGroups.length && wo.group_currentGroups[wo.group_currentGroup].length) {
143
143
  name = $row.find('.group-name').text().toLowerCase();
144
144
  isHidden = $.inArray( name, wo.group_currentGroups[wo.group_currentGroup] ) > -1;
145
145
  $row.toggleClass('collapsed', isHidden);
@@ -219,6 +219,8 @@ ts.addWidget({
219
219
  group_callback : null, // function($cell, $rows, column, table){}, callback allowing modification of the group header labels
220
220
  group_complete : 'groupingComplete', // event triggered on the table when the grouping widget has finished work
221
221
 
222
+ // checkbox parser text used for checked/unchecked values
223
+ group_checkbox : [ 'checked', 'unchecked' ],
222
224
  // change these default date names based on your language preferences
223
225
  group_months : [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ],
224
226
  group_week : [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' ],