jquery-tablesorter 1.19.4 → 1.20.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 (25) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/jquery-tablesorter/version.rb +2 -2
  4. data/vendor/assets/javascripts/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.js +10 -10
  5. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.combined.js +210 -108
  6. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.js +151 -74
  7. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets.js +59 -34
  8. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-input-select.js +62 -32
  9. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-alignChar.js +1 -1
  10. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-build-table.js +1 -1
  11. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-columnSelector.js +2 -2
  12. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-editable.js +15 -12
  13. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter-type-insideRange.js +6 -5
  14. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter.js +53 -28
  15. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-grouping.js +1 -1
  16. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-math.js +154 -76
  17. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-pager.js +9 -9
  18. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-print.js +2 -2
  19. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-resizable.js +3 -3
  20. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-scroller.js +1 -1
  21. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-sort2Hash.js +2 -2
  22. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-staticRow.js +1 -1
  23. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-stickyHeaders.js +2 -2
  24. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-view.js +2 -2
  25. metadata +2 -2
@@ -4,7 +4,7 @@
4
4
  ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██▀▀ ▀▀▀██
5
5
  █████▀ ▀████▀ ██ ██ ▀████▀ ██ ██ ██ ██ ▀████▀ █████▀ ██ ██ █████▀
6
6
  */
7
- /*! tablesorter (FORK) - updated 11-22-2015 (v2.24.6)*/
7
+ /*! tablesorter (FORK) - updated 12-13-2015 (v2.25.0)*/
8
8
  /* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */
9
9
  (function(factory) {
10
10
  if (typeof define === 'function' && define.amd) {
@@ -372,7 +372,7 @@
372
372
 
373
373
  })(jQuery);
374
374
 
375
- /*! Widget: filter - updated 11/10/2015 (v2.24.4) *//*
375
+ /*! Widget: filter - updated 12/13/2015 (v2.25.0) *//*
376
376
  * Requires tablesorter v2.8+ and jQuery 1.7+
377
377
  * by Rob Garrison
378
378
  */
@@ -582,7 +582,7 @@
582
582
  table = c.table,
583
583
  parsed = data.parsed[ data.index ],
584
584
  query = ts.formatFloat( data.iFilter.replace( tsfRegex.operators, '' ), table ),
585
- parser = c.parsers[ data.index ],
585
+ parser = c.parsers[ data.index ] || {},
586
586
  savedSearch = query;
587
587
  // parse filter value in case we're comparing numbers ( dates )
588
588
  if ( parsed || parser.type === 'numeric' ) {
@@ -722,6 +722,7 @@
722
722
 
723
723
  var options, string, txt, $header, column, filters, val, fxn, noSelect;
724
724
  c.$table.addClass( 'hasFilters' );
725
+ c.lastSearch = [];
725
726
 
726
727
  // define timers so using clearTimeout won't cause an undefined error
727
728
  wo.filter_searchTimer = null;
@@ -804,7 +805,7 @@
804
805
  if ( wo.filter_reset instanceof $ ) {
805
806
  // reset contains a jQuery object, bind to it
806
807
  wo.filter_reset.click( function() {
807
- c.$table.trigger( 'filterReset' );
808
+ c.$table.triggerHandler( 'filterReset' );
808
809
  });
809
810
  } else if ( $( wo.filter_reset ).length ) {
810
811
  // reset is a jQuery selector, use event delegation
@@ -812,7 +813,7 @@
812
813
  .undelegate( wo.filter_reset, 'click' + c.namespace + 'filter' )
813
814
  .delegate( wo.filter_reset, 'click' + c.namespace + 'filter', function() {
814
815
  // trigger a reset event, so other functions ( filter_formatter ) know when to reset
815
- c.$table.trigger( 'filterReset' );
816
+ c.$table.triggerHandler( 'filterReset' );
816
817
  });
817
818
  }
818
819
  }
@@ -914,7 +915,7 @@
914
915
  ts.setFilters( table, filters, true );
915
916
  }
916
917
  }
917
- c.$table.trigger( 'filterFomatterUpdate' );
918
+ c.$table.triggerHandler( 'filterFomatterUpdate' );
918
919
  // trigger init after setTimeout to prevent multiple filterStart/End/Init triggers
919
920
  setTimeout( function() {
920
921
  if ( !wo.filter_initialized ) {
@@ -924,7 +925,7 @@
924
925
  });
925
926
  // if filter widget is added after pager has initialized; then set filter init flag
926
927
  if ( c.pager && c.pager.initialized && !wo.filter_initialized ) {
927
- c.$table.trigger( 'filterFomatterUpdate' );
928
+ c.$table.triggerHandler( 'filterFomatterUpdate' );
928
929
  setTimeout( function() {
929
930
  tsf.filterInitComplete( c );
930
931
  }, 100 );
@@ -947,7 +948,7 @@
947
948
  count = 0,
948
949
  completed = function() {
949
950
  wo.filter_initialized = true;
950
- c.$table.trigger( 'filterInit', c );
951
+ c.$table.triggerHandler( 'filterInit', c );
951
952
  tsf.findRows( c.table, c.$table.data( 'lastSearch' ) || [] );
952
953
  };
953
954
  if ( $.isEmptyObject( wo.filter_formatter ) ) {
@@ -1002,7 +1003,7 @@
1002
1003
  for ( indx = 0; indx <= c.columns; indx++ ) {
1003
1004
  // include data-column='all' external filters
1004
1005
  col = indx === c.columns ? 'all' : indx;
1005
- filters[indx] = $filters
1006
+ filters[ indx ] = $filters
1006
1007
  .filter( '[data-column="' + col + '"]' )
1007
1008
  .attr( wo.filter_defaultAttrib ) || filters[indx] || '';
1008
1009
  }
@@ -1024,11 +1025,12 @@
1024
1025
  buildFilter = '<tr role="row" class="' + tscss.filterRow + ' ' + c.cssIgnoreRow + '">';
1025
1026
  for ( column = 0; column < columns; column++ ) {
1026
1027
  if ( c.$headerIndexed[ column ].length ) {
1027
- buildFilter += '<td data-column="' + column + '"';
1028
1028
  // account for entire column set with colspan. See #1047
1029
1029
  tmp = c.$headerIndexed[ column ] && c.$headerIndexed[ column ][0].colSpan || 0;
1030
1030
  if ( tmp > 1 ) {
1031
- buildFilter += ' colspan="' + tmp + '"';
1031
+ buildFilter += '<td data-column="' + column + '-' + ( column + tmp - 1 ) + '" colspan="' + tmp + '"';
1032
+ } else {
1033
+ buildFilter += '<td data-column="' + column + '"';
1032
1034
  }
1033
1035
  if ( arry ) {
1034
1036
  buildFilter += ( cellFilter[ column ] ? ' class="' + cellFilter[ column ] + '"' : '' );
@@ -1047,7 +1049,8 @@
1047
1049
  // assuming last cell of a column is the main column
1048
1050
  $header = c.$headerIndexed[ column ];
1049
1051
  if ( $header && $header.length ) {
1050
- $filter = c.$filters.filter( '[data-column="' + column + '"]' );
1052
+ // $filter = c.$filters.filter( '[data-column="' + column + '"]' );
1053
+ $filter = tsf.getColumnElm( c, c.$filters, column );
1051
1054
  ffxn = ts.getColumnData( table, wo.filter_functions, column );
1052
1055
  makeSelect = ( wo.filter_functions && ffxn && typeof ffxn !== 'function' ) ||
1053
1056
  $header.hasClass( 'filter-select' );
@@ -1087,7 +1090,8 @@
1087
1090
  name = ( $.isArray( wo.filter_cssFilter ) ?
1088
1091
  ( typeof wo.filter_cssFilter[column] !== 'undefined' ? wo.filter_cssFilter[column] || '' : '' ) :
1089
1092
  wo.filter_cssFilter ) || '';
1090
- buildFilter.addClass( tscss.filter + ' ' + name ).attr( 'data-column', column );
1093
+ // copy data-column from table cell (it will include colspan)
1094
+ buildFilter.addClass( tscss.filter + ' ' + name ).attr( 'data-column', $filter.attr( 'data-column' ) );
1091
1095
  if ( disabled ) {
1092
1096
  buildFilter.attr( 'placeholder', '' ).addClass( tscss.filterDisabled )[0].disabled = true;
1093
1097
  }
@@ -1195,7 +1199,7 @@
1195
1199
  // show/hide filter row as needed
1196
1200
  c.$table
1197
1201
  .find( '.' + tscss.filterRow )
1198
- .trigger( combinedFilters === '' ? 'mouseleave' : 'mouseenter' );
1202
+ .triggerHandler( combinedFilters === '' ? 'mouseleave' : 'mouseenter' );
1199
1203
  }
1200
1204
  // return if the last search is the same; but filter === false when updating the search
1201
1205
  // see example-widget-filter.html filter toggle buttons
@@ -1206,6 +1210,8 @@
1206
1210
  c.lastCombinedFilter = null;
1207
1211
  c.lastSearch = [];
1208
1212
  }
1213
+ // define filter inside it is false
1214
+ filters = filters || [];
1209
1215
  // convert filters to strings - see #1070
1210
1216
  filters = Array.prototype.map ?
1211
1217
  filters.map( String ) :
@@ -1213,7 +1219,7 @@
1213
1219
  filters.join( '\u0000' ).split( '\u0000' );
1214
1220
 
1215
1221
  if ( wo.filter_initialized ) {
1216
- c.$table.trigger( 'filterStart', [ filters ] );
1222
+ c.$table.triggerHandler( 'filterStart', [ filters ] );
1217
1223
  }
1218
1224
  if ( c.showProcessing ) {
1219
1225
  // give it time for the processing icon to kick in
@@ -1294,22 +1300,18 @@
1294
1300
  }
1295
1301
  return $input || $();
1296
1302
  },
1297
- multipleColumns: function( c, $input ) {
1303
+ findRange: function( c, val, ignoreRanges ) {
1298
1304
  // look for multiple columns '1-3,4-6,8' in data-column
1299
1305
  var temp, ranges, range, start, end, singles, i, indx, len,
1300
- wo = c.widgetOptions,
1301
- // only target 'all' column inputs on initialization
1302
- // & don't target 'all' column inputs if they don't exist
1303
- targets = wo.filter_initialized || !$input.filter( wo.filter_anyColumnSelector ).length,
1304
- columns = [],
1305
- val = $.trim( tsf.getLatestSearch( $input ).attr( 'data-column' ) || '' );
1306
- if ( /^[0-9]+$/.test(val)) {
1307
- return parseInt( val, 10 );
1306
+ columns = [];
1307
+ if ( /^[0-9]+$/.test( val ) ) {
1308
+ // always return an array
1309
+ return [ parseInt( val, 10 ) ];
1308
1310
  }
1309
1311
  // process column range
1310
- if ( targets && /-/.test( val ) ) {
1312
+ if ( !ignoreRanges && /-/.test( val ) ) {
1311
1313
  ranges = val.match( /(\d+)\s*-\s*(\d+)/g );
1312
- len = ranges.length;
1314
+ len = ranges ? ranges.length : 0;
1313
1315
  for ( indx = 0; indx < len; indx++ ) {
1314
1316
  range = ranges[indx].split( /\s*-\s*/ );
1315
1317
  start = parseInt( range[0], 10 ) || 0;
@@ -1328,7 +1330,7 @@
1328
1330
  }
1329
1331
  }
1330
1332
  // process single columns
1331
- if ( targets && /,/.test( val ) ) {
1333
+ if ( !ignoreRanges && /,/.test( val ) ) {
1332
1334
  singles = val.split( /\s*,\s*/ );
1333
1335
  len = singles.length;
1334
1336
  for ( i = 0; i < len; i++ ) {
@@ -1348,6 +1350,23 @@
1348
1350
  }
1349
1351
  return columns;
1350
1352
  },
1353
+ getColumnElm: function( c, $elements, column ) {
1354
+ // data-column may contain multiple columns '1-3,5-6,8'
1355
+ // replaces: c.$filters.filter( '[data-column="' + column + '"]' );
1356
+ return $elements.filter( function() {
1357
+ var cols = tsf.findRange( c, $( this ).attr( 'data-column' ) );
1358
+ return $.inArray( column, cols ) > -1;
1359
+ });
1360
+ },
1361
+ multipleColumns: function( c, $input ) {
1362
+ // look for multiple columns '1-3,4-6,8' in data-column
1363
+ var wo = c.widgetOptions,
1364
+ // only target 'all' column inputs on initialization
1365
+ // & don't target 'all' column inputs if they don't exist
1366
+ targets = wo.filter_initialized || !$input.filter( wo.filter_anyColumnSelector ).length,
1367
+ val = $.trim( tsf.getLatestSearch( $input ).attr( 'data-column' ) || '' );
1368
+ return tsf.findRange( c, val, !targets );
1369
+ },
1351
1370
  processTypes: function( c, data, vars ) {
1352
1371
  var ffxn,
1353
1372
  filterMatched = null,
@@ -1461,6 +1480,11 @@
1461
1480
  data.filter = ts.replaceAccents( data.filter );
1462
1481
  }
1463
1482
 
1483
+ // replace column specific default filters - see #1088
1484
+ if ( wo.filter_defaultFilter && tsfRegex.iQuery.test( vars.defaultColFilter[ columnIndex ] ) ) {
1485
+ data.filter = tsf.defaultFilter( data.filter, vars.defaultColFilter[ columnIndex ] );
1486
+ }
1487
+
1464
1488
  // data.iFilter = case insensitive ( if wo.filter_ignoreCase is true ),
1465
1489
  // data.filter = case sensitive
1466
1490
  data.iFilter = wo.filter_ignoreCase ? ( data.filter || '' ).toLowerCase() : data.filter;
@@ -1749,7 +1773,8 @@
1749
1773
  console.log( 'Completed filter widget search' + ts.benchmark(time) );
1750
1774
  }
1751
1775
  if ( wo.filter_initialized ) {
1752
- c.$table.trigger( 'filterEnd', c );
1776
+ c.$table.triggerHandler( 'filterBeforeEnd', c );
1777
+ c.$table.triggerHandler( 'filterEnd', c );
1753
1778
  }
1754
1779
  setTimeout( function() {
1755
1780
  ts.applyWidget( c.table ); // make sure zebra widget is applied
@@ -2114,7 +2139,7 @@
2114
2139
  c.lastCombinedFilter = null;
2115
2140
  c.lastSearch = [];
2116
2141
  tsf.searching( c.table, filter, skipFirst );
2117
- c.$table.trigger( 'filterFomatterUpdate' );
2142
+ c.$table.triggerHandler( 'filterFomatterUpdate' );
2118
2143
  }
2119
2144
  return !!valid;
2120
2145
  };
@@ -2162,7 +2187,7 @@
2162
2187
  }
2163
2188
  }
2164
2189
  if ( headers.length && triggerEvent !== false ) {
2165
- c.$table.trigger( 'resize', [ headers ] );
2190
+ c.$table.triggerHandler( 'resize', [ headers ] );
2166
2191
  }
2167
2192
  wo.resize_flag = false;
2168
2193
  };
@@ -2389,7 +2414,7 @@
2389
2414
  }
2390
2415
  }
2391
2416
 
2392
- $table.trigger('stickyHeadersInit');
2417
+ $table.triggerHandler('stickyHeadersInit');
2393
2418
 
2394
2419
  },
2395
2420
  remove: function(table, c, wo) {
@@ -2717,7 +2742,7 @@
2717
2742
  }
2718
2743
  vars.mouseXPosition = event.pageX;
2719
2744
  // dynamically update sticky header widths
2720
- c.$table.trigger('stickyHeadersUpdate');
2745
+ c.$table.triggerHandler('stickyHeadersUpdate');
2721
2746
  },
2722
2747
 
2723
2748
  stopResize : function( c, wo ) {
@@ -2731,7 +2756,7 @@
2731
2756
  vars.mouseXPosition = 0;
2732
2757
  vars.$target = vars.$next = null;
2733
2758
  // will update stickyHeaders, just in case, see #912
2734
- c.$table.trigger('stickyHeadersUpdate');
2759
+ c.$table.triggerHandler('stickyHeadersUpdate');
2735
2760
  }
2736
2761
  };
2737
2762
 
@@ -2793,7 +2818,7 @@
2793
2818
  }
2794
2819
 
2795
2820
  // reset stickyHeader widths
2796
- c.$table.trigger( 'stickyHeadersUpdate' );
2821
+ c.$table.triggerHandler( 'stickyHeadersUpdate' );
2797
2822
  if ( ts.storage && !refreshing ) {
2798
2823
  ts.storage( this, ts.css.resizableStorage, {} );
2799
2824
  }
@@ -1,4 +1,4 @@
1
- /*! Parser: input & select - updated 11/22/2015 (v2.24.6) *//*
1
+ /*! Parser: input & select - updated 12/13/2015 (v2.25.0) *//*
2
2
  * for jQuery 1.7+ & tablesorter 2.7.11+
3
3
  * Demo: http://mottie.github.com/tablesorter/docs/example-widget-grouping.html
4
4
  */
@@ -54,23 +54,12 @@
54
54
  },
55
55
  format : function( txt, table, cell, cellIndex ) {
56
56
  var $cell = $( cell ),
57
- $row = $cell.closest( 'tr' ),
58
57
  wo = table.config.widgetOptions,
59
- checkedClass = table.config.checkboxClass || 'checked',
60
58
  // returning plain language here because this is what is shown in the
61
59
  // group headers - change it as desired
62
60
  status = wo.group_checkbox ? wo.group_checkbox : [ 'checked', 'unchecked' ],
63
61
  $input = $cell.find( 'input[type="checkbox"]' ),
64
62
  isChecked = $input.length ? $input[ 0 ].checked : '';
65
- // adding class to row, indicating that a checkbox is checked; includes
66
- // a column index in case more than one checkbox happens to be in a row
67
- $row.toggleClass( checkedClass + '-' + cellIndex, isChecked );
68
- if ( isChecked ) {
69
- $row.addClass( checkedClass );
70
- } else if ( $row.length && !( $row[0].className || '' ).match( checkedClass + '-' ) ) {
71
- // don't remove checked class if other columns have a check
72
- $row.removeClass( checkedClass );
73
- }
74
63
  return $input.length ? status[ isChecked ? 0 : 1 ] : txt;
75
64
  },
76
65
  parsed : true, // filter widget flag
@@ -127,6 +116,34 @@
127
116
  // if this code interferes somehow, target the specific table $('#mytable'), instead of $('table')
128
117
  $( function() {
129
118
  if ( !$.fn.on ) { return; }
119
+ var toggleRowClass = function( $row, checkboxClass, indx, isChecked ) {
120
+ // adding class to row, indicating that a checkbox is checked; includes
121
+ // a column index in case more than one checkbox happens to be in a row
122
+ $row.toggleClass( checkboxClass + '-' + indx, isChecked );
123
+ // don't remove checked class if other columns have a check
124
+ if ( ( $row[0].className || '' ).match( checkboxClass + '-' ) ) {
125
+ $row.addClass( checkboxClass );
126
+ } else {
127
+ $row.removeClass( checkboxClass );
128
+ }
129
+ },
130
+ updateHeaderCheckbox = function( $table, checkboxClass ) {
131
+ var $rows = $table.children( 'tbody' ).children( ':visible' ), // (include child rows?)
132
+ len = $rows.length;
133
+ // set indeterminate state on header checkbox
134
+ $table.children( 'thead' ).find( 'input[type="checkbox"]' ).each( function() {
135
+ var column = $( this ).closest( 'td, th' ).attr( 'data-column' ),
136
+ vis = $rows.filter( '.' + checkboxClass + '-' + column ).length,
137
+ allChecked = vis === len;
138
+ if ( vis === 0 || allChecked ) {
139
+ this.checked = allChecked;
140
+ this.indeterminate = false;
141
+ } else {
142
+ this.indeterminate = true;
143
+ }
144
+ });
145
+ };
146
+
130
147
  $( 'table' ).on( 'tablesorter-initialized updateComplete', function() {
131
148
  this.tablesorterBusy = false;
132
149
  var namespace = '.parser-forms';
@@ -159,7 +176,7 @@
159
176
  if ( event.type === 'change' ||
160
177
  ( event.type === 'keyup' && event.which === 13 &&
161
178
  ( event.target.nodeName === 'INPUT' || event.target.nodeName === 'TEXTAREA' && event.altKey ) ) ) {
162
- var undef,
179
+ var undef, checkboxClass,
163
180
  $target = $( event.target ),
164
181
  isCheckbox = event.target.type === 'checkbox',
165
182
  $cell = $target.closest( 'td' ),
@@ -169,9 +186,18 @@
169
186
  busy = $table.length && $table[ 0 ].tablesorterBusy,
170
187
  $hdr = c && c.$headerIndexed && c.$headerIndexed[ indx ] || [],
171
188
  val = isCheckbox ? event.target.checked : $target.val();
172
- // abort if not a tablesorter table, or busy, or don't use updateCell if column is set
173
- // to 'sorter-false' and 'filter-false', or column is set to 'parser-false'
174
- if ( $.isEmptyObject( c ) || busy !== false || $hdr.length && ( $hdr.hasClass( 'parser-false' ) ||
189
+ // abort if not a tablesorter table, or busy
190
+ if ( $.isEmptyObject( c ) || busy !== false ) {
191
+ return;
192
+ }
193
+ if ( isCheckbox ) {
194
+ checkboxClass = c.checkboxClass || 'checked';
195
+ toggleRowClass( $cell.closest( 'tr' ), checkboxClass, indx, val );
196
+ updateHeaderCheckbox( $table, checkboxClass );
197
+ }
198
+ // don't use updateCell if column is set to 'sorter-false' and 'filter-false',
199
+ // or column is set to 'parser-false'
200
+ if ( $hdr.length && ( $hdr.hasClass( 'parser-false' ) ||
175
201
  ( $hdr.hasClass( 'sorter-false' ) && $hdr.hasClass( 'filter-false' ) ) ) ||
176
202
  // table already updating; get out of here, we might be in an endless loop (in IE)! See #971
177
203
  ( event.type === 'change' && c.table.isUpdating ) ) {
@@ -201,20 +227,8 @@
201
227
  if ( !$.isEmptyObject( c ) ) {
202
228
  this.tablesorterBusy = true;
203
229
  checkboxClass = c && c.checkboxClass || 'checked';
204
- $rows = $table.children( 'tbody' ).children( ':visible' ); // (include child rows?)
205
- len = $rows.length;
206
230
  // set indeterminate state on header checkbox
207
- $( this ).children( 'thead' ).find( 'input[type="checkbox"]' ).each( function() {
208
- var column = $( this ).closest( 'td, th' ).attr( 'data-column' ),
209
- vis = $rows.filter( '.' + checkboxClass + '-' + column ).length,
210
- allChecked = vis === len;
211
- if ( vis === 0 || allChecked ) {
212
- this.checked = allChecked;
213
- this.indeterminate = false;
214
- } else {
215
- this.indeterminate = true;
216
- }
217
- });
231
+ updateHeaderCheckbox( $table, checkboxClass );
218
232
  this.tablesorterBusy = false;
219
233
  }
220
234
  })
@@ -222,13 +236,14 @@
222
236
  .off( namespace )
223
237
  // modified from http://jsfiddle.net/abkNM/6163/
224
238
  .on( 'change' + namespace, 'input[type="checkbox"]', function( event ) {
225
- var undef, onlyVisible, column, $target,
239
+ var undef, onlyVisible, column, $target, isParsed, $row, checkboxClass,
226
240
  $checkbox = $( this ),
227
241
  $table = $checkbox.closest( 'table' ),
228
242
  c = $table.length && $table[ 0 ].config,
229
243
  isChecked = this.checked;
230
244
  if ( $table.length && c && !$table[ 0 ].tablesorterBusy ) {
231
245
  column = parseInt( $checkbox.closest( 'td, th' ).attr( 'data-column' ), 10 );
246
+ isParsed = c.parsers[ column ].id === 'checkbox';
232
247
  onlyVisible = $table.length && c.checkboxVisible;
233
248
  $table[ 0 ].tablesorterBusy = true; // prevent "change" event from calling updateCell numerous times (see #971)
234
249
  $target = $table
@@ -237,10 +252,25 @@
237
252
  .children( ':nth-child(' + ( column + 1 ) + ')' )
238
253
  .find( 'input[type="checkbox"]' )
239
254
  .prop( 'checked', isChecked );
240
- $.tablesorter.update( c, undef, function() {
255
+ if ( !isParsed ) {
256
+ // add checkbox class names
257
+ checkboxClass = c.checkboxClass || 'checked';
258
+ $target.each(function(){
259
+ $row = $(this).closest('tr');
260
+ toggleRowClass( $(this).closest( 'tr' ), checkboxClass, column, isChecked );
261
+ });
262
+ updateHeaderCheckbox( $table, checkboxClass );
241
263
  updateServer( event, $table, $target );
242
264
  $table[ 0 ].tablesorterBusy = false;
243
- });
265
+ } else {
266
+ // only update cache if checkboxes are being sorted
267
+ $.tablesorter.update( c, undef, function() {
268
+ updateServer( event, $table, $target );
269
+ $table[ 0 ].tablesorterBusy = false;
270
+ });
271
+ }
272
+ // needed for IE8
273
+ return true;
244
274
  }
245
275
  // update already going on, don't do anything!
246
276
  return false;
@@ -132,7 +132,7 @@
132
132
  format : function(table, c, wo){
133
133
  // reinitialize in case table is empty when first initialized
134
134
  if (!wo.alignChar_initialized) {
135
- c.$table.trigger('refreshAlign');
135
+ c.$table.triggerHandler('refreshAlign');
136
136
  }
137
137
  },
138
138
  remove : function(table, c, wo, refreshing){
@@ -192,7 +192,7 @@
192
192
  };
193
193
 
194
194
  bt.buildComplete = function(table, wo){
195
- $(table).trigger(wo.build_complete);
195
+ $(table).triggerHandler(wo.build_complete);
196
196
  ts.setup(table, table.config);
197
197
  };
198
198