jquery-tablesorter 1.16.2 → 1.16.3

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 (30) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/jquery-tablesorter/version.rb +1 -1
  4. data/vendor/assets/javascripts/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.js +8 -6
  5. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.js +30 -20
  6. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets.js +343 -193
  7. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-input-select.js +4 -4
  8. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-build-table.js +3 -2
  9. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter-formatter-select2.js +2 -2
  10. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter.js +26 -23
  11. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-output.js +2 -3
  12. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-pager.js +11 -5
  13. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-resizable.js +277 -139
  14. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-scroller.js +543 -220
  15. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-stickyHeaders.js +3 -10
  16. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-storage.js +28 -15
  17. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-uitheme.js +7 -4
  18. data/vendor/assets/stylesheets/jquery-tablesorter/theme.black-ice.css +5 -4
  19. data/vendor/assets/stylesheets/jquery-tablesorter/theme.blue.css +8 -5
  20. data/vendor/assets/stylesheets/jquery-tablesorter/theme.bootstrap.css +5 -4
  21. data/vendor/assets/stylesheets/jquery-tablesorter/theme.bootstrap_2.css +6 -5
  22. data/vendor/assets/stylesheets/jquery-tablesorter/theme.dark.css +6 -5
  23. data/vendor/assets/stylesheets/jquery-tablesorter/theme.default.css +6 -5
  24. data/vendor/assets/stylesheets/jquery-tablesorter/theme.dropbox.css +5 -5
  25. data/vendor/assets/stylesheets/jquery-tablesorter/theme.green.css +13 -8
  26. data/vendor/assets/stylesheets/jquery-tablesorter/theme.grey.css +8 -5
  27. data/vendor/assets/stylesheets/jquery-tablesorter/theme.ice.css +16 -9
  28. data/vendor/assets/stylesheets/jquery-tablesorter/theme.jui.css +4 -3
  29. data/vendor/assets/stylesheets/jquery-tablesorter/theme.metro-dark.css +5 -4
  30. metadata +3 -3
@@ -1,12 +1,13 @@
1
- /*!
1
+ /*! Widget: scroller - updated 3/26/2015 (v2.21.3) *//*
2
2
  Copyright (C) 2011 T. Connell & Associates, Inc.
3
3
 
4
4
  Dual-licensed under the MIT and GPL licenses
5
5
 
6
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
7
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
8
- FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
9
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
7
+ LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
8
+ NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
9
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
10
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10
11
 
11
12
  Resizable scroller widget for the jQuery tablesorter plugin
12
13
 
@@ -32,261 +33,583 @@
32
33
  Website: www.tconnell.com
33
34
  */
34
35
  /*jshint browser:true, jquery:true, unused:false */
35
- ;(function($, window){
36
- "use strict";
36
+ ;( function( $, window ) {
37
+ 'use strict';
38
+
39
+ var ts = $.tablesorter,
40
+ tscss = ts.css;
41
+
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'
51
+ });
37
52
 
38
- $.fn.hasScrollBar = function(){
39
- return this.get(0).scrollHeight > this.height();
40
- };
41
- var ts = $.tablesorter;
53
+ ts.addWidget({
54
+ id : 'scroller',
55
+ priority : 60, // run after the filter widget
56
+ options : {
57
+ scroller_height : 300,
58
+ scroller_jumpToHeader : true,
59
+ scroller_upAfterSort : true,
60
+ // set number of columns to fix
61
+ scroller_fixedColumns : 0,
62
+ // add hover highlighting to the fixed column (disable if it causes slowing)
63
+ scroller_rowHighlight : 'hover',
64
+ // bar width is now calculated; set a value to override
65
+ scroller_barWidth : null
66
+ },
67
+ format: function( table, c, wo ) {
68
+ if ( !c.isScrolling ) {
69
+ // initialize here instead of in widget init to give the
70
+ // filter widget time to finish building the filter row
71
+ ts.scroller.setup( c, wo );
72
+ }
73
+ },
74
+ remove : function( table, c, wo ) {
75
+ ts.scroller.remove( c, wo );
76
+ }
77
+ });
42
78
 
43
- ts.window_resize = function(){
44
- if (this.resize_timer) {
45
- clearTimeout(this.resize_timer);
79
+ /* Add window resizeEnd event */
80
+ ts.window_resize = function() {
81
+ if ( this.resize_timer ) {
82
+ clearTimeout( this.resize_timer );
46
83
  }
47
- this.resize_timer = setTimeout(function(){
48
- $(this).trigger('resizeEnd');
49
- }, 250);
84
+ this.resize_timer = setTimeout( function() {
85
+ $( this ).trigger( 'resizeEnd' );
86
+ }, 250 );
50
87
  };
51
88
 
52
89
  // Add extra scroller css
53
- $(function(){
54
- var s = '<style>' +
55
- '.tablesorter-scrollbar-measure { width: 100px; height: 100px; overflow: scroll; position: absolute; top: -9999px; } ' +
56
- '.tablesorter-scroller-reset { width: auto !important; } ' +
57
- '.tablesorter-scroller { text-align: left; overflow: hidden; }' +
58
- '.tablesorter-scroller-header, .tablesorter-scroller-footer { overflow: hidden; }' +
59
- '.tablesorter-scroller-header table.tablesorter { margin-bottom: 0; }' +
60
- '.tablesorter-scroller-footer table.tablesorter thead { visibility: hidden, height: 0; overflow: hidden; }' +
61
- '.tablesorter-scroller-table { overflow-y: scroll; }' +
62
- '.tablesorter-scroller-table table.tablesorter { margin-top: 0; margin-bottom: 0; overflow: scroll; } ' +
63
- '.tablesorter-scroller-table .tablesorter-filter-row,.tablesorter-scroller-footer .tablesorter-filter-row,.tablesorter-scroller-table tfoot { display: none; }' +
64
- '.tablesorter-scroller-table table.tablesorter thead tr.tablesorter-headerRow *,.tablesorter-scroller-footer table.tablesorter thead * {' +
65
- 'line-height:0;height:0;border:none;background-image:none;padding-top:0;padding-bottom:0;margin-top:0;margin-bottom:0;overflow:hidden;' +
66
- '}</style>';
67
- $(s).appendTo('body');
90
+ $( function() {
91
+ var style = '<style>' +
92
+ /* measure scroll bar width */
93
+ '.' + tscss.scrollerWrap + 'Measure { width: 100px; height: 100px; overflow: scroll; position: absolute; top: -9999px; }' +
94
+ /* reset width to get accurate measurements after window resize */
95
+ '.' + tscss.scrollerReset + ' { width: auto !important; min-width: auto !important; max-width: auto !important; }' +
96
+ /* overall wrapper & table section wrappers */
97
+ '.' + tscss.scrollerWrap + ' { position: relative; overflow: hidden; }' +
98
+ '.' + tscss.scrollerHeader + ', .' + tscss.scrollerFooter + ' { overflow: hidden; }' +
99
+ '.' + tscss.scrollerHeader + ' table.' + tscss.table + ' { margin-bottom: 0; }' +
100
+ '.' + tscss.scrollerFooter + ' table.' + tscss.table + ' thead { visibility: hidden, height: 0; overflow: hidden; }' +
101
+ /* always leave the scroll bar visible for tbody, or table overflows into the scrollbar when height < max height (filtering) */
102
+ '.' + tscss.scrollerTable + ' { overflow-y: scroll; }' +
103
+ '.' + tscss.scrollerTable + ' table.' + tscss.table + ' { border-top: 0; margin-top: 0; margin-bottom: 0; overflow-y: scroll; }' +
104
+ /* hide filter row in clones */
105
+ '.' + tscss.scrollerTable + ' .' + ( tscss.filterRow || 'tablesorter-filter-row' ) + ',.' + tscss.scrollerFooter + ' .' +
106
+ ( 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
+ /* visibly hide header rows in clones, so we can still set a width on it and still effect the rest of the column */
110
+ '.' + tscss.scrollerTable + ' table.' + tscss.table + ' thead tr.' + tscss.headerRow + ' *, .' + tscss.scrollerFooter +
111
+ ' table.' + tscss.table + ' thead * { line-height: 0; height: 0; border: none; background-image: none; padding-top: 0;' +
112
+ ' padding-bottom: 0; margin-top: 0; margin-bottom: 0; overflow: hidden; }' +
113
+
114
+ /*** fixed column ***/
115
+ '.' + tscss.scrollerFixed + ' { pointer-events: none; }' +
116
+ /* add horizontal scroll bar */
117
+ '.' + tscss.scrollerWrap + '.' + tscss.scrollerHasFix + ' > .' + tscss.scrollerTable + ' { overflow-x: scroll; }' +
118
+ /* need to position the tbody & tfoot absolutely to hide the scrollbar & move the footer below the horizontal scrollbar */
119
+ '.' + tscss.scrollerFixed + ' .' + tscss.scrollerFooter + ' { position: absolute; bottom: 0; }' +
120
+ /* hide fixed tbody scrollbar - see http://goo.gl/VsLe6n */
121
+ '.' + tscss.scrollerFixed + ' .' + tscss.scrollerTable + ' { position: relative; left: 0; overflow-x: hidden; overflow-y: scroll; -ms-overflow-style: none; }' +
122
+ '.' + tscss.scrollerFixed + ' .' + tscss.scrollerTable + '::-webkit-scrollbar { display: none; }' +
123
+ /* remove right border of fixed header tables to hide the boundary */
124
+ '.' + tscss.scrollerWrap + ' .' + tscss.scrollerFixed + ' table { border-right-color: transparent; padding-right: 0; }' +
125
+ '.' + tscss.scrollerWrap + ' .' + tscss.scrollerFixed + '.' + tscss.scrollerRtl + ' table { border-left-color: transparent; padding-left: 0; }' +
126
+ '</style>';
127
+ $( style ).appendTo( 'body' );
68
128
  });
69
129
 
70
- ts.addWidget({
71
- id: 'scroller',
72
- priority: 60, // run after the filter widget
73
- options: {
74
- scroller_height : 300,
75
- scroller_jumpToHeader: true,
76
- scroller_upAfterSort: true,
77
- // bar width is now calculated; set a value to override
78
- scroller_barWidth : null
130
+ ts.scroller = {
131
+
132
+ // Ugh.. Firefox misbehaves, so it needs to be detected
133
+ isFirefox : navigator.userAgent.toLowerCase().indexOf( 'firefox' ) > -1,
134
+
135
+ hasScrollBar : function( $target ) {
136
+ return $target.get(0).scrollHeight > $target.height();
79
137
  },
80
- init: function(table, thisWidget, c, wo){
81
- var $win = $(window),
82
- namespace = c.namespace + 'tsscroller';
138
+
139
+ setWidth : function( $el, width ) {
140
+ $el.css({
141
+ 'width' : width,
142
+ 'min-width' : width,
143
+ 'max-width' : width
144
+ });
145
+ },
146
+
147
+ // modified from http://davidwalsh.name/detect-scrollbar-width
148
+ getBarWidth : function() {
149
+ var $scrollDiv = $( '<div class="' + tscss.scrollerWrap + 'Measure">' ).appendTo( 'body' ),
150
+ div = $scrollDiv[ 0 ],
151
+ barWidth = div.offsetWidth - div.clientWidth;
152
+ $scrollDiv.remove();
153
+ return barWidth;
154
+ },
155
+
156
+ setup : function( c, wo ) {
157
+ var maxHt, tbHt, $hdr, $t, $hCells, $fCells, $tableWrap,
158
+ $win = $( window ),
159
+ namespace = c.namespace + 'tsscroller',
160
+ $foot = $(),
161
+ // c.namespace contains a unique tablesorter ID, per table
162
+ id = c.namespace.slice( 1 ) + 'tsscroller',
163
+ $table = c.$table;
164
+
165
+ // force developer to set fixedWidth to maintain column widths
166
+ c.widthFixed = true;
167
+ maxHt = wo.scroller_height || 300;
168
+ tbHt = $table.children( 'tbody' ).height();
169
+ if ( tbHt !== 0 && maxHt > tbHt ) { maxHt = tbHt + 10; } // Table is less than h px
170
+
171
+ wo.scroller_$header = $hdr = $( '<table class="' + $table.attr( 'class' ) + '" cellpadding=0 cellspacing=0>' +
172
+ $table.children( 'thead' )[0].outerHTML +
173
+ '</table>' )
174
+ .addClass( c.namespace.slice(1) + '_extra_table' );
175
+
176
+ $t = $table.children( 'tfoot' );
177
+ if ( $t.length ) {
178
+ $foot = $( '<table class="' + $table.attr('class') + '" cellpadding=0 cellspacing=0 style="margin-top:0"></table>' )
179
+ .addClass( c.namespace.slice(1) + '_extra_table' )
180
+ .append( $t.clone( true ) ) // maintain any bindings on the tfoot cells
181
+ .append( $table.children( 'thead' )[ 0 ].outerHTML )
182
+ .wrap( '<div class="' + tscss.scrollerFooter + '"/>' );
183
+ $fCells = $foot.children( 'tfoot' ).eq( 0 ).children( 'tr' ).children();
184
+ }
185
+ wo.scroller_$footer = $foot;
186
+
187
+ $table
188
+ .wrap( '<div id="' + id + '" class="' + tscss.scrollerWrap + '" />' )
189
+ .before( $hdr )
190
+ // shrink filter row but don't completely hide it because the inputs/selectors may distort the columns
191
+ .find( '.' + tscss.filterRow ).addClass( tscss.filterRowHide );
192
+
193
+ wo.scroller_$container = $table.parent();
194
+
195
+ if ( $foot.length ) {
196
+ // $foot.parent() to include <div> wrapper
197
+ $table.after( $foot.parent() );
198
+ }
199
+
200
+ $hCells = $hdr
201
+ .wrap( '<div class="' + tscss.scrollerHeader + '" />' )
202
+ .find( '.' + tscss.header );
203
+
204
+ // use max-height, so the height resizes dynamically while filtering
205
+ $table.wrap( '<div class="' + tscss.scrollerTable + '" style="max-height:' + maxHt + 'px;" />' );
206
+ $tableWrap = $table.parent();
207
+
208
+ // make scroller header sortable
209
+ ts.bindEvents( c.table, $hCells );
210
+
211
+ // look for filter widget
212
+ if ( $table.hasClass( 'hasFilters' ) ) {
213
+ ts.filter.bindSearch( $table, $hdr.find('.' + tscss.filter) );
214
+ }
215
+
216
+ // remove any previous fixed columns ( in case we're updating )
217
+ wo.scroller_$container.find( '.' + tscss.scrollerFixed ).remove();
218
+
219
+ if ( wo.scroller_fixedColumns > 0 ) {
220
+ ts.scroller.setupFixed( c, wo );
221
+ }
222
+
223
+ ts.scroller.resize( c, wo );
224
+
225
+ $table.find( 'thead' ).css( 'visibility', 'hidden' );
226
+
227
+ tbHt = $tableWrap.parent().height();
228
+
229
+ // The header will always jump into view if scrolling the table body
230
+ $tableWrap
231
+ .off( 'scroll' + namespace )
232
+ .on( 'scroll' + namespace, function() {
233
+ if ( wo.scroller_jumpToHeader ) {
234
+ var pos = $win.scrollTop() - $hdr.offset().top;
235
+ if ( $( this ).scrollTop() !== 0 && pos < tbHt && pos > 0 ) {
236
+ $win.scrollTop( $hdr.offset().top );
237
+ }
238
+ }
239
+ $hdr.parent().add( $foot.parent() ).scrollLeft( $( this ).scrollLeft() );
240
+ });
241
+
242
+ // Sorting, so scroll to top
243
+ $table
244
+ .off( 'sortEnd' + namespace + ' setFixedColumnSize' + namespace )
245
+ .on( 'sortEnd' + namespace, function() {
246
+ if ( wo.scroller_upAfterSort ) {
247
+ $table.parent().animate({ scrollTop: 0 }, 'fast' );
248
+ }
249
+ })
250
+ .on( 'setFixedColumnSize' + namespace, function( event, size ) {
251
+ if ( typeof size !== 'undefined' && !isNaN( size ) ) {
252
+ wo.scroller_fixedColumns = parseInt( size, 10 );
253
+ }
254
+ // remove fixed columns
255
+ wo.scroller_$container.find( '.' + tscss.scrollerFixed ).remove();
256
+ if ( size > 0 && size < c.columns - 1 ) {
257
+ ts.scroller.setupFixed( c, wo );
258
+ } else {
259
+ wo.scroller_$container.removeClass( tscss.scrollerHasFix );
260
+ }
261
+ });
262
+
83
263
  // Setup window.resizeEnd event
84
264
  $win
85
- .bind('resize' + namespace, ts.window_resize)
86
- .bind('resizeEnd' + namespace, function() {
87
- // init is run before format, so scroller_resizeWidth
88
- // won't be defined within the "c" or "wo" parameters
89
- if ($.isFunction(table.config.widgetOptions.scroller_resizeWidth)) {
90
- // IE calls resize when you modify content, so we have to unbind the resize event
91
- // so we don't end up with an infinite loop. we can rebind after we're done.
92
- $win.unbind('resize' + namespace, ts.window_resize);
93
- table.config.widgetOptions.scroller_resizeWidth();
94
- $win.bind('resize' + namespace, ts.window_resize);
95
- }
265
+ .off( 'resize resizeEnd '.split( ' ' ).join( namespace + ' ' ) )
266
+ .on( 'resize' + namespace, ts.window_resize )
267
+ .on( 'resizeEnd' + namespace, function() {
268
+ // IE calls resize when you modify content, so we have to unbind the resize event
269
+ // so we don't end up with an infinite loop. we can rebind after we're done.
270
+ $win.off( 'resize' + namespace, ts.window_resize );
271
+ ts.scroller.resize( c, wo );
272
+ $win.on( 'resize' + namespace, ts.window_resize );
96
273
  });
274
+
275
+ // initialization flag
276
+ c.isScrolling = true;
277
+
97
278
  },
98
- format: function(table, c, wo) {
99
- var maxHt, tbHt, $hdr, $t, resize, getBarWidth, $hCells, $fCells, $tblWrap,
100
- $ft = $(),
101
- // c.namespace contains a unique tablesorter ID, per table
102
- id = c.namespace.slice(1) + 'tsscroller',
103
- $win = $(window),
104
- $tbl = c.$table;
105
-
106
- if (!c.isScrolling) {
107
- // force developer to set fixedWidth to maintain column widths
108
- c.widthFixed = true;
109
- maxHt = wo.scroller_height || 300;
110
- tbHt = $tbl.children('tbody').height();
111
- if (tbHt !== 0 && maxHt > tbHt) { maxHt = tbHt + 10; } // Table is less than h px
112
-
113
- $hdr = $('<table class="' + $tbl.attr('class') + '" cellpadding=0 cellspacing=0>' +
114
- $tbl.children('thead')[0].outerHTML +
115
- '</table>');
116
-
117
- $t = $tbl.children('tfoot');
118
- if ($t.length) {
119
- $ft = $('<table class="' + $tbl.attr('class') + '" cellpadding=0 cellspacing=0 style="margin-top:0"></table>')
120
- .append( $t.clone(true) ) // maintain any bindings on the tfoot cells
121
- .append( $tbl.children('thead')[0].outerHTML )
122
- .wrap('<div class="tablesorter-scroller-footer"/>');
123
- $fCells = $ft.children('tfoot').eq(0).children('tr').children();
124
- }
125
279
 
126
- if (c.$extraTables && c.$extraTables.length) {
127
- c.$extraTables = c.$extraTables.add($hdr).add($ft);
280
+ resize : function( c, wo ) {
281
+ var index, borderWidth, setWidth, $hCells, $bCells, $fCells, $headers, $this,
282
+ $table = c.$table,
283
+ $tableWrap = $table.parent(),
284
+ $hdr = wo.scroller_$header,
285
+ $foot = wo.scroller_$footer,
286
+ id = c.namespace.slice( 1 ) + 'tsscroller',
287
+ // Hide other scrollers so we can resize
288
+ $div = $( 'div.' + tscss.scrollerWrap + '[id != "' + id + '"]' ).hide();
289
+
290
+ $table.children( 'thead' ).show();
291
+ // only remove colgroup if it was added by the plugin
292
+ // the $.tablesorter.fixColumnWidth() function already does this (v2.19.0)
293
+ // but we need to get "accurate" resized measurements here - see issue #680
294
+ $table.add( $hdr ).add( $foot ).children( 'colgroup' ).remove();
295
+
296
+ // Reset sizes so parent can resize.
297
+ $table
298
+ .addClass( tscss.scrollerReset )
299
+ .children( 'thead' )
300
+ .find( '.' + tscss.headerIn ).addClass( tscss.scrollerReset ).end()
301
+ .find( '.' + tscss.filterRow ).show();
302
+ $tableWrap.addClass( tscss.scrollerReset );
303
+
304
+ // include left & right border widths
305
+ borderWidth = parseInt( $table.css( 'border-left-width' ), 10 );
306
+
307
+ // Shrink a bit to accommodate scrollbar
308
+ wo.scroller_barSetWidth = ( wo.scroller_barWidth || ts.scroller.getBarWidth() || 18 ) + borderWidth;
309
+
310
+ $tableWrap.width( $tableWrap.parent().innerWidth() - ( ts.scroller.hasScrollBar( $tableWrap.parent() ) ? wo.scroller_barSetWidth : 0 ) );
311
+ setWidth = $tableWrap.innerWidth() - ( ts.scroller.hasScrollBar( $tableWrap ) ? wo.scroller_barSetWidth : 0 ) + borderWidth;
312
+ $hdr.parent().add( $foot.parent() ).width( setWidth );
313
+
314
+ $hCells = $hdr.children( 'thead' ).children().children( 'th, td' ).filter( ':visible' );
315
+ $bCells = $table.children('tbody').eq( 0 ).children().eq( 0 ).children( 'th, td' ).filter( ':visible' );
316
+ $fCells = $foot.children( 'tfoot' ).children().children( 'th, td' ).filter( ':visible' );
317
+
318
+ ts.scroller.setWidth( $hCells.add( $bCells ).add( $fCells ), '' );
319
+ $headers = $table.children( 'thead' ).children().eq( 0 ).children( 'th, td' );
320
+ for ( index = 0; index < $headers.length; index++ ) {
321
+ $this = $headers.eq( index );
322
+ // code from https://github.com/jmosbech/StickyTableHeaders
323
+ if ( $this.css( 'box-sizing' ) === 'border-box' ) {
324
+ setWidth = $this.outerWidth();
128
325
  } else {
129
- c.$extraTables = $hdr.add($ft);
326
+ if ( $hCells.eq( index ).css( 'border-collapse' ) === 'collapse' ) {
327
+ if ( $this.length && window.getComputedStyle ) {
328
+ setWidth = parseFloat( window.getComputedStyle( $this[0], null ).width );
329
+ } else {
330
+ // ie8 only
331
+ borderWidth = parseFloat( $this.css( 'border-width' ) ) || 0;
332
+ setWidth = $this.outerWidth() - parseFloat( $this.css( 'padding-left' ) ) - parseFloat( $this.css( 'padding-right' ) ) - borderWidth;
333
+ }
334
+ } else {
335
+ setWidth = $this.width();
336
+ }
130
337
  }
131
- $tbl
132
- .wrap('<div id="' + id + '" class="tablesorter-scroller" />')
133
- .before($hdr)
134
- // shrink filter row but don't completely hide it because the inputs/selectors may distort the columns
135
- .find('.tablesorter-filter-row').addClass('hideme');
136
-
137
- if ($ft.length) {
138
- // $ft.parent() to include <div> wrapper
139
- $tbl.after( $ft.parent() );
338
+ ts.scroller.setWidth( $hCells.eq( index ).add( $bCells.eq( index ) ).add( $fCells.eq( index ) ), setWidth );
339
+ }
340
+
341
+ wo.scroller_$container
342
+ .find( '.' + tscss.scrollerReset )
343
+ .removeClass( tscss.scrollerReset );
344
+
345
+ // refresh colgroup & copy to cloned header
346
+ ts.fixColumnWidth( c.table );
347
+
348
+ // add colgroup to all clones
349
+ $hCells = $table.children( 'colgroup' );
350
+ if ( $hCells.length ) {
351
+ $bCells = $hCells[0].outerHTML;
352
+ $hdr.prepend( $bCells );
353
+ if ( $foot.length ) {
354
+ $foot.prepend( $bCells );
140
355
  }
356
+ }
141
357
 
142
- $hCells = $hdr
143
- .wrap('<div class="tablesorter-scroller-header" />')
144
- .find('.' + ts.css.header);
358
+ // update fixed column sizes
359
+ if ( wo.scroller_fixedColumns > 0 ) {
360
+ ts.scroller.updateFixed( c, wo, true );
361
+ }
145
362
 
146
- // use max-height, so the height resizes dynamically while filtering
147
- $tbl.wrap('<div class="tablesorter-scroller-table" style="max-height:' + maxHt + 'px;" />');
148
- $tblWrap = $tbl.parent();
363
+ // hide filter row because filterEnd event fires
364
+ $table.children( 'thead' ).find( '.' + tscss.filterRow ).hide();
149
365
 
150
- // make scroller header sortable
151
- ts.bindEvents(table, $hCells);
366
+ $div.show();
152
367
 
153
- // look for filter widget
154
- if ($tbl.hasClass('hasFilters')) {
155
- ts.filter.bindSearch( $tbl, $hdr.find('.' + ts.css.filter) );
156
- }
368
+ },
157
369
 
158
- // modified from http://davidwalsh.name/detect-scrollbar-width
159
- getBarWidth = function(){
160
- var $scrollDiv = $('<div class="tablesorter-scrollbar-measure">').appendTo('body'),
161
- div = $scrollDiv[0],
162
- barWidth = div.offsetWidth - div.clientWidth;
163
- $scrollDiv.remove();
164
- return barWidth;
165
- };
166
-
167
- resize = function(){
168
- var b, $h, $f, w,
169
- // Hide other scrollers so we can resize
170
- $div = $('div.tablesorter-scroller[id != "' + id + '"]').hide();
171
-
172
- $tbl.children('thead').show();
173
- // only remove colgroup if it was added by the plugin
174
- // the $.tablesorter.fixColumnWidth() function already does this (v2.19.0)
175
- // but we need to get "accurate" resized measurements here - see issue #680
176
- $tbl.add( $hdr ).add( $ft ).children('colgroup').remove();
177
-
178
- // Reset sizes so parent can resize.
179
- $tbl
180
- .addClass('tablesorter-scroller-reset')
181
- .children('thead')
182
- .find('.tablesorter-header-inner').addClass('tablesorter-scroller-reset').end()
183
- .find('.tablesorter-filter-row').show();
184
- $tblWrap.addClass('tablesorter-scroller-reset');
185
-
186
- $tblWrap.parent().trigger('resize');
187
-
188
- // include left & right border widths
189
- b = parseInt( $tbl.css('border-left-width'), 10 ) + parseInt( $tbl.css('border-right-width'), 10 );
190
-
191
- // Shrink a bit to accommodate scrollbar
192
- w = ( wo.scroller_barWidth || getBarWidth() ) + b;
193
-
194
- $tblWrap.width( $tblWrap.parent().innerWidth() - ( $tblWrap.parent().hasScrollBar() ? w : 0 ) );
195
- w = $tblWrap.innerWidth() - ( $tblWrap.hasScrollBar() ? w : 0 );
196
- $hdr.parent().add( $ft.parent() ).width( w );
197
-
198
- w = $tbl.width();
199
-
200
- $h = $hdr.children('thead').children().children('th, td').filter(':visible');
201
- $f = $ft.children('tfoot').children().children('th, td').filter(':visible');
202
- $tbl.children('thead').children().eq(0).children('th, td').each(function(indx, el) {
203
- var width, border,
204
- $this = $(this);
205
- // code from https://github.com/jmosbech/StickyTableHeaders
206
- if ($this.css('box-sizing') === 'border-box') {
207
- width = $this.outerWidth();
208
- } else {
209
- if ($h.eq(indx).css('border-collapse') === 'collapse') {
210
- if (window.getComputedStyle) {
211
- width = parseFloat( window.getComputedStyle(this, null).width );
212
- } else {
213
- // ie8 only
214
- border = parseFloat( $this.css('border-width') );
215
- width = $this.outerWidth() - parseFloat( $this.css('padding-left') ) - parseFloat( $this.css('padding-right') ) - border;
216
- }
217
- } else {
218
- width = $this.width();
219
- }
220
- }
221
- $h.eq(indx).add( $f.eq(indx) ).css({
222
- 'min-width': width,
223
- 'max-width': width
224
- });
225
- });
370
+ // Add fixed (frozen) columns
371
+ setupFixed : function( c, wo ) {
372
+ var index, index2, $el, len, temp, $fixedColumn, $fixedTbody, $fixedContainer,
373
+ $table = c.$table,
374
+ namespace = c.namespace + 'tsscrollerFixed',
375
+ $wrapper = wo.scroller_$container,
376
+ fixedColumns = wo.scroller_fixedColumns;
377
+
378
+ $fixedColumn = $wrapper
379
+ .addClass( tscss.scrollerHasFix )
380
+ .clone()
381
+ .addClass( tscss.scrollerFixed )
382
+ .removeClass( tscss.scrollerWrap )
383
+ .attr( 'id', '' );
384
+ $fixedTbody = $fixedColumn.find( '.' + tscss.scrollerTable );
385
+ $fixedTbody.find( 'table' )
386
+ .addClass( c.namespace.slice(1) + '_extra_table' )
387
+ .attr( 'id', '' );
388
+ $fixedContainer = $fixedTbody.find( 'tbody' );
389
+
390
+ wo.scroller_$fixedColumns = $fixedColumn;
391
+
392
+ // RTL support (fixes column on right)
393
+ if ( $table.hasClass( tscss.scrollerRtl ) ) {
394
+ $fixedColumn.addClass( tscss.scrollerRtl );
395
+ }
226
396
 
227
- $tbl
228
- .closest('.tablesorter-scroller')
229
- .find('.tablesorter-scroller-reset')
230
- .removeClass('tablesorter-scroller-reset');
231
-
232
- // refresh colgroup & copy to cloned header
233
- $.tablesorter.fixColumnWidth( table );
234
- $h = $tbl.children('colgroup');
235
- if ($h.length) {
236
- b = $h[0].outerHTML;
237
- $hdr.prepend(b);
238
- if ($ft.length) {
239
- $ft.prepend(b);
240
- }
397
+ $el = $fixedColumn.find( 'tr' );
398
+ len = $el.length;
399
+ for ( index = 0; index < len; index++ ) {
400
+ $el.eq( index ).children( ':gt(' + ( fixedColumns - 1 ) + ')' ).remove();
401
+ }
402
+ $fixedColumn.hide().prependTo( $wrapper );
403
+
404
+ // look for filter widget
405
+ if ( c.$table.hasClass( 'hasFilters' ) ) {
406
+ ts.filter.bindSearch( $table, $fixedColumn.find( '.' + tscss.filter ) );
407
+ // disable/enable filters behind fixed column
408
+ $el = $wrapper.children( '.' + tscss.scrollerHeader ).find( '.' + tscss.filter );
409
+ len = $el.length;
410
+ for ( index = 0; index < len; index++ ) {
411
+ // previously disabled filter; don't mess with it! filterDisabled class added by filter widget
412
+ if ( !$el.eq( index ).hasClass( tscss.filterDisabled || 'disabled' ) ) {
413
+ // disable filters behind fixed column; don't disable visible filters
414
+ $el.eq( index ).prop( 'disabled', index < fixedColumns );
241
415
  }
416
+ }
417
+ // enable visible fixed column filters
418
+ $fixedColumn.children( '.' + tscss.scrollerHeader ).find( '.' + tscss.filter ).css( 'pointer-events', 'all' );
419
+ }
242
420
 
243
- // hide filter row because filterEnd event fires
244
- $tbl.children('thead').find('.tablesorter-filter-row').hide();
421
+ // disable/enable tab indexes behind fixed column
422
+ c.$table.children( 'thead' ).children( 'tr.' + tscss.headerRow ).children().attr( 'tabindex', -1 );
423
+ $el = wo.scroller_$header
424
+ .add( $fixedColumn.find( '.' + tscss.scrollerTable + ' table, .' + tscss.scrollerFooter + ' table' ) )
425
+ .children( 'thead' ).children( 'tr.' + tscss.headerRow );
426
+ len = $el.length;
427
+ for ( index = 0; index < len; index++ ) {
428
+ temp = $el.eq( index ).children();
429
+ for ( index2 = 0; index2 < temp.length; index2++ ) {
430
+ temp.eq( index2 ).attr( 'tabindex', index2 < fixedColumns ? -1 : 0 );
431
+ }
432
+ }
245
433
 
246
- $div.show();
247
- };
434
+ ts.bindEvents( c.table, $fixedColumn.find( '.' + tscss.header ) );
435
+
436
+ // update thead & tbody in fixed column
437
+ temp = ( 'sortEnd filterEnd ' ).split( ' ' ).join( namespace + ' ' );
438
+ c.$table
439
+ .off( temp )
440
+ .on( temp, function( event, size ) {
441
+ ts.scroller.updateFixed( c, wo, false );
442
+ })
443
+ .parent()
444
+ // *** SCROLL *** scroll fixed column along with main
445
+ .off( 'scroll' + namespace )
446
+ .on( 'scroll' + namespace, function() {
447
+ $fixedTbody.scrollTop( $( this ).scrollTop() );
448
+ });
449
+ // scroll main along with fixed column
450
+ $fixedTbody
451
+ .off( 'scroll' + namespace )
452
+ .on( 'scroll' + namespace, function() {
453
+ c.$table.parent().scrollTop( $fixedTbody.scrollTop() );
454
+ })
455
+ .scroll();
456
+
457
+ // *** ROW HIGHLIGHT ***
458
+ if ( wo.scroller_rowHighlight !== '' ) {
459
+ temp = 'mouseover mouseleave '.split( ' ' ).join( namespace + ' ' );
460
+ c.$table
461
+ .off( temp, 'tr' )
462
+ .on( temp, 'tr', function( event ) {
463
+ var indx = $( this ).index();
464
+ $fixedContainer.children().eq( indx )
465
+ .add( this )
466
+ .toggleClass( wo.scroller_rowHighlight, event.type === 'mouseover' );
467
+ });
468
+ $fixedTbody.find( 'table' )
469
+ .off( temp, 'tr' )
470
+ .on( temp, 'tr', function( event ) {
471
+ var indx = $( this ).index();
472
+ c.$tbodies.children().eq( indx )
473
+ .add( this )
474
+ .toggleClass( wo.scroller_rowHighlight, event.type === 'mouseover' );
475
+ });
476
+ }
248
477
 
249
- // Expose to external calls
250
- wo.scroller_resizeWidth = resize;
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;">' );
481
+ }
251
482
 
252
- resize();
483
+ ts.scroller.updateFixed( c, wo, true );
253
484
 
254
- $tbl.find('thead').css('visibility', 'hidden');
255
- c.isScrolling = true;
485
+ },
256
486
 
257
- tbHt = $tblWrap.parent().height();
487
+ updateFixed : function( c, wo ) {
488
+ if ( !c.isScrolling ) { return; }
489
+
490
+ // no idea why this happens, but sometimes the main table wrapper gets the scrollbar width
491
+ // subtracted from it on load and on theme change - it can be very sporatic; this fixes it.
492
+ c.$table.parent().width( wo.scroller_$container.width() );
493
+
494
+ // scroller_fixedColumns
495
+ var index, tbodyIndex, rowIndex, $tbody, $adjCol, $fb, totalRows, widths,
496
+ $table = c.$table,
497
+ $wrapper = wo.scroller_$container,
498
+
499
+ // source cells for measurement
500
+ $mainTbodies = wo.scroller_$container.children( '.' + tscss.scrollerTable ).children( 'table' ).children( 'tbody' ),
501
+ $rows = wo.scroller_$header.children( 'thead' ).children( '.' + tscss.headerRow ), // variable gets redefined
502
+
503
+ // hide fixed column during resize, or we get a FOUC
504
+ $fixedColumn = wo.scroller_$fixedColumns.hide(),
505
+
506
+ // target cells
507
+ $fixedTbodiesTable = $fixedColumn.find( '.' + tscss.scrollerTable ).children( 'table' ),
508
+ $fixedTbodies = $fixedTbodiesTable.children( 'tbody' ),
509
+ $fixedHeader = $fixedColumn.find( '.' + tscss.scrollerHeader ).children( 'table' ).children( 'thead' ),
510
+ // variables
511
+ isFirefox = ts.scroller.isFirefox,
512
+ scrollBarWidth = wo.scroller_barSetWidth,
513
+ fixedColumns = wo.scroller_fixedColumns,
514
+ // get dimensions
515
+ $temp = $table.find( 'tbody td' ),
516
+ borderRightWidth = parseInt( $temp.css( 'border-right-width' ), 10 ) || 1,
517
+ borderBottomWidth = parseInt( $temp.css( 'border-bottom-width' ), 10 ) || 1,
518
+ borderSpacing = parseInt( $temp.css( 'border-spacing' ).split( /\s/ )[ 0 ], 10 ) / 2 || 0,
519
+ totalWidth = parseInt( $table.css( 'padding-left' ), 10 ) + parseInt( $table.css( 'padding-right' ), 10 ) - borderRightWidth;
520
+
521
+ // fixed header cell height
522
+ $temp = $fixedHeader.children( '.' + tscss.headerRow );
523
+ for ( index = 0; index < $temp.length; index++ ) {
524
+ $temp.eq( index ).height( $rows.eq( index ).outerHeight() );
525
+ }
258
526
 
259
- // The header will always jump into view if scrolling the table body
260
- $tblWrap.bind('scroll', function(){
261
- if (wo.scroller_jumpToHeader) {
262
- var pos = $win.scrollTop() - $hdr.offset().top;
263
- if ($(this).scrollTop() !== 0 && pos < tbHt && pos > 0) {
264
- $win.scrollTop( $hdr.offset().top );
527
+ // body cell dimensions seem to be more accurate *shrug*
528
+ $rows = ( c.filteredRows > 0 ? c.$tbodies : $table.children( 'thead' ) ).children( 'tr:visible' );
529
+ // recalculate widths
530
+ widths = $rows.children( ':lt(' + fixedColumns + ')' ).map( function() {
531
+ totalWidth += $( this ).outerWidth() + borderSpacing;
532
+ return $( this ).outerWidth();
533
+ }).get();
534
+
535
+ // 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 );
538
+
539
+ // set fixed column height ( changes with filtering )
540
+ $fixedColumn.height( $wrapper.height() );
541
+
542
+ if ( wo.scroller_$footer.length ) {
543
+ // adjust footer row heights (text could wrap on resize)
544
+ $temp = $wrapper.children( '.' + tscss.scrollerFooter ).find( 'tfoot tr' );
545
+ $rows = $fixedColumn.find( '.' + tscss.scrollerFooter + ' tfoot tr' );
546
+ for ( index = 0; index < $rows.length; index++ ) {
547
+ $rows.eq( index ).height( $temp.eq( index ).height() );
548
+ }
549
+ }
550
+ // leave a gap under the tbody for the horizontal scrollbar
551
+ $fixedColumn.find( '.' + tscss.scrollerTable )
552
+ .height( $table.parent().height() - scrollBarWidth + borderBottomWidth );
553
+
554
+ // update fixed column tbody content, set row height & set cell widths for first row
555
+ for ( tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++ ) {
556
+ $tbody = $mainTbodies.eq( tbodyIndex );
557
+ if ( $tbody.length ) {
558
+ // get tbody
559
+ $rows = $tbody.children();
560
+ totalRows = $rows.length;
561
+ $fb = ts.processTbody( $fixedTbodiesTable, $fixedTbodies.eq( tbodyIndex ), true);
562
+ $fb.empty();
563
+ // update tbody cells after sort/filtering
564
+ for ( rowIndex = 0; rowIndex < totalRows; rowIndex++ ) {
565
+ $adjCol = $( $rows[ rowIndex ].outerHTML );
566
+ $adjCol.children( 'td, th' ).slice( fixedColumns ).remove();
567
+ // set row height
568
+ $adjCol.children().eq( 0 ).height( $rows.eq( rowIndex ).outerHeight() - ( isFirefox ? borderBottomWidth * 2 : 0 ) );
569
+ // still need to adjust tbody cell widths ( the previous row may now be filtered )
570
+ if ( rowIndex === 0 ) {
571
+ ts.scroller.setWidth( $adjCol.children().eq( 0 ), widths[ 0 ] );
265
572
  }
573
+ $fb.append( $adjCol );
574
+ }
575
+
576
+ // adjust fixed header cell widths
577
+ $temp = $fixedColumn.find( 'thead' ).children( 'tr.' + tscss.headerRow );
578
+ for ( index = 0; index < fixedColumns; index++ ) {
579
+ ts.scroller.setWidth( $temp.children( ':eq(' + index + ')' ), widths[ index ] );
266
580
  }
267
- $hdr.parent().add( $ft.parent() ).scrollLeft( $(this).scrollLeft() );
268
- });
269
581
 
582
+ // restore tbody
583
+ ts.processTbody( $fixedTbodiesTable, $fb, false );
584
+ }
270
585
  }
271
586
 
272
- // Sorting, so scroll to top
273
- if (wo.scroller_upAfterSort) {
274
- $tbl.parent().animate({ scrollTop: 0 }, 'fast');
587
+ /*** STUPID FIREFOX HACK! Since we can't hide the scrollbar with css ***/
588
+ if ( isFirefox ) {
589
+ $fixedTbodiesTable.parent().css({
590
+ 'width' : totalWidth + scrollBarWidth + borderRightWidth
591
+ });
275
592
  }
276
593
 
594
+ $fixedColumn.show();
595
+
277
596
  },
278
- remove : function(table, c){
279
- var $table = c.$table,
597
+
598
+ remove : function( c, wo ) {
599
+ var $wrap = wo.scroller_$container,
280
600
  namespace = c.namespace + 'tsscroller';
281
- $table.closest('.tablesorter-scroller').find('.tablesorter-scroller-header').remove();
282
- $table.closest('.tablesorter-scroller').find('.tablesorter-scroller-footer').remove();
283
- $table
284
- .unwrap()
285
- .find('.tablesorter-filter-row').removeClass('hideme').end()
286
- .find('thead').show().css('visibility', 'visible');
287
- $(window).unbind('resize' + namespace + ' resizeEnd' + namespace);
601
+ c.$table
602
+ .off( namespace )
603
+ .insertBefore( $wrap )
604
+ .find( 'thead' ).show().css( 'visibility', 'visible' )
605
+ .children( 'tr.' + tscss.headerRow + ' > *' ).attr( 'tabindex', 0 )
606
+ .end()
607
+ .find( '.' + tscss.filterRow ).show().removeClass( tscss.filterRowHide );
608
+ $wrap.remove();
609
+ $( window ).off( namespace );
288
610
  c.isScrolling = false;
289
611
  }
290
- });
291
612
 
292
- })(jQuery, window);
613
+ };
614
+
615
+ })( jQuery, window );