jquery-tablesorter 1.11.2 → 1.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/lib/jquery-tablesorter/version.rb +1 -1
- data/vendor/assets/images/jquery-tablesorter/bootstrap-black-unsorted.png +0 -0
- data/vendor/assets/images/jquery-tablesorter/bootstrap-white-unsorted.png +0 -0
- data/vendor/assets/images/jquery-tablesorter/metro-black-asc.png +0 -0
- data/vendor/assets/images/jquery-tablesorter/metro-black-desc.png +0 -0
- data/vendor/assets/images/jquery-tablesorter/metro-loading.gif +0 -0
- data/vendor/assets/images/jquery-tablesorter/metro-unsorted.png +0 -0
- data/vendor/assets/images/jquery-tablesorter/metro-white-asc.png +0 -0
- data/vendor/assets/images/jquery-tablesorter/metro-white-desc.png +0 -0
- data/vendor/assets/javascripts/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.js +8 -3
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.js +94 -29
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets.js +103 -67
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-columnSelector.js +18 -7
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-cssStickyHeaders.js +10 -7
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-math.js +64 -25
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-output.js +45 -21
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-pager.js +9 -4
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-print.js +122 -0
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-scroller.js +3 -3
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.bootstrap.css +9 -3
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.green.css +10 -10
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.metro-dark.css +192 -0
- metadata +12 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65ae3cb21c44ee0f6bfee2c97b57b137ae72b4eb
|
4
|
+
data.tar.gz: 8497edb9c98963bd4645d158c8b161467646d23a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 297953c27301fe09470785ac076576f262ed73f4c8847a2b8da5d0485e9f4bd629755b586021d5ca11a859972a950825cf0f16306de247ddedd0e30e09f1e51a
|
7
|
+
data.tar.gz: 9c2d2ee68462a3c05b1a35c9294bd0fd4c2d22daf20949aed52dc1d37e133ea4f4b541f0cb7fa4d6503d6fa7132605de69597b798dc65865c212b0376c8c0234
|
data/README.md
CHANGED
@@ -4,9 +4,9 @@
|
|
4
4
|
|
5
5
|
Simple integration of jquery-tablesorter into the asset pipeline.
|
6
6
|
|
7
|
-
Current tablesorter version: 2.
|
7
|
+
Current tablesorter version: 2.17.0 (5/22/2014), [documentation]
|
8
8
|
|
9
|
-
Any issue
|
9
|
+
Any issue associated with the js/css files, please report to [Mottie's fork].
|
10
10
|
|
11
11
|
## Installation
|
12
12
|
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*!
|
2
2
|
* tablesorter pager plugin
|
3
|
-
* updated
|
3
|
+
* updated 5/22/2014 (v2.17.0)
|
4
4
|
*/
|
5
5
|
/*jshint browser:true, jquery:true, unused:false */
|
6
6
|
;(function($) {
|
@@ -289,7 +289,7 @@
|
|
289
289
|
exception === 'timeout' ? 'Time out error' :
|
290
290
|
exception === 'abort' ? 'Ajax Request aborted' :
|
291
291
|
'Uncaught error: ' + xhr.statusText + ' [' + xhr.status + ']' );
|
292
|
-
c.$tbodies.eq(0).
|
292
|
+
c.$tbodies.eq(0).detach();
|
293
293
|
p.totalRows = 0;
|
294
294
|
} else {
|
295
295
|
// process ajax object
|
@@ -311,7 +311,7 @@
|
|
311
311
|
if (d instanceof jQuery) {
|
312
312
|
if (p.processAjaxOnInit) {
|
313
313
|
// append jQuery object
|
314
|
-
c.$tbodies.eq(0).
|
314
|
+
c.$tbodies.eq(0).detach().append(d);
|
315
315
|
}
|
316
316
|
} else if (l) {
|
317
317
|
// build table from array
|
@@ -726,6 +726,11 @@
|
|
726
726
|
})
|
727
727
|
.bind('update updateRows updateAll addRows '.split(' ').join('.pager '), function(e){
|
728
728
|
e.stopPropagation();
|
729
|
+
fixHeight(table, p);
|
730
|
+
var $rows = c.$tbodies.eq(0).children();
|
731
|
+
p.totalRows = $rows.length - ( p.countChildRows ? 0 : $rows.filter('.' + c.cssChildRow).length );
|
732
|
+
p.totalPages = Math.ceil( p.totalRows / p.size );
|
733
|
+
updatePageDisplay(table, p);
|
729
734
|
hideRows(table, p);
|
730
735
|
})
|
731
736
|
.bind('pageSize.pager', function(e,v){
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/**!
|
2
|
-
* TableSorter 2.
|
2
|
+
* TableSorter 2.17.0 - Client-side table sorting with ease!
|
3
3
|
* @requires jQuery v1.2.6+
|
4
4
|
*
|
5
5
|
* Copyright (c) 2007 Christian Bach
|
@@ -24,7 +24,7 @@
|
|
24
24
|
|
25
25
|
var ts = this;
|
26
26
|
|
27
|
-
ts.version = "2.
|
27
|
+
ts.version = "2.17.0";
|
28
28
|
|
29
29
|
ts.parsers = [];
|
30
30
|
ts.widgets = [];
|
@@ -167,7 +167,7 @@
|
|
167
167
|
|
168
168
|
function getElementText(table, node, cellIndex) {
|
169
169
|
if (!node) { return ""; }
|
170
|
-
var c = table.config,
|
170
|
+
var te, c = table.config,
|
171
171
|
t = c.textExtraction || '',
|
172
172
|
text = "";
|
173
173
|
if (t === "basic") {
|
@@ -176,8 +176,8 @@
|
|
176
176
|
} else {
|
177
177
|
if (typeof(t) === "function") {
|
178
178
|
text = t(node, table, cellIndex);
|
179
|
-
} else if (typeof(
|
180
|
-
text =
|
179
|
+
} else if (typeof (te = ts.getColumnData( table, t, cellIndex )) === 'function') {
|
180
|
+
text = te(node, table, cellIndex);
|
181
181
|
} else {
|
182
182
|
// previous "simple" method
|
183
183
|
text = node.textContent || node.innerText || $(node).text() || "";
|
@@ -219,7 +219,7 @@
|
|
219
219
|
var c = table.config,
|
220
220
|
// update table bodies in case we start with an empty table
|
221
221
|
tb = c.$tbodies = c.$table.children('tbody:not(.' + c.cssInfoBlock + ')'),
|
222
|
-
rows, list, l, i, h, ch, p, time,
|
222
|
+
rows, list, l, i, h, ch, p, time,
|
223
223
|
j = 0,
|
224
224
|
parsersDebug = "",
|
225
225
|
len = tb.length;
|
@@ -233,16 +233,11 @@
|
|
233
233
|
while (j < len) {
|
234
234
|
rows = tb[j].rows;
|
235
235
|
if (rows[j]) {
|
236
|
-
l = rows[j].cells.length;
|
236
|
+
l = c.columns; // rows[j].cells.length;
|
237
237
|
for (i = 0; i < l; i++) {
|
238
|
-
|
239
|
-
//
|
240
|
-
|
241
|
-
h = h.add( c.$headers.filter('[colspan="1"]') ) // ie8 fix
|
242
|
-
.filter('[data-column="' + i + '"]:last');
|
243
|
-
// get headers option corrected index
|
244
|
-
indx = c.$headers.index(h);
|
245
|
-
ch = c.headers[indx];
|
238
|
+
h = c.$headers.filter('[data-column="' + i + '"]:last');
|
239
|
+
// get column indexed table cell
|
240
|
+
ch = ts.getColumnData( table, c.headers, i );
|
246
241
|
// get column parser
|
247
242
|
p = ts.getParserById( ts.getData(h, ch, 'sorter') );
|
248
243
|
// empty cells behaviour - keeping emptyToBottom for backwards compatibility
|
@@ -421,10 +416,12 @@
|
|
421
416
|
c.columns = ts.computeColumnIndex( c.$table.children('thead, tfoot').children('tr') );
|
422
417
|
// add icon if cssIcon option exists
|
423
418
|
i = c.cssIcon ? '<i class="' + ( c.cssIcon === ts.css.icon ? ts.css.icon : c.cssIcon + ' ' + ts.css.icon ) + '"></i>' : '';
|
424
|
-
c.$headers
|
419
|
+
c.$headers.each(function(index) {
|
425
420
|
$t = $(this);
|
426
|
-
|
427
|
-
|
421
|
+
// make sure to get header cell & not column indexed cell
|
422
|
+
ch = ts.getColumnData( table, c.headers, index, true );
|
423
|
+
// save original header content
|
424
|
+
c.headerContent[index] = $(this).html();
|
428
425
|
// set up header template
|
429
426
|
t = c.headerTemplate.replace(/\{content\}/g, $(this).html()).replace(/\{icon\}/g, i);
|
430
427
|
if (c.onRenderTemplate) {
|
@@ -473,10 +470,11 @@
|
|
473
470
|
}
|
474
471
|
|
475
472
|
function updateHeader(table) {
|
476
|
-
var s, $th,
|
473
|
+
var s, $th,
|
474
|
+
c = table.config;
|
477
475
|
c.$headers.each(function(index, th){
|
478
476
|
$th = $(th);
|
479
|
-
s = ts.getData( th, c.headers
|
477
|
+
s = ts.getData( th, ts.getColumnData( table, c.headers, index, true ), 'sorter' ) === 'false';
|
480
478
|
th.sortDisabled = s;
|
481
479
|
$th[ s ? 'addClass' : 'removeClass' ]('sorter-false').attr('aria-disabled', '' + s);
|
482
480
|
// aria-controls - requires table ID
|
@@ -546,19 +544,46 @@
|
|
546
544
|
}
|
547
545
|
}
|
548
546
|
|
549
|
-
function updateHeaderSortCount(table, list
|
550
|
-
var s, t, o,
|
547
|
+
function updateHeaderSortCount(table, list) {
|
548
|
+
var s, t, o, col, primary,
|
549
|
+
c = table.config,
|
551
550
|
sl = list || c.sortList;
|
552
551
|
c.sortList = [];
|
553
552
|
$.each(sl, function(i,v){
|
554
553
|
// ensure all sortList values are numeric - fixes #127
|
555
|
-
|
554
|
+
col = parseInt(v[0], 10);
|
556
555
|
// make sure header exists
|
557
|
-
o = c.$headers.filter('[data-column="' +
|
556
|
+
o = c.$headers.filter('[data-column="' + col + '"]:last')[0];
|
558
557
|
if (o) { // prevents error if sorton array is wrong
|
558
|
+
// o.count = o.count + 1;
|
559
|
+
t = ('' + v[1]).match(/^(1|d|s|o|n)/);
|
560
|
+
t = t ? t[0] : '';
|
561
|
+
// 0/(a)sc (default), 1/(d)esc, (s)ame, (o)pposite, (n)ext
|
562
|
+
switch(t) {
|
563
|
+
case '1': case 'd': // descending
|
564
|
+
t = 1;
|
565
|
+
break;
|
566
|
+
case 's': // same direction (as primary column)
|
567
|
+
// if primary sort is set to "s", make it ascending
|
568
|
+
t = primary || 0;
|
569
|
+
break;
|
570
|
+
case 'o':
|
571
|
+
s = o.order[(primary || 0) % (c.sortReset ? 3 : 2)];
|
572
|
+
// opposite of primary column; but resets if primary resets
|
573
|
+
t = s === 0 ? 1 : s === 1 ? 0 : 2;
|
574
|
+
break;
|
575
|
+
case 'n':
|
576
|
+
o.count = o.count + 1;
|
577
|
+
t = o.order[(o.count) % (c.sortReset ? 3 : 2)];
|
578
|
+
break;
|
579
|
+
default: // ascending
|
580
|
+
t = 0;
|
581
|
+
break;
|
582
|
+
}
|
583
|
+
primary = i === 0 ? t : primary;
|
584
|
+
s = [ col, parseInt(t, 10) || 0 ];
|
559
585
|
c.sortList.push(s);
|
560
586
|
t = $.inArray(s[1], o.order); // fixes issue #167
|
561
|
-
if (triggered) { o.count = o.count + 1; }
|
562
587
|
o.count = t >= 0 ? t : s[1] % (c.sortReset ? 3 : 2);
|
563
588
|
}
|
564
589
|
});
|
@@ -872,7 +897,7 @@
|
|
872
897
|
e.stopPropagation();
|
873
898
|
$table.trigger("sortStart", this);
|
874
899
|
// update header count index
|
875
|
-
updateHeaderSortCount(table, list
|
900
|
+
updateHeaderSortCount(table, list);
|
876
901
|
// set css for headers
|
877
902
|
setHeadersCss(table);
|
878
903
|
// fixes #346
|
@@ -921,6 +946,16 @@
|
|
921
946
|
.bind("destroy" + c.namespace, function(e, c, cb){
|
922
947
|
e.stopPropagation();
|
923
948
|
ts.destroy(table, c, cb);
|
949
|
+
})
|
950
|
+
.bind("resetToLoadState" + c.namespace, function(e){
|
951
|
+
// remove all widgets
|
952
|
+
ts.refreshWidgets(table, true, true);
|
953
|
+
// restore original settings; this clears out current settings, but does not clear
|
954
|
+
// values saved to storage.
|
955
|
+
c = $.extend(true, ts.defaults, c.originalSettings);
|
956
|
+
table.hasInitialized = false;
|
957
|
+
// setup the entire table again
|
958
|
+
ts.setup( table, c );
|
924
959
|
});
|
925
960
|
}
|
926
961
|
|
@@ -930,6 +965,8 @@
|
|
930
965
|
var table = this,
|
931
966
|
// merge & extend config options
|
932
967
|
c = $.extend(true, {}, ts.defaults, settings);
|
968
|
+
// save initial settings
|
969
|
+
c.originalSettings = settings;
|
933
970
|
// create a table from data (build table widget)
|
934
971
|
if (!table.hasInitialized && ts.buildTable && this.tagName !== 'TABLE') {
|
935
972
|
// return the table (in case the original target is the table's container)
|
@@ -973,6 +1010,7 @@
|
|
973
1010
|
c.$table = $table
|
974
1011
|
.addClass(ts.css.table + ' ' + c.tableClass + k)
|
975
1012
|
.attr({ role : 'grid'});
|
1013
|
+
c.$headers = $(table).find(c.selectorHeaders);
|
976
1014
|
|
977
1015
|
// give the table a unique id, which will be used in namespace binding
|
978
1016
|
if (!c.namespace) {
|
@@ -1050,6 +1088,31 @@
|
|
1050
1088
|
if (typeof c.initialized === 'function') { c.initialized(table); }
|
1051
1089
|
};
|
1052
1090
|
|
1091
|
+
ts.getColumnData = function(table, obj, indx, getCell){
|
1092
|
+
if (typeof obj === 'undefined' || obj === null) { return; }
|
1093
|
+
table = $(table)[0];
|
1094
|
+
var result, $h, k,
|
1095
|
+
c = table.config;
|
1096
|
+
if (obj[indx]) {
|
1097
|
+
return getCell ? obj[indx] : obj[c.$headers.index( c.$headers.filter('[data-column="' + indx + '"]:last') )];
|
1098
|
+
}
|
1099
|
+
for (k in obj) {
|
1100
|
+
if (typeof k === 'string') {
|
1101
|
+
if (getCell) {
|
1102
|
+
// get header cell
|
1103
|
+
$h = c.$headers.eq(indx).filter(k);
|
1104
|
+
} else {
|
1105
|
+
// get column indexed cell
|
1106
|
+
$h = c.$headers.filter('[data-column="' + indx + '"]:last').filter(k);
|
1107
|
+
}
|
1108
|
+
if ($h.length) {
|
1109
|
+
return obj[k];
|
1110
|
+
}
|
1111
|
+
}
|
1112
|
+
}
|
1113
|
+
return result;
|
1114
|
+
};
|
1115
|
+
|
1053
1116
|
// computeTableHeaderCellIndexes from:
|
1054
1117
|
// http://www.javascripttoolbox.com/lib/table/examples.php
|
1055
1118
|
// http://www.javascripttoolbox.com/temp/table_cellindex.html
|
@@ -1136,7 +1199,7 @@
|
|
1136
1199
|
};
|
1137
1200
|
|
1138
1201
|
ts.clearTableBody = function(table) {
|
1139
|
-
$(table)[0].config.$tbodies.
|
1202
|
+
$(table)[0].config.$tbodies.detach();
|
1140
1203
|
};
|
1141
1204
|
|
1142
1205
|
ts.bindEvents = function(table, $headers, core){
|
@@ -1217,7 +1280,7 @@
|
|
1217
1280
|
// disable tablesorter
|
1218
1281
|
$t
|
1219
1282
|
.removeData('tablesorter')
|
1220
|
-
.unbind('sortReset update updateAll updateRows updateCell addRows updateComplete sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave keypress sortBegin sortEnd '.split(' ').join(c.namespace + ' '));
|
1283
|
+
.unbind('sortReset update updateAll updateRows updateCell addRows updateComplete sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave keypress sortBegin sortEnd resetToLoadState '.split(' ').join(c.namespace + ' '));
|
1221
1284
|
c.$headers.add($f)
|
1222
1285
|
.removeClass( [ts.css.header, c.cssHeader, c.cssAsc, c.cssDesc, ts.css.sortAsc, ts.css.sortDesc, ts.css.sortNone].join(' ') )
|
1223
1286
|
.removeAttr('data-column')
|
@@ -1403,6 +1466,8 @@
|
|
1403
1466
|
};
|
1404
1467
|
|
1405
1468
|
ts.getParserById = function(name) {
|
1469
|
+
/*jshint eqeqeq:false */
|
1470
|
+
if (name == 'false') { return false; }
|
1406
1471
|
var i, l = ts.parsers.length;
|
1407
1472
|
for (i = 0; i < l; i++) {
|
1408
1473
|
if (ts.parsers[i].id.toLowerCase() === (name.toString()).toLowerCase()) {
|
@@ -1678,7 +1743,7 @@
|
|
1678
1743
|
if (s) {
|
1679
1744
|
var c = table.config,
|
1680
1745
|
ci = c.$headers.filter('[data-column=' + cellIndex + ']:last'),
|
1681
|
-
format = ci.length && ci[0].dateFormat || ts.getData( ci, c.headers
|
1746
|
+
format = ci.length && ci[0].dateFormat || ts.getData( ci, ts.getColumnData( table, c.headers, cellIndex ), 'dateFormat') || c.dateFormat;
|
1682
1747
|
s = s.replace(/\s+/g," ").replace(/[\-.,]/g, "/"); // escaped - because JSHint in Firefox was showing it as an error
|
1683
1748
|
if (format === "mmddyyyy") {
|
1684
1749
|
s = s.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$3/$1/$2");
|
@@ -1,4 +1,4 @@
|
|
1
|
-
/*! tableSorter 2.16+ widgets - updated
|
1
|
+
/*! tableSorter 2.16+ widgets - updated 5/22/2014 (v2.17.0)
|
2
2
|
*
|
3
3
|
* Column Styles
|
4
4
|
* Column Filters
|
@@ -438,16 +438,18 @@ ts.filter = {
|
|
438
438
|
query = ts.formatFloat( iFilter.replace(ts.filter.regex.operators, ''), table ),
|
439
439
|
parser = c.parsers[index],
|
440
440
|
savedSearch = query;
|
441
|
-
|
441
|
+
// parse filter value in case we're comparing numbers (dates)
|
442
442
|
if (parsed[index] || parser.type === 'numeric') {
|
443
|
-
|
444
|
-
query = ( typeof
|
443
|
+
result = parser.format( $.trim('' + iFilter.replace(ts.filter.regex.operators, '')), table, [], index );
|
444
|
+
query = ( typeof result === "number" && result !== '' && !isNaN(result) ) ? result : query;
|
445
445
|
}
|
446
|
+
|
446
447
|
// iExact may be numeric - see issue #149;
|
447
448
|
// check if cached is defined, because sometimes j goes out of range? (numeric columns)
|
448
|
-
cachedValue = ( parsed[index] || parser.type === 'numeric' ) && !isNaN(query) && cached ? cached :
|
449
|
+
cachedValue = ( parsed[index] || parser.type === 'numeric' ) && !isNaN(query) && typeof cached !== 'undefined' ? cached :
|
449
450
|
isNaN(iExact) ? ts.formatFloat( iExact.replace(ts.filter.regex.nondigit, ''), table) :
|
450
451
|
ts.formatFloat( iExact, table );
|
452
|
+
|
451
453
|
if ( />/.test(iFilter) ) { result = />=/.test(iFilter) ? cachedValue >= query : cachedValue > query; }
|
452
454
|
if ( /</.test(iFilter) ) { result = /<=/.test(iFilter) ? cachedValue <= query : cachedValue < query; }
|
453
455
|
// keep showing all rows if nothing follows the operator
|
@@ -476,8 +478,8 @@ ts.filter = {
|
|
476
478
|
},
|
477
479
|
// Look for an AND or && operator (logical and)
|
478
480
|
and : function( filter, iFilter, exact, iExact ) {
|
479
|
-
if (
|
480
|
-
var query = iFilter.split(
|
481
|
+
if ( ts.filter.regex.andTest.test(filter) ) {
|
482
|
+
var query = iFilter.split( ts.filter.regex.andSplit ),
|
481
483
|
result = iExact.search( $.trim(query[0]) ) >= 0,
|
482
484
|
indx = query.length - 1;
|
483
485
|
while (result && indx) {
|
@@ -490,10 +492,11 @@ ts.filter = {
|
|
490
492
|
},
|
491
493
|
// Look for a range (using " to " or " - ") - see issue #166; thanks matzhu!
|
492
494
|
range : function( filter, iFilter, exact, iExact, cached, index, table, wo, parsed ) {
|
493
|
-
if (
|
495
|
+
if ( ts.filter.regex.toTest.test(iFilter) ) {
|
494
496
|
var result, tmp,
|
495
497
|
c = table.config,
|
496
|
-
|
498
|
+
// make sure the dash is for a range and not indicating a negative number
|
499
|
+
query = iFilter.split( ts.filter.regex.toSplit ),
|
497
500
|
range1 = ts.formatFloat(query[0].replace(ts.filter.regex.nondigit, ''), table),
|
498
501
|
range2 = ts.formatFloat(query[1].replace(ts.filter.regex.nondigit, ''), table);
|
499
502
|
// parse filter value in case we're comparing numbers (dates)
|
@@ -513,9 +516,9 @@ ts.filter = {
|
|
513
516
|
},
|
514
517
|
// Look for wild card: ? = single, * = multiple, or | = logical OR
|
515
518
|
wild : function( filter, iFilter, exact, iExact, cached, index, table, wo, parsed, rowArray ) {
|
516
|
-
if ( /[\?|\*]/.test(iFilter) ||
|
519
|
+
if ( /[\?|\*]/.test(iFilter) || ts.filter.regex.orReplace.test(filter) ) {
|
517
520
|
var c = table.config,
|
518
|
-
query = iFilter.replace(
|
521
|
+
query = iFilter.replace(ts.filter.regex.orReplace, "|");
|
519
522
|
// look for an exact match with the "or" unless the "filter-match" class is found
|
520
523
|
if (!c.$headers.filter('[data-column="' + index + '"]:last').hasClass('filter-match') && /\|/.test(query)) {
|
521
524
|
query = $.isArray(rowArray) ? '(' + query + ')' : '^(' + query + ')$';
|
@@ -545,14 +548,30 @@ ts.filter = {
|
|
545
548
|
}
|
546
549
|
},
|
547
550
|
init: function(table, c, wo) {
|
548
|
-
|
551
|
+
// filter language options
|
552
|
+
ts.language = $.extend(true, {}, {
|
553
|
+
to : 'to',
|
554
|
+
or : 'or',
|
555
|
+
and : 'and'
|
556
|
+
}, ts.language);
|
557
|
+
|
558
|
+
var options, string, $header, column, filters, time, fxn,
|
559
|
+
regex = ts.filter.regex;
|
549
560
|
if (c.debug) {
|
550
561
|
time = new Date();
|
551
562
|
}
|
552
563
|
c.$table.addClass('hasFilters');
|
553
564
|
|
554
|
-
|
555
|
-
|
565
|
+
$.extend( regex, {
|
566
|
+
child : new RegExp(c.cssChildRow),
|
567
|
+
filtered : new RegExp(wo.filter_filteredRow),
|
568
|
+
alreadyFiltered : new RegExp('(\\s+(' + ts.language.or + '|-|' + ts.language.to + ')\\s+)', 'i'),
|
569
|
+
toTest : new RegExp('\\s+(-|' + ts.language.to + ')\\s+', 'i'),
|
570
|
+
toSplit : new RegExp('(?:\\s+(?:-|' + ts.language.to + ')\\s+)' ,'gi'),
|
571
|
+
andTest : new RegExp('\\s+(' + ts.language.and + '|&&)\\s+', 'i'),
|
572
|
+
andSplit : new RegExp('(?:\\s+(?:' + ts.language.and + '|&&)\\s+)', 'gi'),
|
573
|
+
orReplace : new RegExp('\\s+(' + ts.language.or + ')\\s+', 'gi')
|
574
|
+
});
|
556
575
|
|
557
576
|
// don't build filter row if columnFilters is false or all columns are set to "filter-false" - issue #156
|
558
577
|
if (wo.filter_columnFilters !== false && c.$headers.filter('.filter-false').length !== c.$headers.length) {
|
@@ -576,6 +595,7 @@ ts.filter = {
|
|
576
595
|
if (/(update|add)/.test(event.type) && event.type !== "updateComplete") {
|
577
596
|
// force a new search since content has changed
|
578
597
|
c.lastCombinedFilter = null;
|
598
|
+
c.lastSearch = [];
|
579
599
|
}
|
580
600
|
// pass true (skipFirst) to prevent the tablesorter.setFilters function from skipping the first input
|
581
601
|
// ensures all inputs are updated when a search is triggered on the table $('table').trigger('search', [...]);
|
@@ -602,16 +622,16 @@ ts.filter = {
|
|
602
622
|
}
|
603
623
|
}
|
604
624
|
if (wo.filter_functions) {
|
605
|
-
|
606
|
-
|
607
|
-
if (
|
625
|
+
for (column = 0; column < c.columns; column++) {
|
626
|
+
fxn = ts.getColumnData( table, wo.filter_functions, column );
|
627
|
+
if (fxn) {
|
608
628
|
$header = c.$headers.filter('[data-column="' + column + '"]:last');
|
609
629
|
options = '';
|
610
|
-
if (
|
630
|
+
if (fxn === true && !$header.hasClass('filter-false')) {
|
611
631
|
ts.filter.buildSelect(table, column);
|
612
|
-
} else if (typeof
|
632
|
+
} else if (typeof fxn === 'object' && !$header.hasClass('filter-false')) {
|
613
633
|
// add custom drop down list
|
614
|
-
for (string in
|
634
|
+
for (string in fxn) {
|
615
635
|
if (typeof string === 'string') {
|
616
636
|
options += options === '' ?
|
617
637
|
'<option value="">' + ($header.data('placeholder') || $header.attr('data-placeholder') || wo.filter_placeholder.select || '') + '</option>' : '';
|
@@ -683,7 +703,7 @@ ts.filter = {
|
|
683
703
|
return filters;
|
684
704
|
},
|
685
705
|
buildRow: function(table, c, wo) {
|
686
|
-
var column, $header, buildSelect, disabled, name,
|
706
|
+
var column, $header, buildSelect, disabled, name, ffxn,
|
687
707
|
// c.columns defined in computeThIndexes()
|
688
708
|
columns = c.columns,
|
689
709
|
buildFilter = '<tr class="' + ts.css.filterRow + '">';
|
@@ -696,22 +716,18 @@ ts.filter = {
|
|
696
716
|
disabled = false;
|
697
717
|
// assuming last cell of a column is the main column
|
698
718
|
$header = c.$headers.filter('[data-column="' + column + '"]:last');
|
699
|
-
|
719
|
+
ffxn = ts.getColumnData( table, wo.filter_functions, column );
|
720
|
+
buildSelect = (wo.filter_functions && ffxn && typeof ffxn !== "function" ) ||
|
700
721
|
$header.hasClass('filter-select');
|
701
722
|
// get data from jQuery data, metadata, headers option or header class name
|
702
|
-
|
703
|
-
|
704
|
-
disabled = ts.getData($header[0], c.headers[column], 'filter') === 'false';
|
705
|
-
} else {
|
706
|
-
// only class names and header options - keep this for compatibility with tablesorter v2.0.5
|
707
|
-
disabled = (c.headers[column] && c.headers[column].hasOwnProperty('filter') && c.headers[column].filter === false) ||
|
708
|
-
$header.hasClass('filter-false');
|
709
|
-
}
|
723
|
+
disabled = ts.getData($header[0], ts.getColumnData( table, c.headers, column ), 'filter') === 'false';
|
724
|
+
|
710
725
|
if (buildSelect) {
|
711
726
|
buildFilter = $('<select>').appendTo( c.$filters.eq(column) );
|
712
727
|
} else {
|
713
|
-
|
714
|
-
|
728
|
+
ffxn = ts.getColumnData( table, wo.filter_formatter, column );
|
729
|
+
if (ffxn) {
|
730
|
+
buildFilter = ffxn( c.$filters.eq(column), column );
|
715
731
|
// no element returned, so lets go find it
|
716
732
|
if (buildFilter && buildFilter.length === 0) {
|
717
733
|
buildFilter = c.$filters.eq(column).children('input');
|
@@ -761,7 +777,7 @@ ts.filter = {
|
|
761
777
|
$el
|
762
778
|
// use data attribute instead of jQuery data since the head is cloned without including the data/binding
|
763
779
|
.attr('data-lastSearchTime', new Date().getTime())
|
764
|
-
.unbind('keyup search change '.split(' ').join(c.namespace + 'filter '))
|
780
|
+
.unbind('keypress keyup search change '.split(' ').join(c.namespace + 'filter '))
|
765
781
|
// include change for select - fixes #473
|
766
782
|
.bind('keyup search change '.split(' ').join(c.namespace + 'filter '), function(event) {
|
767
783
|
$(this).attr('data-lastSearchTime', new Date().getTime());
|
@@ -774,8 +790,14 @@ ts.filter = {
|
|
774
790
|
( event.which >= 37 && event.which <= 40 ) || (event.which !== 13 && wo.filter_liveSearch === false) ) ) ) {
|
775
791
|
return;
|
776
792
|
}
|
777
|
-
// true flag tells getFilters to skip newest timed input
|
778
|
-
ts.filter.searching( table,
|
793
|
+
// change event = no delay; last true flag tells getFilters to skip newest timed input
|
794
|
+
ts.filter.searching( table, event.type !== 'change', true );
|
795
|
+
})
|
796
|
+
.bind('keypress.' + c.namespace + 'filter', function(event){
|
797
|
+
if (event.which === 13) {
|
798
|
+
event.preventDefault();
|
799
|
+
$(this).blur();
|
800
|
+
}
|
779
801
|
});
|
780
802
|
c.$table.bind('filterReset', function(){
|
781
803
|
$el.val('');
|
@@ -787,6 +809,8 @@ ts.filter = {
|
|
787
809
|
filterArray = $.isArray(filter),
|
788
810
|
filters = (filterArray) ? filter : ts.getFilters(table, true),
|
789
811
|
combinedFilters = (filters || []).join(''); // combined filter values
|
812
|
+
// prevent errors if delay init is set
|
813
|
+
if ($.isEmptyObject(c.cache)) { return; }
|
790
814
|
// add filter array back into inputs
|
791
815
|
if (filterArray) {
|
792
816
|
ts.setFilters( table, filters, false, skipFirst !== true );
|
@@ -802,6 +826,7 @@ ts.filter = {
|
|
802
826
|
} else if (filter === false) {
|
803
827
|
// force filter refresh
|
804
828
|
c.lastCombinedFilter = null;
|
829
|
+
c.lastSearch = [];
|
805
830
|
}
|
806
831
|
c.$table.trigger('filterStart', [filters]);
|
807
832
|
if (c.showProcessing) {
|
@@ -856,8 +881,9 @@ ts.filter = {
|
|
856
881
|
if (table.config.lastCombinedFilter === combinedFilters) { return; }
|
857
882
|
var cached, len, $rows, rowIndex, tbodyIndex, $tbody, $cells, columnIndex,
|
858
883
|
childRow, childRowText, exact, iExact, iFilter, lastSearch, matches, result,
|
859
|
-
notFiltered, searchFiltered, filterMatched, showRow, time,
|
860
|
-
anyMatch, iAnyMatch, rowArray, rowText, iRowText, rowCache,
|
884
|
+
notFiltered, searchFiltered, filterMatched, showRow, time, val, indx,
|
885
|
+
anyMatch, iAnyMatch, rowArray, rowText, iRowText, rowCache, fxn,
|
886
|
+
regex = ts.filter.regex,
|
861
887
|
c = table.config,
|
862
888
|
wo = c.widgetOptions,
|
863
889
|
columns = c.columns,
|
@@ -868,7 +894,7 @@ ts.filter = {
|
|
868
894
|
parsed = c.$headers.map(function(columnIndex) {
|
869
895
|
return c.parsers && c.parsers[columnIndex] && c.parsers[columnIndex].parsed ||
|
870
896
|
// getData won't return "parsed" if other "filter-" class names exist (e.g. <th class="filter-select filter-parsed">)
|
871
|
-
ts.getData && ts.getData(c.$headers.filter('[data-column="' + columnIndex + '"]:last'), c.headers
|
897
|
+
ts.getData && ts.getData(c.$headers.filter('[data-column="' + columnIndex + '"]:last'), ts.getColumnData( table, c.headers, columnIndex ), 'filter') === 'parsed' ||
|
872
898
|
$(this).hasClass('filter-parsed');
|
873
899
|
}).get();
|
874
900
|
if (c.debug) { time = new Date(); }
|
@@ -879,26 +905,34 @@ ts.filter = {
|
|
879
905
|
// $rows = $tbody.children('tr').not(c.selectorRemove);
|
880
906
|
columnIndex = c.columns;
|
881
907
|
// convert stored rows into a jQuery object
|
882
|
-
$rows =
|
883
|
-
|
908
|
+
$rows = $( $.map(c.cache[tbodyIndex].normalized, function(el){ return el[columnIndex].$row.get(); }) );
|
909
|
+
|
884
910
|
if (combinedFilters === '' || wo.filter_serversideFiltering) {
|
885
911
|
$rows.removeClass(wo.filter_filteredRow).not('.' + c.cssChildRow).show();
|
886
912
|
} else {
|
913
|
+
// filter out child rows
|
914
|
+
$rows = $rows.not('.' + c.cssChildRow);
|
915
|
+
len = $rows.length;
|
887
916
|
// optimize searching only through already filtered rows - see #313
|
888
917
|
searchFiltered = true;
|
889
918
|
lastSearch = c.lastSearch || c.$table.data('lastSearch') || [];
|
890
|
-
|
919
|
+
for (indx = 0; indx < columnIndex; indx++) {
|
920
|
+
val = filters[indx] || '';
|
921
|
+
// break out of loop if we've already determined not to search filtered rows
|
922
|
+
if (!searchFiltered) { indx = columnIndex; }
|
891
923
|
// search already filtered rows if...
|
892
|
-
searchFiltered = searchFiltered &&
|
893
|
-
// there are changes from beginning of filter
|
894
|
-
|
895
|
-
// if there is
|
896
|
-
|
897
|
-
// if we are not doing exact matches
|
898
|
-
!/[=\"]/.test(
|
924
|
+
searchFiltered = searchFiltered && lastSearch.length &&
|
925
|
+
// there are no changes from beginning of filter
|
926
|
+
val.indexOf(lastSearch[indx] || '') === 0 &&
|
927
|
+
// if there is NOT a logical "or", or range ("to" or "-") in the string
|
928
|
+
!regex.alreadyFiltered.test(val) &&
|
929
|
+
// if we are not doing exact matches, using "|" (logical or) or not "!"
|
930
|
+
!/[=\"\|!]/.test(val) &&
|
931
|
+
// don't search only filtered if the value is negative ('> -10' => '> -100' will ignore hidden rows)
|
932
|
+
!(/(>=?\s*-\d)/.test(val) || /(<=?\s*\d)/.test(val)) &&
|
899
933
|
// if filtering using a select without a "filter-match" class (exact match) - fixes #593
|
900
|
-
!( val !== '' &&
|
901
|
-
}
|
934
|
+
!( val !== '' && c.$filters && c.$filters.eq(indx).find('select').length && !c.$headers.filter('[data-column="' + indx + '"]:last').hasClass('filter-match') );
|
935
|
+
}
|
902
936
|
notFiltered = $rows.not('.' + wo.filter_filteredRow).length;
|
903
937
|
// can't search when all rows are hidden - this happens when looking for exact matches
|
904
938
|
if (searchFiltered && notFiltered === 0) { searchFiltered = false; }
|
@@ -917,7 +951,7 @@ ts.filter = {
|
|
917
951
|
for (rowIndex = 0; rowIndex < len; rowIndex++) {
|
918
952
|
childRow = $rows[rowIndex].className;
|
919
953
|
// skip child rows & already filtered rows
|
920
|
-
if (
|
954
|
+
if ( regex.child.test(childRow) || (searchFiltered && regex.filtered.test(childRow)) ) { continue; }
|
921
955
|
showRow = true;
|
922
956
|
// *** nextAll/nextUntil not supported by Zepto! ***
|
923
957
|
childRow = $rows.eq(rowIndex).nextUntil('tr:not(.' + c.cssChildRow + ')');
|
@@ -973,24 +1007,25 @@ ts.filter = {
|
|
973
1007
|
exact = $.trim($cells.eq(columnIndex).text());
|
974
1008
|
exact = c.sortLocaleCompare ? ts.replaceAccents(exact) : exact; // issue #405
|
975
1009
|
}
|
976
|
-
iExact = !
|
1010
|
+
iExact = !regex.type.test(typeof exact) && wo.filter_ignoreCase ? exact.toLocaleLowerCase() : exact;
|
977
1011
|
result = showRow; // if showRow is true, show that row
|
978
1012
|
|
979
1013
|
// replace accents - see #357
|
980
1014
|
filters[columnIndex] = c.sortLocaleCompare ? ts.replaceAccents(filters[columnIndex]) : filters[columnIndex];
|
981
1015
|
// val = case insensitive, filters[columnIndex] = case sensitive
|
982
1016
|
iFilter = wo.filter_ignoreCase ? (filters[columnIndex] || '').toLocaleLowerCase() : filters[columnIndex];
|
983
|
-
|
984
|
-
|
1017
|
+
fxn = ts.getColumnData( table, wo.filter_functions, columnIndex );
|
1018
|
+
if (fxn) {
|
1019
|
+
if (fxn === true) {
|
985
1020
|
// default selector; no "filter-select" class
|
986
1021
|
result = (c.$headers.filter('[data-column="' + columnIndex + '"]:last').hasClass('filter-match')) ?
|
987
1022
|
iExact.search(iFilter) >= 0 : filters[columnIndex] === exact;
|
988
|
-
} else if (typeof
|
1023
|
+
} else if (typeof fxn === 'function') {
|
989
1024
|
// filter callback( exact cell content, parser normalized content, filter input value, column index, jQuery row object )
|
990
|
-
result =
|
991
|
-
} else if (typeof
|
1025
|
+
result = fxn(exact, cached, filters[columnIndex], columnIndex, $rows.eq(rowIndex));
|
1026
|
+
} else if (typeof fxn[filters[columnIndex]] === 'function') {
|
992
1027
|
// selector option function
|
993
|
-
result =
|
1028
|
+
result = fxn[filters[columnIndex]](exact, cached, filters[columnIndex], columnIndex, $rows.eq(rowIndex));
|
994
1029
|
}
|
995
1030
|
} else {
|
996
1031
|
filterMatched = null;
|
@@ -1044,15 +1079,16 @@ ts.filter = {
|
|
1044
1079
|
wo = c.widgetOptions,
|
1045
1080
|
parsed = [],
|
1046
1081
|
arry = false,
|
1047
|
-
source = wo.filter_selectSource
|
1082
|
+
source = wo.filter_selectSource,
|
1083
|
+
fxn = $.isFunction(source) ? true : ts.getColumnData( table, source, column );
|
1048
1084
|
|
1049
1085
|
// filter select source option
|
1050
|
-
if (
|
1086
|
+
if (fxn === true) {
|
1051
1087
|
// OVERALL source
|
1052
1088
|
arry = source(table, column, onlyAvail);
|
1053
|
-
} else if ($.type(source) === 'object' &&
|
1089
|
+
} else if ($.type(source) === 'object' && fxn) {
|
1054
1090
|
// custom select source function for a SPECIFIC COLUMN
|
1055
|
-
arry =
|
1091
|
+
arry = fxn(table, column, onlyAvail);
|
1056
1092
|
}
|
1057
1093
|
if (arry === false) {
|
1058
1094
|
// fall back to original method
|
@@ -1159,6 +1195,8 @@ ts.filter = {
|
|
1159
1195
|
$filters = $filters && $filters.length ? $filters.add(wo.filter_$externalFilters) : wo.filter_$externalFilters;
|
1160
1196
|
}
|
1161
1197
|
$filters.filter('select[data-column="' + column + '"]')[ updating ? 'html' : 'append' ](options);
|
1198
|
+
if (!wo.filter_functions) { wo.filter_functions = {}; }
|
1199
|
+
wo.filter_functions[column] = true;
|
1162
1200
|
},
|
1163
1201
|
buildDefault: function(table, updating) {
|
1164
1202
|
var columnIndex, $header,
|
@@ -1169,10 +1207,7 @@ ts.filter = {
|
|
1169
1207
|
for (columnIndex = 0; columnIndex < columns; columnIndex++) {
|
1170
1208
|
$header = c.$headers.filter('[data-column="' + columnIndex + '"]:last');
|
1171
1209
|
// look for the filter-select class; build/update it if found
|
1172
|
-
if (($header.hasClass('filter-select') ||
|
1173
|
-
!$header.hasClass('filter-false')) {
|
1174
|
-
if (!wo.filter_functions) { wo.filter_functions = {}; }
|
1175
|
-
wo.filter_functions[columnIndex] = true; // make sure this select gets processed by filter_functions
|
1210
|
+
if (($header.hasClass('filter-select') || ts.getColumnData( table, wo.filter_functions, columnIndex ) === true) && !$header.hasClass('filter-false')) {
|
1176
1211
|
ts.filter.buildSelect(table, columnIndex, updating, $header.hasClass(wo.filter_onlyAvail));
|
1177
1212
|
}
|
1178
1213
|
}
|
@@ -1244,6 +1279,7 @@ ts.setFilters = function(table, filter, apply, skipFirst) {
|
|
1244
1279
|
if (c && apply) {
|
1245
1280
|
// ensure new set filters are applied, even if the search is the same
|
1246
1281
|
c.lastCombinedFilter = null;
|
1282
|
+
c.lastSearch = [];
|
1247
1283
|
ts.filter.searching(c.$table[0], filter, skipFirst);
|
1248
1284
|
c.$table.trigger('filterFomatterUpdate');
|
1249
1285
|
}
|
@@ -1475,7 +1511,7 @@ ts.addWidget({
|
|
1475
1511
|
var canResize,
|
1476
1512
|
$column = $(this);
|
1477
1513
|
column = $column.attr('data-column');
|
1478
|
-
canResize = ts.getData( $column, c.headers
|
1514
|
+
canResize = ts.getData( $column, ts.getColumnData( table, c.headers, column ), 'resizable') === "false";
|
1479
1515
|
$rows.children().filter('[data-column="' + column + '"]')[canResize ? 'addClass' : 'removeClass']('resizable-false');
|
1480
1516
|
});
|
1481
1517
|
// add wrapper inside each cell to allow for positioning of the resizable target block
|