jquery-tablesorter 1.18.1 → 1.18.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 +3 -4
- data/lib/jquery-tablesorter/version.rb +1 -1
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.combined.js +218 -155
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.js +79 -43
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets.js +139 -112
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-columnSelector.js +6 -4
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter.js +138 -111
- metadata +2 -2
@@ -1,4 +1,4 @@
|
|
1
|
-
/* Widget: columnSelector (responsive table widget) - updated 8/
|
1
|
+
/* Widget: columnSelector (responsive table widget) - updated 8/23/2015 (v2.23.2) *//*
|
2
2
|
* Requires tablesorter v2.8+ and jQuery 1.7+
|
3
3
|
* by Justin Hallett & Rob Garrison
|
4
4
|
*/
|
@@ -224,7 +224,7 @@
|
|
224
224
|
}
|
225
225
|
// trigger columnUpdate if auto is true (it gets skipped in updateCols()
|
226
226
|
if (colSel.auto) {
|
227
|
-
c.$table.trigger(
|
227
|
+
c.$table.trigger(wo.columnSelector_updated);
|
228
228
|
}
|
229
229
|
},
|
230
230
|
|
@@ -299,7 +299,7 @@
|
|
299
299
|
if (wo.columnSelector_saveColumns && ts.storage) {
|
300
300
|
ts.storage( c.$table[0], 'tablesorter-columnSelector', colSel.states );
|
301
301
|
}
|
302
|
-
c.$table.trigger(
|
302
|
+
c.$table.trigger(wo.columnSelector_updated);
|
303
303
|
},
|
304
304
|
|
305
305
|
attachTo : function(table, elm) {
|
@@ -370,7 +370,9 @@
|
|
370
370
|
columnSelector_priority : 'data-priority',
|
371
371
|
// class name added to checked checkboxes - this fixes an issue with Chrome not updating FontAwesome
|
372
372
|
// applied icons; use this class name (input.checked) instead of input:checked
|
373
|
-
columnSelector_cssChecked : 'checked'
|
373
|
+
columnSelector_cssChecked : 'checked',
|
374
|
+
// event triggered when columnSelector completes
|
375
|
+
columnSelector_updated : 'columnUpdate'
|
374
376
|
|
375
377
|
},
|
376
378
|
init: function(table, thisWidget, c, wo) {
|
@@ -1,11 +1,12 @@
|
|
1
|
-
/*! Widget: filter - updated 8/
|
1
|
+
/*! Widget: filter - updated 8/23/2015 (v2.23.2) *//*
|
2
2
|
* Requires tablesorter v2.8+ and jQuery 1.7+
|
3
3
|
* by Rob Garrison
|
4
4
|
*/
|
5
5
|
;( function ( $ ) {
|
6
6
|
'use strict';
|
7
|
-
var
|
8
|
-
|
7
|
+
var tsf,
|
8
|
+
ts = $.tablesorter || {},
|
9
|
+
tscss = ts.css;
|
9
10
|
|
10
11
|
$.extend( tscss, {
|
11
12
|
filterRow : 'tablesorter-filter-row',
|
@@ -49,7 +50,7 @@
|
|
49
50
|
},
|
50
51
|
format: function( table, c, wo ) {
|
51
52
|
if ( !c.$table.hasClass( 'hasFilters' ) ) {
|
52
|
-
|
53
|
+
tsf.init( table, c, wo );
|
53
54
|
}
|
54
55
|
},
|
55
56
|
remove: function( table, c, wo, refreshing ) {
|
@@ -61,7 +62,7 @@
|
|
61
62
|
$table
|
62
63
|
.removeClass( 'hasFilters' )
|
63
64
|
// add .tsfilter namespace to all BUT search
|
64
|
-
.unbind( events.replace(
|
65
|
+
.unbind( events.replace( ts.regex.spaces, ' ' ) )
|
65
66
|
// remove the filter row even if refreshing, because the column might have been moved
|
66
67
|
.find( '.' + tscss.filterRow ).remove();
|
67
68
|
if ( refreshing ) { return; }
|
@@ -76,7 +77,7 @@
|
|
76
77
|
}
|
77
78
|
});
|
78
79
|
|
79
|
-
ts.filter = {
|
80
|
+
tsf = ts.filter = {
|
80
81
|
|
81
82
|
// regex used in filter 'check' functions - not for general use and not documented
|
82
83
|
regex: {
|
@@ -85,9 +86,13 @@
|
|
85
86
|
filtered : /filtered/, // filtered (hidden) row class name; updated in the script
|
86
87
|
type : /undefined|number/, // check type
|
87
88
|
exact : /(^[\"\'=]+)|([\"\'=]+$)/g, // exact match (allow '==')
|
88
|
-
nondigit : /[^\w,. \-()]/g, // replace non-digits (from digit & currency parser)
|
89
89
|
operators : /[<>=]/g, // replace operators
|
90
|
-
query : '(q|query)' // replace filter queries
|
90
|
+
query : '(q|query)', // replace filter queries
|
91
|
+
wild01 : /\?/g, // wild card match 0 or 1
|
92
|
+
wild0More : /\*/g, // wild care match 0 or more
|
93
|
+
quote : /\"/g,
|
94
|
+
isNeg1 : /(>=?\s*-\d)/,
|
95
|
+
isNeg2 : /(<=?\s*\d)/
|
91
96
|
},
|
92
97
|
// function( c, data ) { }
|
93
98
|
// c = table.config
|
@@ -104,27 +109,27 @@
|
|
104
109
|
// data.parsed = array ( by column ) of boolean values ( from filter_useParsedData or 'filter-parsed' class )
|
105
110
|
types: {
|
106
111
|
or : function( c, data, vars ) {
|
107
|
-
if (
|
112
|
+
if ( tsf.regex.orTest.test( data.iFilter ) || tsf.regex.orSplit.test( data.filter ) ) {
|
108
113
|
var indx, filterMatched, query, regex,
|
109
114
|
// duplicate data but split filter
|
110
115
|
data2 = $.extend( {}, data ),
|
111
116
|
index = data.index,
|
112
117
|
parsed = data.parsed[ index ],
|
113
|
-
filter = data.filter.split(
|
114
|
-
iFilter = data.iFilter.split(
|
118
|
+
filter = data.filter.split( tsf.regex.orSplit ),
|
119
|
+
iFilter = data.iFilter.split( tsf.regex.orSplit ),
|
115
120
|
len = filter.length;
|
116
121
|
for ( indx = 0; indx < len; indx++ ) {
|
117
122
|
data2.nestedFilters = true;
|
118
|
-
data2.filter = '' + (
|
119
|
-
data2.iFilter = '' + (
|
120
|
-
query = '(' + (
|
123
|
+
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' );
|
124
|
+
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
|
125
|
+
query = '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')';
|
121
126
|
try {
|
122
127
|
// use try/catch, because query may not be a valid regex if "|" is contained within a partial regex search,
|
123
128
|
// e.g "/(Alex|Aar" -> Uncaught SyntaxError: Invalid regular expression: /(/(Alex)/: Unterminated group
|
124
129
|
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
|
125
130
|
// filterMatched = data2.filter === '' && indx > 0 ? true
|
126
131
|
// look for an exact match with the 'or' unless the 'filter-match' class is found
|
127
|
-
filterMatched = regex.test( data2.exact ) ||
|
132
|
+
filterMatched = regex.test( data2.exact ) || tsf.processTypes( c, data2, vars );
|
128
133
|
if ( filterMatched ) {
|
129
134
|
return filterMatched;
|
130
135
|
}
|
@@ -139,27 +144,27 @@
|
|
139
144
|
},
|
140
145
|
// Look for an AND or && operator ( logical and )
|
141
146
|
and : function( c, data, vars ) {
|
142
|
-
if (
|
147
|
+
if ( tsf.regex.andTest.test( data.filter ) ) {
|
143
148
|
var indx, filterMatched, result, query, regex,
|
144
149
|
// duplicate data but split filter
|
145
150
|
data2 = $.extend( {}, data ),
|
146
151
|
index = data.index,
|
147
152
|
parsed = data.parsed[ index ],
|
148
|
-
filter = data.filter.split(
|
149
|
-
iFilter = data.iFilter.split(
|
153
|
+
filter = data.filter.split( tsf.regex.andSplit ),
|
154
|
+
iFilter = data.iFilter.split( tsf.regex.andSplit ),
|
150
155
|
len = filter.length;
|
151
156
|
for ( indx = 0; indx < len; indx++ ) {
|
152
157
|
data2.nestedFilters = true;
|
153
|
-
data2.filter = '' + (
|
154
|
-
data2.iFilter = '' + (
|
155
|
-
query = ( '(' + (
|
158
|
+
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' );
|
159
|
+
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
|
160
|
+
query = ( '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')' )
|
156
161
|
// replace wild cards since /(a*)/i will match anything
|
157
|
-
.replace(
|
162
|
+
.replace( tsf.regex.wild01, '\\S{1}' ).replace( tsf.regex.wild0More, '\\S*' );
|
158
163
|
try {
|
159
164
|
// use try/catch just in case RegExp is invalid
|
160
165
|
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
|
161
166
|
// look for an exact match with the 'and' unless the 'filter-match' class is found
|
162
|
-
result = ( regex.test( data2.exact ) ||
|
167
|
+
result = ( regex.test( data2.exact ) || tsf.processTypes( c, data2, vars ) );
|
163
168
|
if ( indx === 0 ) {
|
164
169
|
filterMatched = result;
|
165
170
|
} else {
|
@@ -176,10 +181,10 @@
|
|
176
181
|
},
|
177
182
|
// Look for regex
|
178
183
|
regex: function( c, data ) {
|
179
|
-
if (
|
184
|
+
if ( tsf.regex.regex.test( data.filter ) ) {
|
180
185
|
var matches,
|
181
186
|
// cache regex per column for optimal speed
|
182
|
-
regex = data.filter_regexCache[ data.index ] ||
|
187
|
+
regex = data.filter_regexCache[ data.index ] || tsf.regex.regex.exec( data.filter ),
|
183
188
|
isRegex = regex instanceof RegExp;
|
184
189
|
try {
|
185
190
|
if ( !isRegex ) {
|
@@ -198,18 +203,18 @@
|
|
198
203
|
// Look for operators >, >=, < or <=
|
199
204
|
operators: function( c, data ) {
|
200
205
|
// ignore empty strings... because '' < 10 is true
|
201
|
-
if (
|
206
|
+
if ( tsf.regex.operTest.test( data.iFilter ) && data.iExact !== '' ) {
|
202
207
|
var cachedValue, result, txt,
|
203
208
|
table = c.table,
|
204
209
|
index = data.index,
|
205
210
|
parsed = data.parsed[index],
|
206
|
-
query = ts.formatFloat( data.iFilter.replace(
|
211
|
+
query = ts.formatFloat( data.iFilter.replace( tsf.regex.operators, '' ), table ),
|
207
212
|
parser = c.parsers[index],
|
208
213
|
savedSearch = query;
|
209
214
|
// parse filter value in case we're comparing numbers ( dates )
|
210
215
|
if ( parsed || parser.type === 'numeric' ) {
|
211
|
-
txt = $.trim( '' + data.iFilter.replace(
|
212
|
-
result =
|
216
|
+
txt = $.trim( '' + data.iFilter.replace( tsf.regex.operators, '' ) );
|
217
|
+
result = tsf.parseFilter( c, txt, index, true );
|
213
218
|
query = ( typeof result === 'number' && result !== '' && !isNaN( result ) ) ? result : query;
|
214
219
|
}
|
215
220
|
// iExact may be numeric - see issue #149;
|
@@ -218,13 +223,13 @@
|
|
218
223
|
typeof data.cache !== 'undefined' ) {
|
219
224
|
cachedValue = data.cache;
|
220
225
|
} else {
|
221
|
-
txt = isNaN( data.iExact ) ? data.iExact.replace( ts.
|
226
|
+
txt = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
|
222
227
|
cachedValue = ts.formatFloat( txt, table );
|
223
228
|
}
|
224
|
-
if (
|
225
|
-
result =
|
226
|
-
} else if (
|
227
|
-
result =
|
229
|
+
if ( tsf.regex.gtTest.test( data.iFilter ) ) {
|
230
|
+
result = tsf.regex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
|
231
|
+
} else if ( tsf.regex.ltTest.test( data.iFilter ) ) {
|
232
|
+
result = tsf.regex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
|
228
233
|
}
|
229
234
|
// keep showing all rows if nothing follows the operator
|
230
235
|
if ( !result && savedSearch === '' ) {
|
@@ -236,13 +241,13 @@
|
|
236
241
|
},
|
237
242
|
// Look for a not match
|
238
243
|
notMatch: function( c, data ) {
|
239
|
-
if (
|
244
|
+
if ( tsf.regex.notTest.test( data.iFilter ) ) {
|
240
245
|
var indx,
|
241
246
|
txt = data.iFilter.replace( '!', '' ),
|
242
|
-
filter =
|
243
|
-
if (
|
247
|
+
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
248
|
+
if ( tsf.regex.exact.test( filter ) ) {
|
244
249
|
// look for exact not matches - see #628
|
245
|
-
filter = filter.replace(
|
250
|
+
filter = filter.replace( tsf.regex.exact, '' );
|
246
251
|
return filter === '' ? true : $.trim( filter ) !== data.iExact;
|
247
252
|
} else {
|
248
253
|
indx = data.iExact.search( $.trim( filter ) );
|
@@ -254,27 +259,27 @@
|
|
254
259
|
// Look for quotes or equals to get an exact match; ignore type since iExact could be numeric
|
255
260
|
exact: function( c, data ) {
|
256
261
|
/*jshint eqeqeq:false */
|
257
|
-
if (
|
258
|
-
var txt = data.iFilter.replace(
|
259
|
-
filter =
|
262
|
+
if ( tsf.regex.exact.test( data.iFilter ) ) {
|
263
|
+
var txt = data.iFilter.replace( tsf.regex.exact, '' ),
|
264
|
+
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
260
265
|
return data.anyMatch ? $.inArray( filter, data.rowArray ) >= 0 : filter == data.iExact;
|
261
266
|
}
|
262
267
|
return null;
|
263
268
|
},
|
264
269
|
// Look for a range ( using ' to ' or ' - ' ) - see issue #166; thanks matzhu!
|
265
270
|
range : function( c, data ) {
|
266
|
-
if (
|
271
|
+
if ( tsf.regex.toTest.test( data.iFilter ) ) {
|
267
272
|
var result, tmp, range1, range2,
|
268
273
|
table = c.table,
|
269
274
|
index = data.index,
|
270
275
|
parsed = data.parsed[index],
|
271
276
|
// make sure the dash is for a range and not indicating a negative number
|
272
|
-
query = data.iFilter.split(
|
277
|
+
query = data.iFilter.split( tsf.regex.toSplit );
|
273
278
|
|
274
|
-
tmp = query[0].replace( ts.
|
275
|
-
range1 = ts.formatFloat(
|
276
|
-
tmp = query[1].replace( ts.
|
277
|
-
range2 = ts.formatFloat(
|
279
|
+
tmp = query[0].replace( ts.regex.nondigit, '' ) || '';
|
280
|
+
range1 = ts.formatFloat( tsf.parseFilter( c, tmp, index, parsed ), table );
|
281
|
+
tmp = query[1].replace( ts.regex.nondigit, '' ) || '';
|
282
|
+
range2 = ts.formatFloat( tsf.parseFilter( c, tmp, index, parsed ), table );
|
278
283
|
// parse filter value in case we're comparing numbers ( dates )
|
279
284
|
if ( parsed || c.parsers[index].type === 'numeric' ) {
|
280
285
|
result = c.parsers[ index ].format( '' + query[0], table, c.$headers.eq( index ), index );
|
@@ -285,7 +290,7 @@
|
|
285
290
|
if ( ( parsed || c.parsers[ index ].type === 'numeric' ) && !isNaN( range1 ) && !isNaN( range2 ) ) {
|
286
291
|
result = data.cache;
|
287
292
|
} else {
|
288
|
-
tmp = isNaN( data.iExact ) ? data.iExact.replace( ts.
|
293
|
+
tmp = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
|
289
294
|
result = ts.formatFloat( tmp, table );
|
290
295
|
}
|
291
296
|
if ( range1 > range2 ) {
|
@@ -297,18 +302,18 @@
|
|
297
302
|
},
|
298
303
|
// Look for wild card: ? = single, * = multiple, or | = logical OR
|
299
304
|
wild : function( c, data ) {
|
300
|
-
if (
|
305
|
+
if ( tsf.regex.wildOrTest.test( data.iFilter ) ) {
|
301
306
|
var index = data.index,
|
302
307
|
parsed = data.parsed[ index ],
|
303
|
-
query = '' + (
|
308
|
+
query = '' + ( tsf.parseFilter( c, data.iFilter, index, parsed ) || '' );
|
304
309
|
// look for an exact match with the 'or' unless the 'filter-match' class is found
|
305
|
-
if (
|
310
|
+
if ( !tsf.regex.wildTest.test( query ) && data.nestedFilters ) {
|
306
311
|
query = data.isMatch ? query : '^(' + query + ')$';
|
307
312
|
}
|
308
313
|
// parsing the filter may not work properly when using wildcards =/
|
309
314
|
try {
|
310
315
|
return new RegExp(
|
311
|
-
query.replace(
|
316
|
+
query.replace( tsf.regex.wild01, '\\S{1}' ).replace( tsf.regex.wild0More, '\\S*' ),
|
312
317
|
c.widgetOptions.filter_ignoreCase ? 'i' : ''
|
313
318
|
)
|
314
319
|
.test( data.exact );
|
@@ -320,12 +325,12 @@
|
|
320
325
|
},
|
321
326
|
// fuzzy text search; modified from https://github.com/mattyork/fuzzy ( MIT license )
|
322
327
|
fuzzy: function( c, data ) {
|
323
|
-
if (
|
328
|
+
if ( tsf.regex.fuzzyTest.test( data.iFilter ) ) {
|
324
329
|
var indx,
|
325
330
|
patternIndx = 0,
|
326
331
|
len = data.iExact.length,
|
327
332
|
txt = data.iFilter.slice( 1 ),
|
328
|
-
pattern =
|
333
|
+
pattern = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
329
334
|
for ( indx = 0; indx < len; indx++ ) {
|
330
335
|
if ( data.iExact[ indx ] === pattern[ patternIndx ] ) {
|
331
336
|
patternIndx += 1;
|
@@ -348,7 +353,7 @@
|
|
348
353
|
}, ts.language );
|
349
354
|
|
350
355
|
var options, string, txt, $header, column, filters, val, fxn, noSelect,
|
351
|
-
regex =
|
356
|
+
regex = tsf.regex;
|
352
357
|
c.$table.addClass( 'hasFilters' );
|
353
358
|
|
354
359
|
// define timers so using clearTimeout won't cause an undefined error
|
@@ -359,7 +364,7 @@
|
|
359
364
|
wo.filter_anyColumnSelector = '[data-column="all"],[data-column="any"]';
|
360
365
|
wo.filter_multipleColumnSelector = '[data-column*="-"],[data-column*=","]';
|
361
366
|
|
362
|
-
val = '\\{' +
|
367
|
+
val = '\\{' + tsf.regex.query + '\\}';
|
363
368
|
$.extend( regex, {
|
364
369
|
child : new RegExp( c.cssChildRow ),
|
365
370
|
filtered : new RegExp( wo.filter_filteredRow ),
|
@@ -368,9 +373,20 @@
|
|
368
373
|
toSplit : new RegExp( '(?:\\s+(?:-|' + ts.language.to + ')\\s+)', 'gi' ),
|
369
374
|
andTest : new RegExp( '\\s+(' + ts.language.and + '|&&)\\s+', 'i' ),
|
370
375
|
andSplit : new RegExp( '(?:\\s+(?:' + ts.language.and + '|&&)\\s+)', 'gi' ),
|
376
|
+
orTest : /\|/,
|
371
377
|
orSplit : new RegExp( '(?:\\s+(?:' + ts.language.or + ')\\s+|\\|)', 'gi' ),
|
372
378
|
iQuery : new RegExp( val, 'i' ),
|
373
|
-
igQuery : new RegExp( val, 'ig' )
|
379
|
+
igQuery : new RegExp( val, 'ig' ),
|
380
|
+
operTest : /^[<>]=?/,
|
381
|
+
gtTest : />/,
|
382
|
+
gteTest : />=/,
|
383
|
+
ltTest : /</,
|
384
|
+
lteTest : /<=/,
|
385
|
+
notTest : /^\!/,
|
386
|
+
wildOrTest : /[\?\*\|]/,
|
387
|
+
wildTest : /\?\*/,
|
388
|
+
fuzzyTest : /^~/,
|
389
|
+
exactTest : /[=\"\|!]/
|
374
390
|
});
|
375
391
|
|
376
392
|
// don't build filter row if columnFilters is false or all columns are set to 'filter-false'
|
@@ -378,7 +394,7 @@
|
|
378
394
|
val = c.$headers.filter( '.filter-false, .parser-false' ).length;
|
379
395
|
if ( wo.filter_columnFilters !== false && val !== c.$headers.length ) {
|
380
396
|
// build filter row
|
381
|
-
|
397
|
+
tsf.buildRow( table, c, wo );
|
382
398
|
}
|
383
399
|
|
384
400
|
txt = 'addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search '
|
@@ -391,13 +407,13 @@
|
|
391
407
|
c.$table.find( '.' + tscss.filterRow ).toggleClass( wo.filter_filteredRow, val ); // fixes #450
|
392
408
|
if ( !/(search|filter)/.test( event.type ) ) {
|
393
409
|
event.stopPropagation();
|
394
|
-
|
410
|
+
tsf.buildDefault( table, true );
|
395
411
|
}
|
396
412
|
if ( event.type === 'filterReset' ) {
|
397
413
|
c.$table.find( '.' + tscss.filter ).add( wo.filter_$externalFilters ).val( '' );
|
398
|
-
|
414
|
+
tsf.searching( table, [] );
|
399
415
|
} else if ( event.type === 'filterEnd' ) {
|
400
|
-
|
416
|
+
tsf.buildDefault( table, true );
|
401
417
|
} else {
|
402
418
|
// send false argument to force a new search; otherwise if the filter hasn't changed,
|
403
419
|
// it will return
|
@@ -411,7 +427,7 @@
|
|
411
427
|
// pass true ( skipFirst ) to prevent the tablesorter.setFilters function from skipping the first
|
412
428
|
// input ensures all inputs are updated when a search is triggered on the table
|
413
429
|
// $( 'table' ).trigger( 'search', [...] );
|
414
|
-
|
430
|
+
tsf.searching( table, filter, true );
|
415
431
|
}
|
416
432
|
return false;
|
417
433
|
});
|
@@ -444,7 +460,7 @@
|
|
444
460
|
noSelect = !( $header.hasClass( 'filter-false' ) || $header.hasClass( 'parser-false' ) );
|
445
461
|
options = '';
|
446
462
|
if ( fxn === true && noSelect ) {
|
447
|
-
|
463
|
+
tsf.buildSelect( table, column );
|
448
464
|
} else if ( typeof fxn === 'object' && noSelect ) {
|
449
465
|
// add custom drop down list
|
450
466
|
for ( string in fxn ) {
|
@@ -477,7 +493,7 @@
|
|
477
493
|
fxn = $.isFunction( txt ) ? true : ts.getColumnData( table, txt, column );
|
478
494
|
if ( fxn ) {
|
479
495
|
// updating so the extra options are appended
|
480
|
-
|
496
|
+
tsf.buildSelect( c.table, column, '', true, $header.hasClass( wo.filter_onlyAvail ) );
|
481
497
|
}
|
482
498
|
}
|
483
499
|
}
|
@@ -485,22 +501,22 @@
|
|
485
501
|
}
|
486
502
|
// not really updating, but if the column has both the 'filter-select' class &
|
487
503
|
// filter_functions set to true, it would append the same options twice.
|
488
|
-
|
504
|
+
tsf.buildDefault( table, true );
|
489
505
|
|
490
|
-
|
506
|
+
tsf.bindSearch( table, c.$table.find( '.' + tscss.filter ), true );
|
491
507
|
if ( wo.filter_external ) {
|
492
|
-
|
508
|
+
tsf.bindSearch( table, wo.filter_external );
|
493
509
|
}
|
494
510
|
|
495
511
|
if ( wo.filter_hideFilters ) {
|
496
|
-
|
512
|
+
tsf.hideFilters( table, c );
|
497
513
|
}
|
498
514
|
|
499
515
|
// show processing icon
|
500
516
|
if ( c.showProcessing ) {
|
501
517
|
txt = 'filterStart filterEnd '.split( ' ' ).join( c.namespace + 'filter ' );
|
502
518
|
c.$table
|
503
|
-
.unbind( txt.replace(
|
519
|
+
.unbind( txt.replace( ts.regex.spaces, ' ' ) )
|
504
520
|
.bind( txt, function( event, columns ) {
|
505
521
|
// only add processing to certain columns to all columns
|
506
522
|
$header = ( columns ) ?
|
@@ -520,11 +536,11 @@
|
|
520
536
|
// add default values
|
521
537
|
txt = 'tablesorter-initialized pagerBeforeInitialized '.split( ' ' ).join( c.namespace + 'filter ' );
|
522
538
|
c.$table
|
523
|
-
.unbind( txt.replace(
|
539
|
+
.unbind( txt.replace( ts.regex.spaces, ' ' ) )
|
524
540
|
.bind( txt, function() {
|
525
541
|
// redefine 'wo' as it does not update properly inside this callback
|
526
542
|
var wo = this.config.widgetOptions;
|
527
|
-
filters =
|
543
|
+
filters = tsf.setDefaults( table, c, wo ) || [];
|
528
544
|
if ( filters.length ) {
|
529
545
|
// prevent delayInit from triggering a cache build if filters are empty
|
530
546
|
if ( !( c.delayInit && filters.join( '' ) === '' ) ) {
|
@@ -535,7 +551,7 @@
|
|
535
551
|
// trigger init after setTimeout to prevent multiple filterStart/End/Init triggers
|
536
552
|
setTimeout( function() {
|
537
553
|
if ( !wo.filter_initialized ) {
|
538
|
-
|
554
|
+
tsf.filterInitComplete( c );
|
539
555
|
}
|
540
556
|
}, 100 );
|
541
557
|
});
|
@@ -543,7 +559,7 @@
|
|
543
559
|
if ( c.pager && c.pager.initialized && !wo.filter_initialized ) {
|
544
560
|
c.$table.trigger( 'filterFomatterUpdate' );
|
545
561
|
setTimeout( function() {
|
546
|
-
|
562
|
+
tsf.filterInitComplete( c );
|
547
563
|
}, 100 );
|
548
564
|
}
|
549
565
|
},
|
@@ -564,7 +580,7 @@
|
|
564
580
|
completed = function() {
|
565
581
|
wo.filter_initialized = true;
|
566
582
|
c.$table.trigger( 'filterInit', c );
|
567
|
-
|
583
|
+
tsf.findRows( c.table, c.$table.data( 'lastSearch' ) || [] );
|
568
584
|
};
|
569
585
|
if ( $.isEmptyObject( wo.filter_formatter ) ) {
|
570
586
|
completed();
|
@@ -716,7 +732,7 @@
|
|
716
732
|
// use data attribute instead of jQuery data since the head is cloned without including
|
717
733
|
// the data/binding
|
718
734
|
.attr( 'data-lastSearchTime', new Date().getTime() )
|
719
|
-
.unbind( tmp.replace(
|
735
|
+
.unbind( tmp.replace( ts.regex.spaces, ' ' ) )
|
720
736
|
// include change for select - fixes #473
|
721
737
|
.bind( 'keyup' + namespace, function( event ) {
|
722
738
|
$( this ).attr( 'data-lastSearchTime', new Date().getTime() );
|
@@ -736,17 +752,18 @@
|
|
736
752
|
return;
|
737
753
|
}
|
738
754
|
// change event = no delay; last true flag tells getFilters to skip newest timed input
|
739
|
-
|
755
|
+
tsf.searching( table, true, true );
|
740
756
|
})
|
741
757
|
.bind( 'search change keypress '.split( ' ' ).join( namespace + ' ' ), function( event ) {
|
742
|
-
|
758
|
+
// don't get cached data, in case data-column changes dynamically
|
759
|
+
var column = parseInt( $( this ).attr( 'data-column' ), 10 );
|
743
760
|
// don't allow 'change' event to process if the input value is the same - fixes #685
|
744
761
|
if ( event.which === 13 || event.type === 'search' ||
|
745
762
|
event.type === 'change' && this.value !== c.lastSearch[column] ) {
|
746
763
|
event.preventDefault();
|
747
764
|
// init search with no delay
|
748
765
|
$( this ).attr( 'data-lastSearchTime', new Date().getTime() );
|
749
|
-
|
766
|
+
tsf.searching( table, false, true );
|
750
767
|
}
|
751
768
|
});
|
752
769
|
},
|
@@ -756,11 +773,11 @@
|
|
756
773
|
if ( typeof filter === 'undefined' || filter === true ) {
|
757
774
|
// delay filtering
|
758
775
|
wo.searchTimer = setTimeout( function() {
|
759
|
-
|
776
|
+
tsf.checkFilters( table, filter, skipFirst );
|
760
777
|
}, wo.filter_liveSearch ? wo.filter_searchDelay : 10 );
|
761
778
|
} else {
|
762
779
|
// skip delay
|
763
|
-
|
780
|
+
tsf.checkFilters( table, filter, skipFirst );
|
764
781
|
}
|
765
782
|
},
|
766
783
|
checkFilters: function( table, filter, skipFirst ) {
|
@@ -774,7 +791,7 @@
|
|
774
791
|
// update cache if delayInit set & pager has initialized ( after user initiates a search )
|
775
792
|
if ( c.delayInit && c.pager && c.pager.initialized ) {
|
776
793
|
c.$table.trigger( 'updateCache', [ function() {
|
777
|
-
|
794
|
+
tsf.checkFilters( table, false, skipFirst );
|
778
795
|
} ] );
|
779
796
|
}
|
780
797
|
return;
|
@@ -805,11 +822,11 @@
|
|
805
822
|
if ( c.showProcessing ) {
|
806
823
|
// give it time for the processing icon to kick in
|
807
824
|
setTimeout( function() {
|
808
|
-
|
825
|
+
tsf.findRows( table, filters, combinedFilters );
|
809
826
|
return false;
|
810
827
|
}, 30 );
|
811
828
|
} else {
|
812
|
-
|
829
|
+
tsf.findRows( table, filters, combinedFilters );
|
813
830
|
return false;
|
814
831
|
}
|
815
832
|
},
|
@@ -852,8 +869,8 @@
|
|
852
869
|
},
|
853
870
|
defaultFilter: function( filter, mask ) {
|
854
871
|
if ( filter === '' ) { return filter; }
|
855
|
-
var regex =
|
856
|
-
maskLen = mask.match(
|
872
|
+
var regex = tsf.regex.iQuery,
|
873
|
+
maskLen = mask.match( tsf.regex.igQuery ).length,
|
857
874
|
query = maskLen > 1 ? $.trim( filter ).split( /\s/ ) : [ $.trim( filter ) ],
|
858
875
|
len = query.length - 1,
|
859
876
|
indx = 0,
|
@@ -889,7 +906,10 @@
|
|
889
906
|
// & don't target 'all' column inputs if they don't exist
|
890
907
|
targets = wo.filter_initialized || !$input.filter( wo.filter_anyColumnSelector ).length,
|
891
908
|
columns = [],
|
892
|
-
val = $.trim(
|
909
|
+
val = $.trim( tsf.getLatestSearch( $input ).attr( 'data-column' ) || '' );
|
910
|
+
if ( !/[,-]/.test(val) && val.length === 1 ) {
|
911
|
+
return parseInt( val, 10 );
|
912
|
+
}
|
893
913
|
// process column range
|
894
914
|
if ( targets && /-/.test( val ) ) {
|
895
915
|
ranges = val.match( /(\d+)\s*-\s*(\d+)/g );
|
@@ -936,9 +956,9 @@
|
|
936
956
|
var ffxn,
|
937
957
|
filterMatched = null,
|
938
958
|
matches = null;
|
939
|
-
for ( ffxn in
|
959
|
+
for ( ffxn in tsf.types ) {
|
940
960
|
if ( $.inArray( ffxn, vars.excludeMatch ) < 0 && matches === null ) {
|
941
|
-
matches =
|
961
|
+
matches = tsf.types[ffxn]( c, data, vars );
|
942
962
|
if ( matches !== null ) {
|
943
963
|
filterMatched = matches;
|
944
964
|
}
|
@@ -947,16 +967,23 @@
|
|
947
967
|
return filterMatched;
|
948
968
|
},
|
949
969
|
processRow: function( c, data, vars ) {
|
950
|
-
var
|
970
|
+
var hasSelect, result, val, filterMatched,
|
951
971
|
fxn, ffxn, txt,
|
952
|
-
regex =
|
972
|
+
regex = tsf.regex,
|
953
973
|
wo = c.widgetOptions,
|
954
|
-
showRow = true
|
974
|
+
showRow = true,
|
975
|
+
|
976
|
+
// if wo.filter_$anyMatch data-column attribute is changed dynamically
|
977
|
+
// we don't want to do an "anyMatch" search on one column using data
|
978
|
+
// for the entire row - see #998
|
979
|
+
columnIndex = wo.filter_$anyMatch && wo.filter_$anyMatch.length ?
|
980
|
+
// look for multiple columns '1-3,4-6,8'
|
981
|
+
tsf.multipleColumns( c, wo.filter_$anyMatch ) :
|
982
|
+
[];
|
983
|
+
|
955
984
|
data.$cells = data.$row.children();
|
956
985
|
|
957
|
-
if ( data.anyMatchFlag ) {
|
958
|
-
// look for multiple columns '1-3,4-6,8'
|
959
|
-
columnIndex = ts.filter.multipleColumns( c, wo.filter_$anyMatch );
|
986
|
+
if ( data.anyMatchFlag && columnIndex.length > 1 ) {
|
960
987
|
data.anyMatch = true;
|
961
988
|
data.isMatch = true;
|
962
989
|
data.rowArray = data.$cells.map( function( i ) {
|
@@ -980,7 +1007,7 @@
|
|
980
1007
|
data.cache = data.cacheArray.slice( 0, -1 ).join( ' ' );
|
981
1008
|
|
982
1009
|
vars.excludeMatch = vars.noAnyMatch;
|
983
|
-
filterMatched =
|
1010
|
+
filterMatched = tsf.processTypes( c, data, vars );
|
984
1011
|
|
985
1012
|
if ( filterMatched !== null ) {
|
986
1013
|
showRow = filterMatched;
|
@@ -1041,7 +1068,7 @@
|
|
1041
1068
|
|
1042
1069
|
val = true;
|
1043
1070
|
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultColFilter[ columnIndex ] ) ) {
|
1044
|
-
data.filter =
|
1071
|
+
data.filter = tsf.defaultFilter( data.filter, vars.defaultColFilter[ columnIndex ] );
|
1045
1072
|
// val is used to indicate that a filter select is using a default filter;
|
1046
1073
|
// so we override the exact & partial matches
|
1047
1074
|
val = false;
|
@@ -1072,13 +1099,13 @@
|
|
1072
1099
|
if ( filterMatched === null ) {
|
1073
1100
|
// cycle through the different filters
|
1074
1101
|
// filters return a boolean or null if nothing matches
|
1075
|
-
filterMatched =
|
1102
|
+
filterMatched = tsf.processTypes( c, data, vars );
|
1076
1103
|
if ( filterMatched !== null ) {
|
1077
1104
|
result = filterMatched;
|
1078
1105
|
// Look for match, and add child row data for matching
|
1079
1106
|
} else {
|
1080
1107
|
txt = ( data.iExact + data.childRowText )
|
1081
|
-
.indexOf(
|
1108
|
+
.indexOf( tsf.parseFilter( c, data.iFilter, columnIndex, data.parsed[ columnIndex ] ) );
|
1082
1109
|
result = ( ( !wo.filter_startsWith && txt >= 0 ) || ( wo.filter_startsWith && txt === 0 ) );
|
1083
1110
|
}
|
1084
1111
|
} else {
|
@@ -1098,7 +1125,7 @@
|
|
1098
1125
|
isChild, childRow, lastSearch, showRow, time, val, indx,
|
1099
1126
|
notFiltered, searchFiltered, query, injected, res, id, txt,
|
1100
1127
|
storedFilters = $.extend( [], filters ),
|
1101
|
-
regex =
|
1128
|
+
regex = tsf.regex,
|
1102
1129
|
c = table.config,
|
1103
1130
|
wo = c.widgetOptions,
|
1104
1131
|
// data object passed to filters; anyMatch is a flag for the filters
|
@@ -1175,7 +1202,7 @@
|
|
1175
1202
|
data.anyMatchFlag = true;
|
1176
1203
|
data.anyMatchFilter = '' + (
|
1177
1204
|
filters[ c.columns ] ||
|
1178
|
-
wo.filter_$anyMatch &&
|
1205
|
+
wo.filter_$anyMatch && tsf.getLatestSearch( wo.filter_$anyMatch ).val() ||
|
1179
1206
|
''
|
1180
1207
|
);
|
1181
1208
|
if ( wo.filter_columnAnyMatch ) {
|
@@ -1217,10 +1244,10 @@
|
|
1217
1244
|
// if there is NOT a logical 'or', or range ( 'to' or '-' ) in the string
|
1218
1245
|
!regex.alreadyFiltered.test( val ) &&
|
1219
1246
|
// if we are not doing exact matches, using '|' ( logical or ) or not '!'
|
1220
|
-
|
1247
|
+
!regex.exactTest.test( val ) &&
|
1221
1248
|
// don't search only filtered if the value is negative
|
1222
1249
|
// ( '> -10' => '> -100' will ignore hidden rows )
|
1223
|
-
!(
|
1250
|
+
!( regex.isNeg1.test( val ) || regex.isNeg2.test( val ) ) &&
|
1224
1251
|
// if filtering using a select without a 'filter-match' class ( exact match ) - fixes #593
|
1225
1252
|
!( val !== '' && c.$filters && c.$filters.eq( indx ).find( 'select' ).length &&
|
1226
1253
|
!c.$headerIndexed[indx].hasClass( 'filter-match' ) );
|
@@ -1239,7 +1266,7 @@
|
|
1239
1266
|
data.anyMatchFilter = ts.replaceAccents( data.anyMatchFilter );
|
1240
1267
|
}
|
1241
1268
|
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultAnyFilter ) ) {
|
1242
|
-
data.anyMatchFilter =
|
1269
|
+
data.anyMatchFilter = tsf.defaultFilter( data.anyMatchFilter, vars.defaultAnyFilter );
|
1243
1270
|
// clear search filtered flag because default filters are not saved to the last search
|
1244
1271
|
searchFiltered = false;
|
1245
1272
|
}
|
@@ -1282,7 +1309,7 @@
|
|
1282
1309
|
'';
|
1283
1310
|
}
|
1284
1311
|
|
1285
|
-
showRow =
|
1312
|
+
showRow = tsf.processRow( c, data, vars );
|
1286
1313
|
childRow = rowData.$row.filter( ':gt( 0 )' );
|
1287
1314
|
|
1288
1315
|
if ( wo.filter_childRows && childRow.length ) {
|
@@ -1293,7 +1320,7 @@
|
|
1293
1320
|
data.cacheArray = rowData.child[ indx ];
|
1294
1321
|
data.rawArray = data.cacheArray;
|
1295
1322
|
// use OR comparison on child rows
|
1296
|
-
showRow = showRow ||
|
1323
|
+
showRow = showRow || tsf.processRow( c, data, vars );
|
1297
1324
|
}
|
1298
1325
|
}
|
1299
1326
|
childRow.toggleClass( wo.filter_filteredRow, !showRow );
|
@@ -1355,7 +1382,7 @@
|
|
1355
1382
|
}
|
1356
1383
|
if ( arry === false ) {
|
1357
1384
|
// fall back to original method
|
1358
|
-
arry =
|
1385
|
+
arry = tsf.getOptions( table, column, onlyAvail );
|
1359
1386
|
}
|
1360
1387
|
|
1361
1388
|
// get unique elements and sort the list
|
@@ -1467,13 +1494,13 @@
|
|
1467
1494
|
// nothing included in arry ( external source ), so get the options from
|
1468
1495
|
// filter_selectSource or column data
|
1469
1496
|
if ( typeof arry === 'undefined' || arry === '' ) {
|
1470
|
-
arry =
|
1497
|
+
arry = tsf.getOptionSource( table, column, onlyAvail );
|
1471
1498
|
}
|
1472
1499
|
|
1473
1500
|
if ( $.isArray( arry ) ) {
|
1474
1501
|
// build option list
|
1475
1502
|
for ( indx = 0; indx < arry.length; indx++ ) {
|
1476
|
-
txt = arry[indx] = ( '' + arry[indx] ).replace(
|
1503
|
+
txt = arry[indx] = ( '' + arry[indx] ).replace( tsf.regex.quote, '"' );
|
1477
1504
|
val = txt;
|
1478
1505
|
// allow including a symbol in the selectSource array
|
1479
1506
|
// 'a-z|A through Z' so that 'a-z' becomes the option value
|
@@ -1529,7 +1556,7 @@
|
|
1529
1556
|
// look for the filter-select class; build/update it if found
|
1530
1557
|
if ( ( $header.hasClass( 'filter-select' ) ||
|
1531
1558
|
ts.getColumnData( table, wo.filter_functions, columnIndex ) === true ) && noSelect ) {
|
1532
|
-
|
1559
|
+
tsf.buildSelect( table, columnIndex, '', updating, $header.hasClass( wo.filter_onlyAvail ) );
|
1533
1560
|
}
|
1534
1561
|
}
|
1535
1562
|
}
|
@@ -1565,7 +1592,7 @@
|
|
1565
1592
|
$column = $filters.filter( cols );
|
1566
1593
|
if ( $column.length ) {
|
1567
1594
|
// move the latest search to the first slot in the array
|
1568
|
-
$column =
|
1595
|
+
$column = tsf.getLatestSearch( $column );
|
1569
1596
|
if ( $.isArray( setFilters ) ) {
|
1570
1597
|
// skip first ( latest input ) to maintain cursor position while typing
|
1571
1598
|
if ( skipFirst && $column.length > 1 ) {
|
@@ -1615,7 +1642,7 @@
|
|
1615
1642
|
// ensure new set filters are applied, even if the search is the same
|
1616
1643
|
c.lastCombinedFilter = null;
|
1617
1644
|
c.lastSearch = [];
|
1618
|
-
|
1645
|
+
tsf.searching( c.table, filter, skipFirst );
|
1619
1646
|
c.$table.trigger( 'filterFomatterUpdate' );
|
1620
1647
|
}
|
1621
1648
|
return !!valid;
|