jquery-tablesorter 1.18.1 → 1.18.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -4
- data/lib/jquery-tablesorter/version.rb +1 -1
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.combined.js +218 -155
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.js +79 -43
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets.js +139 -112
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-columnSelector.js +6 -4
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter.js +138 -111
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 886efa143e551b3b1b348bfc4a5ceb244cba60d1
|
4
|
+
data.tar.gz: b3ae2ede803d0ef6014d497114a502a3128b4d27
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a526f91f99c7d413b1d4c92b5b3ff03cb539bc4fda82e6f23cee1ffb162338b698b2c7ab91c5779fd824e52813f7eb4747e7dbd37ec7d9cc3f7d9f83cbb26d3
|
7
|
+
data.tar.gz: e42ae380bbddbca7bb6c7ccb74d2581cad6eb2d5273cd07f39bbd2ec804dec5ac2b8a63080b37e9eda3d236d8fdfd51c8fdb47dd19cf8cc6b4af7dbacddbe72f
|
data/README.md
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
Simple integration of jquery-tablesorter into the asset pipeline.
|
6
6
|
|
7
|
-
Current tablesorter version: 2.23.
|
7
|
+
Current tablesorter version: 2.23.2 (8/23/2015), [documentation]
|
8
8
|
|
9
9
|
Any issue associated with the js/css files, please report to [Mottie's fork].
|
10
10
|
|
@@ -24,9 +24,8 @@ Or install it yourself as:
|
|
24
24
|
|
25
25
|
## Requirements
|
26
26
|
|
27
|
-
Rails 3.2 and higher (tested up to 4.2)
|
28
|
-
|
29
|
-
Tested with ruby 1.9.3 - 2.2.2
|
27
|
+
It should work with Rails 3.2 and higher (tested up to 4.2) as well as with ruby 1.9.3 - 2.2.x.
|
28
|
+
Each release is always tested with the latest version of both.
|
30
29
|
|
31
30
|
## Usage
|
32
31
|
|
@@ -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) {
|
@@ -16,7 +16,7 @@
|
|
16
16
|
}
|
17
17
|
}(function($) {
|
18
18
|
|
19
|
-
/*! TableSorter (FORK) v2.23.
|
19
|
+
/*! TableSorter (FORK) v2.23.2 *//*
|
20
20
|
* Client-side table sorting with ease!
|
21
21
|
* @requires jQuery v1.2.6+
|
22
22
|
*
|
@@ -44,7 +44,7 @@
|
|
44
44
|
|
45
45
|
var ts = this;
|
46
46
|
|
47
|
-
ts.version = '2.23.
|
47
|
+
ts.version = '2.23.2';
|
48
48
|
|
49
49
|
ts.parsers = [];
|
50
50
|
ts.widgets = [];
|
@@ -169,6 +169,15 @@
|
|
169
169
|
nextNone : 'activate to remove the sort'
|
170
170
|
};
|
171
171
|
|
172
|
+
ts.regex = {
|
173
|
+
templateContent : /\{content\}/g,
|
174
|
+
templateIcon : /\{icon\}/g,
|
175
|
+
templateName : /\{name\}/i,
|
176
|
+
spaces : /\s+/g,
|
177
|
+
nonWord : /\W/g,
|
178
|
+
formElements : /(input|select|button|textarea)/i
|
179
|
+
};
|
180
|
+
|
172
181
|
// These methods can be applied on table.config instance
|
173
182
|
ts.instanceMethods = {};
|
174
183
|
|
@@ -461,7 +470,9 @@
|
|
461
470
|
// if headerTemplate is empty, don't reformat the header cell
|
462
471
|
if ( c.headerTemplate !== '' && !$t.find('.' + ts.css.headerIn).length ) {
|
463
472
|
// set up header template
|
464
|
-
t = c.headerTemplate
|
473
|
+
t = c.headerTemplate
|
474
|
+
.replace(ts.regex.templateContent, $t.html())
|
475
|
+
.replace(ts.regex.templateIcon, $t.find('.' + ts.css.icon).length ? '' : i);
|
465
476
|
if (c.onRenderTemplate) {
|
466
477
|
h = c.onRenderTemplate.apply( $t, [ index, t ] );
|
467
478
|
if (h && typeof h === 'string') { t = h; } // only change t if something is returned
|
@@ -874,7 +885,7 @@
|
|
874
885
|
.join( c.namespace + ' ' );
|
875
886
|
// apply easy methods that trigger bound events
|
876
887
|
$table
|
877
|
-
.unbind( events.replace(
|
888
|
+
.unbind( events.replace( ts.regex.spaces, ' ' ) )
|
878
889
|
.bind( 'sortReset' + c.namespace, function( e, callback ) {
|
879
890
|
e.stopPropagation();
|
880
891
|
// using this.config to ensure functions are getting a non-cached version of the config
|
@@ -1021,7 +1032,7 @@
|
|
1021
1032
|
c.namespace = '.tablesorter' + Math.random().toString(16).slice(2);
|
1022
1033
|
} else {
|
1023
1034
|
// make sure namespace starts with a period & doesn't have weird characters
|
1024
|
-
c.namespace = '.' + c.namespace.replace(
|
1035
|
+
c.namespace = '.' + c.namespace.replace(ts.regex.nonWord, '');
|
1025
1036
|
}
|
1026
1037
|
|
1027
1038
|
c.$table.children().children('tr').attr('role', 'row');
|
@@ -1249,7 +1260,7 @@
|
|
1249
1260
|
}
|
1250
1261
|
}
|
1251
1262
|
t = ( c.pointerDown + ' ' + c.pointerUp + ' ' + c.pointerClick + ' sort keyup ' )
|
1252
|
-
.replace(
|
1263
|
+
.replace(ts.regex.spaces, ' ')
|
1253
1264
|
.split(' ')
|
1254
1265
|
.join(c.namespace + ' ');
|
1255
1266
|
// apply event handling to headers and/or additional headers (stickyheaders, scroller, etc)
|
@@ -1283,7 +1294,7 @@
|
|
1283
1294
|
}
|
1284
1295
|
downTarget = null;
|
1285
1296
|
// prevent sort being triggered on form elements
|
1286
|
-
if (
|
1297
|
+
if ( ts.regex.formElements.test(e.target.nodeName) ||
|
1287
1298
|
// nosort class name, or elements within a nosort container
|
1288
1299
|
$target.hasClass(c.cssNoSort) || $target.parents('.' + c.cssNoSort).length > 0 ||
|
1289
1300
|
// elements within a button
|
@@ -1569,13 +1580,13 @@
|
|
1569
1580
|
.join(c.namespace + ' ');
|
1570
1581
|
$t
|
1571
1582
|
.removeData('tablesorter')
|
1572
|
-
.unbind( events.replace(
|
1583
|
+
.unbind( events.replace(ts.regex.spaces, ' ') );
|
1573
1584
|
c.$headers.add($f)
|
1574
1585
|
.removeClass( [ ts.css.header, c.cssHeader, c.cssAsc, c.cssDesc, ts.css.sortAsc, ts.css.sortDesc, ts.css.sortNone ].join(' ') )
|
1575
1586
|
.removeAttr('data-column')
|
1576
1587
|
.removeAttr('aria-label')
|
1577
1588
|
.attr('aria-disabled', 'true');
|
1578
|
-
$r.find(c.selectorSort).unbind( ('mousedown mouseup keypress '.split(' ').join(c.namespace + ' ')).replace(
|
1589
|
+
$r.find(c.selectorSort).unbind( ('mousedown mouseup keypress '.split(' ').join(c.namespace + ' ')).replace(ts.regex.spaces, ' ') );
|
1579
1590
|
ts.restoreHeaders(table);
|
1580
1591
|
$t.toggleClass(ts.css.table + ' ' + c.tableClass + ' tablesorter-' + c.theme, removeClasses === false);
|
1581
1592
|
// clear flag in case the plugin is initialized again
|
@@ -1591,11 +1602,9 @@
|
|
1591
1602
|
|
1592
1603
|
// *** sort functions ***
|
1593
1604
|
// regex used in natural sort
|
1594
|
-
ts.regex =
|
1595
|
-
|
1596
|
-
|
1597
|
-
hex: /^0x[0-9a-f]+$/i // hex
|
1598
|
-
};
|
1605
|
+
ts.regex.chunk = /(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi; // chunk/tokenize numbers & letters
|
1606
|
+
ts.regex.chunks = /(^\\0|\\0$)/; // replace chunks @ ends
|
1607
|
+
ts.regex.hex = /^0x[0-9a-f]+$/i; // hex
|
1599
1608
|
|
1600
1609
|
// Natural sort - https://github.com/overset/javascript-natural-sort (date sorting removed)
|
1601
1610
|
// this function will only accept strings, or you'll see 'TypeError: undefined is not a function'
|
@@ -1822,7 +1831,7 @@
|
|
1822
1831
|
if (c.debug) { time = new Date(); }
|
1823
1832
|
// look for widgets to apply from in table class
|
1824
1833
|
// stop using \b otherwise this matches 'ui-widget-content' & adds 'content' widget
|
1825
|
-
wd = new RegExp( '\\s' + c.widgetClass.replace(
|
1834
|
+
wd = new RegExp( '\\s' + c.widgetClass.replace( ts.regex.templateName, '([\\w-]+)' ) + '\\s', 'g' );
|
1826
1835
|
if ( tableClass.match( wd ) ) {
|
1827
1836
|
// extract out the widget id from the table class (widget id's can include dashes)
|
1828
1837
|
w = tableClass.match( wd );
|
@@ -2048,6 +2057,10 @@
|
|
2048
2057
|
return $.trim(val);
|
2049
2058
|
};
|
2050
2059
|
|
2060
|
+
ts.regex.comma = /,/g;
|
2061
|
+
ts.regex.digitNonUS = /[\s|\.]/g;
|
2062
|
+
ts.regex.digitNegativeTest = /^\s*\([.\d]+\)/;
|
2063
|
+
ts.regex.digitNegativeReplace = /^\s*\(([.\d]+)\)/;
|
2051
2064
|
ts.formatFloat = function(s, table) {
|
2052
2065
|
if (typeof s !== 'string' || s === '') { return s; }
|
2053
2066
|
// allow using formatFloat without a table; defaults to US number format
|
@@ -2056,24 +2069,28 @@
|
|
2056
2069
|
typeof table !== 'undefined' ? table : true;
|
2057
2070
|
if (t) {
|
2058
2071
|
// US Format - 1,234,567.89 -> 1234567.89
|
2059
|
-
s = s.replace(
|
2072
|
+
s = s.replace(ts.regex.comma, '');
|
2060
2073
|
} else {
|
2061
2074
|
// German Format = 1.234.567,89 -> 1234567.89
|
2062
2075
|
// French Format = 1 234 567,89 -> 1234567.89
|
2063
|
-
s = s.replace(
|
2076
|
+
s = s.replace(ts.regex.digitNonUS, '').replace(ts.regex.comma, '.');
|
2064
2077
|
}
|
2065
|
-
if (
|
2078
|
+
if (ts.regex.digitNegativeTest.test(s)) {
|
2066
2079
|
// make (#) into a negative number -> (10) = -10
|
2067
|
-
s = s.replace(
|
2080
|
+
s = s.replace(ts.regex.digitNegativeReplace, '-$1');
|
2068
2081
|
}
|
2069
2082
|
i = parseFloat(s);
|
2070
2083
|
// return the text instead of zero
|
2071
2084
|
return isNaN(i) ? $.trim(s) : i;
|
2072
2085
|
};
|
2073
2086
|
|
2087
|
+
ts.regex.digitTest = /^[\-+(]?\d+[)]?$/;
|
2088
|
+
ts.regex.digitReplace = /[,.'"\s]/g;
|
2074
2089
|
ts.isDigit = function(s) {
|
2075
2090
|
// replace all unwanted chars and match
|
2076
|
-
return isNaN(s) ?
|
2091
|
+
return isNaN(s) ?
|
2092
|
+
ts.regex.digitTest.test( s.toString().replace( ts.regex.digitReplace, '' ) ) :
|
2093
|
+
s !== '';
|
2077
2094
|
};
|
2078
2095
|
|
2079
2096
|
}()
|
@@ -2132,65 +2149,76 @@
|
|
2132
2149
|
type: 'text'
|
2133
2150
|
});
|
2134
2151
|
|
2152
|
+
ts.regex.nondigit = /[^\w,. \-()]/g;
|
2135
2153
|
ts.addParser({
|
2136
2154
|
id: 'digit',
|
2137
2155
|
is: function(s) {
|
2138
2156
|
return ts.isDigit(s);
|
2139
2157
|
},
|
2140
2158
|
format: function(s, table) {
|
2141
|
-
var n = ts.formatFloat((s || '').replace(
|
2159
|
+
var n = ts.formatFloat((s || '').replace(ts.regex.nondigit, ''), table);
|
2142
2160
|
return s && typeof n === 'number' ? n :
|
2143
2161
|
s ? $.trim( s && table.config.ignoreCase ? s.toLocaleLowerCase() : s ) : s;
|
2144
2162
|
},
|
2145
2163
|
type: 'numeric'
|
2146
2164
|
});
|
2147
2165
|
|
2166
|
+
ts.regex.currencyReplace = /[+\-,. ]/g;
|
2167
|
+
ts.regex.currencyTest = /^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/;
|
2148
2168
|
ts.addParser({
|
2149
2169
|
id: 'currency',
|
2150
2170
|
is: function(s) {
|
2151
|
-
s = (s || '').replace(
|
2171
|
+
s = (s || '').replace(ts.regex.currencyReplace, '');
|
2152
2172
|
// test for £$€¤¥¢
|
2153
|
-
return
|
2173
|
+
return ts.regex.currencyTest.test(s);
|
2154
2174
|
},
|
2155
2175
|
format: function(s, table) {
|
2156
|
-
var n = ts.formatFloat((s || '').replace(
|
2176
|
+
var n = ts.formatFloat((s || '').replace(ts.regex.nondigit, ''), table);
|
2157
2177
|
return s && typeof n === 'number' ? n :
|
2158
2178
|
s ? $.trim( s && table.config.ignoreCase ? s.toLocaleLowerCase() : s ) : s;
|
2159
2179
|
},
|
2160
2180
|
type: 'numeric'
|
2161
2181
|
});
|
2162
2182
|
|
2183
|
+
// too many protocols to add them all https://en.wikipedia.org/wiki/URI_scheme
|
2184
|
+
// now, this regex can be updated before initialization
|
2185
|
+
ts.regex.urlProtocolTest = /^(https?|ftp|file):\/\//;
|
2186
|
+
ts.regex.urlProtocolReplace = /(https?|ftp|file):\/\//;
|
2163
2187
|
ts.addParser({
|
2164
2188
|
id: 'url',
|
2165
2189
|
is: function(s) {
|
2166
|
-
return
|
2190
|
+
return ts.regex.urlProtocolTest.test(s);
|
2167
2191
|
},
|
2168
2192
|
format: function(s) {
|
2169
|
-
return s ? $.trim(s.replace(
|
2193
|
+
return s ? $.trim(s.replace(ts.regex.urlProtocolReplace, '')) : s;
|
2170
2194
|
},
|
2171
2195
|
parsed : true, // filter widget flag
|
2172
2196
|
type: 'text'
|
2173
2197
|
});
|
2174
2198
|
|
2199
|
+
ts.regex.dash = /-/g;
|
2200
|
+
ts.regex.isoDate = /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/;
|
2175
2201
|
ts.addParser({
|
2176
2202
|
id: 'isoDate',
|
2177
2203
|
is: function(s) {
|
2178
|
-
return
|
2204
|
+
return ts.regex.isoDate.test(s);
|
2179
2205
|
},
|
2180
2206
|
format: function(s, table) {
|
2181
|
-
var date = s ? new Date( s.replace(
|
2207
|
+
var date = s ? new Date( s.replace(ts.regex.dash, '/') ) : s;
|
2182
2208
|
return date instanceof Date && isFinite(date) ? date.getTime() : s;
|
2183
2209
|
},
|
2184
2210
|
type: 'numeric'
|
2185
2211
|
});
|
2186
2212
|
|
2213
|
+
ts.regex.percent = /%/g;
|
2214
|
+
ts.regex.percentTest = /(\d\s*?%|%\s*?\d)/;
|
2187
2215
|
ts.addParser({
|
2188
2216
|
id: 'percent',
|
2189
2217
|
is: function(s) {
|
2190
|
-
return
|
2218
|
+
return ts.regex.percentTest.test(s) && s.length < 15;
|
2191
2219
|
},
|
2192
2220
|
format: function(s, table) {
|
2193
|
-
return s ? ts.formatFloat(s.replace(
|
2221
|
+
return s ? ts.formatFloat(s.replace(ts.regex.percent, ''), table) : s;
|
2194
2222
|
},
|
2195
2223
|
type: 'numeric'
|
2196
2224
|
});
|
@@ -2208,27 +2236,35 @@
|
|
2208
2236
|
type: 'text'
|
2209
2237
|
});
|
2210
2238
|
|
2239
|
+
ts.regex.dateReplace = /(\S)([AP]M)$/i; // used by usLongDate & time parser
|
2240
|
+
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;
|
2241
|
+
ts.regex.usLongDateTest2 = /^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i;
|
2211
2242
|
ts.addParser({
|
2212
2243
|
id: 'usLongDate',
|
2213
2244
|
is: function(s) {
|
2214
2245
|
// two digit years are not allowed cross-browser
|
2215
2246
|
// Jan 01, 2013 12:34:56 PM or 01 Jan 2013
|
2216
|
-
return (
|
2217
|
-
(/^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i).test(s);
|
2247
|
+
return ts.regex.usLongDateTest1.test(s) || ts.regex.usLongDateTest2.test(s);
|
2218
2248
|
},
|
2219
2249
|
format: function(s, table) {
|
2220
|
-
var date = s ? new Date( s.replace(
|
2250
|
+
var date = s ? new Date( s.replace(ts.regex.dateReplace, '$1 $2') ) : s;
|
2221
2251
|
return date instanceof Date && isFinite(date) ? date.getTime() : s;
|
2222
2252
|
},
|
2223
2253
|
type: 'numeric'
|
2224
2254
|
});
|
2225
2255
|
|
2256
|
+
// testing for ##-##-#### or ####-##-##, so it's not perfect; time can be included
|
2257
|
+
ts.regex.shortDateTest = /(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/;
|
2258
|
+
// escaped "-" because JSHint in Firefox was showing it as an error
|
2259
|
+
ts.regex.shortDateReplace = /[\-.,]/g;
|
2260
|
+
// XXY covers MDY & DMY formats
|
2261
|
+
ts.regex.shortDateXXY = /(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/;
|
2262
|
+
ts.regex.shortDateYMD = /(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/;
|
2226
2263
|
ts.addParser({
|
2227
2264
|
id: 'shortDate', // 'mmddyyyy', 'ddmmyyyy' or 'yyyymmdd'
|
2228
2265
|
is: function(s) {
|
2229
|
-
s = (s || '').replace(
|
2230
|
-
|
2231
|
-
return (/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/).test(s);
|
2266
|
+
s = (s || '').replace(ts.regex.spaces, ' ').replace(ts.regex.shortDateReplace, '/');
|
2267
|
+
return ts.regex.shortDateTest.test(s);
|
2232
2268
|
},
|
2233
2269
|
format: function(s, table, cell, cellIndex) {
|
2234
2270
|
if (s) {
|
@@ -2238,14 +2274,13 @@
|
|
2238
2274
|
format = ci.length && ci[0].dateFormat ||
|
2239
2275
|
ts.getData( ci, ts.getColumnData( table, c.headers, cellIndex ), 'dateFormat') ||
|
2240
2276
|
c.dateFormat;
|
2241
|
-
|
2242
|
-
d = s.replace(/\s+/g, ' ').replace(/[\-.,]/g, '/');
|
2277
|
+
d = s.replace(ts.regex.spaces, ' ').replace(ts.regex.shortDateReplace, '/');
|
2243
2278
|
if (format === 'mmddyyyy') {
|
2244
|
-
d = d.replace(
|
2279
|
+
d = d.replace(ts.regex.shortDateXXY, '$3/$1/$2');
|
2245
2280
|
} else if (format === 'ddmmyyyy') {
|
2246
|
-
d = d.replace(
|
2281
|
+
d = d.replace(ts.regex.shortDateXXY, '$3/$2/$1');
|
2247
2282
|
} else if (format === 'yyyymmdd') {
|
2248
|
-
d = d.replace(
|
2283
|
+
d = d.replace(ts.regex.shortDateYMD, '$1/$2/$3');
|
2249
2284
|
}
|
2250
2285
|
date = new Date(d);
|
2251
2286
|
return date instanceof Date && isFinite(date) ? date.getTime() : s;
|
@@ -2255,13 +2290,14 @@
|
|
2255
2290
|
type: 'numeric'
|
2256
2291
|
});
|
2257
2292
|
|
2293
|
+
ts.regex.timeTest = /^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i;
|
2258
2294
|
ts.addParser({
|
2259
2295
|
id: 'time',
|
2260
2296
|
is: function(s) {
|
2261
|
-
return
|
2297
|
+
return ts.regex.timeTest.test(s);
|
2262
2298
|
},
|
2263
2299
|
format: function(s, table) {
|
2264
|
-
var date = s ? new Date( '2000/01/01 ' + s.replace(
|
2300
|
+
var date = s ? new Date( '2000/01/01 ' + s.replace(ts.regex.dateReplace, '$1 $2') ) : s;
|
2265
2301
|
return date instanceof Date && isFinite(date) ? date.getTime() : s;
|
2266
2302
|
},
|
2267
2303
|
type: 'numeric'
|
@@ -2678,14 +2714,15 @@
|
|
2678
2714
|
|
2679
2715
|
})(jQuery);
|
2680
2716
|
|
2681
|
-
/*! Widget: filter - updated 8/
|
2717
|
+
/*! Widget: filter - updated 8/23/2015 (v2.23.2) *//*
|
2682
2718
|
* Requires tablesorter v2.8+ and jQuery 1.7+
|
2683
2719
|
* by Rob Garrison
|
2684
2720
|
*/
|
2685
2721
|
;( function ( $ ) {
|
2686
2722
|
'use strict';
|
2687
|
-
var
|
2688
|
-
|
2723
|
+
var tsf,
|
2724
|
+
ts = $.tablesorter || {},
|
2725
|
+
tscss = ts.css;
|
2689
2726
|
|
2690
2727
|
$.extend( tscss, {
|
2691
2728
|
filterRow : 'tablesorter-filter-row',
|
@@ -2729,7 +2766,7 @@
|
|
2729
2766
|
},
|
2730
2767
|
format: function( table, c, wo ) {
|
2731
2768
|
if ( !c.$table.hasClass( 'hasFilters' ) ) {
|
2732
|
-
|
2769
|
+
tsf.init( table, c, wo );
|
2733
2770
|
}
|
2734
2771
|
},
|
2735
2772
|
remove: function( table, c, wo, refreshing ) {
|
@@ -2741,7 +2778,7 @@
|
|
2741
2778
|
$table
|
2742
2779
|
.removeClass( 'hasFilters' )
|
2743
2780
|
// add .tsfilter namespace to all BUT search
|
2744
|
-
.unbind( events.replace(
|
2781
|
+
.unbind( events.replace( ts.regex.spaces, ' ' ) )
|
2745
2782
|
// remove the filter row even if refreshing, because the column might have been moved
|
2746
2783
|
.find( '.' + tscss.filterRow ).remove();
|
2747
2784
|
if ( refreshing ) { return; }
|
@@ -2756,7 +2793,7 @@
|
|
2756
2793
|
}
|
2757
2794
|
});
|
2758
2795
|
|
2759
|
-
ts.filter = {
|
2796
|
+
tsf = ts.filter = {
|
2760
2797
|
|
2761
2798
|
// regex used in filter 'check' functions - not for general use and not documented
|
2762
2799
|
regex: {
|
@@ -2765,9 +2802,13 @@
|
|
2765
2802
|
filtered : /filtered/, // filtered (hidden) row class name; updated in the script
|
2766
2803
|
type : /undefined|number/, // check type
|
2767
2804
|
exact : /(^[\"\'=]+)|([\"\'=]+$)/g, // exact match (allow '==')
|
2768
|
-
nondigit : /[^\w,. \-()]/g, // replace non-digits (from digit & currency parser)
|
2769
2805
|
operators : /[<>=]/g, // replace operators
|
2770
|
-
query : '(q|query)' // replace filter queries
|
2806
|
+
query : '(q|query)', // replace filter queries
|
2807
|
+
wild01 : /\?/g, // wild card match 0 or 1
|
2808
|
+
wild0More : /\*/g, // wild care match 0 or more
|
2809
|
+
quote : /\"/g,
|
2810
|
+
isNeg1 : /(>=?\s*-\d)/,
|
2811
|
+
isNeg2 : /(<=?\s*\d)/
|
2771
2812
|
},
|
2772
2813
|
// function( c, data ) { }
|
2773
2814
|
// c = table.config
|
@@ -2784,27 +2825,27 @@
|
|
2784
2825
|
// data.parsed = array ( by column ) of boolean values ( from filter_useParsedData or 'filter-parsed' class )
|
2785
2826
|
types: {
|
2786
2827
|
or : function( c, data, vars ) {
|
2787
|
-
if (
|
2828
|
+
if ( tsf.regex.orTest.test( data.iFilter ) || tsf.regex.orSplit.test( data.filter ) ) {
|
2788
2829
|
var indx, filterMatched, query, regex,
|
2789
2830
|
// duplicate data but split filter
|
2790
2831
|
data2 = $.extend( {}, data ),
|
2791
2832
|
index = data.index,
|
2792
2833
|
parsed = data.parsed[ index ],
|
2793
|
-
filter = data.filter.split(
|
2794
|
-
iFilter = data.iFilter.split(
|
2834
|
+
filter = data.filter.split( tsf.regex.orSplit ),
|
2835
|
+
iFilter = data.iFilter.split( tsf.regex.orSplit ),
|
2795
2836
|
len = filter.length;
|
2796
2837
|
for ( indx = 0; indx < len; indx++ ) {
|
2797
2838
|
data2.nestedFilters = true;
|
2798
|
-
data2.filter = '' + (
|
2799
|
-
data2.iFilter = '' + (
|
2800
|
-
query = '(' + (
|
2839
|
+
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' );
|
2840
|
+
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
|
2841
|
+
query = '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')';
|
2801
2842
|
try {
|
2802
2843
|
// use try/catch, because query may not be a valid regex if "|" is contained within a partial regex search,
|
2803
2844
|
// e.g "/(Alex|Aar" -> Uncaught SyntaxError: Invalid regular expression: /(/(Alex)/: Unterminated group
|
2804
2845
|
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
|
2805
2846
|
// filterMatched = data2.filter === '' && indx > 0 ? true
|
2806
2847
|
// look for an exact match with the 'or' unless the 'filter-match' class is found
|
2807
|
-
filterMatched = regex.test( data2.exact ) ||
|
2848
|
+
filterMatched = regex.test( data2.exact ) || tsf.processTypes( c, data2, vars );
|
2808
2849
|
if ( filterMatched ) {
|
2809
2850
|
return filterMatched;
|
2810
2851
|
}
|
@@ -2819,27 +2860,27 @@
|
|
2819
2860
|
},
|
2820
2861
|
// Look for an AND or && operator ( logical and )
|
2821
2862
|
and : function( c, data, vars ) {
|
2822
|
-
if (
|
2863
|
+
if ( tsf.regex.andTest.test( data.filter ) ) {
|
2823
2864
|
var indx, filterMatched, result, query, regex,
|
2824
2865
|
// duplicate data but split filter
|
2825
2866
|
data2 = $.extend( {}, data ),
|
2826
2867
|
index = data.index,
|
2827
2868
|
parsed = data.parsed[ index ],
|
2828
|
-
filter = data.filter.split(
|
2829
|
-
iFilter = data.iFilter.split(
|
2869
|
+
filter = data.filter.split( tsf.regex.andSplit ),
|
2870
|
+
iFilter = data.iFilter.split( tsf.regex.andSplit ),
|
2830
2871
|
len = filter.length;
|
2831
2872
|
for ( indx = 0; indx < len; indx++ ) {
|
2832
2873
|
data2.nestedFilters = true;
|
2833
|
-
data2.filter = '' + (
|
2834
|
-
data2.iFilter = '' + (
|
2835
|
-
query = ( '(' + (
|
2874
|
+
data2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], index, parsed ) || '' );
|
2875
|
+
data2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], index, parsed ) || '' );
|
2876
|
+
query = ( '(' + ( tsf.parseFilter( c, data2.filter, index, parsed ) || '' ) + ')' )
|
2836
2877
|
// replace wild cards since /(a*)/i will match anything
|
2837
|
-
.replace(
|
2878
|
+
.replace( tsf.regex.wild01, '\\S{1}' ).replace( tsf.regex.wild0More, '\\S*' );
|
2838
2879
|
try {
|
2839
2880
|
// use try/catch just in case RegExp is invalid
|
2840
2881
|
regex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );
|
2841
2882
|
// look for an exact match with the 'and' unless the 'filter-match' class is found
|
2842
|
-
result = ( regex.test( data2.exact ) ||
|
2883
|
+
result = ( regex.test( data2.exact ) || tsf.processTypes( c, data2, vars ) );
|
2843
2884
|
if ( indx === 0 ) {
|
2844
2885
|
filterMatched = result;
|
2845
2886
|
} else {
|
@@ -2856,10 +2897,10 @@
|
|
2856
2897
|
},
|
2857
2898
|
// Look for regex
|
2858
2899
|
regex: function( c, data ) {
|
2859
|
-
if (
|
2900
|
+
if ( tsf.regex.regex.test( data.filter ) ) {
|
2860
2901
|
var matches,
|
2861
2902
|
// cache regex per column for optimal speed
|
2862
|
-
regex = data.filter_regexCache[ data.index ] ||
|
2903
|
+
regex = data.filter_regexCache[ data.index ] || tsf.regex.regex.exec( data.filter ),
|
2863
2904
|
isRegex = regex instanceof RegExp;
|
2864
2905
|
try {
|
2865
2906
|
if ( !isRegex ) {
|
@@ -2878,18 +2919,18 @@
|
|
2878
2919
|
// Look for operators >, >=, < or <=
|
2879
2920
|
operators: function( c, data ) {
|
2880
2921
|
// ignore empty strings... because '' < 10 is true
|
2881
|
-
if (
|
2922
|
+
if ( tsf.regex.operTest.test( data.iFilter ) && data.iExact !== '' ) {
|
2882
2923
|
var cachedValue, result, txt,
|
2883
2924
|
table = c.table,
|
2884
2925
|
index = data.index,
|
2885
2926
|
parsed = data.parsed[index],
|
2886
|
-
query = ts.formatFloat( data.iFilter.replace(
|
2927
|
+
query = ts.formatFloat( data.iFilter.replace( tsf.regex.operators, '' ), table ),
|
2887
2928
|
parser = c.parsers[index],
|
2888
2929
|
savedSearch = query;
|
2889
2930
|
// parse filter value in case we're comparing numbers ( dates )
|
2890
2931
|
if ( parsed || parser.type === 'numeric' ) {
|
2891
|
-
txt = $.trim( '' + data.iFilter.replace(
|
2892
|
-
result =
|
2932
|
+
txt = $.trim( '' + data.iFilter.replace( tsf.regex.operators, '' ) );
|
2933
|
+
result = tsf.parseFilter( c, txt, index, true );
|
2893
2934
|
query = ( typeof result === 'number' && result !== '' && !isNaN( result ) ) ? result : query;
|
2894
2935
|
}
|
2895
2936
|
// iExact may be numeric - see issue #149;
|
@@ -2898,13 +2939,13 @@
|
|
2898
2939
|
typeof data.cache !== 'undefined' ) {
|
2899
2940
|
cachedValue = data.cache;
|
2900
2941
|
} else {
|
2901
|
-
txt = isNaN( data.iExact ) ? data.iExact.replace( ts.
|
2942
|
+
txt = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
|
2902
2943
|
cachedValue = ts.formatFloat( txt, table );
|
2903
2944
|
}
|
2904
|
-
if (
|
2905
|
-
result =
|
2906
|
-
} else if (
|
2907
|
-
result =
|
2945
|
+
if ( tsf.regex.gtTest.test( data.iFilter ) ) {
|
2946
|
+
result = tsf.regex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;
|
2947
|
+
} else if ( tsf.regex.ltTest.test( data.iFilter ) ) {
|
2948
|
+
result = tsf.regex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;
|
2908
2949
|
}
|
2909
2950
|
// keep showing all rows if nothing follows the operator
|
2910
2951
|
if ( !result && savedSearch === '' ) {
|
@@ -2916,13 +2957,13 @@
|
|
2916
2957
|
},
|
2917
2958
|
// Look for a not match
|
2918
2959
|
notMatch: function( c, data ) {
|
2919
|
-
if (
|
2960
|
+
if ( tsf.regex.notTest.test( data.iFilter ) ) {
|
2920
2961
|
var indx,
|
2921
2962
|
txt = data.iFilter.replace( '!', '' ),
|
2922
|
-
filter =
|
2923
|
-
if (
|
2963
|
+
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
2964
|
+
if ( tsf.regex.exact.test( filter ) ) {
|
2924
2965
|
// look for exact not matches - see #628
|
2925
|
-
filter = filter.replace(
|
2966
|
+
filter = filter.replace( tsf.regex.exact, '' );
|
2926
2967
|
return filter === '' ? true : $.trim( filter ) !== data.iExact;
|
2927
2968
|
} else {
|
2928
2969
|
indx = data.iExact.search( $.trim( filter ) );
|
@@ -2934,27 +2975,27 @@
|
|
2934
2975
|
// Look for quotes or equals to get an exact match; ignore type since iExact could be numeric
|
2935
2976
|
exact: function( c, data ) {
|
2936
2977
|
/*jshint eqeqeq:false */
|
2937
|
-
if (
|
2938
|
-
var txt = data.iFilter.replace(
|
2939
|
-
filter =
|
2978
|
+
if ( tsf.regex.exact.test( data.iFilter ) ) {
|
2979
|
+
var txt = data.iFilter.replace( tsf.regex.exact, '' ),
|
2980
|
+
filter = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
2940
2981
|
return data.anyMatch ? $.inArray( filter, data.rowArray ) >= 0 : filter == data.iExact;
|
2941
2982
|
}
|
2942
2983
|
return null;
|
2943
2984
|
},
|
2944
2985
|
// Look for a range ( using ' to ' or ' - ' ) - see issue #166; thanks matzhu!
|
2945
2986
|
range : function( c, data ) {
|
2946
|
-
if (
|
2987
|
+
if ( tsf.regex.toTest.test( data.iFilter ) ) {
|
2947
2988
|
var result, tmp, range1, range2,
|
2948
2989
|
table = c.table,
|
2949
2990
|
index = data.index,
|
2950
2991
|
parsed = data.parsed[index],
|
2951
2992
|
// make sure the dash is for a range and not indicating a negative number
|
2952
|
-
query = data.iFilter.split(
|
2993
|
+
query = data.iFilter.split( tsf.regex.toSplit );
|
2953
2994
|
|
2954
|
-
tmp = query[0].replace( ts.
|
2955
|
-
range1 = ts.formatFloat(
|
2956
|
-
tmp = query[1].replace( ts.
|
2957
|
-
range2 = ts.formatFloat(
|
2995
|
+
tmp = query[0].replace( ts.regex.nondigit, '' ) || '';
|
2996
|
+
range1 = ts.formatFloat( tsf.parseFilter( c, tmp, index, parsed ), table );
|
2997
|
+
tmp = query[1].replace( ts.regex.nondigit, '' ) || '';
|
2998
|
+
range2 = ts.formatFloat( tsf.parseFilter( c, tmp, index, parsed ), table );
|
2958
2999
|
// parse filter value in case we're comparing numbers ( dates )
|
2959
3000
|
if ( parsed || c.parsers[index].type === 'numeric' ) {
|
2960
3001
|
result = c.parsers[ index ].format( '' + query[0], table, c.$headers.eq( index ), index );
|
@@ -2965,7 +3006,7 @@
|
|
2965
3006
|
if ( ( parsed || c.parsers[ index ].type === 'numeric' ) && !isNaN( range1 ) && !isNaN( range2 ) ) {
|
2966
3007
|
result = data.cache;
|
2967
3008
|
} else {
|
2968
|
-
tmp = isNaN( data.iExact ) ? data.iExact.replace( ts.
|
3009
|
+
tmp = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;
|
2969
3010
|
result = ts.formatFloat( tmp, table );
|
2970
3011
|
}
|
2971
3012
|
if ( range1 > range2 ) {
|
@@ -2977,18 +3018,18 @@
|
|
2977
3018
|
},
|
2978
3019
|
// Look for wild card: ? = single, * = multiple, or | = logical OR
|
2979
3020
|
wild : function( c, data ) {
|
2980
|
-
if (
|
3021
|
+
if ( tsf.regex.wildOrTest.test( data.iFilter ) ) {
|
2981
3022
|
var index = data.index,
|
2982
3023
|
parsed = data.parsed[ index ],
|
2983
|
-
query = '' + (
|
3024
|
+
query = '' + ( tsf.parseFilter( c, data.iFilter, index, parsed ) || '' );
|
2984
3025
|
// look for an exact match with the 'or' unless the 'filter-match' class is found
|
2985
|
-
if (
|
3026
|
+
if ( !tsf.regex.wildTest.test( query ) && data.nestedFilters ) {
|
2986
3027
|
query = data.isMatch ? query : '^(' + query + ')$';
|
2987
3028
|
}
|
2988
3029
|
// parsing the filter may not work properly when using wildcards =/
|
2989
3030
|
try {
|
2990
3031
|
return new RegExp(
|
2991
|
-
query.replace(
|
3032
|
+
query.replace( tsf.regex.wild01, '\\S{1}' ).replace( tsf.regex.wild0More, '\\S*' ),
|
2992
3033
|
c.widgetOptions.filter_ignoreCase ? 'i' : ''
|
2993
3034
|
)
|
2994
3035
|
.test( data.exact );
|
@@ -3000,12 +3041,12 @@
|
|
3000
3041
|
},
|
3001
3042
|
// fuzzy text search; modified from https://github.com/mattyork/fuzzy ( MIT license )
|
3002
3043
|
fuzzy: function( c, data ) {
|
3003
|
-
if (
|
3044
|
+
if ( tsf.regex.fuzzyTest.test( data.iFilter ) ) {
|
3004
3045
|
var indx,
|
3005
3046
|
patternIndx = 0,
|
3006
3047
|
len = data.iExact.length,
|
3007
3048
|
txt = data.iFilter.slice( 1 ),
|
3008
|
-
pattern =
|
3049
|
+
pattern = tsf.parseFilter( c, txt, data.index, data.parsed[data.index] ) || '';
|
3009
3050
|
for ( indx = 0; indx < len; indx++ ) {
|
3010
3051
|
if ( data.iExact[ indx ] === pattern[ patternIndx ] ) {
|
3011
3052
|
patternIndx += 1;
|
@@ -3028,7 +3069,7 @@
|
|
3028
3069
|
}, ts.language );
|
3029
3070
|
|
3030
3071
|
var options, string, txt, $header, column, filters, val, fxn, noSelect,
|
3031
|
-
regex =
|
3072
|
+
regex = tsf.regex;
|
3032
3073
|
c.$table.addClass( 'hasFilters' );
|
3033
3074
|
|
3034
3075
|
// define timers so using clearTimeout won't cause an undefined error
|
@@ -3039,7 +3080,7 @@
|
|
3039
3080
|
wo.filter_anyColumnSelector = '[data-column="all"],[data-column="any"]';
|
3040
3081
|
wo.filter_multipleColumnSelector = '[data-column*="-"],[data-column*=","]';
|
3041
3082
|
|
3042
|
-
val = '\\{' +
|
3083
|
+
val = '\\{' + tsf.regex.query + '\\}';
|
3043
3084
|
$.extend( regex, {
|
3044
3085
|
child : new RegExp( c.cssChildRow ),
|
3045
3086
|
filtered : new RegExp( wo.filter_filteredRow ),
|
@@ -3048,9 +3089,20 @@
|
|
3048
3089
|
toSplit : new RegExp( '(?:\\s+(?:-|' + ts.language.to + ')\\s+)', 'gi' ),
|
3049
3090
|
andTest : new RegExp( '\\s+(' + ts.language.and + '|&&)\\s+', 'i' ),
|
3050
3091
|
andSplit : new RegExp( '(?:\\s+(?:' + ts.language.and + '|&&)\\s+)', 'gi' ),
|
3092
|
+
orTest : /\|/,
|
3051
3093
|
orSplit : new RegExp( '(?:\\s+(?:' + ts.language.or + ')\\s+|\\|)', 'gi' ),
|
3052
3094
|
iQuery : new RegExp( val, 'i' ),
|
3053
|
-
igQuery : new RegExp( val, 'ig' )
|
3095
|
+
igQuery : new RegExp( val, 'ig' ),
|
3096
|
+
operTest : /^[<>]=?/,
|
3097
|
+
gtTest : />/,
|
3098
|
+
gteTest : />=/,
|
3099
|
+
ltTest : /</,
|
3100
|
+
lteTest : /<=/,
|
3101
|
+
notTest : /^\!/,
|
3102
|
+
wildOrTest : /[\?\*\|]/,
|
3103
|
+
wildTest : /\?\*/,
|
3104
|
+
fuzzyTest : /^~/,
|
3105
|
+
exactTest : /[=\"\|!]/
|
3054
3106
|
});
|
3055
3107
|
|
3056
3108
|
// don't build filter row if columnFilters is false or all columns are set to 'filter-false'
|
@@ -3058,7 +3110,7 @@
|
|
3058
3110
|
val = c.$headers.filter( '.filter-false, .parser-false' ).length;
|
3059
3111
|
if ( wo.filter_columnFilters !== false && val !== c.$headers.length ) {
|
3060
3112
|
// build filter row
|
3061
|
-
|
3113
|
+
tsf.buildRow( table, c, wo );
|
3062
3114
|
}
|
3063
3115
|
|
3064
3116
|
txt = 'addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search '
|
@@ -3071,13 +3123,13 @@
|
|
3071
3123
|
c.$table.find( '.' + tscss.filterRow ).toggleClass( wo.filter_filteredRow, val ); // fixes #450
|
3072
3124
|
if ( !/(search|filter)/.test( event.type ) ) {
|
3073
3125
|
event.stopPropagation();
|
3074
|
-
|
3126
|
+
tsf.buildDefault( table, true );
|
3075
3127
|
}
|
3076
3128
|
if ( event.type === 'filterReset' ) {
|
3077
3129
|
c.$table.find( '.' + tscss.filter ).add( wo.filter_$externalFilters ).val( '' );
|
3078
|
-
|
3130
|
+
tsf.searching( table, [] );
|
3079
3131
|
} else if ( event.type === 'filterEnd' ) {
|
3080
|
-
|
3132
|
+
tsf.buildDefault( table, true );
|
3081
3133
|
} else {
|
3082
3134
|
// send false argument to force a new search; otherwise if the filter hasn't changed,
|
3083
3135
|
// it will return
|
@@ -3091,7 +3143,7 @@
|
|
3091
3143
|
// pass true ( skipFirst ) to prevent the tablesorter.setFilters function from skipping the first
|
3092
3144
|
// input ensures all inputs are updated when a search is triggered on the table
|
3093
3145
|
// $( 'table' ).trigger( 'search', [...] );
|
3094
|
-
|
3146
|
+
tsf.searching( table, filter, true );
|
3095
3147
|
}
|
3096
3148
|
return false;
|
3097
3149
|
});
|
@@ -3124,7 +3176,7 @@
|
|
3124
3176
|
noSelect = !( $header.hasClass( 'filter-false' ) || $header.hasClass( 'parser-false' ) );
|
3125
3177
|
options = '';
|
3126
3178
|
if ( fxn === true && noSelect ) {
|
3127
|
-
|
3179
|
+
tsf.buildSelect( table, column );
|
3128
3180
|
} else if ( typeof fxn === 'object' && noSelect ) {
|
3129
3181
|
// add custom drop down list
|
3130
3182
|
for ( string in fxn ) {
|
@@ -3157,7 +3209,7 @@
|
|
3157
3209
|
fxn = $.isFunction( txt ) ? true : ts.getColumnData( table, txt, column );
|
3158
3210
|
if ( fxn ) {
|
3159
3211
|
// updating so the extra options are appended
|
3160
|
-
|
3212
|
+
tsf.buildSelect( c.table, column, '', true, $header.hasClass( wo.filter_onlyAvail ) );
|
3161
3213
|
}
|
3162
3214
|
}
|
3163
3215
|
}
|
@@ -3165,22 +3217,22 @@
|
|
3165
3217
|
}
|
3166
3218
|
// not really updating, but if the column has both the 'filter-select' class &
|
3167
3219
|
// filter_functions set to true, it would append the same options twice.
|
3168
|
-
|
3220
|
+
tsf.buildDefault( table, true );
|
3169
3221
|
|
3170
|
-
|
3222
|
+
tsf.bindSearch( table, c.$table.find( '.' + tscss.filter ), true );
|
3171
3223
|
if ( wo.filter_external ) {
|
3172
|
-
|
3224
|
+
tsf.bindSearch( table, wo.filter_external );
|
3173
3225
|
}
|
3174
3226
|
|
3175
3227
|
if ( wo.filter_hideFilters ) {
|
3176
|
-
|
3228
|
+
tsf.hideFilters( table, c );
|
3177
3229
|
}
|
3178
3230
|
|
3179
3231
|
// show processing icon
|
3180
3232
|
if ( c.showProcessing ) {
|
3181
3233
|
txt = 'filterStart filterEnd '.split( ' ' ).join( c.namespace + 'filter ' );
|
3182
3234
|
c.$table
|
3183
|
-
.unbind( txt.replace(
|
3235
|
+
.unbind( txt.replace( ts.regex.spaces, ' ' ) )
|
3184
3236
|
.bind( txt, function( event, columns ) {
|
3185
3237
|
// only add processing to certain columns to all columns
|
3186
3238
|
$header = ( columns ) ?
|
@@ -3200,11 +3252,11 @@
|
|
3200
3252
|
// add default values
|
3201
3253
|
txt = 'tablesorter-initialized pagerBeforeInitialized '.split( ' ' ).join( c.namespace + 'filter ' );
|
3202
3254
|
c.$table
|
3203
|
-
.unbind( txt.replace(
|
3255
|
+
.unbind( txt.replace( ts.regex.spaces, ' ' ) )
|
3204
3256
|
.bind( txt, function() {
|
3205
3257
|
// redefine 'wo' as it does not update properly inside this callback
|
3206
3258
|
var wo = this.config.widgetOptions;
|
3207
|
-
filters =
|
3259
|
+
filters = tsf.setDefaults( table, c, wo ) || [];
|
3208
3260
|
if ( filters.length ) {
|
3209
3261
|
// prevent delayInit from triggering a cache build if filters are empty
|
3210
3262
|
if ( !( c.delayInit && filters.join( '' ) === '' ) ) {
|
@@ -3215,7 +3267,7 @@
|
|
3215
3267
|
// trigger init after setTimeout to prevent multiple filterStart/End/Init triggers
|
3216
3268
|
setTimeout( function() {
|
3217
3269
|
if ( !wo.filter_initialized ) {
|
3218
|
-
|
3270
|
+
tsf.filterInitComplete( c );
|
3219
3271
|
}
|
3220
3272
|
}, 100 );
|
3221
3273
|
});
|
@@ -3223,7 +3275,7 @@
|
|
3223
3275
|
if ( c.pager && c.pager.initialized && !wo.filter_initialized ) {
|
3224
3276
|
c.$table.trigger( 'filterFomatterUpdate' );
|
3225
3277
|
setTimeout( function() {
|
3226
|
-
|
3278
|
+
tsf.filterInitComplete( c );
|
3227
3279
|
}, 100 );
|
3228
3280
|
}
|
3229
3281
|
},
|
@@ -3244,7 +3296,7 @@
|
|
3244
3296
|
completed = function() {
|
3245
3297
|
wo.filter_initialized = true;
|
3246
3298
|
c.$table.trigger( 'filterInit', c );
|
3247
|
-
|
3299
|
+
tsf.findRows( c.table, c.$table.data( 'lastSearch' ) || [] );
|
3248
3300
|
};
|
3249
3301
|
if ( $.isEmptyObject( wo.filter_formatter ) ) {
|
3250
3302
|
completed();
|
@@ -3396,7 +3448,7 @@
|
|
3396
3448
|
// use data attribute instead of jQuery data since the head is cloned without including
|
3397
3449
|
// the data/binding
|
3398
3450
|
.attr( 'data-lastSearchTime', new Date().getTime() )
|
3399
|
-
.unbind( tmp.replace(
|
3451
|
+
.unbind( tmp.replace( ts.regex.spaces, ' ' ) )
|
3400
3452
|
// include change for select - fixes #473
|
3401
3453
|
.bind( 'keyup' + namespace, function( event ) {
|
3402
3454
|
$( this ).attr( 'data-lastSearchTime', new Date().getTime() );
|
@@ -3416,17 +3468,18 @@
|
|
3416
3468
|
return;
|
3417
3469
|
}
|
3418
3470
|
// change event = no delay; last true flag tells getFilters to skip newest timed input
|
3419
|
-
|
3471
|
+
tsf.searching( table, true, true );
|
3420
3472
|
})
|
3421
3473
|
.bind( 'search change keypress '.split( ' ' ).join( namespace + ' ' ), function( event ) {
|
3422
|
-
|
3474
|
+
// don't get cached data, in case data-column changes dynamically
|
3475
|
+
var column = parseInt( $( this ).attr( 'data-column' ), 10 );
|
3423
3476
|
// don't allow 'change' event to process if the input value is the same - fixes #685
|
3424
3477
|
if ( event.which === 13 || event.type === 'search' ||
|
3425
3478
|
event.type === 'change' && this.value !== c.lastSearch[column] ) {
|
3426
3479
|
event.preventDefault();
|
3427
3480
|
// init search with no delay
|
3428
3481
|
$( this ).attr( 'data-lastSearchTime', new Date().getTime() );
|
3429
|
-
|
3482
|
+
tsf.searching( table, false, true );
|
3430
3483
|
}
|
3431
3484
|
});
|
3432
3485
|
},
|
@@ -3436,11 +3489,11 @@
|
|
3436
3489
|
if ( typeof filter === 'undefined' || filter === true ) {
|
3437
3490
|
// delay filtering
|
3438
3491
|
wo.searchTimer = setTimeout( function() {
|
3439
|
-
|
3492
|
+
tsf.checkFilters( table, filter, skipFirst );
|
3440
3493
|
}, wo.filter_liveSearch ? wo.filter_searchDelay : 10 );
|
3441
3494
|
} else {
|
3442
3495
|
// skip delay
|
3443
|
-
|
3496
|
+
tsf.checkFilters( table, filter, skipFirst );
|
3444
3497
|
}
|
3445
3498
|
},
|
3446
3499
|
checkFilters: function( table, filter, skipFirst ) {
|
@@ -3454,7 +3507,7 @@
|
|
3454
3507
|
// update cache if delayInit set & pager has initialized ( after user initiates a search )
|
3455
3508
|
if ( c.delayInit && c.pager && c.pager.initialized ) {
|
3456
3509
|
c.$table.trigger( 'updateCache', [ function() {
|
3457
|
-
|
3510
|
+
tsf.checkFilters( table, false, skipFirst );
|
3458
3511
|
} ] );
|
3459
3512
|
}
|
3460
3513
|
return;
|
@@ -3485,11 +3538,11 @@
|
|
3485
3538
|
if ( c.showProcessing ) {
|
3486
3539
|
// give it time for the processing icon to kick in
|
3487
3540
|
setTimeout( function() {
|
3488
|
-
|
3541
|
+
tsf.findRows( table, filters, combinedFilters );
|
3489
3542
|
return false;
|
3490
3543
|
}, 30 );
|
3491
3544
|
} else {
|
3492
|
-
|
3545
|
+
tsf.findRows( table, filters, combinedFilters );
|
3493
3546
|
return false;
|
3494
3547
|
}
|
3495
3548
|
},
|
@@ -3532,8 +3585,8 @@
|
|
3532
3585
|
},
|
3533
3586
|
defaultFilter: function( filter, mask ) {
|
3534
3587
|
if ( filter === '' ) { return filter; }
|
3535
|
-
var regex =
|
3536
|
-
maskLen = mask.match(
|
3588
|
+
var regex = tsf.regex.iQuery,
|
3589
|
+
maskLen = mask.match( tsf.regex.igQuery ).length,
|
3537
3590
|
query = maskLen > 1 ? $.trim( filter ).split( /\s/ ) : [ $.trim( filter ) ],
|
3538
3591
|
len = query.length - 1,
|
3539
3592
|
indx = 0,
|
@@ -3569,7 +3622,10 @@
|
|
3569
3622
|
// & don't target 'all' column inputs if they don't exist
|
3570
3623
|
targets = wo.filter_initialized || !$input.filter( wo.filter_anyColumnSelector ).length,
|
3571
3624
|
columns = [],
|
3572
|
-
val = $.trim(
|
3625
|
+
val = $.trim( tsf.getLatestSearch( $input ).attr( 'data-column' ) || '' );
|
3626
|
+
if ( !/[,-]/.test(val) && val.length === 1 ) {
|
3627
|
+
return parseInt( val, 10 );
|
3628
|
+
}
|
3573
3629
|
// process column range
|
3574
3630
|
if ( targets && /-/.test( val ) ) {
|
3575
3631
|
ranges = val.match( /(\d+)\s*-\s*(\d+)/g );
|
@@ -3616,9 +3672,9 @@
|
|
3616
3672
|
var ffxn,
|
3617
3673
|
filterMatched = null,
|
3618
3674
|
matches = null;
|
3619
|
-
for ( ffxn in
|
3675
|
+
for ( ffxn in tsf.types ) {
|
3620
3676
|
if ( $.inArray( ffxn, vars.excludeMatch ) < 0 && matches === null ) {
|
3621
|
-
matches =
|
3677
|
+
matches = tsf.types[ffxn]( c, data, vars );
|
3622
3678
|
if ( matches !== null ) {
|
3623
3679
|
filterMatched = matches;
|
3624
3680
|
}
|
@@ -3627,16 +3683,23 @@
|
|
3627
3683
|
return filterMatched;
|
3628
3684
|
},
|
3629
3685
|
processRow: function( c, data, vars ) {
|
3630
|
-
var
|
3686
|
+
var hasSelect, result, val, filterMatched,
|
3631
3687
|
fxn, ffxn, txt,
|
3632
|
-
regex =
|
3688
|
+
regex = tsf.regex,
|
3633
3689
|
wo = c.widgetOptions,
|
3634
|
-
showRow = true
|
3690
|
+
showRow = true,
|
3691
|
+
|
3692
|
+
// if wo.filter_$anyMatch data-column attribute is changed dynamically
|
3693
|
+
// we don't want to do an "anyMatch" search on one column using data
|
3694
|
+
// for the entire row - see #998
|
3695
|
+
columnIndex = wo.filter_$anyMatch && wo.filter_$anyMatch.length ?
|
3696
|
+
// look for multiple columns '1-3,4-6,8'
|
3697
|
+
tsf.multipleColumns( c, wo.filter_$anyMatch ) :
|
3698
|
+
[];
|
3699
|
+
|
3635
3700
|
data.$cells = data.$row.children();
|
3636
3701
|
|
3637
|
-
if ( data.anyMatchFlag ) {
|
3638
|
-
// look for multiple columns '1-3,4-6,8'
|
3639
|
-
columnIndex = ts.filter.multipleColumns( c, wo.filter_$anyMatch );
|
3702
|
+
if ( data.anyMatchFlag && columnIndex.length > 1 ) {
|
3640
3703
|
data.anyMatch = true;
|
3641
3704
|
data.isMatch = true;
|
3642
3705
|
data.rowArray = data.$cells.map( function( i ) {
|
@@ -3660,7 +3723,7 @@
|
|
3660
3723
|
data.cache = data.cacheArray.slice( 0, -1 ).join( ' ' );
|
3661
3724
|
|
3662
3725
|
vars.excludeMatch = vars.noAnyMatch;
|
3663
|
-
filterMatched =
|
3726
|
+
filterMatched = tsf.processTypes( c, data, vars );
|
3664
3727
|
|
3665
3728
|
if ( filterMatched !== null ) {
|
3666
3729
|
showRow = filterMatched;
|
@@ -3721,7 +3784,7 @@
|
|
3721
3784
|
|
3722
3785
|
val = true;
|
3723
3786
|
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultColFilter[ columnIndex ] ) ) {
|
3724
|
-
data.filter =
|
3787
|
+
data.filter = tsf.defaultFilter( data.filter, vars.defaultColFilter[ columnIndex ] );
|
3725
3788
|
// val is used to indicate that a filter select is using a default filter;
|
3726
3789
|
// so we override the exact & partial matches
|
3727
3790
|
val = false;
|
@@ -3752,13 +3815,13 @@
|
|
3752
3815
|
if ( filterMatched === null ) {
|
3753
3816
|
// cycle through the different filters
|
3754
3817
|
// filters return a boolean or null if nothing matches
|
3755
|
-
filterMatched =
|
3818
|
+
filterMatched = tsf.processTypes( c, data, vars );
|
3756
3819
|
if ( filterMatched !== null ) {
|
3757
3820
|
result = filterMatched;
|
3758
3821
|
// Look for match, and add child row data for matching
|
3759
3822
|
} else {
|
3760
3823
|
txt = ( data.iExact + data.childRowText )
|
3761
|
-
.indexOf(
|
3824
|
+
.indexOf( tsf.parseFilter( c, data.iFilter, columnIndex, data.parsed[ columnIndex ] ) );
|
3762
3825
|
result = ( ( !wo.filter_startsWith && txt >= 0 ) || ( wo.filter_startsWith && txt === 0 ) );
|
3763
3826
|
}
|
3764
3827
|
} else {
|
@@ -3778,7 +3841,7 @@
|
|
3778
3841
|
isChild, childRow, lastSearch, showRow, time, val, indx,
|
3779
3842
|
notFiltered, searchFiltered, query, injected, res, id, txt,
|
3780
3843
|
storedFilters = $.extend( [], filters ),
|
3781
|
-
regex =
|
3844
|
+
regex = tsf.regex,
|
3782
3845
|
c = table.config,
|
3783
3846
|
wo = c.widgetOptions,
|
3784
3847
|
// data object passed to filters; anyMatch is a flag for the filters
|
@@ -3855,7 +3918,7 @@
|
|
3855
3918
|
data.anyMatchFlag = true;
|
3856
3919
|
data.anyMatchFilter = '' + (
|
3857
3920
|
filters[ c.columns ] ||
|
3858
|
-
wo.filter_$anyMatch &&
|
3921
|
+
wo.filter_$anyMatch && tsf.getLatestSearch( wo.filter_$anyMatch ).val() ||
|
3859
3922
|
''
|
3860
3923
|
);
|
3861
3924
|
if ( wo.filter_columnAnyMatch ) {
|
@@ -3897,10 +3960,10 @@
|
|
3897
3960
|
// if there is NOT a logical 'or', or range ( 'to' or '-' ) in the string
|
3898
3961
|
!regex.alreadyFiltered.test( val ) &&
|
3899
3962
|
// if we are not doing exact matches, using '|' ( logical or ) or not '!'
|
3900
|
-
|
3963
|
+
!regex.exactTest.test( val ) &&
|
3901
3964
|
// don't search only filtered if the value is negative
|
3902
3965
|
// ( '> -10' => '> -100' will ignore hidden rows )
|
3903
|
-
!(
|
3966
|
+
!( regex.isNeg1.test( val ) || regex.isNeg2.test( val ) ) &&
|
3904
3967
|
// if filtering using a select without a 'filter-match' class ( exact match ) - fixes #593
|
3905
3968
|
!( val !== '' && c.$filters && c.$filters.eq( indx ).find( 'select' ).length &&
|
3906
3969
|
!c.$headerIndexed[indx].hasClass( 'filter-match' ) );
|
@@ -3919,7 +3982,7 @@
|
|
3919
3982
|
data.anyMatchFilter = ts.replaceAccents( data.anyMatchFilter );
|
3920
3983
|
}
|
3921
3984
|
if ( wo.filter_defaultFilter && regex.iQuery.test( vars.defaultAnyFilter ) ) {
|
3922
|
-
data.anyMatchFilter =
|
3985
|
+
data.anyMatchFilter = tsf.defaultFilter( data.anyMatchFilter, vars.defaultAnyFilter );
|
3923
3986
|
// clear search filtered flag because default filters are not saved to the last search
|
3924
3987
|
searchFiltered = false;
|
3925
3988
|
}
|
@@ -3962,7 +4025,7 @@
|
|
3962
4025
|
'';
|
3963
4026
|
}
|
3964
4027
|
|
3965
|
-
showRow =
|
4028
|
+
showRow = tsf.processRow( c, data, vars );
|
3966
4029
|
childRow = rowData.$row.filter( ':gt( 0 )' );
|
3967
4030
|
|
3968
4031
|
if ( wo.filter_childRows && childRow.length ) {
|
@@ -3973,7 +4036,7 @@
|
|
3973
4036
|
data.cacheArray = rowData.child[ indx ];
|
3974
4037
|
data.rawArray = data.cacheArray;
|
3975
4038
|
// use OR comparison on child rows
|
3976
|
-
showRow = showRow ||
|
4039
|
+
showRow = showRow || tsf.processRow( c, data, vars );
|
3977
4040
|
}
|
3978
4041
|
}
|
3979
4042
|
childRow.toggleClass( wo.filter_filteredRow, !showRow );
|
@@ -4035,7 +4098,7 @@
|
|
4035
4098
|
}
|
4036
4099
|
if ( arry === false ) {
|
4037
4100
|
// fall back to original method
|
4038
|
-
arry =
|
4101
|
+
arry = tsf.getOptions( table, column, onlyAvail );
|
4039
4102
|
}
|
4040
4103
|
|
4041
4104
|
// get unique elements and sort the list
|
@@ -4147,13 +4210,13 @@
|
|
4147
4210
|
// nothing included in arry ( external source ), so get the options from
|
4148
4211
|
// filter_selectSource or column data
|
4149
4212
|
if ( typeof arry === 'undefined' || arry === '' ) {
|
4150
|
-
arry =
|
4213
|
+
arry = tsf.getOptionSource( table, column, onlyAvail );
|
4151
4214
|
}
|
4152
4215
|
|
4153
4216
|
if ( $.isArray( arry ) ) {
|
4154
4217
|
// build option list
|
4155
4218
|
for ( indx = 0; indx < arry.length; indx++ ) {
|
4156
|
-
txt = arry[indx] = ( '' + arry[indx] ).replace(
|
4219
|
+
txt = arry[indx] = ( '' + arry[indx] ).replace( tsf.regex.quote, '"' );
|
4157
4220
|
val = txt;
|
4158
4221
|
// allow including a symbol in the selectSource array
|
4159
4222
|
// 'a-z|A through Z' so that 'a-z' becomes the option value
|
@@ -4209,7 +4272,7 @@
|
|
4209
4272
|
// look for the filter-select class; build/update it if found
|
4210
4273
|
if ( ( $header.hasClass( 'filter-select' ) ||
|
4211
4274
|
ts.getColumnData( table, wo.filter_functions, columnIndex ) === true ) && noSelect ) {
|
4212
|
-
|
4275
|
+
tsf.buildSelect( table, columnIndex, '', updating, $header.hasClass( wo.filter_onlyAvail ) );
|
4213
4276
|
}
|
4214
4277
|
}
|
4215
4278
|
}
|
@@ -4245,7 +4308,7 @@
|
|
4245
4308
|
$column = $filters.filter( cols );
|
4246
4309
|
if ( $column.length ) {
|
4247
4310
|
// move the latest search to the first slot in the array
|
4248
|
-
$column =
|
4311
|
+
$column = tsf.getLatestSearch( $column );
|
4249
4312
|
if ( $.isArray( setFilters ) ) {
|
4250
4313
|
// skip first ( latest input ) to maintain cursor position while typing
|
4251
4314
|
if ( skipFirst && $column.length > 1 ) {
|
@@ -4295,7 +4358,7 @@
|
|
4295
4358
|
// ensure new set filters are applied, even if the search is the same
|
4296
4359
|
c.lastCombinedFilter = null;
|
4297
4360
|
c.lastSearch = [];
|
4298
|
-
|
4361
|
+
tsf.searching( c.table, filter, skipFirst );
|
4299
4362
|
c.$table.trigger( 'filterFomatterUpdate' );
|
4300
4363
|
}
|
4301
4364
|
return !!valid;
|