jquery-tablesorter 1.15.0 → 1.16.0

Sign up to get free protection for your applications and to get access to all the features.
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' ],