jquery-tablesorter 1.17.2 → 1.17.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) 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 +76 -71
  5. data/vendor/assets/javascripts/jquery-tablesorter/extras/jquery.dragtable.mod.js +1 -1
  6. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.combined.js +2647 -2576
  7. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.js +174 -119
  8. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets.js +2487 -2471
  9. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-extract.js +15 -15
  10. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-iso8601.js +1 -1
  11. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-month.js +4 -4
  12. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-range.js +1 -1
  13. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-two-digit-year.js +12 -12
  14. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-weekday.js +4 -4
  15. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date.js +1 -1
  16. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-duration.js +1 -1
  17. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-feet-inch-fraction.js +6 -6
  18. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-file-type.js +22 -22
  19. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-globalize.js +1 -1
  20. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-ignore-articles.js +15 -15
  21. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-image.js +3 -3
  22. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-input-select.js +10 -3
  23. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-metric.js +2 -2
  24. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-named-numbers.js +3 -3
  25. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-network.js +1 -1
  26. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-roman.js +4 -4
  27. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-alignChar.js +122 -121
  28. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-build-table.js +13 -13
  29. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-chart.js +2 -2
  30. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-columnSelector.js +324 -324
  31. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-columns.js +60 -60
  32. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-editable.js +219 -219
  33. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter-formatter-html5.js +360 -361
  34. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter-formatter-jui.js +666 -666
  35. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter-formatter-select2.js +124 -124
  36. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter-type-insideRange.js +1 -1
  37. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter.js +1448 -1433
  38. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-formatter.js +1 -1
  39. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-grouping.js +213 -213
  40. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-headerTitles.js +3 -3
  41. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-math.js +271 -216
  42. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-output.js +339 -320
  43. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-pager.js +1057 -1045
  44. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-print.js +109 -109
  45. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-reflow.js +114 -115
  46. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-resizable.js +360 -359
  47. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-saveSort.js +59 -59
  48. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-scroller.js +818 -806
  49. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-sort2Hash.js +128 -0
  50. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-sortTbodies.js +195 -195
  51. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-staticRow.js +90 -90
  52. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-stickyHeaders.js +257 -257
  53. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-storage.js +76 -76
  54. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-uitheme.js +170 -170
  55. metadata +3 -3
  56. data/vendor/assets/javascripts/jquery-tablesorter/extras/jquery.quicksearch.js +0 -195
@@ -1,68 +1,68 @@
1
1
  /*! Widget: saveSort */
2
2
  ;(function ($) {
3
- 'use strict';
4
- var ts = $.tablesorter || {};
3
+ 'use strict';
4
+ var ts = $.tablesorter || {};
5
5
 
6
- // this widget saves the last sort only if the
7
- // saveSort widget option is true AND the
8
- // $.tablesorter.storage function is included
9
- // **************************
10
- ts.addWidget({
11
- id: 'saveSort',
12
- priority: 20,
13
- options: {
14
- saveSort : true
15
- },
16
- init: function(table, thisWidget, c, wo) {
17
- // run widget format before all other widgets are applied to the table
18
- thisWidget.format(table, c, wo, true);
19
- },
20
- format: function(table, c, wo, init) {
21
- var stored, time,
22
- $table = c.$table,
23
- saveSort = wo.saveSort !== false, // make saveSort active/inactive; default to true
24
- sortList = { "sortList" : c.sortList };
25
- if (c.debug) {
26
- time = new Date();
27
- }
28
- if ($table.hasClass('hasSaveSort')) {
29
- if (saveSort && table.hasInitialized && ts.storage) {
30
- ts.storage( table, 'tablesorter-savesort', sortList );
31
- if (c.debug) {
32
- ts.benchmark('saveSort widget: Saving last sort: ' + c.sortList, time);
33
- }
6
+ // this widget saves the last sort only if the
7
+ // saveSort widget option is true AND the
8
+ // $.tablesorter.storage function is included
9
+ // **************************
10
+ ts.addWidget({
11
+ id: 'saveSort',
12
+ priority: 20,
13
+ options: {
14
+ saveSort : true
15
+ },
16
+ init: function(table, thisWidget, c, wo) {
17
+ // run widget format before all other widgets are applied to the table
18
+ thisWidget.format(table, c, wo, true);
19
+ },
20
+ format: function(table, c, wo, init) {
21
+ var stored, time,
22
+ $table = c.$table,
23
+ saveSort = wo.saveSort !== false, // make saveSort active/inactive; default to true
24
+ sortList = { 'sortList' : c.sortList };
25
+ if (c.debug) {
26
+ time = new Date();
34
27
  }
35
- } else {
36
- // set table sort on initial run of the widget
37
- $table.addClass('hasSaveSort');
38
- sortList = '';
39
- // get data
40
- if (ts.storage) {
41
- stored = ts.storage( table, 'tablesorter-savesort' );
42
- sortList = (stored && stored.hasOwnProperty('sortList') && $.isArray(stored.sortList)) ? stored.sortList : '';
43
- if (c.debug) {
44
- ts.benchmark('saveSort: Last sort loaded: "' + sortList + '"', time);
28
+ if ($table.hasClass('hasSaveSort')) {
29
+ if (saveSort && table.hasInitialized && ts.storage) {
30
+ ts.storage( table, 'tablesorter-savesort', sortList );
31
+ if (c.debug) {
32
+ console.log('saveSort widget: Saving last sort: ' + c.sortList + ts.benchmark(time));
33
+ }
34
+ }
35
+ } else {
36
+ // set table sort on initial run of the widget
37
+ $table.addClass('hasSaveSort');
38
+ sortList = '';
39
+ // get data
40
+ if (ts.storage) {
41
+ stored = ts.storage( table, 'tablesorter-savesort' );
42
+ sortList = (stored && stored.hasOwnProperty('sortList') && $.isArray(stored.sortList)) ? stored.sortList : '';
43
+ if (c.debug) {
44
+ console.log('saveSort: Last sort loaded: "' + sortList + '"' + ts.benchmark(time));
45
+ }
46
+ $table.bind('saveSortReset', function(event) {
47
+ event.stopPropagation();
48
+ ts.storage( table, 'tablesorter-savesort', '' );
49
+ });
50
+ }
51
+ // init is true when widget init is run, this will run this widget before all other widgets have initialized
52
+ // this method allows using this widget in the original tablesorter plugin; but then it will run all widgets twice.
53
+ if (init && sortList && sortList.length > 0) {
54
+ c.sortList = sortList;
55
+ } else if (table.hasInitialized && sortList && sortList.length > 0) {
56
+ // update sort change
57
+ $table.trigger('sorton', [ sortList ]);
45
58
  }
46
- $table.bind('saveSortReset', function(event) {
47
- event.stopPropagation();
48
- ts.storage( table, 'tablesorter-savesort', '' );
49
- });
50
- }
51
- // init is true when widget init is run, this will run this widget before all other widgets have initialized
52
- // this method allows using this widget in the original tablesorter plugin; but then it will run all widgets twice.
53
- if (init && sortList && sortList.length > 0) {
54
- c.sortList = sortList;
55
- } else if (table.hasInitialized && sortList && sortList.length > 0) {
56
- // update sort change
57
- $table.trigger('sorton', [sortList]);
58
59
  }
60
+ },
61
+ remove: function(table, c) {
62
+ c.$table.removeClass('hasSaveSort');
63
+ // clear storage
64
+ if (ts.storage) { ts.storage( table, 'tablesorter-savesort', '' ); }
59
65
  }
60
- },
61
- remove: function(table, c) {
62
- c.$table.removeClass('hasSaveSort');
63
- // clear storage
64
- if (ts.storage) { ts.storage( table, 'tablesorter-savesort', '' ); }
65
- }
66
- });
66
+ });
67
67
 
68
68
  })(jQuery);
@@ -1,4 +1,4 @@
1
- /*! Widget: scroller - updated 5/17/2015 (v2.22.0) *//*
1
+ /*! Widget: scroller - updated 7/28/2015 (v2.22.4) *//*
2
2
  Copyright (C) 2011 T. Connell & Associates, Inc.
3
3
 
4
4
  Dual-licensed under the MIT and GPL licenses
@@ -33,873 +33,885 @@
33
33
  */
34
34
  /*jshint browser:true, jquery:true, unused:false */
35
35
  ;( function( $, window ) {
36
- 'use strict';
37
-
38
- var ts = $.tablesorter,
39
- tscss = ts.css;
40
-
41
- $.extend( ts.css, {
42
- scrollerWrap : 'tablesorter-scroller',
43
- scrollerHeader : 'tablesorter-scroller-header',
44
- scrollerTable : 'tablesorter-scroller-table',
45
- scrollerFooter : 'tablesorter-scroller-footer',
46
- scrollerFixed : 'tablesorter-scroller-fixed',
47
- scrollerFixedPanel : 'tablesorter-scroller-fixed-panel',
48
- scrollerHasFix : 'tablesorter-scroller-has-fixed-columns',
49
- scrollerHideColumn : 'tablesorter-scroller-hidden-column',
50
- scrollerHideElement : 'tablesorter-scroller-hidden',
51
- scrollerSpacerRow : 'tablesorter-scroller-spacer',
52
- scrollerBarSpacer : 'tablesorter-scroller-bar-spacer',
53
- scrollerAddedHeight : 'tablesorter-scroller-added-height',
54
- scrollerHack : 'tablesorter-scroller-scrollbar-hack',
55
- // class name on table cannot start with 'tablesorter-' or the
56
- // suffix "scroller-rtl" will match as a theme name
57
- scrollerRtl : 'ts-scroller-rtl'
58
- });
59
-
60
- ts.addWidget({
61
- id : 'scroller',
62
- priority : 60, // run after the filter widget
63
- options : {
64
- scroller_height : 300,
65
- // pop table header into view while scrolling up the page
66
- scroller_jumpToHeader : true,
67
- // scroll tbody to top after sorting
68
- scroller_upAfterSort : true,
69
- // set number of fixed columns
70
- scroller_fixedColumns : 0,
71
- // add hover highlighting to the fixed column (disable if it causes slowing)
72
- scroller_rowHighlight : 'hover',
73
- // add a fixed column overlay for styling
74
- scroller_addFixedOverlay : false,
75
- // In tablesorter v2.19.0 the scroll bar width is auto-detected
76
- // add a value here to override the auto-detected setting
77
- scroller_barWidth : null
78
- },
79
- format : function( table, c, wo ) {
80
- if ( !c.isScrolling ) {
81
- // initialize here instead of in widget init to give the
82
- // filter widget time to finish building the filter row
83
- ts.scroller.setup( c, wo );
84
- }
85
- },
86
- remove : function( table, c, wo ) {
87
- ts.scroller.remove( c, wo );
88
- }
89
- });
90
-
91
- /* Add window resizeEnd event */
92
- ts.window_resize = function() {
93
- if ( ts.timer_resize ) {
94
- clearTimeout( ts.timer_resize );
95
- }
96
- ts.timer_resize = setTimeout( function() {
97
- $( window ).trigger( 'resizeEnd' );
98
- }, 250 );
99
- };
100
-
101
- // Add extra scroller css
102
- $( function() {
103
- var style = '<style>' +
104
- /* overall wrapper & table section wrappers */
105
- '.' + tscss.scrollerWrap + ' { position: relative; overflow: hidden; }' +
106
- /* add border-box sizing to all scroller widget tables; see #135 */
107
- '.' + tscss.scrollerWrap + ' * { box-sizing: border-box; }' +
108
- '.' + tscss.scrollerHeader + ', .' + tscss.scrollerFooter + ' { position: relative; overflow: hidden; }' +
109
- '.' + tscss.scrollerHeader + ' table.' + tscss.table + ' { margin-bottom: 0; }' +
110
- /* always leave the scroll bar visible for tbody, or table overflows into the scrollbar
111
- when height < max height (filtering) */
112
- '.' + tscss.scrollerTable + ' { position: relative; overflow: auto; }' +
113
- '.' + tscss.scrollerTable + ' table.' + tscss.table +
114
- ' { border-top: 0; margin-top: 0; margin-bottom: 0; overflow: hidden; }' +
115
- /* hide footer in original table */
116
- '.' + tscss.scrollerTable + ' tfoot, .' + tscss.scrollerHideElement + ', .' + tscss.scrollerHideColumn +
117
- ' { display: none; }' +
118
-
119
- /*** fixed column ***/
120
- /* disable pointer-events on fixed column wrapper or the user can't interact with the horizontal scrollbar */
121
- '.' + tscss.scrollerFixed + ', .' + tscss.scrollerFixed + ' .' + tscss.scrollerFixedPanel +
122
- ' { pointer-events: none; }' +
123
- /* enable pointer-events for fixed column children; see #135 & #878 */
124
- '.' + tscss.scrollerFixed + ' > div { pointer-events: all; }' +
125
- '.' + tscss.scrollerWrap + ' .' + tscss.scrollerFixed + ' { position: absolute; top: 0; z-index: 1; left: 0 } ' +
126
- '.' + tscss.scrollerWrap + ' .' + tscss.scrollerFixed + '.' + tscss.scrollerRtl + ' { left: auto; right: 0 } ' +
127
- /* add horizontal scroll bar; set to "auto", see #135 */
128
- '.' + tscss.scrollerWrap + '.' + tscss.scrollerHasFix + ' > .' + tscss.scrollerTable + ' { overflow: auto; }' +
129
- /* need to position the tbody & tfoot absolutely to hide the scrollbar & move the footer
130
- below the horizontal scrollbar */
131
- '.' + tscss.scrollerFixed + ' .' + tscss.scrollerFooter + ' { position: absolute; bottom: 0; }' +
132
- /* hide fixed tbody scrollbar - see http://goo.gl/VsLe6n - set overflow to auto here for mousewheel scroll */
133
- '.' + tscss.scrollerFixed + ' .' + tscss.scrollerTable +
134
- ' { position: relative; left: 0; overflow: auto; -ms-overflow-style: none; }' +
135
- '.' + tscss.scrollerFixed + ' .' + tscss.scrollerTable + '::-webkit-scrollbar { display: none; }' +
136
- /*** fixed column panel ***/
137
- '.' + tscss.scrollerWrap + ' .' + tscss.scrollerFixedPanel +
138
- ' { position: absolute; top: 0; bottom: 0; z-index: 2; left: 0; right: 0; } ' +
139
- '</style>';
140
- $( style ).appendTo( 'body' );
141
- });
142
-
143
- ts.scroller = {
144
-
145
- // Ugh.. Firefox misbehaves, so it needs to be detected
146
- isFirefox : navigator.userAgent.toLowerCase().indexOf( 'firefox' ) > -1,
147
- // old IE needs a wrap to hide the fixed column scrollbar; http://stackoverflow.com/a/24408672/145346
148
- isOldIE : document.all && !window.atob,
149
- isIE : ( document.all && !window.atob ) || navigator.appVersion.indexOf( 'Trident/' ) > 0,
150
- // http://stackoverflow.com/questions/7944460/detect-safari-browser - needed to position scrolling body
151
- // when the table is set up in RTL direction
152
- isSafari : navigator.userAgent.toLowerCase().indexOf( 'safari' ) > -1 &&
153
- navigator.userAgent.toLowerCase().indexOf( 'chrome' ) === -1,
154
-
155
- hasScrollBar : function( $target, checkWidth ) {
156
- if ( checkWidth ) {
157
- return $target.get(0).scrollWidth > $target.width();
158
- } else {
159
- return $target.get(0).scrollHeight > $target.height();
36
+ 'use strict';
37
+
38
+ var ts = $.tablesorter,
39
+ tscss = ts.css;
40
+
41
+ $.extend( ts.css, {
42
+ scrollerWrap : 'tablesorter-scroller',
43
+ scrollerHeader : 'tablesorter-scroller-header',
44
+ scrollerTable : 'tablesorter-scroller-table',
45
+ scrollerFooter : 'tablesorter-scroller-footer',
46
+ scrollerFixed : 'tablesorter-scroller-fixed',
47
+ scrollerFixedPanel : 'tablesorter-scroller-fixed-panel',
48
+ scrollerHasFix : 'tablesorter-scroller-has-fixed-columns',
49
+ scrollerHideColumn : 'tablesorter-scroller-hidden-column',
50
+ scrollerHideElement : 'tablesorter-scroller-hidden',
51
+ scrollerSpacerRow : 'tablesorter-scroller-spacer',
52
+ scrollerBarSpacer : 'tablesorter-scroller-bar-spacer',
53
+ scrollerAddedHeight : 'tablesorter-scroller-added-height',
54
+ scrollerHack : 'tablesorter-scroller-scrollbar-hack',
55
+ // class name on table cannot start with 'tablesorter-' or the
56
+ // suffix 'scroller-rtl' will match as a theme name
57
+ scrollerRtl : 'ts-scroller-rtl'
58
+ });
59
+
60
+ ts.addWidget({
61
+ id : 'scroller',
62
+ priority : 60, // run after the filter widget
63
+ options : {
64
+ scroller_height : 300,
65
+ // pop table header into view while scrolling up the page
66
+ scroller_jumpToHeader : true,
67
+ // scroll tbody to top after sorting
68
+ scroller_upAfterSort : true,
69
+ // set number of fixed columns
70
+ scroller_fixedColumns : 0,
71
+ // add hover highlighting to the fixed column (disable if it causes slowing)
72
+ scroller_rowHighlight : 'hover',
73
+ // add a fixed column overlay for styling
74
+ scroller_addFixedOverlay : false,
75
+ // In tablesorter v2.19.0 the scroll bar width is auto-detected
76
+ // add a value here to override the auto-detected setting
77
+ scroller_barWidth : null
78
+ },
79
+ format : function( table, c, wo ) {
80
+ if ( !c.isScrolling ) {
81
+ // initialize here instead of in widget init to give the
82
+ // filter widget time to finish building the filter row
83
+ ts.scroller.setup( c, wo );
84
+ }
85
+ },
86
+ remove : function( table, c, wo ) {
87
+ ts.scroller.remove( c, wo );
160
88
  }
161
- },
89
+ });
162
90
 
163
- setWidth : function( $el, width ) {
164
- $el.css({
165
- 'width' : width,
166
- 'min-width' : width,
167
- 'max-width' : width
168
- });
169
- },
170
-
171
- // modified from http://davidwalsh.name/detect-scrollbar-width
172
- getBarWidth : function() {
173
- var $div = $( '<div>' ).css({
174
- 'position' : 'absolute',
175
- 'top' : '-9999px',
176
- 'left' : 0,
177
- 'width' : '100px',
178
- 'height' : '100px',
179
- 'overflow' : 'scroll',
180
- 'visibility' : 'hidden'
181
- }).appendTo( 'body' ),
182
- div = $div[0],
183
- barWidth = div.offsetWidth - div.clientWidth;
184
- $div.remove();
185
- return barWidth;
186
- },
187
-
188
- setup : function( c, wo ) {
189
- var maxHt, tbHt, $hdr, $t, $hCells, $fCells, $tableWrap, events, tmp,
190
- $win = $( window ),
191
- tsScroller = ts.scroller,
192
- namespace = c.namespace + 'tsscroller',
193
- $foot = $(),
194
- // c.namespace contains a unique tablesorter ID, per table
195
- id = c.namespace.slice( 1 ) + 'tsscroller',
196
- $table = c.$table;
197
-
198
- // force config.widthFixed option - this helps maintain proper alignment across cloned tables
199
- c.widthFixed = true;
200
-
201
- wo.scroller_calcWidths = [];
202
- wo.scroller_saved = [ 0, 0 ];
203
- wo.scroller_isBusy = true;
204
-
205
- // set scrollbar width & allow setting width to zero
206
- wo.scroller_barSetWidth = wo.scroller_barWidth !== null ?
207
- wo.scroller_barWidth :
208
- ( tsScroller.getBarWidth() || 15 );
209
-
210
- maxHt = wo.scroller_height || 300;
211
-
212
- $hdr = $( '<table class="' + $table.attr( 'class' ) + '" cellpadding=0 cellspacing=0>' +
213
- $table.children( 'thead' )[ 0 ].outerHTML + '</table>' );
214
- wo.scroller_$header = $hdr.addClass( c.namespace.slice( 1 ) + '_extra_table' );
215
-
216
- $t = $table.children( 'tfoot' );
217
- if ( $t.length ) {
218
- $foot = $( '<table class="' + $table.attr( 'class' ) +
219
- '" cellpadding=0 cellspacing=0 style="margin-top:0"></table>' )
220
- .addClass( c.namespace.slice( 1 ) + '_extra_table' )
221
- // maintain any bindings on the tfoot cells
222
- .append( $t.clone( true ) )
223
- .wrap( '<div class="' + tscss.scrollerFooter + '"/>' );
224
- $fCells = $foot.children( 'tfoot' ).eq( 0 ).children( 'tr' ).children();
91
+ /* Add window resizeEnd event */
92
+ ts.window_resize = function() {
93
+ if ( ts.timer_resize ) {
94
+ clearTimeout( ts.timer_resize );
225
95
  }
226
- wo.scroller_$footer = $foot;
96
+ ts.timer_resize = setTimeout( function() {
97
+ $( window ).trigger( 'resizeEnd' );
98
+ }, 250 );
99
+ };
100
+
101
+ // Add extra scroller css
102
+ $( function() {
103
+ var style = '<style>' +
104
+ /* overall wrapper & table section wrappers */
105
+ '.' + tscss.scrollerWrap + ' { position: relative; overflow: hidden; }' +
106
+ /* add border-box sizing to all scroller widget tables; see #135 */
107
+ '.' + tscss.scrollerWrap + ' * { box-sizing: border-box; }' +
108
+ '.' + tscss.scrollerHeader + ', .' + tscss.scrollerFooter + ' { position: relative; overflow: hidden; }' +
109
+ '.' + tscss.scrollerHeader + ' table.' + tscss.table + ' { margin-bottom: 0; }' +
110
+ /* always leave the scroll bar visible for tbody, or table overflows into the scrollbar
111
+ when height < max height (filtering) */
112
+ '.' + tscss.scrollerTable + ' { position: relative; overflow: auto; }' +
113
+ '.' + tscss.scrollerTable + ' table.' + tscss.table +
114
+ ' { border-top: 0; margin-top: 0; margin-bottom: 0; overflow: hidden; }' +
115
+ /* hide footer in original table */
116
+ '.' + tscss.scrollerTable + ' tfoot, .' + tscss.scrollerHideElement + ', .' + tscss.scrollerHideColumn +
117
+ ' { display: none; }' +
118
+
119
+ /*** fixed column ***/
120
+ /* disable pointer-events on fixed column wrapper or the user can't interact with the horizontal scrollbar */
121
+ '.' + tscss.scrollerFixed + ', .' + tscss.scrollerFixed + ' .' + tscss.scrollerFixedPanel +
122
+ ' { pointer-events: none; }' +
123
+ /* enable pointer-events for fixed column children; see #135 & #878 */
124
+ '.' + tscss.scrollerFixed + ' > div { pointer-events: all; }' +
125
+ '.' + tscss.scrollerWrap + ' .' + tscss.scrollerFixed + ' { position: absolute; top: 0; z-index: 1; left: 0 } ' +
126
+ '.' + tscss.scrollerWrap + ' .' + tscss.scrollerFixed + '.' + tscss.scrollerRtl + ' { left: auto; right: 0 } ' +
127
+ /* add horizontal scroll bar; set to 'auto', see #135 */
128
+ '.' + tscss.scrollerWrap + '.' + tscss.scrollerHasFix + ' > .' + tscss.scrollerTable + ' { overflow: auto; }' +
129
+ /* need to position the tbody & tfoot absolutely to hide the scrollbar & move the footer
130
+ below the horizontal scrollbar */
131
+ '.' + tscss.scrollerFixed + ' .' + tscss.scrollerFooter + ' { position: absolute; bottom: 0; }' +
132
+ /* hide fixed tbody scrollbar - see http://goo.gl/VsLe6n - set overflow to auto here for mousewheel scroll */
133
+ '.' + tscss.scrollerFixed + ' .' + tscss.scrollerTable +
134
+ ' { position: relative; left: 0; overflow: auto; -ms-overflow-style: none; }' +
135
+ '.' + tscss.scrollerFixed + ' .' + tscss.scrollerTable + '::-webkit-scrollbar { display: none; }' +
136
+ /*** fixed column panel ***/
137
+ '.' + tscss.scrollerWrap + ' .' + tscss.scrollerFixedPanel +
138
+ ' { position: absolute; top: 0; bottom: 0; z-index: 2; left: 0; right: 0; } ' +
139
+ '</style>';
140
+ $( style ).appendTo( 'body' );
141
+ });
142
+
143
+ ts.scroller = {
144
+
145
+ // Ugh.. Firefox misbehaves, so it needs to be detected
146
+ isFirefox : navigator.userAgent.toLowerCase().indexOf( 'firefox' ) > -1,
147
+ // old IE needs a wrap to hide the fixed column scrollbar; http://stackoverflow.com/a/24408672/145346
148
+ isOldIE : document.all && !window.atob,
149
+ isIE : ( document.all && !window.atob ) || navigator.appVersion.indexOf( 'Trident/' ) > 0,
150
+ // http://stackoverflow.com/questions/7944460/detect-safari-browser - needed to position scrolling body
151
+ // when the table is set up in RTL direction
152
+ isSafari : navigator.userAgent.toLowerCase().indexOf( 'safari' ) > -1 &&
153
+ navigator.userAgent.toLowerCase().indexOf( 'chrome' ) === -1,
154
+
155
+ hasScrollBar : function( $target, checkWidth ) {
156
+ if ( checkWidth ) {
157
+ return $target.get(0).scrollWidth > $target.width();
158
+ } else {
159
+ return $target.get(0).scrollHeight > $target.height();
160
+ }
161
+ },
227
162
 
228
- $table
229
- .wrap( '<div id="' + id + '" class="' + tscss.scrollerWrap + '" />' )
230
- .before( $hdr )
231
- // shrink filter row but don't completely hide it because the inputs/selectors may distort the columns
232
- .find( '.' + tscss.filterRow )
233
- .addClass( tscss.filterRowHide );
163
+ setWidth : function( $el, width ) {
164
+ $el.css({
165
+ 'width' : width,
166
+ 'min-width' : width,
167
+ 'max-width' : width
168
+ });
169
+ },
170
+
171
+ // modified from http://davidwalsh.name/detect-scrollbar-width
172
+ getBarWidth : function() {
173
+ var $div = $( '<div>' ).css({
174
+ 'position' : 'absolute',
175
+ 'top' : '-9999px',
176
+ 'left' : 0,
177
+ 'width' : '100px',
178
+ 'height' : '100px',
179
+ 'overflow' : 'scroll',
180
+ 'visibility' : 'hidden'
181
+ }).appendTo( 'body' ),
182
+ div = $div[0],
183
+ barWidth = div.offsetWidth - div.clientWidth;
184
+ $div.remove();
185
+ return barWidth;
186
+ },
187
+
188
+ setup : function( c, wo ) {
189
+ var maxHt, tbHt, $hdr, $t, $hCells, $fCells, $tableWrap, events, tmp,
190
+ $win = $( window ),
191
+ tsScroller = ts.scroller,
192
+ namespace = c.namespace + 'tsscroller',
193
+ $foot = $(),
194
+ // c.namespace contains a unique tablesorter ID, per table
195
+ id = c.namespace.slice( 1 ) + 'tsscroller',
196
+ $table = c.$table;
197
+
198
+ // force config.widthFixed option - this helps maintain proper alignment across cloned tables
199
+ c.widthFixed = true;
200
+
201
+ wo.scroller_calcWidths = [];
202
+ wo.scroller_saved = [ 0, 0 ];
203
+ wo.scroller_isBusy = true;
204
+
205
+ // set scrollbar width & allow setting width to zero
206
+ wo.scroller_barSetWidth = wo.scroller_barWidth !== null ?
207
+ wo.scroller_barWidth :
208
+ ( tsScroller.getBarWidth() || 15 );
209
+
210
+ maxHt = wo.scroller_height || 300;
211
+
212
+ $hdr = $( '<table class="' + $table.attr( 'class' ) + '" cellpadding=0 cellspacing=0>' +
213
+ $table.children( 'thead' )[ 0 ].outerHTML + '</table>' );
214
+ wo.scroller_$header = $hdr.addClass( c.namespace.slice( 1 ) + '_extra_table' );
215
+
216
+ $t = $table.children( 'tfoot' );
217
+ if ( $t.length ) {
218
+ $foot = $( '<table class="' + $table.attr( 'class' ) +
219
+ '" cellpadding=0 cellspacing=0 style="margin-top:0"></table>' )
220
+ .addClass( c.namespace.slice( 1 ) + '_extra_table' )
221
+ // maintain any bindings on the tfoot cells
222
+ .append( $t.clone( true ) )
223
+ .wrap( '<div class="' + tscss.scrollerFooter + '"/>' );
224
+ $fCells = $foot.children( 'tfoot' ).eq( 0 ).children( 'tr' ).children();
225
+ }
226
+ wo.scroller_$footer = $foot;
234
227
 
235
- wo.scroller_$container = $table.parent();
228
+ $table
229
+ .wrap( '<div id="' + id + '" class="' + tscss.scrollerWrap + '" />' )
230
+ .before( $hdr )
231
+ // shrink filter row but don't completely hide it because the inputs/selectors may distort the columns
232
+ .find( '.' + tscss.filterRow )
233
+ .addClass( tscss.filterRowHide );
236
234
 
237
- if ( $foot.length ) {
238
- // $foot.parent() to include <div> wrapper
239
- $table.after( $foot.parent() );
240
- }
235
+ wo.scroller_$container = $table.parent();
241
236
 
242
- $hCells = $hdr
243
- .wrap( '<div class="' + tscss.scrollerHeader + '" />' )
244
- .find( '.' + tscss.header );
237
+ if ( $foot.length ) {
238
+ // $foot.parent() to include <div> wrapper
239
+ $table.after( $foot.parent() );
240
+ }
245
241
 
246
- // use max-height, so the height resizes dynamically while filtering
247
- $table.wrap( '<div class="' + tscss.scrollerTable + '" style="max-height:' + maxHt + 'px;" />' );
248
- $tableWrap = $table.parent();
242
+ $hCells = $hdr
243
+ .wrap( '<div class="' + tscss.scrollerHeader + '" />' )
244
+ .find( '.' + tscss.header );
249
245
 
250
- // make scroller header sortable
251
- ts.bindEvents( c.table, $hCells );
246
+ // use max-height, so the height resizes dynamically while filtering
247
+ $table.wrap( '<div class="' + tscss.scrollerTable + '" style="max-height:' + maxHt + 'px;" />' );
248
+ $tableWrap = $table.parent();
252
249
 
253
- // look for filter widget
254
- if ( $table.hasClass( 'hasFilters' ) ) {
255
- ts.filter.bindSearch( $table, $hdr.find( '.' + tscss.filter ) );
256
- }
250
+ // make scroller header sortable
251
+ ts.bindEvents( c.table, $hCells );
257
252
 
258
- $table
259
- .find( 'thead' )
260
- .addClass( tscss.scrollerHideElement );
253
+ // look for filter widget
254
+ if ( $table.hasClass( 'hasFilters' ) ) {
255
+ ts.filter.bindSearch( $table, $hdr.find( '.' + tscss.filter ) );
256
+ }
261
257
 
262
- tbHt = $tableWrap.parent().height();
258
+ $table
259
+ .find( 'thead' )
260
+ .addClass( tscss.scrollerHideElement );
261
+
262
+ tbHt = $tableWrap.parent().height();
263
+
264
+ // The header will always jump into view if scrolling the table body
265
+ $tableWrap
266
+ .off( 'scroll' + namespace )
267
+ .on( 'scroll' + namespace, function() {
268
+ if ( wo.scroller_jumpToHeader ) {
269
+ var pos = $win.scrollTop() - $hdr.offset().top;
270
+ if ( $( this ).scrollTop() !== 0 && pos < tbHt && pos > 0 ) {
271
+ $win.scrollTop( $hdr.offset().top );
272
+ }
273
+ }
274
+ $hdr
275
+ .parent()
276
+ .add( $foot.parent() )
277
+ .scrollLeft( $( this ).scrollLeft() );
278
+ });
263
279
 
264
- // The header will always jump into view if scrolling the table body
265
- $tableWrap
266
- .off( 'scroll' + namespace )
267
- .on( 'scroll' + namespace, function() {
268
- if ( wo.scroller_jumpToHeader ) {
269
- var pos = $win.scrollTop() - $hdr.offset().top;
270
- if ( $( this ).scrollTop() !== 0 && pos < tbHt && pos > 0 ) {
271
- $win.scrollTop( $hdr.offset().top );
280
+ // resize/update events - filterEnd fires after "tablesorter-initialized" and "updateComplete"
281
+ events = ( ( ts.hasWidget( c.table, 'filter' ) ? 'filterEnd' : 'tablesorter-initialized updateComplete' ) +
282
+ ' sortEnd pagerComplete columnUpdate ' ).split( ' ' ).join( namespace + ' ' );
283
+
284
+ $table
285
+ .off( namespace )
286
+ .on( 'sortEnd filterEnd'.split( ' ' ).join( namespace + ' ' ), function( event ) {
287
+ // Sorting, so scroll to top
288
+ if ( event.type === 'sortEnd' && wo.scroller_upAfterSort ) {
289
+ $tableWrap.animate({
290
+ scrollTop : 0
291
+ }, 'fast' );
292
+ } else if ( wo.scroller_fixedColumns ) {
293
+ setTimeout( function() {
294
+ // restore previous scroll position
295
+ $tableWrap
296
+ .scrollTop( wo.scroller_saved[1] )
297
+ .scrollLeft( wo.scroller_saved[0] );
298
+ tsScroller.updateFixed( c, wo );
299
+ }, 0 );
272
300
  }
273
- }
274
- $hdr
275
- .parent()
276
- .add( $foot.parent() )
277
- .scrollLeft( $( this ).scrollLeft() );
278
- });
301
+ })
302
+ .on( 'setFixedColumnSize' + namespace, function( event, size ) {
303
+ var $wrap = wo.scroller_$container;
304
+ if ( typeof size !== 'undefined' && !isNaN( size ) ) {
305
+ wo.scroller_fixedColumns = parseInt( size, 10 );
306
+ }
307
+ // remove fixed columns
308
+ tsScroller.removeFixed( c, wo );
309
+ size = wo.scroller_fixedColumns;
310
+ if ( size > 0 && size < c.columns - 1 ) {
311
+ tsScroller.updateFixed( c, wo );
312
+ } else if ( $wrap.hasClass( tscss.scrollerHasFix ) ) {
313
+ $wrap.removeClass( tscss.scrollerHasFix );
314
+ // resize needed to make tables full width
315
+ tsScroller.resize( c, wo );
316
+ }
317
+ })
318
+ .on( events, function( event ) {
319
+ // Stop from running twice with pager
320
+ if ( ts.hasWidget( 'pager' ) && event.type === 'updateComplete' ) {
321
+ return;
322
+ }
323
+ if ( wo.scroller_fixedColumns > 0 ) {
324
+ tsScroller.updateFixed( c, wo );
325
+ }
326
+ // adjust column sizes after an update
327
+ tsScroller.resize( c, wo );
328
+ });
279
329
 
280
- // resize/update events
281
- events = ( ( ts.hasWidget( c.table, 'filter' ) ? 'filterEnd' : 'tablesorter-initialized' ) +
282
- ' updateComplete pagerComplete columnUpdate ' ).split( ' ' ).join( namespace + ' ' );
283
-
284
- $table
285
- .off( namespace )
286
- .on( 'sortEnd filterEnd'.split( ' ' ).join( namespace + ' ' ), function( event ) {
287
- // Sorting, so scroll to top
288
- if ( event.type === 'sortEnd' && wo.scroller_upAfterSort ) {
289
- $tableWrap.animate({
290
- scrollTop : 0
291
- }, 'fast' );
292
- } else if ( wo.scroller_fixedColumns ) {
293
- setTimeout( function() {
294
- // restore previous scroll position
295
- $tableWrap
296
- .scrollTop( wo.scroller_saved[1] )
297
- .scrollLeft( wo.scroller_saved[0] );
298
- tsScroller.updateFixed( c, wo, false );
299
- }, 0 );
300
- }
301
- })
302
- .on( 'setFixedColumnSize' + namespace, function( event, size ) {
303
- var $wrap = wo.scroller_$container;
304
- if ( typeof size !== 'undefined' && !isNaN( size ) ) {
305
- wo.scroller_fixedColumns = parseInt( size, 10 );
306
- }
307
- // remove fixed columns
308
- tsScroller.removeFixed( c, wo );
309
- size = wo.scroller_fixedColumns;
310
- if ( size > 0 && size < c.columns - 1 ) {
311
- tsScroller.updateFixed( c, wo );
312
- } else if ( $wrap.hasClass( tscss.scrollerHasFix ) ) {
313
- $wrap.removeClass( tscss.scrollerHasFix );
314
- // resize needed to make tables full width
330
+ // Setup window.resizeEnd event
331
+ $win
332
+ .off( 'resize resizeEnd '.split( ' ' ).join( namespace + ' ' ) )
333
+ .on( 'resize' + namespace, ts.window_resize )
334
+ .on( 'resizeEnd' + namespace, function() {
335
+ // IE calls resize when you modify content, so we have to unbind the resize event
336
+ // so we don't end up with an infinite loop. we can rebind after we're done.
337
+ $win.off( 'resize' + namespace, ts.window_resize );
315
338
  tsScroller.resize( c, wo );
316
- }
317
- })
318
- .on( events, function( event ) {
319
- // Stop from running twice with pager
320
- if ( ts.hasWidget( 'pager' ) && event.type === 'updateComplete' ) {
321
- return;
322
- }
323
- if ( wo.scroller_fixedColumns > 0 ) {
324
- tsScroller.updateFixed( c, wo, false );
325
- }
326
- // adjust column sizes after an update
327
- tsScroller.resize( c, wo );
328
- });
339
+ $win.on( 'resize' + namespace, ts.window_resize );
340
+ $tableWrap.trigger( 'scroll' + namespace );
341
+ });
329
342
 
330
- // Setup window.resizeEnd event
331
- $win
332
- .off( 'resize resizeEnd '.split( ' ' ).join( namespace + ' ' ) )
333
- .on( 'resize' + namespace, ts.window_resize )
334
- .on( 'resizeEnd' + namespace, function() {
335
- // IE calls resize when you modify content, so we have to unbind the resize event
336
- // so we don't end up with an infinite loop. we can rebind after we're done.
337
- $win.off( 'resize' + namespace, ts.window_resize );
338
- tsScroller.resize( c, wo );
339
- $win.on( 'resize' + namespace, ts.window_resize );
340
- $tableWrap.trigger( 'scroll' + namespace );
341
- });
343
+ // initialization flag
344
+ c.isScrolling = true;
342
345
 
343
- // initialization flag
344
- c.isScrolling = true;
345
-
346
- tsScroller.updateFixed( c, wo );
347
-
348
- },
349
-
350
- resize : function( c, wo ) {
351
- if ( wo.scroller_isBusy ) { return; }
352
- var index, borderWidth, setWidth, $hCells, $bCells, $fCells, $headers, $this, temp,
353
- tsScroller = ts.scroller,
354
- $container = wo.scroller_$container,
355
- $table = c.$table,
356
- $tableWrap = $table.parent(),
357
- $hdr = wo.scroller_$header,
358
- $foot = wo.scroller_$footer,
359
- id = c.namespace.slice( 1 ) + 'tsscroller',
360
- // Hide other scrollers so we can resize
361
- $div = $( 'div.' + tscss.scrollerWrap + '[id!="' + id + '"]' )
362
- .addClass( tscss.scrollerHideElement ),
363
- row = '<tr class="' + tscss.scrollerSpacerRow + ' ' + c.selectorRemove.slice(1) + '">';
364
-
365
- wo.scroller_calcWidths = [];
366
-
367
- // Remove fixed so we get proper widths and heights
368
- tsScroller.removeFixed( c, wo );
369
- $container.find( '.' + tscss.scrollerSpacerRow ).remove();
370
- // remove ts added colgroups
371
- $container.find( '.' + ts.css.colgroup ).remove();
372
-
373
- // show original table elements to get proper alignment
374
- $table
375
- .find( '.' + tscss.scrollerHideElement )
376
- .removeClass( tscss.scrollerHideElement );
377
-
378
- // include left & right border widths
379
- borderWidth = parseInt( $table.css( 'border-left-width' ), 10 );
380
-
381
- $headers = c.$headerIndexed;
382
-
383
- for ( index = 0; index < c.columns; index++ ) {
384
- $this = $headers[ index ];
385
- // code from https://github.com/jmosbech/StickyTableHeaders
386
- if ( $this.css( 'box-sizing' ) === 'border-box' ) {
387
- setWidth = $this.outerWidth();
388
- } else {
389
- if ( $hCells.eq( index ).css( 'border-collapse' ) === 'collapse' ) {
390
- if ( $this.length && window.getComputedStyle ) {
391
- setWidth = parseFloat( window.getComputedStyle( $this[ 0 ], null ).width );
346
+ tsScroller.updateFixed( c, wo );
347
+
348
+ // updateAll called - need to give the browser time to adjust the layout
349
+ // before calculating fix column widths
350
+ if ( c.table.hasInitialized && c.isScrolling ) {
351
+ setTimeout(function(){
352
+ ts.scroller.resize( c, wo );
353
+ }, 50);
354
+ }
355
+
356
+ },
357
+
358
+ resize : function( c, wo ) {
359
+ if ( wo.scroller_isBusy ) { return; }
360
+ var index, borderWidth, setWidth, $hCells, $bCells, $fCells, $headers, $this, temp,
361
+ tsScroller = ts.scroller,
362
+ $container = wo.scroller_$container,
363
+ $table = c.$table,
364
+ $tableWrap = $table.parent(),
365
+ $hdr = wo.scroller_$header,
366
+ $foot = wo.scroller_$footer,
367
+ id = c.namespace.slice( 1 ) + 'tsscroller',
368
+ // Hide other scrollers so we can resize
369
+ $div = $( 'div.' + tscss.scrollerWrap + '[id!="' + id + '"]' )
370
+ .addClass( tscss.scrollerHideElement ),
371
+ row = '<tr class="' + tscss.scrollerSpacerRow + ' ' + c.selectorRemove.slice(1) + '">';
372
+
373
+ wo.scroller_calcWidths = [];
374
+
375
+ // Remove fixed so we get proper widths and heights
376
+ tsScroller.removeFixed( c, wo );
377
+ $container.find( '.' + tscss.scrollerSpacerRow ).remove();
378
+ // remove ts added colgroups
379
+ $container.find( '.' + ts.css.colgroup ).remove();
380
+
381
+ // show original table elements to get proper alignment
382
+ $table
383
+ .find( '.' + tscss.scrollerHideElement )
384
+ .removeClass( tscss.scrollerHideElement );
385
+
386
+ // include left & right border widths
387
+ borderWidth = parseInt( $table.css( 'border-left-width' ), 10 );
388
+
389
+ $headers = c.$headerIndexed;
390
+
391
+ for ( index = 0; index < c.columns; index++ ) {
392
+ $this = $headers[ index ];
393
+ // code from https://github.com/jmosbech/StickyTableHeaders
394
+ if ( $this.css( 'box-sizing' ) === 'border-box' ) {
395
+ setWidth = $this.outerWidth();
396
+ } else {
397
+ if ( $this.css( 'border-collapse' ) === 'collapse' ) {
398
+ if ( $this.length && window.getComputedStyle ) {
399
+ setWidth = parseFloat( window.getComputedStyle( $this[ 0 ], null ).width );
400
+ } else {
401
+ // ie8 only
402
+ setWidth = $this.outerWidth() - parseFloat( $this.css( 'padding-left' ) ) -
403
+ parseFloat( $this.css( 'padding-right' ) ) -
404
+ ( parseFloat( $this.css( 'border-width' ) ) || 0 );
405
+ }
392
406
  } else {
393
- // ie8 only
394
- setWidth = $this.outerWidth() - parseFloat( $this.css( 'padding-left' ) ) -
395
- parseFloat( $this.css( 'padding-right' ) ) -
396
- ( parseFloat( $this.css( 'border-width' ) ) || 0 );
407
+ setWidth = $this.width();
397
408
  }
398
- } else {
399
- setWidth = $this.width();
400
409
  }
410
+ row += '<td data-column="' + index + '" style="padding:0;margin:0;border:0;height:0;max-height:0;' +
411
+ 'min-height:0;width:' + setWidth + 'px;min-width:' + setWidth + 'px;max-width:' + setWidth + 'px"></td>';
412
+
413
+ // save current widths
414
+ wo.scroller_calcWidths[ index ] = setWidth;
401
415
  }
402
- row += '<td data-column="' + index + '" style="padding:0;margin:0;border:0;height:0;max-height:0;' +
403
- 'min-height:0;width:' + setWidth + 'px;min-width:' + setWidth + 'px;max-width:' + setWidth + 'px"></td>';
416
+ row += '</tr>';
417
+ c.$tbodies.eq(0).prepend( row ); // tbody
418
+ $hdr.children( 'thead' ).append( row );
419
+ $foot.children( 'tfoot' ).append( row );
420
+
421
+ // include colgroup or alignment is off
422
+ ts.fixColumnWidth( c.table );
423
+ row = c.$table.children( 'colgroup' )[0].outerHTML;
424
+ $hdr.prepend( row );
425
+ $foot.prepend( row );
426
+
427
+ temp = $tableWrap.parent().innerWidth() -
428
+ ( tsScroller.hasScrollBar( $tableWrap ) ? wo.scroller_barSetWidth : 0 );
429
+ $tableWrap.width( temp );
404
430
 
405
- // save current widths
406
- wo.scroller_calcWidths[ index ] = setWidth;
407
- }
408
- row += '</tr>';
409
- c.$tbodies.eq(0).prepend( row ); // tbody
410
- $hdr.children( 'thead' ).append( row );
411
- $foot.children( 'tfoot' ).append( row );
412
-
413
- // include colgroup or alignment is off
414
- ts.fixColumnWidth( c.table );
415
- row = c.$table.children( 'colgroup' )[0].outerHTML;
416
- $hdr.prepend( row );
417
- $foot.prepend( row );
418
-
419
- temp = $tableWrap.parent().innerWidth() -
420
- ( tsScroller.hasScrollBar( $tableWrap ) ? wo.scroller_barSetWidth : 0 );
421
- $tableWrap.width( temp );
422
-
423
- temp = ( tsScroller.hasScrollBar( $tableWrap ) ? wo.scroller_barSetWidth : 0 ) + borderWidth;
424
- setWidth = $tableWrap.innerWidth() - temp;
425
-
426
- $hdr
427
- .parent()
428
- .add( $foot.parent() )
429
- .width( setWidth );
430
-
431
- $tableWrap
432
- .width( setWidth + temp );
433
-
434
- // hide original table thead
435
- $table.children( 'thead' ).addClass( tscss.scrollerHideElement );
436
-
437
- // update fixed column sizes
438
- tsScroller.updateFixed( c, wo );
439
-
440
- $div.removeClass( tscss.scrollerHideElement );
441
-
442
- // restore scrollTop - fixes #926
443
- $tableWrap.scrollTop( wo.scroller_saved[1] );
444
- wo.scroller_$container
445
- .find( '.' + tscss.scrollerFixed )
446
- .find( '.' + tscss.scrollerTable )
447
- .scrollTop( wo.scroller_saved[1] );
448
-
449
- // update resizable widget handles
450
- setTimeout( function() {
451
- c.$table.trigger( 'resizableUpdate' );
452
- }, 100 );
453
-
454
- },
455
-
456
- // Add fixed (frozen) columns (Do not call directly, use updateFixed)
457
- setupFixed : function( c, wo ) {
458
- var index, index2, $el, len, temp, $fixedColumn, $fixedTbody,
459
- $table = c.$table,
460
- $wrapper = wo.scroller_$container,
461
- fixedColumns = wo.scroller_fixedColumns;
462
-
463
- $fixedColumn = $wrapper
464
- .addClass( tscss.scrollerHasFix )
465
- .clone()
466
- .addClass( tscss.scrollerFixed )
467
- .removeClass( tscss.scrollerWrap )
468
- .attr( 'id', '' );
469
-
470
- if ( wo.scroller_addFixedOverlay ) {
471
- $fixedColumn.append( '<div class="' + tscss.scrollerFixedPanel + '">' );
472
- }
431
+ temp = ( tsScroller.hasScrollBar( $tableWrap ) ? wo.scroller_barSetWidth : 0 ) + borderWidth;
432
+ setWidth = $tableWrap.innerWidth() - temp;
473
433
 
474
- $fixedTbody = $fixedColumn.find( '.' + tscss.scrollerTable );
475
- $fixedTbody
476
- .children( 'table' )
477
- .addClass( c.namespace.slice( 1 ) + '_extra_table' )
478
- .attr( 'id', '' )
479
- .children( 'thead, tfoot' )
480
- .remove();
434
+ $hdr
435
+ .parent()
436
+ .add( $foot.parent() )
437
+ .width( setWidth );
481
438
 
482
- wo.scroller_$fixedColumns = $fixedColumn;
439
+ $tableWrap
440
+ .width( setWidth + temp );
483
441
 
484
- // RTL support (fixes column on right)
485
- if ( $table.hasClass( tscss.scrollerRtl ) ) {
486
- $fixedColumn.addClass( tscss.scrollerRtl );
487
- }
442
+ // hide original table thead
443
+ $table.children( 'thead' ).addClass( tscss.scrollerHideElement );
488
444
 
489
- $el = $fixedColumn.find( 'tr' );
490
- len = $el.length;
491
- for ( index = 0; index < len; index++ ) {
492
- $el.eq( index ).children( ':gt(' + ( fixedColumns - 1 ) + ')' ).remove();
493
- }
494
- $fixedColumn
495
- .addClass( tscss.scrollerHideElement )
496
- .prependTo( $wrapper );
497
-
498
- // look for filter widget
499
- if ( c.$table.hasClass( 'hasFilters' ) ) {
500
- // make sure fixed column filters aren't disabled
501
- $el = $fixedColumn
502
- .find( '.' + tscss.filter )
503
- .not( '.' + tscss.filterDisabled )
504
- .prop( 'disabled', false );
505
- ts.filter.bindSearch( $table, $fixedColumn.find( '.' + tscss.filter ) );
506
- // disable/enable filters behind fixed column
507
- $el = $wrapper
508
- .children( '.' + tscss.scrollerHeader )
509
- .find( '.' + tscss.filter );
445
+ // update fixed column sizes
446
+ tsScroller.updateFixed( c, wo );
447
+
448
+ $div.removeClass( tscss.scrollerHideElement );
449
+
450
+ // restore scrollTop - fixes #926
451
+ $tableWrap.scrollTop( wo.scroller_saved[1] );
452
+ wo.scroller_$container
453
+ .find( '.' + tscss.scrollerFixed )
454
+ .find( '.' + tscss.scrollerTable )
455
+ .scrollTop( wo.scroller_saved[1] );
456
+
457
+ // update resizable widget handles
458
+ setTimeout( function() {
459
+ c.$table.trigger( 'resizableUpdate' );
460
+ }, 100 );
461
+
462
+ },
463
+
464
+ // Add fixed (frozen) columns (Do not call directly, use updateFixed)
465
+ setupFixed : function( c, wo ) {
466
+ var index, index2, $el, len, temp, $fixedColumn, $fixedTbody,
467
+ $table = c.$table,
468
+ $wrapper = wo.scroller_$container,
469
+ fixedColumns = wo.scroller_fixedColumns;
470
+
471
+ $fixedColumn = $wrapper
472
+ .addClass( tscss.scrollerHasFix )
473
+ .clone()
474
+ .addClass( tscss.scrollerFixed )
475
+ .removeClass( tscss.scrollerWrap )
476
+ .attr( 'id', '' );
477
+
478
+ if ( wo.scroller_addFixedOverlay ) {
479
+ $fixedColumn.append( '<div class="' + tscss.scrollerFixedPanel + '">' );
480
+ }
481
+
482
+ $fixedTbody = $fixedColumn.find( '.' + tscss.scrollerTable );
483
+ $fixedTbody
484
+ .children( 'table' )
485
+ .addClass( c.namespace.slice( 1 ) + '_extra_table' )
486
+ .attr( 'id', '' )
487
+ .children( 'thead, tfoot' )
488
+ .remove();
489
+
490
+ wo.scroller_$fixedColumns = $fixedColumn;
491
+
492
+ // RTL support (fixes column on right)
493
+ if ( $table.hasClass( tscss.scrollerRtl ) ) {
494
+ $fixedColumn.addClass( tscss.scrollerRtl );
495
+ }
496
+
497
+ $el = $fixedColumn.find( 'tr' );
510
498
  len = $el.length;
511
499
  for ( index = 0; index < len; index++ ) {
512
- // previously disabled filter; don't mess with it! filterDisabled class added by filter widget
513
- if ( !$el.eq( index ).hasClass( tscss.filterDisabled || 'disabled' ) ) {
514
- // disable filters behind fixed column; don't disable visible filters
515
- $el.eq( index ).prop( 'disabled', index < fixedColumns );
500
+ $el.eq( index ).children( ':gt(' + ( fixedColumns - 1 ) + ')' ).remove();
501
+ }
502
+ $fixedColumn
503
+ .addClass( tscss.scrollerHideElement )
504
+ .prependTo( $wrapper );
505
+
506
+ // look for filter widget
507
+ if ( c.$table.hasClass( 'hasFilters' ) ) {
508
+ // make sure fixed column filters aren't disabled
509
+ $el = $fixedColumn
510
+ .find( '.' + tscss.filter )
511
+ .not( '.' + tscss.filterDisabled )
512
+ .prop( 'disabled', false );
513
+ ts.filter.bindSearch( $table, $fixedColumn.find( '.' + tscss.filter ) );
514
+ // disable/enable filters behind fixed column
515
+ $el = $wrapper
516
+ .children( '.' + tscss.scrollerHeader )
517
+ .find( '.' + tscss.filter );
518
+ len = $el.length;
519
+ for ( index = 0; index < len; index++ ) {
520
+ // previously disabled filter; don't mess with it! filterDisabled class added by filter widget
521
+ if ( !$el.eq( index ).hasClass( tscss.filterDisabled || 'disabled' ) ) {
522
+ // disable filters behind fixed column; don't disable visible filters
523
+ $el.eq( index ).prop( 'disabled', index < fixedColumns );
524
+ }
516
525
  }
517
526
  }
518
- }
519
527
 
520
- // disable/enable tab indexes behind fixed column
521
- c.$table
522
- .add( '.' + tscss.scrollerFooter + ' table' )
523
- .children( 'thead' )
524
- .children( 'tr.' + tscss.headerRow )
525
- .children()
526
- .attr( 'tabindex', -1 );
527
-
528
- $el = wo.scroller_$header
529
- .add( $fixedColumn.find( '.' + tscss.scrollerTable + ' table' ) )
530
- .children( 'thead' )
531
- .children( 'tr.' + tscss.headerRow );
532
- len = $el.length;
533
- for ( index = 0; index < len; index++ ) {
534
- temp = $el.eq( index ).children();
535
- for ( index2 = 0; index2 < temp.length; index2++ ) {
536
- temp.eq( index2 ).attr( 'tabindex', index2 < fixedColumns ? -1 : 0 );
528
+ // disable/enable tab indexes behind fixed column
529
+ c.$table
530
+ .add( '.' + tscss.scrollerFooter + ' table' )
531
+ .children( 'thead' )
532
+ .children( 'tr.' + tscss.headerRow )
533
+ .children()
534
+ .attr( 'tabindex', -1 );
535
+
536
+ $el = wo.scroller_$header
537
+ .add( $fixedColumn.find( '.' + tscss.scrollerTable + ' table' ) )
538
+ .children( 'thead' )
539
+ .children( 'tr.' + tscss.headerRow );
540
+ len = $el.length;
541
+ for ( index = 0; index < len; index++ ) {
542
+ temp = $el.eq( index ).children();
543
+ for ( index2 = 0; index2 < temp.length; index2++ ) {
544
+ temp.eq( index2 ).attr( 'tabindex', index2 < fixedColumns ? -1 : 0 );
545
+ }
537
546
  }
538
- }
539
547
 
540
- ts.bindEvents( c.table, $fixedColumn.find( '.' + tscss.header ) );
541
- ts.scroller.bindFixedColumnEvents( c, wo );
548
+ ts.bindEvents( c.table, $fixedColumn.find( '.' + tscss.header ) );
549
+ ts.scroller.bindFixedColumnEvents( c, wo );
542
550
 
543
- /*** Scrollbar hack! Since we can't hide the scrollbar with css ***/
544
- if ( ts.scroller.isFirefox || ts.scroller.isOldIE ) {
545
- $fixedTbody.wrap( '<div class="' + tscss.scrollerHack + '" style="overflow:hidden;">' );
546
- }
551
+ /*** Scrollbar hack! Since we can't hide the scrollbar with css ***/
552
+ if ( ts.scroller.isFirefox || ts.scroller.isOldIE ) {
553
+ $fixedTbody.wrap( '<div class="' + tscss.scrollerHack + '" style="overflow:hidden;">' );
554
+ }
547
555
 
548
- },
549
-
550
- bindFixedColumnEvents : function( c, wo ) {
551
- // update thead & tbody in fixed column
552
- var tsScroller = ts.scroller,
553
- namespace = c.namespace + 'tsscrollerFixed',
554
- events = 'scroll' + namespace,
555
- $fixedTbody = wo.scroller_$fixedColumns.find( '.' + tscss.scrollerTable ),
556
- fixedScroll = true,
557
- tableScroll = true;
558
-
559
- c.$table
560
- .parent()
561
- // *** SCROLL *** scroll fixed column along with main
562
- .off( events )
563
- .on( events, function() {
564
- if ( wo.scroller_isBusy ) { return; }
565
- // using flags to prevent firing the scroll event excessively leading to slow scrolling in Firefox
566
- if ( !wo.scroller_isBusy && ( fixedScroll || !( tsScroller.isFirefox || tsScroller.isIE ) ) ) {
567
- tableScroll = false;
568
- var $this = $( this );
569
- $fixedTbody[0].scrollTop = wo.scroller_saved[1] = $this.scrollTop();
570
- wo.scroller_saved[0] = $this.scrollLeft();
571
- setTimeout( function() {
572
- tableScroll = true;
573
- }, 20 );
574
- }
575
- });
576
- // scroll main along with fixed column
577
- $fixedTbody
578
- .off( events )
579
- .on( events, function() {
580
- // using flags to prevent firing the scroll event excessively leading to slow scrolling in Firefox
581
- if ( !wo.scroller_isBusy && ( tableScroll || !( tsScroller.isFirefox || tsScroller.isIE ) ) ) {
582
- fixedScroll = false;
583
- var $this = $( this );
584
- c.$table.parent()[0].scrollTop = wo.scroller_saved[1] = $this.scrollTop();
585
- setTimeout( function() {
586
- fixedScroll = true;
587
- }, 20 );
588
- }
589
- })
590
- .scroll();
556
+ },
557
+
558
+ bindFixedColumnEvents : function( c, wo ) {
559
+ // update thead & tbody in fixed column
560
+ var tsScroller = ts.scroller,
561
+ namespace = c.namespace + 'tsscrollerFixed',
562
+ events = 'scroll' + namespace,
563
+ $fixedTbody = wo.scroller_$fixedColumns.find( '.' + tscss.scrollerTable ),
564
+ fixedScroll = true,
565
+ tableScroll = true;
591
566
 
592
- // *** ROW HIGHLIGHT ***
593
- if ( wo.scroller_rowHighlight !== '' ) {
594
- events = 'mouseover mouseleave '.split( ' ' ).join( namespace + ' ' );
595
- // can't use c.$tbodies because it doesn't include info-only tbodies
596
567
  c.$table
597
- .off( events, 'tbody > tr' )
598
- .on( events, 'tbody > tr', function( event ) {
599
- var indx = c.$table.children( 'tbody' ).children( 'tr' ).index( this );
600
- $fixedTbody
601
- .children( 'table' )
602
- .children( 'tbody' )
603
- .children( 'tr' )
604
- .eq( indx )
605
- .add( this )
606
- .toggleClass( wo.scroller_rowHighlight, event.type === 'mouseover' );
568
+ .parent()
569
+ // *** SCROLL *** scroll fixed column along with main
570
+ .off( events )
571
+ .on( events, function() {
572
+ if ( wo.scroller_isBusy ) { return; }
573
+ // using flags to prevent firing the scroll event excessively leading to slow scrolling in Firefox
574
+ if ( !wo.scroller_isBusy && ( fixedScroll || !( tsScroller.isFirefox || tsScroller.isIE ) ) ) {
575
+ tableScroll = false;
576
+ var $this = $( this );
577
+ $fixedTbody[0].scrollTop = wo.scroller_saved[1] = $this.scrollTop();
578
+ wo.scroller_saved[0] = $this.scrollLeft();
579
+ setTimeout( function() {
580
+ tableScroll = true;
581
+ }, 20 );
582
+ }
607
583
  });
584
+ // scroll main along with fixed column
608
585
  $fixedTbody
609
- .find( 'table' )
610
- .off( events, 'tbody > tr' )
611
- .on( events, 'tbody > tr', function( event ) {
612
- var $fixed = $fixedTbody.children( 'table' ).children( 'tbody' ).children( 'tr' ),
613
- indx = $fixed.index( this );
614
- c.$table
615
- .children( 'tbody' )
616
- .children( 'tr' )
617
- .eq( indx )
618
- .add( this )
619
- .toggleClass( wo.scroller_rowHighlight, event.type === 'mouseover' );
620
- });
621
- }
622
- },
623
-
624
- adjustWidth : function( c, wo, totalWidth, adj, dir ) {
625
- var $wrapper = wo.scroller_$container;
626
-
627
- // RTL support (fixes column on right)
628
- $wrapper
629
- .children( '.' + tscss.scrollerTable )
630
- .css( dir ? 'right' : 'left', totalWidth );
631
- $wrapper
632
- .children( '.' + tscss.scrollerHeader + ', .' + tscss.scrollerFooter )
633
- // Safari needs a scrollbar width of extra adjusment to align the fixed & scrolling columns
634
- .css( dir ? 'right' : 'left', totalWidth + ( dir && ts.scroller.isSafari ? adj : 0 ) );
635
- },
636
-
637
- updateFixed : function( c, wo ) {
638
- var temp, adj,
639
- $wrapper = wo.scroller_$container,
640
- $hdr = wo.scroller_$header,
641
- $foot = wo.scroller_$footer,
642
- $table = c.$table,
643
- $tableWrap = $table.parent(),
644
- scrollBarWidth = wo.scroller_barSetWidth,
645
- dir = $table.hasClass( tscss.scrollerRtl );
646
-
647
- if ( wo.scroller_fixedColumns === 0 ) {
648
- wo.scroller_isBusy = false;
649
- ts.scroller.removeFixed( c, wo );
650
- temp = $wrapper.width();
651
- $tableWrap.width( temp );
586
+ .off( events )
587
+ .on( events, function() {
588
+ // using flags to prevent firing the scroll event excessively leading to slow scrolling in Firefox
589
+ if ( !wo.scroller_isBusy && ( tableScroll || !( tsScroller.isFirefox || tsScroller.isIE ) ) ) {
590
+ fixedScroll = false;
591
+ var $this = $( this );
592
+ c.$table.parent()[0].scrollTop = wo.scroller_saved[1] = $this.scrollTop();
593
+ setTimeout( function() {
594
+ fixedScroll = true;
595
+ }, 20 );
596
+ }
597
+ })
598
+ .scroll();
599
+
600
+ // *** ROW HIGHLIGHT ***
601
+ if ( wo.scroller_rowHighlight !== '' ) {
602
+ events = 'mouseover mouseleave '.split( ' ' ).join( namespace + ' ' );
603
+ // can't use c.$tbodies because it doesn't include info-only tbodies
604
+ c.$table
605
+ .off( events, 'tbody > tr' )
606
+ .on( events, 'tbody > tr', function( event ) {
607
+ var indx = c.$table.children( 'tbody' ).children( 'tr' ).index( this );
608
+ $fixedTbody
609
+ .children( 'table' )
610
+ .children( 'tbody' )
611
+ .children( 'tr' )
612
+ .eq( indx )
613
+ .add( this )
614
+ .toggleClass( wo.scroller_rowHighlight, event.type === 'mouseover' );
615
+ });
616
+ $fixedTbody
617
+ .find( 'table' )
618
+ .off( events, 'tbody > tr' )
619
+ .on( events, 'tbody > tr', function( event ) {
620
+ var $fixed = $fixedTbody.children( 'table' ).children( 'tbody' ).children( 'tr' ),
621
+ indx = $fixed.index( this );
622
+ c.$table
623
+ .children( 'tbody' )
624
+ .children( 'tr' )
625
+ .eq( indx )
626
+ .add( this )
627
+ .toggleClass( wo.scroller_rowHighlight, event.type === 'mouseover' );
628
+ });
629
+ }
630
+ },
631
+
632
+ adjustWidth : function( c, wo, totalWidth, adj, dir ) {
633
+ var $wrapper = wo.scroller_$container;
634
+
635
+ // RTL support (fixes column on right)
636
+ $wrapper
637
+ .children( '.' + tscss.scrollerTable )
638
+ .css( dir ? 'right' : 'left', totalWidth );
639
+ $wrapper
640
+ .children( '.' + tscss.scrollerHeader + ', .' + tscss.scrollerFooter )
641
+ // Safari needs a scrollbar width of extra adjusment to align the fixed & scrolling columns
642
+ .css( dir ? 'right' : 'left', totalWidth + ( dir && ts.scroller.isSafari ? adj : 0 ) );
643
+ },
644
+
645
+ updateFixed : function( c, wo ) {
646
+ var temp, adj,
647
+ $wrapper = wo.scroller_$container,
648
+ $hdr = wo.scroller_$header,
649
+ $foot = wo.scroller_$footer,
650
+ $table = c.$table,
651
+ $tableWrap = $table.parent(),
652
+ scrollBarWidth = wo.scroller_barSetWidth,
653
+ dir = $table.hasClass( tscss.scrollerRtl );
654
+
655
+ if ( wo.scroller_fixedColumns === 0 ) {
656
+ wo.scroller_isBusy = false;
657
+ ts.scroller.removeFixed( c, wo );
658
+ temp = $wrapper.width();
659
+ $tableWrap.width( temp );
660
+ adj = ts.scroller.hasScrollBar( $tableWrap ) ? scrollBarWidth : 0;
661
+ $hdr
662
+ .parent()
663
+ .add( $foot.parent() )
664
+ .width( temp - adj );
665
+ return;
666
+ }
667
+
668
+ if ( !c.isScrolling ) {
669
+ return;
670
+ }
671
+
672
+ wo.scroller_isBusy = true;
673
+
674
+ // Make sure the wo.scroller_$fixedColumns container exists, if not build it
675
+ if ( !$wrapper.find( '.' + tscss.scrollerFixed ).length ) {
676
+ ts.scroller.setupFixed( c, wo );
677
+ }
678
+
679
+ // scroller_fixedColumns
680
+ var index, tbodyIndex, rowIndex, $tbody, $adjCol, $fb, $fixHead, $fixBody, $fixFoot,
681
+ totalRows, row,
682
+
683
+ // source cells for measurement
684
+ $mainTbodies = wo.scroller_$container
685
+ .children( '.' + tscss.scrollerTable )
686
+ .children( 'table' )
687
+ .children( 'tbody' ),
688
+ // variable gets redefined
689
+ $rows = wo.scroller_$header
690
+ .children( 'thead' )
691
+ .children( '.' + tscss.headerRow ),
692
+
693
+ // hide fixed column during resize, or we get a FOUC
694
+ $fixedColumn = wo.scroller_$fixedColumns
695
+ .addClass( tscss.scrollerHideElement ),
696
+
697
+ // target cells
698
+ $fixedTbodiesTable = $fixedColumn
699
+ .find( '.' + tscss.scrollerTable )
700
+ .children( 'table' ),
701
+ $fixedTbodies = $fixedTbodiesTable
702
+ .children( 'tbody' ),
703
+ // variables
704
+ tsScroller = ts.scroller,
705
+ fixedColumns = wo.scroller_fixedColumns,
706
+ // get dimensions
707
+ $temp = $table.find( 'tbody td' ),
708
+ borderRightWidth = parseInt( $temp.css( 'border-right-width' ), 10 ) || 1,
709
+ borderSpacing = parseInt( ( $temp.css( 'border-spacing' ) || '' ).split( /\s/ )[ 0 ], 10 ) / 2 || 0,
710
+ totalWidth = parseInt( $table.css( 'padding-left' ), 10 ) +
711
+ parseInt( $table.css( 'padding-right' ), 10 ) -
712
+ borderRightWidth,
713
+ widths = wo.scroller_calcWidths;
714
+
715
+ ts.scroller.removeFixed( c, wo, false );
716
+
717
+ // calculate fixed column width
718
+ for ( index = 0; index < fixedColumns; index++ ) {
719
+ totalWidth += widths[ index ] + borderSpacing;
720
+ }
721
+
722
+ // set fixed column width
723
+ totalWidth = totalWidth + borderRightWidth * 2 - borderSpacing;
724
+ tsScroller.setWidth( $fixedColumn.add( $fixedColumn.children() ), totalWidth );
725
+ tsScroller.setWidth( $fixedColumn.children().children( 'table' ), totalWidth );
726
+
727
+ // update fixed column tbody content, set cell widths on hidden row
728
+ for ( tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++ ) {
729
+ $tbody = $mainTbodies.eq( tbodyIndex );
730
+ if ( $tbody.length ) {
731
+ // get tbody
732
+ $rows = $tbody.children();
733
+ totalRows = $rows.length;
734
+ $fb = ts.processTbody( $fixedTbodiesTable, $fixedTbodies.eq( tbodyIndex ), true );
735
+ $fb.empty();
736
+ // update tbody cells after sort/filtering
737
+ for ( rowIndex = 0; rowIndex < totalRows; rowIndex++ ) {
738
+ $adjCol = $( $rows[ rowIndex ].outerHTML );
739
+ $adjCol
740
+ .children( 'td, th' )
741
+ .slice( fixedColumns )
742
+ .remove();
743
+ $fb.append( $adjCol );
744
+ }
745
+
746
+ // restore tbody
747
+ ts.processTbody( $fixedTbodiesTable, $fb, false );
748
+ }
749
+ }
750
+
652
751
  adj = ts.scroller.hasScrollBar( $tableWrap ) ? scrollBarWidth : 0;
752
+
753
+ /*** scrollbar HACK! Since we can't hide the scrollbar with css ***/
754
+ if ( tsScroller.isFirefox || tsScroller.isOldIE ) {
755
+ $fixedTbodiesTable
756
+ .css( 'width', totalWidth )
757
+ .parent()
758
+ .css( 'width', totalWidth + adj );
759
+ }
760
+
761
+ $fixedColumn.removeClass( tscss.scrollerHideElement );
762
+ for ( index = 0; index < fixedColumns; index++ ) {
763
+ $wrapper
764
+ .children( 'div' )
765
+ .children( 'table' )
766
+ .find( 'th:nth-child(' + ( index + 1 ) + '), td:nth-child(' + ( index + 1 ) + ')' )
767
+ .addClass( tscss.scrollerHideColumn );
768
+ }
769
+
770
+ totalWidth = totalWidth - borderRightWidth;
771
+ temp = $tableWrap.parent().innerWidth() - totalWidth;
772
+ $tableWrap.width( temp );
773
+ // RTL support (fixes column on right)
774
+ $wrapper
775
+ .children( '.' + tscss.scrollerTable )
776
+ .css( dir ? 'right' : 'left', totalWidth );
777
+ $wrapper
778
+ .children( '.' + tscss.scrollerHeader + ', .' + tscss.scrollerFooter )
779
+ // Safari needs a scrollbar width of extra adjusment to align the fixed & scrolling columns
780
+ .css( dir ? 'right' : 'left', totalWidth + ( dir && ts.scroller.isSafari ? adj : 0 ) );
781
+
653
782
  $hdr
654
783
  .parent()
655
784
  .add( $foot.parent() )
656
785
  .width( temp - adj );
657
- return;
658
- }
659
786
 
660
- if ( !c.isScrolling ) {
661
- return;
662
- }
787
+ // fix gap under the tbody for the horizontal scrollbar
788
+ temp = ts.scroller.hasScrollBar( $tableWrap, true );
789
+ adj = temp ? scrollBarWidth : 0;
790
+ if ( !$fixedColumn.find( '.' + tscss.scrollerBarSpacer ).length && temp ) {
791
+ $temp = $( '<div class="' + tscss.scrollerBarSpacer + '">' )
792
+ .css( 'height', adj + 'px' );
793
+ $fixedColumn.find( '.' + tscss.scrollerTable ).append( $temp );
794
+ } else if ( !temp ) {
795
+ $fixedColumn.find( '.' + tscss.scrollerBarSpacer ).remove();
796
+ }
663
797
 
664
- wo.scroller_isBusy = true;
798
+ ts.scroller.updateRowHeight( c, wo );
799
+ // set fixed column height (changes with filtering)
800
+ $fixedColumn.height( $wrapper.height() );
665
801
 
666
- // Make sure the wo.scroller_$fixedColumns container exists, if not build it
667
- if ( !$wrapper.find( '.' + tscss.scrollerFixed ).length ) {
668
- ts.scroller.setupFixed( c, wo );
669
- }
802
+ $fixedColumn.removeClass( tscss.scrollerHideElement );
670
803
 
671
- // scroller_fixedColumns
672
- var index, tbodyIndex, rowIndex, $tbody, $adjCol, $fb, $fixHead, $fixBody, $fixFoot,
673
- totalRows, row,
804
+ wo.scroller_isBusy = false;
674
805
 
675
- // source cells for measurement
676
- $mainTbodies = wo.scroller_$container
677
- .children( '.' + tscss.scrollerTable )
678
- .children( 'table' )
679
- .children( 'tbody' ),
680
- // variable gets redefined
681
- $rows = wo.scroller_$header
682
- .children( 'thead' )
683
- .children( '.' + tscss.headerRow ),
806
+ },
684
807
 
685
- // hide fixed column during resize, or we get a FOUC
686
- $fixedColumn = wo.scroller_$fixedColumns
687
- .addClass( tscss.scrollerHideElement ),
808
+ fixHeight : function( $rows, $fixedRows ) {
809
+ var index, heightRow, heightFixed, $r, $f,
810
+ addedHt = tscss.scrollerAddedHeight,
811
+ len = $rows.length;
812
+ for ( index = 0; index < len; index++ ) {
813
+ $r = $rows.eq( index );
814
+ $f = $fixedRows.eq( index );
815
+ heightRow = $r.height();
816
+ heightFixed = $f.height();
817
+ if ( heightRow > heightFixed ) {
818
+ $f.addClass( addedHt ).height( heightRow );
819
+ } else if ( heightRow < heightFixed ) {
820
+ $r.addClass( addedHt ).height( heightFixed );
821
+ }
822
+ }
823
+ },
688
824
 
689
- // target cells
690
- $fixedTbodiesTable = $fixedColumn
691
- .find( '.' + tscss.scrollerTable )
692
- .children( 'table' ),
693
- $fixedTbodies = $fixedTbodiesTable
694
- .children( 'tbody' ),
695
- // variables
696
- tsScroller = ts.scroller,
697
- fixedColumns = wo.scroller_fixedColumns,
698
- // get dimensions
699
- $temp = $table.find( 'tbody td' ),
700
- borderRightWidth = parseInt( $temp.css( 'border-right-width' ), 10 ) || 1,
701
- borderSpacing = parseInt( ( $temp.css( 'border-spacing' ) || '' ).split( /\s/ )[ 0 ], 10 ) / 2 || 0,
702
- totalWidth = parseInt( $table.css( 'padding-left' ), 10 ) +
703
- parseInt( $table.css( 'padding-right' ), 10 ) -
704
- borderRightWidth,
705
- widths = wo.scroller_calcWidths;
706
-
707
- ts.scroller.removeFixed( c, wo, false );
708
-
709
- // calculate fixed column width
710
- for ( index = 0; index < fixedColumns; index++ ) {
711
- totalWidth += widths[ index ] + borderSpacing;
712
- }
825
+ updateRowHeight : function( c, wo ) {
826
+ var $rows, $fixed,
827
+ $fixedColumns = wo.scroller_$fixedColumns;
713
828
 
714
- // set fixed column width
715
- totalWidth = totalWidth + borderRightWidth * 2 - borderSpacing;
716
- tsScroller.setWidth( $fixedColumn.add( $fixedColumn.children() ), totalWidth );
717
- tsScroller.setWidth( $fixedColumn.children().children( 'table' ), totalWidth );
718
-
719
- // update fixed column tbody content, set cell widths on hidden row
720
- for ( tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++ ) {
721
- $tbody = $mainTbodies.eq( tbodyIndex );
722
- if ( $tbody.length ) {
723
- // get tbody
724
- $rows = $tbody.children();
725
- totalRows = $rows.length;
726
- $fb = ts.processTbody( $fixedTbodiesTable, $fixedTbodies.eq( tbodyIndex ), true );
727
- $fb.empty();
728
- // update tbody cells after sort/filtering
729
- for ( rowIndex = 0; rowIndex < totalRows; rowIndex++ ) {
730
- $adjCol = $( $rows[ rowIndex ].outerHTML );
731
- $adjCol
732
- .children( 'td, th' )
733
- .slice( fixedColumns )
734
- .remove();
735
- $fb.append( $adjCol );
736
- }
829
+ wo.scroller_$container
830
+ .find( '.' + tscss.scrollerAddedHeight )
831
+ .removeClass( tscss.scrollerAddedHeight )
832
+ .height( '' );
833
+
834
+ $rows = wo.scroller_$header
835
+ .children( 'thead' )
836
+ .children( 'tr' );
837
+ $fixed = $fixedColumns
838
+ .children( '.' + tscss.scrollerHeader )
839
+ .children( 'table' )
840
+ .children( 'thead' )
841
+ .children( 'tr' );
842
+ ts.scroller.fixHeight( $rows, $fixed );
843
+
844
+ $rows = wo.scroller_$footer
845
+ .children( 'tfoot' )
846
+ .children( 'tr' );
847
+ $fixed = $fixedColumns
848
+ .children( '.' + tscss.scrollerFooter )
849
+ .children( 'table' )
850
+ .children( 'tfoot' )
851
+ .children( 'tr' );
852
+ ts.scroller.fixHeight( $rows, $fixed );
737
853
 
738
- // restore tbody
739
- ts.processTbody( $fixedTbodiesTable, $fb, false );
854
+ if ( ts.scroller.isFirefox || ts.scroller.isOldIE ) {
855
+ // Firefox/Old IE scrollbar hack (wraps table to hide the scrollbar)
856
+ $fixedColumns = $fixedColumns.find( '.' + tscss.scrollerHack );
740
857
  }
741
- }
858
+ $rows = c.$table
859
+ .children( 'tbody' )
860
+ .children( 'tr' );
861
+ $fixed = $fixedColumns
862
+ .children( '.' + tscss.scrollerTable )
863
+ .children( 'table' )
864
+ .children( 'tbody' )
865
+ .children( 'tr' );
866
+ ts.scroller.fixHeight( $rows, $fixed );
742
867
 
743
- adj = ts.scroller.hasScrollBar( $tableWrap ) ? scrollBarWidth : 0;
868
+ },
744
869
 
745
- /*** scrollbar HACK! Since we can't hide the scrollbar with css ***/
746
- if ( tsScroller.isFirefox || tsScroller.isOldIE ) {
747
- $fixedTbodiesTable
748
- .css( 'width', totalWidth )
749
- .parent()
750
- .css( 'width', totalWidth + adj );
751
- }
870
+ removeFixed : function( c, wo, removeIt ) {
871
+ var $table = c.$table,
872
+ $wrapper = wo.scroller_$container,
873
+ dir = $table.hasClass( tscss.scrollerRtl );
752
874
 
753
- $fixedColumn.removeClass( tscss.scrollerHideElement );
754
- for ( index = 0; index < fixedColumns; index++ ) {
755
- $wrapper
756
- .children( 'div' )
757
- .children( 'table' )
758
- .find( 'th:nth-child(' + ( index + 1 ) + '), td:nth-child(' + ( index + 1 ) + ')' )
759
- .addClass( tscss.scrollerHideColumn );
760
- }
875
+ // remove fixed columns
876
+ if ( removeIt || typeof removeIt === 'undefined' ) {
877
+ $wrapper.find( '.' + tscss.scrollerFixed ).remove();
878
+ }
761
879
 
762
- totalWidth = totalWidth - borderRightWidth;
763
- temp = $tableWrap.parent().innerWidth() - totalWidth;
764
- $tableWrap.width( temp );
765
- // RTL support (fixes column on right)
766
- $wrapper
767
- .children( '.' + tscss.scrollerTable )
768
- .css( dir ? 'right' : 'left', totalWidth );
769
- $wrapper
770
- .children( '.' + tscss.scrollerHeader + ', .' + tscss.scrollerFooter )
771
- // Safari needs a scrollbar width of extra adjusment to align the fixed & scrolling columns
772
- .css( dir ? 'right' : 'left', totalWidth + ( dir && ts.scroller.isSafari ? adj : 0 ) );
773
-
774
- $hdr
775
- .parent()
776
- .add( $foot.parent() )
777
- .width( temp - adj );
778
-
779
- // fix gap under the tbody for the horizontal scrollbar
780
- temp = ts.scroller.hasScrollBar( $tableWrap, true );
781
- adj = temp ? scrollBarWidth : 0;
782
- if ( !$fixedColumn.find( '.' + tscss.scrollerBarSpacer ).length && temp ) {
783
- $temp = $( '<div class="' + tscss.scrollerBarSpacer + '">' )
784
- .css( 'height', adj + 'px' );
785
- $fixedColumn.find( '.' + tscss.scrollerTable ).append( $temp );
786
- } else if ( !temp ) {
787
- $fixedColumn.find( '.' + tscss.scrollerBarSpacer ).remove();
788
- }
880
+ $wrapper
881
+ .find( '.' + tscss.scrollerHideColumn )
882
+ .removeClass( tscss.scrollerHideColumn );
789
883
 
790
- ts.scroller.updateRowHeight( c, wo );
791
- // set fixed column height (changes with filtering)
792
- $fixedColumn.height( $wrapper.height() );
793
-
794
- $fixedColumn.removeClass( tscss.scrollerHideElement );
795
-
796
- wo.scroller_isBusy = false;
797
- },
798
-
799
- fixHeight : function( $rows, $fixedRows ) {
800
- var index, heightRow, heightFixed, $r, $f,
801
- len = $rows.length;
802
- for ( index = 0; index < len; index++ ) {
803
- $r = $rows.eq( index );
804
- $f = $fixedRows.eq( index );
805
- heightRow = $r.height();
806
- heightFixed = $f.height();
807
- if ( heightRow > heightFixed ) {
808
- $f.addClass( tscss.scrollerAddedHeight ).height( heightRow );
809
- } else if ( heightRow < heightFixed ) {
810
- $r.addClass( tscss.scrollerAddedHeight ).height( heightFixed );
884
+ // RTL support ( fixes column on right )
885
+ $wrapper
886
+ .children( ':not(.' + tscss.scrollerFixed + ')' )
887
+ .css( dir ? 'right' : 'left', 0 );
888
+ },
889
+
890
+ remove : function( c, wo ) {
891
+ var $wrap = wo.scroller_$container,
892
+ namespace = c.namespace + 'tsscroller';
893
+ c.$table.off( namespace );
894
+ $( window ).off( namespace );
895
+ if ( $wrap ) {
896
+ c.$table
897
+ .insertBefore( $wrap )
898
+ .find( 'thead' )
899
+ .removeClass( tscss.scrollerHideElement )
900
+ .children( 'tr.' + tscss.headerRow )
901
+ .children()
902
+ .attr( 'tabindex', 0 )
903
+ .end()
904
+ .find( '.' + tscss.filterRow )
905
+ .removeClass( tscss.scrollerHideElement + ' ' + tscss.filterRowHide );
906
+ c.$table
907
+ .find( '.' + tscss.filter )
908
+ .not( '.' + tscss.filterDisabled )
909
+ .prop( 'disabled', false );
910
+ $wrap.remove();
911
+ c.isScrolling = false;
811
912
  }
812
913
  }
813
- },
814
-
815
- updateRowHeight : function( c, wo ) {
816
- var $rows, $fixed,
817
- $fixedColumns = wo.scroller_$fixedColumns;
818
-
819
- wo.scroller_$container
820
- .find( '.' + tscss.scrollerAddedHeight )
821
- .removeClass( tscss.scrollerAddedHeight )
822
- .height( '' );
823
-
824
- $rows = wo.scroller_$header
825
- .children( 'thead' )
826
- .children( 'tr' );
827
- $fixed = $fixedColumns
828
- .children( '.' + tscss.scrollerHeader )
829
- .children( 'table' )
830
- .children( 'thead' )
831
- .children( 'tr' );
832
- ts.scroller.fixHeight( $rows, $fixed );
833
-
834
- $rows = wo.scroller_$footer
835
- .children( 'tfoot' )
836
- .children( 'tr' );
837
- $fixed = $fixedColumns
838
- .children( '.' + tscss.scrollerFooter )
839
- .children( 'table' )
840
- .children( 'tfoot' )
841
- .children( 'tr' );
842
- ts.scroller.fixHeight( $rows, $fixed );
843
-
844
- if ( ts.scroller.isFirefox || ts.scroller.isOldIE ) {
845
- // Firefox/Old IE scrollbar hack (wraps table to hide the scrollbar)
846
- $fixedColumns = $fixedColumns.find( '.' + tscss.scrollerHack );
847
- }
848
- $rows = c.$table
849
- .children( 'tbody' )
850
- .children( 'tr' );
851
- $fixed = $fixedColumns
852
- .children( '.' + tscss.scrollerTable )
853
- .children( 'table' )
854
- .children( 'tbody' )
855
- .children( 'tr' );
856
- ts.scroller.fixHeight( $rows, $fixed );
857
-
858
- },
859
-
860
- removeFixed : function( c, wo, removeIt ) {
861
- var $table = c.$table,
862
- $wrapper = wo.scroller_$container,
863
- dir = $table.hasClass( tscss.scrollerRtl );
864
-
865
- // remove fixed columns
866
- if ( removeIt || typeof removeIt === 'undefined' ) {
867
- $wrapper.find( '.' + tscss.scrollerFixed ).remove();
868
- }
869
914
 
870
- $wrapper
871
- .find( '.' + tscss.scrollerHideColumn )
872
- .removeClass( tscss.scrollerHideColumn );
873
-
874
- // RTL support ( fixes column on right )
875
- $wrapper
876
- .children( ':not(.' + tscss.scrollerFixed + ')' )
877
- .css( dir ? 'right' : 'left', 0 );
878
- },
879
-
880
- remove : function( c, wo ) {
881
- var $wrap = wo.scroller_$container,
882
- namespace = c.namespace + 'tsscroller';
883
- c.$table
884
- .off( namespace )
885
- .insertBefore( $wrap )
886
- .find( 'thead' )
887
- .removeClass( tscss.scrollerHideElement )
888
- .children( 'tr.' + tscss.headerRow )
889
- .children()
890
- .attr( 'tabindex', 0 )
891
- .end()
892
- .find( '.' + tscss.filterRow )
893
- .removeClass( tscss.scrollerHideElement + ' ' + tscss.filterRowHide );
894
- c.$table
895
- .find( '.' + tscss.filter )
896
- .not( '.' + tscss.filterDisabled )
897
- .prop( 'disabled', false );
898
- $wrap.remove();
899
- $( window ).off( namespace );
900
- c.isScrolling = false;
901
- }
902
-
903
- };
915
+ };
904
916
 
905
917
  })( jQuery, window );