jquery-tablesorter 1.19.4 → 1.20.0

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