jquery-tablesorter 1.19.1 → 1.19.2
Sign up to get free protection for your applications and to get access to all the features.
- 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 +9 -5
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.combined.js +201 -168
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.js +59 -47
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets.js +142 -121
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-file-type.js +24 -2
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter.js +141 -120
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-grouping.js +2 -2
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-headerTitles.js +2 -2
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-math.js +6 -5
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-pager.js +8 -5
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-sort2Hash.js +45 -23
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-toggle.js +81 -0
- metadata +3 -2
@@ -4,7 +4,7 @@
|
|
4
4
|
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██▀▀ ▀▀▀██
|
5
5
|
█████▀ ▀████▀ ██ ██ ▀████▀ ██ ██ ██ ██ ▀████▀ █████▀ ██ ██ █████▀
|
6
6
|
*/
|
7
|
-
/*! tablesorter (FORK) - updated 11-
|
7
|
+
/*! tablesorter (FORK) - updated 11-10-2015 (v2.24.4)*/
|
8
8
|
/* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */
|
9
9
|
(function(factory) {
|
10
10
|
if (typeof define === 'function' && define.amd) {
|
@@ -16,7 +16,7 @@
|
|
16
16
|
}
|
17
17
|
}(function($) {
|
18
18
|
|
19
|
-
/*! TableSorter (FORK) v2.24.
|
19
|
+
/*! TableSorter (FORK) v2.24.4 *//*
|
20
20
|
* Client-side table sorting with ease!
|
21
21
|
* @requires jQuery v1.2.6+
|
22
22
|
*
|
@@ -39,7 +39,7 @@
|
|
39
39
|
'use strict';
|
40
40
|
var ts = $.tablesorter = {
|
41
41
|
|
42
|
-
version : '2.24.
|
42
|
+
version : '2.24.4',
|
43
43
|
|
44
44
|
parsers : [],
|
45
45
|
widgets : [],
|
@@ -157,12 +157,13 @@
|
|
157
157
|
|
158
158
|
// labels applied to sortable headers for accessibility (aria) support
|
159
159
|
language : {
|
160
|
-
sortAsc
|
161
|
-
sortDesc
|
162
|
-
sortNone
|
163
|
-
|
164
|
-
|
165
|
-
|
160
|
+
sortAsc : 'Ascending sort applied, ',
|
161
|
+
sortDesc : 'Descending sort applied, ',
|
162
|
+
sortNone : 'No sort applied, ',
|
163
|
+
sortDisabled : 'sorting is disabled',
|
164
|
+
nextAsc : 'activate to apply an ascending sort',
|
165
|
+
nextDesc : 'activate to apply a descending sort',
|
166
|
+
nextNone : 'activate to remove the sort'
|
166
167
|
},
|
167
168
|
|
168
169
|
regex : {
|
@@ -1011,7 +1012,7 @@
|
|
1011
1012
|
▀████▀ ██ █████▀ ██ ██ ██ ██████
|
1012
1013
|
*/
|
1013
1014
|
setHeadersCss : function( c ) {
|
1014
|
-
var $sorted,
|
1015
|
+
var $sorted, indx, column,
|
1015
1016
|
list = c.sortList,
|
1016
1017
|
len = list.length,
|
1017
1018
|
none = ts.css.sortNone + ' ' + c.cssNone,
|
@@ -1079,50 +1080,62 @@
|
|
1079
1080
|
}
|
1080
1081
|
// add verbose aria labels
|
1081
1082
|
len = c.$headers.length;
|
1082
|
-
$headers = c.$headers.not( '.sorter-false' );
|
1083
1083
|
for ( indx = 0; indx < len; indx++ ) {
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1084
|
+
ts.setColumnAriaLabel( c, c.$headers.eq( indx ) );
|
1085
|
+
}
|
1086
|
+
},
|
1087
|
+
|
1088
|
+
// nextSort (optional), lets you disable next sort text
|
1089
|
+
setColumnAriaLabel : function( c, $header, nextSort ) {
|
1090
|
+
if ( $header.length ) {
|
1091
|
+
var column = parseInt( $header.attr( 'data-column' ), 10 ),
|
1089
1092
|
tmp = $header.hasClass( ts.css.sortAsc ) ?
|
1090
1093
|
'sortAsc' :
|
1091
|
-
$header.hasClass( ts.css.sortDesc ) ? 'sortDesc' : 'sortNone'
|
1092
|
-
txt = $.trim( $header.text() ) + ': ' +
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1094
|
+
$header.hasClass( ts.css.sortDesc ) ? 'sortDesc' : 'sortNone',
|
1095
|
+
txt = $.trim( $header.text() ) + ': ' + ts.language[ tmp ];
|
1096
|
+
if ( $header.hasClass( 'sorter-false' ) || nextSort === false ) {
|
1097
|
+
txt += ts.language.sortDisabled;
|
1098
|
+
} else {
|
1099
|
+
nextSort = c.sortVars[ column ].order[ ( c.sortVars[ column ].count + 1 ) % ( c.sortReset ? 3 : 2 ) ];
|
1100
|
+
// if nextSort
|
1101
|
+
txt += ts.language[ nextSort === 0 ? 'nextAsc' : nextSort === 1 ? 'nextDesc' : 'nextNone' ];
|
1096
1102
|
}
|
1103
|
+
$header.attr( 'aria-label', txt );
|
1097
1104
|
}
|
1098
1105
|
},
|
1099
1106
|
|
1100
1107
|
updateHeader : function( c ) {
|
1101
|
-
var index, isDisabled, $
|
1108
|
+
var index, isDisabled, $header, col,
|
1102
1109
|
table = c.table,
|
1103
1110
|
len = c.$headers.length;
|
1104
1111
|
for ( index = 0; index < len; index++ ) {
|
1105
|
-
$
|
1112
|
+
$header = c.$headers.eq( index );
|
1106
1113
|
col = ts.getColumnData( table, c.headers, index, true );
|
1107
1114
|
// add 'sorter-false' class if 'parser-false' is set
|
1108
|
-
isDisabled = ts.getData( $
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1115
|
+
isDisabled = ts.getData( $header, col, 'sorter' ) === 'false' || ts.getData( $header, col, 'parser' ) === 'false';
|
1116
|
+
ts.setColumnSort( c, $header, isDisabled );
|
1117
|
+
}
|
1118
|
+
},
|
1119
|
+
|
1120
|
+
setColumnSort : function( c, $header, isDisabled ) {
|
1121
|
+
var id = c.table.id;
|
1122
|
+
$header[ 0 ].sortDisabled = isDisabled;
|
1123
|
+
$header[ isDisabled ? 'addClass' : 'removeClass' ]( 'sorter-false' )
|
1124
|
+
.attr( 'aria-disabled', '' + isDisabled );
|
1125
|
+
// disable tab index on disabled cells
|
1126
|
+
if ( c.tabIndex ) {
|
1127
|
+
if ( isDisabled ) {
|
1128
|
+
$header.removeAttr( 'tabindex' );
|
1129
|
+
} else {
|
1130
|
+
$header.attr( 'tabindex', '0' );
|
1118
1131
|
}
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1132
|
+
}
|
1133
|
+
// aria-controls - requires table ID
|
1134
|
+
if ( id ) {
|
1135
|
+
if ( isDisabled ) {
|
1136
|
+
$header.removeAttr( 'aria-controls' );
|
1137
|
+
} else {
|
1138
|
+
$header.attr( 'aria-controls', id );
|
1126
1139
|
}
|
1127
1140
|
}
|
1128
1141
|
},
|
@@ -1420,13 +1433,12 @@
|
|
1420
1433
|
event[ c.sortResetKey ] ? 2 : ( c.sortVars[ col ].count + 1 ) % ( c.sortReset ? 3 : 2 );
|
1421
1434
|
// reset all sorts on non-current column - issue #30
|
1422
1435
|
if ( c.sortRestart ) {
|
1423
|
-
tmp = cell;
|
1424
1436
|
for ( headerIndx = 0; headerIndx < len; headerIndx++ ) {
|
1425
1437
|
$header = c.$headers.eq( headerIndx );
|
1438
|
+
tmp = parseInt( $header.attr( 'data-column' ), 10 );
|
1426
1439
|
// only reset counts on columns that weren't just clicked on and if not included in a multisort
|
1427
|
-
if ( $header
|
1428
|
-
|
1429
|
-
c.sortVars[ $header.attr( 'data-column' ) ].count = -1;
|
1440
|
+
if ( col !== tmp && ( notMultiSort || $header.hasClass( ts.css.sortNone ) ) ) {
|
1441
|
+
c.sortVars[ tmp ].count = -1;
|
1430
1442
|
}
|
1431
1443
|
}
|
1432
1444
|
}
|
@@ -2185,14 +2197,14 @@
|
|
2185
2197
|
|
2186
2198
|
// *** Process table ***
|
2187
2199
|
// add processing indicator
|
2188
|
-
isProcessing : function( $table, toggle, $
|
2200
|
+
isProcessing : function( $table, toggle, $headers ) {
|
2189
2201
|
$table = $( $table );
|
2190
2202
|
var c = $table[ 0 ].config,
|
2191
2203
|
// default to all headers
|
2192
|
-
$header = $
|
2204
|
+
$header = $headers || $table.find( '.' + ts.css.header );
|
2193
2205
|
if ( toggle ) {
|
2194
|
-
// don't use sortList if custom $
|
2195
|
-
if ( typeof $
|
2206
|
+
// don't use sortList if custom $headers used
|
2207
|
+
if ( typeof $headers !== 'undefined' && c.sortList.length > 0 ) {
|
2196
2208
|
// get headers from the sortList
|
2197
2209
|
$header = $header.filter( function() {
|
2198
2210
|
// get data-column from attr to keep compatibility with jQuery 1.2.6
|
@@ -2984,13 +2996,13 @@
|
|
2984
2996
|
|
2985
2997
|
})(jQuery);
|
2986
2998
|
|
2987
|
-
/*! Widget: filter - updated 11/
|
2999
|
+
/*! Widget: filter - updated 11/10/2015 (v2.24.4) *//*
|
2988
3000
|
* Requires tablesorter v2.8+ and jQuery 1.7+
|
2989
3001
|
* by Rob Garrison
|
2990
3002
|
*/
|
2991
3003
|
;( function ( $ ) {
|
2992
3004
|
'use strict';
|
2993
|
-
var tsf,
|
3005
|
+
var tsf, tsfRegex,
|
2994
3006
|
ts = $.tablesorter || {},
|
2995
3007
|
tscss = ts.css;
|
2996
3008
|
|
@@ -3096,20 +3108,21 @@
|
|
3096
3108
|
// data.parsed = array ( by column ) of boolean values ( from filter_useParsedData or 'filter-parsed' class )
|
3097
3109
|
types: {
|
3098
3110
|
or : function( c, data, vars ) {
|
3099
|
-
|
3111
|
+
// look for "|", but not if it is inside of a regular expression
|
3112
|
+
if ( ( tsfRegex.orTest.test( data.iFilter ) || tsfRegex.orSplit.test( data.filter ) ) &&
|
3113
|
+
// this test for regex has potential to slow down the overall search
|
3114
|
+
!tsfRegex.regex.test( data.filter ) ) {
|
3100
3115
|
var indx, filterMatched, query, regex,
|
3101
3116
|
// duplicate data but split filter
|
3102
3117
|
data2 = $.extend( {}, data ),
|
3103
|
-
|
3104
|
-
|
3105
|
-
filter = data.filter.split( tsf.regex.orSplit ),
|
3106
|
-
iFilter = data.iFilter.split( tsf.regex.orSplit ),
|
3118
|
+
filter = data.filter.split( tsfRegex.orSplit ),
|
3119
|
+
iFilter = data.iFilter.split( tsfRegex.orSplit ),
|
3107
3120
|
len = filter.length;
|
3108
3121
|
for ( indx = 0; indx < len; indx++ ) {
|
3109
3122
|
data2.nestedFilters = true;
|
3110
|
-
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ],
|
3111
|
-
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ],
|
3112
|
-
query = '(' + ( tsf.parseFilter( c, data2.filter,
|
3123
|
+
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], data ) || '' );
|
3124
|
+
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], data ) || '' );
|
3125
|
+
query = '(' + ( tsf.parseFilter( c, data2.filter, data ) || '' ) + ')';
|
3113
3126
|
try {
|
3114
3127
|
// use try/catch, because query may not be a valid regex if "|" is contained within a partial regex search,
|
3115
3128
|
// e.g "/(Alex|Aar" -> Uncaught SyntaxError: Invalid regular expression: /(/(Alex)/: Unterminated group
|
@@ -3131,22 +3144,20 @@
|
|
3131
3144
|
},
|
3132
3145
|
// Look for an AND or && operator ( logical and )
|
3133
3146
|
and : function( c, data, vars ) {
|
3134
|
-
if (
|
3147
|
+
if ( tsfRegex.andTest.test( data.filter ) ) {
|
3135
3148
|
var indx, filterMatched, result, query, regex,
|
3136
3149
|
// duplicate data but split filter
|
3137
3150
|
data2 = $.extend( {}, data ),
|
3138
|
-
|
3139
|
-
|
3140
|
-
filter = data.filter.split( tsf.regex.andSplit ),
|
3141
|
-
iFilter = data.iFilter.split( tsf.regex.andSplit ),
|
3151
|
+
filter = data.filter.split( tsfRegex.andSplit ),
|
3152
|
+
iFilter = data.iFilter.split( tsfRegex.andSplit ),
|
3142
3153
|
len = filter.length;
|
3143
3154
|
for ( indx = 0; indx < len; indx++ ) {
|
3144
3155
|
data2.nestedFilters = true;
|
3145
|
-
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ],
|
3146
|
-
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ],
|
3147
|
-
query = ( '(' + ( tsf.parseFilter( c, data2.filter,
|
3156
|
+
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], data ) || '' );
|
3157
|
+
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], data ) || '' );
|
3158
|
+
query = ( '(' + ( tsf.parseFilter( c, data2.filter, data ) || '' ) + ')' )
|
3148
3159
|
// replace wild cards since /(a*)/i will match anything
|
3149
|
-
.replace(
|
3160
|
+
.replace( tsfRegex.wild01, '\\S{1}' ).replace( tsfRegex.wild0More, '\\S*' );
|
3150
3161
|
try {
|
3151
3162
|
// use try/catch just in case RegExp is invalid
|
3152
3163
|
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
|
@@ -3168,10 +3179,10 @@
|
|
3168
3179
|
},
|
3169
3180
|
// Look for regex
|
3170
3181
|
regex: function( c, data ) {
|
3171
|
-
if (
|
3182
|
+
if ( tsfRegex.regex.test( data.filter ) ) {
|
3172
3183
|
var matches,
|
3173
3184
|
// cache regex per column for optimal speed
|
3174
|
-
regex = data.filter_regexCache[ data.index ] ||
|
3185
|
+
regex = data.filter_regexCache[ data.index ] || tsfRegex.regex.exec( data.filter ),
|
3175
3186
|
isRegex = regex instanceof RegExp;
|
3176
3187
|
try {
|
3177
3188
|
if ( !isRegex ) {
|
@@ -3190,18 +3201,17 @@
|
|
3190
3201
|
// Look for operators >, >=, < or <=
|
3191
3202
|
operators: function( c, data ) {
|
3192
3203
|
// ignore empty strings... because '' < 10 is true
|
3193
|
-
if (
|
3204
|
+
if ( tsfRegex.operTest.test( data.iFilter ) && data.iExact !== '' ) {
|
3194
3205
|
var cachedValue, result, txt,
|
3195
3206
|
table = c.table,
|
3196
|
-
|
3197
|
-
|
3198
|
-
|
3199
|
-
parser = c.parsers[index],
|
3207
|
+
parsed = data.parsed[ data.index ],
|
3208
|
+
query = ts.formatFloat( data.iFilter.replace( tsfRegex.operators, '' ), table ),
|
3209
|
+
parser = c.parsers[ data.index ],
|
3200
3210
|
savedSearch = query;
|
3201
3211
|
// parse filter value in case we're comparing numbers ( dates )
|
3202
3212
|
if ( parsed || parser.type === 'numeric' ) {
|
3203
|
-
txt = $.trim( '' + data.iFilter.replace(
|
3204
|
-
result = tsf.parseFilter( c, txt,
|
3213
|
+
txt = $.trim( '' + data.iFilter.replace( tsfRegex.operators, '' ) );
|
3214
|
+
result = tsf.parseFilter( c, txt, data, true );
|
3205
3215
|
query = ( typeof result === 'number' && result !== '' && !isNaN( result ) ) ? result : query;
|
3206
3216
|
}
|
3207
3217
|
// iExact may be numeric - see issue #149;
|
@@ -3213,10 +3223,10 @@
|
|
3213
3223
|
txt = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
|
3214
3224
|
cachedValue = ts.formatFloat( txt, table );
|
3215
3225
|
}
|
3216
|
-
if (
|
3217
|
-
result =
|
3218
|
-
} else if (
|
3219
|
-
result =
|
3226
|
+
if ( tsfRegex.gtTest.test( data.iFilter ) ) {
|
3227
|
+
result = tsfRegex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
|
3228
|
+
} else if ( tsfRegex.ltTest.test( data.iFilter ) ) {
|
3229
|
+
result = tsfRegex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
|
3220
3230
|
}
|
3221
3231
|
// keep showing all rows if nothing follows the operator
|
3222
3232
|
if ( !result && savedSearch === '' ) {
|
@@ -3228,13 +3238,13 @@
|
|
3228
3238
|
},
|
3229
3239
|
// Look for a not match
|
3230
3240
|
notMatch: function( c, data ) {
|
3231
|
-
if (
|
3241
|
+
if ( tsfRegex.notTest.test( data.iFilter ) ) {
|
3232
3242
|
var indx,
|
3233
3243
|
txt = data.iFilter.replace( '!', '' ),
|
3234
|
-
filter = tsf.parseFilter( c, txt, data
|
3235
|
-
if (
|
3244
|
+
filter = tsf.parseFilter( c, txt, data ) || '';
|
3245
|
+
if ( tsfRegex.exact.test( filter ) ) {
|
3236
3246
|
// look for exact not matches - see #628
|
3237
|
-
filter = filter.replace(
|
3247
|
+
filter = filter.replace( tsfRegex.exact, '' );
|
3238
3248
|
return filter === '' ? true : $.trim( filter ) !== data.iExact;
|
3239
3249
|
} else {
|
3240
3250
|
indx = data.iExact.search( $.trim( filter ) );
|
@@ -3246,29 +3256,29 @@
|
|
3246
3256
|
// Look for quotes or equals to get an exact match; ignore type since iExact could be numeric
|
3247
3257
|
exact: function( c, data ) {
|
3248
3258
|
/*jshint eqeqeq:false */
|
3249
|
-
if (
|
3250
|
-
var txt = data.iFilter.replace(
|
3251
|
-
filter = tsf.parseFilter( c, txt, data
|
3259
|
+
if ( tsfRegex.exact.test( data.iFilter ) ) {
|
3260
|
+
var txt = data.iFilter.replace( tsfRegex.exact, '' ),
|
3261
|
+
filter = tsf.parseFilter( c, txt, data ) || '';
|
3252
3262
|
return data.anyMatch ? $.inArray( filter, data.rowArray ) >= 0 : filter == data.iExact;
|
3253
3263
|
}
|
3254
3264
|
return null;
|
3255
3265
|
},
|
3256
3266
|
// Look for a range ( using ' to ' or ' - ' ) - see issue #166; thanks matzhu!
|
3257
3267
|
range : function( c, data ) {
|
3258
|
-
if (
|
3268
|
+
if ( tsfRegex.toTest.test( data.iFilter ) ) {
|
3259
3269
|
var result, tmp, range1, range2,
|
3260
3270
|
table = c.table,
|
3261
3271
|
index = data.index,
|
3262
3272
|
parsed = data.parsed[index],
|
3263
3273
|
// make sure the dash is for a range and not indicating a negative number
|
3264
|
-
query = data.iFilter.split(
|
3274
|
+
query = data.iFilter.split( tsfRegex.toSplit );
|
3265
3275
|
|
3266
3276
|
tmp = query[0].replace( ts.regex.nondigit, '' ) || '';
|
3267
|
-
range1 = ts.formatFloat( tsf.parseFilter( c, tmp,
|
3277
|
+
range1 = ts.formatFloat( tsf.parseFilter( c, tmp, data ), table );
|
3268
3278
|
tmp = query[1].replace( ts.regex.nondigit, '' ) || '';
|
3269
|
-
range2 = ts.formatFloat( tsf.parseFilter( c, tmp,
|
3279
|
+
range2 = ts.formatFloat( tsf.parseFilter( c, tmp, data ), table );
|
3270
3280
|
// parse filter value in case we're comparing numbers ( dates )
|
3271
|
-
if ( parsed || c.parsers[index].type === 'numeric' ) {
|
3281
|
+
if ( parsed || c.parsers[ index ].type === 'numeric' ) {
|
3272
3282
|
result = c.parsers[ index ].format( '' + query[0], table, c.$headers.eq( index ), index );
|
3273
3283
|
range1 = ( result !== '' && !isNaN( result ) ) ? result : range1;
|
3274
3284
|
result = c.parsers[ index ].format( '' + query[1], table, c.$headers.eq( index ), index );
|
@@ -3289,18 +3299,16 @@
|
|
3289
3299
|
},
|
3290
3300
|
// Look for wild card: ? = single, * = multiple, or | = logical OR
|
3291
3301
|
wild : function( c, data ) {
|
3292
|
-
if (
|
3293
|
-
var
|
3294
|
-
parsed = data.parsed[ index ],
|
3295
|
-
query = '' + ( tsf.parseFilter( c, data.iFilter, index, parsed ) || '' );
|
3302
|
+
if ( tsfRegex.wildOrTest.test( data.iFilter ) ) {
|
3303
|
+
var query = '' + ( tsf.parseFilter( c, data.iFilter, data ) || '' );
|
3296
3304
|
// look for an exact match with the 'or' unless the 'filter-match' class is found
|
3297
|
-
if ( !
|
3305
|
+
if ( !tsfRegex.wildTest.test( query ) && data.nestedFilters ) {
|
3298
3306
|
query = data.isMatch ? query : '^(' + query + ')$';
|
3299
3307
|
}
|
3300
3308
|
// parsing the filter may not work properly when using wildcards =/
|
3301
3309
|
try {
|
3302
3310
|
return new RegExp(
|
3303
|
-
query.replace(
|
3311
|
+
query.replace( tsfRegex.wild01, '\\S{1}' ).replace( tsfRegex.wild0More, '\\S*' ),
|
3304
3312
|
c.widgetOptions.filter_ignoreCase ? 'i' : ''
|
3305
3313
|
)
|
3306
3314
|
.test( data.exact );
|
@@ -3312,21 +3320,18 @@
|
|
3312
3320
|
},
|
3313
3321
|
// fuzzy text search; modified from https://github.com/mattyork/fuzzy ( MIT license )
|
3314
3322
|
fuzzy: function( c, data ) {
|
3315
|
-
if (
|
3323
|
+
if ( tsfRegex.fuzzyTest.test( data.iFilter ) ) {
|
3316
3324
|
var indx,
|
3317
3325
|
patternIndx = 0,
|
3318
3326
|
len = data.iExact.length,
|
3319
3327
|
txt = data.iFilter.slice( 1 ),
|
3320
|
-
pattern = tsf.parseFilter( c, txt, data
|
3328
|
+
pattern = tsf.parseFilter( c, txt, data ) || '';
|
3321
3329
|
for ( indx = 0; indx < len; indx++ ) {
|
3322
3330
|
if ( data.iExact[ indx ] === pattern[ patternIndx ] ) {
|
3323
3331
|
patternIndx += 1;
|
3324
3332
|
}
|
3325
3333
|
}
|
3326
|
-
|
3327
|
-
return true;
|
3328
|
-
}
|
3329
|
-
return false;
|
3334
|
+
return patternIndx === pattern.length;
|
3330
3335
|
}
|
3331
3336
|
return null;
|
3332
3337
|
}
|
@@ -3339,8 +3344,7 @@
|
|
3339
3344
|
and : 'and'
|
3340
3345
|
}, ts.language );
|
3341
3346
|
|
3342
|
-
var options, string, txt, $header, column, filters, val, fxn, noSelect
|
3343
|
-
regex = tsf.regex;
|
3347
|
+
var options, string, txt, $header, column, filters, val, fxn, noSelect;
|
3344
3348
|
c.$table.addClass( 'hasFilters' );
|
3345
3349
|
|
3346
3350
|
// define timers so using clearTimeout won't cause an undefined error
|
@@ -3351,8 +3355,8 @@
|
|
3351
3355
|
wo.filter_anyColumnSelector = '[data-column="all"],[data-column="any"]';
|
3352
3356
|
wo.filter_multipleColumnSelector = '[data-column*="-"],[data-column*=","]';
|
3353
3357
|
|
3354
|
-
val = '\\{' +
|
3355
|
-
$.extend(
|
3358
|
+
val = '\\{' + tsfRegex.query + '\\}';
|
3359
|
+
$.extend( tsfRegex, {
|
3356
3360
|
child : new RegExp( c.cssChildRow ),
|
3357
3361
|
filtered : new RegExp( wo.filter_filteredRow ),
|
3358
3362
|
alreadyFiltered : new RegExp( '(\\s+(' + ts.language.or + '|-|' + ts.language.to + ')\\s+)', 'i' ),
|
@@ -3630,8 +3634,10 @@
|
|
3630
3634
|
c.$table.data( 'lastSearch', filters );
|
3631
3635
|
return filters;
|
3632
3636
|
},
|
3633
|
-
parseFilter: function( c, filter,
|
3634
|
-
return parsed
|
3637
|
+
parseFilter: function( c, filter, data, parsed ) {
|
3638
|
+
return parsed || data.parsed[ data.index ] ?
|
3639
|
+
c.parsers[ data.index ].format( filter, c.table, [], data.index ) :
|
3640
|
+
filter;
|
3635
3641
|
},
|
3636
3642
|
buildRow: function( table, c, wo ) {
|
3637
3643
|
var $filter, col, column, $header, makeSelect, disabled, name, ffxn, tmp,
|
@@ -3824,8 +3830,12 @@
|
|
3824
3830
|
c.lastCombinedFilter = null;
|
3825
3831
|
c.lastSearch = [];
|
3826
3832
|
}
|
3827
|
-
// convert filters to strings
|
3828
|
-
filters =
|
3833
|
+
// convert filters to strings - see #1070
|
3834
|
+
filters = Array.prototype.map ?
|
3835
|
+
filters.map( String ) :
|
3836
|
+
// for IE8 & older browsers - maybe not the best method
|
3837
|
+
filters.join( '\u0000' ).split( '\u0000' );
|
3838
|
+
|
3829
3839
|
if ( wo.filter_initialized ) {
|
3830
3840
|
c.$table.trigger( 'filterStart', [ filters ] );
|
3831
3841
|
}
|
@@ -3879,8 +3889,8 @@
|
|
3879
3889
|
},
|
3880
3890
|
defaultFilter: function( filter, mask ) {
|
3881
3891
|
if ( filter === '' ) { return filter; }
|
3882
|
-
var regex =
|
3883
|
-
maskLen = mask.match(
|
3892
|
+
var regex = tsfRegex.iQuery,
|
3893
|
+
maskLen = mask.match( tsfRegex.igQuery ).length,
|
3884
3894
|
query = maskLen > 1 ? $.trim( filter ).split( /\s/ ) : [ $.trim( filter ) ],
|
3885
3895
|
len = query.length - 1,
|
3886
3896
|
indx = 0,
|
@@ -3977,9 +3987,8 @@
|
|
3977
3987
|
return filterMatched;
|
3978
3988
|
},
|
3979
3989
|
processRow: function( c, data, vars ) {
|
3980
|
-
var
|
3990
|
+
var result, filterMatched,
|
3981
3991
|
fxn, ffxn, txt,
|
3982
|
-
regex = tsf.regex,
|
3983
3992
|
wo = c.widgetOptions,
|
3984
3993
|
showRow = true,
|
3985
3994
|
|
@@ -4058,7 +4067,7 @@
|
|
4058
4067
|
result = data.rawArray[ columnIndex ] || '';
|
4059
4068
|
data.exact = c.sortLocaleCompare ? ts.replaceAccents( result ) : result; // issue #405
|
4060
4069
|
}
|
4061
|
-
data.iExact = !
|
4070
|
+
data.iExact = !tsfRegex.type.test( typeof data.exact ) && wo.filter_ignoreCase ?
|
4062
4071
|
data.exact.toLowerCase() : data.exact;
|
4063
4072
|
|
4064
4073
|
data.isMatch = c.$headerIndexed[ data.index ].hasClass( 'filter-match' );
|
@@ -4076,21 +4085,13 @@
|
|
4076
4085
|
data.filter = ts.replaceAccents( data.filter );
|
4077
4086
|
}
|
4078
4087
|
|
4079
|
-
val = true;
|
4080
|
-
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultColFilter[ columnIndex ] ) ) {
|
4081
|
-
data.filter = tsf.defaultFilter( data.filter, vars.defaultColFilter[ columnIndex ] );
|
4082
|
-
// val is used to indicate that a filter select is using a default filter;
|
4083
|
-
// so we override the exact & partial matches
|
4084
|
-
val = false;
|
4085
|
-
}
|
4086
4088
|
// data.iFilter = case insensitive ( if wo.filter_ignoreCase is true ),
|
4087
4089
|
// data.filter = case sensitive
|
4088
4090
|
data.iFilter = wo.filter_ignoreCase ? ( data.filter || '' ).toLowerCase() : data.filter;
|
4089
4091
|
fxn = vars.functions[ columnIndex ];
|
4090
|
-
hasSelect = c.$headerIndexed[ columnIndex ].hasClass( 'filter-select' );
|
4091
4092
|
filterMatched = null;
|
4092
|
-
if ( fxn
|
4093
|
-
if ( fxn === true
|
4093
|
+
if ( fxn ) {
|
4094
|
+
if ( fxn === true ) {
|
4094
4095
|
// default selector uses exact match unless 'filter-match' class is found
|
4095
4096
|
filterMatched = data.isMatch ?
|
4096
4097
|
// data.iExact may be a number
|
@@ -4116,7 +4117,7 @@
|
|
4116
4117
|
// Look for match, and add child row data for matching
|
4117
4118
|
} else {
|
4118
4119
|
txt = ( data.iExact + data.childRowText )
|
4119
|
-
.indexOf( tsf.parseFilter( c, data.iFilter,
|
4120
|
+
.indexOf( tsf.parseFilter( c, data.iFilter, data ) );
|
4120
4121
|
result = ( ( !wo.filter_startsWith && txt >= 0 ) || ( wo.filter_startsWith && txt === 0 ) );
|
4121
4122
|
}
|
4122
4123
|
} else {
|
@@ -4136,7 +4137,6 @@
|
|
4136
4137
|
isChild, childRow, lastSearch, showRow, showParent, time, val, indx,
|
4137
4138
|
notFiltered, searchFiltered, query, injected, res, id, txt,
|
4138
4139
|
storedFilters = $.extend( [], filters ),
|
4139
|
-
regex = tsf.regex,
|
4140
4140
|
c = table.config,
|
4141
4141
|
wo = c.widgetOptions,
|
4142
4142
|
// data object passed to filters; anyMatch is a flag for the filters
|
@@ -4218,7 +4218,7 @@
|
|
4218
4218
|
);
|
4219
4219
|
if ( wo.filter_columnAnyMatch ) {
|
4220
4220
|
// specific columns search
|
4221
|
-
query = data.anyMatchFilter.split(
|
4221
|
+
query = data.anyMatchFilter.split( tsfRegex.andSplit );
|
4222
4222
|
injected = false;
|
4223
4223
|
for ( indx = 0; indx < query.length; indx++ ) {
|
4224
4224
|
res = query[ indx ].split( ':' );
|
@@ -4253,12 +4253,12 @@
|
|
4253
4253
|
// there are no changes from beginning of filter
|
4254
4254
|
val.indexOf( lastSearch[indx] || '' ) === 0 &&
|
4255
4255
|
// if there is NOT a logical 'or', or range ( 'to' or '-' ) in the string
|
4256
|
-
!
|
4256
|
+
!tsfRegex.alreadyFiltered.test( val ) &&
|
4257
4257
|
// if we are not doing exact matches, using '|' ( logical or ) or not '!'
|
4258
|
-
!
|
4258
|
+
!tsfRegex.exactTest.test( val ) &&
|
4259
4259
|
// don't search only filtered if the value is negative
|
4260
4260
|
// ( '> -10' => '> -100' will ignore hidden rows )
|
4261
|
-
!(
|
4261
|
+
!( tsfRegex.isNeg1.test( val ) || tsfRegex.isNeg2.test( val ) ) &&
|
4262
4262
|
// if filtering using a select without a 'filter-match' class ( exact match ) - fixes #593
|
4263
4263
|
!( val !== '' && c.$filters && c.$filters.filter( '[data-column="' + indx + '"]' ).find( 'select' ).length &&
|
4264
4264
|
!c.$headerIndexed[indx].hasClass( 'filter-match' ) );
|
@@ -4276,7 +4276,7 @@
|
|
4276
4276
|
// replace accents
|
4277
4277
|
data.anyMatchFilter = ts.replaceAccents( data.anyMatchFilter );
|
4278
4278
|
}
|
4279
|
-
if ( wo.filter_defaultFilter &&
|
4279
|
+
if ( wo.filter_defaultFilter && tsfRegex.iQuery.test( vars.defaultAnyFilter ) ) {
|
4280
4280
|
data.anyMatchFilter = tsf.defaultFilter( data.anyMatchFilter, vars.defaultAnyFilter );
|
4281
4281
|
// clear search filtered flag because default filters are not saved to the last search
|
4282
4282
|
searchFiltered = false;
|
@@ -4293,9 +4293,9 @@
|
|
4293
4293
|
|
4294
4294
|
txt = $rows[ rowIndex ].className;
|
4295
4295
|
// the first row can never be a child row
|
4296
|
-
isChild = rowIndex &&
|
4296
|
+
isChild = rowIndex && tsfRegex.child.test( txt );
|
4297
4297
|
// skip child rows & already filtered rows
|
4298
|
-
if ( isChild || ( searchFiltered &&
|
4298
|
+
if ( isChild || ( searchFiltered && tsfRegex.filtered.test( txt ) ) ) {
|
4299
4299
|
continue;
|
4300
4300
|
}
|
4301
4301
|
|
@@ -4405,7 +4405,6 @@
|
|
4405
4405
|
// custom select source function for a SPECIFIC COLUMN
|
4406
4406
|
arry = fxn( table, column, onlyAvail );
|
4407
4407
|
}
|
4408
|
-
|
4409
4408
|
if ( arry === false ) {
|
4410
4409
|
// fall back to original method
|
4411
4410
|
arry = tsf.getOptions( table, column, onlyAvail );
|
@@ -4419,18 +4418,19 @@
|
|
4419
4418
|
return false;
|
4420
4419
|
}
|
4421
4420
|
table = $( table )[0];
|
4422
|
-
var cts, txt, indx, len,
|
4421
|
+
var cts, txt, indx, len, parsedTxt, str,
|
4423
4422
|
c = table.config,
|
4424
4423
|
validColumn = typeof column !== 'undefined' && column !== null && column >= 0 && column < c.columns,
|
4425
4424
|
parsed = [];
|
4426
|
-
|
4427
4425
|
// get unique elements and sort the list
|
4428
4426
|
// if $.tablesorter.sortText exists ( not in the original tablesorter ),
|
4429
4427
|
// then natural sort the list otherwise use a basic sort
|
4430
4428
|
arry = $.grep( arry, function( value, indx ) {
|
4429
|
+
if ( value.text ) {
|
4430
|
+
return true;
|
4431
|
+
}
|
4431
4432
|
return $.inArray( value, arry ) === indx;
|
4432
4433
|
});
|
4433
|
-
|
4434
4434
|
if ( validColumn && c.$headerIndexed[ column ].hasClass( 'filter-select-nosort' ) ) {
|
4435
4435
|
// unsorted select options
|
4436
4436
|
return arry;
|
@@ -4439,22 +4439,30 @@
|
|
4439
4439
|
// parse select option values
|
4440
4440
|
for ( indx = 0; indx < len; indx++ ) {
|
4441
4441
|
txt = arry[ indx ];
|
4442
|
+
// check for object
|
4443
|
+
str = txt.text ? txt.text : txt;
|
4444
|
+
// sortNatural breaks if you don't pass it strings
|
4445
|
+
parsedTxt = ( validColumn && c.parsers && c.parsers.length &&
|
4446
|
+
c.parsers[ column ].format( str, table, [], column ) || str ).toString();
|
4447
|
+
parsedTxt = c.widgetOptions.filter_ignoreCase ? parsedTxt.toLowerCase() : parsedTxt;
|
4442
4448
|
// parse array data using set column parser; this DOES NOT pass the original
|
4443
4449
|
// table cell to the parser format function
|
4444
|
-
|
4445
|
-
|
4446
|
-
|
4447
|
-
|
4448
|
-
|
4449
|
-
|
4450
|
+
if ( txt.text ) {
|
4451
|
+
txt.parsed = parsedTxt;
|
4452
|
+
parsed.push( txt );
|
4453
|
+
} else {
|
4454
|
+
parsed.push({
|
4455
|
+
text : txt,
|
4456
|
+
// check parser length - fixes #934
|
4457
|
+
parsed : parsedTxt
|
4458
|
+
});
|
4459
|
+
}
|
4450
4460
|
}
|
4451
|
-
|
4452
4461
|
// sort parsed select options
|
4453
4462
|
cts = c.textSorter || '';
|
4454
4463
|
parsed.sort( function( a, b ) {
|
4455
|
-
|
4456
|
-
|
4457
|
-
y = b.p.toString();
|
4464
|
+
var x = a.parsed,
|
4465
|
+
y = b.parsed;
|
4458
4466
|
if ( validColumn && typeof cts === 'function' ) {
|
4459
4467
|
// custom OVERALL text sorter
|
4460
4468
|
return cts( x, y, true, column, table );
|
@@ -4472,7 +4480,7 @@
|
|
4472
4480
|
arry = [];
|
4473
4481
|
len = parsed.length;
|
4474
4482
|
for ( indx = 0; indx < len; indx++ ) {
|
4475
|
-
arry.push( parsed[indx]
|
4483
|
+
arry.push( parsed[indx] );
|
4476
4484
|
}
|
4477
4485
|
return arry;
|
4478
4486
|
}
|
@@ -4532,7 +4540,7 @@
|
|
4532
4540
|
return;
|
4533
4541
|
}
|
4534
4542
|
|
4535
|
-
var indx, val, txt, t, $filters, $filter,
|
4543
|
+
var indx, val, txt, t, $filters, $filter, option,
|
4536
4544
|
c = table.config,
|
4537
4545
|
wo = c.widgetOptions,
|
4538
4546
|
node = c.$headerIndexed[ column ],
|
@@ -4557,23 +4565,45 @@
|
|
4557
4565
|
if ( $.isArray( arry ) ) {
|
4558
4566
|
// build option list
|
4559
4567
|
for ( indx = 0; indx < arry.length; indx++ ) {
|
4560
|
-
|
4561
|
-
|
4562
|
-
|
4563
|
-
|
4564
|
-
|
4565
|
-
|
4566
|
-
|
4567
|
-
|
4568
|
-
|
4568
|
+
option = arry[ indx ];
|
4569
|
+
if ( option.text ) {
|
4570
|
+
// OBJECT!! add data-function-name in case the value is set in filter_functions
|
4571
|
+
option['data-function-name'] = typeof option.value === 'undefined' ? option.text : option.value;
|
4572
|
+
|
4573
|
+
// support jQuery < v1.8, otherwise the below code could be shortened to
|
4574
|
+
// options += $( '<option>', option )[ 0 ].outerHTML;
|
4575
|
+
options += '<option';
|
4576
|
+
for ( val in option ) {
|
4577
|
+
if ( option.hasOwnProperty( val ) && val !== 'text' ) {
|
4578
|
+
options += ' ' + val + '="' + option[ val ] + '"';
|
4579
|
+
}
|
4580
|
+
}
|
4581
|
+
if ( !option.value ) {
|
4582
|
+
options += ' value="' + option.text + '"';
|
4583
|
+
}
|
4584
|
+
options += '>' + option.text + '</option>';
|
4585
|
+
// above code is needed in jQuery < v1.8
|
4586
|
+
|
4587
|
+
// make sure we don't turn an object into a string (objects without a "text" property)
|
4588
|
+
} else if ( '' + option !== '[object Object]' ) {
|
4589
|
+
txt = option = ( '' + option ).replace( tsfRegex.quote, '"' );
|
4590
|
+
val = txt;
|
4591
|
+
// allow including a symbol in the selectSource array
|
4592
|
+
// 'a-z|A through Z' so that 'a-z' becomes the option value
|
4593
|
+
// and 'A through Z' becomes the option text
|
4594
|
+
if ( txt.indexOf( wo.filter_selectSourceSeparator ) >= 0 ) {
|
4595
|
+
t = txt.split( wo.filter_selectSourceSeparator );
|
4596
|
+
val = t[0];
|
4597
|
+
txt = t[1];
|
4598
|
+
}
|
4599
|
+
// replace quotes - fixes #242 & ignore empty strings
|
4600
|
+
// see http://stackoverflow.com/q/14990971/145346
|
4601
|
+
options += option !== '' ?
|
4602
|
+
'<option ' +
|
4603
|
+
( val === txt ? '' : 'data-function-name="' + option + '" ' ) +
|
4604
|
+
'value="' + val + '">' + txt +
|
4605
|
+
'</option>' : '';
|
4569
4606
|
}
|
4570
|
-
// replace quotes - fixes #242 & ignore empty strings
|
4571
|
-
// see http://stackoverflow.com/q/14990971/145346
|
4572
|
-
options += arry[indx] !== '' ?
|
4573
|
-
'<option ' +
|
4574
|
-
( val === txt ? '' : 'data-function-name="' + arry[indx] + '" ' ) +
|
4575
|
-
'value="' + val + '">' + txt +
|
4576
|
-
'</option>' : '';
|
4577
4607
|
}
|
4578
4608
|
// clear arry so it doesn't get appended twice
|
4579
4609
|
arry = [];
|
@@ -4619,6 +4649,9 @@
|
|
4619
4649
|
}
|
4620
4650
|
};
|
4621
4651
|
|
4652
|
+
// filter regex variable
|
4653
|
+
tsfRegex = tsf.regex;
|
4654
|
+
|
4622
4655
|
ts.getFilters = function( table, getRaw, setFilters, skipFirst ) {
|
4623
4656
|
var i, $filters, $column, cols,
|
4624
4657
|
filters = false,
|