mirror of
https://github.com/Mottie/tablesorter.git
synced 2024-11-15 23:54:22 +00:00
version bump
This commit is contained in:
parent
aa315b1e88
commit
68ae07cb79
21
README.md
21
README.md
@ -82,6 +82,21 @@ If you would like to contribute, please...
|
||||
|
||||
View the [complete change log here](//github.com/Mottie/tablesorter/wiki/Changes).
|
||||
|
||||
#### <a name="v2.23.2">Version 2.23.2</a> (8/23/2015)
|
||||
|
||||
* Readme
|
||||
* Corrections for last update
|
||||
* Docs
|
||||
* Add parsed values function no longer wraps empty content.
|
||||
* Core
|
||||
* Cache regular expressions.
|
||||
* ColumnSelector
|
||||
* Add `columnSelector_updated` option (triggered event name).
|
||||
* Filter
|
||||
* Allow dynamically changing the "any match" filter. Fixes [issue #998](https://github.com/Mottie/tablesorter/issues/998).
|
||||
* Cache regular expressions.
|
||||
* Add reference to widget code to make the file more compressible.
|
||||
|
||||
#### <a name="v2.23.1">Version 2.23.1</a> (8/19/2015)
|
||||
|
||||
* Core
|
||||
@ -154,9 +169,3 @@ View the [complete change log here](//github.com/Mottie/tablesorter/wiki/Changes
|
||||
* Miscellaneous cleanup of testing code.
|
||||
* Add empty `ignore` entry to bower.json. Fixes [issue #991](https://github.com/Mottie/tablesorter/issues/991).
|
||||
* Fix license in package.json to match the new spdx license expression syntax.
|
||||
|
||||
#### <a name="v2.22.5">Version 2.22.5</a> (7/28/2015)
|
||||
|
||||
* Overall:
|
||||
* Set JSHint "undef" & "unused" options. Fixed issues.
|
||||
* The math widget was throwing a javascript error after missing a changed variable name & JSHint wasn't catching it, until now.
|
||||
|
352
dist/js/jquery.tablesorter.combined.js
vendored
352
dist/js/jquery.tablesorter.combined.js
vendored
@ -1,4 +1,4 @@
|
||||
/*! tablesorter (FORK) - updated 08-21-2015 (v2.23.1)*/
|
||||
/*! tablesorter (FORK) - updated 08-23-2015 (v2.23.2)*/
|
||||
/* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */
|
||||
(function(factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
@ -10,7 +10,7 @@
|
||||
}
|
||||
}(function($) {
|
||||
|
||||
/*! TableSorter (FORK) v2.23.1 *//*
|
||||
/*! TableSorter (FORK) v2.23.2 *//*
|
||||
* Client-side table sorting with ease!
|
||||
* @requires jQuery v1.2.6+
|
||||
*
|
||||
@ -38,7 +38,7 @@
|
||||
|
||||
var ts = this;
|
||||
|
||||
ts.version = '2.23.1';
|
||||
ts.version = '2.23.2';
|
||||
|
||||
ts.parsers = [];
|
||||
ts.widgets = [];
|
||||
@ -163,6 +163,15 @@
|
||||
nextNone : 'activate to remove the sort'
|
||||
};
|
||||
|
||||
ts.regex = {
|
||||
templateContent : /\{content\}/g,
|
||||
templateIcon : /\{icon\}/g,
|
||||
templateName : /\{name\}/i,
|
||||
spaces : /\s+/g,
|
||||
nonWord : /\W/g,
|
||||
formElements : /(input|select|button|textarea)/i
|
||||
};
|
||||
|
||||
// These methods can be applied on table.config instance
|
||||
ts.instanceMethods = {};
|
||||
|
||||
@ -455,7 +464,9 @@
|
||||
// if headerTemplate is empty, don't reformat the header cell
|
||||
if ( c.headerTemplate !== '' && !$t.find('.' + ts.css.headerIn).length ) {
|
||||
// set up header template
|
||||
t = c.headerTemplate.replace(/\{content\}/g, $t.html()).replace(/\{icon\}/g, $t.find('.' + ts.css.icon).length ? '' : i);
|
||||
t = c.headerTemplate
|
||||
.replace(ts.regex.templateContent, $t.html())
|
||||
.replace(ts.regex.templateIcon, $t.find('.' + ts.css.icon).length ? '' : i);
|
||||
if (c.onRenderTemplate) {
|
||||
h = c.onRenderTemplate.apply( $t, [ index, t ] );
|
||||
if (h && typeof h === 'string') { t = h; } // only change t if something is returned
|
||||
@ -868,7 +879,7 @@
|
||||
.join( c.namespace + ' ' );
|
||||
// apply easy methods that trigger bound events
|
||||
$table
|
||||
.unbind( events.replace( /\s+/g, ' ' ) )
|
||||
.unbind( events.replace( ts.regex.spaces, ' ' ) )
|
||||
.bind( 'sortReset' + c.namespace, function( e, callback ) {
|
||||
e.stopPropagation();
|
||||
// using this.config to ensure functions are getting a non-cached version of the config
|
||||
@ -1015,7 +1026,7 @@
|
||||
c.namespace = '.tablesorter' + Math.random().toString(16).slice(2);
|
||||
} else {
|
||||
// make sure namespace starts with a period & doesn't have weird characters
|
||||
c.namespace = '.' + c.namespace.replace(/\W/g, '');
|
||||
c.namespace = '.' + c.namespace.replace(ts.regex.nonWord, '');
|
||||
}
|
||||
|
||||
c.$table.children().children('tr').attr('role', 'row');
|
||||
@ -1243,7 +1254,7 @@
|
||||
}
|
||||
}
|
||||
t = ( c.pointerDown + ' ' + c.pointerUp + ' ' + c.pointerClick + ' sort keyup ' )
|
||||
.replace(/\s+/g, ' ')
|
||||
.replace(ts.regex.spaces, ' ')
|
||||
.split(' ')
|
||||
.join(c.namespace + ' ');
|
||||
// apply event handling to headers and/or additional headers (stickyheaders, scroller, etc)
|
||||
@ -1277,7 +1288,7 @@
|
||||
}
|
||||
downTarget = null;
|
||||
// prevent sort being triggered on form elements
|
||||
if ( /(input|select|button|textarea)/i.test(e.target.nodeName) ||
|
||||
if ( ts.regex.formElements.test(e.target.nodeName) ||
|
||||
// nosort class name, or elements within a nosort container
|
||||
$target.hasClass(c.cssNoSort) || $target.parents('.' + c.cssNoSort).length > 0 ||
|
||||
// elements within a button
|
||||
@ -1563,13 +1574,13 @@
|
||||
.join(c.namespace + ' ');
|
||||
$t
|
||||
.removeData('tablesorter')
|
||||
.unbind( events.replace(/\s+/g, ' ') );
|
||||
.unbind( events.replace(ts.regex.spaces, ' ') );
|
||||
c.$headers.add($f)
|
||||
.removeClass( [ ts.css.header, c.cssHeader, c.cssAsc, c.cssDesc, ts.css.sortAsc, ts.css.sortDesc, ts.css.sortNone ].join(' ') )
|
||||
.removeAttr('data-column')
|
||||
.removeAttr('aria-label')
|
||||
.attr('aria-disabled', 'true');
|
||||
$r.find(c.selectorSort).unbind( ('mousedown mouseup keypress '.split(' ').join(c.namespace + ' ')).replace(/\s+/g, ' ') );
|
||||
$r.find(c.selectorSort).unbind( ('mousedown mouseup keypress '.split(' ').join(c.namespace + ' ')).replace(ts.regex.spaces, ' ') );
|
||||
ts.restoreHeaders(table);
|
||||
$t.toggleClass(ts.css.table + ' ' + c.tableClass + ' tablesorter-' + c.theme, removeClasses === false);
|
||||
// clear flag in case the plugin is initialized again
|
||||
@ -1585,11 +1596,9 @@
|
||||
|
||||
// *** sort functions ***
|
||||
// regex used in natural sort
|
||||
ts.regex = {
|
||||
chunk : /(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi, // chunk/tokenize numbers & letters
|
||||
chunks: /(^\\0|\\0$)/, // replace chunks @ ends
|
||||
hex: /^0x[0-9a-f]+$/i // hex
|
||||
};
|
||||
ts.regex.chunk = /(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi; // chunk/tokenize numbers & letters
|
||||
ts.regex.chunks = /(^\\0|\\0$)/; // replace chunks @ ends
|
||||
ts.regex.hex = /^0x[0-9a-f]+$/i; // hex
|
||||
|
||||
// Natural sort - https://github.com/overset/javascript-natural-sort (date sorting removed)
|
||||
// this function will only accept strings, or you'll see 'TypeError: undefined is not a function'
|
||||
@ -1816,7 +1825,7 @@
|
||||
if (c.debug) { time = new Date(); }
|
||||
// look for widgets to apply from in table class
|
||||
// stop using \b otherwise this matches 'ui-widget-content' & adds 'content' widget
|
||||
wd = new RegExp( '\\s' + c.widgetClass.replace( /\{name\}/i, '([\\w-]+)' ) + '\\s', 'g' );
|
||||
wd = new RegExp( '\\s' + c.widgetClass.replace( ts.regex.templateName, '([\\w-]+)' ) + '\\s', 'g' );
|
||||
if ( tableClass.match( wd ) ) {
|
||||
// extract out the widget id from the table class (widget id's can include dashes)
|
||||
w = tableClass.match( wd );
|
||||
@ -2042,6 +2051,10 @@
|
||||
return $.trim(val);
|
||||
};
|
||||
|
||||
ts.regex.comma = /,/g;
|
||||
ts.regex.digitNonUS = /[\s|\.]/g;
|
||||
ts.regex.digitNegativeTest = /^\s*\([.\d]+\)/;
|
||||
ts.regex.digitNegativeReplace = /^\s*\(([.\d]+)\)/;
|
||||
ts.formatFloat = function(s, table) {
|
||||
if (typeof s !== 'string' || s === '') { return s; }
|
||||
// allow using formatFloat without a table; defaults to US number format
|
||||
@ -2050,24 +2063,28 @@
|
||||
typeof table !== 'undefined' ? table : true;
|
||||
if (t) {
|
||||
// US Format - 1,234,567.89 -> 1234567.89
|
||||
s = s.replace(/,/g, '');
|
||||
s = s.replace(ts.regex.comma, '');
|
||||
} else {
|
||||
// German Format = 1.234.567,89 -> 1234567.89
|
||||
// French Format = 1 234 567,89 -> 1234567.89
|
||||
s = s.replace(/[\s|\.]/g, '').replace(/,/g, '.');
|
||||
s = s.replace(ts.regex.digitNonUS, '').replace(ts.regex.comma, '.');
|
||||
}
|
||||
if (/^\s*\([.\d]+\)/.test(s)) {
|
||||
if (ts.regex.digitNegativeTest.test(s)) {
|
||||
// make (#) into a negative number -> (10) = -10
|
||||
s = s.replace(/^\s*\(([.\d]+)\)/, '-$1');
|
||||
s = s.replace(ts.regex.digitNegativeReplace, '-$1');
|
||||
}
|
||||
i = parseFloat(s);
|
||||
// return the text instead of zero
|
||||
return isNaN(i) ? $.trim(s) : i;
|
||||
};
|
||||
|
||||
ts.regex.digitTest = /^[\-+(]?\d+[)]?$/;
|
||||
ts.regex.digitReplace = /[,.'"\s]/g;
|
||||
ts.isDigit = function(s) {
|
||||
// replace all unwanted chars and match
|
||||
return isNaN(s) ? (/^[\-+(]?\d+[)]?$/).test(s.toString().replace(/[,.'"\s]/g, '')) : s !== '';
|
||||
return isNaN(s) ?
|
||||
ts.regex.digitTest.test( s.toString().replace( ts.regex.digitReplace, '' ) ) :
|
||||
s !== '';
|
||||
};
|
||||
|
||||
}()
|
||||
@ -2126,65 +2143,76 @@
|
||||
type: 'text'
|
||||
});
|
||||
|
||||
ts.regex.nondigit = /[^\w,. \-()]/g;
|
||||
ts.addParser({
|
||||
id: 'digit',
|
||||
is: function(s) {
|
||||
return ts.isDigit(s);
|
||||
},
|
||||
format: function(s, table) {
|
||||
var n = ts.formatFloat((s || '').replace(/[^\w,. \-()]/g, ''), table);
|
||||
var n = ts.formatFloat((s || '').replace(ts.regex.nondigit, ''), table);
|
||||
return s && typeof n === 'number' ? n :
|
||||
s ? $.trim( s && table.config.ignoreCase ? s.toLocaleLowerCase() : s ) : s;
|
||||
},
|
||||
type: 'numeric'
|
||||
});
|
||||
|
||||
ts.regex.currencyReplace = /[+\-,. ]/g;
|
||||
ts.regex.currencyTest = /^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/;
|
||||
ts.addParser({
|
||||
id: 'currency',
|
||||
is: function(s) {
|
||||
s = (s || '').replace(/[+\-,. ]/g, '');
|
||||
s = (s || '').replace(ts.regex.currencyReplace, '');
|
||||
// test for £$€¤¥¢
|
||||
return (/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/).test(s);
|
||||
return ts.regex.currencyTest.test(s);
|
||||
},
|
||||
format: function(s, table) {
|
||||
var n = ts.formatFloat((s || '').replace(/[^\w,. \-()]/g, ''), table);
|
||||
var n = ts.formatFloat((s || '').replace(ts.regex.nondigit, ''), table);
|
||||
return s && typeof n === 'number' ? n :
|
||||
s ? $.trim( s && table.config.ignoreCase ? s.toLocaleLowerCase() : s ) : s;
|
||||
},
|
||||
type: 'numeric'
|
||||
});
|
||||
|
||||
// too many protocols to add them all https://en.wikipedia.org/wiki/URI_scheme
|
||||
// now, this regex can be updated before initialization
|
||||
ts.regex.urlProtocolTest = /^(https?|ftp|file):\/\//;
|
||||
ts.regex.urlProtocolReplace = /(https?|ftp|file):\/\//;
|
||||
ts.addParser({
|
||||
id: 'url',
|
||||
is: function(s) {
|
||||
return (/^(https?|ftp|file):\/\//).test(s);
|
||||
return ts.regex.urlProtocolTest.test(s);
|
||||
},
|
||||
format: function(s) {
|
||||
return s ? $.trim(s.replace(/(https?|ftp|file):\/\//, '')) : s;
|
||||
return s ? $.trim(s.replace(ts.regex.urlProtocolReplace, '')) : s;
|
||||
},
|
||||
parsed : true, // filter widget flag
|
||||
type: 'text'
|
||||
});
|
||||
|
||||
ts.regex.dash = /-/g;
|
||||
ts.regex.isoDate = /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/;
|
||||
ts.addParser({
|
||||
id: 'isoDate',
|
||||
is: function(s) {
|
||||
return (/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/).test(s);
|
||||
return ts.regex.isoDate.test(s);
|
||||
},
|
||||
format: function(s, table) {
|
||||
var date = s ? new Date( s.replace(/-/g, '/') ) : s;
|
||||
var date = s ? new Date( s.replace(ts.regex.dash, '/') ) : s;
|
||||
return date instanceof Date && isFinite(date) ? date.getTime() : s;
|
||||
},
|
||||
type: 'numeric'
|
||||
});
|
||||
|
||||
ts.regex.percent = /%/g;
|
||||
ts.regex.percentTest = /(\d\s*?%|%\s*?\d)/;
|
||||
ts.addParser({
|
||||
id: 'percent',
|
||||
is: function(s) {
|
||||
return (/(\d\s*?%|%\s*?\d)/).test(s) && s.length < 15;
|
||||
return ts.regex.percentTest.test(s) && s.length < 15;
|
||||
},
|
||||
format: function(s, table) {
|
||||
return s ? ts.formatFloat(s.replace(/%/g, ''), table) : s;
|
||||
return s ? ts.formatFloat(s.replace(ts.regex.percent, ''), table) : s;
|
||||
},
|
||||
type: 'numeric'
|
||||
});
|
||||
@ -2202,27 +2230,35 @@
|
||||
type: 'text'
|
||||
});
|
||||
|
||||
ts.regex.dateReplace = /(\S)([AP]M)$/i; // used by usLongDate & time parser
|
||||
ts.regex.usLongDateTest1 = /^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i;
|
||||
ts.regex.usLongDateTest2 = /^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i;
|
||||
ts.addParser({
|
||||
id: 'usLongDate',
|
||||
is: function(s) {
|
||||
// two digit years are not allowed cross-browser
|
||||
// Jan 01, 2013 12:34:56 PM or 01 Jan 2013
|
||||
return (/^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i).test(s) ||
|
||||
(/^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i).test(s);
|
||||
return ts.regex.usLongDateTest1.test(s) || ts.regex.usLongDateTest2.test(s);
|
||||
},
|
||||
format: function(s, table) {
|
||||
var date = s ? new Date( s.replace(/(\S)([AP]M)$/i, '$1 $2') ) : s;
|
||||
var date = s ? new Date( s.replace(ts.regex.dateReplace, '$1 $2') ) : s;
|
||||
return date instanceof Date && isFinite(date) ? date.getTime() : s;
|
||||
},
|
||||
type: 'numeric'
|
||||
});
|
||||
|
||||
// testing for ##-##-#### or ####-##-##, so it's not perfect; time can be included
|
||||
ts.regex.shortDateTest = /(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/;
|
||||
// escaped "-" because JSHint in Firefox was showing it as an error
|
||||
ts.regex.shortDateReplace = /[\-.,]/g;
|
||||
// XXY covers MDY & DMY formats
|
||||
ts.regex.shortDateXXY = /(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/;
|
||||
ts.regex.shortDateYMD = /(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/;
|
||||
ts.addParser({
|
||||
id: 'shortDate', // 'mmddyyyy', 'ddmmyyyy' or 'yyyymmdd'
|
||||
is: function(s) {
|
||||
s = (s || '').replace(/\s+/g, ' ').replace(/[\-.,]/g, '/');
|
||||
// testing for ##-##-#### or ####-##-##, so it's not perfect; time can be included
|
||||
return (/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/).test(s);
|
||||
s = (s || '').replace(ts.regex.spaces, ' ').replace(ts.regex.shortDateReplace, '/');
|
||||
return ts.regex.shortDateTest.test(s);
|
||||
},
|
||||
format: function(s, table, cell, cellIndex) {
|
||||
if (s) {
|
||||
@ -2232,14 +2268,13 @@
|
||||
format = ci.length && ci[0].dateFormat ||
|
||||
ts.getData( ci, ts.getColumnData( table, c.headers, cellIndex ), 'dateFormat') ||
|
||||
c.dateFormat;
|
||||
// escaped "-" because JSHint in Firefox was showing it as an error
|
||||
d = s.replace(/\s+/g, ' ').replace(/[\-.,]/g, '/');
|
||||
d = s.replace(ts.regex.spaces, ' ').replace(ts.regex.shortDateReplace, '/');
|
||||
if (format === 'mmddyyyy') {
|
||||
d = d.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, '$3/$1/$2');
|
||||
d = d.replace(ts.regex.shortDateXXY, '$3/$1/$2');
|
||||
} else if (format === 'ddmmyyyy') {
|
||||
d = d.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, '$3/$2/$1');
|
||||
d = d.replace(ts.regex.shortDateXXY, '$3/$2/$1');
|
||||
} else if (format === 'yyyymmdd') {
|
||||
d = d.replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/, '$1/$2/$3');
|
||||
d = d.replace(ts.regex.shortDateYMD, '$1/$2/$3');
|
||||
}
|
||||
date = new Date(d);
|
||||
return date instanceof Date && isFinite(date) ? date.getTime() : s;
|
||||
@ -2249,13 +2284,14 @@
|
||||
type: 'numeric'
|
||||
});
|
||||
|
||||
ts.regex.timeTest = /^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i;
|
||||
ts.addParser({
|
||||
id: 'time',
|
||||
is: function(s) {
|
||||
return (/^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i).test(s);
|
||||
return ts.regex.timeTest.test(s);
|
||||
},
|
||||
format: function(s, table) {
|
||||
var date = s ? new Date( '2000/01/01 ' + s.replace(/(\S)([AP]M)$/i, '$1 $2') ) : s;
|
||||
var date = s ? new Date( '2000/01/01 ' + s.replace(ts.regex.dateReplace, '$1 $2') ) : s;
|
||||
return date instanceof Date && isFinite(date) ? date.getTime() : s;
|
||||
},
|
||||
type: 'numeric'
|
||||
@ -2672,14 +2708,15 @@
|
||||
|
||||
})(jQuery);
|
||||
|
||||
/*! Widget: filter - updated 8/17/2015 (v2.23.0) *//*
|
||||
/*! Widget: filter - updated 8/23/2015 (v2.23.2) *//*
|
||||
* Requires tablesorter v2.8+ and jQuery 1.7+
|
||||
* by Rob Garrison
|
||||
*/
|
||||
;( function ( $ ) {
|
||||
'use strict';
|
||||
var ts = $.tablesorter || {},
|
||||
tscss = ts.css;
|
||||
var tsf,
|
||||
ts = $.tablesorter || {},
|
||||
tscss = ts.css;
|
||||
|
||||
$.extend( tscss, {
|
||||
filterRow : 'tablesorter-filter-row',
|
||||
@ -2723,7 +2760,7 @@
|
||||
},
|
||||
format: function( table, c, wo ) {
|
||||
if ( !c.$table.hasClass( 'hasFilters' ) ) {
|
||||
ts.filter.init( table, c, wo );
|
||||
tsf.init( table, c, wo );
|
||||
}
|
||||
},
|
||||
remove: function( table, c, wo, refreshing ) {
|
||||
@ -2735,7 +2772,7 @@
|
||||
$table
|
||||
.removeClass( 'hasFilters' )
|
||||
// add .tsfilter namespace to all BUT search
|
||||
.unbind( events.replace( /\s+/g, ' ' ) )
|
||||
.unbind( events.replace( ts.regex.spaces, ' ' ) )
|
||||
// remove the filter row even if refreshing, because the column might have been moved
|
||||
.find( '.' + tscss.filterRow ).remove();
|
||||
if ( refreshing ) { return; }
|
||||
@ -2750,7 +2787,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
ts.filter = {
|
||||
tsf = ts.filter = {
|
||||
|
||||
// regex used in filter 'check' functions - not for general use and not documented
|
||||
regex: {
|
||||
@ -2759,9 +2796,13 @@
|
||||
filtered : /filtered/, // filtered (hidden) row class name; updated in the script
|
||||
type : /undefined|number/, // check type
|
||||
exact : /(^[\"\'=]+)|([\"\'=]+$)/g, // exact match (allow '==')
|
||||
nondigit : /[^\w,. \-()]/g, // replace non-digits (from digit & currency parser)
|
||||
operators : /[<>=]/g, // replace operators
|
||||
query : '(q|query)' // replace filter queries
|
||||
query : '(q|query)', // replace filter queries
|
||||
wild01 : /\?/g, // wild card match 0 or 1
|
||||
wild0More : /\*/g, // wild care match 0 or more
|
||||
quote : /\"/g,
|
||||
isNeg1 : /(>=?\s*-\d)/,
|
||||
isNeg2 : /(<=?\s*\d)/
|
||||
},
|
||||
// function( c, data ) { }
|
||||
// c = table.config
|
||||
@ -2778,27 +2819,27 @@
|
||||
// data.parsed = array ( by column ) of boolean values ( from filter_useParsedData or 'filter-parsed' class )
|
||||
types: {
|
||||
or : function( c, data, vars ) {
|
||||
if ( /\|/.test( data.iFilter ) || ts.filter.regex.orSplit.test( data.filter ) ) {
|
||||
if ( tsf.regex.orTest.test( data.iFilter ) || tsf.regex.orSplit.test( data.filter ) ) {
|
||||
var indx, filterMatched, query, regex,
|
||||
// duplicate data but split filter
|
||||
data2 = $.extend( {}, data ),
|
||||
index = data.index,
|
||||
parsed = data.parsed[ index ],
|
||||
filter = data.filter.split( ts.filter.regex.orSplit ),
|
||||
iFilter = data.iFilter.split( ts.filter.regex.orSplit ),
|
||||
filter = data.filter.split( tsf.regex.orSplit ),
|
||||
iFilter = data.iFilter.split( tsf.regex.orSplit ),
|
||||
len = filter.length;
|
||||
for ( indx = 0; indx < len; indx++ ) {
|
||||
data2.nestedFilters = true;
|
||||
data2.filter = '' + ( ts.filter.parseFilter( c, filter[ indx ], index, parsed ) || '' );
|
||||
data2.iFilter = '' + ( ts.filter.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
|
||||
query = '(' + ( ts.filter.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')';
|
||||
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' );
|
||||
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
|
||||
query = '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')';
|
||||
try {
|
||||
// use try/catch, because query may not be a valid regex if "|" is contained within a partial regex search,
|
||||
// e.g "/(Alex|Aar" -> Uncaught SyntaxError: Invalid regular expression: /(/(Alex)/: Unterminated group
|
||||
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
|
||||
// filterMatched = data2.filter === '' && indx > 0 ? true
|
||||
// look for an exact match with the 'or' unless the 'filter-match' class is found
|
||||
filterMatched = regex.test( data2.exact ) || ts.filter.processTypes( c, data2, vars );
|
||||
filterMatched = regex.test( data2.exact ) || tsf.processTypes( c, data2, vars );
|
||||
if ( filterMatched ) {
|
||||
return filterMatched;
|
||||
}
|
||||
@ -2813,27 +2854,27 @@
|
||||
},
|
||||
// Look for an AND or && operator ( logical and )
|
||||
and : function( c, data, vars ) {
|
||||
if ( ts.filter.regex.andTest.test( data.filter ) ) {
|
||||
if ( tsf.regex.andTest.test( data.filter ) ) {
|
||||
var indx, filterMatched, result, query, regex,
|
||||
// duplicate data but split filter
|
||||
data2 = $.extend( {}, data ),
|
||||
index = data.index,
|
||||
parsed = data.parsed[ index ],
|
||||
filter = data.filter.split( ts.filter.regex.andSplit ),
|
||||
iFilter = data.iFilter.split( ts.filter.regex.andSplit ),
|
||||
filter = data.filter.split( tsf.regex.andSplit ),
|
||||
iFilter = data.iFilter.split( tsf.regex.andSplit ),
|
||||
len = filter.length;
|
||||
for ( indx = 0; indx < len; indx++ ) {
|
||||
data2.nestedFilters = true;
|
||||
data2.filter = '' + ( ts.filter.parseFilter( c, filter[ indx ], index, parsed ) || '' );
|
||||
data2.iFilter = '' + ( ts.filter.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
|
||||
query = ( '(' + ( ts.filter.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')' )
|
||||
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' );
|
||||
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
|
||||
query = ( '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')' )
|
||||
// replace wild cards since /(a*)/i will match anything
|
||||
.replace( /\?/g, '\\S{1}' ).replace( /\*/g, '\\S*' );
|
||||
.replace( tsf.regex.wild01, '\\S{1}' ).replace( tsf.regex.wild0More, '\\S*' );
|
||||
try {
|
||||
// use try/catch just in case RegExp is invalid
|
||||
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
|
||||
// look for an exact match with the 'and' unless the 'filter-match' class is found
|
||||
result = ( regex.test( data2.exact ) || ts.filter.processTypes( c, data2, vars ) );
|
||||
result = ( regex.test( data2.exact ) || tsf.processTypes( c, data2, vars ) );
|
||||
if ( indx === 0 ) {
|
||||
filterMatched = result;
|
||||
} else {
|
||||
@ -2850,10 +2891,10 @@
|
||||
},
|
||||
// Look for regex
|
||||
regex: function( c, data ) {
|
||||
if ( ts.filter.regex.regex.test( data.filter ) ) {
|
||||
if ( tsf.regex.regex.test( data.filter ) ) {
|
||||
var matches,
|
||||
// cache regex per column for optimal speed
|
||||
regex = data.filter_regexCache[ data.index ] || ts.filter.regex.regex.exec( data.filter ),
|
||||
regex = data.filter_regexCache[ data.index ] || tsf.regex.regex.exec( data.filter ),
|
||||
isRegex = regex instanceof RegExp;
|
||||
try {
|
||||
if ( !isRegex ) {
|
||||
@ -2872,18 +2913,18 @@
|
||||
// Look for operators >, >=, < or <=
|
||||
operators: function( c, data ) {
|
||||
// ignore empty strings... because '' < 10 is true
|
||||
if ( /^[<>]=?/.test( data.iFilter ) && data.iExact !== '' ) {
|
||||
if ( tsf.regex.operTest.test( data.iFilter ) && data.iExact !== '' ) {
|
||||
var cachedValue, result, txt,
|
||||
table = c.table,
|
||||
index = data.index,
|
||||
parsed = data.parsed[index],
|
||||
query = ts.formatFloat( data.iFilter.replace( ts.filter.regex.operators, '' ), table ),
|
||||
query = ts.formatFloat( data.iFilter.replace( tsf.regex.operators, '' ), table ),
|
||||
parser = c.parsers[index],
|
||||
savedSearch = query;
|
||||
// parse filter value in case we're comparing numbers ( dates )
|
||||
if ( parsed || parser.type === 'numeric' ) {
|
||||
txt = $.trim( '' + data.iFilter.replace( ts.filter.regex.operators, '' ) );
|
||||
result = ts.filter.parseFilter( c, txt, index, true );
|
||||
txt = $.trim( '' + data.iFilter.replace( tsf.regex.operators, '' ) );
|
||||
result = tsf.parseFilter( c, txt, index, true );
|
||||
query = ( typeof result === 'number' && result !== '' && !isNaN( result ) ) ? result : query;
|
||||
}
|
||||
// iExact may be numeric - see issue #149;
|
||||
@ -2892,13 +2933,13 @@
|
||||
typeof data.cache !== 'undefined' ) {
|
||||
cachedValue = data.cache;
|
||||
} else {
|
||||
txt = isNaN( data.iExact ) ? data.iExact.replace( ts.filter.regex.nondigit, '' ) : data.iExact;
|
||||
txt = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
|
||||
cachedValue = ts.formatFloat( txt, table );
|
||||
}
|
||||
if ( />/.test( data.iFilter ) ) {
|
||||
result = />=/.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
|
||||
} else if ( /</.test( data.iFilter ) ) {
|
||||
result = /<=/.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
|
||||
if ( tsf.regex.gtTest.test( data.iFilter ) ) {
|
||||
result = tsf.regex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
|
||||
} else if ( tsf.regex.ltTest.test( data.iFilter ) ) {
|
||||
result = tsf.regex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
|
||||
}
|
||||
// keep showing all rows if nothing follows the operator
|
||||
if ( !result && savedSearch === '' ) {
|
||||
@ -2910,13 +2951,13 @@
|
||||
},
|
||||
// Look for a not match
|
||||
notMatch: function( c, data ) {
|
||||
if ( /^\!/.test( data.iFilter ) ) {
|
||||
if ( tsf.regex.notTest.test( data.iFilter ) ) {
|
||||
var indx,
|
||||
txt = data.iFilter.replace( '!', '' ),
|
||||
filter = ts.filter.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
||||
if ( ts.filter.regex.exact.test( filter ) ) {
|
||||
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
||||
if ( tsf.regex.exact.test( filter ) ) {
|
||||
// look for exact not matches - see #628
|
||||
filter = filter.replace( ts.filter.regex.exact, '' );
|
||||
filter = filter.replace( tsf.regex.exact, '' );
|
||||
return filter === '' ? true : $.trim( filter ) !== data.iExact;
|
||||
} else {
|
||||
indx = data.iExact.search( $.trim( filter ) );
|
||||
@ -2928,27 +2969,27 @@
|
||||
// Look for quotes or equals to get an exact match; ignore type since iExact could be numeric
|
||||
exact: function( c, data ) {
|
||||
/*jshint eqeqeq:false */
|
||||
if ( ts.filter.regex.exact.test( data.iFilter ) ) {
|
||||
var txt = data.iFilter.replace( ts.filter.regex.exact, '' ),
|
||||
filter = ts.filter.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
||||
if ( tsf.regex.exact.test( data.iFilter ) ) {
|
||||
var txt = data.iFilter.replace( tsf.regex.exact, '' ),
|
||||
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
||||
return data.anyMatch ? $.inArray( filter, data.rowArray ) >= 0 : filter == data.iExact;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
// Look for a range ( using ' to ' or ' - ' ) - see issue #166; thanks matzhu!
|
||||
range : function( c, data ) {
|
||||
if ( ts.filter.regex.toTest.test( data.iFilter ) ) {
|
||||
if ( tsf.regex.toTest.test( data.iFilter ) ) {
|
||||
var result, tmp, range1, range2,
|
||||
table = c.table,
|
||||
index = data.index,
|
||||
parsed = data.parsed[index],
|
||||
// make sure the dash is for a range and not indicating a negative number
|
||||
query = data.iFilter.split( ts.filter.regex.toSplit );
|
||||
query = data.iFilter.split( tsf.regex.toSplit );
|
||||
|
||||
tmp = query[0].replace( ts.filter.regex.nondigit, '' ) || '';
|
||||
range1 = ts.formatFloat( ts.filter.parseFilter( c, tmp, index, parsed ), table );
|
||||
tmp = query[1].replace( ts.filter.regex.nondigit, '' ) || '';
|
||||
range2 = ts.formatFloat( ts.filter.parseFilter( c, tmp, index, parsed ), table );
|
||||
tmp = query[0].replace( ts.regex.nondigit, '' ) || '';
|
||||
range1 = ts.formatFloat( tsf.parseFilter( c, tmp, index, parsed ), table );
|
||||
tmp = query[1].replace( ts.regex.nondigit, '' ) || '';
|
||||
range2 = ts.formatFloat( tsf.parseFilter( c, tmp, index, parsed ), table );
|
||||
// parse filter value in case we're comparing numbers ( dates )
|
||||
if ( parsed || c.parsers[index].type === 'numeric' ) {
|
||||
result = c.parsers[ index ].format( '' + query[0], table, c.$headers.eq( index ), index );
|
||||
@ -2959,7 +3000,7 @@
|
||||
if ( ( parsed || c.parsers[ index ].type === 'numeric' ) && !isNaN( range1 ) && !isNaN( range2 ) ) {
|
||||
result = data.cache;
|
||||
} else {
|
||||
tmp = isNaN( data.iExact ) ? data.iExact.replace( ts.filter.regex.nondigit, '' ) : data.iExact;
|
||||
tmp = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
|
||||
result = ts.formatFloat( tmp, table );
|
||||
}
|
||||
if ( range1 > range2 ) {
|
||||
@ -2971,18 +3012,18 @@
|
||||
},
|
||||
// Look for wild card: ? = single, * = multiple, or | = logical OR
|
||||
wild : function( c, data ) {
|
||||
if ( /[\?\*\|]/.test( data.iFilter ) ) {
|
||||
if ( tsf.regex.wildOrTest.test( data.iFilter ) ) {
|
||||
var index = data.index,
|
||||
parsed = data.parsed[ index ],
|
||||
query = '' + ( ts.filter.parseFilter( c, data.iFilter, index, parsed ) || '' );
|
||||
query = '' + ( tsf.parseFilter( c, data.iFilter, index, parsed ) || '' );
|
||||
// look for an exact match with the 'or' unless the 'filter-match' class is found
|
||||
if ( !/\?\*/.test( query ) && data.nestedFilters ) {
|
||||
if ( !tsf.regex.wildTest.test( query ) && data.nestedFilters ) {
|
||||
query = data.isMatch ? query : '^(' + query + ')$';
|
||||
}
|
||||
// parsing the filter may not work properly when using wildcards =/
|
||||
try {
|
||||
return new RegExp(
|
||||
query.replace( /\?/g, '\\S{1}' ).replace( /\*/g, '\\S*' ),
|
||||
query.replace( tsf.regex.wild01, '\\S{1}' ).replace( tsf.regex.wild0More, '\\S*' ),
|
||||
c.widgetOptions.filter_ignoreCase ? 'i' : ''
|
||||
)
|
||||
.test( data.exact );
|
||||
@ -2994,12 +3035,12 @@
|
||||
},
|
||||
// fuzzy text search; modified from https://github.com/mattyork/fuzzy ( MIT license )
|
||||
fuzzy: function( c, data ) {
|
||||
if ( /^~/.test( data.iFilter ) ) {
|
||||
if ( tsf.regex.fuzzyTest.test( data.iFilter ) ) {
|
||||
var indx,
|
||||
patternIndx = 0,
|
||||
len = data.iExact.length,
|
||||
txt = data.iFilter.slice( 1 ),
|
||||
pattern = ts.filter.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
||||
pattern = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
||||
for ( indx = 0; indx < len; indx++ ) {
|
||||
if ( data.iExact[ indx ] === pattern[ patternIndx ] ) {
|
||||
patternIndx += 1;
|
||||
@ -3022,7 +3063,7 @@
|
||||
}, ts.language );
|
||||
|
||||
var options, string, txt, $header, column, filters, val, fxn, noSelect,
|
||||
regex = ts.filter.regex;
|
||||
regex = tsf.regex;
|
||||
c.$table.addClass( 'hasFilters' );
|
||||
|
||||
// define timers so using clearTimeout won't cause an undefined error
|
||||
@ -3033,7 +3074,7 @@
|
||||
wo.filter_anyColumnSelector = '[data-column="all"],[data-column="any"]';
|
||||
wo.filter_multipleColumnSelector = '[data-column*="-"],[data-column*=","]';
|
||||
|
||||
val = '\\{' + ts.filter.regex.query + '\\}';
|
||||
val = '\\{' + tsf.regex.query + '\\}';
|
||||
$.extend( regex, {
|
||||
child : new RegExp( c.cssChildRow ),
|
||||
filtered : new RegExp( wo.filter_filteredRow ),
|
||||
@ -3042,9 +3083,20 @@
|
||||
toSplit : new RegExp( '(?:\\s+(?:-|' + ts.language.to + ')\\s+)', 'gi' ),
|
||||
andTest : new RegExp( '\\s+(' + ts.language.and + '|&&)\\s+', 'i' ),
|
||||
andSplit : new RegExp( '(?:\\s+(?:' + ts.language.and + '|&&)\\s+)', 'gi' ),
|
||||
orTest : /\|/,
|
||||
orSplit : new RegExp( '(?:\\s+(?:' + ts.language.or + ')\\s+|\\|)', 'gi' ),
|
||||
iQuery : new RegExp( val, 'i' ),
|
||||
igQuery : new RegExp( val, 'ig' )
|
||||
igQuery : new RegExp( val, 'ig' ),
|
||||
operTest : /^[<>]=?/,
|
||||
gtTest : />/,
|
||||
gteTest : />=/,
|
||||
ltTest : /</,
|
||||
lteTest : /<=/,
|
||||
notTest : /^\!/,
|
||||
wildOrTest : /[\?\*\|]/,
|
||||
wildTest : /\?\*/,
|
||||
fuzzyTest : /^~/,
|
||||
exactTest : /[=\"\|!]/
|
||||
});
|
||||
|
||||
// don't build filter row if columnFilters is false or all columns are set to 'filter-false'
|
||||
@ -3052,7 +3104,7 @@
|
||||
val = c.$headers.filter( '.filter-false, .parser-false' ).length;
|
||||
if ( wo.filter_columnFilters !== false && val !== c.$headers.length ) {
|
||||
// build filter row
|
||||
ts.filter.buildRow( table, c, wo );
|
||||
tsf.buildRow( table, c, wo );
|
||||
}
|
||||
|
||||
txt = 'addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search '
|
||||
@ -3065,13 +3117,13 @@
|
||||
c.$table.find( '.' + tscss.filterRow ).toggleClass( wo.filter_filteredRow, val ); // fixes #450
|
||||
if ( !/(search|filter)/.test( event.type ) ) {
|
||||
event.stopPropagation();
|
||||
ts.filter.buildDefault( table, true );
|
||||
tsf.buildDefault( table, true );
|
||||
}
|
||||
if ( event.type === 'filterReset' ) {
|
||||
c.$table.find( '.' + tscss.filter ).add( wo.filter_$externalFilters ).val( '' );
|
||||
ts.filter.searching( table, [] );
|
||||
tsf.searching( table, [] );
|
||||
} else if ( event.type === 'filterEnd' ) {
|
||||
ts.filter.buildDefault( table, true );
|
||||
tsf.buildDefault( table, true );
|
||||
} else {
|
||||
// send false argument to force a new search; otherwise if the filter hasn't changed,
|
||||
// it will return
|
||||
@ -3085,7 +3137,7 @@
|
||||
// pass true ( skipFirst ) to prevent the tablesorter.setFilters function from skipping the first
|
||||
// input ensures all inputs are updated when a search is triggered on the table
|
||||
// $( 'table' ).trigger( 'search', [...] );
|
||||
ts.filter.searching( table, filter, true );
|
||||
tsf.searching( table, filter, true );
|
||||
}
|
||||
return false;
|
||||
});
|
||||
@ -3118,7 +3170,7 @@
|
||||
noSelect = !( $header.hasClass( 'filter-false' ) || $header.hasClass( 'parser-false' ) );
|
||||
options = '';
|
||||
if ( fxn === true && noSelect ) {
|
||||
ts.filter.buildSelect( table, column );
|
||||
tsf.buildSelect( table, column );
|
||||
} else if ( typeof fxn === 'object' && noSelect ) {
|
||||
// add custom drop down list
|
||||
for ( string in fxn ) {
|
||||
@ -3151,7 +3203,7 @@
|
||||
fxn = $.isFunction( txt ) ? true : ts.getColumnData( table, txt, column );
|
||||
if ( fxn ) {
|
||||
// updating so the extra options are appended
|
||||
ts.filter.buildSelect( c.table, column, '', true, $header.hasClass( wo.filter_onlyAvail ) );
|
||||
tsf.buildSelect( c.table, column, '', true, $header.hasClass( wo.filter_onlyAvail ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3159,22 +3211,22 @@
|
||||
}
|
||||
// not really updating, but if the column has both the 'filter-select' class &
|
||||
// filter_functions set to true, it would append the same options twice.
|
||||
ts.filter.buildDefault( table, true );
|
||||
tsf.buildDefault( table, true );
|
||||
|
||||
ts.filter.bindSearch( table, c.$table.find( '.' + tscss.filter ), true );
|
||||
tsf.bindSearch( table, c.$table.find( '.' + tscss.filter ), true );
|
||||
if ( wo.filter_external ) {
|
||||
ts.filter.bindSearch( table, wo.filter_external );
|
||||
tsf.bindSearch( table, wo.filter_external );
|
||||
}
|
||||
|
||||
if ( wo.filter_hideFilters ) {
|
||||
ts.filter.hideFilters( table, c );
|
||||
tsf.hideFilters( table, c );
|
||||
}
|
||||
|
||||
// show processing icon
|
||||
if ( c.showProcessing ) {
|
||||
txt = 'filterStart filterEnd '.split( ' ' ).join( c.namespace + 'filter ' );
|
||||
c.$table
|
||||
.unbind( txt.replace( /\s+/g, ' ' ) )
|
||||
.unbind( txt.replace( ts.regex.spaces, ' ' ) )
|
||||
.bind( txt, function( event, columns ) {
|
||||
// only add processing to certain columns to all columns
|
||||
$header = ( columns ) ?
|
||||
@ -3194,11 +3246,11 @@
|
||||
// add default values
|
||||
txt = 'tablesorter-initialized pagerBeforeInitialized '.split( ' ' ).join( c.namespace + 'filter ' );
|
||||
c.$table
|
||||
.unbind( txt.replace( /\s+/g, ' ' ) )
|
||||
.unbind( txt.replace( ts.regex.spaces, ' ' ) )
|
||||
.bind( txt, function() {
|
||||
// redefine 'wo' as it does not update properly inside this callback
|
||||
var wo = this.config.widgetOptions;
|
||||
filters = ts.filter.setDefaults( table, c, wo ) || [];
|
||||
filters = tsf.setDefaults( table, c, wo ) || [];
|
||||
if ( filters.length ) {
|
||||
// prevent delayInit from triggering a cache build if filters are empty
|
||||
if ( !( c.delayInit && filters.join( '' ) === '' ) ) {
|
||||
@ -3209,7 +3261,7 @@
|
||||
// trigger init after setTimeout to prevent multiple filterStart/End/Init triggers
|
||||
setTimeout( function() {
|
||||
if ( !wo.filter_initialized ) {
|
||||
ts.filter.filterInitComplete( c );
|
||||
tsf.filterInitComplete( c );
|
||||
}
|
||||
}, 100 );
|
||||
});
|
||||
@ -3217,7 +3269,7 @@
|
||||
if ( c.pager && c.pager.initialized && !wo.filter_initialized ) {
|
||||
c.$table.trigger( 'filterFomatterUpdate' );
|
||||
setTimeout( function() {
|
||||
ts.filter.filterInitComplete( c );
|
||||
tsf.filterInitComplete( c );
|
||||
}, 100 );
|
||||
}
|
||||
},
|
||||
@ -3238,7 +3290,7 @@
|
||||
completed = function() {
|
||||
wo.filter_initialized = true;
|
||||
c.$table.trigger( 'filterInit', c );
|
||||
ts.filter.findRows( c.table, c.$table.data( 'lastSearch' ) || [] );
|
||||
tsf.findRows( c.table, c.$table.data( 'lastSearch' ) || [] );
|
||||
};
|
||||
if ( $.isEmptyObject( wo.filter_formatter ) ) {
|
||||
completed();
|
||||
@ -3390,7 +3442,7 @@
|
||||
// use data attribute instead of jQuery data since the head is cloned without including
|
||||
// the data/binding
|
||||
.attr( 'data-lastSearchTime', new Date().getTime() )
|
||||
.unbind( tmp.replace( /\s+/g, ' ' ) )
|
||||
.unbind( tmp.replace( ts.regex.spaces, ' ' ) )
|
||||
// include change for select - fixes #473
|
||||
.bind( 'keyup' + namespace, function( event ) {
|
||||
$( this ).attr( 'data-lastSearchTime', new Date().getTime() );
|
||||
@ -3410,7 +3462,7 @@
|
||||
return;
|
||||
}
|
||||
// change event = no delay; last true flag tells getFilters to skip newest timed input
|
||||
ts.filter.searching( table, true, true );
|
||||
tsf.searching( table, true, true );
|
||||
})
|
||||
.bind( 'search change keypress '.split( ' ' ).join( namespace + ' ' ), function( event ) {
|
||||
// don't get cached data, in case data-column changes dynamically
|
||||
@ -3421,7 +3473,7 @@
|
||||
event.preventDefault();
|
||||
// init search with no delay
|
||||
$( this ).attr( 'data-lastSearchTime', new Date().getTime() );
|
||||
ts.filter.searching( table, false, true );
|
||||
tsf.searching( table, false, true );
|
||||
}
|
||||
});
|
||||
},
|
||||
@ -3431,11 +3483,11 @@
|
||||
if ( typeof filter === 'undefined' || filter === true ) {
|
||||
// delay filtering
|
||||
wo.searchTimer = setTimeout( function() {
|
||||
ts.filter.checkFilters( table, filter, skipFirst );
|
||||
tsf.checkFilters( table, filter, skipFirst );
|
||||
}, wo.filter_liveSearch ? wo.filter_searchDelay : 10 );
|
||||
} else {
|
||||
// skip delay
|
||||
ts.filter.checkFilters( table, filter, skipFirst );
|
||||
tsf.checkFilters( table, filter, skipFirst );
|
||||
}
|
||||
},
|
||||
checkFilters: function( table, filter, skipFirst ) {
|
||||
@ -3449,7 +3501,7 @@
|
||||
// update cache if delayInit set & pager has initialized ( after user initiates a search )
|
||||
if ( c.delayInit && c.pager && c.pager.initialized ) {
|
||||
c.$table.trigger( 'updateCache', [ function() {
|
||||
ts.filter.checkFilters( table, false, skipFirst );
|
||||
tsf.checkFilters( table, false, skipFirst );
|
||||
} ] );
|
||||
}
|
||||
return;
|
||||
@ -3480,11 +3532,11 @@
|
||||
if ( c.showProcessing ) {
|
||||
// give it time for the processing icon to kick in
|
||||
setTimeout( function() {
|
||||
ts.filter.findRows( table, filters, combinedFilters );
|
||||
tsf.findRows( table, filters, combinedFilters );
|
||||
return false;
|
||||
}, 30 );
|
||||
} else {
|
||||
ts.filter.findRows( table, filters, combinedFilters );
|
||||
tsf.findRows( table, filters, combinedFilters );
|
||||
return false;
|
||||
}
|
||||
},
|
||||
@ -3527,8 +3579,8 @@
|
||||
},
|
||||
defaultFilter: function( filter, mask ) {
|
||||
if ( filter === '' ) { return filter; }
|
||||
var regex = ts.filter.regex.iQuery,
|
||||
maskLen = mask.match( ts.filter.regex.igQuery ).length,
|
||||
var regex = tsf.regex.iQuery,
|
||||
maskLen = mask.match( tsf.regex.igQuery ).length,
|
||||
query = maskLen > 1 ? $.trim( filter ).split( /\s/ ) : [ $.trim( filter ) ],
|
||||
len = query.length - 1,
|
||||
indx = 0,
|
||||
@ -3564,7 +3616,7 @@
|
||||
// & don't target 'all' column inputs if they don't exist
|
||||
targets = wo.filter_initialized || !$input.filter( wo.filter_anyColumnSelector ).length,
|
||||
columns = [],
|
||||
val = $.trim( ts.filter.getLatestSearch( $input ).attr( 'data-column' ) || '' );
|
||||
val = $.trim( tsf.getLatestSearch( $input ).attr( 'data-column' ) || '' );
|
||||
if ( !/[,-]/.test(val) && val.length === 1 ) {
|
||||
return parseInt( val, 10 );
|
||||
}
|
||||
@ -3614,9 +3666,9 @@
|
||||
var ffxn,
|
||||
filterMatched = null,
|
||||
matches = null;
|
||||
for ( ffxn in ts.filter.types ) {
|
||||
for ( ffxn in tsf.types ) {
|
||||
if ( $.inArray( ffxn, vars.excludeMatch ) < 0 && matches === null ) {
|
||||
matches = ts.filter.types[ffxn]( c, data, vars );
|
||||
matches = tsf.types[ffxn]( c, data, vars );
|
||||
if ( matches !== null ) {
|
||||
filterMatched = matches;
|
||||
}
|
||||
@ -3627,7 +3679,7 @@
|
||||
processRow: function( c, data, vars ) {
|
||||
var hasSelect, result, val, filterMatched,
|
||||
fxn, ffxn, txt,
|
||||
regex = ts.filter.regex,
|
||||
regex = tsf.regex,
|
||||
wo = c.widgetOptions,
|
||||
showRow = true,
|
||||
|
||||
@ -3636,7 +3688,7 @@
|
||||
// for the entire row - see #998
|
||||
columnIndex = wo.filter_$anyMatch && wo.filter_$anyMatch.length ?
|
||||
// look for multiple columns '1-3,4-6,8'
|
||||
ts.filter.multipleColumns( c, wo.filter_$anyMatch ) :
|
||||
tsf.multipleColumns( c, wo.filter_$anyMatch ) :
|
||||
[];
|
||||
|
||||
data.$cells = data.$row.children();
|
||||
@ -3665,7 +3717,7 @@
|
||||
data.cache = data.cacheArray.slice( 0, -1 ).join( ' ' );
|
||||
|
||||
vars.excludeMatch = vars.noAnyMatch;
|
||||
filterMatched = ts.filter.processTypes( c, data, vars );
|
||||
filterMatched = tsf.processTypes( c, data, vars );
|
||||
|
||||
if ( filterMatched !== null ) {
|
||||
showRow = filterMatched;
|
||||
@ -3726,7 +3778,7 @@
|
||||
|
||||
val = true;
|
||||
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultColFilter[ columnIndex ] ) ) {
|
||||
data.filter = ts.filter.defaultFilter( data.filter, vars.defaultColFilter[ columnIndex ] );
|
||||
data.filter = tsf.defaultFilter( data.filter, vars.defaultColFilter[ columnIndex ] );
|
||||
// val is used to indicate that a filter select is using a default filter;
|
||||
// so we override the exact & partial matches
|
||||
val = false;
|
||||
@ -3757,13 +3809,13 @@
|
||||
if ( filterMatched === null ) {
|
||||
// cycle through the different filters
|
||||
// filters return a boolean or null if nothing matches
|
||||
filterMatched = ts.filter.processTypes( c, data, vars );
|
||||
filterMatched = tsf.processTypes( c, data, vars );
|
||||
if ( filterMatched !== null ) {
|
||||
result = filterMatched;
|
||||
// Look for match, and add child row data for matching
|
||||
} else {
|
||||
txt = ( data.iExact + data.childRowText )
|
||||
.indexOf( ts.filter.parseFilter( c, data.iFilter, columnIndex, data.parsed[ columnIndex ] ) );
|
||||
.indexOf( tsf.parseFilter( c, data.iFilter, columnIndex, data.parsed[ columnIndex ] ) );
|
||||
result = ( ( !wo.filter_startsWith && txt >= 0 ) || ( wo.filter_startsWith && txt === 0 ) );
|
||||
}
|
||||
} else {
|
||||
@ -3783,7 +3835,7 @@
|
||||
isChild, childRow, lastSearch, showRow, time, val, indx,
|
||||
notFiltered, searchFiltered, query, injected, res, id, txt,
|
||||
storedFilters = $.extend( [], filters ),
|
||||
regex = ts.filter.regex,
|
||||
regex = tsf.regex,
|
||||
c = table.config,
|
||||
wo = c.widgetOptions,
|
||||
// data object passed to filters; anyMatch is a flag for the filters
|
||||
@ -3860,7 +3912,7 @@
|
||||
data.anyMatchFlag = true;
|
||||
data.anyMatchFilter = '' + (
|
||||
filters[ c.columns ] ||
|
||||
wo.filter_$anyMatch && ts.filter.getLatestSearch( wo.filter_$anyMatch ).val() ||
|
||||
wo.filter_$anyMatch && tsf.getLatestSearch( wo.filter_$anyMatch ).val() ||
|
||||
''
|
||||
);
|
||||
if ( wo.filter_columnAnyMatch ) {
|
||||
@ -3902,10 +3954,10 @@
|
||||
// if there is NOT a logical 'or', or range ( 'to' or '-' ) in the string
|
||||
!regex.alreadyFiltered.test( val ) &&
|
||||
// if we are not doing exact matches, using '|' ( logical or ) or not '!'
|
||||
!/[=\"\|!]/.test( val ) &&
|
||||
!regex.exactTest.test( val ) &&
|
||||
// don't search only filtered if the value is negative
|
||||
// ( '> -10' => '> -100' will ignore hidden rows )
|
||||
!( /(>=?\s*-\d)/.test( val ) || /(<=?\s*\d)/.test( val ) ) &&
|
||||
!( regex.isNeg1.test( val ) || regex.isNeg2.test( val ) ) &&
|
||||
// if filtering using a select without a 'filter-match' class ( exact match ) - fixes #593
|
||||
!( val !== '' && c.$filters && c.$filters.eq( indx ).find( 'select' ).length &&
|
||||
!c.$headerIndexed[indx].hasClass( 'filter-match' ) );
|
||||
@ -3924,7 +3976,7 @@
|
||||
data.anyMatchFilter = ts.replaceAccents( data.anyMatchFilter );
|
||||
}
|
||||
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultAnyFilter ) ) {
|
||||
data.anyMatchFilter = ts.filter.defaultFilter( data.anyMatchFilter, vars.defaultAnyFilter );
|
||||
data.anyMatchFilter = tsf.defaultFilter( data.anyMatchFilter, vars.defaultAnyFilter );
|
||||
// clear search filtered flag because default filters are not saved to the last search
|
||||
searchFiltered = false;
|
||||
}
|
||||
@ -3967,7 +4019,7 @@
|
||||
'';
|
||||
}
|
||||
|
||||
showRow = ts.filter.processRow( c, data, vars );
|
||||
showRow = tsf.processRow( c, data, vars );
|
||||
childRow = rowData.$row.filter( ':gt( 0 )' );
|
||||
|
||||
if ( wo.filter_childRows && childRow.length ) {
|
||||
@ -3978,7 +4030,7 @@
|
||||
data.cacheArray = rowData.child[ indx ];
|
||||
data.rawArray = data.cacheArray;
|
||||
// use OR comparison on child rows
|
||||
showRow = showRow || ts.filter.processRow( c, data, vars );
|
||||
showRow = showRow || tsf.processRow( c, data, vars );
|
||||
}
|
||||
}
|
||||
childRow.toggleClass( wo.filter_filteredRow, !showRow );
|
||||
@ -4040,7 +4092,7 @@
|
||||
}
|
||||
if ( arry === false ) {
|
||||
// fall back to original method
|
||||
arry = ts.filter.getOptions( table, column, onlyAvail );
|
||||
arry = tsf.getOptions( table, column, onlyAvail );
|
||||
}
|
||||
|
||||
// get unique elements and sort the list
|
||||
@ -4152,13 +4204,13 @@
|
||||
// nothing included in arry ( external source ), so get the options from
|
||||
// filter_selectSource or column data
|
||||
if ( typeof arry === 'undefined' || arry === '' ) {
|
||||
arry = ts.filter.getOptionSource( table, column, onlyAvail );
|
||||
arry = tsf.getOptionSource( table, column, onlyAvail );
|
||||
}
|
||||
|
||||
if ( $.isArray( arry ) ) {
|
||||
// build option list
|
||||
for ( indx = 0; indx < arry.length; indx++ ) {
|
||||
txt = arry[indx] = ( '' + arry[indx] ).replace( /\"/g, '"' );
|
||||
txt = arry[indx] = ( '' + arry[indx] ).replace( tsf.regex.quote, '"' );
|
||||
val = txt;
|
||||
// allow including a symbol in the selectSource array
|
||||
// 'a-z|A through Z' so that 'a-z' becomes the option value
|
||||
@ -4214,7 +4266,7 @@
|
||||
// look for the filter-select class; build/update it if found
|
||||
if ( ( $header.hasClass( 'filter-select' ) ||
|
||||
ts.getColumnData( table, wo.filter_functions, columnIndex ) === true ) && noSelect ) {
|
||||
ts.filter.buildSelect( table, columnIndex, '', updating, $header.hasClass( wo.filter_onlyAvail ) );
|
||||
tsf.buildSelect( table, columnIndex, '', updating, $header.hasClass( wo.filter_onlyAvail ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4250,7 +4302,7 @@
|
||||
$column = $filters.filter( cols );
|
||||
if ( $column.length ) {
|
||||
// move the latest search to the first slot in the array
|
||||
$column = ts.filter.getLatestSearch( $column );
|
||||
$column = tsf.getLatestSearch( $column );
|
||||
if ( $.isArray( setFilters ) ) {
|
||||
// skip first ( latest input ) to maintain cursor position while typing
|
||||
if ( skipFirst && $column.length > 1 ) {
|
||||
@ -4300,7 +4352,7 @@
|
||||
// ensure new set filters are applied, even if the search is the same
|
||||
c.lastCombinedFilter = null;
|
||||
c.lastSearch = [];
|
||||
ts.filter.searching( c.table, filter, skipFirst );
|
||||
tsf.searching( c.table, filter, skipFirst );
|
||||
c.$table.trigger( 'filterFomatterUpdate' );
|
||||
}
|
||||
return !!valid;
|
||||
|
8
dist/js/jquery.tablesorter.combined.min.js
vendored
8
dist/js/jquery.tablesorter.combined.min.js
vendored
File diff suppressed because one or more lines are too long
122
dist/js/jquery.tablesorter.js
vendored
122
dist/js/jquery.tablesorter.js
vendored
@ -8,7 +8,7 @@
|
||||
}
|
||||
}(function($) {
|
||||
|
||||
/*! TableSorter (FORK) v2.23.1 *//*
|
||||
/*! TableSorter (FORK) v2.23.2 *//*
|
||||
* Client-side table sorting with ease!
|
||||
* @requires jQuery v1.2.6+
|
||||
*
|
||||
@ -36,7 +36,7 @@
|
||||
|
||||
var ts = this;
|
||||
|
||||
ts.version = '2.23.1';
|
||||
ts.version = '2.23.2';
|
||||
|
||||
ts.parsers = [];
|
||||
ts.widgets = [];
|
||||
@ -161,6 +161,15 @@
|
||||
nextNone : 'activate to remove the sort'
|
||||
};
|
||||
|
||||
ts.regex = {
|
||||
templateContent : /\{content\}/g,
|
||||
templateIcon : /\{icon\}/g,
|
||||
templateName : /\{name\}/i,
|
||||
spaces : /\s+/g,
|
||||
nonWord : /\W/g,
|
||||
formElements : /(input|select|button|textarea)/i
|
||||
};
|
||||
|
||||
// These methods can be applied on table.config instance
|
||||
ts.instanceMethods = {};
|
||||
|
||||
@ -453,7 +462,9 @@
|
||||
// if headerTemplate is empty, don't reformat the header cell
|
||||
if ( c.headerTemplate !== '' && !$t.find('.' + ts.css.headerIn).length ) {
|
||||
// set up header template
|
||||
t = c.headerTemplate.replace(/\{content\}/g, $t.html()).replace(/\{icon\}/g, $t.find('.' + ts.css.icon).length ? '' : i);
|
||||
t = c.headerTemplate
|
||||
.replace(ts.regex.templateContent, $t.html())
|
||||
.replace(ts.regex.templateIcon, $t.find('.' + ts.css.icon).length ? '' : i);
|
||||
if (c.onRenderTemplate) {
|
||||
h = c.onRenderTemplate.apply( $t, [ index, t ] );
|
||||
if (h && typeof h === 'string') { t = h; } // only change t if something is returned
|
||||
@ -866,7 +877,7 @@
|
||||
.join( c.namespace + ' ' );
|
||||
// apply easy methods that trigger bound events
|
||||
$table
|
||||
.unbind( events.replace( /\s+/g, ' ' ) )
|
||||
.unbind( events.replace( ts.regex.spaces, ' ' ) )
|
||||
.bind( 'sortReset' + c.namespace, function( e, callback ) {
|
||||
e.stopPropagation();
|
||||
// using this.config to ensure functions are getting a non-cached version of the config
|
||||
@ -1013,7 +1024,7 @@
|
||||
c.namespace = '.tablesorter' + Math.random().toString(16).slice(2);
|
||||
} else {
|
||||
// make sure namespace starts with a period & doesn't have weird characters
|
||||
c.namespace = '.' + c.namespace.replace(/\W/g, '');
|
||||
c.namespace = '.' + c.namespace.replace(ts.regex.nonWord, '');
|
||||
}
|
||||
|
||||
c.$table.children().children('tr').attr('role', 'row');
|
||||
@ -1241,7 +1252,7 @@
|
||||
}
|
||||
}
|
||||
t = ( c.pointerDown + ' ' + c.pointerUp + ' ' + c.pointerClick + ' sort keyup ' )
|
||||
.replace(/\s+/g, ' ')
|
||||
.replace(ts.regex.spaces, ' ')
|
||||
.split(' ')
|
||||
.join(c.namespace + ' ');
|
||||
// apply event handling to headers and/or additional headers (stickyheaders, scroller, etc)
|
||||
@ -1275,7 +1286,7 @@
|
||||
}
|
||||
downTarget = null;
|
||||
// prevent sort being triggered on form elements
|
||||
if ( /(input|select|button|textarea)/i.test(e.target.nodeName) ||
|
||||
if ( ts.regex.formElements.test(e.target.nodeName) ||
|
||||
// nosort class name, or elements within a nosort container
|
||||
$target.hasClass(c.cssNoSort) || $target.parents('.' + c.cssNoSort).length > 0 ||
|
||||
// elements within a button
|
||||
@ -1561,13 +1572,13 @@
|
||||
.join(c.namespace + ' ');
|
||||
$t
|
||||
.removeData('tablesorter')
|
||||
.unbind( events.replace(/\s+/g, ' ') );
|
||||
.unbind( events.replace(ts.regex.spaces, ' ') );
|
||||
c.$headers.add($f)
|
||||
.removeClass( [ ts.css.header, c.cssHeader, c.cssAsc, c.cssDesc, ts.css.sortAsc, ts.css.sortDesc, ts.css.sortNone ].join(' ') )
|
||||
.removeAttr('data-column')
|
||||
.removeAttr('aria-label')
|
||||
.attr('aria-disabled', 'true');
|
||||
$r.find(c.selectorSort).unbind( ('mousedown mouseup keypress '.split(' ').join(c.namespace + ' ')).replace(/\s+/g, ' ') );
|
||||
$r.find(c.selectorSort).unbind( ('mousedown mouseup keypress '.split(' ').join(c.namespace + ' ')).replace(ts.regex.spaces, ' ') );
|
||||
ts.restoreHeaders(table);
|
||||
$t.toggleClass(ts.css.table + ' ' + c.tableClass + ' tablesorter-' + c.theme, removeClasses === false);
|
||||
// clear flag in case the plugin is initialized again
|
||||
@ -1583,11 +1594,9 @@
|
||||
|
||||
// *** sort functions ***
|
||||
// regex used in natural sort
|
||||
ts.regex = {
|
||||
chunk : /(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi, // chunk/tokenize numbers & letters
|
||||
chunks: /(^\\0|\\0$)/, // replace chunks @ ends
|
||||
hex: /^0x[0-9a-f]+$/i // hex
|
||||
};
|
||||
ts.regex.chunk = /(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi; // chunk/tokenize numbers & letters
|
||||
ts.regex.chunks = /(^\\0|\\0$)/; // replace chunks @ ends
|
||||
ts.regex.hex = /^0x[0-9a-f]+$/i; // hex
|
||||
|
||||
// Natural sort - https://github.com/overset/javascript-natural-sort (date sorting removed)
|
||||
// this function will only accept strings, or you'll see 'TypeError: undefined is not a function'
|
||||
@ -1814,7 +1823,7 @@
|
||||
if (c.debug) { time = new Date(); }
|
||||
// look for widgets to apply from in table class
|
||||
// stop using \b otherwise this matches 'ui-widget-content' & adds 'content' widget
|
||||
wd = new RegExp( '\\s' + c.widgetClass.replace( /\{name\}/i, '([\\w-]+)' ) + '\\s', 'g' );
|
||||
wd = new RegExp( '\\s' + c.widgetClass.replace( ts.regex.templateName, '([\\w-]+)' ) + '\\s', 'g' );
|
||||
if ( tableClass.match( wd ) ) {
|
||||
// extract out the widget id from the table class (widget id's can include dashes)
|
||||
w = tableClass.match( wd );
|
||||
@ -2040,6 +2049,10 @@
|
||||
return $.trim(val);
|
||||
};
|
||||
|
||||
ts.regex.comma = /,/g;
|
||||
ts.regex.digitNonUS = /[\s|\.]/g;
|
||||
ts.regex.digitNegativeTest = /^\s*\([.\d]+\)/;
|
||||
ts.regex.digitNegativeReplace = /^\s*\(([.\d]+)\)/;
|
||||
ts.formatFloat = function(s, table) {
|
||||
if (typeof s !== 'string' || s === '') { return s; }
|
||||
// allow using formatFloat without a table; defaults to US number format
|
||||
@ -2048,24 +2061,28 @@
|
||||
typeof table !== 'undefined' ? table : true;
|
||||
if (t) {
|
||||
// US Format - 1,234,567.89 -> 1234567.89
|
||||
s = s.replace(/,/g, '');
|
||||
s = s.replace(ts.regex.comma, '');
|
||||
} else {
|
||||
// German Format = 1.234.567,89 -> 1234567.89
|
||||
// French Format = 1 234 567,89 -> 1234567.89
|
||||
s = s.replace(/[\s|\.]/g, '').replace(/,/g, '.');
|
||||
s = s.replace(ts.regex.digitNonUS, '').replace(ts.regex.comma, '.');
|
||||
}
|
||||
if (/^\s*\([.\d]+\)/.test(s)) {
|
||||
if (ts.regex.digitNegativeTest.test(s)) {
|
||||
// make (#) into a negative number -> (10) = -10
|
||||
s = s.replace(/^\s*\(([.\d]+)\)/, '-$1');
|
||||
s = s.replace(ts.regex.digitNegativeReplace, '-$1');
|
||||
}
|
||||
i = parseFloat(s);
|
||||
// return the text instead of zero
|
||||
return isNaN(i) ? $.trim(s) : i;
|
||||
};
|
||||
|
||||
ts.regex.digitTest = /^[\-+(]?\d+[)]?$/;
|
||||
ts.regex.digitReplace = /[,.'"\s]/g;
|
||||
ts.isDigit = function(s) {
|
||||
// replace all unwanted chars and match
|
||||
return isNaN(s) ? (/^[\-+(]?\d+[)]?$/).test(s.toString().replace(/[,.'"\s]/g, '')) : s !== '';
|
||||
return isNaN(s) ?
|
||||
ts.regex.digitTest.test( s.toString().replace( ts.regex.digitReplace, '' ) ) :
|
||||
s !== '';
|
||||
};
|
||||
|
||||
}()
|
||||
@ -2124,65 +2141,76 @@
|
||||
type: 'text'
|
||||
});
|
||||
|
||||
ts.regex.nondigit = /[^\w,. \-()]/g;
|
||||
ts.addParser({
|
||||
id: 'digit',
|
||||
is: function(s) {
|
||||
return ts.isDigit(s);
|
||||
},
|
||||
format: function(s, table) {
|
||||
var n = ts.formatFloat((s || '').replace(/[^\w,. \-()]/g, ''), table);
|
||||
var n = ts.formatFloat((s || '').replace(ts.regex.nondigit, ''), table);
|
||||
return s && typeof n === 'number' ? n :
|
||||
s ? $.trim( s && table.config.ignoreCase ? s.toLocaleLowerCase() : s ) : s;
|
||||
},
|
||||
type: 'numeric'
|
||||
});
|
||||
|
||||
ts.regex.currencyReplace = /[+\-,. ]/g;
|
||||
ts.regex.currencyTest = /^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/;
|
||||
ts.addParser({
|
||||
id: 'currency',
|
||||
is: function(s) {
|
||||
s = (s || '').replace(/[+\-,. ]/g, '');
|
||||
s = (s || '').replace(ts.regex.currencyReplace, '');
|
||||
// test for £$€¤¥¢
|
||||
return (/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/).test(s);
|
||||
return ts.regex.currencyTest.test(s);
|
||||
},
|
||||
format: function(s, table) {
|
||||
var n = ts.formatFloat((s || '').replace(/[^\w,. \-()]/g, ''), table);
|
||||
var n = ts.formatFloat((s || '').replace(ts.regex.nondigit, ''), table);
|
||||
return s && typeof n === 'number' ? n :
|
||||
s ? $.trim( s && table.config.ignoreCase ? s.toLocaleLowerCase() : s ) : s;
|
||||
},
|
||||
type: 'numeric'
|
||||
});
|
||||
|
||||
// too many protocols to add them all https://en.wikipedia.org/wiki/URI_scheme
|
||||
// now, this regex can be updated before initialization
|
||||
ts.regex.urlProtocolTest = /^(https?|ftp|file):\/\//;
|
||||
ts.regex.urlProtocolReplace = /(https?|ftp|file):\/\//;
|
||||
ts.addParser({
|
||||
id: 'url',
|
||||
is: function(s) {
|
||||
return (/^(https?|ftp|file):\/\//).test(s);
|
||||
return ts.regex.urlProtocolTest.test(s);
|
||||
},
|
||||
format: function(s) {
|
||||
return s ? $.trim(s.replace(/(https?|ftp|file):\/\//, '')) : s;
|
||||
return s ? $.trim(s.replace(ts.regex.urlProtocolReplace, '')) : s;
|
||||
},
|
||||
parsed : true, // filter widget flag
|
||||
type: 'text'
|
||||
});
|
||||
|
||||
ts.regex.dash = /-/g;
|
||||
ts.regex.isoDate = /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/;
|
||||
ts.addParser({
|
||||
id: 'isoDate',
|
||||
is: function(s) {
|
||||
return (/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/).test(s);
|
||||
return ts.regex.isoDate.test(s);
|
||||
},
|
||||
format: function(s, table) {
|
||||
var date = s ? new Date( s.replace(/-/g, '/') ) : s;
|
||||
var date = s ? new Date( s.replace(ts.regex.dash, '/') ) : s;
|
||||
return date instanceof Date && isFinite(date) ? date.getTime() : s;
|
||||
},
|
||||
type: 'numeric'
|
||||
});
|
||||
|
||||
ts.regex.percent = /%/g;
|
||||
ts.regex.percentTest = /(\d\s*?%|%\s*?\d)/;
|
||||
ts.addParser({
|
||||
id: 'percent',
|
||||
is: function(s) {
|
||||
return (/(\d\s*?%|%\s*?\d)/).test(s) && s.length < 15;
|
||||
return ts.regex.percentTest.test(s) && s.length < 15;
|
||||
},
|
||||
format: function(s, table) {
|
||||
return s ? ts.formatFloat(s.replace(/%/g, ''), table) : s;
|
||||
return s ? ts.formatFloat(s.replace(ts.regex.percent, ''), table) : s;
|
||||
},
|
||||
type: 'numeric'
|
||||
});
|
||||
@ -2200,27 +2228,35 @@
|
||||
type: 'text'
|
||||
});
|
||||
|
||||
ts.regex.dateReplace = /(\S)([AP]M)$/i; // used by usLongDate & time parser
|
||||
ts.regex.usLongDateTest1 = /^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i;
|
||||
ts.regex.usLongDateTest2 = /^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i;
|
||||
ts.addParser({
|
||||
id: 'usLongDate',
|
||||
is: function(s) {
|
||||
// two digit years are not allowed cross-browser
|
||||
// Jan 01, 2013 12:34:56 PM or 01 Jan 2013
|
||||
return (/^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i).test(s) ||
|
||||
(/^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i).test(s);
|
||||
return ts.regex.usLongDateTest1.test(s) || ts.regex.usLongDateTest2.test(s);
|
||||
},
|
||||
format: function(s, table) {
|
||||
var date = s ? new Date( s.replace(/(\S)([AP]M)$/i, '$1 $2') ) : s;
|
||||
var date = s ? new Date( s.replace(ts.regex.dateReplace, '$1 $2') ) : s;
|
||||
return date instanceof Date && isFinite(date) ? date.getTime() : s;
|
||||
},
|
||||
type: 'numeric'
|
||||
});
|
||||
|
||||
// testing for ##-##-#### or ####-##-##, so it's not perfect; time can be included
|
||||
ts.regex.shortDateTest = /(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/;
|
||||
// escaped "-" because JSHint in Firefox was showing it as an error
|
||||
ts.regex.shortDateReplace = /[\-.,]/g;
|
||||
// XXY covers MDY & DMY formats
|
||||
ts.regex.shortDateXXY = /(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/;
|
||||
ts.regex.shortDateYMD = /(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/;
|
||||
ts.addParser({
|
||||
id: 'shortDate', // 'mmddyyyy', 'ddmmyyyy' or 'yyyymmdd'
|
||||
is: function(s) {
|
||||
s = (s || '').replace(/\s+/g, ' ').replace(/[\-.,]/g, '/');
|
||||
// testing for ##-##-#### or ####-##-##, so it's not perfect; time can be included
|
||||
return (/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/).test(s);
|
||||
s = (s || '').replace(ts.regex.spaces, ' ').replace(ts.regex.shortDateReplace, '/');
|
||||
return ts.regex.shortDateTest.test(s);
|
||||
},
|
||||
format: function(s, table, cell, cellIndex) {
|
||||
if (s) {
|
||||
@ -2230,14 +2266,13 @@
|
||||
format = ci.length && ci[0].dateFormat ||
|
||||
ts.getData( ci, ts.getColumnData( table, c.headers, cellIndex ), 'dateFormat') ||
|
||||
c.dateFormat;
|
||||
// escaped "-" because JSHint in Firefox was showing it as an error
|
||||
d = s.replace(/\s+/g, ' ').replace(/[\-.,]/g, '/');
|
||||
d = s.replace(ts.regex.spaces, ' ').replace(ts.regex.shortDateReplace, '/');
|
||||
if (format === 'mmddyyyy') {
|
||||
d = d.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, '$3/$1/$2');
|
||||
d = d.replace(ts.regex.shortDateXXY, '$3/$1/$2');
|
||||
} else if (format === 'ddmmyyyy') {
|
||||
d = d.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, '$3/$2/$1');
|
||||
d = d.replace(ts.regex.shortDateXXY, '$3/$2/$1');
|
||||
} else if (format === 'yyyymmdd') {
|
||||
d = d.replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/, '$1/$2/$3');
|
||||
d = d.replace(ts.regex.shortDateYMD, '$1/$2/$3');
|
||||
}
|
||||
date = new Date(d);
|
||||
return date instanceof Date && isFinite(date) ? date.getTime() : s;
|
||||
@ -2247,13 +2282,14 @@
|
||||
type: 'numeric'
|
||||
});
|
||||
|
||||
ts.regex.timeTest = /^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i;
|
||||
ts.addParser({
|
||||
id: 'time',
|
||||
is: function(s) {
|
||||
return (/^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i).test(s);
|
||||
return ts.regex.timeTest.test(s);
|
||||
},
|
||||
format: function(s, table) {
|
||||
var date = s ? new Date( '2000/01/01 ' + s.replace(/(\S)([AP]M)$/i, '$1 $2') ) : s;
|
||||
var date = s ? new Date( '2000/01/01 ' + s.replace(ts.regex.dateReplace, '$1 $2') ) : s;
|
||||
return date instanceof Date && isFinite(date) ? date.getTime() : s;
|
||||
},
|
||||
type: 'numeric'
|
||||
|
4
dist/js/jquery.tablesorter.min.js
vendored
4
dist/js/jquery.tablesorter.min.js
vendored
File diff suppressed because one or more lines are too long
230
dist/js/jquery.tablesorter.widgets.js
vendored
230
dist/js/jquery.tablesorter.widgets.js
vendored
@ -1,4 +1,4 @@
|
||||
/*! tablesorter (FORK) - updated 08-21-2015 (v2.23.1)*/
|
||||
/*! tablesorter (FORK) - updated 08-23-2015 (v2.23.2)*/
|
||||
/* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */
|
||||
(function(factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
@ -366,14 +366,15 @@
|
||||
|
||||
})(jQuery);
|
||||
|
||||
/*! Widget: filter - updated 8/17/2015 (v2.23.0) *//*
|
||||
/*! Widget: filter - updated 8/23/2015 (v2.23.2) *//*
|
||||
* Requires tablesorter v2.8+ and jQuery 1.7+
|
||||
* by Rob Garrison
|
||||
*/
|
||||
;( function ( $ ) {
|
||||
'use strict';
|
||||
var ts = $.tablesorter || {},
|
||||
tscss = ts.css;
|
||||
var tsf,
|
||||
ts = $.tablesorter || {},
|
||||
tscss = ts.css;
|
||||
|
||||
$.extend( tscss, {
|
||||
filterRow : 'tablesorter-filter-row',
|
||||
@ -417,7 +418,7 @@
|
||||
},
|
||||
format: function( table, c, wo ) {
|
||||
if ( !c.$table.hasClass( 'hasFilters' ) ) {
|
||||
ts.filter.init( table, c, wo );
|
||||
tsf.init( table, c, wo );
|
||||
}
|
||||
},
|
||||
remove: function( table, c, wo, refreshing ) {
|
||||
@ -429,7 +430,7 @@
|
||||
$table
|
||||
.removeClass( 'hasFilters' )
|
||||
// add .tsfilter namespace to all BUT search
|
||||
.unbind( events.replace( /\s+/g, ' ' ) )
|
||||
.unbind( events.replace( ts.regex.spaces, ' ' ) )
|
||||
// remove the filter row even if refreshing, because the column might have been moved
|
||||
.find( '.' + tscss.filterRow ).remove();
|
||||
if ( refreshing ) { return; }
|
||||
@ -444,7 +445,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
ts.filter = {
|
||||
tsf = ts.filter = {
|
||||
|
||||
// regex used in filter 'check' functions - not for general use and not documented
|
||||
regex: {
|
||||
@ -453,9 +454,13 @@
|
||||
filtered : /filtered/, // filtered (hidden) row class name; updated in the script
|
||||
type : /undefined|number/, // check type
|
||||
exact : /(^[\"\'=]+)|([\"\'=]+$)/g, // exact match (allow '==')
|
||||
nondigit : /[^\w,. \-()]/g, // replace non-digits (from digit & currency parser)
|
||||
operators : /[<>=]/g, // replace operators
|
||||
query : '(q|query)' // replace filter queries
|
||||
query : '(q|query)', // replace filter queries
|
||||
wild01 : /\?/g, // wild card match 0 or 1
|
||||
wild0More : /\*/g, // wild care match 0 or more
|
||||
quote : /\"/g,
|
||||
isNeg1 : /(>=?\s*-\d)/,
|
||||
isNeg2 : /(<=?\s*\d)/
|
||||
},
|
||||
// function( c, data ) { }
|
||||
// c = table.config
|
||||
@ -472,27 +477,27 @@
|
||||
// data.parsed = array ( by column ) of boolean values ( from filter_useParsedData or 'filter-parsed' class )
|
||||
types: {
|
||||
or : function( c, data, vars ) {
|
||||
if ( /\|/.test( data.iFilter ) || ts.filter.regex.orSplit.test( data.filter ) ) {
|
||||
if ( tsf.regex.orTest.test( data.iFilter ) || tsf.regex.orSplit.test( data.filter ) ) {
|
||||
var indx, filterMatched, query, regex,
|
||||
// duplicate data but split filter
|
||||
data2 = $.extend( {}, data ),
|
||||
index = data.index,
|
||||
parsed = data.parsed[ index ],
|
||||
filter = data.filter.split( ts.filter.regex.orSplit ),
|
||||
iFilter = data.iFilter.split( ts.filter.regex.orSplit ),
|
||||
filter = data.filter.split( tsf.regex.orSplit ),
|
||||
iFilter = data.iFilter.split( tsf.regex.orSplit ),
|
||||
len = filter.length;
|
||||
for ( indx = 0; indx < len; indx++ ) {
|
||||
data2.nestedFilters = true;
|
||||
data2.filter = '' + ( ts.filter.parseFilter( c, filter[ indx ], index, parsed ) || '' );
|
||||
data2.iFilter = '' + ( ts.filter.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
|
||||
query = '(' + ( ts.filter.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')';
|
||||
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' );
|
||||
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
|
||||
query = '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')';
|
||||
try {
|
||||
// use try/catch, because query may not be a valid regex if "|" is contained within a partial regex search,
|
||||
// e.g "/(Alex|Aar" -> Uncaught SyntaxError: Invalid regular expression: /(/(Alex)/: Unterminated group
|
||||
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
|
||||
// filterMatched = data2.filter === '' && indx > 0 ? true
|
||||
// look for an exact match with the 'or' unless the 'filter-match' class is found
|
||||
filterMatched = regex.test( data2.exact ) || ts.filter.processTypes( c, data2, vars );
|
||||
filterMatched = regex.test( data2.exact ) || tsf.processTypes( c, data2, vars );
|
||||
if ( filterMatched ) {
|
||||
return filterMatched;
|
||||
}
|
||||
@ -507,27 +512,27 @@
|
||||
},
|
||||
// Look for an AND or && operator ( logical and )
|
||||
and : function( c, data, vars ) {
|
||||
if ( ts.filter.regex.andTest.test( data.filter ) ) {
|
||||
if ( tsf.regex.andTest.test( data.filter ) ) {
|
||||
var indx, filterMatched, result, query, regex,
|
||||
// duplicate data but split filter
|
||||
data2 = $.extend( {}, data ),
|
||||
index = data.index,
|
||||
parsed = data.parsed[ index ],
|
||||
filter = data.filter.split( ts.filter.regex.andSplit ),
|
||||
iFilter = data.iFilter.split( ts.filter.regex.andSplit ),
|
||||
filter = data.filter.split( tsf.regex.andSplit ),
|
||||
iFilter = data.iFilter.split( tsf.regex.andSplit ),
|
||||
len = filter.length;
|
||||
for ( indx = 0; indx < len; indx++ ) {
|
||||
data2.nestedFilters = true;
|
||||
data2.filter = '' + ( ts.filter.parseFilter( c, filter[ indx ], index, parsed ) || '' );
|
||||
data2.iFilter = '' + ( ts.filter.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
|
||||
query = ( '(' + ( ts.filter.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')' )
|
||||
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' );
|
||||
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
|
||||
query = ( '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')' )
|
||||
// replace wild cards since /(a*)/i will match anything
|
||||
.replace( /\?/g, '\\S{1}' ).replace( /\*/g, '\\S*' );
|
||||
.replace( tsf.regex.wild01, '\\S{1}' ).replace( tsf.regex.wild0More, '\\S*' );
|
||||
try {
|
||||
// use try/catch just in case RegExp is invalid
|
||||
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
|
||||
// look for an exact match with the 'and' unless the 'filter-match' class is found
|
||||
result = ( regex.test( data2.exact ) || ts.filter.processTypes( c, data2, vars ) );
|
||||
result = ( regex.test( data2.exact ) || tsf.processTypes( c, data2, vars ) );
|
||||
if ( indx === 0 ) {
|
||||
filterMatched = result;
|
||||
} else {
|
||||
@ -544,10 +549,10 @@
|
||||
},
|
||||
// Look for regex
|
||||
regex: function( c, data ) {
|
||||
if ( ts.filter.regex.regex.test( data.filter ) ) {
|
||||
if ( tsf.regex.regex.test( data.filter ) ) {
|
||||
var matches,
|
||||
// cache regex per column for optimal speed
|
||||
regex = data.filter_regexCache[ data.index ] || ts.filter.regex.regex.exec( data.filter ),
|
||||
regex = data.filter_regexCache[ data.index ] || tsf.regex.regex.exec( data.filter ),
|
||||
isRegex = regex instanceof RegExp;
|
||||
try {
|
||||
if ( !isRegex ) {
|
||||
@ -566,18 +571,18 @@
|
||||
// Look for operators >, >=, < or <=
|
||||
operators: function( c, data ) {
|
||||
// ignore empty strings... because '' < 10 is true
|
||||
if ( /^[<>]=?/.test( data.iFilter ) && data.iExact !== '' ) {
|
||||
if ( tsf.regex.operTest.test( data.iFilter ) && data.iExact !== '' ) {
|
||||
var cachedValue, result, txt,
|
||||
table = c.table,
|
||||
index = data.index,
|
||||
parsed = data.parsed[index],
|
||||
query = ts.formatFloat( data.iFilter.replace( ts.filter.regex.operators, '' ), table ),
|
||||
query = ts.formatFloat( data.iFilter.replace( tsf.regex.operators, '' ), table ),
|
||||
parser = c.parsers[index],
|
||||
savedSearch = query;
|
||||
// parse filter value in case we're comparing numbers ( dates )
|
||||
if ( parsed || parser.type === 'numeric' ) {
|
||||
txt = $.trim( '' + data.iFilter.replace( ts.filter.regex.operators, '' ) );
|
||||
result = ts.filter.parseFilter( c, txt, index, true );
|
||||
txt = $.trim( '' + data.iFilter.replace( tsf.regex.operators, '' ) );
|
||||
result = tsf.parseFilter( c, txt, index, true );
|
||||
query = ( typeof result === 'number' && result !== '' && !isNaN( result ) ) ? result : query;
|
||||
}
|
||||
// iExact may be numeric - see issue #149;
|
||||
@ -586,13 +591,13 @@
|
||||
typeof data.cache !== 'undefined' ) {
|
||||
cachedValue = data.cache;
|
||||
} else {
|
||||
txt = isNaN( data.iExact ) ? data.iExact.replace( ts.filter.regex.nondigit, '' ) : data.iExact;
|
||||
txt = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
|
||||
cachedValue = ts.formatFloat( txt, table );
|
||||
}
|
||||
if ( />/.test( data.iFilter ) ) {
|
||||
result = />=/.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
|
||||
} else if ( /</.test( data.iFilter ) ) {
|
||||
result = /<=/.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
|
||||
if ( tsf.regex.gtTest.test( data.iFilter ) ) {
|
||||
result = tsf.regex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
|
||||
} else if ( tsf.regex.ltTest.test( data.iFilter ) ) {
|
||||
result = tsf.regex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
|
||||
}
|
||||
// keep showing all rows if nothing follows the operator
|
||||
if ( !result && savedSearch === '' ) {
|
||||
@ -604,13 +609,13 @@
|
||||
},
|
||||
// Look for a not match
|
||||
notMatch: function( c, data ) {
|
||||
if ( /^\!/.test( data.iFilter ) ) {
|
||||
if ( tsf.regex.notTest.test( data.iFilter ) ) {
|
||||
var indx,
|
||||
txt = data.iFilter.replace( '!', '' ),
|
||||
filter = ts.filter.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
||||
if ( ts.filter.regex.exact.test( filter ) ) {
|
||||
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
||||
if ( tsf.regex.exact.test( filter ) ) {
|
||||
// look for exact not matches - see #628
|
||||
filter = filter.replace( ts.filter.regex.exact, '' );
|
||||
filter = filter.replace( tsf.regex.exact, '' );
|
||||
return filter === '' ? true : $.trim( filter ) !== data.iExact;
|
||||
} else {
|
||||
indx = data.iExact.search( $.trim( filter ) );
|
||||
@ -622,27 +627,27 @@
|
||||
// Look for quotes or equals to get an exact match; ignore type since iExact could be numeric
|
||||
exact: function( c, data ) {
|
||||
/*jshint eqeqeq:false */
|
||||
if ( ts.filter.regex.exact.test( data.iFilter ) ) {
|
||||
var txt = data.iFilter.replace( ts.filter.regex.exact, '' ),
|
||||
filter = ts.filter.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
||||
if ( tsf.regex.exact.test( data.iFilter ) ) {
|
||||
var txt = data.iFilter.replace( tsf.regex.exact, '' ),
|
||||
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
||||
return data.anyMatch ? $.inArray( filter, data.rowArray ) >= 0 : filter == data.iExact;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
// Look for a range ( using ' to ' or ' - ' ) - see issue #166; thanks matzhu!
|
||||
range : function( c, data ) {
|
||||
if ( ts.filter.regex.toTest.test( data.iFilter ) ) {
|
||||
if ( tsf.regex.toTest.test( data.iFilter ) ) {
|
||||
var result, tmp, range1, range2,
|
||||
table = c.table,
|
||||
index = data.index,
|
||||
parsed = data.parsed[index],
|
||||
// make sure the dash is for a range and not indicating a negative number
|
||||
query = data.iFilter.split( ts.filter.regex.toSplit );
|
||||
query = data.iFilter.split( tsf.regex.toSplit );
|
||||
|
||||
tmp = query[0].replace( ts.filter.regex.nondigit, '' ) || '';
|
||||
range1 = ts.formatFloat( ts.filter.parseFilter( c, tmp, index, parsed ), table );
|
||||
tmp = query[1].replace( ts.filter.regex.nondigit, '' ) || '';
|
||||
range2 = ts.formatFloat( ts.filter.parseFilter( c, tmp, index, parsed ), table );
|
||||
tmp = query[0].replace( ts.regex.nondigit, '' ) || '';
|
||||
range1 = ts.formatFloat( tsf.parseFilter( c, tmp, index, parsed ), table );
|
||||
tmp = query[1].replace( ts.regex.nondigit, '' ) || '';
|
||||
range2 = ts.formatFloat( tsf.parseFilter( c, tmp, index, parsed ), table );
|
||||
// parse filter value in case we're comparing numbers ( dates )
|
||||
if ( parsed || c.parsers[index].type === 'numeric' ) {
|
||||
result = c.parsers[ index ].format( '' + query[0], table, c.$headers.eq( index ), index );
|
||||
@ -653,7 +658,7 @@
|
||||
if ( ( parsed || c.parsers[ index ].type === 'numeric' ) && !isNaN( range1 ) && !isNaN( range2 ) ) {
|
||||
result = data.cache;
|
||||
} else {
|
||||
tmp = isNaN( data.iExact ) ? data.iExact.replace( ts.filter.regex.nondigit, '' ) : data.iExact;
|
||||
tmp = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
|
||||
result = ts.formatFloat( tmp, table );
|
||||
}
|
||||
if ( range1 > range2 ) {
|
||||
@ -665,18 +670,18 @@
|
||||
},
|
||||
// Look for wild card: ? = single, * = multiple, or | = logical OR
|
||||
wild : function( c, data ) {
|
||||
if ( /[\?\*\|]/.test( data.iFilter ) ) {
|
||||
if ( tsf.regex.wildOrTest.test( data.iFilter ) ) {
|
||||
var index = data.index,
|
||||
parsed = data.parsed[ index ],
|
||||
query = '' + ( ts.filter.parseFilter( c, data.iFilter, index, parsed ) || '' );
|
||||
query = '' + ( tsf.parseFilter( c, data.iFilter, index, parsed ) || '' );
|
||||
// look for an exact match with the 'or' unless the 'filter-match' class is found
|
||||
if ( !/\?\*/.test( query ) && data.nestedFilters ) {
|
||||
if ( !tsf.regex.wildTest.test( query ) && data.nestedFilters ) {
|
||||
query = data.isMatch ? query : '^(' + query + ')$';
|
||||
}
|
||||
// parsing the filter may not work properly when using wildcards =/
|
||||
try {
|
||||
return new RegExp(
|
||||
query.replace( /\?/g, '\\S{1}' ).replace( /\*/g, '\\S*' ),
|
||||
query.replace( tsf.regex.wild01, '\\S{1}' ).replace( tsf.regex.wild0More, '\\S*' ),
|
||||
c.widgetOptions.filter_ignoreCase ? 'i' : ''
|
||||
)
|
||||
.test( data.exact );
|
||||
@ -688,12 +693,12 @@
|
||||
},
|
||||
// fuzzy text search; modified from https://github.com/mattyork/fuzzy ( MIT license )
|
||||
fuzzy: function( c, data ) {
|
||||
if ( /^~/.test( data.iFilter ) ) {
|
||||
if ( tsf.regex.fuzzyTest.test( data.iFilter ) ) {
|
||||
var indx,
|
||||
patternIndx = 0,
|
||||
len = data.iExact.length,
|
||||
txt = data.iFilter.slice( 1 ),
|
||||
pattern = ts.filter.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
||||
pattern = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
||||
for ( indx = 0; indx < len; indx++ ) {
|
||||
if ( data.iExact[ indx ] === pattern[ patternIndx ] ) {
|
||||
patternIndx += 1;
|
||||
@ -716,7 +721,7 @@
|
||||
}, ts.language );
|
||||
|
||||
var options, string, txt, $header, column, filters, val, fxn, noSelect,
|
||||
regex = ts.filter.regex;
|
||||
regex = tsf.regex;
|
||||
c.$table.addClass( 'hasFilters' );
|
||||
|
||||
// define timers so using clearTimeout won't cause an undefined error
|
||||
@ -727,7 +732,7 @@
|
||||
wo.filter_anyColumnSelector = '[data-column="all"],[data-column="any"]';
|
||||
wo.filter_multipleColumnSelector = '[data-column*="-"],[data-column*=","]';
|
||||
|
||||
val = '\\{' + ts.filter.regex.query + '\\}';
|
||||
val = '\\{' + tsf.regex.query + '\\}';
|
||||
$.extend( regex, {
|
||||
child : new RegExp( c.cssChildRow ),
|
||||
filtered : new RegExp( wo.filter_filteredRow ),
|
||||
@ -736,9 +741,20 @@
|
||||
toSplit : new RegExp( '(?:\\s+(?:-|' + ts.language.to + ')\\s+)', 'gi' ),
|
||||
andTest : new RegExp( '\\s+(' + ts.language.and + '|&&)\\s+', 'i' ),
|
||||
andSplit : new RegExp( '(?:\\s+(?:' + ts.language.and + '|&&)\\s+)', 'gi' ),
|
||||
orTest : /\|/,
|
||||
orSplit : new RegExp( '(?:\\s+(?:' + ts.language.or + ')\\s+|\\|)', 'gi' ),
|
||||
iQuery : new RegExp( val, 'i' ),
|
||||
igQuery : new RegExp( val, 'ig' )
|
||||
igQuery : new RegExp( val, 'ig' ),
|
||||
operTest : /^[<>]=?/,
|
||||
gtTest : />/,
|
||||
gteTest : />=/,
|
||||
ltTest : /</,
|
||||
lteTest : /<=/,
|
||||
notTest : /^\!/,
|
||||
wildOrTest : /[\?\*\|]/,
|
||||
wildTest : /\?\*/,
|
||||
fuzzyTest : /^~/,
|
||||
exactTest : /[=\"\|!]/
|
||||
});
|
||||
|
||||
// don't build filter row if columnFilters is false or all columns are set to 'filter-false'
|
||||
@ -746,7 +762,7 @@
|
||||
val = c.$headers.filter( '.filter-false, .parser-false' ).length;
|
||||
if ( wo.filter_columnFilters !== false && val !== c.$headers.length ) {
|
||||
// build filter row
|
||||
ts.filter.buildRow( table, c, wo );
|
||||
tsf.buildRow( table, c, wo );
|
||||
}
|
||||
|
||||
txt = 'addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search '
|
||||
@ -759,13 +775,13 @@
|
||||
c.$table.find( '.' + tscss.filterRow ).toggleClass( wo.filter_filteredRow, val ); // fixes #450
|
||||
if ( !/(search|filter)/.test( event.type ) ) {
|
||||
event.stopPropagation();
|
||||
ts.filter.buildDefault( table, true );
|
||||
tsf.buildDefault( table, true );
|
||||
}
|
||||
if ( event.type === 'filterReset' ) {
|
||||
c.$table.find( '.' + tscss.filter ).add( wo.filter_$externalFilters ).val( '' );
|
||||
ts.filter.searching( table, [] );
|
||||
tsf.searching( table, [] );
|
||||
} else if ( event.type === 'filterEnd' ) {
|
||||
ts.filter.buildDefault( table, true );
|
||||
tsf.buildDefault( table, true );
|
||||
} else {
|
||||
// send false argument to force a new search; otherwise if the filter hasn't changed,
|
||||
// it will return
|
||||
@ -779,7 +795,7 @@
|
||||
// pass true ( skipFirst ) to prevent the tablesorter.setFilters function from skipping the first
|
||||
// input ensures all inputs are updated when a search is triggered on the table
|
||||
// $( 'table' ).trigger( 'search', [...] );
|
||||
ts.filter.searching( table, filter, true );
|
||||
tsf.searching( table, filter, true );
|
||||
}
|
||||
return false;
|
||||
});
|
||||
@ -812,7 +828,7 @@
|
||||
noSelect = !( $header.hasClass( 'filter-false' ) || $header.hasClass( 'parser-false' ) );
|
||||
options = '';
|
||||
if ( fxn === true && noSelect ) {
|
||||
ts.filter.buildSelect( table, column );
|
||||
tsf.buildSelect( table, column );
|
||||
} else if ( typeof fxn === 'object' && noSelect ) {
|
||||
// add custom drop down list
|
||||
for ( string in fxn ) {
|
||||
@ -845,7 +861,7 @@
|
||||
fxn = $.isFunction( txt ) ? true : ts.getColumnData( table, txt, column );
|
||||
if ( fxn ) {
|
||||
// updating so the extra options are appended
|
||||
ts.filter.buildSelect( c.table, column, '', true, $header.hasClass( wo.filter_onlyAvail ) );
|
||||
tsf.buildSelect( c.table, column, '', true, $header.hasClass( wo.filter_onlyAvail ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -853,22 +869,22 @@
|
||||
}
|
||||
// not really updating, but if the column has both the 'filter-select' class &
|
||||
// filter_functions set to true, it would append the same options twice.
|
||||
ts.filter.buildDefault( table, true );
|
||||
tsf.buildDefault( table, true );
|
||||
|
||||
ts.filter.bindSearch( table, c.$table.find( '.' + tscss.filter ), true );
|
||||
tsf.bindSearch( table, c.$table.find( '.' + tscss.filter ), true );
|
||||
if ( wo.filter_external ) {
|
||||
ts.filter.bindSearch( table, wo.filter_external );
|
||||
tsf.bindSearch( table, wo.filter_external );
|
||||
}
|
||||
|
||||
if ( wo.filter_hideFilters ) {
|
||||
ts.filter.hideFilters( table, c );
|
||||
tsf.hideFilters( table, c );
|
||||
}
|
||||
|
||||
// show processing icon
|
||||
if ( c.showProcessing ) {
|
||||
txt = 'filterStart filterEnd '.split( ' ' ).join( c.namespace + 'filter ' );
|
||||
c.$table
|
||||
.unbind( txt.replace( /\s+/g, ' ' ) )
|
||||
.unbind( txt.replace( ts.regex.spaces, ' ' ) )
|
||||
.bind( txt, function( event, columns ) {
|
||||
// only add processing to certain columns to all columns
|
||||
$header = ( columns ) ?
|
||||
@ -888,11 +904,11 @@
|
||||
// add default values
|
||||
txt = 'tablesorter-initialized pagerBeforeInitialized '.split( ' ' ).join( c.namespace + 'filter ' );
|
||||
c.$table
|
||||
.unbind( txt.replace( /\s+/g, ' ' ) )
|
||||
.unbind( txt.replace( ts.regex.spaces, ' ' ) )
|
||||
.bind( txt, function() {
|
||||
// redefine 'wo' as it does not update properly inside this callback
|
||||
var wo = this.config.widgetOptions;
|
||||
filters = ts.filter.setDefaults( table, c, wo ) || [];
|
||||
filters = tsf.setDefaults( table, c, wo ) || [];
|
||||
if ( filters.length ) {
|
||||
// prevent delayInit from triggering a cache build if filters are empty
|
||||
if ( !( c.delayInit && filters.join( '' ) === '' ) ) {
|
||||
@ -903,7 +919,7 @@
|
||||
// trigger init after setTimeout to prevent multiple filterStart/End/Init triggers
|
||||
setTimeout( function() {
|
||||
if ( !wo.filter_initialized ) {
|
||||
ts.filter.filterInitComplete( c );
|
||||
tsf.filterInitComplete( c );
|
||||
}
|
||||
}, 100 );
|
||||
});
|
||||
@ -911,7 +927,7 @@
|
||||
if ( c.pager && c.pager.initialized && !wo.filter_initialized ) {
|
||||
c.$table.trigger( 'filterFomatterUpdate' );
|
||||
setTimeout( function() {
|
||||
ts.filter.filterInitComplete( c );
|
||||
tsf.filterInitComplete( c );
|
||||
}, 100 );
|
||||
}
|
||||
},
|
||||
@ -932,7 +948,7 @@
|
||||
completed = function() {
|
||||
wo.filter_initialized = true;
|
||||
c.$table.trigger( 'filterInit', c );
|
||||
ts.filter.findRows( c.table, c.$table.data( 'lastSearch' ) || [] );
|
||||
tsf.findRows( c.table, c.$table.data( 'lastSearch' ) || [] );
|
||||
};
|
||||
if ( $.isEmptyObject( wo.filter_formatter ) ) {
|
||||
completed();
|
||||
@ -1084,7 +1100,7 @@
|
||||
// use data attribute instead of jQuery data since the head is cloned without including
|
||||
// the data/binding
|
||||
.attr( 'data-lastSearchTime', new Date().getTime() )
|
||||
.unbind( tmp.replace( /\s+/g, ' ' ) )
|
||||
.unbind( tmp.replace( ts.regex.spaces, ' ' ) )
|
||||
// include change for select - fixes #473
|
||||
.bind( 'keyup' + namespace, function( event ) {
|
||||
$( this ).attr( 'data-lastSearchTime', new Date().getTime() );
|
||||
@ -1104,7 +1120,7 @@
|
||||
return;
|
||||
}
|
||||
// change event = no delay; last true flag tells getFilters to skip newest timed input
|
||||
ts.filter.searching( table, true, true );
|
||||
tsf.searching( table, true, true );
|
||||
})
|
||||
.bind( 'search change keypress '.split( ' ' ).join( namespace + ' ' ), function( event ) {
|
||||
// don't get cached data, in case data-column changes dynamically
|
||||
@ -1115,7 +1131,7 @@
|
||||
event.preventDefault();
|
||||
// init search with no delay
|
||||
$( this ).attr( 'data-lastSearchTime', new Date().getTime() );
|
||||
ts.filter.searching( table, false, true );
|
||||
tsf.searching( table, false, true );
|
||||
}
|
||||
});
|
||||
},
|
||||
@ -1125,11 +1141,11 @@
|
||||
if ( typeof filter === 'undefined' || filter === true ) {
|
||||
// delay filtering
|
||||
wo.searchTimer = setTimeout( function() {
|
||||
ts.filter.checkFilters( table, filter, skipFirst );
|
||||
tsf.checkFilters( table, filter, skipFirst );
|
||||
}, wo.filter_liveSearch ? wo.filter_searchDelay : 10 );
|
||||
} else {
|
||||
// skip delay
|
||||
ts.filter.checkFilters( table, filter, skipFirst );
|
||||
tsf.checkFilters( table, filter, skipFirst );
|
||||
}
|
||||
},
|
||||
checkFilters: function( table, filter, skipFirst ) {
|
||||
@ -1143,7 +1159,7 @@
|
||||
// update cache if delayInit set & pager has initialized ( after user initiates a search )
|
||||
if ( c.delayInit && c.pager && c.pager.initialized ) {
|
||||
c.$table.trigger( 'updateCache', [ function() {
|
||||
ts.filter.checkFilters( table, false, skipFirst );
|
||||
tsf.checkFilters( table, false, skipFirst );
|
||||
} ] );
|
||||
}
|
||||
return;
|
||||
@ -1174,11 +1190,11 @@
|
||||
if ( c.showProcessing ) {
|
||||
// give it time for the processing icon to kick in
|
||||
setTimeout( function() {
|
||||
ts.filter.findRows( table, filters, combinedFilters );
|
||||
tsf.findRows( table, filters, combinedFilters );
|
||||
return false;
|
||||
}, 30 );
|
||||
} else {
|
||||
ts.filter.findRows( table, filters, combinedFilters );
|
||||
tsf.findRows( table, filters, combinedFilters );
|
||||
return false;
|
||||
}
|
||||
},
|
||||
@ -1221,8 +1237,8 @@
|
||||
},
|
||||
defaultFilter: function( filter, mask ) {
|
||||
if ( filter === '' ) { return filter; }
|
||||
var regex = ts.filter.regex.iQuery,
|
||||
maskLen = mask.match( ts.filter.regex.igQuery ).length,
|
||||
var regex = tsf.regex.iQuery,
|
||||
maskLen = mask.match( tsf.regex.igQuery ).length,
|
||||
query = maskLen > 1 ? $.trim( filter ).split( /\s/ ) : [ $.trim( filter ) ],
|
||||
len = query.length - 1,
|
||||
indx = 0,
|
||||
@ -1258,7 +1274,7 @@
|
||||
// & don't target 'all' column inputs if they don't exist
|
||||
targets = wo.filter_initialized || !$input.filter( wo.filter_anyColumnSelector ).length,
|
||||
columns = [],
|
||||
val = $.trim( ts.filter.getLatestSearch( $input ).attr( 'data-column' ) || '' );
|
||||
val = $.trim( tsf.getLatestSearch( $input ).attr( 'data-column' ) || '' );
|
||||
if ( !/[,-]/.test(val) && val.length === 1 ) {
|
||||
return parseInt( val, 10 );
|
||||
}
|
||||
@ -1308,9 +1324,9 @@
|
||||
var ffxn,
|
||||
filterMatched = null,
|
||||
matches = null;
|
||||
for ( ffxn in ts.filter.types ) {
|
||||
for ( ffxn in tsf.types ) {
|
||||
if ( $.inArray( ffxn, vars.excludeMatch ) < 0 && matches === null ) {
|
||||
matches = ts.filter.types[ffxn]( c, data, vars );
|
||||
matches = tsf.types[ffxn]( c, data, vars );
|
||||
if ( matches !== null ) {
|
||||
filterMatched = matches;
|
||||
}
|
||||
@ -1321,7 +1337,7 @@
|
||||
processRow: function( c, data, vars ) {
|
||||
var hasSelect, result, val, filterMatched,
|
||||
fxn, ffxn, txt,
|
||||
regex = ts.filter.regex,
|
||||
regex = tsf.regex,
|
||||
wo = c.widgetOptions,
|
||||
showRow = true,
|
||||
|
||||
@ -1330,7 +1346,7 @@
|
||||
// for the entire row - see #998
|
||||
columnIndex = wo.filter_$anyMatch && wo.filter_$anyMatch.length ?
|
||||
// look for multiple columns '1-3,4-6,8'
|
||||
ts.filter.multipleColumns( c, wo.filter_$anyMatch ) :
|
||||
tsf.multipleColumns( c, wo.filter_$anyMatch ) :
|
||||
[];
|
||||
|
||||
data.$cells = data.$row.children();
|
||||
@ -1359,7 +1375,7 @@
|
||||
data.cache = data.cacheArray.slice( 0, -1 ).join( ' ' );
|
||||
|
||||
vars.excludeMatch = vars.noAnyMatch;
|
||||
filterMatched = ts.filter.processTypes( c, data, vars );
|
||||
filterMatched = tsf.processTypes( c, data, vars );
|
||||
|
||||
if ( filterMatched !== null ) {
|
||||
showRow = filterMatched;
|
||||
@ -1420,7 +1436,7 @@
|
||||
|
||||
val = true;
|
||||
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultColFilter[ columnIndex ] ) ) {
|
||||
data.filter = ts.filter.defaultFilter( data.filter, vars.defaultColFilter[ columnIndex ] );
|
||||
data.filter = tsf.defaultFilter( data.filter, vars.defaultColFilter[ columnIndex ] );
|
||||
// val is used to indicate that a filter select is using a default filter;
|
||||
// so we override the exact & partial matches
|
||||
val = false;
|
||||
@ -1451,13 +1467,13 @@
|
||||
if ( filterMatched === null ) {
|
||||
// cycle through the different filters
|
||||
// filters return a boolean or null if nothing matches
|
||||
filterMatched = ts.filter.processTypes( c, data, vars );
|
||||
filterMatched = tsf.processTypes( c, data, vars );
|
||||
if ( filterMatched !== null ) {
|
||||
result = filterMatched;
|
||||
// Look for match, and add child row data for matching
|
||||
} else {
|
||||
txt = ( data.iExact + data.childRowText )
|
||||
.indexOf( ts.filter.parseFilter( c, data.iFilter, columnIndex, data.parsed[ columnIndex ] ) );
|
||||
.indexOf( tsf.parseFilter( c, data.iFilter, columnIndex, data.parsed[ columnIndex ] ) );
|
||||
result = ( ( !wo.filter_startsWith && txt >= 0 ) || ( wo.filter_startsWith && txt === 0 ) );
|
||||
}
|
||||
} else {
|
||||
@ -1477,7 +1493,7 @@
|
||||
isChild, childRow, lastSearch, showRow, time, val, indx,
|
||||
notFiltered, searchFiltered, query, injected, res, id, txt,
|
||||
storedFilters = $.extend( [], filters ),
|
||||
regex = ts.filter.regex,
|
||||
regex = tsf.regex,
|
||||
c = table.config,
|
||||
wo = c.widgetOptions,
|
||||
// data object passed to filters; anyMatch is a flag for the filters
|
||||
@ -1554,7 +1570,7 @@
|
||||
data.anyMatchFlag = true;
|
||||
data.anyMatchFilter = '' + (
|
||||
filters[ c.columns ] ||
|
||||
wo.filter_$anyMatch && ts.filter.getLatestSearch( wo.filter_$anyMatch ).val() ||
|
||||
wo.filter_$anyMatch && tsf.getLatestSearch( wo.filter_$anyMatch ).val() ||
|
||||
''
|
||||
);
|
||||
if ( wo.filter_columnAnyMatch ) {
|
||||
@ -1596,10 +1612,10 @@
|
||||
// if there is NOT a logical 'or', or range ( 'to' or '-' ) in the string
|
||||
!regex.alreadyFiltered.test( val ) &&
|
||||
// if we are not doing exact matches, using '|' ( logical or ) or not '!'
|
||||
!/[=\"\|!]/.test( val ) &&
|
||||
!regex.exactTest.test( val ) &&
|
||||
// don't search only filtered if the value is negative
|
||||
// ( '> -10' => '> -100' will ignore hidden rows )
|
||||
!( /(>=?\s*-\d)/.test( val ) || /(<=?\s*\d)/.test( val ) ) &&
|
||||
!( regex.isNeg1.test( val ) || regex.isNeg2.test( val ) ) &&
|
||||
// if filtering using a select without a 'filter-match' class ( exact match ) - fixes #593
|
||||
!( val !== '' && c.$filters && c.$filters.eq( indx ).find( 'select' ).length &&
|
||||
!c.$headerIndexed[indx].hasClass( 'filter-match' ) );
|
||||
@ -1618,7 +1634,7 @@
|
||||
data.anyMatchFilter = ts.replaceAccents( data.anyMatchFilter );
|
||||
}
|
||||
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultAnyFilter ) ) {
|
||||
data.anyMatchFilter = ts.filter.defaultFilter( data.anyMatchFilter, vars.defaultAnyFilter );
|
||||
data.anyMatchFilter = tsf.defaultFilter( data.anyMatchFilter, vars.defaultAnyFilter );
|
||||
// clear search filtered flag because default filters are not saved to the last search
|
||||
searchFiltered = false;
|
||||
}
|
||||
@ -1661,7 +1677,7 @@
|
||||
'';
|
||||
}
|
||||
|
||||
showRow = ts.filter.processRow( c, data, vars );
|
||||
showRow = tsf.processRow( c, data, vars );
|
||||
childRow = rowData.$row.filter( ':gt( 0 )' );
|
||||
|
||||
if ( wo.filter_childRows && childRow.length ) {
|
||||
@ -1672,7 +1688,7 @@
|
||||
data.cacheArray = rowData.child[ indx ];
|
||||
data.rawArray = data.cacheArray;
|
||||
// use OR comparison on child rows
|
||||
showRow = showRow || ts.filter.processRow( c, data, vars );
|
||||
showRow = showRow || tsf.processRow( c, data, vars );
|
||||
}
|
||||
}
|
||||
childRow.toggleClass( wo.filter_filteredRow, !showRow );
|
||||
@ -1734,7 +1750,7 @@
|
||||
}
|
||||
if ( arry === false ) {
|
||||
// fall back to original method
|
||||
arry = ts.filter.getOptions( table, column, onlyAvail );
|
||||
arry = tsf.getOptions( table, column, onlyAvail );
|
||||
}
|
||||
|
||||
// get unique elements and sort the list
|
||||
@ -1846,13 +1862,13 @@
|
||||
// nothing included in arry ( external source ), so get the options from
|
||||
// filter_selectSource or column data
|
||||
if ( typeof arry === 'undefined' || arry === '' ) {
|
||||
arry = ts.filter.getOptionSource( table, column, onlyAvail );
|
||||
arry = tsf.getOptionSource( table, column, onlyAvail );
|
||||
}
|
||||
|
||||
if ( $.isArray( arry ) ) {
|
||||
// build option list
|
||||
for ( indx = 0; indx < arry.length; indx++ ) {
|
||||
txt = arry[indx] = ( '' + arry[indx] ).replace( /\"/g, '"' );
|
||||
txt = arry[indx] = ( '' + arry[indx] ).replace( tsf.regex.quote, '"' );
|
||||
val = txt;
|
||||
// allow including a symbol in the selectSource array
|
||||
// 'a-z|A through Z' so that 'a-z' becomes the option value
|
||||
@ -1908,7 +1924,7 @@
|
||||
// look for the filter-select class; build/update it if found
|
||||
if ( ( $header.hasClass( 'filter-select' ) ||
|
||||
ts.getColumnData( table, wo.filter_functions, columnIndex ) === true ) && noSelect ) {
|
||||
ts.filter.buildSelect( table, columnIndex, '', updating, $header.hasClass( wo.filter_onlyAvail ) );
|
||||
tsf.buildSelect( table, columnIndex, '', updating, $header.hasClass( wo.filter_onlyAvail ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1944,7 +1960,7 @@
|
||||
$column = $filters.filter( cols );
|
||||
if ( $column.length ) {
|
||||
// move the latest search to the first slot in the array
|
||||
$column = ts.filter.getLatestSearch( $column );
|
||||
$column = tsf.getLatestSearch( $column );
|
||||
if ( $.isArray( setFilters ) ) {
|
||||
// skip first ( latest input ) to maintain cursor position while typing
|
||||
if ( skipFirst && $column.length > 1 ) {
|
||||
@ -1994,7 +2010,7 @@
|
||||
// ensure new set filters are applied, even if the search is the same
|
||||
c.lastCombinedFilter = null;
|
||||
c.lastSearch = [];
|
||||
ts.filter.searching( c.table, filter, skipFirst );
|
||||
tsf.searching( c.table, filter, skipFirst );
|
||||
c.$table.trigger( 'filterFomatterUpdate' );
|
||||
}
|
||||
return !!valid;
|
||||
|
6
dist/js/jquery.tablesorter.widgets.min.js
vendored
6
dist/js/jquery.tablesorter.widgets.min.js
vendored
File diff suppressed because one or more lines are too long
4
dist/js/widgets/widget-filter.min.js
vendored
4
dist/js/widgets/widget-filter.min.js
vendored
File diff suppressed because one or more lines are too long
@ -4,7 +4,7 @@
|
||||
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██▀▀ ▀▀▀▀██
|
||||
█████▀ ▀████▀ ██ ██ ▀████▀ ██ ██ ██ ██ ▀████▀ █████▀ ██ ██ █████▀
|
||||
*/
|
||||
/*! tablesorter (FORK) - updated 08-21-2015 (v2.23.1)*/
|
||||
/*! tablesorter (FORK) - updated 08-23-2015 (v2.23.2)*/
|
||||
/* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */
|
||||
(function(factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
@ -16,7 +16,7 @@
|
||||
}
|
||||
}(function($) {
|
||||
|
||||
/*! TableSorter (FORK) v2.23.1 *//*
|
||||
/*! TableSorter (FORK) v2.23.2 *//*
|
||||
* Client-side table sorting with ease!
|
||||
* @requires jQuery v1.2.6+
|
||||
*
|
||||
@ -44,7 +44,7 @@
|
||||
|
||||
var ts = this;
|
||||
|
||||
ts.version = '2.23.1';
|
||||
ts.version = '2.23.2';
|
||||
|
||||
ts.parsers = [];
|
||||
ts.widgets = [];
|
||||
@ -169,6 +169,15 @@
|
||||
nextNone : 'activate to remove the sort'
|
||||
};
|
||||
|
||||
ts.regex = {
|
||||
templateContent : /\{content\}/g,
|
||||
templateIcon : /\{icon\}/g,
|
||||
templateName : /\{name\}/i,
|
||||
spaces : /\s+/g,
|
||||
nonWord : /\W/g,
|
||||
formElements : /(input|select|button|textarea)/i
|
||||
};
|
||||
|
||||
// These methods can be applied on table.config instance
|
||||
ts.instanceMethods = {};
|
||||
|
||||
@ -461,7 +470,9 @@
|
||||
// if headerTemplate is empty, don't reformat the header cell
|
||||
if ( c.headerTemplate !== '' && !$t.find('.' + ts.css.headerIn).length ) {
|
||||
// set up header template
|
||||
t = c.headerTemplate.replace(/\{content\}/g, $t.html()).replace(/\{icon\}/g, $t.find('.' + ts.css.icon).length ? '' : i);
|
||||
t = c.headerTemplate
|
||||
.replace(ts.regex.templateContent, $t.html())
|
||||
.replace(ts.regex.templateIcon, $t.find('.' + ts.css.icon).length ? '' : i);
|
||||
if (c.onRenderTemplate) {
|
||||
h = c.onRenderTemplate.apply( $t, [ index, t ] );
|
||||
if (h && typeof h === 'string') { t = h; } // only change t if something is returned
|
||||
@ -874,7 +885,7 @@
|
||||
.join( c.namespace + ' ' );
|
||||
// apply easy methods that trigger bound events
|
||||
$table
|
||||
.unbind( events.replace( /\s+/g, ' ' ) )
|
||||
.unbind( events.replace( ts.regex.spaces, ' ' ) )
|
||||
.bind( 'sortReset' + c.namespace, function( e, callback ) {
|
||||
e.stopPropagation();
|
||||
// using this.config to ensure functions are getting a non-cached version of the config
|
||||
@ -1021,7 +1032,7 @@
|
||||
c.namespace = '.tablesorter' + Math.random().toString(16).slice(2);
|
||||
} else {
|
||||
// make sure namespace starts with a period & doesn't have weird characters
|
||||
c.namespace = '.' + c.namespace.replace(/\W/g, '');
|
||||
c.namespace = '.' + c.namespace.replace(ts.regex.nonWord, '');
|
||||
}
|
||||
|
||||
c.$table.children().children('tr').attr('role', 'row');
|
||||
@ -1249,7 +1260,7 @@
|
||||
}
|
||||
}
|
||||
t = ( c.pointerDown + ' ' + c.pointerUp + ' ' + c.pointerClick + ' sort keyup ' )
|
||||
.replace(/\s+/g, ' ')
|
||||
.replace(ts.regex.spaces, ' ')
|
||||
.split(' ')
|
||||
.join(c.namespace + ' ');
|
||||
// apply event handling to headers and/or additional headers (stickyheaders, scroller, etc)
|
||||
@ -1283,7 +1294,7 @@
|
||||
}
|
||||
downTarget = null;
|
||||
// prevent sort being triggered on form elements
|
||||
if ( /(input|select|button|textarea)/i.test(e.target.nodeName) ||
|
||||
if ( ts.regex.formElements.test(e.target.nodeName) ||
|
||||
// nosort class name, or elements within a nosort container
|
||||
$target.hasClass(c.cssNoSort) || $target.parents('.' + c.cssNoSort).length > 0 ||
|
||||
// elements within a button
|
||||
@ -1569,13 +1580,13 @@
|
||||
.join(c.namespace + ' ');
|
||||
$t
|
||||
.removeData('tablesorter')
|
||||
.unbind( events.replace(/\s+/g, ' ') );
|
||||
.unbind( events.replace(ts.regex.spaces, ' ') );
|
||||
c.$headers.add($f)
|
||||
.removeClass( [ ts.css.header, c.cssHeader, c.cssAsc, c.cssDesc, ts.css.sortAsc, ts.css.sortDesc, ts.css.sortNone ].join(' ') )
|
||||
.removeAttr('data-column')
|
||||
.removeAttr('aria-label')
|
||||
.attr('aria-disabled', 'true');
|
||||
$r.find(c.selectorSort).unbind( ('mousedown mouseup keypress '.split(' ').join(c.namespace + ' ')).replace(/\s+/g, ' ') );
|
||||
$r.find(c.selectorSort).unbind( ('mousedown mouseup keypress '.split(' ').join(c.namespace + ' ')).replace(ts.regex.spaces, ' ') );
|
||||
ts.restoreHeaders(table);
|
||||
$t.toggleClass(ts.css.table + ' ' + c.tableClass + ' tablesorter-' + c.theme, removeClasses === false);
|
||||
// clear flag in case the plugin is initialized again
|
||||
@ -1591,11 +1602,9 @@
|
||||
|
||||
// *** sort functions ***
|
||||
// regex used in natural sort
|
||||
ts.regex = {
|
||||
chunk : /(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi, // chunk/tokenize numbers & letters
|
||||
chunks: /(^\\0|\\0$)/, // replace chunks @ ends
|
||||
hex: /^0x[0-9a-f]+$/i // hex
|
||||
};
|
||||
ts.regex.chunk = /(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi; // chunk/tokenize numbers & letters
|
||||
ts.regex.chunks = /(^\\0|\\0$)/; // replace chunks @ ends
|
||||
ts.regex.hex = /^0x[0-9a-f]+$/i; // hex
|
||||
|
||||
// Natural sort - https://github.com/overset/javascript-natural-sort (date sorting removed)
|
||||
// this function will only accept strings, or you'll see 'TypeError: undefined is not a function'
|
||||
@ -1822,7 +1831,7 @@
|
||||
if (c.debug) { time = new Date(); }
|
||||
// look for widgets to apply from in table class
|
||||
// stop using \b otherwise this matches 'ui-widget-content' & adds 'content' widget
|
||||
wd = new RegExp( '\\s' + c.widgetClass.replace( /\{name\}/i, '([\\w-]+)' ) + '\\s', 'g' );
|
||||
wd = new RegExp( '\\s' + c.widgetClass.replace( ts.regex.templateName, '([\\w-]+)' ) + '\\s', 'g' );
|
||||
if ( tableClass.match( wd ) ) {
|
||||
// extract out the widget id from the table class (widget id's can include dashes)
|
||||
w = tableClass.match( wd );
|
||||
@ -2048,6 +2057,10 @@
|
||||
return $.trim(val);
|
||||
};
|
||||
|
||||
ts.regex.comma = /,/g;
|
||||
ts.regex.digitNonUS = /[\s|\.]/g;
|
||||
ts.regex.digitNegativeTest = /^\s*\([.\d]+\)/;
|
||||
ts.regex.digitNegativeReplace = /^\s*\(([.\d]+)\)/;
|
||||
ts.formatFloat = function(s, table) {
|
||||
if (typeof s !== 'string' || s === '') { return s; }
|
||||
// allow using formatFloat without a table; defaults to US number format
|
||||
@ -2056,24 +2069,28 @@
|
||||
typeof table !== 'undefined' ? table : true;
|
||||
if (t) {
|
||||
// US Format - 1,234,567.89 -> 1234567.89
|
||||
s = s.replace(/,/g, '');
|
||||
s = s.replace(ts.regex.comma, '');
|
||||
} else {
|
||||
// German Format = 1.234.567,89 -> 1234567.89
|
||||
// French Format = 1 234 567,89 -> 1234567.89
|
||||
s = s.replace(/[\s|\.]/g, '').replace(/,/g, '.');
|
||||
s = s.replace(ts.regex.digitNonUS, '').replace(ts.regex.comma, '.');
|
||||
}
|
||||
if (/^\s*\([.\d]+\)/.test(s)) {
|
||||
if (ts.regex.digitNegativeTest.test(s)) {
|
||||
// make (#) into a negative number -> (10) = -10
|
||||
s = s.replace(/^\s*\(([.\d]+)\)/, '-$1');
|
||||
s = s.replace(ts.regex.digitNegativeReplace, '-$1');
|
||||
}
|
||||
i = parseFloat(s);
|
||||
// return the text instead of zero
|
||||
return isNaN(i) ? $.trim(s) : i;
|
||||
};
|
||||
|
||||
ts.regex.digitTest = /^[\-+(]?\d+[)]?$/;
|
||||
ts.regex.digitReplace = /[,.'"\s]/g;
|
||||
ts.isDigit = function(s) {
|
||||
// replace all unwanted chars and match
|
||||
return isNaN(s) ? (/^[\-+(]?\d+[)]?$/).test(s.toString().replace(/[,.'"\s]/g, '')) : s !== '';
|
||||
return isNaN(s) ?
|
||||
ts.regex.digitTest.test( s.toString().replace( ts.regex.digitReplace, '' ) ) :
|
||||
s !== '';
|
||||
};
|
||||
|
||||
}()
|
||||
@ -2132,65 +2149,76 @@
|
||||
type: 'text'
|
||||
});
|
||||
|
||||
ts.regex.nondigit = /[^\w,. \-()]/g;
|
||||
ts.addParser({
|
||||
id: 'digit',
|
||||
is: function(s) {
|
||||
return ts.isDigit(s);
|
||||
},
|
||||
format: function(s, table) {
|
||||
var n = ts.formatFloat((s || '').replace(/[^\w,. \-()]/g, ''), table);
|
||||
var n = ts.formatFloat((s || '').replace(ts.regex.nondigit, ''), table);
|
||||
return s && typeof n === 'number' ? n :
|
||||
s ? $.trim( s && table.config.ignoreCase ? s.toLocaleLowerCase() : s ) : s;
|
||||
},
|
||||
type: 'numeric'
|
||||
});
|
||||
|
||||
ts.regex.currencyReplace = /[+\-,. ]/g;
|
||||
ts.regex.currencyTest = /^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/;
|
||||
ts.addParser({
|
||||
id: 'currency',
|
||||
is: function(s) {
|
||||
s = (s || '').replace(/[+\-,. ]/g, '');
|
||||
s = (s || '').replace(ts.regex.currencyReplace, '');
|
||||
// test for £$€¤¥¢
|
||||
return (/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/).test(s);
|
||||
return ts.regex.currencyTest.test(s);
|
||||
},
|
||||
format: function(s, table) {
|
||||
var n = ts.formatFloat((s || '').replace(/[^\w,. \-()]/g, ''), table);
|
||||
var n = ts.formatFloat((s || '').replace(ts.regex.nondigit, ''), table);
|
||||
return s && typeof n === 'number' ? n :
|
||||
s ? $.trim( s && table.config.ignoreCase ? s.toLocaleLowerCase() : s ) : s;
|
||||
},
|
||||
type: 'numeric'
|
||||
});
|
||||
|
||||
// too many protocols to add them all https://en.wikipedia.org/wiki/URI_scheme
|
||||
// now, this regex can be updated before initialization
|
||||
ts.regex.urlProtocolTest = /^(https?|ftp|file):\/\//;
|
||||
ts.regex.urlProtocolReplace = /(https?|ftp|file):\/\//;
|
||||
ts.addParser({
|
||||
id: 'url',
|
||||
is: function(s) {
|
||||
return (/^(https?|ftp|file):\/\//).test(s);
|
||||
return ts.regex.urlProtocolTest.test(s);
|
||||
},
|
||||
format: function(s) {
|
||||
return s ? $.trim(s.replace(/(https?|ftp|file):\/\//, '')) : s;
|
||||
return s ? $.trim(s.replace(ts.regex.urlProtocolReplace, '')) : s;
|
||||
},
|
||||
parsed : true, // filter widget flag
|
||||
type: 'text'
|
||||
});
|
||||
|
||||
ts.regex.dash = /-/g;
|
||||
ts.regex.isoDate = /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/;
|
||||
ts.addParser({
|
||||
id: 'isoDate',
|
||||
is: function(s) {
|
||||
return (/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/).test(s);
|
||||
return ts.regex.isoDate.test(s);
|
||||
},
|
||||
format: function(s, table) {
|
||||
var date = s ? new Date( s.replace(/-/g, '/') ) : s;
|
||||
var date = s ? new Date( s.replace(ts.regex.dash, '/') ) : s;
|
||||
return date instanceof Date && isFinite(date) ? date.getTime() : s;
|
||||
},
|
||||
type: 'numeric'
|
||||
});
|
||||
|
||||
ts.regex.percent = /%/g;
|
||||
ts.regex.percentTest = /(\d\s*?%|%\s*?\d)/;
|
||||
ts.addParser({
|
||||
id: 'percent',
|
||||
is: function(s) {
|
||||
return (/(\d\s*?%|%\s*?\d)/).test(s) && s.length < 15;
|
||||
return ts.regex.percentTest.test(s) && s.length < 15;
|
||||
},
|
||||
format: function(s, table) {
|
||||
return s ? ts.formatFloat(s.replace(/%/g, ''), table) : s;
|
||||
return s ? ts.formatFloat(s.replace(ts.regex.percent, ''), table) : s;
|
||||
},
|
||||
type: 'numeric'
|
||||
});
|
||||
@ -2208,27 +2236,35 @@
|
||||
type: 'text'
|
||||
});
|
||||
|
||||
ts.regex.dateReplace = /(\S)([AP]M)$/i; // used by usLongDate & time parser
|
||||
ts.regex.usLongDateTest1 = /^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i;
|
||||
ts.regex.usLongDateTest2 = /^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i;
|
||||
ts.addParser({
|
||||
id: 'usLongDate',
|
||||
is: function(s) {
|
||||
// two digit years are not allowed cross-browser
|
||||
// Jan 01, 2013 12:34:56 PM or 01 Jan 2013
|
||||
return (/^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i).test(s) ||
|
||||
(/^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i).test(s);
|
||||
return ts.regex.usLongDateTest1.test(s) || ts.regex.usLongDateTest2.test(s);
|
||||
},
|
||||
format: function(s, table) {
|
||||
var date = s ? new Date( s.replace(/(\S)([AP]M)$/i, '$1 $2') ) : s;
|
||||
var date = s ? new Date( s.replace(ts.regex.dateReplace, '$1 $2') ) : s;
|
||||
return date instanceof Date && isFinite(date) ? date.getTime() : s;
|
||||
},
|
||||
type: 'numeric'
|
||||
});
|
||||
|
||||
// testing for ##-##-#### or ####-##-##, so it's not perfect; time can be included
|
||||
ts.regex.shortDateTest = /(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/;
|
||||
// escaped "-" because JSHint in Firefox was showing it as an error
|
||||
ts.regex.shortDateReplace = /[\-.,]/g;
|
||||
// XXY covers MDY & DMY formats
|
||||
ts.regex.shortDateXXY = /(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/;
|
||||
ts.regex.shortDateYMD = /(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/;
|
||||
ts.addParser({
|
||||
id: 'shortDate', // 'mmddyyyy', 'ddmmyyyy' or 'yyyymmdd'
|
||||
is: function(s) {
|
||||
s = (s || '').replace(/\s+/g, ' ').replace(/[\-.,]/g, '/');
|
||||
// testing for ##-##-#### or ####-##-##, so it's not perfect; time can be included
|
||||
return (/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/).test(s);
|
||||
s = (s || '').replace(ts.regex.spaces, ' ').replace(ts.regex.shortDateReplace, '/');
|
||||
return ts.regex.shortDateTest.test(s);
|
||||
},
|
||||
format: function(s, table, cell, cellIndex) {
|
||||
if (s) {
|
||||
@ -2238,14 +2274,13 @@
|
||||
format = ci.length && ci[0].dateFormat ||
|
||||
ts.getData( ci, ts.getColumnData( table, c.headers, cellIndex ), 'dateFormat') ||
|
||||
c.dateFormat;
|
||||
// escaped "-" because JSHint in Firefox was showing it as an error
|
||||
d = s.replace(/\s+/g, ' ').replace(/[\-.,]/g, '/');
|
||||
d = s.replace(ts.regex.spaces, ' ').replace(ts.regex.shortDateReplace, '/');
|
||||
if (format === 'mmddyyyy') {
|
||||
d = d.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, '$3/$1/$2');
|
||||
d = d.replace(ts.regex.shortDateXXY, '$3/$1/$2');
|
||||
} else if (format === 'ddmmyyyy') {
|
||||
d = d.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, '$3/$2/$1');
|
||||
d = d.replace(ts.regex.shortDateXXY, '$3/$2/$1');
|
||||
} else if (format === 'yyyymmdd') {
|
||||
d = d.replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/, '$1/$2/$3');
|
||||
d = d.replace(ts.regex.shortDateYMD, '$1/$2/$3');
|
||||
}
|
||||
date = new Date(d);
|
||||
return date instanceof Date && isFinite(date) ? date.getTime() : s;
|
||||
@ -2255,13 +2290,14 @@
|
||||
type: 'numeric'
|
||||
});
|
||||
|
||||
ts.regex.timeTest = /^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i;
|
||||
ts.addParser({
|
||||
id: 'time',
|
||||
is: function(s) {
|
||||
return (/^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i).test(s);
|
||||
return ts.regex.timeTest.test(s);
|
||||
},
|
||||
format: function(s, table) {
|
||||
var date = s ? new Date( '2000/01/01 ' + s.replace(/(\S)([AP]M)$/i, '$1 $2') ) : s;
|
||||
var date = s ? new Date( '2000/01/01 ' + s.replace(ts.regex.dateReplace, '$1 $2') ) : s;
|
||||
return date instanceof Date && isFinite(date) ? date.getTime() : s;
|
||||
},
|
||||
type: 'numeric'
|
||||
@ -2678,14 +2714,15 @@
|
||||
|
||||
})(jQuery);
|
||||
|
||||
/*! Widget: filter - updated 8/17/2015 (v2.23.0) *//*
|
||||
/*! Widget: filter - updated 8/23/2015 (v2.23.2) *//*
|
||||
* Requires tablesorter v2.8+ and jQuery 1.7+
|
||||
* by Rob Garrison
|
||||
*/
|
||||
;( function ( $ ) {
|
||||
'use strict';
|
||||
var ts = $.tablesorter || {},
|
||||
tscss = ts.css;
|
||||
var tsf,
|
||||
ts = $.tablesorter || {},
|
||||
tscss = ts.css;
|
||||
|
||||
$.extend( tscss, {
|
||||
filterRow : 'tablesorter-filter-row',
|
||||
@ -2729,7 +2766,7 @@
|
||||
},
|
||||
format: function( table, c, wo ) {
|
||||
if ( !c.$table.hasClass( 'hasFilters' ) ) {
|
||||
ts.filter.init( table, c, wo );
|
||||
tsf.init( table, c, wo );
|
||||
}
|
||||
},
|
||||
remove: function( table, c, wo, refreshing ) {
|
||||
@ -2741,7 +2778,7 @@
|
||||
$table
|
||||
.removeClass( 'hasFilters' )
|
||||
// add .tsfilter namespace to all BUT search
|
||||
.unbind( events.replace( /\s+/g, ' ' ) )
|
||||
.unbind( events.replace( ts.regex.spaces, ' ' ) )
|
||||
// remove the filter row even if refreshing, because the column might have been moved
|
||||
.find( '.' + tscss.filterRow ).remove();
|
||||
if ( refreshing ) { return; }
|
||||
@ -2756,7 +2793,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
ts.filter = {
|
||||
tsf = ts.filter = {
|
||||
|
||||
// regex used in filter 'check' functions - not for general use and not documented
|
||||
regex: {
|
||||
@ -2765,9 +2802,13 @@
|
||||
filtered : /filtered/, // filtered (hidden) row class name; updated in the script
|
||||
type : /undefined|number/, // check type
|
||||
exact : /(^[\"\'=]+)|([\"\'=]+$)/g, // exact match (allow '==')
|
||||
nondigit : /[^\w,. \-()]/g, // replace non-digits (from digit & currency parser)
|
||||
operators : /[<>=]/g, // replace operators
|
||||
query : '(q|query)' // replace filter queries
|
||||
query : '(q|query)', // replace filter queries
|
||||
wild01 : /\?/g, // wild card match 0 or 1
|
||||
wild0More : /\*/g, // wild care match 0 or more
|
||||
quote : /\"/g,
|
||||
isNeg1 : /(>=?\s*-\d)/,
|
||||
isNeg2 : /(<=?\s*\d)/
|
||||
},
|
||||
// function( c, data ) { }
|
||||
// c = table.config
|
||||
@ -2784,27 +2825,27 @@
|
||||
// data.parsed = array ( by column ) of boolean values ( from filter_useParsedData or 'filter-parsed' class )
|
||||
types: {
|
||||
or : function( c, data, vars ) {
|
||||
if ( /\|/.test( data.iFilter ) || ts.filter.regex.orSplit.test( data.filter ) ) {
|
||||
if ( tsf.regex.orTest.test( data.iFilter ) || tsf.regex.orSplit.test( data.filter ) ) {
|
||||
var indx, filterMatched, query, regex,
|
||||
// duplicate data but split filter
|
||||
data2 = $.extend( {}, data ),
|
||||
index = data.index,
|
||||
parsed = data.parsed[ index ],
|
||||
filter = data.filter.split( ts.filter.regex.orSplit ),
|
||||
iFilter = data.iFilter.split( ts.filter.regex.orSplit ),
|
||||
filter = data.filter.split( tsf.regex.orSplit ),
|
||||
iFilter = data.iFilter.split( tsf.regex.orSplit ),
|
||||
len = filter.length;
|
||||
for ( indx = 0; indx < len; indx++ ) {
|
||||
data2.nestedFilters = true;
|
||||
data2.filter = '' + ( ts.filter.parseFilter( c, filter[ indx ], index, parsed ) || '' );
|
||||
data2.iFilter = '' + ( ts.filter.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
|
||||
query = '(' + ( ts.filter.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')';
|
||||
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' );
|
||||
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
|
||||
query = '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')';
|
||||
try {
|
||||
// use try/catch, because query may not be a valid regex if "|" is contained within a partial regex search,
|
||||
// e.g "/(Alex|Aar" -> Uncaught SyntaxError: Invalid regular expression: /(/(Alex)/: Unterminated group
|
||||
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
|
||||
// filterMatched = data2.filter === '' && indx > 0 ? true
|
||||
// look for an exact match with the 'or' unless the 'filter-match' class is found
|
||||
filterMatched = regex.test( data2.exact ) || ts.filter.processTypes( c, data2, vars );
|
||||
filterMatched = regex.test( data2.exact ) || tsf.processTypes( c, data2, vars );
|
||||
if ( filterMatched ) {
|
||||
return filterMatched;
|
||||
}
|
||||
@ -2819,27 +2860,27 @@
|
||||
},
|
||||
// Look for an AND or && operator ( logical and )
|
||||
and : function( c, data, vars ) {
|
||||
if ( ts.filter.regex.andTest.test( data.filter ) ) {
|
||||
if ( tsf.regex.andTest.test( data.filter ) ) {
|
||||
var indx, filterMatched, result, query, regex,
|
||||
// duplicate data but split filter
|
||||
data2 = $.extend( {}, data ),
|
||||
index = data.index,
|
||||
parsed = data.parsed[ index ],
|
||||
filter = data.filter.split( ts.filter.regex.andSplit ),
|
||||
iFilter = data.iFilter.split( ts.filter.regex.andSplit ),
|
||||
filter = data.filter.split( tsf.regex.andSplit ),
|
||||
iFilter = data.iFilter.split( tsf.regex.andSplit ),
|
||||
len = filter.length;
|
||||
for ( indx = 0; indx < len; indx++ ) {
|
||||
data2.nestedFilters = true;
|
||||
data2.filter = '' + ( ts.filter.parseFilter( c, filter[ indx ], index, parsed ) || '' );
|
||||
data2.iFilter = '' + ( ts.filter.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
|
||||
query = ( '(' + ( ts.filter.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')' )
|
||||
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' );
|
||||
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
|
||||
query = ( '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')' )
|
||||
// replace wild cards since /(a*)/i will match anything
|
||||
.replace( /\?/g, '\\S{1}' ).replace( /\*/g, '\\S*' );
|
||||
.replace( tsf.regex.wild01, '\\S{1}' ).replace( tsf.regex.wild0More, '\\S*' );
|
||||
try {
|
||||
// use try/catch just in case RegExp is invalid
|
||||
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
|
||||
// look for an exact match with the 'and' unless the 'filter-match' class is found
|
||||
result = ( regex.test( data2.exact ) || ts.filter.processTypes( c, data2, vars ) );
|
||||
result = ( regex.test( data2.exact ) || tsf.processTypes( c, data2, vars ) );
|
||||
if ( indx === 0 ) {
|
||||
filterMatched = result;
|
||||
} else {
|
||||
@ -2856,10 +2897,10 @@
|
||||
},
|
||||
// Look for regex
|
||||
regex: function( c, data ) {
|
||||
if ( ts.filter.regex.regex.test( data.filter ) ) {
|
||||
if ( tsf.regex.regex.test( data.filter ) ) {
|
||||
var matches,
|
||||
// cache regex per column for optimal speed
|
||||
regex = data.filter_regexCache[ data.index ] || ts.filter.regex.regex.exec( data.filter ),
|
||||
regex = data.filter_regexCache[ data.index ] || tsf.regex.regex.exec( data.filter ),
|
||||
isRegex = regex instanceof RegExp;
|
||||
try {
|
||||
if ( !isRegex ) {
|
||||
@ -2878,18 +2919,18 @@
|
||||
// Look for operators >, >=, < or <=
|
||||
operators: function( c, data ) {
|
||||
// ignore empty strings... because '' < 10 is true
|
||||
if ( /^[<>]=?/.test( data.iFilter ) && data.iExact !== '' ) {
|
||||
if ( tsf.regex.operTest.test( data.iFilter ) && data.iExact !== '' ) {
|
||||
var cachedValue, result, txt,
|
||||
table = c.table,
|
||||
index = data.index,
|
||||
parsed = data.parsed[index],
|
||||
query = ts.formatFloat( data.iFilter.replace( ts.filter.regex.operators, '' ), table ),
|
||||
query = ts.formatFloat( data.iFilter.replace( tsf.regex.operators, '' ), table ),
|
||||
parser = c.parsers[index],
|
||||
savedSearch = query;
|
||||
// parse filter value in case we're comparing numbers ( dates )
|
||||
if ( parsed || parser.type === 'numeric' ) {
|
||||
txt = $.trim( '' + data.iFilter.replace( ts.filter.regex.operators, '' ) );
|
||||
result = ts.filter.parseFilter( c, txt, index, true );
|
||||
txt = $.trim( '' + data.iFilter.replace( tsf.regex.operators, '' ) );
|
||||
result = tsf.parseFilter( c, txt, index, true );
|
||||
query = ( typeof result === 'number' && result !== '' && !isNaN( result ) ) ? result : query;
|
||||
}
|
||||
// iExact may be numeric - see issue #149;
|
||||
@ -2898,13 +2939,13 @@
|
||||
typeof data.cache !== 'undefined' ) {
|
||||
cachedValue = data.cache;
|
||||
} else {
|
||||
txt = isNaN( data.iExact ) ? data.iExact.replace( ts.filter.regex.nondigit, '' ) : data.iExact;
|
||||
txt = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
|
||||
cachedValue = ts.formatFloat( txt, table );
|
||||
}
|
||||
if ( />/.test( data.iFilter ) ) {
|
||||
result = />=/.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
|
||||
} else if ( /</.test( data.iFilter ) ) {
|
||||
result = /<=/.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
|
||||
if ( tsf.regex.gtTest.test( data.iFilter ) ) {
|
||||
result = tsf.regex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
|
||||
} else if ( tsf.regex.ltTest.test( data.iFilter ) ) {
|
||||
result = tsf.regex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
|
||||
}
|
||||
// keep showing all rows if nothing follows the operator
|
||||
if ( !result && savedSearch === '' ) {
|
||||
@ -2916,13 +2957,13 @@
|
||||
},
|
||||
// Look for a not match
|
||||
notMatch: function( c, data ) {
|
||||
if ( /^\!/.test( data.iFilter ) ) {
|
||||
if ( tsf.regex.notTest.test( data.iFilter ) ) {
|
||||
var indx,
|
||||
txt = data.iFilter.replace( '!', '' ),
|
||||
filter = ts.filter.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
||||
if ( ts.filter.regex.exact.test( filter ) ) {
|
||||
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
||||
if ( tsf.regex.exact.test( filter ) ) {
|
||||
// look for exact not matches - see #628
|
||||
filter = filter.replace( ts.filter.regex.exact, '' );
|
||||
filter = filter.replace( tsf.regex.exact, '' );
|
||||
return filter === '' ? true : $.trim( filter ) !== data.iExact;
|
||||
} else {
|
||||
indx = data.iExact.search( $.trim( filter ) );
|
||||
@ -2934,27 +2975,27 @@
|
||||
// Look for quotes or equals to get an exact match; ignore type since iExact could be numeric
|
||||
exact: function( c, data ) {
|
||||
/*jshint eqeqeq:false */
|
||||
if ( ts.filter.regex.exact.test( data.iFilter ) ) {
|
||||
var txt = data.iFilter.replace( ts.filter.regex.exact, '' ),
|
||||
filter = ts.filter.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
||||
if ( tsf.regex.exact.test( data.iFilter ) ) {
|
||||
var txt = data.iFilter.replace( tsf.regex.exact, '' ),
|
||||
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
||||
return data.anyMatch ? $.inArray( filter, data.rowArray ) >= 0 : filter == data.iExact;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
// Look for a range ( using ' to ' or ' - ' ) - see issue #166; thanks matzhu!
|
||||
range : function( c, data ) {
|
||||
if ( ts.filter.regex.toTest.test( data.iFilter ) ) {
|
||||
if ( tsf.regex.toTest.test( data.iFilter ) ) {
|
||||
var result, tmp, range1, range2,
|
||||
table = c.table,
|
||||
index = data.index,
|
||||
parsed = data.parsed[index],
|
||||
// make sure the dash is for a range and not indicating a negative number
|
||||
query = data.iFilter.split( ts.filter.regex.toSplit );
|
||||
query = data.iFilter.split( tsf.regex.toSplit );
|
||||
|
||||
tmp = query[0].replace( ts.filter.regex.nondigit, '' ) || '';
|
||||
range1 = ts.formatFloat( ts.filter.parseFilter( c, tmp, index, parsed ), table );
|
||||
tmp = query[1].replace( ts.filter.regex.nondigit, '' ) || '';
|
||||
range2 = ts.formatFloat( ts.filter.parseFilter( c, tmp, index, parsed ), table );
|
||||
tmp = query[0].replace( ts.regex.nondigit, '' ) || '';
|
||||
range1 = ts.formatFloat( tsf.parseFilter( c, tmp, index, parsed ), table );
|
||||
tmp = query[1].replace( ts.regex.nondigit, '' ) || '';
|
||||
range2 = ts.formatFloat( tsf.parseFilter( c, tmp, index, parsed ), table );
|
||||
// parse filter value in case we're comparing numbers ( dates )
|
||||
if ( parsed || c.parsers[index].type === 'numeric' ) {
|
||||
result = c.parsers[ index ].format( '' + query[0], table, c.$headers.eq( index ), index );
|
||||
@ -2965,7 +3006,7 @@
|
||||
if ( ( parsed || c.parsers[ index ].type === 'numeric' ) && !isNaN( range1 ) && !isNaN( range2 ) ) {
|
||||
result = data.cache;
|
||||
} else {
|
||||
tmp = isNaN( data.iExact ) ? data.iExact.replace( ts.filter.regex.nondigit, '' ) : data.iExact;
|
||||
tmp = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
|
||||
result = ts.formatFloat( tmp, table );
|
||||
}
|
||||
if ( range1 > range2 ) {
|
||||
@ -2977,18 +3018,18 @@
|
||||
},
|
||||
// Look for wild card: ? = single, * = multiple, or | = logical OR
|
||||
wild : function( c, data ) {
|
||||
if ( /[\?\*\|]/.test( data.iFilter ) ) {
|
||||
if ( tsf.regex.wildOrTest.test( data.iFilter ) ) {
|
||||
var index = data.index,
|
||||
parsed = data.parsed[ index ],
|
||||
query = '' + ( ts.filter.parseFilter( c, data.iFilter, index, parsed ) || '' );
|
||||
query = '' + ( tsf.parseFilter( c, data.iFilter, index, parsed ) || '' );
|
||||
// look for an exact match with the 'or' unless the 'filter-match' class is found
|
||||
if ( !/\?\*/.test( query ) && data.nestedFilters ) {
|
||||
if ( !tsf.regex.wildTest.test( query ) && data.nestedFilters ) {
|
||||
query = data.isMatch ? query : '^(' + query + ')$';
|
||||
}
|
||||
// parsing the filter may not work properly when using wildcards =/
|
||||
try {
|
||||
return new RegExp(
|
||||
query.replace( /\?/g, '\\S{1}' ).replace( /\*/g, '\\S*' ),
|
||||
query.replace( tsf.regex.wild01, '\\S{1}' ).replace( tsf.regex.wild0More, '\\S*' ),
|
||||
c.widgetOptions.filter_ignoreCase ? 'i' : ''
|
||||
)
|
||||
.test( data.exact );
|
||||
@ -3000,12 +3041,12 @@
|
||||
},
|
||||
// fuzzy text search; modified from https://github.com/mattyork/fuzzy ( MIT license )
|
||||
fuzzy: function( c, data ) {
|
||||
if ( /^~/.test( data.iFilter ) ) {
|
||||
if ( tsf.regex.fuzzyTest.test( data.iFilter ) ) {
|
||||
var indx,
|
||||
patternIndx = 0,
|
||||
len = data.iExact.length,
|
||||
txt = data.iFilter.slice( 1 ),
|
||||
pattern = ts.filter.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
||||
pattern = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
||||
for ( indx = 0; indx < len; indx++ ) {
|
||||
if ( data.iExact[ indx ] === pattern[ patternIndx ] ) {
|
||||
patternIndx += 1;
|
||||
@ -3028,7 +3069,7 @@
|
||||
}, ts.language );
|
||||
|
||||
var options, string, txt, $header, column, filters, val, fxn, noSelect,
|
||||
regex = ts.filter.regex;
|
||||
regex = tsf.regex;
|
||||
c.$table.addClass( 'hasFilters' );
|
||||
|
||||
// define timers so using clearTimeout won't cause an undefined error
|
||||
@ -3039,7 +3080,7 @@
|
||||
wo.filter_anyColumnSelector = '[data-column="all"],[data-column="any"]';
|
||||
wo.filter_multipleColumnSelector = '[data-column*="-"],[data-column*=","]';
|
||||
|
||||
val = '\\{' + ts.filter.regex.query + '\\}';
|
||||
val = '\\{' + tsf.regex.query + '\\}';
|
||||
$.extend( regex, {
|
||||
child : new RegExp( c.cssChildRow ),
|
||||
filtered : new RegExp( wo.filter_filteredRow ),
|
||||
@ -3048,9 +3089,20 @@
|
||||
toSplit : new RegExp( '(?:\\s+(?:-|' + ts.language.to + ')\\s+)', 'gi' ),
|
||||
andTest : new RegExp( '\\s+(' + ts.language.and + '|&&)\\s+', 'i' ),
|
||||
andSplit : new RegExp( '(?:\\s+(?:' + ts.language.and + '|&&)\\s+)', 'gi' ),
|
||||
orTest : /\|/,
|
||||
orSplit : new RegExp( '(?:\\s+(?:' + ts.language.or + ')\\s+|\\|)', 'gi' ),
|
||||
iQuery : new RegExp( val, 'i' ),
|
||||
igQuery : new RegExp( val, 'ig' )
|
||||
igQuery : new RegExp( val, 'ig' ),
|
||||
operTest : /^[<>]=?/,
|
||||
gtTest : />/,
|
||||
gteTest : />=/,
|
||||
ltTest : /</,
|
||||
lteTest : /<=/,
|
||||
notTest : /^\!/,
|
||||
wildOrTest : /[\?\*\|]/,
|
||||
wildTest : /\?\*/,
|
||||
fuzzyTest : /^~/,
|
||||
exactTest : /[=\"\|!]/
|
||||
});
|
||||
|
||||
// don't build filter row if columnFilters is false or all columns are set to 'filter-false'
|
||||
@ -3058,7 +3110,7 @@
|
||||
val = c.$headers.filter( '.filter-false, .parser-false' ).length;
|
||||
if ( wo.filter_columnFilters !== false && val !== c.$headers.length ) {
|
||||
// build filter row
|
||||
ts.filter.buildRow( table, c, wo );
|
||||
tsf.buildRow( table, c, wo );
|
||||
}
|
||||
|
||||
txt = 'addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search '
|
||||
@ -3071,13 +3123,13 @@
|
||||
c.$table.find( '.' + tscss.filterRow ).toggleClass( wo.filter_filteredRow, val ); // fixes #450
|
||||
if ( !/(search|filter)/.test( event.type ) ) {
|
||||
event.stopPropagation();
|
||||
ts.filter.buildDefault( table, true );
|
||||
tsf.buildDefault( table, true );
|
||||
}
|
||||
if ( event.type === 'filterReset' ) {
|
||||
c.$table.find( '.' + tscss.filter ).add( wo.filter_$externalFilters ).val( '' );
|
||||
ts.filter.searching( table, [] );
|
||||
tsf.searching( table, [] );
|
||||
} else if ( event.type === 'filterEnd' ) {
|
||||
ts.filter.buildDefault( table, true );
|
||||
tsf.buildDefault( table, true );
|
||||
} else {
|
||||
// send false argument to force a new search; otherwise if the filter hasn't changed,
|
||||
// it will return
|
||||
@ -3091,7 +3143,7 @@
|
||||
// pass true ( skipFirst ) to prevent the tablesorter.setFilters function from skipping the first
|
||||
// input ensures all inputs are updated when a search is triggered on the table
|
||||
// $( 'table' ).trigger( 'search', [...] );
|
||||
ts.filter.searching( table, filter, true );
|
||||
tsf.searching( table, filter, true );
|
||||
}
|
||||
return false;
|
||||
});
|
||||
@ -3124,7 +3176,7 @@
|
||||
noSelect = !( $header.hasClass( 'filter-false' ) || $header.hasClass( 'parser-false' ) );
|
||||
options = '';
|
||||
if ( fxn === true && noSelect ) {
|
||||
ts.filter.buildSelect( table, column );
|
||||
tsf.buildSelect( table, column );
|
||||
} else if ( typeof fxn === 'object' && noSelect ) {
|
||||
// add custom drop down list
|
||||
for ( string in fxn ) {
|
||||
@ -3157,7 +3209,7 @@
|
||||
fxn = $.isFunction( txt ) ? true : ts.getColumnData( table, txt, column );
|
||||
if ( fxn ) {
|
||||
// updating so the extra options are appended
|
||||
ts.filter.buildSelect( c.table, column, '', true, $header.hasClass( wo.filter_onlyAvail ) );
|
||||
tsf.buildSelect( c.table, column, '', true, $header.hasClass( wo.filter_onlyAvail ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3165,22 +3217,22 @@
|
||||
}
|
||||
// not really updating, but if the column has both the 'filter-select' class &
|
||||
// filter_functions set to true, it would append the same options twice.
|
||||
ts.filter.buildDefault( table, true );
|
||||
tsf.buildDefault( table, true );
|
||||
|
||||
ts.filter.bindSearch( table, c.$table.find( '.' + tscss.filter ), true );
|
||||
tsf.bindSearch( table, c.$table.find( '.' + tscss.filter ), true );
|
||||
if ( wo.filter_external ) {
|
||||
ts.filter.bindSearch( table, wo.filter_external );
|
||||
tsf.bindSearch( table, wo.filter_external );
|
||||
}
|
||||
|
||||
if ( wo.filter_hideFilters ) {
|
||||
ts.filter.hideFilters( table, c );
|
||||
tsf.hideFilters( table, c );
|
||||
}
|
||||
|
||||
// show processing icon
|
||||
if ( c.showProcessing ) {
|
||||
txt = 'filterStart filterEnd '.split( ' ' ).join( c.namespace + 'filter ' );
|
||||
c.$table
|
||||
.unbind( txt.replace( /\s+/g, ' ' ) )
|
||||
.unbind( txt.replace( ts.regex.spaces, ' ' ) )
|
||||
.bind( txt, function( event, columns ) {
|
||||
// only add processing to certain columns to all columns
|
||||
$header = ( columns ) ?
|
||||
@ -3200,11 +3252,11 @@
|
||||
// add default values
|
||||
txt = 'tablesorter-initialized pagerBeforeInitialized '.split( ' ' ).join( c.namespace + 'filter ' );
|
||||
c.$table
|
||||
.unbind( txt.replace( /\s+/g, ' ' ) )
|
||||
.unbind( txt.replace( ts.regex.spaces, ' ' ) )
|
||||
.bind( txt, function() {
|
||||
// redefine 'wo' as it does not update properly inside this callback
|
||||
var wo = this.config.widgetOptions;
|
||||
filters = ts.filter.setDefaults( table, c, wo ) || [];
|
||||
filters = tsf.setDefaults( table, c, wo ) || [];
|
||||
if ( filters.length ) {
|
||||
// prevent delayInit from triggering a cache build if filters are empty
|
||||
if ( !( c.delayInit && filters.join( '' ) === '' ) ) {
|
||||
@ -3215,7 +3267,7 @@
|
||||
// trigger init after setTimeout to prevent multiple filterStart/End/Init triggers
|
||||
setTimeout( function() {
|
||||
if ( !wo.filter_initialized ) {
|
||||
ts.filter.filterInitComplete( c );
|
||||
tsf.filterInitComplete( c );
|
||||
}
|
||||
}, 100 );
|
||||
});
|
||||
@ -3223,7 +3275,7 @@
|
||||
if ( c.pager && c.pager.initialized && !wo.filter_initialized ) {
|
||||
c.$table.trigger( 'filterFomatterUpdate' );
|
||||
setTimeout( function() {
|
||||
ts.filter.filterInitComplete( c );
|
||||
tsf.filterInitComplete( c );
|
||||
}, 100 );
|
||||
}
|
||||
},
|
||||
@ -3244,7 +3296,7 @@
|
||||
completed = function() {
|
||||
wo.filter_initialized = true;
|
||||
c.$table.trigger( 'filterInit', c );
|
||||
ts.filter.findRows( c.table, c.$table.data( 'lastSearch' ) || [] );
|
||||
tsf.findRows( c.table, c.$table.data( 'lastSearch' ) || [] );
|
||||
};
|
||||
if ( $.isEmptyObject( wo.filter_formatter ) ) {
|
||||
completed();
|
||||
@ -3396,7 +3448,7 @@
|
||||
// use data attribute instead of jQuery data since the head is cloned without including
|
||||
// the data/binding
|
||||
.attr( 'data-lastSearchTime', new Date().getTime() )
|
||||
.unbind( tmp.replace( /\s+/g, ' ' ) )
|
||||
.unbind( tmp.replace( ts.regex.spaces, ' ' ) )
|
||||
// include change for select - fixes #473
|
||||
.bind( 'keyup' + namespace, function( event ) {
|
||||
$( this ).attr( 'data-lastSearchTime', new Date().getTime() );
|
||||
@ -3416,7 +3468,7 @@
|
||||
return;
|
||||
}
|
||||
// change event = no delay; last true flag tells getFilters to skip newest timed input
|
||||
ts.filter.searching( table, true, true );
|
||||
tsf.searching( table, true, true );
|
||||
})
|
||||
.bind( 'search change keypress '.split( ' ' ).join( namespace + ' ' ), function( event ) {
|
||||
// don't get cached data, in case data-column changes dynamically
|
||||
@ -3427,7 +3479,7 @@
|
||||
event.preventDefault();
|
||||
// init search with no delay
|
||||
$( this ).attr( 'data-lastSearchTime', new Date().getTime() );
|
||||
ts.filter.searching( table, false, true );
|
||||
tsf.searching( table, false, true );
|
||||
}
|
||||
});
|
||||
},
|
||||
@ -3437,11 +3489,11 @@
|
||||
if ( typeof filter === 'undefined' || filter === true ) {
|
||||
// delay filtering
|
||||
wo.searchTimer = setTimeout( function() {
|
||||
ts.filter.checkFilters( table, filter, skipFirst );
|
||||
tsf.checkFilters( table, filter, skipFirst );
|
||||
}, wo.filter_liveSearch ? wo.filter_searchDelay : 10 );
|
||||
} else {
|
||||
// skip delay
|
||||
ts.filter.checkFilters( table, filter, skipFirst );
|
||||
tsf.checkFilters( table, filter, skipFirst );
|
||||
}
|
||||
},
|
||||
checkFilters: function( table, filter, skipFirst ) {
|
||||
@ -3455,7 +3507,7 @@
|
||||
// update cache if delayInit set & pager has initialized ( after user initiates a search )
|
||||
if ( c.delayInit && c.pager && c.pager.initialized ) {
|
||||
c.$table.trigger( 'updateCache', [ function() {
|
||||
ts.filter.checkFilters( table, false, skipFirst );
|
||||
tsf.checkFilters( table, false, skipFirst );
|
||||
} ] );
|
||||
}
|
||||
return;
|
||||
@ -3486,11 +3538,11 @@
|
||||
if ( c.showProcessing ) {
|
||||
// give it time for the processing icon to kick in
|
||||
setTimeout( function() {
|
||||
ts.filter.findRows( table, filters, combinedFilters );
|
||||
tsf.findRows( table, filters, combinedFilters );
|
||||
return false;
|
||||
}, 30 );
|
||||
} else {
|
||||
ts.filter.findRows( table, filters, combinedFilters );
|
||||
tsf.findRows( table, filters, combinedFilters );
|
||||
return false;
|
||||
}
|
||||
},
|
||||
@ -3533,8 +3585,8 @@
|
||||
},
|
||||
defaultFilter: function( filter, mask ) {
|
||||
if ( filter === '' ) { return filter; }
|
||||
var regex = ts.filter.regex.iQuery,
|
||||
maskLen = mask.match( ts.filter.regex.igQuery ).length,
|
||||
var regex = tsf.regex.iQuery,
|
||||
maskLen = mask.match( tsf.regex.igQuery ).length,
|
||||
query = maskLen > 1 ? $.trim( filter ).split( /\s/ ) : [ $.trim( filter ) ],
|
||||
len = query.length - 1,
|
||||
indx = 0,
|
||||
@ -3570,7 +3622,7 @@
|
||||
// & don't target 'all' column inputs if they don't exist
|
||||
targets = wo.filter_initialized || !$input.filter( wo.filter_anyColumnSelector ).length,
|
||||
columns = [],
|
||||
val = $.trim( ts.filter.getLatestSearch( $input ).attr( 'data-column' ) || '' );
|
||||
val = $.trim( tsf.getLatestSearch( $input ).attr( 'data-column' ) || '' );
|
||||
if ( !/[,-]/.test(val) && val.length === 1 ) {
|
||||
return parseInt( val, 10 );
|
||||
}
|
||||
@ -3620,9 +3672,9 @@
|
||||
var ffxn,
|
||||
filterMatched = null,
|
||||
matches = null;
|
||||
for ( ffxn in ts.filter.types ) {
|
||||
for ( ffxn in tsf.types ) {
|
||||
if ( $.inArray( ffxn, vars.excludeMatch ) < 0 && matches === null ) {
|
||||
matches = ts.filter.types[ffxn]( c, data, vars );
|
||||
matches = tsf.types[ffxn]( c, data, vars );
|
||||
if ( matches !== null ) {
|
||||
filterMatched = matches;
|
||||
}
|
||||
@ -3633,7 +3685,7 @@
|
||||
processRow: function( c, data, vars ) {
|
||||
var hasSelect, result, val, filterMatched,
|
||||
fxn, ffxn, txt,
|
||||
regex = ts.filter.regex,
|
||||
regex = tsf.regex,
|
||||
wo = c.widgetOptions,
|
||||
showRow = true,
|
||||
|
||||
@ -3642,7 +3694,7 @@
|
||||
// for the entire row - see #998
|
||||
columnIndex = wo.filter_$anyMatch && wo.filter_$anyMatch.length ?
|
||||
// look for multiple columns '1-3,4-6,8'
|
||||
ts.filter.multipleColumns( c, wo.filter_$anyMatch ) :
|
||||
tsf.multipleColumns( c, wo.filter_$anyMatch ) :
|
||||
[];
|
||||
|
||||
data.$cells = data.$row.children();
|
||||
@ -3671,7 +3723,7 @@
|
||||
data.cache = data.cacheArray.slice( 0, -1 ).join( ' ' );
|
||||
|
||||
vars.excludeMatch = vars.noAnyMatch;
|
||||
filterMatched = ts.filter.processTypes( c, data, vars );
|
||||
filterMatched = tsf.processTypes( c, data, vars );
|
||||
|
||||
if ( filterMatched !== null ) {
|
||||
showRow = filterMatched;
|
||||
@ -3732,7 +3784,7 @@
|
||||
|
||||
val = true;
|
||||
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultColFilter[ columnIndex ] ) ) {
|
||||
data.filter = ts.filter.defaultFilter( data.filter, vars.defaultColFilter[ columnIndex ] );
|
||||
data.filter = tsf.defaultFilter( data.filter, vars.defaultColFilter[ columnIndex ] );
|
||||
// val is used to indicate that a filter select is using a default filter;
|
||||
// so we override the exact & partial matches
|
||||
val = false;
|
||||
@ -3763,13 +3815,13 @@
|
||||
if ( filterMatched === null ) {
|
||||
// cycle through the different filters
|
||||
// filters return a boolean or null if nothing matches
|
||||
filterMatched = ts.filter.processTypes( c, data, vars );
|
||||
filterMatched = tsf.processTypes( c, data, vars );
|
||||
if ( filterMatched !== null ) {
|
||||
result = filterMatched;
|
||||
// Look for match, and add child row data for matching
|
||||
} else {
|
||||
txt = ( data.iExact + data.childRowText )
|
||||
.indexOf( ts.filter.parseFilter( c, data.iFilter, columnIndex, data.parsed[ columnIndex ] ) );
|
||||
.indexOf( tsf.parseFilter( c, data.iFilter, columnIndex, data.parsed[ columnIndex ] ) );
|
||||
result = ( ( !wo.filter_startsWith && txt >= 0 ) || ( wo.filter_startsWith && txt === 0 ) );
|
||||
}
|
||||
} else {
|
||||
@ -3789,7 +3841,7 @@
|
||||
isChild, childRow, lastSearch, showRow, time, val, indx,
|
||||
notFiltered, searchFiltered, query, injected, res, id, txt,
|
||||
storedFilters = $.extend( [], filters ),
|
||||
regex = ts.filter.regex,
|
||||
regex = tsf.regex,
|
||||
c = table.config,
|
||||
wo = c.widgetOptions,
|
||||
// data object passed to filters; anyMatch is a flag for the filters
|
||||
@ -3866,7 +3918,7 @@
|
||||
data.anyMatchFlag = true;
|
||||
data.anyMatchFilter = '' + (
|
||||
filters[ c.columns ] ||
|
||||
wo.filter_$anyMatch && ts.filter.getLatestSearch( wo.filter_$anyMatch ).val() ||
|
||||
wo.filter_$anyMatch && tsf.getLatestSearch( wo.filter_$anyMatch ).val() ||
|
||||
''
|
||||
);
|
||||
if ( wo.filter_columnAnyMatch ) {
|
||||
@ -3908,10 +3960,10 @@
|
||||
// if there is NOT a logical 'or', or range ( 'to' or '-' ) in the string
|
||||
!regex.alreadyFiltered.test( val ) &&
|
||||
// if we are not doing exact matches, using '|' ( logical or ) or not '!'
|
||||
!/[=\"\|!]/.test( val ) &&
|
||||
!regex.exactTest.test( val ) &&
|
||||
// don't search only filtered if the value is negative
|
||||
// ( '> -10' => '> -100' will ignore hidden rows )
|
||||
!( /(>=?\s*-\d)/.test( val ) || /(<=?\s*\d)/.test( val ) ) &&
|
||||
!( regex.isNeg1.test( val ) || regex.isNeg2.test( val ) ) &&
|
||||
// if filtering using a select without a 'filter-match' class ( exact match ) - fixes #593
|
||||
!( val !== '' && c.$filters && c.$filters.eq( indx ).find( 'select' ).length &&
|
||||
!c.$headerIndexed[indx].hasClass( 'filter-match' ) );
|
||||
@ -3930,7 +3982,7 @@
|
||||
data.anyMatchFilter = ts.replaceAccents( data.anyMatchFilter );
|
||||
}
|
||||
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultAnyFilter ) ) {
|
||||
data.anyMatchFilter = ts.filter.defaultFilter( data.anyMatchFilter, vars.defaultAnyFilter );
|
||||
data.anyMatchFilter = tsf.defaultFilter( data.anyMatchFilter, vars.defaultAnyFilter );
|
||||
// clear search filtered flag because default filters are not saved to the last search
|
||||
searchFiltered = false;
|
||||
}
|
||||
@ -3973,7 +4025,7 @@
|
||||
'';
|
||||
}
|
||||
|
||||
showRow = ts.filter.processRow( c, data, vars );
|
||||
showRow = tsf.processRow( c, data, vars );
|
||||
childRow = rowData.$row.filter( ':gt( 0 )' );
|
||||
|
||||
if ( wo.filter_childRows && childRow.length ) {
|
||||
@ -3984,7 +4036,7 @@
|
||||
data.cacheArray = rowData.child[ indx ];
|
||||
data.rawArray = data.cacheArray;
|
||||
// use OR comparison on child rows
|
||||
showRow = showRow || ts.filter.processRow( c, data, vars );
|
||||
showRow = showRow || tsf.processRow( c, data, vars );
|
||||
}
|
||||
}
|
||||
childRow.toggleClass( wo.filter_filteredRow, !showRow );
|
||||
@ -4046,7 +4098,7 @@
|
||||
}
|
||||
if ( arry === false ) {
|
||||
// fall back to original method
|
||||
arry = ts.filter.getOptions( table, column, onlyAvail );
|
||||
arry = tsf.getOptions( table, column, onlyAvail );
|
||||
}
|
||||
|
||||
// get unique elements and sort the list
|
||||
@ -4158,13 +4210,13 @@
|
||||
// nothing included in arry ( external source ), so get the options from
|
||||
// filter_selectSource or column data
|
||||
if ( typeof arry === 'undefined' || arry === '' ) {
|
||||
arry = ts.filter.getOptionSource( table, column, onlyAvail );
|
||||
arry = tsf.getOptionSource( table, column, onlyAvail );
|
||||
}
|
||||
|
||||
if ( $.isArray( arry ) ) {
|
||||
// build option list
|
||||
for ( indx = 0; indx < arry.length; indx++ ) {
|
||||
txt = arry[indx] = ( '' + arry[indx] ).replace( /\"/g, '"' );
|
||||
txt = arry[indx] = ( '' + arry[indx] ).replace( tsf.regex.quote, '"' );
|
||||
val = txt;
|
||||
// allow including a symbol in the selectSource array
|
||||
// 'a-z|A through Z' so that 'a-z' becomes the option value
|
||||
@ -4220,7 +4272,7 @@
|
||||
// look for the filter-select class; build/update it if found
|
||||
if ( ( $header.hasClass( 'filter-select' ) ||
|
||||
ts.getColumnData( table, wo.filter_functions, columnIndex ) === true ) && noSelect ) {
|
||||
ts.filter.buildSelect( table, columnIndex, '', updating, $header.hasClass( wo.filter_onlyAvail ) );
|
||||
tsf.buildSelect( table, columnIndex, '', updating, $header.hasClass( wo.filter_onlyAvail ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4256,7 +4308,7 @@
|
||||
$column = $filters.filter( cols );
|
||||
if ( $column.length ) {
|
||||
// move the latest search to the first slot in the array
|
||||
$column = ts.filter.getLatestSearch( $column );
|
||||
$column = tsf.getLatestSearch( $column );
|
||||
if ( $.isArray( setFilters ) ) {
|
||||
// skip first ( latest input ) to maintain cursor position while typing
|
||||
if ( skipFirst && $column.length > 1 ) {
|
||||
@ -4306,7 +4358,7 @@
|
||||
// ensure new set filters are applied, even if the search is the same
|
||||
c.lastCombinedFilter = null;
|
||||
c.lastSearch = [];
|
||||
ts.filter.searching( c.table, filter, skipFirst );
|
||||
tsf.searching( c.table, filter, skipFirst );
|
||||
c.$table.trigger( 'filterFomatterUpdate' );
|
||||
}
|
||||
return !!valid;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*! TableSorter (FORK) v2.23.1 *//*
|
||||
/*! TableSorter (FORK) v2.23.2 *//*
|
||||
* Client-side table sorting with ease!
|
||||
* @requires jQuery v1.2.6+
|
||||
*
|
||||
@ -26,7 +26,7 @@
|
||||
|
||||
var ts = this;
|
||||
|
||||
ts.version = '2.23.1';
|
||||
ts.version = '2.23.2';
|
||||
|
||||
ts.parsers = [];
|
||||
ts.widgets = [];
|
||||
|
@ -4,7 +4,7 @@
|
||||
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██▀▀ ▀▀▀▀██
|
||||
█████▀ ▀████▀ ██ ██ ▀████▀ ██ ██ ██ ██ ▀████▀ █████▀ ██ ██ █████▀
|
||||
*/
|
||||
/*! tablesorter (FORK) - updated 08-21-2015 (v2.23.1)*/
|
||||
/*! tablesorter (FORK) - updated 08-23-2015 (v2.23.2)*/
|
||||
/* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */
|
||||
(function(factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
@ -372,14 +372,15 @@
|
||||
|
||||
})(jQuery);
|
||||
|
||||
/*! Widget: filter - updated 8/17/2015 (v2.23.0) *//*
|
||||
/*! Widget: filter - updated 8/23/2015 (v2.23.2) *//*
|
||||
* Requires tablesorter v2.8+ and jQuery 1.7+
|
||||
* by Rob Garrison
|
||||
*/
|
||||
;( function ( $ ) {
|
||||
'use strict';
|
||||
var ts = $.tablesorter || {},
|
||||
tscss = ts.css;
|
||||
var tsf,
|
||||
ts = $.tablesorter || {},
|
||||
tscss = ts.css;
|
||||
|
||||
$.extend( tscss, {
|
||||
filterRow : 'tablesorter-filter-row',
|
||||
@ -423,7 +424,7 @@
|
||||
},
|
||||
format: function( table, c, wo ) {
|
||||
if ( !c.$table.hasClass( 'hasFilters' ) ) {
|
||||
ts.filter.init( table, c, wo );
|
||||
tsf.init( table, c, wo );
|
||||
}
|
||||
},
|
||||
remove: function( table, c, wo, refreshing ) {
|
||||
@ -435,7 +436,7 @@
|
||||
$table
|
||||
.removeClass( 'hasFilters' )
|
||||
// add .tsfilter namespace to all BUT search
|
||||
.unbind( events.replace( /\s+/g, ' ' ) )
|
||||
.unbind( events.replace( ts.regex.spaces, ' ' ) )
|
||||
// remove the filter row even if refreshing, because the column might have been moved
|
||||
.find( '.' + tscss.filterRow ).remove();
|
||||
if ( refreshing ) { return; }
|
||||
@ -450,7 +451,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
ts.filter = {
|
||||
tsf = ts.filter = {
|
||||
|
||||
// regex used in filter 'check' functions - not for general use and not documented
|
||||
regex: {
|
||||
@ -459,9 +460,13 @@
|
||||
filtered : /filtered/, // filtered (hidden) row class name; updated in the script
|
||||
type : /undefined|number/, // check type
|
||||
exact : /(^[\"\'=]+)|([\"\'=]+$)/g, // exact match (allow '==')
|
||||
nondigit : /[^\w,. \-()]/g, // replace non-digits (from digit & currency parser)
|
||||
operators : /[<>=]/g, // replace operators
|
||||
query : '(q|query)' // replace filter queries
|
||||
query : '(q|query)', // replace filter queries
|
||||
wild01 : /\?/g, // wild card match 0 or 1
|
||||
wild0More : /\*/g, // wild care match 0 or more
|
||||
quote : /\"/g,
|
||||
isNeg1 : /(>=?\s*-\d)/,
|
||||
isNeg2 : /(<=?\s*\d)/
|
||||
},
|
||||
// function( c, data ) { }
|
||||
// c = table.config
|
||||
@ -478,27 +483,27 @@
|
||||
// data.parsed = array ( by column ) of boolean values ( from filter_useParsedData or 'filter-parsed' class )
|
||||
types: {
|
||||
or : function( c, data, vars ) {
|
||||
if ( /\|/.test( data.iFilter ) || ts.filter.regex.orSplit.test( data.filter ) ) {
|
||||
if ( tsf.regex.orTest.test( data.iFilter ) || tsf.regex.orSplit.test( data.filter ) ) {
|
||||
var indx, filterMatched, query, regex,
|
||||
// duplicate data but split filter
|
||||
data2 = $.extend( {}, data ),
|
||||
index = data.index,
|
||||
parsed = data.parsed[ index ],
|
||||
filter = data.filter.split( ts.filter.regex.orSplit ),
|
||||
iFilter = data.iFilter.split( ts.filter.regex.orSplit ),
|
||||
filter = data.filter.split( tsf.regex.orSplit ),
|
||||
iFilter = data.iFilter.split( tsf.regex.orSplit ),
|
||||
len = filter.length;
|
||||
for ( indx = 0; indx < len; indx++ ) {
|
||||
data2.nestedFilters = true;
|
||||
data2.filter = '' + ( ts.filter.parseFilter( c, filter[ indx ], index, parsed ) || '' );
|
||||
data2.iFilter = '' + ( ts.filter.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
|
||||
query = '(' + ( ts.filter.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')';
|
||||
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' );
|
||||
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
|
||||
query = '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')';
|
||||
try {
|
||||
// use try/catch, because query may not be a valid regex if "|" is contained within a partial regex search,
|
||||
// e.g "/(Alex|Aar" -> Uncaught SyntaxError: Invalid regular expression: /(/(Alex)/: Unterminated group
|
||||
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
|
||||
// filterMatched = data2.filter === '' && indx > 0 ? true
|
||||
// look for an exact match with the 'or' unless the 'filter-match' class is found
|
||||
filterMatched = regex.test( data2.exact ) || ts.filter.processTypes( c, data2, vars );
|
||||
filterMatched = regex.test( data2.exact ) || tsf.processTypes( c, data2, vars );
|
||||
if ( filterMatched ) {
|
||||
return filterMatched;
|
||||
}
|
||||
@ -513,27 +518,27 @@
|
||||
},
|
||||
// Look for an AND or && operator ( logical and )
|
||||
and : function( c, data, vars ) {
|
||||
if ( ts.filter.regex.andTest.test( data.filter ) ) {
|
||||
if ( tsf.regex.andTest.test( data.filter ) ) {
|
||||
var indx, filterMatched, result, query, regex,
|
||||
// duplicate data but split filter
|
||||
data2 = $.extend( {}, data ),
|
||||
index = data.index,
|
||||
parsed = data.parsed[ index ],
|
||||
filter = data.filter.split( ts.filter.regex.andSplit ),
|
||||
iFilter = data.iFilter.split( ts.filter.regex.andSplit ),
|
||||
filter = data.filter.split( tsf.regex.andSplit ),
|
||||
iFilter = data.iFilter.split( tsf.regex.andSplit ),
|
||||
len = filter.length;
|
||||
for ( indx = 0; indx < len; indx++ ) {
|
||||
data2.nestedFilters = true;
|
||||
data2.filter = '' + ( ts.filter.parseFilter( c, filter[ indx ], index, parsed ) || '' );
|
||||
data2.iFilter = '' + ( ts.filter.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
|
||||
query = ( '(' + ( ts.filter.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')' )
|
||||
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' );
|
||||
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
|
||||
query = ( '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')' )
|
||||
// replace wild cards since /(a*)/i will match anything
|
||||
.replace( /\?/g, '\\S{1}' ).replace( /\*/g, '\\S*' );
|
||||
.replace( tsf.regex.wild01, '\\S{1}' ).replace( tsf.regex.wild0More, '\\S*' );
|
||||
try {
|
||||
// use try/catch just in case RegExp is invalid
|
||||
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
|
||||
// look for an exact match with the 'and' unless the 'filter-match' class is found
|
||||
result = ( regex.test( data2.exact ) || ts.filter.processTypes( c, data2, vars ) );
|
||||
result = ( regex.test( data2.exact ) || tsf.processTypes( c, data2, vars ) );
|
||||
if ( indx === 0 ) {
|
||||
filterMatched = result;
|
||||
} else {
|
||||
@ -550,10 +555,10 @@
|
||||
},
|
||||
// Look for regex
|
||||
regex: function( c, data ) {
|
||||
if ( ts.filter.regex.regex.test( data.filter ) ) {
|
||||
if ( tsf.regex.regex.test( data.filter ) ) {
|
||||
var matches,
|
||||
// cache regex per column for optimal speed
|
||||
regex = data.filter_regexCache[ data.index ] || ts.filter.regex.regex.exec( data.filter ),
|
||||
regex = data.filter_regexCache[ data.index ] || tsf.regex.regex.exec( data.filter ),
|
||||
isRegex = regex instanceof RegExp;
|
||||
try {
|
||||
if ( !isRegex ) {
|
||||
@ -572,18 +577,18 @@
|
||||
// Look for operators >, >=, < or <=
|
||||
operators: function( c, data ) {
|
||||
// ignore empty strings... because '' < 10 is true
|
||||
if ( /^[<>]=?/.test( data.iFilter ) && data.iExact !== '' ) {
|
||||
if ( tsf.regex.operTest.test( data.iFilter ) && data.iExact !== '' ) {
|
||||
var cachedValue, result, txt,
|
||||
table = c.table,
|
||||
index = data.index,
|
||||
parsed = data.parsed[index],
|
||||
query = ts.formatFloat( data.iFilter.replace( ts.filter.regex.operators, '' ), table ),
|
||||
query = ts.formatFloat( data.iFilter.replace( tsf.regex.operators, '' ), table ),
|
||||
parser = c.parsers[index],
|
||||
savedSearch = query;
|
||||
// parse filter value in case we're comparing numbers ( dates )
|
||||
if ( parsed || parser.type === 'numeric' ) {
|
||||
txt = $.trim( '' + data.iFilter.replace( ts.filter.regex.operators, '' ) );
|
||||
result = ts.filter.parseFilter( c, txt, index, true );
|
||||
txt = $.trim( '' + data.iFilter.replace( tsf.regex.operators, '' ) );
|
||||
result = tsf.parseFilter( c, txt, index, true );
|
||||
query = ( typeof result === 'number' && result !== '' && !isNaN( result ) ) ? result : query;
|
||||
}
|
||||
// iExact may be numeric - see issue #149;
|
||||
@ -592,13 +597,13 @@
|
||||
typeof data.cache !== 'undefined' ) {
|
||||
cachedValue = data.cache;
|
||||
} else {
|
||||
txt = isNaN( data.iExact ) ? data.iExact.replace( ts.filter.regex.nondigit, '' ) : data.iExact;
|
||||
txt = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
|
||||
cachedValue = ts.formatFloat( txt, table );
|
||||
}
|
||||
if ( />/.test( data.iFilter ) ) {
|
||||
result = />=/.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
|
||||
} else if ( /</.test( data.iFilter ) ) {
|
||||
result = /<=/.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
|
||||
if ( tsf.regex.gtTest.test( data.iFilter ) ) {
|
||||
result = tsf.regex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
|
||||
} else if ( tsf.regex.ltTest.test( data.iFilter ) ) {
|
||||
result = tsf.regex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
|
||||
}
|
||||
// keep showing all rows if nothing follows the operator
|
||||
if ( !result && savedSearch === '' ) {
|
||||
@ -610,13 +615,13 @@
|
||||
},
|
||||
// Look for a not match
|
||||
notMatch: function( c, data ) {
|
||||
if ( /^\!/.test( data.iFilter ) ) {
|
||||
if ( tsf.regex.notTest.test( data.iFilter ) ) {
|
||||
var indx,
|
||||
txt = data.iFilter.replace( '!', '' ),
|
||||
filter = ts.filter.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
||||
if ( ts.filter.regex.exact.test( filter ) ) {
|
||||
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
||||
if ( tsf.regex.exact.test( filter ) ) {
|
||||
// look for exact not matches - see #628
|
||||
filter = filter.replace( ts.filter.regex.exact, '' );
|
||||
filter = filter.replace( tsf.regex.exact, '' );
|
||||
return filter === '' ? true : $.trim( filter ) !== data.iExact;
|
||||
} else {
|
||||
indx = data.iExact.search( $.trim( filter ) );
|
||||
@ -628,27 +633,27 @@
|
||||
// Look for quotes or equals to get an exact match; ignore type since iExact could be numeric
|
||||
exact: function( c, data ) {
|
||||
/*jshint eqeqeq:false */
|
||||
if ( ts.filter.regex.exact.test( data.iFilter ) ) {
|
||||
var txt = data.iFilter.replace( ts.filter.regex.exact, '' ),
|
||||
filter = ts.filter.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
||||
if ( tsf.regex.exact.test( data.iFilter ) ) {
|
||||
var txt = data.iFilter.replace( tsf.regex.exact, '' ),
|
||||
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
||||
return data.anyMatch ? $.inArray( filter, data.rowArray ) >= 0 : filter == data.iExact;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
// Look for a range ( using ' to ' or ' - ' ) - see issue #166; thanks matzhu!
|
||||
range : function( c, data ) {
|
||||
if ( ts.filter.regex.toTest.test( data.iFilter ) ) {
|
||||
if ( tsf.regex.toTest.test( data.iFilter ) ) {
|
||||
var result, tmp, range1, range2,
|
||||
table = c.table,
|
||||
index = data.index,
|
||||
parsed = data.parsed[index],
|
||||
// make sure the dash is for a range and not indicating a negative number
|
||||
query = data.iFilter.split( ts.filter.regex.toSplit );
|
||||
query = data.iFilter.split( tsf.regex.toSplit );
|
||||
|
||||
tmp = query[0].replace( ts.filter.regex.nondigit, '' ) || '';
|
||||
range1 = ts.formatFloat( ts.filter.parseFilter( c, tmp, index, parsed ), table );
|
||||
tmp = query[1].replace( ts.filter.regex.nondigit, '' ) || '';
|
||||
range2 = ts.formatFloat( ts.filter.parseFilter( c, tmp, index, parsed ), table );
|
||||
tmp = query[0].replace( ts.regex.nondigit, '' ) || '';
|
||||
range1 = ts.formatFloat( tsf.parseFilter( c, tmp, index, parsed ), table );
|
||||
tmp = query[1].replace( ts.regex.nondigit, '' ) || '';
|
||||
range2 = ts.formatFloat( tsf.parseFilter( c, tmp, index, parsed ), table );
|
||||
// parse filter value in case we're comparing numbers ( dates )
|
||||
if ( parsed || c.parsers[index].type === 'numeric' ) {
|
||||
result = c.parsers[ index ].format( '' + query[0], table, c.$headers.eq( index ), index );
|
||||
@ -659,7 +664,7 @@
|
||||
if ( ( parsed || c.parsers[ index ].type === 'numeric' ) && !isNaN( range1 ) && !isNaN( range2 ) ) {
|
||||
result = data.cache;
|
||||
} else {
|
||||
tmp = isNaN( data.iExact ) ? data.iExact.replace( ts.filter.regex.nondigit, '' ) : data.iExact;
|
||||
tmp = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
|
||||
result = ts.formatFloat( tmp, table );
|
||||
}
|
||||
if ( range1 > range2 ) {
|
||||
@ -671,18 +676,18 @@
|
||||
},
|
||||
// Look for wild card: ? = single, * = multiple, or | = logical OR
|
||||
wild : function( c, data ) {
|
||||
if ( /[\?\*\|]/.test( data.iFilter ) ) {
|
||||
if ( tsf.regex.wildOrTest.test( data.iFilter ) ) {
|
||||
var index = data.index,
|
||||
parsed = data.parsed[ index ],
|
||||
query = '' + ( ts.filter.parseFilter( c, data.iFilter, index, parsed ) || '' );
|
||||
query = '' + ( tsf.parseFilter( c, data.iFilter, index, parsed ) || '' );
|
||||
// look for an exact match with the 'or' unless the 'filter-match' class is found
|
||||
if ( !/\?\*/.test( query ) && data.nestedFilters ) {
|
||||
if ( !tsf.regex.wildTest.test( query ) && data.nestedFilters ) {
|
||||
query = data.isMatch ? query : '^(' + query + ')$';
|
||||
}
|
||||
// parsing the filter may not work properly when using wildcards =/
|
||||
try {
|
||||
return new RegExp(
|
||||
query.replace( /\?/g, '\\S{1}' ).replace( /\*/g, '\\S*' ),
|
||||
query.replace( tsf.regex.wild01, '\\S{1}' ).replace( tsf.regex.wild0More, '\\S*' ),
|
||||
c.widgetOptions.filter_ignoreCase ? 'i' : ''
|
||||
)
|
||||
.test( data.exact );
|
||||
@ -694,12 +699,12 @@
|
||||
},
|
||||
// fuzzy text search; modified from https://github.com/mattyork/fuzzy ( MIT license )
|
||||
fuzzy: function( c, data ) {
|
||||
if ( /^~/.test( data.iFilter ) ) {
|
||||
if ( tsf.regex.fuzzyTest.test( data.iFilter ) ) {
|
||||
var indx,
|
||||
patternIndx = 0,
|
||||
len = data.iExact.length,
|
||||
txt = data.iFilter.slice( 1 ),
|
||||
pattern = ts.filter.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
||||
pattern = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
||||
for ( indx = 0; indx < len; indx++ ) {
|
||||
if ( data.iExact[ indx ] === pattern[ patternIndx ] ) {
|
||||
patternIndx += 1;
|
||||
@ -722,7 +727,7 @@
|
||||
}, ts.language );
|
||||
|
||||
var options, string, txt, $header, column, filters, val, fxn, noSelect,
|
||||
regex = ts.filter.regex;
|
||||
regex = tsf.regex;
|
||||
c.$table.addClass( 'hasFilters' );
|
||||
|
||||
// define timers so using clearTimeout won't cause an undefined error
|
||||
@ -733,7 +738,7 @@
|
||||
wo.filter_anyColumnSelector = '[data-column="all"],[data-column="any"]';
|
||||
wo.filter_multipleColumnSelector = '[data-column*="-"],[data-column*=","]';
|
||||
|
||||
val = '\\{' + ts.filter.regex.query + '\\}';
|
||||
val = '\\{' + tsf.regex.query + '\\}';
|
||||
$.extend( regex, {
|
||||
child : new RegExp( c.cssChildRow ),
|
||||
filtered : new RegExp( wo.filter_filteredRow ),
|
||||
@ -742,9 +747,20 @@
|
||||
toSplit : new RegExp( '(?:\\s+(?:-|' + ts.language.to + ')\\s+)', 'gi' ),
|
||||
andTest : new RegExp( '\\s+(' + ts.language.and + '|&&)\\s+', 'i' ),
|
||||
andSplit : new RegExp( '(?:\\s+(?:' + ts.language.and + '|&&)\\s+)', 'gi' ),
|
||||
orTest : /\|/,
|
||||
orSplit : new RegExp( '(?:\\s+(?:' + ts.language.or + ')\\s+|\\|)', 'gi' ),
|
||||
iQuery : new RegExp( val, 'i' ),
|
||||
igQuery : new RegExp( val, 'ig' )
|
||||
igQuery : new RegExp( val, 'ig' ),
|
||||
operTest : /^[<>]=?/,
|
||||
gtTest : />/,
|
||||
gteTest : />=/,
|
||||
ltTest : /</,
|
||||
lteTest : /<=/,
|
||||
notTest : /^\!/,
|
||||
wildOrTest : /[\?\*\|]/,
|
||||
wildTest : /\?\*/,
|
||||
fuzzyTest : /^~/,
|
||||
exactTest : /[=\"\|!]/
|
||||
});
|
||||
|
||||
// don't build filter row if columnFilters is false or all columns are set to 'filter-false'
|
||||
@ -752,7 +768,7 @@
|
||||
val = c.$headers.filter( '.filter-false, .parser-false' ).length;
|
||||
if ( wo.filter_columnFilters !== false && val !== c.$headers.length ) {
|
||||
// build filter row
|
||||
ts.filter.buildRow( table, c, wo );
|
||||
tsf.buildRow( table, c, wo );
|
||||
}
|
||||
|
||||
txt = 'addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search '
|
||||
@ -765,13 +781,13 @@
|
||||
c.$table.find( '.' + tscss.filterRow ).toggleClass( wo.filter_filteredRow, val ); // fixes #450
|
||||
if ( !/(search|filter)/.test( event.type ) ) {
|
||||
event.stopPropagation();
|
||||
ts.filter.buildDefault( table, true );
|
||||
tsf.buildDefault( table, true );
|
||||
}
|
||||
if ( event.type === 'filterReset' ) {
|
||||
c.$table.find( '.' + tscss.filter ).add( wo.filter_$externalFilters ).val( '' );
|
||||
ts.filter.searching( table, [] );
|
||||
tsf.searching( table, [] );
|
||||
} else if ( event.type === 'filterEnd' ) {
|
||||
ts.filter.buildDefault( table, true );
|
||||
tsf.buildDefault( table, true );
|
||||
} else {
|
||||
// send false argument to force a new search; otherwise if the filter hasn't changed,
|
||||
// it will return
|
||||
@ -785,7 +801,7 @@
|
||||
// pass true ( skipFirst ) to prevent the tablesorter.setFilters function from skipping the first
|
||||
// input ensures all inputs are updated when a search is triggered on the table
|
||||
// $( 'table' ).trigger( 'search', [...] );
|
||||
ts.filter.searching( table, filter, true );
|
||||
tsf.searching( table, filter, true );
|
||||
}
|
||||
return false;
|
||||
});
|
||||
@ -818,7 +834,7 @@
|
||||
noSelect = !( $header.hasClass( 'filter-false' ) || $header.hasClass( 'parser-false' ) );
|
||||
options = '';
|
||||
if ( fxn === true && noSelect ) {
|
||||
ts.filter.buildSelect( table, column );
|
||||
tsf.buildSelect( table, column );
|
||||
} else if ( typeof fxn === 'object' && noSelect ) {
|
||||
// add custom drop down list
|
||||
for ( string in fxn ) {
|
||||
@ -851,7 +867,7 @@
|
||||
fxn = $.isFunction( txt ) ? true : ts.getColumnData( table, txt, column );
|
||||
if ( fxn ) {
|
||||
// updating so the extra options are appended
|
||||
ts.filter.buildSelect( c.table, column, '', true, $header.hasClass( wo.filter_onlyAvail ) );
|
||||
tsf.buildSelect( c.table, column, '', true, $header.hasClass( wo.filter_onlyAvail ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -859,22 +875,22 @@
|
||||
}
|
||||
// not really updating, but if the column has both the 'filter-select' class &
|
||||
// filter_functions set to true, it would append the same options twice.
|
||||
ts.filter.buildDefault( table, true );
|
||||
tsf.buildDefault( table, true );
|
||||
|
||||
ts.filter.bindSearch( table, c.$table.find( '.' + tscss.filter ), true );
|
||||
tsf.bindSearch( table, c.$table.find( '.' + tscss.filter ), true );
|
||||
if ( wo.filter_external ) {
|
||||
ts.filter.bindSearch( table, wo.filter_external );
|
||||
tsf.bindSearch( table, wo.filter_external );
|
||||
}
|
||||
|
||||
if ( wo.filter_hideFilters ) {
|
||||
ts.filter.hideFilters( table, c );
|
||||
tsf.hideFilters( table, c );
|
||||
}
|
||||
|
||||
// show processing icon
|
||||
if ( c.showProcessing ) {
|
||||
txt = 'filterStart filterEnd '.split( ' ' ).join( c.namespace + 'filter ' );
|
||||
c.$table
|
||||
.unbind( txt.replace( /\s+/g, ' ' ) )
|
||||
.unbind( txt.replace( ts.regex.spaces, ' ' ) )
|
||||
.bind( txt, function( event, columns ) {
|
||||
// only add processing to certain columns to all columns
|
||||
$header = ( columns ) ?
|
||||
@ -894,11 +910,11 @@
|
||||
// add default values
|
||||
txt = 'tablesorter-initialized pagerBeforeInitialized '.split( ' ' ).join( c.namespace + 'filter ' );
|
||||
c.$table
|
||||
.unbind( txt.replace( /\s+/g, ' ' ) )
|
||||
.unbind( txt.replace( ts.regex.spaces, ' ' ) )
|
||||
.bind( txt, function() {
|
||||
// redefine 'wo' as it does not update properly inside this callback
|
||||
var wo = this.config.widgetOptions;
|
||||
filters = ts.filter.setDefaults( table, c, wo ) || [];
|
||||
filters = tsf.setDefaults( table, c, wo ) || [];
|
||||
if ( filters.length ) {
|
||||
// prevent delayInit from triggering a cache build if filters are empty
|
||||
if ( !( c.delayInit && filters.join( '' ) === '' ) ) {
|
||||
@ -909,7 +925,7 @@
|
||||
// trigger init after setTimeout to prevent multiple filterStart/End/Init triggers
|
||||
setTimeout( function() {
|
||||
if ( !wo.filter_initialized ) {
|
||||
ts.filter.filterInitComplete( c );
|
||||
tsf.filterInitComplete( c );
|
||||
}
|
||||
}, 100 );
|
||||
});
|
||||
@ -917,7 +933,7 @@
|
||||
if ( c.pager && c.pager.initialized && !wo.filter_initialized ) {
|
||||
c.$table.trigger( 'filterFomatterUpdate' );
|
||||
setTimeout( function() {
|
||||
ts.filter.filterInitComplete( c );
|
||||
tsf.filterInitComplete( c );
|
||||
}, 100 );
|
||||
}
|
||||
},
|
||||
@ -938,7 +954,7 @@
|
||||
completed = function() {
|
||||
wo.filter_initialized = true;
|
||||
c.$table.trigger( 'filterInit', c );
|
||||
ts.filter.findRows( c.table, c.$table.data( 'lastSearch' ) || [] );
|
||||
tsf.findRows( c.table, c.$table.data( 'lastSearch' ) || [] );
|
||||
};
|
||||
if ( $.isEmptyObject( wo.filter_formatter ) ) {
|
||||
completed();
|
||||
@ -1090,7 +1106,7 @@
|
||||
// use data attribute instead of jQuery data since the head is cloned without including
|
||||
// the data/binding
|
||||
.attr( 'data-lastSearchTime', new Date().getTime() )
|
||||
.unbind( tmp.replace( /\s+/g, ' ' ) )
|
||||
.unbind( tmp.replace( ts.regex.spaces, ' ' ) )
|
||||
// include change for select - fixes #473
|
||||
.bind( 'keyup' + namespace, function( event ) {
|
||||
$( this ).attr( 'data-lastSearchTime', new Date().getTime() );
|
||||
@ -1110,7 +1126,7 @@
|
||||
return;
|
||||
}
|
||||
// change event = no delay; last true flag tells getFilters to skip newest timed input
|
||||
ts.filter.searching( table, true, true );
|
||||
tsf.searching( table, true, true );
|
||||
})
|
||||
.bind( 'search change keypress '.split( ' ' ).join( namespace + ' ' ), function( event ) {
|
||||
// don't get cached data, in case data-column changes dynamically
|
||||
@ -1121,7 +1137,7 @@
|
||||
event.preventDefault();
|
||||
// init search with no delay
|
||||
$( this ).attr( 'data-lastSearchTime', new Date().getTime() );
|
||||
ts.filter.searching( table, false, true );
|
||||
tsf.searching( table, false, true );
|
||||
}
|
||||
});
|
||||
},
|
||||
@ -1131,11 +1147,11 @@
|
||||
if ( typeof filter === 'undefined' || filter === true ) {
|
||||
// delay filtering
|
||||
wo.searchTimer = setTimeout( function() {
|
||||
ts.filter.checkFilters( table, filter, skipFirst );
|
||||
tsf.checkFilters( table, filter, skipFirst );
|
||||
}, wo.filter_liveSearch ? wo.filter_searchDelay : 10 );
|
||||
} else {
|
||||
// skip delay
|
||||
ts.filter.checkFilters( table, filter, skipFirst );
|
||||
tsf.checkFilters( table, filter, skipFirst );
|
||||
}
|
||||
},
|
||||
checkFilters: function( table, filter, skipFirst ) {
|
||||
@ -1149,7 +1165,7 @@
|
||||
// update cache if delayInit set & pager has initialized ( after user initiates a search )
|
||||
if ( c.delayInit && c.pager && c.pager.initialized ) {
|
||||
c.$table.trigger( 'updateCache', [ function() {
|
||||
ts.filter.checkFilters( table, false, skipFirst );
|
||||
tsf.checkFilters( table, false, skipFirst );
|
||||
} ] );
|
||||
}
|
||||
return;
|
||||
@ -1180,11 +1196,11 @@
|
||||
if ( c.showProcessing ) {
|
||||
// give it time for the processing icon to kick in
|
||||
setTimeout( function() {
|
||||
ts.filter.findRows( table, filters, combinedFilters );
|
||||
tsf.findRows( table, filters, combinedFilters );
|
||||
return false;
|
||||
}, 30 );
|
||||
} else {
|
||||
ts.filter.findRows( table, filters, combinedFilters );
|
||||
tsf.findRows( table, filters, combinedFilters );
|
||||
return false;
|
||||
}
|
||||
},
|
||||
@ -1227,8 +1243,8 @@
|
||||
},
|
||||
defaultFilter: function( filter, mask ) {
|
||||
if ( filter === '' ) { return filter; }
|
||||
var regex = ts.filter.regex.iQuery,
|
||||
maskLen = mask.match( ts.filter.regex.igQuery ).length,
|
||||
var regex = tsf.regex.iQuery,
|
||||
maskLen = mask.match( tsf.regex.igQuery ).length,
|
||||
query = maskLen > 1 ? $.trim( filter ).split( /\s/ ) : [ $.trim( filter ) ],
|
||||
len = query.length - 1,
|
||||
indx = 0,
|
||||
@ -1264,7 +1280,7 @@
|
||||
// & don't target 'all' column inputs if they don't exist
|
||||
targets = wo.filter_initialized || !$input.filter( wo.filter_anyColumnSelector ).length,
|
||||
columns = [],
|
||||
val = $.trim( ts.filter.getLatestSearch( $input ).attr( 'data-column' ) || '' );
|
||||
val = $.trim( tsf.getLatestSearch( $input ).attr( 'data-column' ) || '' );
|
||||
if ( !/[,-]/.test(val) && val.length === 1 ) {
|
||||
return parseInt( val, 10 );
|
||||
}
|
||||
@ -1314,9 +1330,9 @@
|
||||
var ffxn,
|
||||
filterMatched = null,
|
||||
matches = null;
|
||||
for ( ffxn in ts.filter.types ) {
|
||||
for ( ffxn in tsf.types ) {
|
||||
if ( $.inArray( ffxn, vars.excludeMatch ) < 0 && matches === null ) {
|
||||
matches = ts.filter.types[ffxn]( c, data, vars );
|
||||
matches = tsf.types[ffxn]( c, data, vars );
|
||||
if ( matches !== null ) {
|
||||
filterMatched = matches;
|
||||
}
|
||||
@ -1327,7 +1343,7 @@
|
||||
processRow: function( c, data, vars ) {
|
||||
var hasSelect, result, val, filterMatched,
|
||||
fxn, ffxn, txt,
|
||||
regex = ts.filter.regex,
|
||||
regex = tsf.regex,
|
||||
wo = c.widgetOptions,
|
||||
showRow = true,
|
||||
|
||||
@ -1336,7 +1352,7 @@
|
||||
// for the entire row - see #998
|
||||
columnIndex = wo.filter_$anyMatch && wo.filter_$anyMatch.length ?
|
||||
// look for multiple columns '1-3,4-6,8'
|
||||
ts.filter.multipleColumns( c, wo.filter_$anyMatch ) :
|
||||
tsf.multipleColumns( c, wo.filter_$anyMatch ) :
|
||||
[];
|
||||
|
||||
data.$cells = data.$row.children();
|
||||
@ -1365,7 +1381,7 @@
|
||||
data.cache = data.cacheArray.slice( 0, -1 ).join( ' ' );
|
||||
|
||||
vars.excludeMatch = vars.noAnyMatch;
|
||||
filterMatched = ts.filter.processTypes( c, data, vars );
|
||||
filterMatched = tsf.processTypes( c, data, vars );
|
||||
|
||||
if ( filterMatched !== null ) {
|
||||
showRow = filterMatched;
|
||||
@ -1426,7 +1442,7 @@
|
||||
|
||||
val = true;
|
||||
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultColFilter[ columnIndex ] ) ) {
|
||||
data.filter = ts.filter.defaultFilter( data.filter, vars.defaultColFilter[ columnIndex ] );
|
||||
data.filter = tsf.defaultFilter( data.filter, vars.defaultColFilter[ columnIndex ] );
|
||||
// val is used to indicate that a filter select is using a default filter;
|
||||
// so we override the exact & partial matches
|
||||
val = false;
|
||||
@ -1457,13 +1473,13 @@
|
||||
if ( filterMatched === null ) {
|
||||
// cycle through the different filters
|
||||
// filters return a boolean or null if nothing matches
|
||||
filterMatched = ts.filter.processTypes( c, data, vars );
|
||||
filterMatched = tsf.processTypes( c, data, vars );
|
||||
if ( filterMatched !== null ) {
|
||||
result = filterMatched;
|
||||
// Look for match, and add child row data for matching
|
||||
} else {
|
||||
txt = ( data.iExact + data.childRowText )
|
||||
.indexOf( ts.filter.parseFilter( c, data.iFilter, columnIndex, data.parsed[ columnIndex ] ) );
|
||||
.indexOf( tsf.parseFilter( c, data.iFilter, columnIndex, data.parsed[ columnIndex ] ) );
|
||||
result = ( ( !wo.filter_startsWith && txt >= 0 ) || ( wo.filter_startsWith && txt === 0 ) );
|
||||
}
|
||||
} else {
|
||||
@ -1483,7 +1499,7 @@
|
||||
isChild, childRow, lastSearch, showRow, time, val, indx,
|
||||
notFiltered, searchFiltered, query, injected, res, id, txt,
|
||||
storedFilters = $.extend( [], filters ),
|
||||
regex = ts.filter.regex,
|
||||
regex = tsf.regex,
|
||||
c = table.config,
|
||||
wo = c.widgetOptions,
|
||||
// data object passed to filters; anyMatch is a flag for the filters
|
||||
@ -1560,7 +1576,7 @@
|
||||
data.anyMatchFlag = true;
|
||||
data.anyMatchFilter = '' + (
|
||||
filters[ c.columns ] ||
|
||||
wo.filter_$anyMatch && ts.filter.getLatestSearch( wo.filter_$anyMatch ).val() ||
|
||||
wo.filter_$anyMatch && tsf.getLatestSearch( wo.filter_$anyMatch ).val() ||
|
||||
''
|
||||
);
|
||||
if ( wo.filter_columnAnyMatch ) {
|
||||
@ -1602,10 +1618,10 @@
|
||||
// if there is NOT a logical 'or', or range ( 'to' or '-' ) in the string
|
||||
!regex.alreadyFiltered.test( val ) &&
|
||||
// if we are not doing exact matches, using '|' ( logical or ) or not '!'
|
||||
!/[=\"\|!]/.test( val ) &&
|
||||
!regex.exactTest.test( val ) &&
|
||||
// don't search only filtered if the value is negative
|
||||
// ( '> -10' => '> -100' will ignore hidden rows )
|
||||
!( /(>=?\s*-\d)/.test( val ) || /(<=?\s*\d)/.test( val ) ) &&
|
||||
!( regex.isNeg1.test( val ) || regex.isNeg2.test( val ) ) &&
|
||||
// if filtering using a select without a 'filter-match' class ( exact match ) - fixes #593
|
||||
!( val !== '' && c.$filters && c.$filters.eq( indx ).find( 'select' ).length &&
|
||||
!c.$headerIndexed[indx].hasClass( 'filter-match' ) );
|
||||
@ -1624,7 +1640,7 @@
|
||||
data.anyMatchFilter = ts.replaceAccents( data.anyMatchFilter );
|
||||
}
|
||||
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultAnyFilter ) ) {
|
||||
data.anyMatchFilter = ts.filter.defaultFilter( data.anyMatchFilter, vars.defaultAnyFilter );
|
||||
data.anyMatchFilter = tsf.defaultFilter( data.anyMatchFilter, vars.defaultAnyFilter );
|
||||
// clear search filtered flag because default filters are not saved to the last search
|
||||
searchFiltered = false;
|
||||
}
|
||||
@ -1667,7 +1683,7 @@
|
||||
'';
|
||||
}
|
||||
|
||||
showRow = ts.filter.processRow( c, data, vars );
|
||||
showRow = tsf.processRow( c, data, vars );
|
||||
childRow = rowData.$row.filter( ':gt( 0 )' );
|
||||
|
||||
if ( wo.filter_childRows && childRow.length ) {
|
||||
@ -1678,7 +1694,7 @@
|
||||
data.cacheArray = rowData.child[ indx ];
|
||||
data.rawArray = data.cacheArray;
|
||||
// use OR comparison on child rows
|
||||
showRow = showRow || ts.filter.processRow( c, data, vars );
|
||||
showRow = showRow || tsf.processRow( c, data, vars );
|
||||
}
|
||||
}
|
||||
childRow.toggleClass( wo.filter_filteredRow, !showRow );
|
||||
@ -1740,7 +1756,7 @@
|
||||
}
|
||||
if ( arry === false ) {
|
||||
// fall back to original method
|
||||
arry = ts.filter.getOptions( table, column, onlyAvail );
|
||||
arry = tsf.getOptions( table, column, onlyAvail );
|
||||
}
|
||||
|
||||
// get unique elements and sort the list
|
||||
@ -1852,13 +1868,13 @@
|
||||
// nothing included in arry ( external source ), so get the options from
|
||||
// filter_selectSource or column data
|
||||
if ( typeof arry === 'undefined' || arry === '' ) {
|
||||
arry = ts.filter.getOptionSource( table, column, onlyAvail );
|
||||
arry = tsf.getOptionSource( table, column, onlyAvail );
|
||||
}
|
||||
|
||||
if ( $.isArray( arry ) ) {
|
||||
// build option list
|
||||
for ( indx = 0; indx < arry.length; indx++ ) {
|
||||
txt = arry[indx] = ( '' + arry[indx] ).replace( /\"/g, '"' );
|
||||
txt = arry[indx] = ( '' + arry[indx] ).replace( tsf.regex.quote, '"' );
|
||||
val = txt;
|
||||
// allow including a symbol in the selectSource array
|
||||
// 'a-z|A through Z' so that 'a-z' becomes the option value
|
||||
@ -1914,7 +1930,7 @@
|
||||
// look for the filter-select class; build/update it if found
|
||||
if ( ( $header.hasClass( 'filter-select' ) ||
|
||||
ts.getColumnData( table, wo.filter_functions, columnIndex ) === true ) && noSelect ) {
|
||||
ts.filter.buildSelect( table, columnIndex, '', updating, $header.hasClass( wo.filter_onlyAvail ) );
|
||||
tsf.buildSelect( table, columnIndex, '', updating, $header.hasClass( wo.filter_onlyAvail ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1950,7 +1966,7 @@
|
||||
$column = $filters.filter( cols );
|
||||
if ( $column.length ) {
|
||||
// move the latest search to the first slot in the array
|
||||
$column = ts.filter.getLatestSearch( $column );
|
||||
$column = tsf.getLatestSearch( $column );
|
||||
if ( $.isArray( setFilters ) ) {
|
||||
// skip first ( latest input ) to maintain cursor position while typing
|
||||
if ( skipFirst && $column.length > 1 ) {
|
||||
@ -2000,7 +2016,7 @@
|
||||
// ensure new set filters are applied, even if the search is the same
|
||||
c.lastCombinedFilter = null;
|
||||
c.lastSearch = [];
|
||||
ts.filter.searching( c.table, filter, skipFirst );
|
||||
tsf.searching( c.table, filter, skipFirst );
|
||||
c.$table.trigger( 'filterFomatterUpdate' );
|
||||
}
|
||||
return !!valid;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Widget: columnSelector (responsive table widget) - updated 8/17/2015 (v2.23.0) *//*
|
||||
/* Widget: columnSelector (responsive table widget) - updated 8/23/2015 (v2.23.2) *//*
|
||||
* Requires tablesorter v2.8+ and jQuery 1.7+
|
||||
* by Justin Hallett & Rob Garrison
|
||||
*/
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*! Widget: filter - updated 8/17/2015 (v2.23.0) *//*
|
||||
/*! Widget: filter - updated 8/23/2015 (v2.23.2) *//*
|
||||
* Requires tablesorter v2.8+ and jQuery 1.7+
|
||||
* by Rob Garrison
|
||||
*/
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "tablesorter",
|
||||
"title": "tablesorter",
|
||||
"version": "2.23.1",
|
||||
"version": "2.23.2",
|
||||
"description": "tablesorter (FORK) is a jQuery plugin for turning a standard HTML table with THEAD and TBODY tags into a sortable table without page refreshes. tablesorter can successfully parse and sort many types of data including linked data in a cell.",
|
||||
"author": {
|
||||
"name": "Christian Bach",
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "tablesorter",
|
||||
"title": "tablesorter",
|
||||
"version": "2.23.1",
|
||||
"version": "2.23.2",
|
||||
"description": "tablesorter is a jQuery plugin for turning a standard HTML table with THEAD and TBODY tags into a sortable table without page refreshes. tablesorter can successfully parse and sort many types of data including linked data in a cell.\n\nThis forked version adds lots of new enhancements including: alphanumeric sorting, pager callback functons, multiple widgets providing column styling, ui theme application, sticky headers, column filters and resizer, as well as extended documentation with a lot more demos.",
|
||||
"author": {
|
||||
"name": "Christian Bach",
|
||||
|
Loading…
Reference in New Issue
Block a user