jquery-tablesorter 1.16.5 → 1.17.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 +2 -2
- data/lib/jquery-tablesorter/version.rb +1 -1
- data/vendor/assets/javascripts/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.js +38 -27
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.combined.js +1104 -839
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.js +167 -123
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets.js +938 -717
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date.js +5 -5
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-globalize.js +46 -0
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-input-select.js +96 -72
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-named-numbers.js +6 -5
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-network.js +26 -17
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-columns.js +1 -1
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-editable.js +95 -42
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter.js +921 -700
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-grouping.js +5 -3
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-math.js +22 -20
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-output.js +7 -5
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-pager.js +40 -29
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-resizable.js +6 -6
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-saveSort.js +1 -1
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-scroller.js +53 -31
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-stickyHeaders.js +1 -1
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-storage.js +1 -1
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-uitheme.js +1 -1
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.black-ice.css +2 -1
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.blue.css +2 -1
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.bootstrap.css +2 -1
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.bootstrap_2.css +8 -6
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.dark.css +2 -1
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.default.css +1 -1
- metadata +3 -2
@@ -4,7 +4,7 @@
|
|
4
4
|
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██▀▀ ▀▀▀▀██
|
5
5
|
█████▀ ▀████▀ ██ ██ ▀████▀ ██ ██ ██ ██ ▀████▀ █████▀ ██ ██ █████▀
|
6
6
|
*/
|
7
|
-
/*! tablesorter (FORK) - updated
|
7
|
+
/*! tablesorter (FORK) - updated 05-17-2015 (v2.22.0)*/
|
8
8
|
/* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */
|
9
9
|
(function(factory) {
|
10
10
|
if (typeof define === 'function' && define.amd) {
|
@@ -20,7 +20,7 @@
|
|
20
20
|
;(function ($, window, document) {
|
21
21
|
'use strict';
|
22
22
|
|
23
|
-
var ts = $.tablesorter
|
23
|
+
var ts = $.tablesorter || {};
|
24
24
|
// *** Store data in local storage, with a cookie fallback ***
|
25
25
|
/* IE7 needs JSON library for JSON.stringify - (http://caniuse.com/#search=json)
|
26
26
|
if you need it, then include https://github.com/douglascrockford/JSON-js
|
@@ -109,7 +109,7 @@ ts.storage = function(table, key, value, options) {
|
|
109
109
|
/*! Widget: uitheme - updated 3/26/2015 (v2.21.3) */
|
110
110
|
;(function ($) {
|
111
111
|
'use strict';
|
112
|
-
var ts = $.tablesorter
|
112
|
+
var ts = $.tablesorter || {};
|
113
113
|
|
114
114
|
ts.themes = {
|
115
115
|
'bootstrap' : {
|
@@ -295,7 +295,7 @@ ts.addWidget({
|
|
295
295
|
/*! Widget: columns */
|
296
296
|
;(function ($) {
|
297
297
|
'use strict';
|
298
|
-
var ts = $.tablesorter
|
298
|
+
var ts = $.tablesorter || {};
|
299
299
|
|
300
300
|
ts.addWidget({
|
301
301
|
id: "columns",
|
@@ -371,16 +371,16 @@ ts.addWidget({
|
|
371
371
|
|
372
372
|
})(jQuery);
|
373
373
|
|
374
|
-
/*! Widget: filter - updated
|
374
|
+
/*! Widget: filter - updated 5/17/2015 (v2.22.0) *//*
|
375
375
|
* Requires tablesorter v2.8+ and jQuery 1.7+
|
376
376
|
* by Rob Garrison
|
377
377
|
*/
|
378
|
-
;(function ($) {
|
378
|
+
;( function ( $ ) {
|
379
379
|
'use strict';
|
380
|
-
var ts = $.tablesorter
|
380
|
+
var ts = $.tablesorter || {},
|
381
381
|
tscss = ts.css;
|
382
382
|
|
383
|
-
$.extend(tscss, {
|
383
|
+
$.extend( tscss, {
|
384
384
|
filterRow : 'tablesorter-filter-row',
|
385
385
|
filter : 'tablesorter-filter',
|
386
386
|
filterDisabled : 'disabled',
|
@@ -388,26 +388,27 @@ $.extend(tscss, {
|
|
388
388
|
});
|
389
389
|
|
390
390
|
ts.addWidget({
|
391
|
-
id:
|
391
|
+
id: 'filter',
|
392
392
|
priority: 50,
|
393
393
|
options : {
|
394
394
|
filter_childRows : false, // if true, filter includes child row content in the search
|
395
|
+
filter_childByColumn : false, // ( filter_childRows must be true ) if true = search child rows by column; false = search all child row text grouped
|
395
396
|
filter_columnFilters : true, // if true, a filter will be added to the top of each table column
|
396
|
-
filter_columnAnyMatch: true, // if true, allows using
|
397
|
-
filter_cellFilter : '', // css class name added to the filter cell (string or array)
|
398
|
-
filter_cssFilter : '', // css class name added to the filter row & each input in the row (tablesorter-filter is ALWAYS added)
|
399
|
-
filter_defaultFilter : {}, // add a default column filter type
|
397
|
+
filter_columnAnyMatch: true, // if true, allows using '#:{query}' in AnyMatch searches ( column:query )
|
398
|
+
filter_cellFilter : '', // css class name added to the filter cell ( string or array )
|
399
|
+
filter_cssFilter : '', // css class name added to the filter row & each input in the row ( tablesorter-filter is ALWAYS added )
|
400
|
+
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.
|
400
401
|
filter_excludeFilter : {}, // filters to exclude, per column
|
401
|
-
filter_external : '', // jQuery selector string (or jQuery object) of external filters
|
402
|
+
filter_external : '', // jQuery selector string ( or jQuery object ) of external filters
|
402
403
|
filter_filteredRow : 'filtered', // class added to filtered rows; needed by pager plugin
|
403
404
|
filter_formatter : null, // add custom filter elements to the filter row
|
404
405
|
filter_functions : null, // add custom filter functions using this option
|
405
406
|
filter_hideEmpty : true, // hide filter row when table is empty
|
406
407
|
filter_hideFilters : false, // collapse filter row when mouse leaves the area
|
407
408
|
filter_ignoreCase : true, // if true, make all searches case-insensitive
|
408
|
-
filter_liveSearch : true, // if true, search column content while the user types (with a delay)
|
409
|
-
filter_onlyAvail : 'filter-onlyAvail', // a header with a select dropdown & this class name will only show available (visible) options within the drop down
|
410
|
-
filter_placeholder : { search : '', select : '' }, // default placeholder text (overridden by any header
|
409
|
+
filter_liveSearch : true, // if true, search column content while the user types ( with a delay )
|
410
|
+
filter_onlyAvail : 'filter-onlyAvail', // a header with a select dropdown & this class name will only show available ( visible ) options within the drop down
|
411
|
+
filter_placeholder : { search : '', select : '' }, // default placeholder text ( overridden by any header 'data-placeholder' setting )
|
411
412
|
filter_reset : null, // jQuery selector string of an element used to reset the filters
|
412
413
|
filter_saveFilters : false, // Use the $.tablesorter.storage utility to save the most recent filters
|
413
414
|
filter_searchDelay : 300, // typing delay in milliseconds before starting a search
|
@@ -419,37 +420,38 @@ ts.addWidget({
|
|
419
420
|
filter_defaultAttrib : 'data-value', // data attribute in the header cell that contains the default filter value
|
420
421
|
filter_selectSourceSeparator : '|' // filter_selectSource array text left of the separator is added to the option value, right into the option text
|
421
422
|
},
|
422
|
-
format: function(table, c, wo) {
|
423
|
-
if (!c.$table.hasClass('hasFilters')) {
|
424
|
-
ts.filter.init(table, c, wo);
|
423
|
+
format: function( table, c, wo ) {
|
424
|
+
if ( !c.$table.hasClass( 'hasFilters' ) ) {
|
425
|
+
ts.filter.init( table, c, wo );
|
425
426
|
}
|
426
427
|
},
|
427
|
-
remove: function(table, c, wo, refreshing) {
|
428
|
+
remove: function( table, c, wo, refreshing ) {
|
428
429
|
var tbodyIndex, $tbody,
|
429
430
|
$table = c.$table,
|
430
431
|
$tbodies = c.$tbodies,
|
431
|
-
events = 'addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search '
|
432
|
+
events = 'addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search '
|
433
|
+
.split( ' ' ).join( c.namespace + 'filter ' );
|
432
434
|
$table
|
433
|
-
.removeClass('hasFilters')
|
435
|
+
.removeClass( 'hasFilters' )
|
434
436
|
// add .tsfilter namespace to all BUT search
|
435
|
-
.unbind( events.replace(/\s+/g, ' ') )
|
437
|
+
.unbind( events.replace( /\s+/g, ' ' ) )
|
436
438
|
// remove the filter row even if refreshing, because the column might have been moved
|
437
|
-
.find('.' + tscss.filterRow).remove();
|
438
|
-
if (refreshing) { return; }
|
439
|
-
for (tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) {
|
440
|
-
$tbody = ts.processTbody(table, $tbodies.eq(tbodyIndex), true); // remove tbody
|
441
|
-
$tbody.children().removeClass(wo.filter_filteredRow).show();
|
442
|
-
ts.processTbody(table, $tbody, false); // restore tbody
|
439
|
+
.find( '.' + tscss.filterRow ).remove();
|
440
|
+
if ( refreshing ) { return; }
|
441
|
+
for ( tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) {
|
442
|
+
$tbody = ts.processTbody( table, $tbodies.eq( tbodyIndex ), true ); // remove tbody
|
443
|
+
$tbody.children().removeClass( wo.filter_filteredRow ).show();
|
444
|
+
ts.processTbody( table, $tbody, false ); // restore tbody
|
443
445
|
}
|
444
|
-
if (wo.filter_reset) {
|
445
|
-
$(document).undelegate(wo.filter_reset, 'click.tsfilter');
|
446
|
+
if ( wo.filter_reset ) {
|
447
|
+
$( document ).undelegate( wo.filter_reset, 'click.tsfilter' );
|
446
448
|
}
|
447
449
|
}
|
448
450
|
});
|
449
451
|
|
450
452
|
ts.filter = {
|
451
453
|
|
452
|
-
// regex used in filter
|
454
|
+
// regex used in filter 'check' functions - not for general use and not documented
|
453
455
|
regex: {
|
454
456
|
regex : /^\/((?:\\\/|[^\/])+)\/([mig]{0,3})?$/, // regex to test for regex
|
455
457
|
child : /tablesorter-childRow/, // child row class name; this gets updated in the script
|
@@ -462,22 +464,33 @@ ts.filter = {
|
|
462
464
|
},
|
463
465
|
// function( c, data ) { }
|
464
466
|
// c = table.config
|
465
|
-
// data
|
466
|
-
// data
|
467
|
-
// data.
|
468
|
-
// data.
|
469
|
-
// data.
|
470
|
-
// data.
|
471
|
-
// data.
|
467
|
+
// data.$row = jQuery object of the row currently being processed
|
468
|
+
// data.$cells = jQuery object of all cells within the current row
|
469
|
+
// data.filters = array of filters for all columns ( some may be undefined )
|
470
|
+
// data.filter = filter for the current column
|
471
|
+
// data.iFilter = same as data.filter, except lowercase ( if wo.filter_ignoreCase is true )
|
472
|
+
// data.exact = table cell text ( or parsed data if column parser enabled )
|
473
|
+
// data.iExact = same as data.exact, except lowercase ( if wo.filter_ignoreCase is true )
|
474
|
+
// data.cache = table cell text from cache, so it has been parsed ( & in all lower case if c.ignoreCase is true )
|
475
|
+
// data.cacheArray = An array of parsed content from each table cell in the row being processed
|
476
|
+
// data.index = column index; table = table element ( DOM )
|
477
|
+
// data.parsed = array ( by column ) of boolean values ( from filter_useParsedData or 'filter-parsed' class )
|
472
478
|
types: {
|
473
479
|
// Look for regex
|
474
480
|
regex: function( c, data ) {
|
475
|
-
if ( ts.filter.regex.regex.test(data.
|
481
|
+
if ( ts.filter.regex.regex.test( data.filter ) ) {
|
476
482
|
var matches,
|
477
|
-
regex
|
483
|
+
// cache regex per column for optimal speed
|
484
|
+
regex = data.filter_regexCache[ data.index ] || ts.filter.regex.regex.exec( data.filter ),
|
485
|
+
isRegex = regex instanceof RegExp;
|
478
486
|
try {
|
479
|
-
|
480
|
-
|
487
|
+
if ( !isRegex ) {
|
488
|
+
// force case insensitive search if ignoreCase option set?
|
489
|
+
// if ( c.ignoreCase && !regex[2] ) { regex[2] = 'i'; }
|
490
|
+
data.filter_regexCache[ data.index ] = regex = new RegExp( regex[1], regex[2] );
|
491
|
+
}
|
492
|
+
matches = regex.test( data.exact );
|
493
|
+
} catch ( error ) {
|
481
494
|
matches = false;
|
482
495
|
}
|
483
496
|
return matches;
|
@@ -486,46 +499,56 @@ ts.filter = {
|
|
486
499
|
},
|
487
500
|
// Look for operators >, >=, < or <=
|
488
501
|
operators: function( c, data ) {
|
489
|
-
|
490
|
-
|
502
|
+
// ignore empty strings... because '' < 10 is true
|
503
|
+
if ( /^[<>]=?/.test( data.iFilter ) && data.iExact !== '' ) {
|
504
|
+
var cachedValue, result, txt,
|
491
505
|
table = c.table,
|
492
506
|
index = data.index,
|
493
507
|
parsed = data.parsed[index],
|
494
|
-
query = ts.formatFloat( data.iFilter.replace(ts.filter.regex.operators, ''), table ),
|
508
|
+
query = ts.formatFloat( data.iFilter.replace( ts.filter.regex.operators, '' ), table ),
|
495
509
|
parser = c.parsers[index],
|
496
510
|
savedSearch = query;
|
497
|
-
// parse filter value in case we're comparing numbers (dates)
|
498
|
-
if (parsed || parser.type === 'numeric') {
|
499
|
-
|
500
|
-
|
511
|
+
// parse filter value in case we're comparing numbers ( dates )
|
512
|
+
if ( parsed || parser.type === 'numeric' ) {
|
513
|
+
txt = $.trim( '' + data.iFilter.replace( ts.filter.regex.operators, '' ) );
|
514
|
+
result = ts.filter.parseFilter( c, txt, index, true );
|
515
|
+
query = ( typeof result === 'number' && result !== '' && !isNaN( result ) ) ? result : query;
|
501
516
|
}
|
502
|
-
|
503
517
|
// iExact may be numeric - see issue #149;
|
504
|
-
// check if cached is defined, because sometimes j goes out of range? (numeric columns)
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
518
|
+
// check if cached is defined, because sometimes j goes out of range? ( numeric columns )
|
519
|
+
if ( ( parsed || parser.type === 'numeric' ) && !isNaN( query ) &&
|
520
|
+
typeof data.cache !== 'undefined' ) {
|
521
|
+
cachedValue = data.cache;
|
522
|
+
} else {
|
523
|
+
txt = isNaN( data.iExact ) ? data.iExact.replace( ts.filter.regex.nondigit, '' ) : data.iExact;
|
524
|
+
cachedValue = ts.formatFloat( txt, table );
|
525
|
+
}
|
526
|
+
if ( />/.test( data.iFilter ) ) {
|
527
|
+
result = />=/.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
|
528
|
+
} else if ( /</.test( data.iFilter ) ) {
|
529
|
+
result = /<=/.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
|
530
|
+
}
|
511
531
|
// keep showing all rows if nothing follows the operator
|
512
|
-
if ( !result && savedSearch === '' ) {
|
532
|
+
if ( !result && savedSearch === '' ) {
|
533
|
+
result = true;
|
534
|
+
}
|
513
535
|
return result;
|
514
536
|
}
|
515
537
|
return null;
|
516
538
|
},
|
517
539
|
// Look for a not match
|
518
540
|
notMatch: function( c, data ) {
|
519
|
-
if ( /^\!/.test(data.iFilter) ) {
|
541
|
+
if ( /^\!/.test( data.iFilter ) ) {
|
520
542
|
var indx,
|
521
|
-
|
522
|
-
|
543
|
+
txt = data.iFilter.replace( '!', '' ),
|
544
|
+
filter = ts.filter.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
545
|
+
if ( ts.filter.regex.exact.test( filter ) ) {
|
523
546
|
// look for exact not matches - see #628
|
524
|
-
filter = filter.replace(ts.filter.regex.exact, '');
|
525
|
-
return filter === '' ? true : $.trim(filter) !== data.iExact;
|
547
|
+
filter = filter.replace( ts.filter.regex.exact, '' );
|
548
|
+
return filter === '' ? true : $.trim( filter ) !== data.iExact;
|
526
549
|
} else {
|
527
|
-
indx = data.iExact.search( $.trim(filter) );
|
528
|
-
return filter === '' ? true : !(c.widgetOptions.filter_startsWith ? indx === 0 : indx >= 0);
|
550
|
+
indx = data.iExact.search( $.trim( filter ) );
|
551
|
+
return filter === '' ? true : !( c.widgetOptions.filter_startsWith ? indx === 0 : indx >= 0 );
|
529
552
|
}
|
530
553
|
}
|
531
554
|
return null;
|
@@ -533,84 +556,101 @@ ts.filter = {
|
|
533
556
|
// Look for quotes or equals to get an exact match; ignore type since iExact could be numeric
|
534
557
|
exact: function( c, data ) {
|
535
558
|
/*jshint eqeqeq:false */
|
536
|
-
if (ts.filter.regex.exact.test(data.iFilter)) {
|
537
|
-
var
|
538
|
-
|
559
|
+
if ( ts.filter.regex.exact.test( data.iFilter ) ) {
|
560
|
+
var txt = data.iFilter.replace( ts.filter.regex.exact, '' ),
|
561
|
+
filter = ts.filter.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
562
|
+
return data.anyMatch ? $.inArray( filter, data.rowArray ) >= 0 : filter == data.iExact;
|
539
563
|
}
|
540
564
|
return null;
|
541
565
|
},
|
542
|
-
// Look for an AND or && operator (logical and)
|
566
|
+
// Look for an AND or && operator ( logical and )
|
543
567
|
and : function( c, data ) {
|
544
|
-
if ( ts.filter.regex.andTest.test(data.filter) ) {
|
568
|
+
if ( ts.filter.regex.andTest.test( data.filter ) ) {
|
545
569
|
var index = data.index,
|
546
570
|
parsed = data.parsed[index],
|
547
571
|
query = data.iFilter.split( ts.filter.regex.andSplit ),
|
548
|
-
result = data.iExact.search( $.trim( ts.filter.parseFilter(c, query[0], index, parsed) ) ) >= 0,
|
572
|
+
result = data.iExact.search( $.trim( ts.filter.parseFilter( c, query[0], index, parsed ) ) ) >= 0,
|
549
573
|
indx = query.length - 1;
|
550
|
-
while (result && indx) {
|
551
|
-
result = result &&
|
574
|
+
while ( result && indx ) {
|
575
|
+
result = result &&
|
576
|
+
data.iExact.search( $.trim( ts.filter.parseFilter( c, query[indx], index, parsed ) ) ) >= 0;
|
552
577
|
indx--;
|
553
578
|
}
|
554
579
|
return result;
|
555
580
|
}
|
556
581
|
return null;
|
557
582
|
},
|
558
|
-
// Look for a range (using
|
583
|
+
// Look for a range ( using ' to ' or ' - ' ) - see issue #166; thanks matzhu!
|
559
584
|
range : function( c, data ) {
|
560
|
-
if ( ts.filter.regex.toTest.test(data.iFilter) ) {
|
561
|
-
var result, tmp,
|
585
|
+
if ( ts.filter.regex.toTest.test( data.iFilter ) ) {
|
586
|
+
var result, tmp, range1, range2,
|
562
587
|
table = c.table,
|
563
588
|
index = data.index,
|
564
589
|
parsed = data.parsed[index],
|
565
590
|
// make sure the dash is for a range and not indicating a negative number
|
566
|
-
query = data.iFilter.split( ts.filter.regex.toSplit )
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
591
|
+
query = data.iFilter.split( ts.filter.regex.toSplit );
|
592
|
+
|
593
|
+
tmp = query[0].replace( ts.filter.regex.nondigit, '' ) || '';
|
594
|
+
range1 = ts.formatFloat( ts.filter.parseFilter( c, tmp, index, parsed ), table );
|
595
|
+
tmp = query[1].replace( ts.filter.regex.nondigit, '' ) || '';
|
596
|
+
range2 = ts.formatFloat( ts.filter.parseFilter( c, tmp, index, parsed ), table );
|
597
|
+
// parse filter value in case we're comparing numbers ( dates )
|
598
|
+
if ( parsed || c.parsers[index].type === 'numeric' ) {
|
599
|
+
result = c.parsers[ index ].format( '' + query[0], table, c.$headers.eq( index ), index );
|
600
|
+
range1 = ( result !== '' && !isNaN( result ) ) ? result : range1;
|
601
|
+
result = c.parsers[ index ].format( '' + query[1], table, c.$headers.eq( index ), index );
|
602
|
+
range2 = ( result !== '' && !isNaN( result ) ) ? result : range2;
|
575
603
|
}
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
604
|
+
if ( ( parsed || c.parsers[ index ].type === 'numeric' ) && !isNaN( range1 ) && !isNaN( range2 ) ) {
|
605
|
+
result = data.cache;
|
606
|
+
} else {
|
607
|
+
tmp = isNaN( data.iExact ) ? data.iExact.replace( ts.filter.regex.nondigit, '' ) : data.iExact;
|
608
|
+
result = ts.formatFloat( tmp, table );
|
609
|
+
}
|
610
|
+
if ( range1 > range2 ) {
|
611
|
+
tmp = range1; range1 = range2; range2 = tmp; // swap
|
612
|
+
}
|
613
|
+
return ( result >= range1 && result <= range2 ) || ( range1 === '' || range2 === '' );
|
581
614
|
}
|
582
615
|
return null;
|
583
616
|
},
|
584
617
|
// Look for wild card: ? = single, * = multiple, or | = logical OR
|
585
618
|
wild : function( c, data ) {
|
586
|
-
if ( /[\?\*\|]/.test(data.iFilter) || ts.filter.regex.orReplace.test(data.filter) ) {
|
619
|
+
if ( /[\?\*\|]/.test( data.iFilter ) || ts.filter.regex.orReplace.test( data.filter ) ) {
|
587
620
|
var index = data.index,
|
588
|
-
parsed = data.parsed[index],
|
589
|
-
|
590
|
-
|
591
|
-
|
621
|
+
parsed = data.parsed[ index ],
|
622
|
+
txt = data.iFilter.replace( ts.filter.regex.orReplace, '|' ),
|
623
|
+
query = ts.filter.parseFilter( c, txt, index, parsed ) || '';
|
624
|
+
// look for an exact match with the 'or' unless the 'filter-match' class is found
|
625
|
+
if ( !c.$headerIndexed[ index ].hasClass( 'filter-match' ) && /\|/.test( query ) ) {
|
592
626
|
// show all results while using filter match. Fixes #727
|
593
|
-
if (query[ query.length - 1 ] === '|') {
|
594
|
-
|
627
|
+
if ( query[ query.length - 1 ] === '|' ) {
|
628
|
+
query += '*';
|
629
|
+
}
|
630
|
+
query = data.anyMatch && $.isArray( data.rowArray ) ?
|
631
|
+
'(' + query + ')' :
|
632
|
+
'^(' + query + ')$';
|
595
633
|
}
|
596
634
|
// parsing the filter may not work properly when using wildcards =/
|
597
|
-
return new RegExp( query.replace(/\?/g, '\\S{1}').replace(/\*/g, '\\S*') )
|
635
|
+
return new RegExp( query.replace( /\?/g, '\\S{1}' ).replace( /\*/g, '\\S*' ) )
|
636
|
+
.test( data.iExact );
|
598
637
|
}
|
599
638
|
return null;
|
600
639
|
},
|
601
|
-
// fuzzy text search; modified from https://github.com/mattyork/fuzzy (MIT license)
|
640
|
+
// fuzzy text search; modified from https://github.com/mattyork/fuzzy ( MIT license )
|
602
641
|
fuzzy: function( c, data ) {
|
603
|
-
if ( /^~/.test(data.iFilter) ) {
|
642
|
+
if ( /^~/.test( data.iFilter ) ) {
|
604
643
|
var indx,
|
605
644
|
patternIndx = 0,
|
606
645
|
len = data.iExact.length,
|
607
|
-
|
608
|
-
|
609
|
-
|
646
|
+
txt = data.iFilter.slice( 1 ),
|
647
|
+
pattern = ts.filter.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
648
|
+
for ( indx = 0; indx < len; indx++ ) {
|
649
|
+
if ( data.iExact[ indx ] === pattern[ patternIndx ] ) {
|
610
650
|
patternIndx += 1;
|
611
651
|
}
|
612
652
|
}
|
613
|
-
if (patternIndx === pattern.length) {
|
653
|
+
if ( patternIndx === pattern.length ) {
|
614
654
|
return true;
|
615
655
|
}
|
616
656
|
return false;
|
@@ -618,17 +658,17 @@ ts.filter = {
|
|
618
658
|
return null;
|
619
659
|
}
|
620
660
|
},
|
621
|
-
init: function(table, c, wo) {
|
661
|
+
init: function( table, c, wo ) {
|
622
662
|
// filter language options
|
623
|
-
ts.language = $.extend(true, {}, {
|
663
|
+
ts.language = $.extend( true, {}, {
|
624
664
|
to : 'to',
|
625
665
|
or : 'or',
|
626
666
|
and : 'and'
|
627
|
-
}, ts.language);
|
667
|
+
}, ts.language );
|
628
668
|
|
629
669
|
var options, string, txt, $header, column, filters, val, fxn, noSelect,
|
630
670
|
regex = ts.filter.regex;
|
631
|
-
c.$table.addClass('hasFilters');
|
671
|
+
c.$table.addClass( 'hasFilters' );
|
632
672
|
|
633
673
|
// define timers so using clearTimeout won't cause an undefined error
|
634
674
|
wo.searchTimer = null;
|
@@ -638,512 +678,566 @@ ts.filter = {
|
|
638
678
|
wo.filter_anyColumnSelector = '[data-column="all"],[data-column="any"]';
|
639
679
|
wo.filter_multipleColumnSelector = '[data-column*="-"],[data-column*=","]';
|
640
680
|
|
641
|
-
|
681
|
+
val = '\\{' + ts.filter.regex.query + '\\}';
|
642
682
|
$.extend( regex, {
|
643
|
-
child : new RegExp(c.cssChildRow),
|
644
|
-
filtered : new RegExp(wo.filter_filteredRow),
|
645
|
-
alreadyFiltered : new RegExp('(\\s+(' + ts.language.or + '|-|' + ts.language.to + ')\\s+)', 'i'),
|
646
|
-
toTest : new RegExp('\\s+(-|' + ts.language.to + ')\\s+', 'i'),
|
647
|
-
toSplit : new RegExp('(?:\\s+(?:-|' + ts.language.to + ')\\s+)' ,'gi'),
|
648
|
-
andTest : new RegExp('\\s+(' + ts.language.and + '|&&)\\s+', 'i'),
|
649
|
-
andSplit : new RegExp('(?:\\s+(?:' + ts.language.and + '|&&)\\s+)', 'gi'),
|
650
|
-
orReplace : new RegExp('\\s+(' + ts.language.or + ')\\s+', 'gi'),
|
651
|
-
iQuery : new RegExp(
|
652
|
-
igQuery : new RegExp(
|
683
|
+
child : new RegExp( c.cssChildRow ),
|
684
|
+
filtered : new RegExp( wo.filter_filteredRow ),
|
685
|
+
alreadyFiltered : new RegExp( '(\\s+(' + ts.language.or + '|-|' + ts.language.to + ')\\s+)', 'i' ),
|
686
|
+
toTest : new RegExp( '\\s+(-|' + ts.language.to + ')\\s+', 'i' ),
|
687
|
+
toSplit : new RegExp( '(?:\\s+(?:-|' + ts.language.to + ')\\s+)' ,'gi' ),
|
688
|
+
andTest : new RegExp( '\\s+(' + ts.language.and + '|&&)\\s+', 'i' ),
|
689
|
+
andSplit : new RegExp( '(?:\\s+(?:' + ts.language.and + '|&&)\\s+)', 'gi' ),
|
690
|
+
orReplace : new RegExp( '\\s+(' + ts.language.or + ')\\s+', 'gi' ),
|
691
|
+
iQuery : new RegExp( val, 'i' ),
|
692
|
+
igQuery : new RegExp( val, 'ig' )
|
653
693
|
});
|
654
694
|
|
655
|
-
// don't build filter row if columnFilters is false or all columns are set to
|
656
|
-
|
695
|
+
// don't build filter row if columnFilters is false or all columns are set to 'filter-false'
|
696
|
+
// see issue #156
|
697
|
+
val = c.$headers.filter( '.filter-false, .parser-false' ).length;
|
698
|
+
if ( wo.filter_columnFilters !== false && val !== c.$headers.length ) {
|
657
699
|
// build filter row
|
658
|
-
ts.filter.buildRow(table, c, wo);
|
659
|
-
}
|
660
|
-
|
661
|
-
txt = 'addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search '
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
700
|
+
ts.filter.buildRow( table, c, wo );
|
701
|
+
}
|
702
|
+
|
703
|
+
txt = 'addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search '
|
704
|
+
.split( ' ' ).join( c.namespace + 'filter ' );
|
705
|
+
c.$table.bind( txt, function( event, filter ) {
|
706
|
+
val = wo.filter_hideEmpty &&
|
707
|
+
$.isEmptyObject( c.cache ) &&
|
708
|
+
!( c.delayInit && event.type === 'appendCache' );
|
709
|
+
// hide filter row using the 'filtered' class name
|
710
|
+
c.$table.find( '.' + tscss.filterRow ).toggleClass( wo.filter_filteredRow, val ); // fixes #450
|
711
|
+
if ( !/(search|filter)/.test( event.type ) ) {
|
667
712
|
event.stopPropagation();
|
668
|
-
ts.filter.buildDefault(table, true);
|
713
|
+
ts.filter.buildDefault( table, true );
|
669
714
|
}
|
670
|
-
if (event.type === 'filterReset') {
|
671
|
-
c.$table.find('.' + tscss.filter).add(wo.filter_$externalFilters).val('');
|
672
|
-
ts.filter.searching(table, []);
|
673
|
-
} else if (event.type === 'filterEnd') {
|
674
|
-
ts.filter.buildDefault(table, true);
|
715
|
+
if ( event.type === 'filterReset' ) {
|
716
|
+
c.$table.find( '.' + tscss.filter ).add( wo.filter_$externalFilters ).val( '' );
|
717
|
+
ts.filter.searching( table, [] );
|
718
|
+
} else if ( event.type === 'filterEnd' ) {
|
719
|
+
ts.filter.buildDefault( table, true );
|
675
720
|
} else {
|
676
|
-
// send false argument to force a new search; otherwise if the filter hasn't changed,
|
677
|
-
|
678
|
-
|
721
|
+
// send false argument to force a new search; otherwise if the filter hasn't changed,
|
722
|
+
// it will return
|
723
|
+
filter = event.type === 'search' ? filter :
|
724
|
+
event.type === 'updateComplete' ? c.$table.data( 'lastSearch' ) : '';
|
725
|
+
if ( /(update|add)/.test( event.type ) && event.type !== 'updateComplete' ) {
|
679
726
|
// force a new search since content has changed
|
680
727
|
c.lastCombinedFilter = null;
|
681
728
|
c.lastSearch = [];
|
682
729
|
}
|
683
|
-
// pass true (skipFirst) to prevent the tablesorter.setFilters function from skipping the first
|
684
|
-
// ensures all inputs are updated when a search is triggered on the table
|
685
|
-
|
730
|
+
// pass true ( skipFirst ) to prevent the tablesorter.setFilters function from skipping the first
|
731
|
+
// input ensures all inputs are updated when a search is triggered on the table
|
732
|
+
// $( 'table' ).trigger( 'search', [...] );
|
733
|
+
ts.filter.searching( table, filter, true );
|
686
734
|
}
|
687
735
|
return false;
|
688
736
|
});
|
689
737
|
|
690
738
|
// reset button/link
|
691
|
-
if (wo.filter_reset) {
|
692
|
-
if (wo.filter_reset instanceof $) {
|
739
|
+
if ( wo.filter_reset ) {
|
740
|
+
if ( wo.filter_reset instanceof $ ) {
|
693
741
|
// reset contains a jQuery object, bind to it
|
694
|
-
wo.filter_reset.click(function(){
|
695
|
-
c.$table.trigger('filterReset');
|
742
|
+
wo.filter_reset.click( function() {
|
743
|
+
c.$table.trigger( 'filterReset' );
|
696
744
|
});
|
697
|
-
} else if ($(wo.filter_reset).length) {
|
745
|
+
} else if ( $( wo.filter_reset ).length ) {
|
698
746
|
// reset is a jQuery selector, use event delegation
|
699
|
-
$(document)
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
747
|
+
$( document )
|
748
|
+
.undelegate( wo.filter_reset, 'click.tsfilter' )
|
749
|
+
.delegate( wo.filter_reset, 'click.tsfilter', function() {
|
750
|
+
// trigger a reset event, so other functions ( filter_formatter ) know when to reset
|
751
|
+
c.$table.trigger( 'filterReset' );
|
752
|
+
});
|
705
753
|
}
|
706
754
|
}
|
707
|
-
if (wo.filter_functions) {
|
708
|
-
for (column = 0; column < c.columns; column++) {
|
755
|
+
if ( wo.filter_functions ) {
|
756
|
+
for ( column = 0; column < c.columns; column++ ) {
|
709
757
|
fxn = ts.getColumnData( table, wo.filter_functions, column );
|
710
|
-
if (fxn) {
|
711
|
-
// remove
|
712
|
-
|
713
|
-
|
714
|
-
|
758
|
+
if ( fxn ) {
|
759
|
+
// remove 'filter-select' from header otherwise the options added here are replaced with
|
760
|
+
// all options
|
761
|
+
$header = c.$headerIndexed[ column ].removeClass( 'filter-select' );
|
762
|
+
// don't build select if 'filter-false' or 'parser-false' set
|
763
|
+
noSelect = !( $header.hasClass( 'filter-false' ) || $header.hasClass( 'parser-false' ) );
|
715
764
|
options = '';
|
716
765
|
if ( fxn === true && noSelect ) {
|
717
|
-
ts.filter.buildSelect(table, column);
|
766
|
+
ts.filter.buildSelect( table, column );
|
718
767
|
} else if ( typeof fxn === 'object' && noSelect ) {
|
719
768
|
// add custom drop down list
|
720
|
-
for (string in fxn) {
|
721
|
-
if (typeof string === 'string') {
|
769
|
+
for ( string in fxn ) {
|
770
|
+
if ( typeof string === 'string' ) {
|
722
771
|
options += options === '' ?
|
723
|
-
'<option value="">' +
|
772
|
+
'<option value="">' +
|
773
|
+
( $header.data( 'placeholder' ) ||
|
774
|
+
$header.attr( 'data-placeholder' ) ||
|
775
|
+
wo.filter_placeholder.select ||
|
776
|
+
''
|
777
|
+
) +
|
778
|
+
'</option>' : '';
|
724
779
|
val = string;
|
725
780
|
txt = string;
|
726
|
-
if (string.indexOf(wo.filter_selectSourceSeparator) >= 0) {
|
727
|
-
val = string.split(wo.filter_selectSourceSeparator);
|
781
|
+
if ( string.indexOf( wo.filter_selectSourceSeparator ) >= 0 ) {
|
782
|
+
val = string.split( wo.filter_selectSourceSeparator );
|
728
783
|
txt = val[1];
|
729
784
|
val = val[0];
|
730
785
|
}
|
731
|
-
options += '<option ' +
|
786
|
+
options += '<option ' +
|
787
|
+
( txt === val ? '' : 'data-function-name="' + string + '" ' ) +
|
788
|
+
'value="' + val + '">' + txt + '</option>';
|
732
789
|
}
|
733
790
|
}
|
734
|
-
c.$table
|
791
|
+
c.$table
|
792
|
+
.find( 'thead' )
|
793
|
+
.find( 'select.' + tscss.filter + '[data-column="' + column + '"]' )
|
794
|
+
.append( options );
|
735
795
|
txt = wo.filter_selectSource;
|
736
|
-
fxn = $.isFunction(txt) ? true : ts.getColumnData( table, txt, column );
|
737
|
-
if (fxn) {
|
796
|
+
fxn = $.isFunction( txt ) ? true : ts.getColumnData( table, txt, column );
|
797
|
+
if ( fxn ) {
|
738
798
|
// updating so the extra options are appended
|
739
|
-
ts.filter.buildSelect(c.table, column, '', true, $header.hasClass(wo.filter_onlyAvail));
|
799
|
+
ts.filter.buildSelect( c.table, column, '', true, $header.hasClass( wo.filter_onlyAvail ) );
|
740
800
|
}
|
741
801
|
}
|
742
802
|
}
|
743
803
|
}
|
744
804
|
}
|
745
|
-
// not really updating, but if the column has both the
|
746
|
-
// it would append the same options twice.
|
747
|
-
ts.filter.buildDefault(table, true);
|
805
|
+
// not really updating, but if the column has both the 'filter-select' class &
|
806
|
+
// filter_functions set to true, it would append the same options twice.
|
807
|
+
ts.filter.buildDefault( table, true );
|
748
808
|
|
749
|
-
ts.filter.bindSearch( table, c.$table.find('.' + tscss.filter), true );
|
750
|
-
if (wo.filter_external) {
|
809
|
+
ts.filter.bindSearch( table, c.$table.find( '.' + tscss.filter ), true );
|
810
|
+
if ( wo.filter_external ) {
|
751
811
|
ts.filter.bindSearch( table, wo.filter_external );
|
752
812
|
}
|
753
813
|
|
754
|
-
if (wo.filter_hideFilters) {
|
755
|
-
ts.filter.hideFilters(table, c);
|
814
|
+
if ( wo.filter_hideFilters ) {
|
815
|
+
ts.filter.hideFilters( table, c );
|
756
816
|
}
|
757
817
|
|
758
818
|
// show processing icon
|
759
|
-
if (c.showProcessing) {
|
819
|
+
if ( c.showProcessing ) {
|
820
|
+
txt = 'filterStart filterEnd '.split( ' ' ).join( c.namespace + 'filter ' );
|
760
821
|
c.$table
|
761
|
-
.unbind(
|
762
|
-
.bind(
|
822
|
+
.unbind( txt.replace( /\s+/g, ' ' ) )
|
823
|
+
.bind( txt, function( event, columns ) {
|
763
824
|
// only add processing to certain columns to all columns
|
764
|
-
$header = (columns) ?
|
765
|
-
|
766
|
-
|
767
|
-
|
825
|
+
$header = ( columns ) ?
|
826
|
+
c.$table
|
827
|
+
.find( '.' + tscss.header )
|
828
|
+
.filter( '[data-column]' )
|
829
|
+
.filter( function() {
|
830
|
+
return columns[ $( this ).data( 'column' ) ] !== '';
|
831
|
+
}) : '';
|
832
|
+
ts.isProcessing( table, event.type === 'filterStart', columns ? $header : '' );
|
768
833
|
});
|
769
834
|
}
|
770
835
|
|
771
|
-
// set filtered rows count (intially unfiltered)
|
836
|
+
// set filtered rows count ( intially unfiltered )
|
772
837
|
c.filteredRows = c.totalRows;
|
773
838
|
|
774
839
|
// add default values
|
840
|
+
txt = 'tablesorter-initialized pagerBeforeInitialized '.split( ' ' ).join( c.namespace + 'filter ' );
|
775
841
|
c.$table
|
776
|
-
.unbind(
|
777
|
-
.bind(
|
778
|
-
// redefine
|
842
|
+
.unbind( txt.replace( /\s+/g, ' ' ) )
|
843
|
+
.bind( txt, function() {
|
844
|
+
// redefine 'wo' as it does not update properly inside this callback
|
779
845
|
var wo = this.config.widgetOptions;
|
780
|
-
filters = ts.filter.setDefaults(table, c, wo) || [];
|
781
|
-
if (filters.length) {
|
846
|
+
filters = ts.filter.setDefaults( table, c, wo ) || [];
|
847
|
+
if ( filters.length ) {
|
782
848
|
// prevent delayInit from triggering a cache build if filters are empty
|
783
|
-
if ( !(c.delayInit && filters.join('') === '') ) {
|
784
|
-
ts.setFilters(table, filters, true);
|
849
|
+
if ( !( c.delayInit && filters.join( '' ) === '' ) ) {
|
850
|
+
ts.setFilters( table, filters, true );
|
785
851
|
}
|
786
852
|
}
|
787
|
-
c.$table.trigger('filterFomatterUpdate');
|
853
|
+
c.$table.trigger( 'filterFomatterUpdate' );
|
788
854
|
// trigger init after setTimeout to prevent multiple filterStart/End/Init triggers
|
789
|
-
setTimeout(function(){
|
790
|
-
if (!wo.filter_initialized) {
|
791
|
-
ts.filter.filterInitComplete(c);
|
855
|
+
setTimeout( function() {
|
856
|
+
if ( !wo.filter_initialized ) {
|
857
|
+
ts.filter.filterInitComplete( c );
|
792
858
|
}
|
793
|
-
}, 100);
|
859
|
+
}, 100 );
|
794
860
|
});
|
795
861
|
// if filter widget is added after pager has initialized; then set filter init flag
|
796
|
-
if (c.pager && c.pager.initialized && !wo.filter_initialized) {
|
797
|
-
c.$table.trigger('filterFomatterUpdate');
|
798
|
-
setTimeout(function(){
|
799
|
-
ts.filter.filterInitComplete(c);
|
800
|
-
}, 100);
|
862
|
+
if ( c.pager && c.pager.initialized && !wo.filter_initialized ) {
|
863
|
+
c.$table.trigger( 'filterFomatterUpdate' );
|
864
|
+
setTimeout( function() {
|
865
|
+
ts.filter.filterInitComplete( c );
|
866
|
+
}, 100 );
|
801
867
|
}
|
802
868
|
},
|
803
|
-
// $cell parameter, but not the config, is passed to the
|
804
|
-
//
|
805
|
-
formatterUpdated: function($cell, column) {
|
806
|
-
var wo = $cell.closest('table')[0].config.widgetOptions;
|
807
|
-
if (!wo.filter_initialized) {
|
869
|
+
// $cell parameter, but not the config, is passed to the filter_formatters,
|
870
|
+
// so we have to work with it instead
|
871
|
+
formatterUpdated: function( $cell, column ) {
|
872
|
+
var wo = $cell.closest( 'table' )[0].config.widgetOptions;
|
873
|
+
if ( !wo.filter_initialized ) {
|
808
874
|
// add updates by column since this function
|
809
875
|
// may be called numerous times before initialization
|
810
|
-
wo.filter_formatterInit[column] = 1;
|
876
|
+
wo.filter_formatterInit[ column ] = 1;
|
811
877
|
}
|
812
878
|
},
|
813
|
-
filterInitComplete: function(c){
|
879
|
+
filterInitComplete: function( c ) {
|
814
880
|
var indx, len,
|
815
881
|
wo = c.widgetOptions,
|
816
882
|
count = 0,
|
817
|
-
completed = function(){
|
883
|
+
completed = function() {
|
818
884
|
wo.filter_initialized = true;
|
819
|
-
c.$table.trigger('filterInit', c);
|
820
|
-
ts.filter.findRows(c.table, c.$table.data('lastSearch') || []);
|
885
|
+
c.$table.trigger( 'filterInit', c );
|
886
|
+
ts.filter.findRows( c.table, c.$table.data( 'lastSearch' ) || [] );
|
821
887
|
};
|
822
888
|
if ( $.isEmptyObject( wo.filter_formatter ) ) {
|
823
889
|
completed();
|
824
890
|
} else {
|
825
891
|
len = wo.filter_formatterInit.length;
|
826
|
-
for (indx = 0; indx < len; indx++) {
|
827
|
-
if (wo.filter_formatterInit[indx] === 1) {
|
892
|
+
for ( indx = 0; indx < len; indx++ ) {
|
893
|
+
if ( wo.filter_formatterInit[ indx ] === 1 ) {
|
828
894
|
count++;
|
829
895
|
}
|
830
896
|
}
|
831
|
-
clearTimeout(wo.filter_initTimer);
|
832
|
-
if (!wo.filter_initialized && count === wo.filter_formatterCount) {
|
897
|
+
clearTimeout( wo.filter_initTimer );
|
898
|
+
if ( !wo.filter_initialized && count === wo.filter_formatterCount ) {
|
833
899
|
// filter widget initialized
|
834
900
|
completed();
|
835
|
-
} else if (!wo.filter_initialized) {
|
901
|
+
} else if ( !wo.filter_initialized ) {
|
836
902
|
// fall back in case a filter_formatter doesn't call
|
837
|
-
// $.tablesorter.filter.formatterUpdated($cell, column), and the count is off
|
838
|
-
wo.filter_initTimer = setTimeout(function(){
|
903
|
+
// $.tablesorter.filter.formatterUpdated( $cell, column ), and the count is off
|
904
|
+
wo.filter_initTimer = setTimeout( function() {
|
839
905
|
completed();
|
840
|
-
}, 500);
|
906
|
+
}, 500 );
|
841
907
|
}
|
842
908
|
}
|
843
909
|
},
|
844
910
|
|
845
|
-
setDefaults: function(table, c, wo) {
|
911
|
+
setDefaults: function( table, c, wo ) {
|
846
912
|
var isArray, saved, indx, col, $filters,
|
847
|
-
// get current (default) filters
|
848
|
-
filters = ts.getFilters(table) || [];
|
849
|
-
if (wo.filter_saveFilters && ts.storage) {
|
913
|
+
// get current ( default ) filters
|
914
|
+
filters = ts.getFilters( table ) || [];
|
915
|
+
if ( wo.filter_saveFilters && ts.storage ) {
|
850
916
|
saved = ts.storage( table, 'tablesorter-filters' ) || [];
|
851
|
-
isArray = $.isArray(saved);
|
917
|
+
isArray = $.isArray( saved );
|
852
918
|
// make sure we're not just getting an empty array
|
853
|
-
if ( !(isArray && saved.join('') === '' || !isArray) ) {
|
919
|
+
if ( !( isArray && saved.join( '' ) === '' || !isArray ) ) {
|
920
|
+
filters = saved;
|
921
|
+
}
|
854
922
|
}
|
855
923
|
// if no filters saved, then check default settings
|
856
|
-
if (filters.join('') === '') {
|
924
|
+
if ( filters.join( '' ) === '' ) {
|
857
925
|
// allow adding default setting to external filters
|
858
|
-
$filters = c.$headers.add( wo.filter_$externalFilters )
|
859
|
-
|
860
|
-
|
926
|
+
$filters = c.$headers.add( wo.filter_$externalFilters )
|
927
|
+
.filter( '[' + wo.filter_defaultAttrib + ']' );
|
928
|
+
for ( indx = 0; indx <= c.columns; indx++ ) {
|
929
|
+
// include data-column='all' external filters
|
861
930
|
col = indx === c.columns ? 'all' : indx;
|
862
|
-
filters[indx] = $filters
|
931
|
+
filters[indx] = $filters
|
932
|
+
.filter( '[data-column="' + col + '"]' )
|
933
|
+
.attr( wo.filter_defaultAttrib ) || filters[indx] || '';
|
863
934
|
}
|
864
935
|
}
|
865
|
-
c.$table.data('lastSearch', filters);
|
936
|
+
c.$table.data( 'lastSearch', filters );
|
866
937
|
return filters;
|
867
938
|
},
|
868
|
-
parseFilter: function(c, filter, column, parsed
|
869
|
-
return
|
870
|
-
c.parsers[column].format( filter, c.table, [], column ) :
|
871
|
-
filter;
|
939
|
+
parseFilter: function( c, filter, column, parsed ) {
|
940
|
+
return parsed ? c.parsers[column].format( filter, c.table, [], column ) : filter;
|
872
941
|
},
|
873
|
-
buildRow: function(table, c, wo) {
|
874
|
-
var col, column, $header, buildSelect, disabled, name, ffxn,
|
942
|
+
buildRow: function( table, c, wo ) {
|
943
|
+
var col, column, $header, buildSelect, disabled, name, ffxn, tmp,
|
875
944
|
// c.columns defined in computeThIndexes()
|
945
|
+
cellFilter = wo.filter_cellFilter,
|
876
946
|
columns = c.columns,
|
877
|
-
arry = $.isArray(
|
947
|
+
arry = $.isArray( cellFilter ),
|
878
948
|
buildFilter = '<tr role="row" class="' + tscss.filterRow + ' ' + c.cssIgnoreRow + '">';
|
879
|
-
for (column = 0; column < columns; column++) {
|
880
|
-
|
881
|
-
|
949
|
+
for ( column = 0; column < columns; column++ ) {
|
950
|
+
buildFilter += '<td';
|
951
|
+
if ( arry ) {
|
952
|
+
buildFilter += ( cellFilter[ column ] ? ' class="' + cellFilter[ column ] + '"' : '' );
|
882
953
|
} else {
|
883
|
-
buildFilter +=
|
954
|
+
buildFilter += ( cellFilter !== '' ? ' class="' + cellFilter + '"' : '' );
|
884
955
|
}
|
956
|
+
buildFilter += '></td>';
|
885
957
|
}
|
886
|
-
c.$filters = $(buildFilter += '</tr>'
|
958
|
+
c.$filters = $( buildFilter += '</tr>' )
|
959
|
+
.appendTo( c.$table.children( 'thead' ).eq( 0 ) )
|
960
|
+
.find( 'td' );
|
887
961
|
// build each filter input
|
888
|
-
for (column = 0; column < columns; column++) {
|
962
|
+
for ( column = 0; column < columns; column++ ) {
|
889
963
|
disabled = false;
|
890
964
|
// assuming last cell of a column is the main column
|
891
|
-
$header = c.$headerIndexed[column];
|
965
|
+
$header = c.$headerIndexed[ column ];
|
892
966
|
ffxn = ts.getColumnData( table, wo.filter_functions, column );
|
893
|
-
buildSelect = (wo.filter_functions && ffxn && typeof ffxn !==
|
894
|
-
$header.hasClass('filter-select');
|
967
|
+
buildSelect = ( wo.filter_functions && ffxn && typeof ffxn !== 'function' ) ||
|
968
|
+
$header.hasClass( 'filter-select' );
|
895
969
|
// get data from jQuery data, metadata, headers option or header class name
|
896
970
|
col = ts.getColumnData( table, c.headers, column );
|
897
|
-
disabled = ts.getData($header[0], col, 'filter') === 'false' ||
|
971
|
+
disabled = ts.getData( $header[0], col, 'filter' ) === 'false' ||
|
972
|
+
ts.getData( $header[0], col, 'parser' ) === 'false';
|
898
973
|
|
899
|
-
if (buildSelect) {
|
900
|
-
buildFilter = $('<select>').appendTo( c.$filters.eq(column) );
|
974
|
+
if ( buildSelect ) {
|
975
|
+
buildFilter = $( '<select>' ).appendTo( c.$filters.eq( column ) );
|
901
976
|
} else {
|
902
977
|
ffxn = ts.getColumnData( table, wo.filter_formatter, column );
|
903
|
-
if (ffxn) {
|
978
|
+
if ( ffxn ) {
|
904
979
|
wo.filter_formatterCount++;
|
905
|
-
buildFilter = ffxn( c.$filters.eq(column), column );
|
980
|
+
buildFilter = ffxn( c.$filters.eq( column ), column );
|
906
981
|
// no element returned, so lets go find it
|
907
|
-
if (buildFilter && buildFilter.length === 0) {
|
908
|
-
buildFilter = c.$filters.eq(column).children('input');
|
982
|
+
if ( buildFilter && buildFilter.length === 0 ) {
|
983
|
+
buildFilter = c.$filters.eq( column ).children( 'input' );
|
909
984
|
}
|
910
985
|
// element not in DOM, so lets attach it
|
911
|
-
if ( buildFilter && (buildFilter.parent().length === 0 ||
|
912
|
-
(buildFilter.parent().length && buildFilter.parent()[0] !== c.$filters[column])) ) {
|
913
|
-
c.$filters.eq(column).append(buildFilter);
|
986
|
+
if ( buildFilter && ( buildFilter.parent().length === 0 ||
|
987
|
+
( buildFilter.parent().length && buildFilter.parent()[0] !== c.$filters[column] ) ) ) {
|
988
|
+
c.$filters.eq( column ).append( buildFilter );
|
914
989
|
}
|
915
990
|
} else {
|
916
|
-
buildFilter = $('<input type="search">').appendTo( c.$filters.eq(column) );
|
991
|
+
buildFilter = $( '<input type="search">' ).appendTo( c.$filters.eq( column ) );
|
917
992
|
}
|
918
|
-
if (buildFilter) {
|
919
|
-
|
993
|
+
if ( buildFilter ) {
|
994
|
+
tmp = $header.data( 'placeholder' ) ||
|
995
|
+
$header.attr( 'data-placeholder' ) ||
|
996
|
+
wo.filter_placeholder.search || '';
|
997
|
+
buildFilter.attr( 'placeholder', tmp );
|
920
998
|
}
|
921
999
|
}
|
922
|
-
if (buildFilter) {
|
1000
|
+
if ( buildFilter ) {
|
923
1001
|
// add filter class name
|
924
|
-
name = ( $.isArray(wo.filter_cssFilter) ?
|
925
|
-
(typeof wo.filter_cssFilter[column] !== 'undefined' ? wo.filter_cssFilter[column] || '' : '') :
|
1002
|
+
name = ( $.isArray( wo.filter_cssFilter ) ?
|
1003
|
+
( typeof wo.filter_cssFilter[column] !== 'undefined' ? wo.filter_cssFilter[column] || '' : '' ) :
|
926
1004
|
wo.filter_cssFilter ) || '';
|
927
|
-
buildFilter.addClass( tscss.filter + ' ' + name ).attr('data-column', column);
|
928
|
-
if (disabled) {
|
929
|
-
buildFilter.attr('placeholder', '').addClass(tscss.filterDisabled)[0].disabled = true;
|
1005
|
+
buildFilter.addClass( tscss.filter + ' ' + name ).attr( 'data-column', column );
|
1006
|
+
if ( disabled ) {
|
1007
|
+
buildFilter.attr( 'placeholder', '' ).addClass( tscss.filterDisabled )[0].disabled = true;
|
930
1008
|
}
|
931
1009
|
}
|
932
1010
|
}
|
933
1011
|
},
|
934
|
-
bindSearch: function(table, $el, internal) {
|
935
|
-
table = $(table)[0];
|
936
|
-
$el = $($el); // allow passing a selector string
|
937
|
-
if (!$el.length) { return; }
|
938
|
-
var
|
1012
|
+
bindSearch: function( table, $el, internal ) {
|
1013
|
+
table = $( table )[0];
|
1014
|
+
$el = $( $el ); // allow passing a selector string
|
1015
|
+
if ( !$el.length ) { return; }
|
1016
|
+
var tmp,
|
1017
|
+
c = table.config,
|
939
1018
|
wo = c.widgetOptions,
|
1019
|
+
namespace = c.namespace + 'filter',
|
940
1020
|
$ext = wo.filter_$externalFilters;
|
941
|
-
if (internal !== true) {
|
1021
|
+
if ( internal !== true ) {
|
942
1022
|
// save anyMatch element
|
943
|
-
|
944
|
-
|
1023
|
+
tmp = wo.filter_anyColumnSelector + ',' + wo.filter_multipleColumnSelector;
|
1024
|
+
wo.filter_$anyMatch = $el.filter( tmp );
|
1025
|
+
if ( $ext && $ext.length ) {
|
945
1026
|
wo.filter_$externalFilters = wo.filter_$externalFilters.add( $el );
|
946
1027
|
} else {
|
947
1028
|
wo.filter_$externalFilters = $el;
|
948
1029
|
}
|
949
|
-
// update values (external filters added after table initialization)
|
950
|
-
ts.setFilters(table, c.$table.data('lastSearch') || [], internal === false);
|
1030
|
+
// update values ( external filters added after table initialization )
|
1031
|
+
ts.setFilters( table, c.$table.data( 'lastSearch' ) || [], internal === false );
|
951
1032
|
}
|
1033
|
+
// unbind events
|
1034
|
+
tmp = ( 'keypress keyup search change '.split( ' ' ).join( namespace + ' ' ) );
|
952
1035
|
$el
|
953
|
-
// use data attribute instead of jQuery data since the head is cloned without including
|
954
|
-
|
955
|
-
.
|
1036
|
+
// use data attribute instead of jQuery data since the head is cloned without including
|
1037
|
+
// the data/binding
|
1038
|
+
.attr( 'data-lastSearchTime', new Date().getTime() )
|
1039
|
+
.unbind( tmp.replace( /\s+/g, ' ' ) )
|
956
1040
|
// include change for select - fixes #473
|
957
|
-
.bind('keyup' +
|
958
|
-
$(this).attr('data-lastSearchTime', new Date().getTime());
|
1041
|
+
.bind( 'keyup' + namespace, function( event ) {
|
1042
|
+
$( this ).attr( 'data-lastSearchTime', new Date().getTime() );
|
959
1043
|
// emulate what webkit does.... escape clears the filter
|
960
|
-
if (event.which === 27) {
|
1044
|
+
if ( event.which === 27 ) {
|
961
1045
|
this.value = '';
|
962
1046
|
// live search
|
963
1047
|
} else if ( wo.filter_liveSearch === false ) {
|
964
1048
|
return;
|
965
|
-
// don't return if the search value is empty (all rows need to be revealed)
|
1049
|
+
// don't return if the search value is empty ( all rows need to be revealed )
|
966
1050
|
} else if ( this.value !== '' && (
|
967
1051
|
// liveSearch can contain a min value length; ignore arrow and meta keys, but allow backspace
|
968
1052
|
( typeof wo.filter_liveSearch === 'number' && this.value.length < wo.filter_liveSearch ) ||
|
969
1053
|
// let return & backspace continue on, but ignore arrows & non-valid characters
|
970
|
-
( event.which !== 13 && event.which !== 8 &&
|
1054
|
+
( event.which !== 13 && event.which !== 8 &&
|
1055
|
+
( event.which < 32 || ( event.which >= 37 && event.which <= 40 ) ) ) ) ) {
|
971
1056
|
return;
|
972
1057
|
}
|
973
1058
|
// change event = no delay; last true flag tells getFilters to skip newest timed input
|
974
1059
|
ts.filter.searching( table, true, true );
|
975
1060
|
})
|
976
|
-
.bind( 'search change keypress '.split(' ').join(
|
977
|
-
var column = $(this).data('column');
|
978
|
-
// don't allow
|
979
|
-
if (event.which === 13 || event.type === 'search' ||
|
1061
|
+
.bind( 'search change keypress '.split( ' ' ).join( namespace + ' ' ), function( event ) {
|
1062
|
+
var column = $( this ).data( 'column' );
|
1063
|
+
// don't allow 'change' event to process if the input value is the same - fixes #685
|
1064
|
+
if ( event.which === 13 || event.type === 'search' ||
|
1065
|
+
event.type === 'change' && this.value !== c.lastSearch[column] ) {
|
980
1066
|
event.preventDefault();
|
981
1067
|
// init search with no delay
|
982
|
-
$(this).attr('data-lastSearchTime', new Date().getTime());
|
1068
|
+
$( this ).attr( 'data-lastSearchTime', new Date().getTime() );
|
983
1069
|
ts.filter.searching( table, false, true );
|
984
1070
|
}
|
985
1071
|
});
|
986
1072
|
},
|
987
|
-
searching: function(table, filter, skipFirst) {
|
1073
|
+
searching: function( table, filter, skipFirst ) {
|
988
1074
|
var wo = table.config.widgetOptions;
|
989
|
-
clearTimeout(wo.searchTimer);
|
990
|
-
if (typeof filter === 'undefined' || filter === true) {
|
1075
|
+
clearTimeout( wo.searchTimer );
|
1076
|
+
if ( typeof filter === 'undefined' || filter === true ) {
|
991
1077
|
// delay filtering
|
992
|
-
wo.searchTimer = setTimeout(function() {
|
993
|
-
ts.filter.checkFilters(table, filter, skipFirst );
|
994
|
-
}, wo.filter_liveSearch ? wo.filter_searchDelay : 10);
|
1078
|
+
wo.searchTimer = setTimeout( function() {
|
1079
|
+
ts.filter.checkFilters( table, filter, skipFirst );
|
1080
|
+
}, wo.filter_liveSearch ? wo.filter_searchDelay : 10 );
|
995
1081
|
} else {
|
996
1082
|
// skip delay
|
997
|
-
ts.filter.checkFilters(table, filter, skipFirst);
|
1083
|
+
ts.filter.checkFilters( table, filter, skipFirst );
|
998
1084
|
}
|
999
1085
|
},
|
1000
|
-
checkFilters: function(table, filter, skipFirst) {
|
1086
|
+
checkFilters: function( table, filter, skipFirst ) {
|
1001
1087
|
var c = table.config,
|
1002
1088
|
wo = c.widgetOptions,
|
1003
|
-
filterArray = $.isArray(filter),
|
1004
|
-
filters = (filterArray) ? filter : ts.getFilters(table, true),
|
1005
|
-
combinedFilters = (filters || []).join(''); // combined filter values
|
1089
|
+
filterArray = $.isArray( filter ),
|
1090
|
+
filters = ( filterArray ) ? filter : ts.getFilters( table, true ),
|
1091
|
+
combinedFilters = ( filters || [] ).join( '' ); // combined filter values
|
1006
1092
|
// prevent errors if delay init is set
|
1007
|
-
if ($.isEmptyObject(c.cache)) {
|
1008
|
-
// update cache if delayInit set & pager has initialized (after user initiates a search)
|
1009
|
-
if (c.delayInit && c.pager && c.pager.initialized) {
|
1010
|
-
c.$table.trigger('updateCache', [function(){
|
1011
|
-
ts.filter.checkFilters(table, false, skipFirst);
|
1012
|
-
}] );
|
1093
|
+
if ( $.isEmptyObject( c.cache ) ) {
|
1094
|
+
// update cache if delayInit set & pager has initialized ( after user initiates a search )
|
1095
|
+
if ( c.delayInit && c.pager && c.pager.initialized ) {
|
1096
|
+
c.$table.trigger( 'updateCache', [ function() {
|
1097
|
+
ts.filter.checkFilters( table, false, skipFirst );
|
1098
|
+
} ] );
|
1013
1099
|
}
|
1014
1100
|
return;
|
1015
1101
|
}
|
1016
1102
|
// add filter array back into inputs
|
1017
|
-
if (filterArray) {
|
1103
|
+
if ( filterArray ) {
|
1018
1104
|
ts.setFilters( table, filters, false, skipFirst !== true );
|
1019
|
-
if (!wo.filter_initialized) { c.lastCombinedFilter = ''; }
|
1105
|
+
if ( !wo.filter_initialized ) { c.lastCombinedFilter = ''; }
|
1020
1106
|
}
|
1021
|
-
if (wo.filter_hideFilters) {
|
1107
|
+
if ( wo.filter_hideFilters ) {
|
1022
1108
|
// show/hide filter row as needed
|
1023
|
-
c.$table
|
1109
|
+
c.$table
|
1110
|
+
.find( '.' + tscss.filterRow )
|
1111
|
+
.trigger( combinedFilters === '' ? 'mouseleave' : 'mouseenter' );
|
1024
1112
|
}
|
1025
1113
|
// return if the last search is the same; but filter === false when updating the search
|
1026
1114
|
// see example-widget-filter.html filter toggle buttons
|
1027
|
-
if (c.lastCombinedFilter === combinedFilters && filter !== false) {
|
1115
|
+
if ( c.lastCombinedFilter === combinedFilters && filter !== false ) {
|
1028
1116
|
return;
|
1029
|
-
} else if (filter === false) {
|
1117
|
+
} else if ( filter === false ) {
|
1030
1118
|
// force filter refresh
|
1031
1119
|
c.lastCombinedFilter = null;
|
1032
1120
|
c.lastSearch = [];
|
1033
1121
|
}
|
1034
|
-
if (wo.filter_initialized) {
|
1035
|
-
|
1122
|
+
if ( wo.filter_initialized ) {
|
1123
|
+
c.$table.trigger( 'filterStart', [filters] );
|
1124
|
+
}
|
1125
|
+
if ( c.showProcessing ) {
|
1036
1126
|
// give it time for the processing icon to kick in
|
1037
|
-
setTimeout(function() {
|
1038
|
-
ts.filter.findRows(table, filters, combinedFilters);
|
1127
|
+
setTimeout( function() {
|
1128
|
+
ts.filter.findRows( table, filters, combinedFilters );
|
1039
1129
|
return false;
|
1040
|
-
}, 30);
|
1130
|
+
}, 30 );
|
1041
1131
|
} else {
|
1042
|
-
ts.filter.findRows(table, filters, combinedFilters);
|
1132
|
+
ts.filter.findRows( table, filters, combinedFilters );
|
1043
1133
|
return false;
|
1044
1134
|
}
|
1045
1135
|
},
|
1046
|
-
hideFilters: function(table, c) {
|
1136
|
+
hideFilters: function( table, c ) {
|
1047
1137
|
var $filterRow, $filterRow2, timer;
|
1048
|
-
$(table)
|
1049
|
-
.find('.' + tscss.filterRow)
|
1050
|
-
.addClass(tscss.filterRowHide)
|
1051
|
-
.bind('mouseenter mouseleave', function(e) {
|
1138
|
+
$( table )
|
1139
|
+
.find( '.' + tscss.filterRow )
|
1140
|
+
.addClass( tscss.filterRowHide )
|
1141
|
+
.bind( 'mouseenter mouseleave', function( e ) {
|
1052
1142
|
// save event object - http://bugs.jquery.com/ticket/12140
|
1053
1143
|
var event = e;
|
1054
|
-
$filterRow = $(this);
|
1055
|
-
clearTimeout(timer);
|
1056
|
-
timer = setTimeout(function() {
|
1057
|
-
if ( /enter|over/.test(event.type) ) {
|
1058
|
-
$filterRow.removeClass(tscss.filterRowHide);
|
1144
|
+
$filterRow = $( this );
|
1145
|
+
clearTimeout( timer );
|
1146
|
+
timer = setTimeout( function() {
|
1147
|
+
if ( /enter|over/.test( event.type ) ) {
|
1148
|
+
$filterRow.removeClass( tscss.filterRowHide );
|
1059
1149
|
} else {
|
1060
1150
|
// don't hide if input has focus
|
1061
|
-
// $(':focus') needs jQuery 1.6+
|
1062
|
-
if ( $(document.activeElement).closest('tr')[0] !== $filterRow[0] ) {
|
1151
|
+
// $( ':focus' ) needs jQuery 1.6+
|
1152
|
+
if ( $( document.activeElement ).closest( 'tr' )[0] !== $filterRow[0] ) {
|
1063
1153
|
// don't hide row if any filter has a value
|
1064
|
-
if (c.lastCombinedFilter === '') {
|
1065
|
-
$filterRow.addClass(tscss.filterRowHide);
|
1154
|
+
if ( c.lastCombinedFilter === '' ) {
|
1155
|
+
$filterRow.addClass( tscss.filterRowHide );
|
1066
1156
|
}
|
1067
1157
|
}
|
1068
1158
|
}
|
1069
|
-
}, 200);
|
1159
|
+
}, 200 );
|
1070
1160
|
})
|
1071
|
-
.find('input, select').bind('focus blur', function(e) {
|
1072
|
-
$filterRow2 = $(this).closest('tr');
|
1073
|
-
clearTimeout(timer);
|
1161
|
+
.find( 'input, select' ).bind( 'focus blur', function( e ) {
|
1162
|
+
$filterRow2 = $( this ).closest( 'tr' );
|
1163
|
+
clearTimeout( timer );
|
1074
1164
|
var event = e;
|
1075
|
-
timer = setTimeout(function() {
|
1165
|
+
timer = setTimeout( function() {
|
1076
1166
|
// don't hide row if any filter has a value
|
1077
|
-
if (ts.getFilters(c.$table).join('') === '') {
|
1078
|
-
$filterRow2
|
1167
|
+
if ( ts.getFilters( c.$table ).join( '' ) === '' ) {
|
1168
|
+
$filterRow2.toggleClass( tscss.filterRowHide, event.type === 'focus' );
|
1079
1169
|
}
|
1080
|
-
}, 200);
|
1170
|
+
}, 200 );
|
1081
1171
|
});
|
1082
1172
|
},
|
1083
|
-
defaultFilter: function(filter, mask){
|
1084
|
-
if (filter === '') { return filter; }
|
1173
|
+
defaultFilter: function( filter, mask ) {
|
1174
|
+
if ( filter === '' ) { return filter; }
|
1085
1175
|
var regex = ts.filter.regex.iQuery,
|
1086
1176
|
maskLen = mask.match( ts.filter.regex.igQuery ).length,
|
1087
|
-
query = maskLen > 1 ? $.trim(filter).split(/\s/) : [ $.trim(filter) ],
|
1177
|
+
query = maskLen > 1 ? $.trim( filter ).split( /\s/ ) : [ $.trim( filter ) ],
|
1088
1178
|
len = query.length - 1,
|
1089
1179
|
indx = 0,
|
1090
1180
|
val = mask;
|
1091
1181
|
if ( len < 1 && maskLen > 1 ) {
|
1092
|
-
// only one
|
1182
|
+
// only one 'word' in query but mask has >1 slots
|
1093
1183
|
query[1] = query[0];
|
1094
1184
|
}
|
1095
1185
|
// replace all {query} with query words...
|
1096
|
-
// if query =
|
1097
|
-
// if query =
|
1098
|
-
while (regex.test(val)) {
|
1099
|
-
val = val.replace(regex, query[indx++] || '');
|
1100
|
-
if (regex.test(val) && indx < len && (query[indx] || '') !== '') {
|
1101
|
-
val = mask.replace(regex, val);
|
1186
|
+
// if query = 'Bob', then convert mask from '!{query}' to '!Bob'
|
1187
|
+
// if query = 'Bob Joe Frank', then convert mask '{q} OR {q}' to 'Bob OR Joe OR Frank'
|
1188
|
+
while ( regex.test( val ) ) {
|
1189
|
+
val = val.replace( regex, query[indx++] || '' );
|
1190
|
+
if ( regex.test( val ) && indx < len && ( query[indx] || '' ) !== '' ) {
|
1191
|
+
val = mask.replace( regex, val );
|
1102
1192
|
}
|
1103
1193
|
}
|
1104
1194
|
return val;
|
1105
1195
|
},
|
1106
1196
|
getLatestSearch: function( $input ) {
|
1107
|
-
if ($input) {
|
1108
|
-
return $input.sort(function(a, b) {
|
1109
|
-
return $(b).attr('data-lastSearchTime') - $(a).attr('data-lastSearchTime');
|
1197
|
+
if ( $input ) {
|
1198
|
+
return $input.sort( function( a, b ) {
|
1199
|
+
return $( b ).attr( 'data-lastSearchTime' ) - $( a ).attr( 'data-lastSearchTime' );
|
1110
1200
|
});
|
1111
1201
|
}
|
1112
1202
|
return $();
|
1113
1203
|
},
|
1114
1204
|
multipleColumns: function( c, $input ) {
|
1115
|
-
// look for multiple columns
|
1205
|
+
// look for multiple columns '1-3,4-6,8' in data-column
|
1116
1206
|
var temp, ranges, range, start, end, singles, i, indx, len,
|
1117
1207
|
wo = c.widgetOptions,
|
1118
|
-
// only target
|
1119
|
-
// & don't target
|
1120
|
-
targets = wo.filter_initialized || !$input.filter(wo.filter_anyColumnSelector).length,
|
1208
|
+
// only target 'all' column inputs on initialization
|
1209
|
+
// & don't target 'all' column inputs if they don't exist
|
1210
|
+
targets = wo.filter_initialized || !$input.filter( wo.filter_anyColumnSelector ).length,
|
1121
1211
|
columns = [],
|
1122
|
-
val = $.trim( ts.filter.getLatestSearch( $input ).attr('data-column') || '' );
|
1212
|
+
val = $.trim( ts.filter.getLatestSearch( $input ).attr( 'data-column' ) || '' );
|
1123
1213
|
// process column range
|
1124
1214
|
if ( targets && /-/.test( val ) ) {
|
1125
1215
|
ranges = val.match( /(\d+)\s*-\s*(\d+)/g );
|
1126
1216
|
len = ranges.length;
|
1127
|
-
for (indx = 0; indx < len; indx++) {
|
1217
|
+
for ( indx = 0; indx < len; indx++ ) {
|
1128
1218
|
range = ranges[indx].split( /\s*-\s*/ );
|
1129
1219
|
start = parseInt( range[0], 10 ) || 0;
|
1130
1220
|
end = parseInt( range[1], 10 ) || ( c.columns - 1 );
|
1131
|
-
if ( start > end ) {
|
1132
|
-
|
1221
|
+
if ( start > end ) {
|
1222
|
+
temp = start; start = end; end = temp; // swap
|
1223
|
+
}
|
1224
|
+
if ( end >= c.columns ) {
|
1225
|
+
end = c.columns - 1;
|
1226
|
+
}
|
1133
1227
|
for ( ; start <= end; start++ ) {
|
1134
|
-
columns.push(start);
|
1228
|
+
columns.push( start );
|
1135
1229
|
}
|
1136
1230
|
// remove processed range from val
|
1137
|
-
val = val.replace( ranges[indx], '' );
|
1231
|
+
val = val.replace( ranges[ indx ], '' );
|
1138
1232
|
}
|
1139
1233
|
}
|
1140
1234
|
// process single columns
|
1141
1235
|
if ( targets && /,/.test( val ) ) {
|
1142
1236
|
singles = val.split( /\s*,\s*/ );
|
1143
1237
|
len = singles.length;
|
1144
|
-
for (i = 0; i < len; i++) {
|
1145
|
-
if (singles[i] !== '') {
|
1146
|
-
indx = parseInt( singles[i], 10 );
|
1238
|
+
for ( i = 0; i < len; i++ ) {
|
1239
|
+
if ( singles[ i ] !== '' ) {
|
1240
|
+
indx = parseInt( singles[ i ], 10 );
|
1147
1241
|
if ( indx < c.columns ) {
|
1148
1242
|
columns.push( indx );
|
1149
1243
|
}
|
@@ -1151,382 +1245,472 @@ ts.filter = {
|
|
1151
1245
|
}
|
1152
1246
|
}
|
1153
1247
|
// return all columns
|
1154
|
-
if (!columns.length) {
|
1248
|
+
if ( !columns.length ) {
|
1155
1249
|
for ( indx = 0; indx < c.columns; indx++ ) {
|
1156
1250
|
columns.push( indx );
|
1157
1251
|
}
|
1158
1252
|
}
|
1159
1253
|
return columns;
|
1160
1254
|
},
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1255
|
+
processRow: function( c, data, vars ) {
|
1256
|
+
var $cell, columnIndex, hasSelect, matches, result, val, filterMatched, excludeMatch,
|
1257
|
+
fxn, ffxn, txt,
|
1258
|
+
regex = ts.filter.regex,
|
1259
|
+
wo = c.widgetOptions,
|
1260
|
+
showRow = true;
|
1261
|
+
data.$cells = data.$row.children();
|
1262
|
+
|
1263
|
+
if ( data.anyMatchFlag ) {
|
1264
|
+
// look for multiple columns '1-3,4-6,8'
|
1265
|
+
columnIndex = ts.filter.multipleColumns( c, wo.filter_$anyMatch );
|
1266
|
+
data.anyMatch = true;
|
1267
|
+
data.rowArray = data.$cells.map( function( i ) {
|
1268
|
+
if ( $.inArray( i, columnIndex ) > -1 ) {
|
1269
|
+
if ( data.parsed[ i ] ) {
|
1270
|
+
txt = data.cacheArray[ i ];
|
1271
|
+
} else {
|
1272
|
+
txt = data.rawArray[ i ];
|
1273
|
+
txt = $.trim( wo.filter_ignoreCase ? txt.toLowerCase() : txt );
|
1274
|
+
if ( c.sortLocaleCompare ) {
|
1275
|
+
txt = ts.replaceAccents( txt );
|
1276
|
+
}
|
1277
|
+
}
|
1278
|
+
return txt;
|
1279
|
+
}
|
1280
|
+
}).get();
|
1281
|
+
data.filter = data.anyMatchFilter;
|
1282
|
+
data.iFilter = data.iAnyMatchFilter;
|
1283
|
+
data.exact = data.rowArray.join( ' ' );
|
1284
|
+
data.iExact = wo.filter_ignoreCase ? data.exact.toLowerCase() : data.exact;
|
1285
|
+
data.cache = data.cacheArray.slice( 0, -1 ).join( ' ' );
|
1286
|
+
filterMatched = null;
|
1287
|
+
matches = null;
|
1288
|
+
for ( ffxn in ts.filter.types ) {
|
1289
|
+
if ( $.inArray( ffxn, vars.noAnyMatch ) < 0 && matches === null ) {
|
1290
|
+
matches = ts.filter.types[ffxn]( c, data );
|
1291
|
+
if ( matches !== null ) {
|
1292
|
+
filterMatched = matches;
|
1293
|
+
}
|
1294
|
+
}
|
1295
|
+
}
|
1296
|
+
if ( filterMatched !== null ) {
|
1297
|
+
showRow = filterMatched;
|
1298
|
+
} else {
|
1299
|
+
if ( wo.filter_startsWith ) {
|
1300
|
+
showRow = false;
|
1301
|
+
columnIndex = c.columns;
|
1302
|
+
while ( !showRow && columnIndex > 0 ) {
|
1303
|
+
columnIndex--;
|
1304
|
+
showRow = showRow || data.rowArray[ columnIndex ].indexOf( data.iFilter ) === 0;
|
1305
|
+
}
|
1306
|
+
} else {
|
1307
|
+
showRow = ( data.iExact + data.childRowText ).indexOf( data.iFilter ) >= 0;
|
1308
|
+
}
|
1309
|
+
}
|
1310
|
+
data.anyMatch = false;
|
1311
|
+
// no other filters to process
|
1312
|
+
if ( data.filters.join( '' ) === data.filter ) {
|
1313
|
+
return showRow;
|
1314
|
+
}
|
1315
|
+
}
|
1316
|
+
|
1317
|
+
for ( columnIndex = 0; columnIndex < c.columns; columnIndex++ ) {
|
1318
|
+
data.filter = data.filters[ columnIndex ];
|
1319
|
+
data.index = columnIndex;
|
1320
|
+
|
1321
|
+
// filter types to exclude, per column
|
1322
|
+
excludeMatch = vars.excludeFilter[ columnIndex ];
|
1323
|
+
|
1324
|
+
// ignore if filter is empty or disabled
|
1325
|
+
if ( data.filter ) {
|
1326
|
+
data.cache = data.cacheArray[ columnIndex ];
|
1327
|
+
// check if column data should be from the cell or from parsed data
|
1328
|
+
if ( wo.filter_useParsedData || data.parsed[ columnIndex ] ) {
|
1329
|
+
data.exact = data.cache;
|
1330
|
+
} else {
|
1331
|
+
result = data.rawArray[ columnIndex ] || '';
|
1332
|
+
data.exact = c.sortLocaleCompare ? ts.replaceAccents( result ) : result; // issue #405
|
1333
|
+
}
|
1334
|
+
data.iExact = !regex.type.test( typeof data.exact ) && wo.filter_ignoreCase ?
|
1335
|
+
data.exact.toLowerCase() : data.exact;
|
1336
|
+
result = showRow; // if showRow is true, show that row
|
1337
|
+
|
1338
|
+
// in case select filter option has a different value vs text 'a - z|A through Z'
|
1339
|
+
ffxn = wo.filter_columnFilters ?
|
1340
|
+
c.$filters.add( c.$externalFilters )
|
1341
|
+
.filter( '[data-column="'+ columnIndex + '"]' )
|
1342
|
+
.find( 'select option:selected' )
|
1343
|
+
.attr( 'data-function-name' ) || '' : '';
|
1344
|
+
// replace accents - see #357
|
1345
|
+
if ( c.sortLocaleCompare ) {
|
1346
|
+
data.filter = ts.replaceAccents( data.filter );
|
1347
|
+
}
|
1348
|
+
|
1349
|
+
val = true;
|
1350
|
+
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultColFilter[ columnIndex ] ) ) {
|
1351
|
+
data.filter = ts.filter.defaultFilter( data.filter, vars.defaultColFilter[ columnIndex ] );
|
1352
|
+
// val is used to indicate that a filter select is using a default filter;
|
1353
|
+
// so we override the exact & partial matches
|
1354
|
+
val = false;
|
1355
|
+
}
|
1356
|
+
// data.iFilter = case insensitive ( if wo.filter_ignoreCase is true ),
|
1357
|
+
// data.filter = case sensitive
|
1358
|
+
data.iFilter = wo.filter_ignoreCase ? ( data.filter || '' ).toLowerCase() : data.filter;
|
1359
|
+
fxn = vars.functions[ columnIndex ];
|
1360
|
+
$cell = c.$headerIndexed[ columnIndex ];
|
1361
|
+
hasSelect = $cell.hasClass( 'filter-select' );
|
1362
|
+
filterMatched = null;
|
1363
|
+
if ( fxn || ( hasSelect && val ) ) {
|
1364
|
+
if ( fxn === true || hasSelect ) {
|
1365
|
+
// default selector uses exact match unless 'filter-match' class is found
|
1366
|
+
filterMatched = $cell.hasClass( 'filter-match' ) ?
|
1367
|
+
data.iExact.search( data.iFilter ) >= 0 :
|
1368
|
+
data.filter === data.exact;
|
1369
|
+
} else if ( typeof fxn === 'function' ) {
|
1370
|
+
// filter callback( exact cell content, parser normalized content,
|
1371
|
+
// filter input value, column index, jQuery row object )
|
1372
|
+
filterMatched = fxn( data.exact, data.cache, data.filter, columnIndex, data.$row, c, data );
|
1373
|
+
} else if ( typeof fxn[ ffxn || data.filter ] === 'function' ) {
|
1374
|
+
// selector option function
|
1375
|
+
txt = ffxn || data.filter;
|
1376
|
+
filterMatched =
|
1377
|
+
fxn[ txt ]( data.exact, data.cache, data.filter, columnIndex, data.$row, c, data );
|
1378
|
+
}
|
1379
|
+
}
|
1380
|
+
if ( filterMatched === null ) {
|
1381
|
+
// cycle through the different filters
|
1382
|
+
// filters return a boolean or null if nothing matches
|
1383
|
+
matches = null;
|
1384
|
+
for ( ffxn in ts.filter.types ) {
|
1385
|
+
if ( $.inArray( ffxn, excludeMatch ) < 0 && matches === null ) {
|
1386
|
+
matches = ts.filter.types[ ffxn ]( c, data );
|
1387
|
+
if ( matches !== null ) {
|
1388
|
+
filterMatched = matches;
|
1389
|
+
}
|
1390
|
+
}
|
1391
|
+
}
|
1392
|
+
if ( filterMatched !== null ) {
|
1393
|
+
result = filterMatched;
|
1394
|
+
// Look for match, and add child row data for matching
|
1395
|
+
} else {
|
1396
|
+
txt = ( data.iExact + data.childRowText )
|
1397
|
+
.indexOf( ts.filter.parseFilter( c, data.iFilter, columnIndex, data.parsed[ columnIndex ] ) );
|
1398
|
+
result = ( ( !wo.filter_startsWith && txt >= 0 ) || ( wo.filter_startsWith && txt === 0 ) );
|
1399
|
+
}
|
1400
|
+
} else {
|
1401
|
+
result = filterMatched;
|
1402
|
+
}
|
1403
|
+
showRow = ( result ) ? showRow : false;
|
1404
|
+
}
|
1405
|
+
}
|
1406
|
+
return showRow;
|
1407
|
+
},
|
1408
|
+
findRows: function( table, filters, combinedFilters ) {
|
1409
|
+
if ( table.config.lastCombinedFilter === combinedFilters ||
|
1410
|
+
!table.config.widgetOptions.filter_initialized ) {
|
1411
|
+
return;
|
1412
|
+
}
|
1413
|
+
var len, norm_rows, rowData, $rows, rowIndex, tbodyIndex, $tbody, columnIndex,
|
1414
|
+
isChild, childRow, lastSearch, showRow, time, val, indx,
|
1415
|
+
notFiltered, searchFiltered, query, injected, res, id, txt,
|
1416
|
+
storedFilters = $.extend( [], filters ),
|
1167
1417
|
regex = ts.filter.regex,
|
1168
1418
|
c = table.config,
|
1169
1419
|
wo = c.widgetOptions,
|
1170
1420
|
// data object passed to filters; anyMatch is a flag for the filters
|
1171
|
-
data = {
|
1172
|
-
|
1173
|
-
|
1421
|
+
data = {
|
1422
|
+
anyMatch: false,
|
1423
|
+
filters: filters,
|
1424
|
+
// regex filter type cache
|
1425
|
+
filter_regexCache : [],
|
1426
|
+
},
|
1427
|
+
vars = {
|
1428
|
+
// anyMatch really screws up with these types of filters
|
1429
|
+
noAnyMatch: [ 'range', 'notMatch', 'operators' ],
|
1430
|
+
// cache filter variables that use ts.getColumnData in the main loop
|
1431
|
+
functions : [],
|
1432
|
+
excludeFilter : [],
|
1433
|
+
defaultColFilter : [],
|
1434
|
+
defaultAnyFilter : ts.getColumnData( table, wo.filter_defaultFilter, c.columns, true ) || ''
|
1435
|
+
};
|
1174
1436
|
|
1175
1437
|
// parse columns after formatter, in case the class is added at that point
|
1176
|
-
data.parsed = c.$headers.map(function(columnIndex) {
|
1177
|
-
return c.parsers && c.parsers[columnIndex] &&
|
1178
|
-
//
|
1179
|
-
|
1180
|
-
|
1438
|
+
data.parsed = c.$headers.map( function( columnIndex ) {
|
1439
|
+
return c.parsers && c.parsers[ columnIndex ] &&
|
1440
|
+
// force parsing if parser type is numeric
|
1441
|
+
( c.parsers[ columnIndex ].parsed || c.parsers[ columnIndex ].type === 'numeric' ) ||
|
1442
|
+
// getData won't return 'parsed' if other 'filter-' class names exist
|
1443
|
+
// ( e.g. <th class="filter-select filter-parsed"> )
|
1444
|
+
ts.getData && ts.getData( c.$headerIndexed[ columnIndex ],
|
1445
|
+
ts.getColumnData( table, c.headers, columnIndex ), 'filter' ) === 'parsed' ||
|
1446
|
+
$( this ).hasClass( 'filter-parsed' );
|
1181
1447
|
}).get();
|
1182
1448
|
|
1183
|
-
// cache filter variables that use ts.getColumnData in the main loop
|
1184
|
-
wo.filter_indexed = {
|
1185
|
-
functions : [],
|
1186
|
-
excludeFilter : [],
|
1187
|
-
defaultColFilter : [],
|
1188
|
-
defaultAnyFilter : ts.getColumnData( table, wo.filter_defaultFilter, c.columns, true ) || ''
|
1189
|
-
};
|
1190
1449
|
for ( columnIndex = 0; columnIndex < c.columns; columnIndex++ ) {
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1450
|
+
vars.functions[ columnIndex ] =
|
1451
|
+
ts.getColumnData( table, wo.filter_functions, columnIndex );
|
1452
|
+
vars.defaultColFilter[ columnIndex ] =
|
1453
|
+
ts.getColumnData( table, wo.filter_defaultFilter, columnIndex ) || '';
|
1454
|
+
vars.excludeFilter[ columnIndex ] =
|
1455
|
+
( ts.getColumnData( table, wo.filter_excludeFilter, columnIndex, true ) || '' ).split( /\s+/ );
|
1194
1456
|
}
|
1195
1457
|
|
1196
|
-
if (c.debug) {
|
1197
|
-
ts.log('Filter: Starting filter widget search', filters);
|
1458
|
+
if ( c.debug ) {
|
1459
|
+
ts.log( 'Filter: Starting filter widget search', filters );
|
1198
1460
|
time = new Date();
|
1199
1461
|
}
|
1200
1462
|
// filtered rows count
|
1201
1463
|
c.filteredRows = 0;
|
1202
1464
|
c.totalRows = 0;
|
1203
1465
|
// combindedFilters are undefined on init
|
1204
|
-
combinedFilters = (
|
1466
|
+
combinedFilters = ( storedFilters || [] ).join( '' );
|
1205
1467
|
|
1206
|
-
for (tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++ ) {
|
1207
|
-
$tbody = ts.processTbody(table, c.$tbodies.eq(tbodyIndex), true);
|
1208
|
-
// skip child rows & widget added (removable) rows - fixes #448 thanks to @hempel!
|
1209
|
-
// $rows = $tbody.children('tr').not(c.selectorRemove);
|
1468
|
+
for ( tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++ ) {
|
1469
|
+
$tbody = ts.processTbody( table, c.$tbodies.eq( tbodyIndex ), true );
|
1470
|
+
// skip child rows & widget added ( removable ) rows - fixes #448 thanks to @hempel!
|
1471
|
+
// $rows = $tbody.children( 'tr' ).not( c.selectorRemove );
|
1210
1472
|
columnIndex = c.columns;
|
1211
1473
|
// convert stored rows into a jQuery object
|
1212
|
-
norm_rows = c.cache[tbodyIndex].normalized;
|
1213
|
-
$rows = $( $.map(norm_rows, function(
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1474
|
+
norm_rows = c.cache[ tbodyIndex ].normalized;
|
1475
|
+
$rows = $( $.map( norm_rows, function( el ) {
|
1476
|
+
return el[ columnIndex ].$row.get();
|
1477
|
+
}) );
|
1478
|
+
|
1479
|
+
if ( combinedFilters === '' || wo.filter_serversideFiltering ) {
|
1480
|
+
$rows
|
1481
|
+
.removeClass( wo.filter_filteredRow )
|
1482
|
+
.not( '.' + c.cssChildRow )
|
1483
|
+
.css( 'display', '' );
|
1217
1484
|
} else {
|
1218
1485
|
// filter out child rows
|
1219
|
-
$rows = $rows.not('.' + c.cssChildRow);
|
1486
|
+
$rows = $rows.not( '.' + c.cssChildRow );
|
1220
1487
|
len = $rows.length;
|
1221
1488
|
|
1222
|
-
if ( (wo.filter_$anyMatch && wo.filter_$anyMatch.length) ||
|
1489
|
+
if ( ( wo.filter_$anyMatch && wo.filter_$anyMatch.length ) ||
|
1490
|
+
typeof filters[c.columns] !== 'undefined' ) {
|
1223
1491
|
data.anyMatchFlag = true;
|
1224
|
-
data.anyMatchFilter =
|
1225
|
-
|
1492
|
+
data.anyMatchFilter = '' + (
|
1493
|
+
filters[ c.columns ] ||
|
1494
|
+
wo.filter_$anyMatch && ts.filter.getLatestSearch( wo.filter_$anyMatch ).val() ||
|
1495
|
+
''
|
1496
|
+
);
|
1497
|
+
if ( wo.filter_columnAnyMatch ) {
|
1226
1498
|
// specific columns search
|
1227
|
-
query = data.anyMatchFilter.split(
|
1499
|
+
query = data.anyMatchFilter.split( regex.andSplit );
|
1228
1500
|
injected = false;
|
1229
|
-
for (indx = 0; indx < query.length; indx++) {
|
1230
|
-
res = query[indx].split(':');
|
1501
|
+
for ( indx = 0; indx < query.length; indx++ ) {
|
1502
|
+
res = query[ indx ].split( ':' );
|
1231
1503
|
if ( res.length > 1 ) {
|
1232
1504
|
// make the column a one-based index ( non-developers start counting from one :P )
|
1233
1505
|
id = parseInt( res[0], 10 ) - 1;
|
1234
1506
|
if ( id >= 0 && id < c.columns ) { // if id is an integer
|
1235
|
-
filters[id] = res[1];
|
1236
|
-
query.splice(indx, 1);
|
1507
|
+
filters[ id ] = res[1];
|
1508
|
+
query.splice( indx, 1 );
|
1237
1509
|
indx--;
|
1238
1510
|
injected = true;
|
1239
1511
|
}
|
1240
1512
|
}
|
1241
1513
|
}
|
1242
|
-
if (injected) {
|
1243
|
-
data.anyMatchFilter = query.join(' && ');
|
1514
|
+
if ( injected ) {
|
1515
|
+
data.anyMatchFilter = query.join( ' && ' );
|
1244
1516
|
}
|
1245
1517
|
}
|
1246
1518
|
}
|
1247
1519
|
|
1248
1520
|
// optimize searching only through already filtered rows - see #313
|
1249
1521
|
searchFiltered = wo.filter_searchFiltered;
|
1250
|
-
lastSearch = c.lastSearch || c.$table.data('lastSearch') || [];
|
1251
|
-
if (searchFiltered) {
|
1252
|
-
// cycle through all filters; include last (columnIndex + 1 = match any column). Fixes #669
|
1253
|
-
for (indx = 0; indx < columnIndex + 1; indx++) {
|
1522
|
+
lastSearch = c.lastSearch || c.$table.data( 'lastSearch' ) || [];
|
1523
|
+
if ( searchFiltered ) {
|
1524
|
+
// cycle through all filters; include last ( columnIndex + 1 = match any column ). Fixes #669
|
1525
|
+
for ( indx = 0; indx < columnIndex + 1; indx++ ) {
|
1254
1526
|
val = filters[indx] || '';
|
1255
1527
|
// break out of loop if we've already determined not to search filtered rows
|
1256
|
-
if (!searchFiltered) { indx = columnIndex; }
|
1528
|
+
if ( !searchFiltered ) { indx = columnIndex; }
|
1257
1529
|
// search already filtered rows if...
|
1258
1530
|
searchFiltered = searchFiltered && lastSearch.length &&
|
1259
1531
|
// there are no changes from beginning of filter
|
1260
|
-
val.indexOf(lastSearch[indx] || '') === 0 &&
|
1261
|
-
// if there is NOT a logical
|
1262
|
-
!regex.alreadyFiltered.test(val) &&
|
1263
|
-
// if we are not doing exact matches, using
|
1264
|
-
!/[=\"\|!]/.test(val) &&
|
1265
|
-
// don't search only filtered if the value is negative
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1532
|
+
val.indexOf( lastSearch[indx] || '' ) === 0 &&
|
1533
|
+
// if there is NOT a logical 'or', or range ( 'to' or '-' ) in the string
|
1534
|
+
!regex.alreadyFiltered.test( val ) &&
|
1535
|
+
// if we are not doing exact matches, using '|' ( logical or ) or not '!'
|
1536
|
+
!/[=\"\|!]/.test( val ) &&
|
1537
|
+
// don't search only filtered if the value is negative
|
1538
|
+
// ( '> -10' => '> -100' will ignore hidden rows )
|
1539
|
+
!( /(>=?\s*-\d)/.test( val ) || /(<=?\s*\d)/.test( val ) ) &&
|
1540
|
+
// if filtering using a select without a 'filter-match' class ( exact match ) - fixes #593
|
1541
|
+
!( val !== '' && c.$filters && c.$filters.eq( indx ).find( 'select' ).length &&
|
1542
|
+
!c.$headerIndexed[indx].hasClass( 'filter-match' ) );
|
1269
1543
|
}
|
1270
1544
|
}
|
1271
|
-
notFiltered = $rows.not('.' + wo.filter_filteredRow).length;
|
1545
|
+
notFiltered = $rows.not( '.' + wo.filter_filteredRow ).length;
|
1272
1546
|
// can't search when all rows are hidden - this happens when looking for exact matches
|
1273
|
-
if (searchFiltered && notFiltered === 0) { searchFiltered = false; }
|
1274
|
-
if (c.debug) {
|
1275
|
-
ts.log( 'Filter: Searching through ' +
|
1547
|
+
if ( searchFiltered && notFiltered === 0 ) { searchFiltered = false; }
|
1548
|
+
if ( c.debug ) {
|
1549
|
+
ts.log( 'Filter: Searching through ' +
|
1550
|
+
( searchFiltered && notFiltered < len ? notFiltered : 'all' ) + ' rows' );
|
1276
1551
|
}
|
1277
|
-
if (data.anyMatchFlag) {
|
1278
|
-
if (c.sortLocaleCompare) {
|
1552
|
+
if ( data.anyMatchFlag ) {
|
1553
|
+
if ( c.sortLocaleCompare ) {
|
1279
1554
|
// replace accents
|
1280
|
-
data.anyMatchFilter = ts.replaceAccents(data.anyMatchFilter);
|
1555
|
+
data.anyMatchFilter = ts.replaceAccents( data.anyMatchFilter );
|
1281
1556
|
}
|
1282
|
-
if ( wo.filter_defaultFilter && regex.iQuery.test(
|
1283
|
-
data.anyMatchFilter = ts.filter.defaultFilter( data.anyMatchFilter,
|
1557
|
+
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultAnyFilter ) ) {
|
1558
|
+
data.anyMatchFilter = ts.filter.defaultFilter( data.anyMatchFilter, vars.defaultAnyFilter );
|
1284
1559
|
// clear search filtered flag because default filters are not saved to the last search
|
1285
1560
|
searchFiltered = false;
|
1286
1561
|
}
|
1287
1562
|
// make iAnyMatchFilter lowercase unless both filter widget & core ignoreCase options are true
|
1288
1563
|
// when c.ignoreCase is true, the cache contains all lower case data
|
1289
|
-
data.iAnyMatchFilter = !(wo.filter_ignoreCase && c.ignoreCase) ?
|
1564
|
+
data.iAnyMatchFilter = !( wo.filter_ignoreCase && c.ignoreCase ) ?
|
1565
|
+
data.anyMatchFilter :
|
1566
|
+
data.anyMatchFilter.toLowerCase();
|
1290
1567
|
}
|
1291
1568
|
|
1292
1569
|
// loop through the rows
|
1293
|
-
for (rowIndex = 0; rowIndex < len; rowIndex++) {
|
1570
|
+
for ( rowIndex = 0; rowIndex < len; rowIndex++ ) {
|
1294
1571
|
|
1295
|
-
|
1296
|
-
|
1297
|
-
|
1572
|
+
txt = $rows[ rowIndex ].className;
|
1573
|
+
// the first row can never be a child row
|
1574
|
+
isChild = rowIndex && regex.child.test( txt );
|
1298
1575
|
// skip child rows & already filtered rows
|
1299
|
-
if (
|
1300
|
-
|
1301
|
-
// *** nextAll/nextUntil not supported by Zepto! ***
|
1302
|
-
childRow = $rows.eq(rowIndex).nextUntil('tr:not(.' + c.cssChildRow + ')');
|
1303
|
-
// so, if "table.config.widgetOptions.filter_childRows" is true and there is
|
1304
|
-
// a match anywhere in the child row, then it will make the row visible
|
1305
|
-
// checked here so the option can be changed dynamically
|
1306
|
-
data.childRowText = (childRow.length && wo.filter_childRows) ? childRow.text() : '';
|
1307
|
-
data.childRowText = wo.filter_ignoreCase ? data.childRowText.toLocaleLowerCase() : data.childRowText;
|
1308
|
-
$cells = $rows.eq(rowIndex).children();
|
1309
|
-
if (data.anyMatchFlag) {
|
1310
|
-
// look for multiple columns "1-3,4-6,8"
|
1311
|
-
columnIndex = ts.filter.multipleColumns( c, wo.filter_$anyMatch );
|
1312
|
-
data.anyMatch = true;
|
1313
|
-
data.rowArray = $cells.map(function(i){
|
1314
|
-
if ( $.inArray(i, columnIndex) > -1 ) {
|
1315
|
-
var txt;
|
1316
|
-
if (data.parsed[i]) {
|
1317
|
-
txt = data.cacheArray[i];
|
1318
|
-
} else {
|
1319
|
-
txt = this ? this.getAttribute( c.textAttribute ) || this.textContent || $(this).text() : '';
|
1320
|
-
txt = $.trim( wo.filter_ignoreCase ? txt.toLowerCase() : txt );
|
1321
|
-
if (c.sortLocaleCompare) {
|
1322
|
-
txt = ts.replaceAccents(txt);
|
1323
|
-
}
|
1324
|
-
}
|
1325
|
-
return txt;
|
1326
|
-
}
|
1327
|
-
}).get();
|
1328
|
-
data.filter = data.anyMatchFilter;
|
1329
|
-
data.iFilter = data.iAnyMatchFilter;
|
1330
|
-
data.exact = data.rowArray.join(' ');
|
1331
|
-
data.iExact = wo.filter_ignoreCase ? data.exact.toLowerCase() : data.exact;
|
1332
|
-
data.cache = data.cacheArray.slice(0,-1).join(' ');
|
1333
|
-
filterMatched = null;
|
1334
|
-
$.each(ts.filter.types, function(type, typeFunction) {
|
1335
|
-
if ($.inArray(type, noAnyMatch) < 0) {
|
1336
|
-
matches = typeFunction( c, data );
|
1337
|
-
if (matches !== null) {
|
1338
|
-
filterMatched = matches;
|
1339
|
-
return false;
|
1340
|
-
}
|
1341
|
-
}
|
1342
|
-
});
|
1343
|
-
if (filterMatched !== null) {
|
1344
|
-
showRow = filterMatched;
|
1345
|
-
} else {
|
1346
|
-
if (wo.filter_startsWith) {
|
1347
|
-
showRow = false;
|
1348
|
-
columnIndex = c.columns;
|
1349
|
-
while (!showRow && columnIndex > 0) {
|
1350
|
-
columnIndex--;
|
1351
|
-
showRow = showRow || data.rowArray[columnIndex].indexOf(data.iFilter) === 0;
|
1352
|
-
}
|
1353
|
-
} else {
|
1354
|
-
showRow = (data.iExact + data.childRowText).indexOf(data.iFilter) >= 0;
|
1355
|
-
}
|
1356
|
-
}
|
1357
|
-
data.anyMatch = false;
|
1576
|
+
if ( isChild || ( searchFiltered && regex.filtered.test( txt ) ) ) {
|
1577
|
+
continue;
|
1358
1578
|
}
|
1359
1579
|
|
1360
|
-
|
1361
|
-
|
1362
|
-
|
1363
|
-
|
1364
|
-
|
1365
|
-
|
1366
|
-
|
1367
|
-
|
1368
|
-
|
1369
|
-
|
1370
|
-
|
1371
|
-
|
1372
|
-
|
1373
|
-
|
1374
|
-
|
1375
|
-
|
1376
|
-
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1380
|
-
|
1381
|
-
// in case select filter option has a different value vs text "a - z|A through Z"
|
1382
|
-
ffxn = wo.filter_columnFilters ?
|
1383
|
-
c.$filters.add(c.$externalFilters).filter('[data-column="'+ columnIndex + '"]').find('select option:selected').attr('data-function-name') || '' : '';
|
1384
|
-
// replace accents - see #357
|
1385
|
-
if (c.sortLocaleCompare) {
|
1386
|
-
data.filter = ts.replaceAccents(data.filter);
|
1387
|
-
}
|
1580
|
+
data.$row = $rows.eq( rowIndex );
|
1581
|
+
data.cacheArray = norm_rows[ rowIndex ];
|
1582
|
+
rowData = data.cacheArray[ c.columns ];
|
1583
|
+
data.rawArray = rowData.raw;
|
1584
|
+
data.childRowText = '';
|
1585
|
+
|
1586
|
+
if ( !wo.filter_childByColumn ) {
|
1587
|
+
txt = '';
|
1588
|
+
// child row cached text
|
1589
|
+
childRow = rowData.child;
|
1590
|
+
// so, if 'table.config.widgetOptions.filter_childRows' is true and there is
|
1591
|
+
// a match anywhere in the child row, then it will make the row visible
|
1592
|
+
// checked here so the option can be changed dynamically
|
1593
|
+
for ( indx = 0; indx < childRow.length; indx++ ) {
|
1594
|
+
txt += ' ' + childRow[indx].join( '' ) || '';
|
1595
|
+
}
|
1596
|
+
data.childRowText = wo.filter_childRows ?
|
1597
|
+
( wo.filter_ignoreCase ? txt.toLowerCase() : txt ) :
|
1598
|
+
'';
|
1599
|
+
}
|
1388
1600
|
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
1392
|
-
|
1393
|
-
|
1601
|
+
showRow = ts.filter.processRow( c, data, vars );
|
1602
|
+
childRow = rowData.$row.filter( ':gt( 0 )' );
|
1603
|
+
|
1604
|
+
if ( wo.filter_childRows && childRow.length ) {
|
1605
|
+
if ( wo.filter_childByColumn ) {
|
1606
|
+
// cycle through each child row
|
1607
|
+
for ( indx = 0; indx < childRow.length; indx++ ) {
|
1608
|
+
data.$row = childRow.eq( indx );
|
1609
|
+
data.cacheArray = rowData.child[ indx ];
|
1610
|
+
data.rawArray = data.cacheArray;
|
1611
|
+
// use OR comparison on child rows
|
1612
|
+
showRow = showRow || ts.filter.processRow( c, data, vars );
|
1394
1613
|
}
|
1395
|
-
// data.iFilter = case insensitive (if wo.filter_ignoreCase is true), data.filter = case sensitive
|
1396
|
-
data.iFilter = wo.filter_ignoreCase ? (data.filter || '').toLocaleLowerCase() : data.filter;
|
1397
|
-
fxn = wo.filter_indexed.functions[ columnIndex ];
|
1398
|
-
$cell = c.$headerIndexed[columnIndex];
|
1399
|
-
hasSelect = $cell.hasClass('filter-select');
|
1400
|
-
filterMatched = null;
|
1401
|
-
if ( fxn || ( hasSelect && val ) ) {
|
1402
|
-
if (fxn === true || hasSelect) {
|
1403
|
-
// default selector uses exact match unless "filter-match" class is found
|
1404
|
-
filterMatched = ($cell.hasClass('filter-match')) ? data.iExact.search(data.iFilter) >= 0 : data.filter === data.exact;
|
1405
|
-
} else if (typeof fxn === 'function') {
|
1406
|
-
// filter callback( exact cell content, parser normalized content, filter input value, column index, jQuery row object )
|
1407
|
-
filterMatched = fxn(data.exact, data.cache, data.filter, columnIndex, $rows.eq(rowIndex), c);
|
1408
|
-
} else if (typeof fxn[ffxn || data.filter] === 'function') {
|
1409
|
-
// selector option function
|
1410
|
-
filterMatched = fxn[ffxn || data.filter](data.exact, data.cache, data.filter, columnIndex, $rows.eq(rowIndex), c);
|
1411
|
-
}
|
1412
|
-
}
|
1413
|
-
if (filterMatched === null) {
|
1414
|
-
// cycle through the different filters
|
1415
|
-
// filters return a boolean or null if nothing matches
|
1416
|
-
$.each(ts.filter.types, function(type, typeFunction) {
|
1417
|
-
if ($.inArray(type, excludeMatch) < 0) {
|
1418
|
-
matches = typeFunction( c, data );
|
1419
|
-
if (matches !== null) {
|
1420
|
-
filterMatched = matches;
|
1421
|
-
return false;
|
1422
|
-
}
|
1423
|
-
}
|
1424
|
-
});
|
1425
|
-
if (filterMatched !== null) {
|
1426
|
-
result = filterMatched;
|
1427
|
-
// Look for match, and add child row data for matching
|
1428
|
-
} else {
|
1429
|
-
data.exact = (data.iExact + data.childRowText).indexOf( ts.filter.parseFilter(c, data.iFilter, columnIndex, data.parsed[columnIndex]) );
|
1430
|
-
result = ( (!wo.filter_startsWith && data.exact >= 0) || (wo.filter_startsWith && data.exact === 0) );
|
1431
|
-
}
|
1432
|
-
} else {
|
1433
|
-
result = filterMatched;
|
1434
|
-
}
|
1435
|
-
showRow = (result) ? showRow : false;
|
1436
1614
|
}
|
1615
|
+
childRow.toggleClass( wo.filter_filteredRow, !showRow );
|
1437
1616
|
}
|
1438
|
-
|
1439
|
-
|
1617
|
+
|
1618
|
+
rowData.$row
|
1619
|
+
.toggleClass( wo.filter_filteredRow, !showRow )[0]
|
1440
1620
|
.display = showRow ? '' : 'none';
|
1441
|
-
if (childRow.length) {
|
1442
|
-
childRow.toggleClass(wo.filter_filteredRow, !showRow);
|
1443
|
-
}
|
1444
1621
|
}
|
1445
1622
|
}
|
1446
|
-
c.filteredRows += $rows.not('.' + wo.filter_filteredRow).length;
|
1623
|
+
c.filteredRows += $rows.not( '.' + wo.filter_filteredRow ).length;
|
1447
1624
|
c.totalRows += $rows.length;
|
1448
|
-
ts.processTbody(table, $tbody, false);
|
1625
|
+
ts.processTbody( table, $tbody, false );
|
1449
1626
|
}
|
1450
1627
|
c.lastCombinedFilter = combinedFilters; // save last search
|
1451
|
-
|
1452
|
-
c
|
1453
|
-
|
1454
|
-
|
1628
|
+
// don't save 'filters' directly since it may have altered ( AnyMatch column searches )
|
1629
|
+
c.lastSearch = storedFilters;
|
1630
|
+
c.$table.data( 'lastSearch', storedFilters );
|
1631
|
+
if ( wo.filter_saveFilters && ts.storage ) {
|
1632
|
+
ts.storage( table, 'tablesorter-filters', storedFilters );
|
1455
1633
|
}
|
1456
|
-
if (c.debug) {
|
1457
|
-
ts.benchmark(
|
1634
|
+
if ( c.debug ) {
|
1635
|
+
ts.benchmark( 'Completed filter widget search', time );
|
1636
|
+
}
|
1637
|
+
if ( wo.filter_initialized ) {
|
1638
|
+
c.$table.trigger( 'filterEnd', c );
|
1458
1639
|
}
|
1459
|
-
|
1460
|
-
|
1461
|
-
|
1462
|
-
}, 0);
|
1640
|
+
setTimeout( function() {
|
1641
|
+
c.$table.trigger( 'applyWidgets' ); // make sure zebra widget is applied
|
1642
|
+
}, 0 );
|
1463
1643
|
},
|
1464
|
-
getOptionSource: function(table, column, onlyAvail) {
|
1465
|
-
table = $(table)[0];
|
1644
|
+
getOptionSource: function( table, column, onlyAvail ) {
|
1645
|
+
table = $( table )[0];
|
1466
1646
|
var cts, indx, len,
|
1467
1647
|
c = table.config,
|
1468
1648
|
wo = c.widgetOptions,
|
1469
1649
|
parsed = [],
|
1470
1650
|
arry = false,
|
1471
1651
|
source = wo.filter_selectSource,
|
1472
|
-
last = c.$table.data('lastSearch') || [],
|
1473
|
-
fxn = $.isFunction(source) ? true : ts.getColumnData( table, source, column );
|
1652
|
+
last = c.$table.data( 'lastSearch' ) || [],
|
1653
|
+
fxn = $.isFunction( source ) ? true : ts.getColumnData( table, source, column );
|
1474
1654
|
|
1475
|
-
if (onlyAvail && last[column] !== '') {
|
1655
|
+
if ( onlyAvail && last[column] !== '' ) {
|
1476
1656
|
onlyAvail = false;
|
1477
1657
|
}
|
1478
1658
|
|
1479
1659
|
// filter select source option
|
1480
|
-
if (fxn === true) {
|
1660
|
+
if ( fxn === true ) {
|
1481
1661
|
// OVERALL source
|
1482
|
-
arry = source(table, column, onlyAvail);
|
1483
|
-
} else if ( fxn instanceof $ || ($.type(fxn) === 'string' && fxn.indexOf('</option>') >= 0) ) {
|
1662
|
+
arry = source( table, column, onlyAvail );
|
1663
|
+
} else if ( fxn instanceof $ || ( $.type( fxn ) === 'string' && fxn.indexOf( '</option>' ) >= 0 ) ) {
|
1484
1664
|
// selectSource is a jQuery object or string of options
|
1485
1665
|
return fxn;
|
1486
|
-
} else if ($.isArray(fxn)) {
|
1666
|
+
} else if ( $.isArray( fxn ) ) {
|
1487
1667
|
arry = fxn;
|
1488
|
-
} else if ($.type(source) === 'object' && fxn) {
|
1668
|
+
} else if ( $.type( source ) === 'object' && fxn ) {
|
1489
1669
|
// custom select source function for a SPECIFIC COLUMN
|
1490
|
-
arry = fxn(table, column, onlyAvail);
|
1670
|
+
arry = fxn( table, column, onlyAvail );
|
1491
1671
|
}
|
1492
|
-
if (arry === false) {
|
1672
|
+
if ( arry === false ) {
|
1493
1673
|
// fall back to original method
|
1494
|
-
arry = ts.filter.getOptions(table, column, onlyAvail);
|
1674
|
+
arry = ts.filter.getOptions( table, column, onlyAvail );
|
1495
1675
|
}
|
1496
1676
|
|
1497
1677
|
// get unique elements and sort the list
|
1498
|
-
// if $.tablesorter.sortText exists (not in the original tablesorter),
|
1678
|
+
// if $.tablesorter.sortText exists ( not in the original tablesorter ),
|
1499
1679
|
// then natural sort the list otherwise use a basic sort
|
1500
|
-
arry = $.grep(arry, function(value, indx) {
|
1501
|
-
return $.inArray(value, arry) === indx;
|
1680
|
+
arry = $.grep( arry, function( value, indx ) {
|
1681
|
+
return $.inArray( value, arry ) === indx;
|
1502
1682
|
});
|
1503
1683
|
|
1504
|
-
if (c.$headerIndexed[column].hasClass('filter-select-nosort')) {
|
1684
|
+
if ( c.$headerIndexed[ column ].hasClass( 'filter-select-nosort' ) ) {
|
1505
1685
|
// unsorted select options
|
1506
1686
|
return arry;
|
1507
1687
|
} else {
|
1508
1688
|
len = arry.length;
|
1509
1689
|
// parse select option values
|
1510
|
-
for (indx = 0; indx < len; indx++) {
|
1690
|
+
for ( indx = 0; indx < len; indx++ ) {
|
1511
1691
|
// parse array data using set column parser; this DOES NOT pass the original
|
1512
1692
|
// table cell to the parser format function
|
1513
|
-
parsed.push({
|
1693
|
+
parsed.push({
|
1694
|
+
t : arry[ indx ],
|
1695
|
+
p : c.parsers && c.parsers[ column ].format( arry[ indx ], table, [], column )
|
1696
|
+
});
|
1514
1697
|
}
|
1515
1698
|
|
1516
1699
|
// sort parsed select options
|
1517
1700
|
cts = c.textSorter || '';
|
1518
|
-
parsed.sort(function(a, b){
|
1701
|
+
parsed.sort( function( a, b ) {
|
1519
1702
|
// sortNatural breaks if you don't pass it strings
|
1520
|
-
var x = a.p.toString(),
|
1521
|
-
|
1703
|
+
var x = a.p.toString(),
|
1704
|
+
y = b.p.toString();
|
1705
|
+
if ( $.isFunction( cts ) ) {
|
1522
1706
|
// custom OVERALL text sorter
|
1523
|
-
return cts(x, y, true, column, table);
|
1524
|
-
} else if (typeof(cts) === 'object' && cts.hasOwnProperty(column)) {
|
1707
|
+
return cts( x, y, true, column, table );
|
1708
|
+
} else if ( typeof( cts ) === 'object' && cts.hasOwnProperty( column ) ) {
|
1525
1709
|
// custom text sorter for a SPECIFIC COLUMN
|
1526
|
-
return cts[column](x, y, true, column, table);
|
1527
|
-
} else if (ts.sortNatural) {
|
1710
|
+
return cts[column]( x, y, true, column, table );
|
1711
|
+
} else if ( ts.sortNatural ) {
|
1528
1712
|
// fall back to natural sort
|
1529
|
-
return ts.sortNatural(x, y);
|
1713
|
+
return ts.sortNatural( x, y );
|
1530
1714
|
}
|
1531
1715
|
// using an older version! do a basic sort
|
1532
1716
|
return true;
|
@@ -1534,187 +1718,224 @@ ts.filter = {
|
|
1534
1718
|
// rebuild arry from sorted parsed data
|
1535
1719
|
arry = [];
|
1536
1720
|
len = parsed.length;
|
1537
|
-
for (indx = 0; indx < len; indx++) {
|
1721
|
+
for ( indx = 0; indx < len; indx++ ) {
|
1538
1722
|
arry.push( parsed[indx].t );
|
1539
1723
|
}
|
1540
1724
|
return arry;
|
1541
1725
|
}
|
1542
1726
|
},
|
1543
|
-
getOptions: function(table, column, onlyAvail) {
|
1544
|
-
table = $(table)[0];
|
1545
|
-
var rowIndex, tbodyIndex, len, row, cache,
|
1727
|
+
getOptions: function( table, column, onlyAvail ) {
|
1728
|
+
table = $( table )[0];
|
1729
|
+
var rowIndex, tbodyIndex, len, row, cache,
|
1546
1730
|
c = table.config,
|
1547
1731
|
wo = c.widgetOptions,
|
1548
1732
|
arry = [];
|
1549
|
-
for (tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++ ) {
|
1733
|
+
for ( tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++ ) {
|
1550
1734
|
cache = c.cache[tbodyIndex];
|
1551
1735
|
len = c.cache[tbodyIndex].normalized.length;
|
1552
1736
|
// loop through the rows
|
1553
|
-
for (rowIndex = 0; rowIndex < len; rowIndex++) {
|
1554
|
-
// get cached row from cache.row (old) or row data object
|
1555
|
-
|
1737
|
+
for ( rowIndex = 0; rowIndex < len; rowIndex++ ) {
|
1738
|
+
// get cached row from cache.row ( old ) or row data object
|
1739
|
+
// ( new; last item in normalized array )
|
1740
|
+
row = cache.row ?
|
1741
|
+
cache.row[ rowIndex ] :
|
1742
|
+
cache.normalized[ rowIndex ][ c.columns ].$row[0];
|
1556
1743
|
// check if has class filtered
|
1557
|
-
if (onlyAvail && row.className.match(wo.filter_filteredRow)) {
|
1744
|
+
if ( onlyAvail && row.className.match( wo.filter_filteredRow ) ) {
|
1745
|
+
continue;
|
1746
|
+
}
|
1558
1747
|
// get non-normalized cell content
|
1559
|
-
if (wo.filter_useParsedData ||
|
1560
|
-
|
1748
|
+
if ( wo.filter_useParsedData ||
|
1749
|
+
c.parsers[column].parsed ||
|
1750
|
+
c.$headerIndexed[column].hasClass( 'filter-parsed' ) ) {
|
1751
|
+
arry.push( '' + cache.normalized[ rowIndex ][ column ] );
|
1561
1752
|
} else {
|
1562
|
-
|
1563
|
-
|
1564
|
-
arry.push( $.trim( cell.getAttribute( c.textAttribute ) || cell.textContent || $(cell).text() ) );
|
1565
|
-
}
|
1753
|
+
// get raw cached data instead of content directly from the cells
|
1754
|
+
arry.push( cache.normalized[ rowIndex ][ c.columns ].raw[ column ] );
|
1566
1755
|
}
|
1567
1756
|
}
|
1568
1757
|
}
|
1569
1758
|
return arry;
|
1570
1759
|
},
|
1571
|
-
buildSelect: function(table, column, arry, updating, onlyAvail) {
|
1572
|
-
table = $(table)[0];
|
1573
|
-
column = parseInt(column, 10);
|
1574
|
-
if (!table.config.cache || $.isEmptyObject(table.config.cache)) {
|
1760
|
+
buildSelect: function( table, column, arry, updating, onlyAvail ) {
|
1761
|
+
table = $( table )[0];
|
1762
|
+
column = parseInt( column, 10 );
|
1763
|
+
if ( !table.config.cache || $.isEmptyObject( table.config.cache ) ) {
|
1764
|
+
return;
|
1765
|
+
}
|
1575
1766
|
var indx, val, txt, t, $filters, $filter,
|
1576
1767
|
c = table.config,
|
1577
1768
|
wo = c.widgetOptions,
|
1578
|
-
node = c.$headerIndexed[column],
|
1579
|
-
// t.data('placeholder') won't work in jQuery older than 1.4.3
|
1580
|
-
options = '<option value="">' +
|
1769
|
+
node = c.$headerIndexed[ column ],
|
1770
|
+
// t.data( 'placeholder' ) won't work in jQuery older than 1.4.3
|
1771
|
+
options = '<option value="">' +
|
1772
|
+
( node.data( 'placeholder' ) ||
|
1773
|
+
node.attr( 'data-placeholder' ) ||
|
1774
|
+
wo.filter_placeholder.select || ''
|
1775
|
+
) + '</option>',
|
1581
1776
|
// Get curent filter value
|
1582
|
-
currentValue = c.$table
|
1583
|
-
|
1584
|
-
|
1585
|
-
|
1777
|
+
currentValue = c.$table
|
1778
|
+
.find( 'thead' )
|
1779
|
+
.find( 'select.' + tscss.filter + '[data-column="' + column + '"]' )
|
1780
|
+
.val();
|
1781
|
+
// nothing included in arry ( external source ), so get the options from
|
1782
|
+
// filter_selectSource or column data
|
1783
|
+
if ( typeof arry === 'undefined' || arry === '' ) {
|
1784
|
+
arry = ts.filter.getOptionSource( table, column, onlyAvail );
|
1586
1785
|
}
|
1587
1786
|
|
1588
|
-
if ($.isArray(arry)) {
|
1787
|
+
if ( $.isArray( arry ) ) {
|
1589
1788
|
// build option list
|
1590
|
-
for (indx = 0; indx < arry.length; indx++) {
|
1591
|
-
txt = arry[indx] = ('' + arry[indx]).replace(/\"/g,
|
1789
|
+
for ( indx = 0; indx < arry.length; indx++ ) {
|
1790
|
+
txt = arry[indx] = ( '' + arry[indx] ).replace( /\"/g, '"' );
|
1592
1791
|
val = txt;
|
1593
1792
|
// allow including a symbol in the selectSource array
|
1594
|
-
//
|
1595
|
-
// and
|
1596
|
-
if (txt.indexOf(wo.filter_selectSourceSeparator) >= 0) {
|
1597
|
-
t = txt.split(wo.filter_selectSourceSeparator);
|
1793
|
+
// 'a-z|A through Z' so that 'a-z' becomes the option value
|
1794
|
+
// and 'A through Z' becomes the option text
|
1795
|
+
if ( txt.indexOf( wo.filter_selectSourceSeparator ) >= 0 ) {
|
1796
|
+
t = txt.split( wo.filter_selectSourceSeparator );
|
1598
1797
|
val = t[0];
|
1599
1798
|
txt = t[1];
|
1600
1799
|
}
|
1601
|
-
// replace quotes - fixes #242 & ignore empty strings
|
1602
|
-
|
1800
|
+
// replace quotes - fixes #242 & ignore empty strings
|
1801
|
+
// see http://stackoverflow.com/q/14990971/145346
|
1802
|
+
options += arry[indx] !== '' ?
|
1803
|
+
'<option ' +
|
1804
|
+
( val === txt ? '' : 'data-function-name="' + arry[indx] + '" ' ) +
|
1805
|
+
'value="' + val + '">' + txt +
|
1806
|
+
'</option>' : '';
|
1603
1807
|
}
|
1604
1808
|
// clear arry so it doesn't get appended twice
|
1605
1809
|
arry = [];
|
1606
1810
|
}
|
1607
1811
|
|
1608
|
-
// update all selects in the same column (clone thead in sticky headers &
|
1609
|
-
|
1610
|
-
|
1611
|
-
|
1812
|
+
// update all selects in the same column ( clone thead in sticky headers &
|
1813
|
+
// any external selects ) - fixes 473
|
1814
|
+
$filters = ( c.$filters ? c.$filters : c.$table.children( 'thead' ) )
|
1815
|
+
.find( '.' + tscss.filter );
|
1816
|
+
if ( wo.filter_$externalFilters ) {
|
1817
|
+
$filters = $filters && $filters.length ?
|
1818
|
+
$filters.add( wo.filter_$externalFilters ) :
|
1819
|
+
wo.filter_$externalFilters;
|
1612
1820
|
}
|
1613
|
-
$filter = $filters.filter('select[data-column="' + column + '"]');
|
1821
|
+
$filter = $filters.filter( 'select[data-column="' + column + '"]' );
|
1614
1822
|
|
1615
1823
|
// make sure there is a select there!
|
1616
|
-
if ($filter.length) {
|
1617
|
-
$filter[ updating ? 'html' : 'append' ](options);
|
1618
|
-
if (!$.isArray(arry)) {
|
1824
|
+
if ( $filter.length ) {
|
1825
|
+
$filter[ updating ? 'html' : 'append' ]( options );
|
1826
|
+
if ( !$.isArray( arry ) ) {
|
1619
1827
|
// append options if arry is provided externally as a string or jQuery object
|
1620
|
-
// options (default value) was already added
|
1621
|
-
$filter.append(arry).val(currentValue);
|
1828
|
+
// options ( default value ) was already added
|
1829
|
+
$filter.append( arry ).val( currentValue );
|
1622
1830
|
}
|
1623
|
-
$filter.val(currentValue);
|
1831
|
+
$filter.val( currentValue );
|
1624
1832
|
}
|
1625
1833
|
},
|
1626
|
-
buildDefault: function(table, updating) {
|
1834
|
+
buildDefault: function( table, updating ) {
|
1627
1835
|
var columnIndex, $header, noSelect,
|
1628
1836
|
c = table.config,
|
1629
1837
|
wo = c.widgetOptions,
|
1630
1838
|
columns = c.columns;
|
1631
1839
|
// build default select dropdown
|
1632
|
-
for (columnIndex = 0; columnIndex < columns; columnIndex++) {
|
1840
|
+
for ( columnIndex = 0; columnIndex < columns; columnIndex++ ) {
|
1633
1841
|
$header = c.$headerIndexed[columnIndex];
|
1634
|
-
noSelect = !($header.hasClass('filter-false') || $header.hasClass('parser-false'));
|
1842
|
+
noSelect = !( $header.hasClass( 'filter-false' ) || $header.hasClass( 'parser-false' ) );
|
1635
1843
|
// look for the filter-select class; build/update it if found
|
1636
|
-
if (($header.hasClass('filter-select') ||
|
1637
|
-
ts.
|
1844
|
+
if ( ( $header.hasClass( 'filter-select' ) ||
|
1845
|
+
ts.getColumnData( table, wo.filter_functions, columnIndex ) === true ) && noSelect ) {
|
1846
|
+
ts.filter.buildSelect( table, columnIndex, '', updating, $header.hasClass( wo.filter_onlyAvail ) );
|
1638
1847
|
}
|
1639
1848
|
}
|
1640
1849
|
}
|
1641
1850
|
};
|
1642
1851
|
|
1643
|
-
ts.getFilters = function(table, getRaw, setFilters, skipFirst) {
|
1852
|
+
ts.getFilters = function( table, getRaw, setFilters, skipFirst ) {
|
1644
1853
|
var i, $filters, $column, cols,
|
1645
1854
|
filters = false,
|
1646
|
-
c = table ? $(table)[0].config : '',
|
1855
|
+
c = table ? $( table )[0].config : '',
|
1647
1856
|
wo = c ? c.widgetOptions : '';
|
1648
|
-
if (getRaw !== true && wo && !wo.filter_columnFilters)
|
1649
|
-
|
1857
|
+
if ( ( getRaw !== true && wo && !wo.filter_columnFilters ) ||
|
1858
|
+
// setFilters called, but last search is exactly the same as the current
|
1859
|
+
// fixes issue #733 & #903 where calling update causes the input values to reset
|
1860
|
+
( $.isArray(setFilters) && setFilters.join('') === c.lastCombinedFilter ) ) {
|
1861
|
+
return $( table ).data( 'lastSearch' );
|
1650
1862
|
}
|
1651
|
-
if (c) {
|
1652
|
-
if (c.$filters) {
|
1653
|
-
$filters = c.$filters.find('.' + tscss.filter);
|
1863
|
+
if ( c ) {
|
1864
|
+
if ( c.$filters ) {
|
1865
|
+
$filters = c.$filters.find( '.' + tscss.filter );
|
1654
1866
|
}
|
1655
|
-
if (wo.filter_$externalFilters) {
|
1656
|
-
$filters = $filters && $filters.length ?
|
1867
|
+
if ( wo.filter_$externalFilters ) {
|
1868
|
+
$filters = $filters && $filters.length ?
|
1869
|
+
$filters.add( wo.filter_$externalFilters ) :
|
1870
|
+
wo.filter_$externalFilters;
|
1657
1871
|
}
|
1658
|
-
if ($filters && $filters.length) {
|
1872
|
+
if ( $filters && $filters.length ) {
|
1659
1873
|
filters = setFilters || [];
|
1660
|
-
for (i = 0; i < c.columns + 1; i++) {
|
1874
|
+
for ( i = 0; i < c.columns + 1; i++ ) {
|
1661
1875
|
cols = ( i === c.columns ?
|
1662
|
-
//
|
1876
|
+
// 'all' columns can now include a range or set of columms ( data-column='0-2,4,6-7' )
|
1663
1877
|
wo.filter_anyColumnSelector + ',' + wo.filter_multipleColumnSelector :
|
1664
1878
|
'[data-column="' + i + '"]' );
|
1665
|
-
$column = $filters.filter(cols);
|
1666
|
-
if ($column.length) {
|
1879
|
+
$column = $filters.filter( cols );
|
1880
|
+
if ( $column.length ) {
|
1667
1881
|
// move the latest search to the first slot in the array
|
1668
1882
|
$column = ts.filter.getLatestSearch( $column );
|
1669
|
-
if ($.isArray(setFilters)) {
|
1670
|
-
// skip first (latest input) to maintain cursor position while typing
|
1671
|
-
if (skipFirst) {
|
1672
|
-
|
1673
|
-
|
1674
|
-
|
1883
|
+
if ( $.isArray( setFilters ) ) {
|
1884
|
+
// skip first ( latest input ) to maintain cursor position while typing
|
1885
|
+
if ( skipFirst ) {
|
1886
|
+
$column.slice( 1 );
|
1887
|
+
}
|
1888
|
+
if ( i === c.columns ) {
|
1889
|
+
// prevent data-column='all' from filling data-column='0,1' ( etc )
|
1890
|
+
cols = $column.filter( wo.filter_anyColumnSelector );
|
1675
1891
|
$column = cols.length ? cols : $column;
|
1676
1892
|
}
|
1677
1893
|
$column
|
1678
|
-
.val( setFilters[i] )
|
1679
|
-
.trigger('change.tsfilter');
|
1894
|
+
.val( setFilters[ i ] )
|
1895
|
+
.trigger( 'change.tsfilter' );
|
1680
1896
|
} else {
|
1681
1897
|
filters[i] = $column.val() || '';
|
1682
1898
|
// don't change the first... it will move the cursor
|
1683
|
-
if (i === c.columns) {
|
1684
|
-
// don't update range columns from
|
1685
|
-
$column
|
1899
|
+
if ( i === c.columns ) {
|
1900
|
+
// don't update range columns from 'all' setting
|
1901
|
+
$column
|
1902
|
+
.slice( 1 )
|
1903
|
+
.filter( '[data-column*="' + $column.attr( 'data-column' ) + '"]' )
|
1904
|
+
.val( filters[ i ] );
|
1686
1905
|
} else {
|
1687
|
-
$column
|
1906
|
+
$column
|
1907
|
+
.slice( 1 )
|
1908
|
+
.val( filters[ i ] );
|
1688
1909
|
}
|
1689
1910
|
}
|
1690
1911
|
// save any match input dynamically
|
1691
|
-
if (i === c.columns && $column.length) {
|
1912
|
+
if ( i === c.columns && $column.length ) {
|
1692
1913
|
wo.filter_$anyMatch = $column;
|
1693
1914
|
}
|
1694
1915
|
}
|
1695
1916
|
}
|
1696
1917
|
}
|
1697
1918
|
}
|
1698
|
-
if (filters.length === 0) {
|
1919
|
+
if ( filters.length === 0 ) {
|
1699
1920
|
filters = false;
|
1700
1921
|
}
|
1701
1922
|
return filters;
|
1702
1923
|
};
|
1703
1924
|
|
1704
|
-
ts.setFilters = function(table, filter, apply, skipFirst) {
|
1705
|
-
var c = table ? $(table)[0].config : '',
|
1706
|
-
valid = ts.getFilters(table, true, filter, skipFirst);
|
1707
|
-
if (c && apply) {
|
1925
|
+
ts.setFilters = function( table, filter, apply, skipFirst ) {
|
1926
|
+
var c = table ? $( table )[0].config : '',
|
1927
|
+
valid = ts.getFilters( table, true, filter, skipFirst );
|
1928
|
+
if ( c && apply ) {
|
1708
1929
|
// ensure new set filters are applied, even if the search is the same
|
1709
1930
|
c.lastCombinedFilter = null;
|
1710
1931
|
c.lastSearch = [];
|
1711
|
-
ts.filter.searching(c.table, filter, skipFirst);
|
1712
|
-
c.$table.trigger('filterFomatterUpdate');
|
1932
|
+
ts.filter.searching( c.table, filter, skipFirst );
|
1933
|
+
c.$table.trigger( 'filterFomatterUpdate' );
|
1713
1934
|
}
|
1714
1935
|
return !!valid;
|
1715
1936
|
};
|
1716
1937
|
|
1717
|
-
})(jQuery);
|
1938
|
+
})( jQuery );
|
1718
1939
|
|
1719
1940
|
/*! Widget: stickyHeaders - updated 3/26/2015 (v2.21.3) *//*
|
1720
1941
|
* Requires tablesorter v2.8+ and jQuery 1.4.3+
|
@@ -1722,7 +1943,7 @@ ts.setFilters = function(table, filter, apply, skipFirst) {
|
|
1722
1943
|
*/
|
1723
1944
|
;(function ($, window) {
|
1724
1945
|
'use strict';
|
1725
|
-
var ts = $.tablesorter
|
1946
|
+
var ts = $.tablesorter || {};
|
1726
1947
|
|
1727
1948
|
$.extend(ts.css, {
|
1728
1949
|
sticky : 'tablesorter-stickyHeader', // stickyHeader
|
@@ -1988,10 +2209,10 @@ ts.addWidget({
|
|
1988
2209
|
|
1989
2210
|
})(jQuery, window);
|
1990
2211
|
|
1991
|
-
/*! Widget: resizable - updated
|
2212
|
+
/*! Widget: resizable - updated 5/17/2015 (v2.22.0) */
|
1992
2213
|
;(function ($, window) {
|
1993
2214
|
'use strict';
|
1994
|
-
var ts = $.tablesorter
|
2215
|
+
var ts = $.tablesorter || {};
|
1995
2216
|
|
1996
2217
|
$.extend(ts.css, {
|
1997
2218
|
resizableContainer : 'tablesorter-resizable-container',
|
@@ -2280,7 +2501,7 @@ ts.addWidget({
|
|
2280
2501
|
init: function(table, thisWidget, c, wo) {
|
2281
2502
|
ts.resizable.init( c, wo );
|
2282
2503
|
},
|
2283
|
-
remove: function( table, c, wo ) {
|
2504
|
+
remove: function( table, c, wo, refreshing ) {
|
2284
2505
|
if (wo.$resizable_container) {
|
2285
2506
|
var namespace = c.namespace + 'tsresize';
|
2286
2507
|
c.$table.add( $( c.namespace + '_extra_table' ) )
|
@@ -2289,13 +2510,13 @@ ts.addWidget({
|
|
2289
2510
|
|
2290
2511
|
wo.$resizable_container.remove();
|
2291
2512
|
ts.resizable.toggleTextSelection( c, false );
|
2292
|
-
ts.resizableReset( table );
|
2513
|
+
ts.resizableReset( table, refreshing );
|
2293
2514
|
$( document ).unbind( 'mousemove' + namespace + ' mouseup' + namespace );
|
2294
2515
|
}
|
2295
2516
|
}
|
2296
2517
|
});
|
2297
2518
|
|
2298
|
-
ts.resizableReset = function( table,
|
2519
|
+
ts.resizableReset = function( table, refreshing ) {
|
2299
2520
|
$( table ).each(function(){
|
2300
2521
|
var index, $t,
|
2301
2522
|
c = this.config,
|
@@ -2312,7 +2533,7 @@ ts.resizableReset = function( table, nosave ) {
|
|
2312
2533
|
}
|
2313
2534
|
// reset stickyHeader widths
|
2314
2535
|
$( window ).trigger( 'resize' );
|
2315
|
-
if ( ts.storage && !
|
2536
|
+
if ( ts.storage && !refreshing ) {
|
2316
2537
|
ts.storage( this, ts.css.resizableStorage, {} );
|
2317
2538
|
}
|
2318
2539
|
}
|
@@ -2324,7 +2545,7 @@ ts.resizableReset = function( table, nosave ) {
|
|
2324
2545
|
/*! Widget: saveSort */
|
2325
2546
|
;(function ($) {
|
2326
2547
|
'use strict';
|
2327
|
-
var ts = $.tablesorter
|
2548
|
+
var ts = $.tablesorter || {};
|
2328
2549
|
|
2329
2550
|
// this widget saves the last sort only if the
|
2330
2551
|
// saveSort widget option is true AND the
|