jquery-tablesorter 1.18.1 → 1.18.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +3 -4
- data/lib/jquery-tablesorter/version.rb +1 -1
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.combined.js +218 -155
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.js +79 -43
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets.js +139 -112
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-columnSelector.js +6 -4
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter.js +138 -111
- metadata +2 -2
@@ -1,4 +1,4 @@
|
|
1
|
-
/*! TableSorter (FORK) v2.23.
|
1
|
+
/*! TableSorter (FORK) v2.23.2 *//*
|
2
2
|
* Client-side table sorting with ease!
|
3
3
|
* @requires jQuery v1.2.6+
|
4
4
|
*
|
@@ -26,7 +26,7 @@
|
|
26
26
|
|
27
27
|
var ts = this;
|
28
28
|
|
29
|
-
ts.version = '2.23.
|
29
|
+
ts.version = '2.23.2';
|
30
30
|
|
31
31
|
ts.parsers = [];
|
32
32
|
ts.widgets = [];
|
@@ -151,6 +151,15 @@
|
|
151
151
|
nextNone : 'activate to remove the sort'
|
152
152
|
};
|
153
153
|
|
154
|
+
ts.regex = {
|
155
|
+
templateContent : /\{content\}/g,
|
156
|
+
templateIcon : /\{icon\}/g,
|
157
|
+
templateName : /\{name\}/i,
|
158
|
+
spaces : /\s+/g,
|
159
|
+
nonWord : /\W/g,
|
160
|
+
formElements : /(input|select|button|textarea)/i
|
161
|
+
};
|
162
|
+
|
154
163
|
// These methods can be applied on table.config instance
|
155
164
|
ts.instanceMethods = {};
|
156
165
|
|
@@ -443,7 +452,9 @@
|
|
443
452
|
// if headerTemplate is empty, don't reformat the header cell
|
444
453
|
if ( c.headerTemplate !== '' && !$t.find('.' + ts.css.headerIn).length ) {
|
445
454
|
// set up header template
|
446
|
-
t = c.headerTemplate
|
455
|
+
t = c.headerTemplate
|
456
|
+
.replace(ts.regex.templateContent, $t.html())
|
457
|
+
.replace(ts.regex.templateIcon, $t.find('.' + ts.css.icon).length ? '' : i);
|
447
458
|
if (c.onRenderTemplate) {
|
448
459
|
h = c.onRenderTemplate.apply( $t, [ index, t ] );
|
449
460
|
if (h && typeof h === 'string') { t = h; } // only change t if something is returned
|
@@ -856,7 +867,7 @@
|
|
856
867
|
.join( c.namespace + ' ' );
|
857
868
|
// apply easy methods that trigger bound events
|
858
869
|
$table
|
859
|
-
.unbind( events.replace(
|
870
|
+
.unbind( events.replace( ts.regex.spaces, ' ' ) )
|
860
871
|
.bind( 'sortReset' + c.namespace, function( e, callback ) {
|
861
872
|
e.stopPropagation();
|
862
873
|
// using this.config to ensure functions are getting a non-cached version of the config
|
@@ -1003,7 +1014,7 @@
|
|
1003
1014
|
c.namespace = '.tablesorter' + Math.random().toString(16).slice(2);
|
1004
1015
|
} else {
|
1005
1016
|
// make sure namespace starts with a period & doesn't have weird characters
|
1006
|
-
c.namespace = '.' + c.namespace.replace(
|
1017
|
+
c.namespace = '.' + c.namespace.replace(ts.regex.nonWord, '');
|
1007
1018
|
}
|
1008
1019
|
|
1009
1020
|
c.$table.children().children('tr').attr('role', 'row');
|
@@ -1231,7 +1242,7 @@
|
|
1231
1242
|
}
|
1232
1243
|
}
|
1233
1244
|
t = ( c.pointerDown + ' ' + c.pointerUp + ' ' + c.pointerClick + ' sort keyup ' )
|
1234
|
-
.replace(
|
1245
|
+
.replace(ts.regex.spaces, ' ')
|
1235
1246
|
.split(' ')
|
1236
1247
|
.join(c.namespace + ' ');
|
1237
1248
|
// apply event handling to headers and/or additional headers (stickyheaders, scroller, etc)
|
@@ -1265,7 +1276,7 @@
|
|
1265
1276
|
}
|
1266
1277
|
downTarget = null;
|
1267
1278
|
// prevent sort being triggered on form elements
|
1268
|
-
if (
|
1279
|
+
if ( ts.regex.formElements.test(e.target.nodeName) ||
|
1269
1280
|
// nosort class name, or elements within a nosort container
|
1270
1281
|
$target.hasClass(c.cssNoSort) || $target.parents('.' + c.cssNoSort).length > 0 ||
|
1271
1282
|
// elements within a button
|
@@ -1551,13 +1562,13 @@
|
|
1551
1562
|
.join(c.namespace + ' ');
|
1552
1563
|
$t
|
1553
1564
|
.removeData('tablesorter')
|
1554
|
-
.unbind( events.replace(
|
1565
|
+
.unbind( events.replace(ts.regex.spaces, ' ') );
|
1555
1566
|
c.$headers.add($f)
|
1556
1567
|
.removeClass( [ ts.css.header, c.cssHeader, c.cssAsc, c.cssDesc, ts.css.sortAsc, ts.css.sortDesc, ts.css.sortNone ].join(' ') )
|
1557
1568
|
.removeAttr('data-column')
|
1558
1569
|
.removeAttr('aria-label')
|
1559
1570
|
.attr('aria-disabled', 'true');
|
1560
|
-
$r.find(c.selectorSort).unbind( ('mousedown mouseup keypress '.split(' ').join(c.namespace + ' ')).replace(
|
1571
|
+
$r.find(c.selectorSort).unbind( ('mousedown mouseup keypress '.split(' ').join(c.namespace + ' ')).replace(ts.regex.spaces, ' ') );
|
1561
1572
|
ts.restoreHeaders(table);
|
1562
1573
|
$t.toggleClass(ts.css.table + ' ' + c.tableClass + ' tablesorter-' + c.theme, removeClasses === false);
|
1563
1574
|
// clear flag in case the plugin is initialized again
|
@@ -1573,11 +1584,9 @@
|
|
1573
1584
|
|
1574
1585
|
// *** sort functions ***
|
1575
1586
|
// regex used in natural sort
|
1576
|
-
ts.regex =
|
1577
|
-
|
1578
|
-
|
1579
|
-
hex: /^0x[0-9a-f]+$/i // hex
|
1580
|
-
};
|
1587
|
+
ts.regex.chunk = /(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi; // chunk/tokenize numbers & letters
|
1588
|
+
ts.regex.chunks = /(^\\0|\\0$)/; // replace chunks @ ends
|
1589
|
+
ts.regex.hex = /^0x[0-9a-f]+$/i; // hex
|
1581
1590
|
|
1582
1591
|
// Natural sort - https://github.com/overset/javascript-natural-sort (date sorting removed)
|
1583
1592
|
// this function will only accept strings, or you'll see 'TypeError: undefined is not a function'
|
@@ -1804,7 +1813,7 @@
|
|
1804
1813
|
if (c.debug) { time = new Date(); }
|
1805
1814
|
// look for widgets to apply from in table class
|
1806
1815
|
// stop using \b otherwise this matches 'ui-widget-content' & adds 'content' widget
|
1807
|
-
wd = new RegExp( '\\s' + c.widgetClass.replace(
|
1816
|
+
wd = new RegExp( '\\s' + c.widgetClass.replace( ts.regex.templateName, '([\\w-]+)' ) + '\\s', 'g' );
|
1808
1817
|
if ( tableClass.match( wd ) ) {
|
1809
1818
|
// extract out the widget id from the table class (widget id's can include dashes)
|
1810
1819
|
w = tableClass.match( wd );
|
@@ -2030,6 +2039,10 @@
|
|
2030
2039
|
return $.trim(val);
|
2031
2040
|
};
|
2032
2041
|
|
2042
|
+
ts.regex.comma = /,/g;
|
2043
|
+
ts.regex.digitNonUS = /[\s|\.]/g;
|
2044
|
+
ts.regex.digitNegativeTest = /^\s*\([.\d]+\)/;
|
2045
|
+
ts.regex.digitNegativeReplace = /^\s*\(([.\d]+)\)/;
|
2033
2046
|
ts.formatFloat = function(s, table) {
|
2034
2047
|
if (typeof s !== 'string' || s === '') { return s; }
|
2035
2048
|
// allow using formatFloat without a table; defaults to US number format
|
@@ -2038,24 +2051,28 @@
|
|
2038
2051
|
typeof table !== 'undefined' ? table : true;
|
2039
2052
|
if (t) {
|
2040
2053
|
// US Format - 1,234,567.89 -> 1234567.89
|
2041
|
-
s = s.replace(
|
2054
|
+
s = s.replace(ts.regex.comma, '');
|
2042
2055
|
} else {
|
2043
2056
|
// German Format = 1.234.567,89 -> 1234567.89
|
2044
2057
|
// French Format = 1 234 567,89 -> 1234567.89
|
2045
|
-
s = s.replace(
|
2058
|
+
s = s.replace(ts.regex.digitNonUS, '').replace(ts.regex.comma, '.');
|
2046
2059
|
}
|
2047
|
-
if (
|
2060
|
+
if (ts.regex.digitNegativeTest.test(s)) {
|
2048
2061
|
// make (#) into a negative number -> (10) = -10
|
2049
|
-
s = s.replace(
|
2062
|
+
s = s.replace(ts.regex.digitNegativeReplace, '-$1');
|
2050
2063
|
}
|
2051
2064
|
i = parseFloat(s);
|
2052
2065
|
// return the text instead of zero
|
2053
2066
|
return isNaN(i) ? $.trim(s) : i;
|
2054
2067
|
};
|
2055
2068
|
|
2069
|
+
ts.regex.digitTest = /^[\-+(]?\d+[)]?$/;
|
2070
|
+
ts.regex.digitReplace = /[,.'"\s]/g;
|
2056
2071
|
ts.isDigit = function(s) {
|
2057
2072
|
// replace all unwanted chars and match
|
2058
|
-
return isNaN(s) ?
|
2073
|
+
return isNaN(s) ?
|
2074
|
+
ts.regex.digitTest.test( s.toString().replace( ts.regex.digitReplace, '' ) ) :
|
2075
|
+
s !== '';
|
2059
2076
|
};
|
2060
2077
|
|
2061
2078
|
}()
|
@@ -2114,65 +2131,76 @@
|
|
2114
2131
|
type: 'text'
|
2115
2132
|
});
|
2116
2133
|
|
2134
|
+
ts.regex.nondigit = /[^\w,. \-()]/g;
|
2117
2135
|
ts.addParser({
|
2118
2136
|
id: 'digit',
|
2119
2137
|
is: function(s) {
|
2120
2138
|
return ts.isDigit(s);
|
2121
2139
|
},
|
2122
2140
|
format: function(s, table) {
|
2123
|
-
var n = ts.formatFloat((s || '').replace(
|
2141
|
+
var n = ts.formatFloat((s || '').replace(ts.regex.nondigit, ''), table);
|
2124
2142
|
return s && typeof n === 'number' ? n :
|
2125
2143
|
s ? $.trim( s && table.config.ignoreCase ? s.toLocaleLowerCase() : s ) : s;
|
2126
2144
|
},
|
2127
2145
|
type: 'numeric'
|
2128
2146
|
});
|
2129
2147
|
|
2148
|
+
ts.regex.currencyReplace = /[+\-,. ]/g;
|
2149
|
+
ts.regex.currencyTest = /^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/;
|
2130
2150
|
ts.addParser({
|
2131
2151
|
id: 'currency',
|
2132
2152
|
is: function(s) {
|
2133
|
-
s = (s || '').replace(
|
2153
|
+
s = (s || '').replace(ts.regex.currencyReplace, '');
|
2134
2154
|
// test for £$€¤¥¢
|
2135
|
-
return
|
2155
|
+
return ts.regex.currencyTest.test(s);
|
2136
2156
|
},
|
2137
2157
|
format: function(s, table) {
|
2138
|
-
var n = ts.formatFloat((s || '').replace(
|
2158
|
+
var n = ts.formatFloat((s || '').replace(ts.regex.nondigit, ''), table);
|
2139
2159
|
return s && typeof n === 'number' ? n :
|
2140
2160
|
s ? $.trim( s && table.config.ignoreCase ? s.toLocaleLowerCase() : s ) : s;
|
2141
2161
|
},
|
2142
2162
|
type: 'numeric'
|
2143
2163
|
});
|
2144
2164
|
|
2165
|
+
// too many protocols to add them all https://en.wikipedia.org/wiki/URI_scheme
|
2166
|
+
// now, this regex can be updated before initialization
|
2167
|
+
ts.regex.urlProtocolTest = /^(https?|ftp|file):\/\//;
|
2168
|
+
ts.regex.urlProtocolReplace = /(https?|ftp|file):\/\//;
|
2145
2169
|
ts.addParser({
|
2146
2170
|
id: 'url',
|
2147
2171
|
is: function(s) {
|
2148
|
-
return
|
2172
|
+
return ts.regex.urlProtocolTest.test(s);
|
2149
2173
|
},
|
2150
2174
|
format: function(s) {
|
2151
|
-
return s ? $.trim(s.replace(
|
2175
|
+
return s ? $.trim(s.replace(ts.regex.urlProtocolReplace, '')) : s;
|
2152
2176
|
},
|
2153
2177
|
parsed : true, // filter widget flag
|
2154
2178
|
type: 'text'
|
2155
2179
|
});
|
2156
2180
|
|
2181
|
+
ts.regex.dash = /-/g;
|
2182
|
+
ts.regex.isoDate = /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/;
|
2157
2183
|
ts.addParser({
|
2158
2184
|
id: 'isoDate',
|
2159
2185
|
is: function(s) {
|
2160
|
-
return
|
2186
|
+
return ts.regex.isoDate.test(s);
|
2161
2187
|
},
|
2162
2188
|
format: function(s, table) {
|
2163
|
-
var date = s ? new Date( s.replace(
|
2189
|
+
var date = s ? new Date( s.replace(ts.regex.dash, '/') ) : s;
|
2164
2190
|
return date instanceof Date && isFinite(date) ? date.getTime() : s;
|
2165
2191
|
},
|
2166
2192
|
type: 'numeric'
|
2167
2193
|
});
|
2168
2194
|
|
2195
|
+
ts.regex.percent = /%/g;
|
2196
|
+
ts.regex.percentTest = /(\d\s*?%|%\s*?\d)/;
|
2169
2197
|
ts.addParser({
|
2170
2198
|
id: 'percent',
|
2171
2199
|
is: function(s) {
|
2172
|
-
return
|
2200
|
+
return ts.regex.percentTest.test(s) && s.length < 15;
|
2173
2201
|
},
|
2174
2202
|
format: function(s, table) {
|
2175
|
-
return s ? ts.formatFloat(s.replace(
|
2203
|
+
return s ? ts.formatFloat(s.replace(ts.regex.percent, ''), table) : s;
|
2176
2204
|
},
|
2177
2205
|
type: 'numeric'
|
2178
2206
|
});
|
@@ -2190,27 +2218,35 @@
|
|
2190
2218
|
type: 'text'
|
2191
2219
|
});
|
2192
2220
|
|
2221
|
+
ts.regex.dateReplace = /(\S)([AP]M)$/i; // used by usLongDate & time parser
|
2222
|
+
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;
|
2223
|
+
ts.regex.usLongDateTest2 = /^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i;
|
2193
2224
|
ts.addParser({
|
2194
2225
|
id: 'usLongDate',
|
2195
2226
|
is: function(s) {
|
2196
2227
|
// two digit years are not allowed cross-browser
|
2197
2228
|
// Jan 01, 2013 12:34:56 PM or 01 Jan 2013
|
2198
|
-
return (
|
2199
|
-
(/^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i).test(s);
|
2229
|
+
return ts.regex.usLongDateTest1.test(s) || ts.regex.usLongDateTest2.test(s);
|
2200
2230
|
},
|
2201
2231
|
format: function(s, table) {
|
2202
|
-
var date = s ? new Date( s.replace(
|
2232
|
+
var date = s ? new Date( s.replace(ts.regex.dateReplace, '$1 $2') ) : s;
|
2203
2233
|
return date instanceof Date && isFinite(date) ? date.getTime() : s;
|
2204
2234
|
},
|
2205
2235
|
type: 'numeric'
|
2206
2236
|
});
|
2207
2237
|
|
2238
|
+
// testing for ##-##-#### or ####-##-##, so it's not perfect; time can be included
|
2239
|
+
ts.regex.shortDateTest = /(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/;
|
2240
|
+
// escaped "-" because JSHint in Firefox was showing it as an error
|
2241
|
+
ts.regex.shortDateReplace = /[\-.,]/g;
|
2242
|
+
// XXY covers MDY & DMY formats
|
2243
|
+
ts.regex.shortDateXXY = /(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/;
|
2244
|
+
ts.regex.shortDateYMD = /(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/;
|
2208
2245
|
ts.addParser({
|
2209
2246
|
id: 'shortDate', // 'mmddyyyy', 'ddmmyyyy' or 'yyyymmdd'
|
2210
2247
|
is: function(s) {
|
2211
|
-
s = (s || '').replace(
|
2212
|
-
|
2213
|
-
return (/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/).test(s);
|
2248
|
+
s = (s || '').replace(ts.regex.spaces, ' ').replace(ts.regex.shortDateReplace, '/');
|
2249
|
+
return ts.regex.shortDateTest.test(s);
|
2214
2250
|
},
|
2215
2251
|
format: function(s, table, cell, cellIndex) {
|
2216
2252
|
if (s) {
|
@@ -2220,14 +2256,13 @@
|
|
2220
2256
|
format = ci.length && ci[0].dateFormat ||
|
2221
2257
|
ts.getData( ci, ts.getColumnData( table, c.headers, cellIndex ), 'dateFormat') ||
|
2222
2258
|
c.dateFormat;
|
2223
|
-
|
2224
|
-
d = s.replace(/\s+/g, ' ').replace(/[\-.,]/g, '/');
|
2259
|
+
d = s.replace(ts.regex.spaces, ' ').replace(ts.regex.shortDateReplace, '/');
|
2225
2260
|
if (format === 'mmddyyyy') {
|
2226
|
-
d = d.replace(
|
2261
|
+
d = d.replace(ts.regex.shortDateXXY, '$3/$1/$2');
|
2227
2262
|
} else if (format === 'ddmmyyyy') {
|
2228
|
-
d = d.replace(
|
2263
|
+
d = d.replace(ts.regex.shortDateXXY, '$3/$2/$1');
|
2229
2264
|
} else if (format === 'yyyymmdd') {
|
2230
|
-
d = d.replace(
|
2265
|
+
d = d.replace(ts.regex.shortDateYMD, '$1/$2/$3');
|
2231
2266
|
}
|
2232
2267
|
date = new Date(d);
|
2233
2268
|
return date instanceof Date && isFinite(date) ? date.getTime() : s;
|
@@ -2237,13 +2272,14 @@
|
|
2237
2272
|
type: 'numeric'
|
2238
2273
|
});
|
2239
2274
|
|
2275
|
+
ts.regex.timeTest = /^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i;
|
2240
2276
|
ts.addParser({
|
2241
2277
|
id: 'time',
|
2242
2278
|
is: function(s) {
|
2243
|
-
return
|
2279
|
+
return ts.regex.timeTest.test(s);
|
2244
2280
|
},
|
2245
2281
|
format: function(s, table) {
|
2246
|
-
var date = s ? new Date( '2000/01/01 ' + s.replace(
|
2282
|
+
var date = s ? new Date( '2000/01/01 ' + s.replace(ts.regex.dateReplace, '$1 $2') ) : s;
|
2247
2283
|
return date instanceof Date && isFinite(date) ? date.getTime() : s;
|
2248
2284
|
},
|
2249
2285
|
type: 'numeric'
|
@@ -4,7 +4,7 @@
|
|
4
4
|
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██▀▀ ▀▀▀▀██
|
5
5
|
█████▀ ▀████▀ ██ ██ ▀████▀ ██ ██ ██ ██ ▀████▀ █████▀ ██ ██ █████▀
|
6
6
|
*/
|
7
|
-
/*! tablesorter (FORK) - updated 08-
|
7
|
+
/*! tablesorter (FORK) - updated 08-23-2015 (v2.23.2)*/
|
8
8
|
/* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */
|
9
9
|
(function(factory) {
|
10
10
|
if (typeof define === 'function' && define.amd) {
|
@@ -372,14 +372,15 @@
|
|
372
372
|
|
373
373
|
})(jQuery);
|
374
374
|
|
375
|
-
/*! Widget: filter - updated 8/
|
375
|
+
/*! Widget: filter - updated 8/23/2015 (v2.23.2) *//*
|
376
376
|
* Requires tablesorter v2.8+ and jQuery 1.7+
|
377
377
|
* by Rob Garrison
|
378
378
|
*/
|
379
379
|
;( function ( $ ) {
|
380
380
|
'use strict';
|
381
|
-
var
|
382
|
-
|
381
|
+
var tsf,
|
382
|
+
ts = $.tablesorter || {},
|
383
|
+
tscss = ts.css;
|
383
384
|
|
384
385
|
$.extend( tscss, {
|
385
386
|
filterRow : 'tablesorter-filter-row',
|
@@ -423,7 +424,7 @@
|
|
423
424
|
},
|
424
425
|
format: function( table, c, wo ) {
|
425
426
|
if ( !c.$table.hasClass( 'hasFilters' ) ) {
|
426
|
-
|
427
|
+
tsf.init( table, c, wo );
|
427
428
|
}
|
428
429
|
},
|
429
430
|
remove: function( table, c, wo, refreshing ) {
|
@@ -435,7 +436,7 @@
|
|
435
436
|
$table
|
436
437
|
.removeClass( 'hasFilters' )
|
437
438
|
// add .tsfilter namespace to all BUT search
|
438
|
-
.unbind( events.replace(
|
439
|
+
.unbind( events.replace( ts.regex.spaces, ' ' ) )
|
439
440
|
// remove the filter row even if refreshing, because the column might have been moved
|
440
441
|
.find( '.' + tscss.filterRow ).remove();
|
441
442
|
if ( refreshing ) { return; }
|
@@ -450,7 +451,7 @@
|
|
450
451
|
}
|
451
452
|
});
|
452
453
|
|
453
|
-
ts.filter = {
|
454
|
+
tsf = ts.filter = {
|
454
455
|
|
455
456
|
// regex used in filter 'check' functions - not for general use and not documented
|
456
457
|
regex: {
|
@@ -459,9 +460,13 @@
|
|
459
460
|
filtered : /filtered/, // filtered (hidden) row class name; updated in the script
|
460
461
|
type : /undefined|number/, // check type
|
461
462
|
exact : /(^[\"\'=]+)|([\"\'=]+$)/g, // exact match (allow '==')
|
462
|
-
nondigit : /[^\w,. \-()]/g, // replace non-digits (from digit & currency parser)
|
463
463
|
operators : /[<>=]/g, // replace operators
|
464
|
-
query : '(q|query)' // replace filter queries
|
464
|
+
query : '(q|query)', // replace filter queries
|
465
|
+
wild01 : /\?/g, // wild card match 0 or 1
|
466
|
+
wild0More : /\*/g, // wild care match 0 or more
|
467
|
+
quote : /\"/g,
|
468
|
+
isNeg1 : /(>=?\s*-\d)/,
|
469
|
+
isNeg2 : /(<=?\s*\d)/
|
465
470
|
},
|
466
471
|
// function( c, data ) { }
|
467
472
|
// c = table.config
|
@@ -478,27 +483,27 @@
|
|
478
483
|
// data.parsed = array ( by column ) of boolean values ( from filter_useParsedData or 'filter-parsed' class )
|
479
484
|
types: {
|
480
485
|
or : function( c, data, vars ) {
|
481
|
-
if (
|
486
|
+
if ( tsf.regex.orTest.test( data.iFilter ) || tsf.regex.orSplit.test( data.filter ) ) {
|
482
487
|
var indx, filterMatched, query, regex,
|
483
488
|
// duplicate data but split filter
|
484
489
|
data2 = $.extend( {}, data ),
|
485
490
|
index = data.index,
|
486
491
|
parsed = data.parsed[ index ],
|
487
|
-
filter = data.filter.split(
|
488
|
-
iFilter = data.iFilter.split(
|
492
|
+
filter = data.filter.split( tsf.regex.orSplit ),
|
493
|
+
iFilter = data.iFilter.split( tsf.regex.orSplit ),
|
489
494
|
len = filter.length;
|
490
495
|
for ( indx = 0; indx < len; indx++ ) {
|
491
496
|
data2.nestedFilters = true;
|
492
|
-
data2.filter = '' + (
|
493
|
-
data2.iFilter = '' + (
|
494
|
-
query = '(' + (
|
497
|
+
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' );
|
498
|
+
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
|
499
|
+
query = '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')';
|
495
500
|
try {
|
496
501
|
// use try/catch, because query may not be a valid regex if "|" is contained within a partial regex search,
|
497
502
|
// e.g "/(Alex|Aar" -> Uncaught SyntaxError: Invalid regular expression: /(/(Alex)/: Unterminated group
|
498
503
|
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
|
499
504
|
// filterMatched = data2.filter === '' && indx > 0 ? true
|
500
505
|
// look for an exact match with the 'or' unless the 'filter-match' class is found
|
501
|
-
filterMatched = regex.test( data2.exact ) ||
|
506
|
+
filterMatched = regex.test( data2.exact ) || tsf.processTypes( c, data2, vars );
|
502
507
|
if ( filterMatched ) {
|
503
508
|
return filterMatched;
|
504
509
|
}
|
@@ -513,27 +518,27 @@
|
|
513
518
|
},
|
514
519
|
// Look for an AND or && operator ( logical and )
|
515
520
|
and : function( c, data, vars ) {
|
516
|
-
if (
|
521
|
+
if ( tsf.regex.andTest.test( data.filter ) ) {
|
517
522
|
var indx, filterMatched, result, query, regex,
|
518
523
|
// duplicate data but split filter
|
519
524
|
data2 = $.extend( {}, data ),
|
520
525
|
index = data.index,
|
521
526
|
parsed = data.parsed[ index ],
|
522
|
-
filter = data.filter.split(
|
523
|
-
iFilter = data.iFilter.split(
|
527
|
+
filter = data.filter.split( tsf.regex.andSplit ),
|
528
|
+
iFilter = data.iFilter.split( tsf.regex.andSplit ),
|
524
529
|
len = filter.length;
|
525
530
|
for ( indx = 0; indx < len; indx++ ) {
|
526
531
|
data2.nestedFilters = true;
|
527
|
-
data2.filter = '' + (
|
528
|
-
data2.iFilter = '' + (
|
529
|
-
query = ( '(' + (
|
532
|
+
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' );
|
533
|
+
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
|
534
|
+
query = ( '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')' )
|
530
535
|
// replace wild cards since /(a*)/i will match anything
|
531
|
-
.replace(
|
536
|
+
.replace( tsf.regex.wild01, '\\S{1}' ).replace( tsf.regex.wild0More, '\\S*' );
|
532
537
|
try {
|
533
538
|
// use try/catch just in case RegExp is invalid
|
534
539
|
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
|
535
540
|
// look for an exact match with the 'and' unless the 'filter-match' class is found
|
536
|
-
result = ( regex.test( data2.exact ) ||
|
541
|
+
result = ( regex.test( data2.exact ) || tsf.processTypes( c, data2, vars ) );
|
537
542
|
if ( indx === 0 ) {
|
538
543
|
filterMatched = result;
|
539
544
|
} else {
|
@@ -550,10 +555,10 @@
|
|
550
555
|
},
|
551
556
|
// Look for regex
|
552
557
|
regex: function( c, data ) {
|
553
|
-
if (
|
558
|
+
if ( tsf.regex.regex.test( data.filter ) ) {
|
554
559
|
var matches,
|
555
560
|
// cache regex per column for optimal speed
|
556
|
-
regex = data.filter_regexCache[ data.index ] ||
|
561
|
+
regex = data.filter_regexCache[ data.index ] || tsf.regex.regex.exec( data.filter ),
|
557
562
|
isRegex = regex instanceof RegExp;
|
558
563
|
try {
|
559
564
|
if ( !isRegex ) {
|
@@ -572,18 +577,18 @@
|
|
572
577
|
// Look for operators >, >=, < or <=
|
573
578
|
operators: function( c, data ) {
|
574
579
|
// ignore empty strings... because '' < 10 is true
|
575
|
-
if (
|
580
|
+
if ( tsf.regex.operTest.test( data.iFilter ) && data.iExact !== '' ) {
|
576
581
|
var cachedValue, result, txt,
|
577
582
|
table = c.table,
|
578
583
|
index = data.index,
|
579
584
|
parsed = data.parsed[index],
|
580
|
-
query = ts.formatFloat( data.iFilter.replace(
|
585
|
+
query = ts.formatFloat( data.iFilter.replace( tsf.regex.operators, '' ), table ),
|
581
586
|
parser = c.parsers[index],
|
582
587
|
savedSearch = query;
|
583
588
|
// parse filter value in case we're comparing numbers ( dates )
|
584
589
|
if ( parsed || parser.type === 'numeric' ) {
|
585
|
-
txt = $.trim( '' + data.iFilter.replace(
|
586
|
-
result =
|
590
|
+
txt = $.trim( '' + data.iFilter.replace( tsf.regex.operators, '' ) );
|
591
|
+
result = tsf.parseFilter( c, txt, index, true );
|
587
592
|
query = ( typeof result === 'number' && result !== '' && !isNaN( result ) ) ? result : query;
|
588
593
|
}
|
589
594
|
// iExact may be numeric - see issue #149;
|
@@ -592,13 +597,13 @@
|
|
592
597
|
typeof data.cache !== 'undefined' ) {
|
593
598
|
cachedValue = data.cache;
|
594
599
|
} else {
|
595
|
-
txt = isNaN( data.iExact ) ? data.iExact.replace( ts.
|
600
|
+
txt = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
|
596
601
|
cachedValue = ts.formatFloat( txt, table );
|
597
602
|
}
|
598
|
-
if (
|
599
|
-
result =
|
600
|
-
} else if (
|
601
|
-
result =
|
603
|
+
if ( tsf.regex.gtTest.test( data.iFilter ) ) {
|
604
|
+
result = tsf.regex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
|
605
|
+
} else if ( tsf.regex.ltTest.test( data.iFilter ) ) {
|
606
|
+
result = tsf.regex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
|
602
607
|
}
|
603
608
|
// keep showing all rows if nothing follows the operator
|
604
609
|
if ( !result && savedSearch === '' ) {
|
@@ -610,13 +615,13 @@
|
|
610
615
|
},
|
611
616
|
// Look for a not match
|
612
617
|
notMatch: function( c, data ) {
|
613
|
-
if (
|
618
|
+
if ( tsf.regex.notTest.test( data.iFilter ) ) {
|
614
619
|
var indx,
|
615
620
|
txt = data.iFilter.replace( '!', '' ),
|
616
|
-
filter =
|
617
|
-
if (
|
621
|
+
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
622
|
+
if ( tsf.regex.exact.test( filter ) ) {
|
618
623
|
// look for exact not matches - see #628
|
619
|
-
filter = filter.replace(
|
624
|
+
filter = filter.replace( tsf.regex.exact, '' );
|
620
625
|
return filter === '' ? true : $.trim( filter ) !== data.iExact;
|
621
626
|
} else {
|
622
627
|
indx = data.iExact.search( $.trim( filter ) );
|
@@ -628,27 +633,27 @@
|
|
628
633
|
// Look for quotes or equals to get an exact match; ignore type since iExact could be numeric
|
629
634
|
exact: function( c, data ) {
|
630
635
|
/*jshint eqeqeq:false */
|
631
|
-
if (
|
632
|
-
var txt = data.iFilter.replace(
|
633
|
-
filter =
|
636
|
+
if ( tsf.regex.exact.test( data.iFilter ) ) {
|
637
|
+
var txt = data.iFilter.replace( tsf.regex.exact, '' ),
|
638
|
+
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
634
639
|
return data.anyMatch ? $.inArray( filter, data.rowArray ) >= 0 : filter == data.iExact;
|
635
640
|
}
|
636
641
|
return null;
|
637
642
|
},
|
638
643
|
// Look for a range ( using ' to ' or ' - ' ) - see issue #166; thanks matzhu!
|
639
644
|
range : function( c, data ) {
|
640
|
-
if (
|
645
|
+
if ( tsf.regex.toTest.test( data.iFilter ) ) {
|
641
646
|
var result, tmp, range1, range2,
|
642
647
|
table = c.table,
|
643
648
|
index = data.index,
|
644
649
|
parsed = data.parsed[index],
|
645
650
|
// make sure the dash is for a range and not indicating a negative number
|
646
|
-
query = data.iFilter.split(
|
651
|
+
query = data.iFilter.split( tsf.regex.toSplit );
|
647
652
|
|
648
|
-
tmp = query[0].replace( ts.
|
649
|
-
range1 = ts.formatFloat(
|
650
|
-
tmp = query[1].replace( ts.
|
651
|
-
range2 = ts.formatFloat(
|
653
|
+
tmp = query[0].replace( ts.regex.nondigit, '' ) || '';
|
654
|
+
range1 = ts.formatFloat( tsf.parseFilter( c, tmp, index, parsed ), table );
|
655
|
+
tmp = query[1].replace( ts.regex.nondigit, '' ) || '';
|
656
|
+
range2 = ts.formatFloat( tsf.parseFilter( c, tmp, index, parsed ), table );
|
652
657
|
// parse filter value in case we're comparing numbers ( dates )
|
653
658
|
if ( parsed || c.parsers[index].type === 'numeric' ) {
|
654
659
|
result = c.parsers[ index ].format( '' + query[0], table, c.$headers.eq( index ), index );
|
@@ -659,7 +664,7 @@
|
|
659
664
|
if ( ( parsed || c.parsers[ index ].type === 'numeric' ) && !isNaN( range1 ) && !isNaN( range2 ) ) {
|
660
665
|
result = data.cache;
|
661
666
|
} else {
|
662
|
-
tmp = isNaN( data.iExact ) ? data.iExact.replace( ts.
|
667
|
+
tmp = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
|
663
668
|
result = ts.formatFloat( tmp, table );
|
664
669
|
}
|
665
670
|
if ( range1 > range2 ) {
|
@@ -671,18 +676,18 @@
|
|
671
676
|
},
|
672
677
|
// Look for wild card: ? = single, * = multiple, or | = logical OR
|
673
678
|
wild : function( c, data ) {
|
674
|
-
if (
|
679
|
+
if ( tsf.regex.wildOrTest.test( data.iFilter ) ) {
|
675
680
|
var index = data.index,
|
676
681
|
parsed = data.parsed[ index ],
|
677
|
-
query = '' + (
|
682
|
+
query = '' + ( tsf.parseFilter( c, data.iFilter, index, parsed ) || '' );
|
678
683
|
// look for an exact match with the 'or' unless the 'filter-match' class is found
|
679
|
-
if (
|
684
|
+
if ( !tsf.regex.wildTest.test( query ) && data.nestedFilters ) {
|
680
685
|
query = data.isMatch ? query : '^(' + query + ')$';
|
681
686
|
}
|
682
687
|
// parsing the filter may not work properly when using wildcards =/
|
683
688
|
try {
|
684
689
|
return new RegExp(
|
685
|
-
query.replace(
|
690
|
+
query.replace( tsf.regex.wild01, '\\S{1}' ).replace( tsf.regex.wild0More, '\\S*' ),
|
686
691
|
c.widgetOptions.filter_ignoreCase ? 'i' : ''
|
687
692
|
)
|
688
693
|
.test( data.exact );
|
@@ -694,12 +699,12 @@
|
|
694
699
|
},
|
695
700
|
// fuzzy text search; modified from https://github.com/mattyork/fuzzy ( MIT license )
|
696
701
|
fuzzy: function( c, data ) {
|
697
|
-
if (
|
702
|
+
if ( tsf.regex.fuzzyTest.test( data.iFilter ) ) {
|
698
703
|
var indx,
|
699
704
|
patternIndx = 0,
|
700
705
|
len = data.iExact.length,
|
701
706
|
txt = data.iFilter.slice( 1 ),
|
702
|
-
pattern =
|
707
|
+
pattern = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
703
708
|
for ( indx = 0; indx < len; indx++ ) {
|
704
709
|
if ( data.iExact[ indx ] === pattern[ patternIndx ] ) {
|
705
710
|
patternIndx += 1;
|
@@ -722,7 +727,7 @@
|
|
722
727
|
}, ts.language );
|
723
728
|
|
724
729
|
var options, string, txt, $header, column, filters, val, fxn, noSelect,
|
725
|
-
regex =
|
730
|
+
regex = tsf.regex;
|
726
731
|
c.$table.addClass( 'hasFilters' );
|
727
732
|
|
728
733
|
// define timers so using clearTimeout won't cause an undefined error
|
@@ -733,7 +738,7 @@
|
|
733
738
|
wo.filter_anyColumnSelector = '[data-column="all"],[data-column="any"]';
|
734
739
|
wo.filter_multipleColumnSelector = '[data-column*="-"],[data-column*=","]';
|
735
740
|
|
736
|
-
val = '\\{' +
|
741
|
+
val = '\\{' + tsf.regex.query + '\\}';
|
737
742
|
$.extend( regex, {
|
738
743
|
child : new RegExp( c.cssChildRow ),
|
739
744
|
filtered : new RegExp( wo.filter_filteredRow ),
|
@@ -742,9 +747,20 @@
|
|
742
747
|
toSplit : new RegExp( '(?:\\s+(?:-|' + ts.language.to + ')\\s+)', 'gi' ),
|
743
748
|
andTest : new RegExp( '\\s+(' + ts.language.and + '|&&)\\s+', 'i' ),
|
744
749
|
andSplit : new RegExp( '(?:\\s+(?:' + ts.language.and + '|&&)\\s+)', 'gi' ),
|
750
|
+
orTest : /\|/,
|
745
751
|
orSplit : new RegExp( '(?:\\s+(?:' + ts.language.or + ')\\s+|\\|)', 'gi' ),
|
746
752
|
iQuery : new RegExp( val, 'i' ),
|
747
|
-
igQuery : new RegExp( val, 'ig' )
|
753
|
+
igQuery : new RegExp( val, 'ig' ),
|
754
|
+
operTest : /^[<>]=?/,
|
755
|
+
gtTest : />/,
|
756
|
+
gteTest : />=/,
|
757
|
+
ltTest : /</,
|
758
|
+
lteTest : /<=/,
|
759
|
+
notTest : /^\!/,
|
760
|
+
wildOrTest : /[\?\*\|]/,
|
761
|
+
wildTest : /\?\*/,
|
762
|
+
fuzzyTest : /^~/,
|
763
|
+
exactTest : /[=\"\|!]/
|
748
764
|
});
|
749
765
|
|
750
766
|
// don't build filter row if columnFilters is false or all columns are set to 'filter-false'
|
@@ -752,7 +768,7 @@
|
|
752
768
|
val = c.$headers.filter( '.filter-false, .parser-false' ).length;
|
753
769
|
if ( wo.filter_columnFilters !== false && val !== c.$headers.length ) {
|
754
770
|
// build filter row
|
755
|
-
|
771
|
+
tsf.buildRow( table, c, wo );
|
756
772
|
}
|
757
773
|
|
758
774
|
txt = 'addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search '
|
@@ -765,13 +781,13 @@
|
|
765
781
|
c.$table.find( '.' + tscss.filterRow ).toggleClass( wo.filter_filteredRow, val ); // fixes #450
|
766
782
|
if ( !/(search|filter)/.test( event.type ) ) {
|
767
783
|
event.stopPropagation();
|
768
|
-
|
784
|
+
tsf.buildDefault( table, true );
|
769
785
|
}
|
770
786
|
if ( event.type === 'filterReset' ) {
|
771
787
|
c.$table.find( '.' + tscss.filter ).add( wo.filter_$externalFilters ).val( '' );
|
772
|
-
|
788
|
+
tsf.searching( table, [] );
|
773
789
|
} else if ( event.type === 'filterEnd' ) {
|
774
|
-
|
790
|
+
tsf.buildDefault( table, true );
|
775
791
|
} else {
|
776
792
|
// send false argument to force a new search; otherwise if the filter hasn't changed,
|
777
793
|
// it will return
|
@@ -785,7 +801,7 @@
|
|
785
801
|
// pass true ( skipFirst ) to prevent the tablesorter.setFilters function from skipping the first
|
786
802
|
// input ensures all inputs are updated when a search is triggered on the table
|
787
803
|
// $( 'table' ).trigger( 'search', [...] );
|
788
|
-
|
804
|
+
tsf.searching( table, filter, true );
|
789
805
|
}
|
790
806
|
return false;
|
791
807
|
});
|
@@ -818,7 +834,7 @@
|
|
818
834
|
noSelect = !( $header.hasClass( 'filter-false' ) || $header.hasClass( 'parser-false' ) );
|
819
835
|
options = '';
|
820
836
|
if ( fxn === true && noSelect ) {
|
821
|
-
|
837
|
+
tsf.buildSelect( table, column );
|
822
838
|
} else if ( typeof fxn === 'object' && noSelect ) {
|
823
839
|
// add custom drop down list
|
824
840
|
for ( string in fxn ) {
|
@@ -851,7 +867,7 @@
|
|
851
867
|
fxn = $.isFunction( txt ) ? true : ts.getColumnData( table, txt, column );
|
852
868
|
if ( fxn ) {
|
853
869
|
// updating so the extra options are appended
|
854
|
-
|
870
|
+
tsf.buildSelect( c.table, column, '', true, $header.hasClass( wo.filter_onlyAvail ) );
|
855
871
|
}
|
856
872
|
}
|
857
873
|
}
|
@@ -859,22 +875,22 @@
|
|
859
875
|
}
|
860
876
|
// not really updating, but if the column has both the 'filter-select' class &
|
861
877
|
// filter_functions set to true, it would append the same options twice.
|
862
|
-
|
878
|
+
tsf.buildDefault( table, true );
|
863
879
|
|
864
|
-
|
880
|
+
tsf.bindSearch( table, c.$table.find( '.' + tscss.filter ), true );
|
865
881
|
if ( wo.filter_external ) {
|
866
|
-
|
882
|
+
tsf.bindSearch( table, wo.filter_external );
|
867
883
|
}
|
868
884
|
|
869
885
|
if ( wo.filter_hideFilters ) {
|
870
|
-
|
886
|
+
tsf.hideFilters( table, c );
|
871
887
|
}
|
872
888
|
|
873
889
|
// show processing icon
|
874
890
|
if ( c.showProcessing ) {
|
875
891
|
txt = 'filterStart filterEnd '.split( ' ' ).join( c.namespace + 'filter ' );
|
876
892
|
c.$table
|
877
|
-
.unbind( txt.replace(
|
893
|
+
.unbind( txt.replace( ts.regex.spaces, ' ' ) )
|
878
894
|
.bind( txt, function( event, columns ) {
|
879
895
|
// only add processing to certain columns to all columns
|
880
896
|
$header = ( columns ) ?
|
@@ -894,11 +910,11 @@
|
|
894
910
|
// add default values
|
895
911
|
txt = 'tablesorter-initialized pagerBeforeInitialized '.split( ' ' ).join( c.namespace + 'filter ' );
|
896
912
|
c.$table
|
897
|
-
.unbind( txt.replace(
|
913
|
+
.unbind( txt.replace( ts.regex.spaces, ' ' ) )
|
898
914
|
.bind( txt, function() {
|
899
915
|
// redefine 'wo' as it does not update properly inside this callback
|
900
916
|
var wo = this.config.widgetOptions;
|
901
|
-
filters =
|
917
|
+
filters = tsf.setDefaults( table, c, wo ) || [];
|
902
918
|
if ( filters.length ) {
|
903
919
|
// prevent delayInit from triggering a cache build if filters are empty
|
904
920
|
if ( !( c.delayInit && filters.join( '' ) === '' ) ) {
|
@@ -909,7 +925,7 @@
|
|
909
925
|
// trigger init after setTimeout to prevent multiple filterStart/End/Init triggers
|
910
926
|
setTimeout( function() {
|
911
927
|
if ( !wo.filter_initialized ) {
|
912
|
-
|
928
|
+
tsf.filterInitComplete( c );
|
913
929
|
}
|
914
930
|
}, 100 );
|
915
931
|
});
|
@@ -917,7 +933,7 @@
|
|
917
933
|
if ( c.pager && c.pager.initialized && !wo.filter_initialized ) {
|
918
934
|
c.$table.trigger( 'filterFomatterUpdate' );
|
919
935
|
setTimeout( function() {
|
920
|
-
|
936
|
+
tsf.filterInitComplete( c );
|
921
937
|
}, 100 );
|
922
938
|
}
|
923
939
|
},
|
@@ -938,7 +954,7 @@
|
|
938
954
|
completed = function() {
|
939
955
|
wo.filter_initialized = true;
|
940
956
|
c.$table.trigger( 'filterInit', c );
|
941
|
-
|
957
|
+
tsf.findRows( c.table, c.$table.data( 'lastSearch' ) || [] );
|
942
958
|
};
|
943
959
|
if ( $.isEmptyObject( wo.filter_formatter ) ) {
|
944
960
|
completed();
|
@@ -1090,7 +1106,7 @@
|
|
1090
1106
|
// use data attribute instead of jQuery data since the head is cloned without including
|
1091
1107
|
// the data/binding
|
1092
1108
|
.attr( 'data-lastSearchTime', new Date().getTime() )
|
1093
|
-
.unbind( tmp.replace(
|
1109
|
+
.unbind( tmp.replace( ts.regex.spaces, ' ' ) )
|
1094
1110
|
// include change for select - fixes #473
|
1095
1111
|
.bind( 'keyup' + namespace, function( event ) {
|
1096
1112
|
$( this ).attr( 'data-lastSearchTime', new Date().getTime() );
|
@@ -1110,17 +1126,18 @@
|
|
1110
1126
|
return;
|
1111
1127
|
}
|
1112
1128
|
// change event = no delay; last true flag tells getFilters to skip newest timed input
|
1113
|
-
|
1129
|
+
tsf.searching( table, true, true );
|
1114
1130
|
})
|
1115
1131
|
.bind( 'search change keypress '.split( ' ' ).join( namespace + ' ' ), function( event ) {
|
1116
|
-
|
1132
|
+
// don't get cached data, in case data-column changes dynamically
|
1133
|
+
var column = parseInt( $( this ).attr( 'data-column' ), 10 );
|
1117
1134
|
// don't allow 'change' event to process if the input value is the same - fixes #685
|
1118
1135
|
if ( event.which === 13 || event.type === 'search' ||
|
1119
1136
|
event.type === 'change' && this.value !== c.lastSearch[column] ) {
|
1120
1137
|
event.preventDefault();
|
1121
1138
|
// init search with no delay
|
1122
1139
|
$( this ).attr( 'data-lastSearchTime', new Date().getTime() );
|
1123
|
-
|
1140
|
+
tsf.searching( table, false, true );
|
1124
1141
|
}
|
1125
1142
|
});
|
1126
1143
|
},
|
@@ -1130,11 +1147,11 @@
|
|
1130
1147
|
if ( typeof filter === 'undefined' || filter === true ) {
|
1131
1148
|
// delay filtering
|
1132
1149
|
wo.searchTimer = setTimeout( function() {
|
1133
|
-
|
1150
|
+
tsf.checkFilters( table, filter, skipFirst );
|
1134
1151
|
}, wo.filter_liveSearch ? wo.filter_searchDelay : 10 );
|
1135
1152
|
} else {
|
1136
1153
|
// skip delay
|
1137
|
-
|
1154
|
+
tsf.checkFilters( table, filter, skipFirst );
|
1138
1155
|
}
|
1139
1156
|
},
|
1140
1157
|
checkFilters: function( table, filter, skipFirst ) {
|
@@ -1148,7 +1165,7 @@
|
|
1148
1165
|
// update cache if delayInit set & pager has initialized ( after user initiates a search )
|
1149
1166
|
if ( c.delayInit && c.pager && c.pager.initialized ) {
|
1150
1167
|
c.$table.trigger( 'updateCache', [ function() {
|
1151
|
-
|
1168
|
+
tsf.checkFilters( table, false, skipFirst );
|
1152
1169
|
} ] );
|
1153
1170
|
}
|
1154
1171
|
return;
|
@@ -1179,11 +1196,11 @@
|
|
1179
1196
|
if ( c.showProcessing ) {
|
1180
1197
|
// give it time for the processing icon to kick in
|
1181
1198
|
setTimeout( function() {
|
1182
|
-
|
1199
|
+
tsf.findRows( table, filters, combinedFilters );
|
1183
1200
|
return false;
|
1184
1201
|
}, 30 );
|
1185
1202
|
} else {
|
1186
|
-
|
1203
|
+
tsf.findRows( table, filters, combinedFilters );
|
1187
1204
|
return false;
|
1188
1205
|
}
|
1189
1206
|
},
|
@@ -1226,8 +1243,8 @@
|
|
1226
1243
|
},
|
1227
1244
|
defaultFilter: function( filter, mask ) {
|
1228
1245
|
if ( filter === '' ) { return filter; }
|
1229
|
-
var regex =
|
1230
|
-
maskLen = mask.match(
|
1246
|
+
var regex = tsf.regex.iQuery,
|
1247
|
+
maskLen = mask.match( tsf.regex.igQuery ).length,
|
1231
1248
|
query = maskLen > 1 ? $.trim( filter ).split( /\s/ ) : [ $.trim( filter ) ],
|
1232
1249
|
len = query.length - 1,
|
1233
1250
|
indx = 0,
|
@@ -1263,7 +1280,10 @@
|
|
1263
1280
|
// & don't target 'all' column inputs if they don't exist
|
1264
1281
|
targets = wo.filter_initialized || !$input.filter( wo.filter_anyColumnSelector ).length,
|
1265
1282
|
columns = [],
|
1266
|
-
val = $.trim(
|
1283
|
+
val = $.trim( tsf.getLatestSearch( $input ).attr( 'data-column' ) || '' );
|
1284
|
+
if ( !/[,-]/.test(val) && val.length === 1 ) {
|
1285
|
+
return parseInt( val, 10 );
|
1286
|
+
}
|
1267
1287
|
// process column range
|
1268
1288
|
if ( targets && /-/.test( val ) ) {
|
1269
1289
|
ranges = val.match( /(\d+)\s*-\s*(\d+)/g );
|
@@ -1310,9 +1330,9 @@
|
|
1310
1330
|
var ffxn,
|
1311
1331
|
filterMatched = null,
|
1312
1332
|
matches = null;
|
1313
|
-
for ( ffxn in
|
1333
|
+
for ( ffxn in tsf.types ) {
|
1314
1334
|
if ( $.inArray( ffxn, vars.excludeMatch ) < 0 && matches === null ) {
|
1315
|
-
matches =
|
1335
|
+
matches = tsf.types[ffxn]( c, data, vars );
|
1316
1336
|
if ( matches !== null ) {
|
1317
1337
|
filterMatched = matches;
|
1318
1338
|
}
|
@@ -1321,16 +1341,23 @@
|
|
1321
1341
|
return filterMatched;
|
1322
1342
|
},
|
1323
1343
|
processRow: function( c, data, vars ) {
|
1324
|
-
var
|
1344
|
+
var hasSelect, result, val, filterMatched,
|
1325
1345
|
fxn, ffxn, txt,
|
1326
|
-
regex =
|
1346
|
+
regex = tsf.regex,
|
1327
1347
|
wo = c.widgetOptions,
|
1328
|
-
showRow = true
|
1348
|
+
showRow = true,
|
1349
|
+
|
1350
|
+
// if wo.filter_$anyMatch data-column attribute is changed dynamically
|
1351
|
+
// we don't want to do an "anyMatch" search on one column using data
|
1352
|
+
// for the entire row - see #998
|
1353
|
+
columnIndex = wo.filter_$anyMatch && wo.filter_$anyMatch.length ?
|
1354
|
+
// look for multiple columns '1-3,4-6,8'
|
1355
|
+
tsf.multipleColumns( c, wo.filter_$anyMatch ) :
|
1356
|
+
[];
|
1357
|
+
|
1329
1358
|
data.$cells = data.$row.children();
|
1330
1359
|
|
1331
|
-
if ( data.anyMatchFlag ) {
|
1332
|
-
// look for multiple columns '1-3,4-6,8'
|
1333
|
-
columnIndex = ts.filter.multipleColumns( c, wo.filter_$anyMatch );
|
1360
|
+
if ( data.anyMatchFlag && columnIndex.length > 1 ) {
|
1334
1361
|
data.anyMatch = true;
|
1335
1362
|
data.isMatch = true;
|
1336
1363
|
data.rowArray = data.$cells.map( function( i ) {
|
@@ -1354,7 +1381,7 @@
|
|
1354
1381
|
data.cache = data.cacheArray.slice( 0, -1 ).join( ' ' );
|
1355
1382
|
|
1356
1383
|
vars.excludeMatch = vars.noAnyMatch;
|
1357
|
-
filterMatched =
|
1384
|
+
filterMatched = tsf.processTypes( c, data, vars );
|
1358
1385
|
|
1359
1386
|
if ( filterMatched !== null ) {
|
1360
1387
|
showRow = filterMatched;
|
@@ -1415,7 +1442,7 @@
|
|
1415
1442
|
|
1416
1443
|
val = true;
|
1417
1444
|
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultColFilter[ columnIndex ] ) ) {
|
1418
|
-
data.filter =
|
1445
|
+
data.filter = tsf.defaultFilter( data.filter, vars.defaultColFilter[ columnIndex ] );
|
1419
1446
|
// val is used to indicate that a filter select is using a default filter;
|
1420
1447
|
// so we override the exact & partial matches
|
1421
1448
|
val = false;
|
@@ -1446,13 +1473,13 @@
|
|
1446
1473
|
if ( filterMatched === null ) {
|
1447
1474
|
// cycle through the different filters
|
1448
1475
|
// filters return a boolean or null if nothing matches
|
1449
|
-
filterMatched =
|
1476
|
+
filterMatched = tsf.processTypes( c, data, vars );
|
1450
1477
|
if ( filterMatched !== null ) {
|
1451
1478
|
result = filterMatched;
|
1452
1479
|
// Look for match, and add child row data for matching
|
1453
1480
|
} else {
|
1454
1481
|
txt = ( data.iExact + data.childRowText )
|
1455
|
-
.indexOf(
|
1482
|
+
.indexOf( tsf.parseFilter( c, data.iFilter, columnIndex, data.parsed[ columnIndex ] ) );
|
1456
1483
|
result = ( ( !wo.filter_startsWith && txt >= 0 ) || ( wo.filter_startsWith && txt === 0 ) );
|
1457
1484
|
}
|
1458
1485
|
} else {
|
@@ -1472,7 +1499,7 @@
|
|
1472
1499
|
isChild, childRow, lastSearch, showRow, time, val, indx,
|
1473
1500
|
notFiltered, searchFiltered, query, injected, res, id, txt,
|
1474
1501
|
storedFilters = $.extend( [], filters ),
|
1475
|
-
regex =
|
1502
|
+
regex = tsf.regex,
|
1476
1503
|
c = table.config,
|
1477
1504
|
wo = c.widgetOptions,
|
1478
1505
|
// data object passed to filters; anyMatch is a flag for the filters
|
@@ -1549,7 +1576,7 @@
|
|
1549
1576
|
data.anyMatchFlag = true;
|
1550
1577
|
data.anyMatchFilter = '' + (
|
1551
1578
|
filters[ c.columns ] ||
|
1552
|
-
wo.filter_$anyMatch &&
|
1579
|
+
wo.filter_$anyMatch && tsf.getLatestSearch( wo.filter_$anyMatch ).val() ||
|
1553
1580
|
''
|
1554
1581
|
);
|
1555
1582
|
if ( wo.filter_columnAnyMatch ) {
|
@@ -1591,10 +1618,10 @@
|
|
1591
1618
|
// if there is NOT a logical 'or', or range ( 'to' or '-' ) in the string
|
1592
1619
|
!regex.alreadyFiltered.test( val ) &&
|
1593
1620
|
// if we are not doing exact matches, using '|' ( logical or ) or not '!'
|
1594
|
-
|
1621
|
+
!regex.exactTest.test( val ) &&
|
1595
1622
|
// don't search only filtered if the value is negative
|
1596
1623
|
// ( '> -10' => '> -100' will ignore hidden rows )
|
1597
|
-
!(
|
1624
|
+
!( regex.isNeg1.test( val ) || regex.isNeg2.test( val ) ) &&
|
1598
1625
|
// if filtering using a select without a 'filter-match' class ( exact match ) - fixes #593
|
1599
1626
|
!( val !== '' && c.$filters && c.$filters.eq( indx ).find( 'select' ).length &&
|
1600
1627
|
!c.$headerIndexed[indx].hasClass( 'filter-match' ) );
|
@@ -1613,7 +1640,7 @@
|
|
1613
1640
|
data.anyMatchFilter = ts.replaceAccents( data.anyMatchFilter );
|
1614
1641
|
}
|
1615
1642
|
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultAnyFilter ) ) {
|
1616
|
-
data.anyMatchFilter =
|
1643
|
+
data.anyMatchFilter = tsf.defaultFilter( data.anyMatchFilter, vars.defaultAnyFilter );
|
1617
1644
|
// clear search filtered flag because default filters are not saved to the last search
|
1618
1645
|
searchFiltered = false;
|
1619
1646
|
}
|
@@ -1656,7 +1683,7 @@
|
|
1656
1683
|
'';
|
1657
1684
|
}
|
1658
1685
|
|
1659
|
-
showRow =
|
1686
|
+
showRow = tsf.processRow( c, data, vars );
|
1660
1687
|
childRow = rowData.$row.filter( ':gt( 0 )' );
|
1661
1688
|
|
1662
1689
|
if ( wo.filter_childRows && childRow.length ) {
|
@@ -1667,7 +1694,7 @@
|
|
1667
1694
|
data.cacheArray = rowData.child[ indx ];
|
1668
1695
|
data.rawArray = data.cacheArray;
|
1669
1696
|
// use OR comparison on child rows
|
1670
|
-
showRow = showRow ||
|
1697
|
+
showRow = showRow || tsf.processRow( c, data, vars );
|
1671
1698
|
}
|
1672
1699
|
}
|
1673
1700
|
childRow.toggleClass( wo.filter_filteredRow, !showRow );
|
@@ -1729,7 +1756,7 @@
|
|
1729
1756
|
}
|
1730
1757
|
if ( arry === false ) {
|
1731
1758
|
// fall back to original method
|
1732
|
-
arry =
|
1759
|
+
arry = tsf.getOptions( table, column, onlyAvail );
|
1733
1760
|
}
|
1734
1761
|
|
1735
1762
|
// get unique elements and sort the list
|
@@ -1841,13 +1868,13 @@
|
|
1841
1868
|
// nothing included in arry ( external source ), so get the options from
|
1842
1869
|
// filter_selectSource or column data
|
1843
1870
|
if ( typeof arry === 'undefined' || arry === '' ) {
|
1844
|
-
arry =
|
1871
|
+
arry = tsf.getOptionSource( table, column, onlyAvail );
|
1845
1872
|
}
|
1846
1873
|
|
1847
1874
|
if ( $.isArray( arry ) ) {
|
1848
1875
|
// build option list
|
1849
1876
|
for ( indx = 0; indx < arry.length; indx++ ) {
|
1850
|
-
txt = arry[indx] = ( '' + arry[indx] ).replace(
|
1877
|
+
txt = arry[indx] = ( '' + arry[indx] ).replace( tsf.regex.quote, '"' );
|
1851
1878
|
val = txt;
|
1852
1879
|
// allow including a symbol in the selectSource array
|
1853
1880
|
// 'a-z|A through Z' so that 'a-z' becomes the option value
|
@@ -1903,7 +1930,7 @@
|
|
1903
1930
|
// look for the filter-select class; build/update it if found
|
1904
1931
|
if ( ( $header.hasClass( 'filter-select' ) ||
|
1905
1932
|
ts.getColumnData( table, wo.filter_functions, columnIndex ) === true ) && noSelect ) {
|
1906
|
-
|
1933
|
+
tsf.buildSelect( table, columnIndex, '', updating, $header.hasClass( wo.filter_onlyAvail ) );
|
1907
1934
|
}
|
1908
1935
|
}
|
1909
1936
|
}
|
@@ -1939,7 +1966,7 @@
|
|
1939
1966
|
$column = $filters.filter( cols );
|
1940
1967
|
if ( $column.length ) {
|
1941
1968
|
// move the latest search to the first slot in the array
|
1942
|
-
$column =
|
1969
|
+
$column = tsf.getLatestSearch( $column );
|
1943
1970
|
if ( $.isArray( setFilters ) ) {
|
1944
1971
|
// skip first ( latest input ) to maintain cursor position while typing
|
1945
1972
|
if ( skipFirst && $column.length > 1 ) {
|
@@ -1989,7 +2016,7 @@
|
|
1989
2016
|
// ensure new set filters are applied, even if the search is the same
|
1990
2017
|
c.lastCombinedFilter = null;
|
1991
2018
|
c.lastSearch = [];
|
1992
|
-
|
2019
|
+
tsf.searching( c.table, filter, skipFirst );
|
1993
2020
|
c.$table.trigger( 'filterFomatterUpdate' );
|
1994
2021
|
}
|
1995
2022
|
return !!valid;
|