jquery-tablesorter 1.16.5 → 1.17.0

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