jquery-tablesorter 1.12.8 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/jquery-tablesorter/version.rb +1 -1
- data/vendor/assets/javascripts/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.js +115 -67
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.js +62 -40
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets.js +251 -118
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-extract.js +48 -24
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-iso8601.js +5 -4
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-month.js +16 -10
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-two-digit-year.js +26 -19
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-weekday.js +16 -10
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date.js +7 -4
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-named-numbers.js +121 -0
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/{parser-ipv6.js → parser-network.js} +66 -17
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-columnSelector.js +10 -7
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-cssStickyHeaders.js +62 -35
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-editable.js +197 -174
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-grouping.js +3 -6
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-pager.js +145 -62
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-repeatheaders.js +1 -1
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-scroller.js +16 -14
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.black-ice.css +2 -2
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.blue.css +2 -2
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.bootstrap_2.css +2 -2
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.dark.css +2 -2
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.default.css +2 -2
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.dropbox.css +2 -2
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.green.css +2 -2
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.grey.css +2 -2
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.ice.css +2 -2
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.jui.css +4 -1
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.metro-dark.css +4 -4
- metadata +4 -3
@@ -1,4 +1,4 @@
|
|
1
|
-
/*! tableSorter 2.16+ widgets - updated
|
1
|
+
/*! tableSorter 2.16+ widgets - updated 10/26/2014 (v2.18.0)
|
2
2
|
*
|
3
3
|
* Column Styles
|
4
4
|
* Column Filters
|
@@ -9,8 +9,8 @@
|
|
9
9
|
* [ "columns", "filter", "resizable", "stickyHeaders", "uitheme", "saveSort" ]
|
10
10
|
*/
|
11
11
|
/*jshint browser:true, jquery:true, unused:false, loopfunc:true */
|
12
|
-
/*global jQuery: false, localStorage: false
|
13
|
-
;(function(
|
12
|
+
/*global jQuery: false, localStorage: false */
|
13
|
+
;(function ($, window) {
|
14
14
|
"use strict";
|
15
15
|
var ts = $.tablesorter = $.tablesorter || {};
|
16
16
|
|
@@ -33,7 +33,7 @@ ts.themes = {
|
|
33
33
|
},
|
34
34
|
"jui" : {
|
35
35
|
table : 'ui-widget ui-widget-content ui-corner-all', // table classes
|
36
|
-
caption : 'ui-widget-content
|
36
|
+
caption : 'ui-widget-content',
|
37
37
|
header : 'ui-widget-header ui-corner-all ui-state-default', // header classes
|
38
38
|
footerRow : '',
|
39
39
|
footerCells: '',
|
@@ -55,7 +55,8 @@ $.extend(ts.css, {
|
|
55
55
|
wrapper : 'tablesorter-wrapper', // ui theme & resizable
|
56
56
|
resizer : 'tablesorter-resizer', // resizable
|
57
57
|
sticky : 'tablesorter-stickyHeader', // stickyHeader
|
58
|
-
stickyVis : 'tablesorter-sticky-visible'
|
58
|
+
stickyVis : 'tablesorter-sticky-visible',
|
59
|
+
stickyWrap: 'tablesorter-sticky-wrapper'
|
59
60
|
});
|
60
61
|
|
61
62
|
// *** Store data in local storage, with a cookie fallback ***
|
@@ -176,34 +177,42 @@ ts.addWidget({
|
|
176
177
|
id: "uitheme",
|
177
178
|
priority: 10,
|
178
179
|
format: function(table, c, wo) {
|
179
|
-
var i, time, classes, $header, $icon, $tfoot, $h,
|
180
|
+
var i, time, classes, $header, $icon, $tfoot, $h, oldtheme, oldremove,
|
180
181
|
themesAll = ts.themes,
|
181
182
|
$table = c.$table,
|
182
183
|
$headers = c.$headers,
|
183
184
|
theme = c.theme || 'jui',
|
184
185
|
themes = themesAll[theme] || themesAll.jui,
|
185
|
-
remove = themes.sortNone
|
186
|
+
remove = [ themes.sortNone, themes.sortDesc, themes.sortAsc, themes.active ].join( ' ' );
|
186
187
|
if (c.debug) { time = new Date(); }
|
187
188
|
// initialization code - run once
|
188
|
-
if (!$table.hasClass('tablesorter-' + theme) || c.theme
|
189
|
+
if (!$table.hasClass('tablesorter-' + theme) || c.theme !== c.appliedTheme || !table.hasInitialized) {
|
190
|
+
oldtheme = themes[c.appliedTheme] || {};
|
191
|
+
oldremove = oldtheme ? [ oldtheme.sortNone, oldtheme.sortDesc, oldtheme.sortAsc, oldtheme.active ].join( ' ' ) : '';
|
192
|
+
if (oldtheme) {
|
193
|
+
wo.zebra[0] = wo.zebra[0].replace(' ' + oldtheme.even, '');
|
194
|
+
wo.zebra[1] = wo.zebra[1].replace(' ' + oldtheme.odd, '');
|
195
|
+
}
|
189
196
|
// update zebra stripes
|
190
197
|
if (themes.even !== '') { wo.zebra[0] += ' ' + themes.even; }
|
191
198
|
if (themes.odd !== '') { wo.zebra[1] += ' ' + themes.odd; }
|
192
199
|
// add caption style
|
193
|
-
$table.
|
200
|
+
$table.children('caption').removeClass(oldtheme.caption).addClass(themes.caption);
|
194
201
|
// add table/footer class names
|
195
202
|
$tfoot = $table
|
196
203
|
// remove other selected themes
|
197
|
-
.removeClass( c.
|
204
|
+
.removeClass( c.appliedTheme ? 'tablesorter-' + ( c.appliedTheme || '' ) : '' )
|
198
205
|
.addClass('tablesorter-' + theme + ' ' + themes.table) // add theme widget class name
|
199
|
-
.
|
206
|
+
.children('tfoot');
|
200
207
|
if ($tfoot.length) {
|
201
208
|
$tfoot
|
202
|
-
.
|
203
|
-
.children('th, td').addClass(themes.footerCells);
|
209
|
+
.children('tr').removeClass(oldtheme.footerRow).addClass(themes.footerRow)
|
210
|
+
.children('th, td').removeClass(oldtheme.footerCells).addClass(themes.footerCells);
|
204
211
|
}
|
205
212
|
// update header classes
|
206
213
|
$headers
|
214
|
+
.add(c.$extraHeaders)
|
215
|
+
.removeClass(oldtheme.header + ' ' + oldtheme.hover + ' ' + oldremove)
|
207
216
|
.addClass(themes.header)
|
208
217
|
.not('.sorter-false')
|
209
218
|
.bind('mouseenter.tsuitheme mouseleave.tsuitheme', function(event) {
|
@@ -216,16 +225,17 @@ ts.addWidget({
|
|
216
225
|
}
|
217
226
|
if (c.cssIcon) {
|
218
227
|
// if c.cssIcon is '', then no <i> is added to the header
|
219
|
-
$headers.find('.' + ts.css.icon).addClass(themes.icons);
|
228
|
+
$headers.find('.' + ts.css.icon).removeClass(oldtheme.icons + ' ' + oldremove).addClass(themes.icons);
|
220
229
|
}
|
221
230
|
if ($table.hasClass('hasFilters')) {
|
222
|
-
$
|
231
|
+
$table.children('thead').children('.' + ts.css.filterRow).removeClass(oldtheme.filterRow).addClass(themes.filterRow);
|
223
232
|
}
|
233
|
+
c.appliedTheme = c.theme;
|
224
234
|
}
|
225
235
|
for (i = 0; i < c.columns; i++) {
|
226
|
-
$header = c.$headers.add(c.$extraHeaders).filter('[data-column="' + i + '"]');
|
236
|
+
$header = c.$headers.add(c.$extraHeaders).not('.sorter-false').filter('[data-column="' + i + '"]');
|
227
237
|
$icon = (ts.css.icon) ? $header.find('.' + ts.css.icon) : $header;
|
228
|
-
$h =
|
238
|
+
$h = $headers.not('.sorter-false').filter('[data-column="' + i + '"]:last');
|
229
239
|
if ($h.length) {
|
230
240
|
if ($h[0].sortDisabled) {
|
231
241
|
// no sort arrows for disabled columns!
|
@@ -274,7 +284,7 @@ ts.addWidget({
|
|
274
284
|
columns : [ "primary", "secondary", "tertiary" ]
|
275
285
|
},
|
276
286
|
format: function(table, c, wo) {
|
277
|
-
var
|
287
|
+
var $tbody, tbodyIndex, $rows, rows, $row, $cells, remove, indx,
|
278
288
|
$table = c.$table,
|
279
289
|
$tbodies = c.$tbodies,
|
280
290
|
sortList = c.sortList,
|
@@ -283,9 +293,6 @@ ts.addWidget({
|
|
283
293
|
css = wo && wo.columns || [ "primary", "secondary", "tertiary" ],
|
284
294
|
last = css.length - 1;
|
285
295
|
remove = css.join(' ');
|
286
|
-
if (c.debug) {
|
287
|
-
time = new Date();
|
288
|
-
}
|
289
296
|
// check if there is a sort (on initialization there may not be one)
|
290
297
|
for (tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) {
|
291
298
|
$tbody = ts.processTbody(table, $tbodies.eq(tbodyIndex), true); // detach tbody
|
@@ -325,9 +332,6 @@ ts.addWidget({
|
|
325
332
|
}
|
326
333
|
}
|
327
334
|
}
|
328
|
-
if (c.debug) {
|
329
|
-
ts.benchmark("Applying Columns widget", time);
|
330
|
-
}
|
331
335
|
},
|
332
336
|
remove: function(table, c, wo) {
|
333
337
|
var tbodyIndex, $tbody,
|
@@ -353,6 +357,7 @@ ts.addWidget({
|
|
353
357
|
options : {
|
354
358
|
filter_childRows : false, // if true, filter includes child row content in the search
|
355
359
|
filter_columnFilters : true, // if true, a filter will be added to the top of each table column
|
360
|
+
filter_cellFilter : '', // css class name added to the filter cell (string or array)
|
356
361
|
filter_cssFilter : '', // css class name added to the filter row & each input in the row (tablesorter-filter is ALWAYS added)
|
357
362
|
filter_defaultFilter : {}, // add a default column filter type "~{query}" to make fuzzy searches default; "{q1} AND {q2}" to make all searches use a logical AND.
|
358
363
|
filter_excludeFilter : {}, // filters to exclude, per column
|
@@ -410,17 +415,18 @@ ts.filter = {
|
|
410
415
|
child : /tablesorter-childRow/, // child row class name; this gets updated in the script
|
411
416
|
filtered : /filtered/, // filtered (hidden) row class name; updated in the script
|
412
417
|
type : /undefined|number/, // check type
|
413
|
-
exact : /(^[\"
|
418
|
+
exact : /(^[\"\'=]+)|([\"\'=]+$)/g, // exact match (allow '==')
|
414
419
|
nondigit : /[^\w,. \-()]/g, // replace non-digits (from digit & currency parser)
|
415
420
|
operators : /[<>=]/g, // replace operators
|
416
421
|
query : '(q|query)' // replace filter queries
|
417
422
|
},
|
418
423
|
// function( c, data ) { }
|
419
424
|
// c = table.config
|
420
|
-
// data.filter = array of filter input values;
|
425
|
+
// data.filter = array of filter input values;
|
426
|
+
// data.iFilter = same array, except lowercase (if wo.filter_ignoreCase is true)
|
421
427
|
// data.exact = table cell text (or parsed data if column parser enabled)
|
422
|
-
// data.iExact = same as data.exact, except lowercase
|
423
|
-
// data.cache = table cell text from cache, so it has been parsed
|
428
|
+
// data.iExact = same as data.exact, except lowercase (if wo.filter_ignoreCase is true)
|
429
|
+
// data.cache = table cell text from cache, so it has been parsed (& in all lower case if config.ignoreCase is true)
|
424
430
|
// data.index = column index; table = table element (DOM)
|
425
431
|
// data.parsed = array (by column) of boolean values (from filter_useParsedData or "filter-parsed" class)
|
426
432
|
types: {
|
@@ -537,12 +543,14 @@ ts.filter = {
|
|
537
543
|
},
|
538
544
|
// Look for wild card: ? = single, * = multiple, or | = logical OR
|
539
545
|
wild : function( c, data ) {
|
540
|
-
if ( /[
|
546
|
+
if ( /[\?\*\|]/.test(data.iFilter) || ts.filter.regex.orReplace.test(data.filter) ) {
|
541
547
|
var index = data.index,
|
542
548
|
parsed = data.parsed[index],
|
543
549
|
query = ts.filter.parseFilter(c, data.iFilter.replace(ts.filter.regex.orReplace, "|"), index, parsed);
|
544
550
|
// look for an exact match with the "or" unless the "filter-match" class is found
|
545
551
|
if (!c.$headers.filter('[data-column="' + index + '"]:last').hasClass('filter-match') && /\|/.test(query)) {
|
552
|
+
// show all results while using filter match. Fixes #727
|
553
|
+
if (query[ query.length - 1 ] === '|') { query += '*'; }
|
546
554
|
query = data.anyMatch && $.isArray(data.rowArray) ? '(' + query + ')' : '^(' + query + ')$';
|
547
555
|
}
|
548
556
|
// parsing the filter may not work properly when using wildcards =/
|
@@ -578,11 +586,8 @@ ts.filter = {
|
|
578
586
|
and : 'and'
|
579
587
|
}, ts.language);
|
580
588
|
|
581
|
-
var options, string, txt, $header, column, filters, val,
|
589
|
+
var options, string, txt, $header, column, filters, val, fxn, noSelect,
|
582
590
|
regex = ts.filter.regex;
|
583
|
-
if (c.debug) {
|
584
|
-
time = new Date();
|
585
|
-
}
|
586
591
|
c.$table.addClass('hasFilters');
|
587
592
|
|
588
593
|
// define timers so using clearTimeout won't cause an undefined error
|
@@ -591,6 +596,8 @@ ts.filter = {
|
|
591
596
|
wo.filter_formatterCount = 0;
|
592
597
|
wo.filter_formatterInit = [];
|
593
598
|
wo.filter_initializing = true;
|
599
|
+
wo.filter_anyColumnSelector = '[data-column="all"],[data-column="any"]';
|
600
|
+
wo.filter_multipleColumnSelector = '[data-column*="-"],[data-column*=","]';
|
594
601
|
|
595
602
|
txt = '\\{' + ts.filter.regex.query + '\\}';
|
596
603
|
$.extend( regex, {
|
@@ -714,9 +721,6 @@ ts.filter = {
|
|
714
721
|
// set filtered rows count (intially unfiltered)
|
715
722
|
c.filteredRows = c.totalRows;
|
716
723
|
|
717
|
-
if (c.debug) {
|
718
|
-
ts.benchmark("Applying Filter widget", time);
|
719
|
-
}
|
720
724
|
// add default values
|
721
725
|
c.$table.bind('tablesorter-initialized pagerInitialized', function() {
|
722
726
|
// redefine "wo" as it does not update properly inside this callback
|
@@ -758,9 +762,10 @@ ts.filter = {
|
|
758
762
|
var wo = c.widgetOptions,
|
759
763
|
count = 0,
|
760
764
|
completed = function(){
|
761
|
-
|
765
|
+
// set initializing false first so findRows will process
|
762
766
|
wo.filter_initializing = false;
|
763
767
|
ts.filter.findRows(c.table, c.$table.data('lastSearch'), null);
|
768
|
+
wo.filter_initialized = true;
|
764
769
|
c.$table.trigger('filterInit', c);
|
765
770
|
};
|
766
771
|
$.each( wo.filter_formatterInit, function(i, val) {
|
@@ -780,7 +785,7 @@ ts.filter = {
|
|
780
785
|
}, 500);
|
781
786
|
}
|
782
787
|
},
|
783
|
-
|
788
|
+
|
784
789
|
setDefaults: function(table, c, wo) {
|
785
790
|
var isArray, saved, indx,
|
786
791
|
// get current (default) filters
|
@@ -809,9 +814,14 @@ ts.filter = {
|
|
809
814
|
var col, column, $header, buildSelect, disabled, name, ffxn,
|
810
815
|
// c.columns defined in computeThIndexes()
|
811
816
|
columns = c.columns,
|
817
|
+
arry = $.isArray(wo.filter_cellFilter),
|
812
818
|
buildFilter = '<tr role="row" class="' + ts.css.filterRow + '">';
|
813
819
|
for (column = 0; column < columns; column++) {
|
814
|
-
|
820
|
+
if (arry) {
|
821
|
+
buildFilter += '<td' + ( wo.filter_cellFilter[column] ? ' class="' + wo.filter_cellFilter[column] + '"' : '' ) + '></td>';
|
822
|
+
} else {
|
823
|
+
buildFilter += '<td' + ( wo.filter_cellFilter !== '' ? ' class="' + wo.filter_cellFilter + '"' : '' ) + '></td>';
|
824
|
+
}
|
815
825
|
}
|
816
826
|
c.$filters = $(buildFilter += '</tr>').appendTo( c.$table.children('thead').eq(0) ).find('td');
|
817
827
|
// build each filter input
|
@@ -870,7 +880,7 @@ ts.filter = {
|
|
870
880
|
$ext = wo.filter_$externalFilters;
|
871
881
|
if (internal !== true) {
|
872
882
|
// save anyMatch element
|
873
|
-
wo.filter_$anyMatch = $el.filter('
|
883
|
+
wo.filter_$anyMatch = $el.filter(wo.filter_anyColumnSelector + ',' + wo.filter_multipleColumnSelector);
|
874
884
|
if ($ext && $ext.length) {
|
875
885
|
wo.filter_$externalFilters = wo.filter_$externalFilters.add( $el );
|
876
886
|
} else {
|
@@ -1033,6 +1043,57 @@ ts.filter = {
|
|
1033
1043
|
}
|
1034
1044
|
return val;
|
1035
1045
|
},
|
1046
|
+
getLatestSearch: function( $input ) {
|
1047
|
+
return $input.sort(function(a, b) {
|
1048
|
+
return $(b).attr('data-lastSearchTime') - $(a).attr('data-lastSearchTime');
|
1049
|
+
});
|
1050
|
+
},
|
1051
|
+
multipleColumns: function( c, $input ) {
|
1052
|
+
// look for multiple columns "1-3,4-6,8" in data-column
|
1053
|
+
var ranges, singles, indx,
|
1054
|
+
wo = c.widgetOptions,
|
1055
|
+
// only target "all" column inputs on initialization
|
1056
|
+
// & don't target "all" column inputs if they don't exist
|
1057
|
+
targets = wo.filter_initialized || !$input.filter(wo.filter_anyColumnSelector).length,
|
1058
|
+
columns = [],
|
1059
|
+
val = $.trim( ts.filter.getLatestSearch( $input ).attr('data-column') );
|
1060
|
+
// process column range
|
1061
|
+
if ( targets && /-/.test( val ) ) {
|
1062
|
+
ranges = val.match( /(\d+)\s*-\s*(\d+)/g );
|
1063
|
+
$.each(ranges, function(i,v){
|
1064
|
+
var t,
|
1065
|
+
range = v.split( /\s*-\s*/ ),
|
1066
|
+
start = parseInt( range[0], 10 ) || 0,
|
1067
|
+
end = parseInt( range[1], 10 ) || ( c.columns - 1 );
|
1068
|
+
if ( start > end ) { t = start; start = end; end = t; } // swap
|
1069
|
+
if ( end >= c.columns ) { end = c.columns - 1; }
|
1070
|
+
for ( ; start <= end; start++ ) {
|
1071
|
+
columns.push(start);
|
1072
|
+
}
|
1073
|
+
// remove processed range from val
|
1074
|
+
val = val.replace( v, '' );
|
1075
|
+
});
|
1076
|
+
}
|
1077
|
+
// process single columns
|
1078
|
+
if ( targets && /,/.test( val ) ) {
|
1079
|
+
singles = val.split( /\s*,\s*/ );
|
1080
|
+
$.each( singles, function(i,v) {
|
1081
|
+
if (v !== '') {
|
1082
|
+
indx = parseInt( v, 10 );
|
1083
|
+
if ( indx < c.columns ) {
|
1084
|
+
columns.push( indx );
|
1085
|
+
}
|
1086
|
+
}
|
1087
|
+
});
|
1088
|
+
}
|
1089
|
+
// return all columns
|
1090
|
+
if (!columns.length) {
|
1091
|
+
for ( indx = 0; indx < c.columns; indx++ ) {
|
1092
|
+
columns.push( indx );
|
1093
|
+
}
|
1094
|
+
}
|
1095
|
+
return columns;
|
1096
|
+
},
|
1036
1097
|
findRows: function(table, filters, combinedFilters) {
|
1037
1098
|
if (table.config.lastCombinedFilter === combinedFilters || table.config.widgetOptions.filter_initializing) { return; }
|
1038
1099
|
var len, $rows, rowIndex, tbodyIndex, $tbody, $cells, $cell, columnIndex,
|
@@ -1092,7 +1153,7 @@ ts.filter = {
|
|
1092
1153
|
// if we are not doing exact matches, using "|" (logical or) or not "!"
|
1093
1154
|
!/[=\"\|!]/.test(val) &&
|
1094
1155
|
// don't search only filtered if the value is negative ('> -10' => '> -100' will ignore hidden rows)
|
1095
|
-
!(/(>=?\s*-\d)/.test(val) || /(<=?\s*\d)/.test(val)) &&
|
1156
|
+
!(/(>=?\s*-\d)/.test(val) || /(<=?\s*\d)/.test(val)) &&
|
1096
1157
|
// if filtering using a select without a "filter-match" class (exact match) - fixes #593
|
1097
1158
|
!( val !== '' && c.$filters && c.$filters.eq(indx).find('select').length && !c.$headers.filter('[data-column="' + indx + '"]:last').hasClass('filter-match') );
|
1098
1159
|
}
|
@@ -1105,7 +1166,7 @@ ts.filter = {
|
|
1105
1166
|
}
|
1106
1167
|
if ((wo.filter_$anyMatch && wo.filter_$anyMatch.length) || filters[c.columns]) {
|
1107
1168
|
data.anyMatchFlag = true;
|
1108
|
-
data.anyMatchFilter = wo.filter_$anyMatch && wo.filter_$anyMatch.val() || filters[c.columns] || '';
|
1169
|
+
data.anyMatchFilter = wo.filter_$anyMatch && ts.filter.getLatestSearch( wo.filter_$anyMatch ).val() || filters[c.columns] || '';
|
1109
1170
|
if (c.sortLocaleCompare) {
|
1110
1171
|
// replace accents
|
1111
1172
|
data.anyMatchFilter = ts.replaceAccents(data.anyMatchFilter);
|
@@ -1115,7 +1176,9 @@ ts.filter = {
|
|
1115
1176
|
// clear search filtered flag because default filters are not saved to the last search
|
1116
1177
|
searchFiltered = false;
|
1117
1178
|
}
|
1118
|
-
|
1179
|
+
// make iAnyMatchFilter lowercase unless both filter widget & core ignoreCase options are true
|
1180
|
+
// when c.ignoreCase is true, the cache contains all lower case data
|
1181
|
+
data.iAnyMatchFilter = !(wo.filter_ignoreCase && c.ignoreCase) ? data.anyMatchFilter : data.anyMatchFilter.toLocaleLowerCase();
|
1119
1182
|
}
|
1120
1183
|
|
1121
1184
|
// loop through the rows
|
@@ -1135,25 +1198,28 @@ ts.filter = {
|
|
1135
1198
|
data.childRowText = (childRow.length && wo.filter_childRows) ? childRow.text() : '';
|
1136
1199
|
data.childRowText = wo.filter_ignoreCase ? data.childRowText.toLocaleLowerCase() : data.childRowText;
|
1137
1200
|
$cells = $rows.eq(rowIndex).children();
|
1138
|
-
|
1139
1201
|
if (data.anyMatchFlag) {
|
1202
|
+
// look for multiple columns "1-3,4-6,8"
|
1203
|
+
columnIndex = ts.filter.multipleColumns( c, wo.filter_$anyMatch );
|
1140
1204
|
data.anyMatch = true;
|
1141
1205
|
data.rowArray = $cells.map(function(i){
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1147
|
-
|
1148
|
-
|
1206
|
+
if ( $.inArray(i, columnIndex) > -1 ) {
|
1207
|
+
var txt;
|
1208
|
+
if (data.parsed[i]) {
|
1209
|
+
txt = data.cacheArray[i];
|
1210
|
+
} else {
|
1211
|
+
txt = wo.filter_ignoreCase ? $(this).text().toLowerCase() : $(this).text();
|
1212
|
+
if (c.sortLocaleCompare) {
|
1213
|
+
txt = ts.replaceAccents(txt);
|
1214
|
+
}
|
1149
1215
|
}
|
1216
|
+
return txt;
|
1150
1217
|
}
|
1151
|
-
return txt;
|
1152
1218
|
}).get();
|
1153
1219
|
data.filter = data.anyMatchFilter;
|
1154
1220
|
data.iFilter = data.iAnyMatchFilter;
|
1155
1221
|
data.exact = data.rowArray.join(' ');
|
1156
|
-
data.iExact = data.exact.toLowerCase();
|
1222
|
+
data.iExact = wo.filter_ignoreCase ? data.exact.toLowerCase() : data.exact;
|
1157
1223
|
data.cache = data.cacheArray.slice(0,-1).join(' ');
|
1158
1224
|
filterMatched = null;
|
1159
1225
|
$.each(ts.filter.types, function(type, typeFunction) {
|
@@ -1204,7 +1270,7 @@ ts.filter = {
|
|
1204
1270
|
result = showRow; // if showRow is true, show that row
|
1205
1271
|
|
1206
1272
|
// in case select filter option has a different value vs text "a - z|A through Z"
|
1207
|
-
ffxn = wo.filter_columnFilters ?
|
1273
|
+
ffxn = wo.filter_columnFilters ?
|
1208
1274
|
c.$filters.add(c.$externalFilters).filter('[data-column="'+ columnIndex + '"]').find('select option:selected').attr('data-function-name') || '' : '';
|
1209
1275
|
|
1210
1276
|
// replace accents - see #357
|
@@ -1216,7 +1282,7 @@ ts.filter = {
|
|
1216
1282
|
// val is used to indicate that a filter select is using a default filter; so we override the exact & partial matches
|
1217
1283
|
val = false;
|
1218
1284
|
}
|
1219
|
-
// data.iFilter = case insensitive, data.filter = case sensitive
|
1285
|
+
// data.iFilter = case insensitive (if wo.filter_ignoreCase is true), data.filter = case sensitive
|
1220
1286
|
data.iFilter = wo.filter_ignoreCase ? (data.filter || '').toLocaleLowerCase() : data.filter;
|
1221
1287
|
fxn = ts.getColumnData( table, wo.filter_functions, columnIndex );
|
1222
1288
|
$cell = c.$headers.filter('[data-column="' + columnIndex + '"]:last');
|
@@ -1461,7 +1527,7 @@ ts.filter = {
|
|
1461
1527
|
};
|
1462
1528
|
|
1463
1529
|
ts.getFilters = function(table, getRaw, setFilters, skipFirst) {
|
1464
|
-
var i, $filters, $column,
|
1530
|
+
var i, f, $filters, $column, cols,
|
1465
1531
|
filters = false,
|
1466
1532
|
c = table ? $(table)[0].config : '',
|
1467
1533
|
wo = c ? c.widgetOptions : '';
|
@@ -1478,19 +1544,34 @@ ts.getFilters = function(table, getRaw, setFilters, skipFirst) {
|
|
1478
1544
|
if ($filters && $filters.length) {
|
1479
1545
|
filters = setFilters || [];
|
1480
1546
|
for (i = 0; i < c.columns + 1; i++) {
|
1481
|
-
|
1547
|
+
cols = ( i === c.columns ?
|
1548
|
+
// "all" columns can now include a range or set of columms (data-column="0-2,4,6-7")
|
1549
|
+
wo.filter_anyColumnSelector + ',' + wo.filter_multipleColumnSelector :
|
1550
|
+
'[data-column="' + i + '"]' );
|
1551
|
+
$column = $filters.filter(cols);
|
1482
1552
|
if ($column.length) {
|
1483
1553
|
// move the latest search to the first slot in the array
|
1484
|
-
$column =
|
1485
|
-
return $(b).attr('data-lastSearchTime') - $(a).attr('data-lastSearchTime');
|
1486
|
-
});
|
1554
|
+
$column = ts.filter.getLatestSearch( $column );
|
1487
1555
|
if ($.isArray(setFilters)) {
|
1488
1556
|
// skip first (latest input) to maintain cursor position while typing
|
1489
|
-
(skipFirst
|
1557
|
+
if (skipFirst) { $column.slice(1); }
|
1558
|
+
if (i === c.columns) {
|
1559
|
+
// prevent data-column="all" from filling data-column="0,1" (etc)
|
1560
|
+
cols = $column.filter(wo.filter_anyColumnSelector);
|
1561
|
+
$column = cols.length ? cols : $column;
|
1562
|
+
}
|
1563
|
+
$column
|
1564
|
+
.val( setFilters[i] )
|
1565
|
+
.trigger('change.tsfilter');
|
1490
1566
|
} else {
|
1491
1567
|
filters[i] = $column.val() || '';
|
1492
1568
|
// don't change the first... it will move the cursor
|
1493
|
-
|
1569
|
+
if (i === c.columns) {
|
1570
|
+
// don't update range columns from "all" setting
|
1571
|
+
$column.slice(1).filter('[data-column*="' + $column.attr('data-column') + '"]').val( filters[i] );
|
1572
|
+
} else {
|
1573
|
+
$column.slice(1).val( filters[i] );
|
1574
|
+
}
|
1494
1575
|
}
|
1495
1576
|
// save any match input dynamically
|
1496
1577
|
if (i === c.columns && $column.length) {
|
@@ -1530,6 +1611,8 @@ ts.addWidget({
|
|
1530
1611
|
options: {
|
1531
1612
|
stickyHeaders : '', // extra class name added to the sticky header row
|
1532
1613
|
stickyHeaders_attachTo : null, // jQuery selector or object to attach sticky header to
|
1614
|
+
stickyHeaders_xScroll : null, // jQuery selector or object to monitor horizontal scroll position (defaults: xScroll > attachTo > window)
|
1615
|
+
stickyHeaders_yScroll : null, // jQuery selector or object to monitor vertical scroll position (defaults: yScroll > attachTo > window)
|
1533
1616
|
stickyHeaders_offset : 0, // number or jquery selector targeting the position:fixed element
|
1534
1617
|
stickyHeaders_filteredToTop: true, // scroll table top into view after filtering
|
1535
1618
|
stickyHeaders_cloneId : '-sticky', // added to table ID, if it exists
|
@@ -1543,54 +1626,74 @@ ts.addWidget({
|
|
1543
1626
|
return;
|
1544
1627
|
}
|
1545
1628
|
var $table = c.$table,
|
1546
|
-
$attach = $(wo.stickyHeaders_attachTo
|
1629
|
+
$attach = $(wo.stickyHeaders_attachTo),
|
1630
|
+
namespace = c.namespace + 'stickyheaders ',
|
1631
|
+
// element to watch for the scroll event
|
1632
|
+
$yScroll = $(wo.stickyHeaders_yScroll || wo.stickyHeaders_attachTo || window),
|
1633
|
+
$xScroll = $(wo.stickyHeaders_xScroll || wo.stickyHeaders_attachTo || window),
|
1547
1634
|
$thead = $table.children('thead:first'),
|
1548
|
-
$win = $attach.length ? $attach : $(window),
|
1549
1635
|
$header = $thead.children('tr').not('.sticky-false').children(),
|
1550
|
-
|
1551
|
-
$tfoot = $table.find('tfoot'),
|
1636
|
+
$tfoot = $table.children('tfoot'),
|
1552
1637
|
$stickyOffset = isNaN(wo.stickyHeaders_offset) ? $(wo.stickyHeaders_offset) : '',
|
1553
1638
|
stickyOffset = $attach.length ? 0 : $stickyOffset.length ?
|
1554
1639
|
$stickyOffset.height() || 0 : parseInt(wo.stickyHeaders_offset, 10) || 0,
|
1640
|
+
// is this table nested? If so, find parent sticky header wrapper (div, not table)
|
1641
|
+
$nestedSticky = $table.parent().closest('.' + ts.css.table).hasClass('hasStickyHeaders') ?
|
1642
|
+
$table.parent().closest('table.tablesorter')[0].config.widgetOptions.$sticky.parent() : [],
|
1643
|
+
nestedStickyTop = $nestedSticky.length ? $nestedSticky.height() : 0,
|
1644
|
+
// clone table, then wrap to make sticky header
|
1555
1645
|
$stickyTable = wo.$sticky = $table.clone()
|
1556
|
-
.addClass('containsStickyHeaders')
|
1557
|
-
.css
|
1558
|
-
|
1559
|
-
|
1560
|
-
|
1561
|
-
|
1562
|
-
|
1563
|
-
|
1564
|
-
|
1565
|
-
|
1646
|
+
.addClass('containsStickyHeaders ' + ts.css.sticky + ' ' + wo.stickyHeaders)
|
1647
|
+
.wrap('<div class="' + ts.css.stickyWrap + '">'),
|
1648
|
+
$stickyWrap = $stickyTable.parent().css({
|
1649
|
+
position : $attach.length ? 'absolute' : 'fixed',
|
1650
|
+
margin : 0,
|
1651
|
+
top : stickyOffset + nestedStickyTop,
|
1652
|
+
left : 0,
|
1653
|
+
visibility : 'hidden',
|
1654
|
+
zIndex : wo.stickyHeaders_zIndex || 2
|
1655
|
+
}),
|
1656
|
+
$stickyThead = $stickyTable.children('thead:first'),
|
1566
1657
|
$stickyCells,
|
1567
1658
|
laststate = '',
|
1568
1659
|
spacing = 0,
|
1569
|
-
|
1660
|
+
setWidth = function($orig, $clone){
|
1661
|
+
$orig.filter(':visible').each(function(i) {
|
1662
|
+
var width, border,
|
1663
|
+
$cell = $clone.filter(':visible').eq(i),
|
1664
|
+
$this = $(this);
|
1665
|
+
// code from https://github.com/jmosbech/StickyTableHeaders
|
1666
|
+
if ($this.css('box-sizing') === 'border-box') {
|
1667
|
+
width = $this.outerWidth();
|
1668
|
+
} else {
|
1669
|
+
if ($cell.css('border-collapse') === 'collapse') {
|
1670
|
+
if (window.getComputedStyle) {
|
1671
|
+
width = parseFloat( window.getComputedStyle(this, null).width );
|
1672
|
+
} else {
|
1673
|
+
// ie8 only
|
1674
|
+
border = parseFloat( $this.css('border-width') );
|
1675
|
+
width = $this.outerWidth() - parseFloat( $this.css('padding-left') ) - parseFloat( $this.css('padding-right') ) - border;
|
1676
|
+
}
|
1677
|
+
} else {
|
1678
|
+
width = $this.width();
|
1679
|
+
}
|
1680
|
+
}
|
1681
|
+
$cell.css({
|
1682
|
+
'min-width': width,
|
1683
|
+
'max-width': width
|
1684
|
+
});
|
1685
|
+
});
|
1686
|
+
},
|
1570
1687
|
resizeHeader = function() {
|
1571
1688
|
stickyOffset = $stickyOffset.length ? $stickyOffset.height() || 0 : parseInt(wo.stickyHeaders_offset, 10) || 0;
|
1572
1689
|
spacing = 0;
|
1573
|
-
|
1574
|
-
|
1575
|
-
|
1576
|
-
|
1577
|
-
// update border-spacing here because of demos that switch themes
|
1578
|
-
spacing = parseInt($header.eq(0).css('border-left-width'), 10) * 2;
|
1579
|
-
}
|
1580
|
-
$stickyTable.css({
|
1581
|
-
left : $attach.length ? (parseInt($attach.css('padding-left'), 10) || 0) + parseInt(c.$table.css('padding-left'), 10) +
|
1582
|
-
parseInt(c.$table.css('margin-left'), 10) + parseInt($table.css('border-left-width'), 10) :
|
1583
|
-
$thead.offset().left - $win.scrollLeft() - spacing,
|
1584
|
-
width: $table.width()
|
1585
|
-
});
|
1586
|
-
$stickyCells.filter(':visible').each(function(i) {
|
1587
|
-
var $cell = $header.filter(':visible').eq(i),
|
1588
|
-
// some wibbly-wobbly... timey-wimey... stuff, to make columns line up in Firefox
|
1589
|
-
offset = nonwkie && $(this).attr('data-column') === ( '' + parseInt(c.columns/2, 10) ) ? 1 : 0;
|
1590
|
-
$(this)
|
1591
|
-
.css({ width: $cell.width() - spacing })
|
1592
|
-
.find(innerHeader).width( $cell.find(innerHeader).width() - offset );
|
1690
|
+
$stickyWrap.css({
|
1691
|
+
left : $attach.length ? parseInt($attach.css('padding-left'), 10) || 0 :
|
1692
|
+
$table.offset().left - parseInt($table.css('margin-left'), 10) - $xScroll.scrollLeft() - spacing,
|
1693
|
+
width: $table.outerWidth()
|
1593
1694
|
});
|
1695
|
+
setWidth( $table, $stickyTable );
|
1696
|
+
setWidth( $header, $stickyCells );
|
1594
1697
|
};
|
1595
1698
|
// fix clone ID, if it exists - fixes #271
|
1596
1699
|
if ($stickyTable.attr('id')) { $stickyTable[0].id += wo.stickyHeaders_cloneId; }
|
@@ -1600,42 +1703,60 @@ ts.addWidget({
|
|
1600
1703
|
$stickyTable.find('tbody, tfoot').remove();
|
1601
1704
|
if (!wo.stickyHeaders_includeCaption) {
|
1602
1705
|
$stickyTable.find('caption').remove();
|
1603
|
-
} else {
|
1604
|
-
$stickyTable.find('caption').css( 'margin-left', '-1px' );
|
1605
1706
|
}
|
1606
1707
|
// issue #172 - find td/th in sticky header
|
1607
1708
|
$stickyCells = $stickyThead.children().children();
|
1608
|
-
$stickyTable.css({ height:0, width:0,
|
1709
|
+
$stickyTable.css({ height:0, width:0, margin: 0 });
|
1609
1710
|
// remove resizable block
|
1610
1711
|
$stickyCells.find('.' + ts.css.resizer).remove();
|
1611
1712
|
// update sticky header class names to match real header after sorting
|
1612
1713
|
$table
|
1613
1714
|
.addClass('hasStickyHeaders')
|
1614
|
-
.bind('pagerComplete
|
1715
|
+
.bind('pagerComplete' + namespace, function() {
|
1615
1716
|
resizeHeader();
|
1616
1717
|
});
|
1617
1718
|
|
1618
1719
|
ts.bindEvents(table, $stickyThead.children().children('.tablesorter-header'));
|
1619
1720
|
|
1620
1721
|
// add stickyheaders AFTER the table. If the table is selected by ID, the original one (first) will be returned.
|
1621
|
-
$table.after( $
|
1722
|
+
$table.after( $stickyWrap );
|
1723
|
+
|
1724
|
+
// onRenderHeader is defined, we need to do something about it (fixes #641)
|
1725
|
+
if (c.onRenderHeader) {
|
1726
|
+
$stickyThead.children('tr').children().each(function(index){
|
1727
|
+
// send second parameter
|
1728
|
+
c.onRenderHeader.apply( $(this), [ index, c, $stickyTable ] );
|
1729
|
+
});
|
1730
|
+
}
|
1731
|
+
|
1622
1732
|
// make it sticky!
|
1623
|
-
$
|
1733
|
+
$xScroll.add($yScroll)
|
1734
|
+
.unbind('scroll resize '.split(' ').join( namespace ) )
|
1735
|
+
.bind('scroll resize '.split(' ').join( namespace ), function(event) {
|
1624
1736
|
if (!$table.is(':visible')) { return; } // fixes #278
|
1737
|
+
// Detect nested tables - fixes #724
|
1738
|
+
nestedStickyTop = $nestedSticky.length ? $nestedSticky.offset().top - $yScroll.scrollTop() + $nestedSticky.height() : 0;
|
1625
1739
|
var prefix = 'tablesorter-sticky-',
|
1626
1740
|
offset = $table.offset(),
|
1627
|
-
|
1628
|
-
|
1629
|
-
|
1630
|
-
|
1741
|
+
yWindow = $.isWindow( $yScroll[0] ),
|
1742
|
+
xWindow = $.isWindow( $xScroll[0] ),
|
1743
|
+
// scrollTop = ( $attach.length ? $attach.offset().top : $yScroll.scrollTop() ) + stickyOffset + nestedStickyTop,
|
1744
|
+
scrollTop = ( $attach.length ? ( yWindow ? $yScroll.scrollTop() : $yScroll.offset().top ) : $yScroll.scrollTop() ) + stickyOffset + nestedStickyTop,
|
1745
|
+
tableHeight = $table.height() - ($stickyWrap.height() + ($tfoot.height() || 0)),
|
1746
|
+
isVisible = ( scrollTop > offset.top) && (scrollTop < offset.top + tableHeight) ? 'visible' : 'hidden',
|
1631
1747
|
cssSettings = { visibility : isVisible };
|
1748
|
+
|
1632
1749
|
if ($attach.length) {
|
1633
|
-
cssSettings.top = $attach.scrollTop();
|
1634
|
-
}
|
1750
|
+
cssSettings.top = yWindow ? scrollTop : $attach.scrollTop();
|
1751
|
+
}
|
1752
|
+
if (xWindow) {
|
1635
1753
|
// adjust when scrolling horizontally - fixes issue #143
|
1636
|
-
cssSettings.left = $
|
1754
|
+
cssSettings.left = $table.offset().left - parseInt($table.css('margin-left'), 10) - $xScroll.scrollLeft() - spacing;
|
1637
1755
|
}
|
1638
|
-
$
|
1756
|
+
if ($nestedSticky.length) {
|
1757
|
+
cssSettings.top = ( cssSettings.top || 0 ) + stickyOffset + nestedStickyTop;
|
1758
|
+
}
|
1759
|
+
$stickyWrap
|
1639
1760
|
.removeClass(prefix + 'visible ' + prefix + 'hidden')
|
1640
1761
|
.addClass(prefix + isVisible)
|
1641
1762
|
.css(cssSettings);
|
@@ -1650,14 +1771,14 @@ ts.addWidget({
|
|
1650
1771
|
}
|
1651
1772
|
|
1652
1773
|
// look for filter widget
|
1653
|
-
if ($table.hasClass('hasFilters')) {
|
1774
|
+
if ($table.hasClass('hasFilters') && wo.filter_columnFilters) {
|
1654
1775
|
// scroll table into view after filtering, if sticky header is active - #482
|
1655
|
-
$table.bind('filterEnd', function() {
|
1776
|
+
$table.bind('filterEnd' + namespace, function() {
|
1656
1777
|
// $(':focus') needs jQuery 1.6+
|
1657
1778
|
var $td = $(document.activeElement).closest('td'),
|
1658
1779
|
column = $td.parent().children().index($td);
|
1659
1780
|
// only scroll if sticky header is active
|
1660
|
-
if ($
|
1781
|
+
if ($stickyWrap.hasClass(ts.css.stickyVis) && wo.stickyHeaders_filteredToTop) {
|
1661
1782
|
// scroll to original table (not sticky clone)
|
1662
1783
|
window.scrollTo(0, $table.position().top);
|
1663
1784
|
// give same input/select focus; check if c.$filters exists; fixes #594
|
@@ -1677,14 +1798,16 @@ ts.addWidget({
|
|
1677
1798
|
|
1678
1799
|
},
|
1679
1800
|
remove: function(table, c, wo) {
|
1801
|
+
var namespace = c.namespace + 'stickyheaders ';
|
1680
1802
|
c.$table
|
1681
1803
|
.removeClass('hasStickyHeaders')
|
1682
|
-
.unbind('pagerComplete.
|
1683
|
-
.
|
1804
|
+
.unbind( 'pagerComplete filterEnd '.split(' ').join(namespace) )
|
1805
|
+
.next('.' + ts.css.stickyWrap).remove();
|
1684
1806
|
if (wo.$sticky && wo.$sticky.length) { wo.$sticky.remove(); } // remove cloned table
|
1685
1807
|
// don't unbind if any table on the page still has stickyheaders applied
|
1686
1808
|
if (!$('.hasStickyHeaders').length) {
|
1687
|
-
$(window).
|
1809
|
+
$(window).add(wo.stickyHeaders_xScroll).add(wo.stickyHeaders_yScroll).add(wo.stickyHeaders_attachTo)
|
1810
|
+
.unbind( 'scroll resize '.split(' ').join(namespace) );
|
1688
1811
|
}
|
1689
1812
|
ts.addHeaderResizeEvent(table, false);
|
1690
1813
|
}
|
@@ -1710,6 +1833,8 @@ ts.addWidget({
|
|
1710
1833
|
var $rows, $columns, $column, column, timer,
|
1711
1834
|
storedSizes = {},
|
1712
1835
|
$table = c.$table,
|
1836
|
+
$wrap = $table.parent(),
|
1837
|
+
overflow = $table.parent().css('overflow') === 'auto',
|
1713
1838
|
mouseXPosition = 0,
|
1714
1839
|
$target = null,
|
1715
1840
|
$next = null,
|
@@ -1722,6 +1847,14 @@ ts.addWidget({
|
|
1722
1847
|
$target.width( targetWidth + leftEdge );
|
1723
1848
|
if ($target.width() !== targetWidth && fullWidth) {
|
1724
1849
|
$next.width( $next.width() - leftEdge );
|
1850
|
+
} else if (overflow) {
|
1851
|
+
$table.width(function(i, w){
|
1852
|
+
return w + leftEdge;
|
1853
|
+
});
|
1854
|
+
if (!$next.length) {
|
1855
|
+
// if expanding right-most column, scroll the wrapper
|
1856
|
+
$wrap[0].scrollLeft = $table.width();
|
1857
|
+
}
|
1725
1858
|
}
|
1726
1859
|
mouseXPosition = event.pageX;
|
1727
1860
|
},
|
@@ -1909,4 +2042,4 @@ ts.addWidget({
|
|
1909
2042
|
}
|
1910
2043
|
});
|
1911
2044
|
|
1912
|
-
})(jQuery);
|
2045
|
+
})(jQuery, window);
|