jquery-tablesorter 1.16.2 → 1.16.3

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