jquery-tablesorter 1.16.5 → 1.17.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 (32) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/lib/jquery-tablesorter/version.rb +1 -1
  4. data/vendor/assets/javascripts/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.js +38 -27
  5. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.combined.js +1104 -839
  6. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.js +167 -123
  7. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets.js +938 -717
  8. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date.js +5 -5
  9. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-globalize.js +46 -0
  10. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-input-select.js +96 -72
  11. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-named-numbers.js +6 -5
  12. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-network.js +26 -17
  13. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-columns.js +1 -1
  14. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-editable.js +95 -42
  15. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter.js +921 -700
  16. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-grouping.js +5 -3
  17. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-math.js +22 -20
  18. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-output.js +7 -5
  19. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-pager.js +40 -29
  20. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-resizable.js +6 -6
  21. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-saveSort.js +1 -1
  22. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-scroller.js +53 -31
  23. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-stickyHeaders.js +1 -1
  24. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-storage.js +1 -1
  25. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-uitheme.js +1 -1
  26. data/vendor/assets/stylesheets/jquery-tablesorter/theme.black-ice.css +2 -1
  27. data/vendor/assets/stylesheets/jquery-tablesorter/theme.blue.css +2 -1
  28. data/vendor/assets/stylesheets/jquery-tablesorter/theme.bootstrap.css +2 -1
  29. data/vendor/assets/stylesheets/jquery-tablesorter/theme.bootstrap_2.css +8 -6
  30. data/vendor/assets/stylesheets/jquery-tablesorter/theme.dark.css +2 -1
  31. data/vendor/assets/stylesheets/jquery-tablesorter/theme.default.css +1 -1
  32. metadata +3 -2
@@ -110,7 +110,7 @@ ts.grouping = {
110
110
  currentGroup = wo.group_formatter((currentGroup || '').toString(), column, table, c, wo) || currentGroup;
111
111
  }
112
112
  $rows.eq(rowIndex).before('<tr class="group-header ' + c.selectorRemove.slice(1) +
113
- '" unselectable="on"><td colspan="' +
113
+ '" unselectable="on"' + ( c.tabIndex ? ' tabindex="0"' : '' ) + '><td colspan="' +
114
114
  c.columns + '">' + (wo.group_collapsible ? '<i/>' : '') + '<span class="group-name">' +
115
115
  currentGroup + '</span><span class="group-count"></span></td></tr>');
116
116
  if (wo.group_saveGroups && !savedGroup && wo.group_collapsed && wo.group_collapsible) {
@@ -157,13 +157,15 @@ ts.grouping = {
157
157
  if (wo.group_collapsible) {
158
158
  wo.group_currentGroups = [];
159
159
  // .on() requires jQuery 1.7+
160
- c.$table.on('click toggleGroup', 'tr.group-header', function(event){
160
+ c.$table.on('click toggleGroup keyup', 'tr.group-header', function(event){
161
161
  event.stopPropagation();
162
+ // pressing enter will toggle the group
163
+ if (event.type === 'keyup' && event.which !== 13) { return; }
162
164
  var isCollapsed, $groups, indx,
163
165
  $this = $(this),
164
166
  name = $this.find('.group-name').text().toLowerCase();
165
167
  // use shift-click to toggle ALL groups
166
- if (event.type === 'click' && event.shiftKey) {
168
+ if (event.shiftKey && (event.type === 'click' || event.type ==='keyup')) {
167
169
  $this.siblings('.group-header').trigger('toggleGroup');
168
170
  }
169
171
  $this.toggleClass('collapsed');
@@ -1,10 +1,10 @@
1
- /*! Widget: math - updated 2/9/2015 (v2.19.1) *//*
1
+ /*! Widget: math - updated 5/17/2015 (v2.22.0) *//*
2
2
  * Requires tablesorter v2.16+ and jQuery 1.7+
3
3
  * by Rob Garrison
4
4
  */
5
5
  /*jshint browser:true, jquery:true, unused:false */
6
6
  /*global jQuery: false */
7
- ;(function($){
7
+ ;(function($) {
8
8
  "use strict";
9
9
 
10
10
  var ts = $.tablesorter,
@@ -20,10 +20,10 @@
20
20
  c = table.config,
21
21
  arry = [],
22
22
  $row = $el.closest('tr'),
23
- $cells = $row.children();
23
+ $cells = $row.children().not('[' + dataAttrib + '=ignore]');
24
24
  if (!$row.hasClass(wo.filter_filteredRow || 'filtered')) {
25
25
  if (wo.math_ignore.length) {
26
- $cells = $cells.not('[' + dataAttrib + '=ignore]').not('[data-column=' + wo.math_ignore.join('],[data-column=') + ']');
26
+ $cells = $cells.not('[data-column=' + wo.math_ignore.join('],[data-column=') + ']');
27
27
  }
28
28
  arry = $cells.not($el).map(function(){
29
29
  $t = $(this);
@@ -31,7 +31,7 @@
31
31
  if (typeof txt === "undefined") {
32
32
  txt = this.textContent || $t.text();
33
33
  }
34
- txt = ts.formatFloat(txt.replace(/[^\w,. \-()]/g, ""), table);
34
+ txt = ts.formatFloat(txt.replace(/[^\w,. \-()]/g, ""), table) || 0;
35
35
  return isNaN(txt) ? 0 : txt;
36
36
  }).get();
37
37
  }
@@ -39,7 +39,7 @@
39
39
  },
40
40
 
41
41
  // get all of the column numerical values in an arry
42
- getColumn : function(table, wo, $el, type, dataAttrib){
42
+ getColumn : function(table, wo, $el, type, dataAttrib) {
43
43
  var i, txt, $t, len, mathAbove,
44
44
  arry = [],
45
45
  c = table.config,
@@ -65,7 +65,7 @@
65
65
  if (typeof txt === "undefined") {
66
66
  txt = $t[0].textContent || $t.text();
67
67
  }
68
- txt = ts.formatFloat(txt.replace(/[^\w,. \-()]/g, ""), table);
68
+ txt = ts.formatFloat(txt.replace(/[^\w,. \-()]/g, ""), table) || 0;
69
69
  arry.push(isNaN(txt) ? 0 : txt);
70
70
  }
71
71
  }
@@ -79,7 +79,8 @@
79
79
  if (typeof txt === "undefined") {
80
80
  txt = ($t[0] ? $t[0].textContent : '') || $t.text();
81
81
  }
82
- txt = ts.formatFloat(txt.replace(/[^\w,. \-()]/g, ""), table);
82
+ // isNaN('') => false
83
+ txt = ts.formatFloat(txt.replace(/[^\w,. \-()]/g, ""), table) || 0;
83
84
  arry.push(isNaN(txt) ? 0 : txt);
84
85
  }
85
86
  });
@@ -88,7 +89,7 @@
88
89
  },
89
90
 
90
91
  // get all of the column numerical values in an arry
91
- getAll : function(table, wo, dataAttrib){
92
+ getAll : function(table, wo, dataAttrib) {
92
93
  var txt, $t, col,
93
94
  arry = [],
94
95
  c = table.config,
@@ -104,7 +105,7 @@
104
105
  if (typeof txt === "undefined") {
105
106
  txt = ($t[0] ? $t[0].textContent : '') || $t.text();
106
107
  }
107
- txt = ts.formatFloat(txt.replace(/[^\w,. \-()]/g, ""), table);
108
+ txt = ts.formatFloat(txt.replace(/[^\w,. \-()]/g, ""), table) || 0;
108
109
  arry.push(isNaN(txt) ? 0 : txt);
109
110
  }
110
111
  });
@@ -113,7 +114,7 @@
113
114
  return arry;
114
115
  },
115
116
 
116
- recalculate : function(table, c, wo, init){
117
+ recalculate : function(table, c, wo, init) {
117
118
  if (c && (!wo.math_isUpdating || init)) {
118
119
 
119
120
  // add data-column attributes to all table cells
@@ -364,7 +365,7 @@
364
365
  return Math.sqrt( vars );
365
366
  },
366
367
  // standard deviation (population)
367
- stdevp : function(arry){
368
+ stdevp : function(arry) {
368
369
  var varp = ts.equations.variance(arry, true);
369
370
  return Math.sqrt( varp );
370
371
  }
@@ -391,28 +392,29 @@
391
392
  math_suffix : '',
392
393
  math_event : 'recalculate'
393
394
  },
394
- init : function(table, thisWidget, c, wo){
395
+ init : function(table, thisWidget, c, wo) {
395
396
  c.$table
396
397
  .off( (math.events + ' updateComplete.tsmath ' + wo.math_event).replace(/\s+/g, ' ') )
397
- .on(math.events + ' ' + wo.math_event, function(e){
398
+ .on(math.events + ' ' + wo.math_event, function(e) {
398
399
  var init = e.type === 'tablesorter-initialized';
399
- if (e.type === 'updateAll') {
400
- // redo data-column indexes in case columns were rearranged
401
- ts.computeColumnIndex( c.$table.children('tbody').children() );
402
- } else if (!wo.math_isUpdating || init) {
400
+ if ( !wo.math_isUpdating || init ) {
401
+ if ( !/filter/.test(e.type) ) {
402
+ // redo data-column indexes on update
403
+ ts.computeColumnIndex( c.$table.children('tbody').children() );
404
+ }
403
405
  math.recalculate( table, c, wo, init );
404
406
  }
405
407
  })
406
408
  .on('updateComplete.tsmath', function(){
407
409
  setTimeout(function(){
408
410
  wo.math_isUpdating = false;
409
- }, 500);
411
+ }, 20);
410
412
  });
411
413
  wo.math_isUpdating = false;
412
414
  },
413
415
  // this remove function is called when using the refreshWidgets method or when destroying the tablesorter plugin
414
416
  // this function only applies to tablesorter v2.4+
415
- remove: function(table, c, wo, refreshing){
417
+ remove: function(table, c, wo, refreshing) {
416
418
  if (refreshing) { return; }
417
419
  $(table)
418
420
  .off( (math.events + ' updateComplete.tsmath ' + wo.math_event).replace(/\s+/g, ' ') )
@@ -1,4 +1,4 @@
1
- /*! Widget: output - updated 3/26/2015 (v2.21.3) *//*
1
+ /*! Widget: output - updated 5/17/2015 (v2.22.0) *//*
2
2
  * Requires tablesorter v2.8+ and jQuery 1.7+
3
3
  * Modified from:
4
4
  * HTML Table to CSV: http://www.kunalbabre.com/projects/table2CSV.php (License unknown?)
@@ -79,8 +79,8 @@ output = ts.output = {
79
79
  }
80
80
  }
81
81
 
82
- // don't include hidden columns
83
- if ( $this.css('display') !== 'none' ) {
82
+ // don't include hidden columns, unless option is set
83
+ if ( !wo.output_hiddenColumns && $this.css('display') !== 'none' ) {
84
84
  // skip column if already defined
85
85
  while (typeof tmpRow[rowIndex][cellIndex] !== 'undefined') { cellIndex++; }
86
86
  tmpRow[rowIndex][cellIndex] = tmpRow[rowIndex][cellIndex] ||
@@ -255,8 +255,9 @@ output = ts.output = {
255
255
  // Use HTML5 Blob if browser supports it
256
256
  if ( gotBlob ) {
257
257
 
258
- window.URL = window.webkitURL || window.URL;
259
- blob = new Blob([data], {type: wo.output_encoding});
258
+ window.URL = window.URL || window.webkitURL;
259
+ // prepend BOM for utf-8 encoding - see https://github.com/eligrey/FileSaver.js/blob/master/FileSaver.js#L140
260
+ blob = new Blob( [ '\ufeff', data ], { type: wo.output_encoding } );
260
261
 
261
262
  if (nav.msSaveBlob) {
262
263
  // IE 10+
@@ -294,6 +295,7 @@ ts.addWidget({
294
295
  options: {
295
296
  output_separator : ',', // set to "json", "array" or any separator
296
297
  output_ignoreColumns : [], // columns to ignore [0, 1,... ] (zero-based index)
298
+ output_hiddenColumns : false, // include hidden columns in the output
297
299
  output_includeFooter : false, // include footer rows in the output
298
300
  output_dataAttrib : 'data-name', // header attrib containing modified header name
299
301
  output_headerRows : false, // if true, include multiple header rows (JSON only)
@@ -1,4 +1,4 @@
1
- /*! Widget: Pager - updated 3/26/2015 (v2.21.3) */
1
+ /*! Widget: Pager - updated 5/17/2015 (v2.22.0) */
2
2
  /* Requires tablesorter v2.8+ and jQuery 1.7+
3
3
  * by Rob Garrison
4
4
  */
@@ -638,11 +638,11 @@ tsp = ts.pager = {
638
638
  // process data
639
639
  if ( $.isFunction(wo.pager_ajaxProcessing) ) {
640
640
  // ajaxProcessing result: [ total, rows, headers ]
641
- var i, j, t, hsh, $f, $sh, th, d, l, rr_count,
642
- $t = c.$table,
641
+ var i, j, t, hsh, $f, $sh, $headers, $h, icon, th, d, l, rr_count, len,
642
+ $table = c.$table,
643
643
  tds = '',
644
644
  result = wo.pager_ajaxProcessing(data, table, xhr) || [ 0, [] ],
645
- hl = $t.find('thead th').length;
645
+ hl = $table.find('thead th').length;
646
646
 
647
647
  // Clean up any previous error.
648
648
  ts.showError(table);
@@ -698,28 +698,30 @@ tsp = ts.pager = {
698
698
  wo.pager_processAjaxOnInit = true;
699
699
  // only add new header text if the length matches
700
700
  if ( th && th.length === hl ) {
701
- hsh = $t.hasClass('hasStickyHeaders');
701
+ hsh = $table.hasClass('hasStickyHeaders');
702
702
  $sh = hsh ? wo.$sticky.children('thead:first').children('tr').children() : '';
703
- $f = $t.find('tfoot tr:first').children();
703
+ $f = $table.find('tfoot tr:first').children();
704
704
  // don't change td headers (may contain pager)
705
- c.$headers.filter('th').each(function(j){
706
- var $t = $(this), icn;
705
+ $headers = c.$headers.filter( 'th ');
706
+ len = $headers.length;
707
+ for ( j = 0; j < len; j++ ) {
708
+ $h = $headers.eq( j );
707
709
  // add new test within the first span it finds, or just in the header
708
- if ( $t.find('.' + ts.css.icon).length ) {
709
- icn = $t.find('.' + ts.css.icon).clone(true);
710
- $t.find('.tablesorter-header-inner').html( th[j] ).append(icn);
710
+ if ( $h.find('.' + ts.css.icon).length ) {
711
+ icon = $h.find('.' + ts.css.icon).clone(true);
712
+ $h.find('.tablesorter-header-inner').html( th[j] ).append(icon);
711
713
  if ( hsh && $sh.length ) {
712
- icn = $sh.eq(j).find('.' + ts.css.icon).clone(true);
713
- $sh.eq(j).find('.tablesorter-header-inner').html( th[j] ).append(icn);
714
+ icon = $sh.eq(j).find('.' + ts.css.icon).clone(true);
715
+ $sh.eq(j).find('.tablesorter-header-inner').html( th[j] ).append(icon);
714
716
  }
715
717
  } else {
716
- $t.find('.tablesorter-header-inner').html( th[j] );
718
+ $h.find('.tablesorter-header-inner').html( th[j] );
717
719
  if (hsh && $sh.length) {
718
720
  $sh.eq(j).find('.tablesorter-header-inner').html( th[j] );
719
721
  }
720
722
  }
721
723
  $f.eq(j).html( th[j] );
722
- });
724
+ }
723
725
  }
724
726
  }
725
727
  if (c.showProcessing) {
@@ -734,7 +736,7 @@ tsp = ts.pager = {
734
736
  p.initializing = false;
735
737
  // update display without triggering pager complete... before updating cache
736
738
  tsp.updatePageDisplay(table, c, false);
737
- $t.trigger('updateCache', [function(){
739
+ $table.trigger('updateCache', [function(){
738
740
  if (p.initialized) {
739
741
  // apply widgets after table has rendered & after a delay to prevent
740
742
  // multiple applyWidget blocking code from blocking this trigger
@@ -742,7 +744,7 @@ tsp = ts.pager = {
742
744
  if (c.debug) {
743
745
  ts.log('Pager: Triggering pagerChange');
744
746
  }
745
- $t
747
+ $table
746
748
  .trigger('applyWidgets')
747
749
  .trigger('pagerChange', p);
748
750
  tsp.updatePageDisplay(table, c);
@@ -898,7 +900,8 @@ tsp = ts.pager = {
898
900
  },
899
901
 
900
902
  showAllRows: function(table, c){
901
- var p = c.pager,
903
+ var index, $controls, len,
904
+ p = c.pager,
902
905
  wo = c.widgetOptions;
903
906
  if ( p.ajax ) {
904
907
  tsp.pagerArrows(c, true);
@@ -920,9 +923,15 @@ tsp = ts.pager = {
920
923
  }
921
924
  }
922
925
  // disable size selector
923
- p.$size.add(p.$goto).each(function(){
924
- $(this).attr('aria-disabled', 'true').addClass(wo.pager_css.disabled)[0].disabled = true;
925
- });
926
+ $controls = p.$size
927
+ .add( p.$goto )
928
+ .add( p.$container.find( '.ts-startRow, .ts-page ' ) );
929
+ len = $controls.length;
930
+ for ( index = 0; index < len; index++ ) {
931
+ $controls.eq( index )
932
+ .attr( 'aria-disabled', 'true' )
933
+ .addClass( wo.pager_css.disabled )[0].disabled = true;
934
+ }
926
935
  },
927
936
 
928
937
  // updateCache if delayInit: true
@@ -1109,14 +1118,16 @@ tsp = ts.pager = {
1109
1118
  };
1110
1119
 
1111
1120
  // see #486
1112
- ts.showError = function(table, message){
1113
- $(table).each(function(){
1114
- var $row,
1115
- c = this.config,
1116
- wo = c.widgetOptions,
1121
+ ts.showError = function( table, message ) {
1122
+ var index, $row, c, wo, errorRow,
1123
+ $table = $( table ),
1124
+ len = $table.length;
1125
+ for ( index = 0; index < len; index++ ) {
1126
+ c = $table[ index ].config;
1127
+ if ( c ) {
1128
+ wo = c.widgetOptions;
1117
1129
  errorRow = c.pager && c.pager.cssErrorRow || wo.pager_css && wo.pager_css.errorRow || 'tablesorter-errorRow';
1118
- if (c) {
1119
- if (typeof message === 'undefined') {
1130
+ if ( typeof message === 'undefined' ) {
1120
1131
  c.$table.find('thead').find(c.selectorRemove).remove();
1121
1132
  } else {
1122
1133
  $row = ( /tr\>/.test(message) ? $(message) : $('<tr><td colspan="' + c.columns + '">' + message + '</td></tr>') )
@@ -1132,7 +1143,7 @@ ts.showError = function(table, message){
1132
1143
  });
1133
1144
  }
1134
1145
  }
1135
- });
1146
+ }
1136
1147
  };
1137
1148
 
1138
1149
  })(jQuery);
@@ -1,7 +1,7 @@
1
- /*! Widget: resizable - updated 4/2/2015 (v2.21.5) */
1
+ /*! Widget: resizable - updated 5/17/2015 (v2.22.0) */
2
2
  ;(function ($, window) {
3
3
  'use strict';
4
- var ts = $.tablesorter = $.tablesorter || {};
4
+ var ts = $.tablesorter || {};
5
5
 
6
6
  $.extend(ts.css, {
7
7
  resizableContainer : 'tablesorter-resizable-container',
@@ -290,7 +290,7 @@ ts.addWidget({
290
290
  init: function(table, thisWidget, c, wo) {
291
291
  ts.resizable.init( c, wo );
292
292
  },
293
- remove: function( table, c, wo ) {
293
+ remove: function( table, c, wo, refreshing ) {
294
294
  if (wo.$resizable_container) {
295
295
  var namespace = c.namespace + 'tsresize';
296
296
  c.$table.add( $( c.namespace + '_extra_table' ) )
@@ -299,13 +299,13 @@ ts.addWidget({
299
299
 
300
300
  wo.$resizable_container.remove();
301
301
  ts.resizable.toggleTextSelection( c, false );
302
- ts.resizableReset( table );
302
+ ts.resizableReset( table, refreshing );
303
303
  $( document ).unbind( 'mousemove' + namespace + ' mouseup' + namespace );
304
304
  }
305
305
  }
306
306
  });
307
307
 
308
- ts.resizableReset = function( table, nosave ) {
308
+ ts.resizableReset = function( table, refreshing ) {
309
309
  $( table ).each(function(){
310
310
  var index, $t,
311
311
  c = this.config,
@@ -322,7 +322,7 @@ ts.resizableReset = function( table, nosave ) {
322
322
  }
323
323
  // reset stickyHeader widths
324
324
  $( window ).trigger( 'resize' );
325
- if ( ts.storage && !nosave ) {
325
+ if ( ts.storage && !refreshing ) {
326
326
  ts.storage( this, ts.css.resizableStorage, {} );
327
327
  }
328
328
  }
@@ -1,7 +1,7 @@
1
1
  /*! Widget: saveSort */
2
2
  ;(function ($) {
3
3
  'use strict';
4
- var ts = $.tablesorter = $.tablesorter || {};
4
+ var ts = $.tablesorter || {};
5
5
 
6
6
  // this widget saves the last sort only if the
7
7
  // saveSort widget option is true AND the
@@ -1,4 +1,4 @@
1
- /*! Widget: scroller - updated 4/2/2015 (v2.21.5) *//*
1
+ /*! Widget: scroller - updated 5/17/2015 (v2.22.0) *//*
2
2
  Copyright (C) 2011 T. Connell & Associates, Inc.
3
3
 
4
4
  Dual-licensed under the MIT and GPL licenses
@@ -40,14 +40,15 @@ var ts = $.tablesorter,
40
40
  tscss = ts.css;
41
41
 
42
42
  $.extend( ts.css, {
43
- scrollerWrap : 'tablesorter-scroller',
44
- scrollerHeader : 'tablesorter-scroller-header',
45
- scrollerTable : 'tablesorter-scroller-table',
46
- scrollerFooter : 'tablesorter-scroller-footer',
47
- scrollerFixed : 'tablesorter-scroller-fixed',
48
- scrollerHasFix : 'tablesorter-scroller-has-fixed-columns',
49
- scrollerReset : 'tablesorter-scroller-reset',
50
- scrollerRtl : 'tablesorter-scroller-rtl'
43
+ scrollerWrap : 'tablesorter-scroller',
44
+ scrollerHeader : 'tablesorter-scroller-header',
45
+ scrollerTable : 'tablesorter-scroller-table',
46
+ scrollerFooter : 'tablesorter-scroller-footer',
47
+ scrollerFixed : 'tablesorter-scroller-fixed',
48
+ scrollerFixedPanel : 'tablesorter-scroller-fixed-panel',
49
+ scrollerHasFix : 'tablesorter-scroller-has-fixed-columns',
50
+ scrollerReset : 'tablesorter-scroller-reset',
51
+ scrollerRtl : 'tablesorter-scroller-rtl'
51
52
  });
52
53
 
53
54
  ts.addWidget({
@@ -61,6 +62,8 @@ ts.addWidget({
61
62
  scroller_fixedColumns : 0,
62
63
  // add hover highlighting to the fixed column (disable if it causes slowing)
63
64
  scroller_rowHighlight : 'hover',
65
+ // add a fixed column overlay for styling
66
+ scroller_addFixedOverlay : false,
64
67
  // bar width is now calculated; set a value to override
65
68
  scroller_barWidth : null
66
69
  },
@@ -95,6 +98,8 @@ $( function() {
95
98
  '.' + tscss.scrollerReset + ' { width: auto !important; min-width: auto !important; max-width: auto !important; }' +
96
99
  /* overall wrapper & table section wrappers */
97
100
  '.' + tscss.scrollerWrap + ' { position: relative; overflow: hidden; }' +
101
+ /* add border-box sizing to all scroller widget tables; see #135 */
102
+ '.' + tscss.scrollerWrap + ' * { box-sizing: border-box; }' +
98
103
  '.' + tscss.scrollerHeader + ', .' + tscss.scrollerFooter + ' { overflow: hidden; }' +
99
104
  '.' + tscss.scrollerHeader + ' table.' + tscss.table + ' { margin-bottom: 0; }' +
100
105
  '.' + tscss.scrollerFooter + ' table.' + tscss.table + ' thead { visibility: hidden, height: 0; overflow: hidden; }' +
@@ -104,17 +109,20 @@ $( function() {
104
109
  /* hide filter row in clones */
105
110
  '.' + tscss.scrollerTable + ' .' + ( tscss.filterRow || 'tablesorter-filter-row' ) + ',.' + tscss.scrollerFooter + ' .' +
106
111
  ( tscss.filterRow || 'tablesorter-filter-row' ) + ',.' + tscss.scrollerTable + ' tfoot { display: none; }' +
107
- '.' + tscss.scrollerWrap + ' .' + tscss.scrollerFixed + ' { position: absolute; top: 0; z-index: 1; left: 0 } ' +
108
- '.' + tscss.scrollerWrap + ' .' + tscss.scrollerFixed + '.' + tscss.scrollerRtl + ' { left: auto; right: 0 } ' +
109
112
  /* visibly hide header rows in clones, so we can still set a width on it and still effect the rest of the column */
110
113
  '.' + tscss.scrollerTable + ' table.' + tscss.table + ' thead tr.' + tscss.headerRow + ' *, .' + tscss.scrollerFooter +
111
114
  ' table.' + tscss.table + ' thead * { line-height: 0; height: 0; border: none; background-image: none; padding-top: 0;' +
112
115
  ' padding-bottom: 0; margin-top: 0; margin-bottom: 0; overflow: hidden; }' +
113
116
 
114
117
  /*** fixed column ***/
115
- '.' + tscss.scrollerFixed + ' { pointer-events: none; }' +
116
- /* add horizontal scroll bar */
117
- '.' + tscss.scrollerWrap + '.' + tscss.scrollerHasFix + ' > .' + tscss.scrollerTable + ' { overflow-x: scroll; }' +
118
+ /* disable pointer-events on fixed column wrapper or the user can't interact with the horizontal scrollbar */
119
+ '.' + tscss.scrollerFixed + ', .' + tscss.scrollerFixed + ' .' + tscss.scrollerFixedPanel + ' { pointer-events: none; }' +
120
+ /* enable pointer-events for fixed column children; see #135 & #878 */
121
+ '.' + tscss.scrollerFixed + ' > div { pointer-events: all; }' +
122
+ '.' + tscss.scrollerWrap + ' .' + tscss.scrollerFixed + ' { position: absolute; top: 0; z-index: 1; left: 0 } ' +
123
+ '.' + tscss.scrollerWrap + ' .' + tscss.scrollerFixed + '.' + tscss.scrollerRtl + ' { left: auto; right: 0 } ' +
124
+ /* add horizontal scroll bar; set to "auto", see #135 */
125
+ '.' + tscss.scrollerWrap + '.' + tscss.scrollerHasFix + ' > .' + tscss.scrollerTable + ' { overflow-x: auto; }' +
118
126
  /* need to position the tbody & tfoot absolutely to hide the scrollbar & move the footer below the horizontal scrollbar */
119
127
  '.' + tscss.scrollerFixed + ' .' + tscss.scrollerFooter + ' { position: absolute; bottom: 0; }' +
120
128
  /* hide fixed tbody scrollbar - see http://goo.gl/VsLe6n */
@@ -123,6 +131,9 @@ $( function() {
123
131
  /* remove right border of fixed header tables to hide the boundary */
124
132
  '.' + tscss.scrollerWrap + ' .' + tscss.scrollerFixed + ' table { border-right-color: transparent; padding-right: 0; }' +
125
133
  '.' + tscss.scrollerWrap + ' .' + tscss.scrollerFixed + '.' + tscss.scrollerRtl + ' table { border-left-color: transparent; padding-left: 0; }' +
134
+
135
+ /*** fixed column panel ***/
136
+ '.' + tscss.scrollerWrap + ' .' + tscss.scrollerFixedPanel + ' { position: absolute; top: 0; bottom: 0; z-index: 2; left: 0; right: 0; } ' +
126
137
  '</style>';
127
138
  $( style ).appendTo( 'body' );
128
139
  });
@@ -131,6 +142,8 @@ ts.scroller = {
131
142
 
132
143
  // Ugh.. Firefox misbehaves, so it needs to be detected
133
144
  isFirefox : navigator.userAgent.toLowerCase().indexOf( 'firefox' ) > -1,
145
+ // old IE needs a wrap to hide the fixed column scrollbar; http://stackoverflow.com/a/24408672/145346
146
+ isOldIE : document.all && !window.atob,
134
147
 
135
148
  hasScrollBar : function( $target ) {
136
149
  return $target.get(0).scrollHeight > $target.height();
@@ -241,7 +254,7 @@ ts.scroller = {
241
254
 
242
255
  // Sorting, so scroll to top
243
256
  $table
244
- .off( 'sortEnd' + namespace + ' setFixedColumnSize' + namespace )
257
+ .off( 'sortEnd setFixedColumnSize updateComplete '.split( ' ' ).join( namespace + ' ' ) )
245
258
  .on( 'sortEnd' + namespace, function() {
246
259
  if ( wo.scroller_upAfterSort ) {
247
260
  $table.parent().animate({ scrollTop: 0 }, 'fast' );
@@ -253,11 +266,16 @@ ts.scroller = {
253
266
  }
254
267
  // remove fixed columns
255
268
  wo.scroller_$container.find( '.' + tscss.scrollerFixed ).remove();
269
+ size = wo.scroller_fixedColumns;
256
270
  if ( size > 0 && size < c.columns - 1 ) {
257
271
  ts.scroller.setupFixed( c, wo );
258
272
  } else {
259
273
  wo.scroller_$container.removeClass( tscss.scrollerHasFix );
260
274
  }
275
+ })
276
+ .on( 'updateComplete' + namespace, function() {
277
+ // adjust column sizes after an update
278
+ ts.scroller.resize( c, wo );
261
279
  });
262
280
 
263
281
  // Setup window.resizeEnd event
@@ -381,6 +399,9 @@ ts.scroller = {
381
399
  .addClass( tscss.scrollerFixed )
382
400
  .removeClass( tscss.scrollerWrap )
383
401
  .attr( 'id', '' );
402
+ if ( wo.scroller_addFixedOverlay ) {
403
+ $fixedColumn.append( '<div class="' + tscss.scrollerFixedPanel + '">' );
404
+ }
384
405
  $fixedTbody = $fixedColumn.find( '.' + tscss.scrollerTable );
385
406
  $fixedTbody.find( 'table' )
386
407
  .addClass( c.namespace.slice(1) + '_extra_table' )
@@ -414,14 +435,15 @@ ts.scroller = {
414
435
  $el.eq( index ).prop( 'disabled', index < fixedColumns );
415
436
  }
416
437
  }
417
- // enable visible fixed column filters
418
- $fixedColumn.children( '.' + tscss.scrollerHeader ).find( '.' + tscss.filter ).css( 'pointer-events', 'all' );
419
438
  }
420
439
 
421
440
  // disable/enable tab indexes behind fixed column
422
- c.$table.children( 'thead' ).children( 'tr.' + tscss.headerRow ).children().attr( 'tabindex', -1 );
441
+ c.$table
442
+ .add( '.' + tscss.scrollerFooter + ' table' )
443
+ .children( 'thead' )
444
+ .children( 'tr.' + tscss.headerRow ).children().attr( 'tabindex', -1 );
423
445
  $el = wo.scroller_$header
424
- .add( $fixedColumn.find( '.' + tscss.scrollerTable + ' table, .' + tscss.scrollerFooter + ' table' ) )
446
+ .add( $fixedColumn.find( '.' + tscss.scrollerTable + ' table' ) )
425
447
  .children( 'thead' ).children( 'tr.' + tscss.headerRow );
426
448
  len = $el.length;
427
449
  for ( index = 0; index < len; index++ ) {
@@ -475,9 +497,9 @@ ts.scroller = {
475
497
  });
476
498
  }
477
499
 
478
- /*** STUPID FIREFOX HACK! Since we can't hide the scrollbar with css ***/
479
- if ( ts.scroller.isFirefox ) {
480
- $fixedTbody.wrap( '<div class="scroller-firefox-hack" style="overflow:hidden;">' );
500
+ /*** Scrollbar hack! Since we can't hide the scrollbar with css ***/
501
+ if ( ts.scroller.isFirefox || ts.scroller.isOldIE ) {
502
+ $fixedTbody.wrap( '<div class="scroller-scrollbar-hack" style="overflow:hidden;">' );
481
503
  }
482
504
 
483
505
  ts.scroller.updateFixed( c, wo, true );
@@ -508,7 +530,7 @@ ts.scroller = {
508
530
  $fixedTbodies = $fixedTbodiesTable.children( 'tbody' ),
509
531
  $fixedHeader = $fixedColumn.find( '.' + tscss.scrollerHeader ).children( 'table' ).children( 'thead' ),
510
532
  // variables
511
- isFirefox = ts.scroller.isFirefox,
533
+ tsScroller = ts.scroller,
512
534
  scrollBarWidth = wo.scroller_barSetWidth,
513
535
  fixedColumns = wo.scroller_fixedColumns,
514
536
  // get dimensions
@@ -533,8 +555,8 @@ ts.scroller = {
533
555
  }).get();
534
556
 
535
557
  // set fixed column width
536
- ts.scroller.setWidth( $fixedColumn.add( $fixedColumn.children() ), totalWidth + borderRightWidth * 2 - borderSpacing );
537
- ts.scroller.setWidth( $fixedColumn.find( 'table' ), totalWidth + borderRightWidth );
558
+ tsScroller.setWidth( $fixedColumn.add( $fixedColumn.children() ), totalWidth + borderRightWidth * 2 - borderSpacing );
559
+ tsScroller.setWidth( $fixedColumn.find( 'table' ), totalWidth + borderRightWidth );
538
560
 
539
561
  // set fixed column height ( changes with filtering )
540
562
  $fixedColumn.height( $wrapper.height() );
@@ -565,10 +587,10 @@ ts.scroller = {
565
587
  $adjCol = $( $rows[ rowIndex ].outerHTML );
566
588
  $adjCol.children( 'td, th' ).slice( fixedColumns ).remove();
567
589
  // set row height
568
- $adjCol.children().eq( 0 ).height( $rows.eq( rowIndex ).outerHeight() - ( isFirefox ? borderBottomWidth * 2 : 0 ) );
590
+ $adjCol.children().eq( 0 ).height( $rows.eq( rowIndex ).outerHeight() - ( tsScroller.isFirefox ? borderBottomWidth * 2 : 0 ) );
569
591
  // still need to adjust tbody cell widths ( the previous row may now be filtered )
570
592
  if ( rowIndex === 0 ) {
571
- ts.scroller.setWidth( $adjCol.children().eq( 0 ), widths[ 0 ] );
593
+ tsScroller.setWidth( $adjCol.children().eq( 0 ), widths[ 0 ] );
572
594
  }
573
595
  $fb.append( $adjCol );
574
596
  }
@@ -576,7 +598,7 @@ ts.scroller = {
576
598
  // adjust fixed header cell widths
577
599
  $temp = $fixedColumn.find( 'thead' ).children( 'tr.' + tscss.headerRow );
578
600
  for ( index = 0; index < fixedColumns; index++ ) {
579
- ts.scroller.setWidth( $temp.children( ':eq(' + index + ')' ), widths[ index ] );
601
+ tsScroller.setWidth( $temp.children( ':eq(' + index + ')' ), widths[ index ] );
580
602
  }
581
603
 
582
604
  // restore tbody
@@ -584,8 +606,8 @@ ts.scroller = {
584
606
  }
585
607
  }
586
608
 
587
- /*** STUPID FIREFOX HACK! Since we can't hide the scrollbar with css ***/
588
- if ( isFirefox ) {
609
+ /*** scrollbar HACK! Since we can't hide the scrollbar with css ***/
610
+ if ( tsScroller.isFirefox || tsScroller.isOldIE ) {
589
611
  $fixedTbodiesTable.parent().css({
590
612
  'width' : totalWidth + scrollBarWidth + borderRightWidth
591
613
  });
@@ -602,7 +624,7 @@ ts.scroller = {
602
624
  .off( namespace )
603
625
  .insertBefore( $wrap )
604
626
  .find( 'thead' ).show().css( 'visibility', 'visible' )
605
- .children( 'tr.' + tscss.headerRow + ' > *' ).attr( 'tabindex', 0 )
627
+ .children( 'tr.' + tscss.headerRow ).children().attr( 'tabindex', 0 )
606
628
  .end()
607
629
  .find( '.' + tscss.filterRow ).show().removeClass( tscss.filterRowHide );
608
630
  $wrap.remove();