jquery-tablesorter 1.8.0 → 1.8.1
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.markdown +1 -1
- data/lib/jquery-tablesorter/version.rb +1 -1
- data/vendor/assets/javascripts/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.js +71 -40
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.js +24 -17
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets-filter-formatter.js +7 -8
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets.js +613 -448
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.bootstrap.css +3 -1
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.dark.css +1 -1
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.jui.css +2 -2
- 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: e6f685058fd350d114a2f272290ad8a7e5c3f7ed
|
4
|
+
data.tar.gz: e9de584dc9a659b30b9bd79dec2a863cadf04749
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49d6f67cce6923d1ac1fb24d651673dc3162608e41dfb70349fb3ec37c61b815f5cd4462887d2f891cdf1a05a90603d09bd4d45289f6e605270590f2cb744958
|
7
|
+
data.tar.gz: d8c7d5b3890bea49ed049a17600ef2695a205450e432fac80d72b1835e69eb3c8edb7fddfd4517bef9d47207107186696c1fdee1b95992a10562871d357d21a2
|
data/README.markdown
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.13.
|
7
|
+
Current tablesorter version: 2.13.3 (11/9/2013), [documentation]
|
8
8
|
|
9
9
|
Any issue associate with the js/css files, please report to [Mottie's fork].
|
10
10
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*!
|
2
2
|
* tablesorter pager plugin
|
3
|
-
* updated
|
3
|
+
* updated 11/9/2013
|
4
4
|
*/
|
5
5
|
/*jshint browser:true, jquery:true, unused:false */
|
6
6
|
;(function($) {
|
@@ -236,6 +236,9 @@
|
|
236
236
|
$t.find('thead tr.' + p.cssErrorRow).remove(); // Clean up any previous error.
|
237
237
|
|
238
238
|
if ( exception ) {
|
239
|
+
if (c.debug) {
|
240
|
+
ts.log('Ajax Error', xhr, exception);
|
241
|
+
}
|
239
242
|
$err = $('<tr class="' + p.cssErrorRow + '"><td style="text-align:center;" colspan="' + hl + '">' + (
|
240
243
|
xhr.status === 0 ? 'Not connected, verify Network' :
|
241
244
|
xhr.status === 404 ? 'Requested page not found [404]' :
|
@@ -272,15 +275,13 @@
|
|
272
275
|
c.$tbodies.eq(0).empty().append(d);
|
273
276
|
} else if (l) {
|
274
277
|
// build table from array
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
tds += '<td>' + d[i][j] + '</td>';
|
281
|
-
}
|
282
|
-
tds += '</tr>';
|
278
|
+
for ( i = 0; i < l; i++ ) {
|
279
|
+
tds += '<tr>';
|
280
|
+
for ( j = 0; j < d[i].length; j++ ) {
|
281
|
+
// build tbody cells
|
282
|
+
tds += '<td>' + d[i][j] + '</td>';
|
283
283
|
}
|
284
|
+
tds += '</tr>';
|
284
285
|
}
|
285
286
|
// add rows to first tbody
|
286
287
|
c.$tbodies.eq(0).html( tds );
|
@@ -314,9 +315,15 @@
|
|
314
315
|
if (c.showProcessing) {
|
315
316
|
ts.isProcessing(table); // remove loading icon
|
316
317
|
}
|
317
|
-
|
318
|
+
// make sure last pager settings are saved, prevents multiple server side calls with
|
319
|
+
// the same parameters
|
320
|
+
p.last.totalPages = p.totalPages = Math.ceil( p.totalRows / ( p.size || 10 ) );
|
321
|
+
p.last.currentFilters = p.currentFilters;
|
322
|
+
p.last.sortList = (c.sortList || []).join(',');
|
318
323
|
updatePageDisplay(table, p);
|
319
324
|
fixHeight(table, p);
|
325
|
+
// apply widgets after table has rendered
|
326
|
+
$t.trigger('applyWidgets');
|
320
327
|
if (p.initialized) {
|
321
328
|
$t.trigger('pagerChange', p);
|
322
329
|
$t.trigger('updateComplete');
|
@@ -350,17 +357,21 @@
|
|
350
357
|
p.oldAjaxSuccess(data);
|
351
358
|
}
|
352
359
|
};
|
360
|
+
if (c.debug) {
|
361
|
+
ts.log('ajax initialized', p.ajaxObject);
|
362
|
+
}
|
353
363
|
$.ajax(p.ajaxObject);
|
354
364
|
}
|
355
365
|
},
|
356
366
|
|
357
367
|
getAjaxUrl = function(table, p) {
|
358
|
-
var
|
368
|
+
var c = table.config,
|
369
|
+
url = (p.ajaxUrl) ? p.ajaxUrl
|
359
370
|
// allow using "{page+1}" in the url string to switch to a non-zero based index
|
360
371
|
.replace(/\{page([\-+]\d+)?\}/, function(s,n){ return p.page + (n ? parseInt(n, 10) : 0); })
|
361
372
|
.replace(/\{size\}/g, p.size) : '',
|
362
|
-
sl =
|
363
|
-
fl = p.currentFilters || [],
|
373
|
+
sl = c.sortList,
|
374
|
+
fl = p.currentFilters || $(table).data('lastSearch') || [],
|
364
375
|
sortCol = url.match(/\{\s*sort(?:List)?\s*:\s*(\w*)\s*\}/),
|
365
376
|
filterCol = url.match(/\{\s*filter(?:List)?\s*:\s*(\w*)\s*\}/),
|
366
377
|
arry = [];
|
@@ -382,10 +393,14 @@
|
|
382
393
|
});
|
383
394
|
// if the arry is empty, just add the fcol parameter... "&{filterList:fcol}" becomes "&fcol"
|
384
395
|
url = url.replace(/\{\s*filter(?:List)?\s*:\s*(\w*)\s*\}/g, arry.length ? arry.join('&') : filterCol );
|
396
|
+
p.currentFilters = fl;
|
385
397
|
}
|
386
398
|
if ( typeof(p.customAjaxUrl) === "function" ) {
|
387
399
|
url = p.customAjaxUrl(table, url);
|
388
400
|
}
|
401
|
+
if (c.debug) {
|
402
|
+
ts.log('Pager ajax url: ' + url);
|
403
|
+
}
|
389
404
|
return url;
|
390
405
|
},
|
391
406
|
|
@@ -433,6 +448,9 @@
|
|
433
448
|
p.totalPages = 1;
|
434
449
|
$(table).addClass('pagerDisabled').find('tr.pagerSavedHeightSpacer').remove();
|
435
450
|
renderTable(table, table.config.rowsCopy, p);
|
451
|
+
if (table.config.debug) {
|
452
|
+
ts.log('pager disabled');
|
453
|
+
}
|
436
454
|
}
|
437
455
|
// disable size selector
|
438
456
|
p.$size.add(p.$goto).each(function(){
|
@@ -442,17 +460,25 @@
|
|
442
460
|
|
443
461
|
moveToPage = function(table, p, flag) {
|
444
462
|
if ( p.isDisabled ) { return; }
|
445
|
-
var
|
463
|
+
var c = table.config,
|
464
|
+
l = p.last,
|
446
465
|
pg = Math.min( p.totalPages, p.filteredPages );
|
447
466
|
if ( p.page < 0 ) { p.page = 0; }
|
448
467
|
if ( p.page > ( pg - 1 ) && pg !== 0 ) { p.page = pg - 1; }
|
449
|
-
// don't allow rendering multiple times on the same page/size/totalpages/filters
|
450
|
-
if (l.page === p.page && l.size === p.size && l.
|
468
|
+
// don't allow rendering multiple times on the same page/size/totalpages/filters/sorts
|
469
|
+
if ( l.page === p.page && l.size === p.size && l.totalPages === p.totalPages &&
|
470
|
+
(l.currentFilters || []).join(',') === (p.currentFilters || []).join(',') &&
|
471
|
+
l.sortList === (c.sortList || []).join(',') ) { return; }
|
472
|
+
if (c.debug) {
|
473
|
+
ts.log('Pager changing to page ' + p.page);
|
474
|
+
}
|
451
475
|
p.last = {
|
452
476
|
page : p.page,
|
453
477
|
size : p.size,
|
478
|
+
// fixes #408; modify sortList otherwise it auto-updates
|
479
|
+
sortList : (c.sortList || []).join(','),
|
454
480
|
totalPages : p.totalPages,
|
455
|
-
currentFilters : p.currentFilters
|
481
|
+
currentFilters : p.currentFilters || []
|
456
482
|
};
|
457
483
|
if (p.ajax) {
|
458
484
|
getAjax(table, p);
|
@@ -460,18 +486,18 @@
|
|
460
486
|
renderTable(table, table.config.rowsCopy, p);
|
461
487
|
}
|
462
488
|
$.data(table, 'pagerLastPage', p.page);
|
463
|
-
$.data(table, 'pagerUpdateTriggered', true);
|
464
489
|
if (p.initialized && flag !== false) {
|
465
|
-
|
490
|
+
c.$table.trigger('pageMoved', p);
|
491
|
+
c.$table.trigger('applyWidgets');
|
466
492
|
}
|
467
493
|
},
|
468
494
|
|
469
495
|
setPageSize = function(table, size, p) {
|
470
|
-
p.size = size;
|
471
|
-
p.$size.val(size);
|
496
|
+
p.size = size || p.size || 10;
|
497
|
+
p.$size.val(p.size);
|
472
498
|
$.data(table, 'pagerLastPage', p.page);
|
473
499
|
$.data(table, 'pagerLastSize', p.size);
|
474
|
-
p.totalPages = Math.ceil( p.totalRows /
|
500
|
+
p.totalPages = Math.ceil( p.totalRows / p.size );
|
475
501
|
moveToPage(table, p);
|
476
502
|
},
|
477
503
|
|
@@ -517,14 +543,17 @@
|
|
517
543
|
p.$goto.removeClass(p.cssDisabled).removeAttr('disabled');
|
518
544
|
p.isDisabled = false;
|
519
545
|
p.page = $.data(table, 'pagerLastPage') || p.page || 0;
|
520
|
-
p.size = $.data(table, 'pagerLastSize') || parseInt(pg.find('option[selected]').val(), 10) || p.size;
|
546
|
+
p.size = $.data(table, 'pagerLastSize') || parseInt(pg.find('option[selected]').val(), 10) || p.size || 10;
|
521
547
|
pg.val(p.size); // set page size
|
522
|
-
p.totalPages = Math.ceil( Math.min( p.totalPages, p.filteredPages ) /
|
548
|
+
p.totalPages = Math.ceil( Math.min( p.totalPages, p.filteredPages ) / p.size );
|
523
549
|
if ( triggered ) {
|
524
550
|
$(table).trigger('update');
|
525
551
|
setPageSize(table, p.size, p);
|
526
552
|
hideRowsSetup(table, p);
|
527
553
|
fixHeight(table, p);
|
554
|
+
if (table.config.debug) {
|
555
|
+
ts.log('pager enabled');
|
556
|
+
}
|
528
557
|
}
|
529
558
|
};
|
530
559
|
|
@@ -534,8 +563,8 @@
|
|
534
563
|
if ( !p.ajax ) {
|
535
564
|
c.rowsCopy = rows;
|
536
565
|
p.totalRows = p.countChildRows ? c.$tbodies.eq(0).children().length : rows.length;
|
537
|
-
p.size = $.data(table, 'pagerLastSize') || p.size;
|
538
|
-
p.totalPages = Math.ceil( p.totalRows /
|
566
|
+
p.size = $.data(table, 'pagerLastSize') || p.size || 10;
|
567
|
+
p.totalPages = Math.ceil( p.totalRows / p.size );
|
539
568
|
renderTable(table, rows, p);
|
540
569
|
}
|
541
570
|
};
|
@@ -551,34 +580,36 @@
|
|
551
580
|
$t = c.$table,
|
552
581
|
// added in case the pager is reinitialized after being destroyed.
|
553
582
|
pager = p.$container = $(p.container).addClass('tablesorter-pager').show();
|
583
|
+
if (c.debug) {
|
584
|
+
ts.log('Pager initializing');
|
585
|
+
}
|
554
586
|
p.oldAjaxSuccess = p.oldAjaxSuccess || p.ajaxObject.success;
|
555
587
|
c.appender = $this.appender;
|
556
|
-
|
588
|
+
if (ts.filter && c.widgets.indexOf('filter') >= 0) {
|
589
|
+
// get any default filter settings (data-value attribute) fixes #388
|
590
|
+
p.currentFilters = c.$table.data('lastSearch') || ts.filter.setDefaults(table, c, c.widgetOptions) || [];
|
591
|
+
// set, but don't apply current filters
|
592
|
+
ts.setFilters(table, p.currentFilters, false);
|
593
|
+
}
|
557
594
|
if (p.savePages && ts.storage) {
|
558
595
|
t = ts.storage(table, 'tablesorter-pager') || {}; // fixes #387
|
559
596
|
p.page = isNaN(t.page) ? p.page : t.page;
|
560
597
|
p.size = ( isNaN(t.size) ? p.size : t.size ) || 10;
|
598
|
+
$.data(table, 'pagerLastSize', p.size);
|
561
599
|
}
|
562
600
|
|
563
601
|
$t
|
564
|
-
.unbind('filterStart
|
602
|
+
.unbind('filterStart filterEnd sortEnd disable enable destroy update pageSize '.split(' ').join('.pager '))
|
565
603
|
.bind('filterStart.pager', function(e, filters) {
|
566
|
-
$.data(table, 'pagerUpdateTriggered', false);
|
567
604
|
p.currentFilters = filters;
|
568
605
|
})
|
569
606
|
// update pager after filter widget completes
|
570
|
-
.bind('filterEnd.pager sortEnd.pager', function(
|
571
|
-
|
572
|
-
if ($.data(table, 'pagerUpdateTriggered')) {
|
573
|
-
$.data(table, 'pagerUpdateTriggered', false);
|
574
|
-
return;
|
575
|
-
}
|
576
|
-
//only run the server side sorting if it has been enabled
|
577
|
-
if (e.type === "filterEnd" || (e.type === "sortEnd" && c.serverSideSorting)) {
|
607
|
+
.bind('filterEnd.pager sortEnd.pager', function() {
|
608
|
+
if (p.initialized) {
|
578
609
|
moveToPage(table, p, false);
|
610
|
+
updatePageDisplay(table, p, false);
|
611
|
+
fixHeight(table, p);
|
579
612
|
}
|
580
|
-
updatePageDisplay(table, p, false);
|
581
|
-
fixHeight(table, p);
|
582
613
|
})
|
583
614
|
.bind('disable.pager', function(e){
|
584
615
|
e.stopPropagation();
|
@@ -617,6 +648,7 @@
|
|
617
648
|
pager.find(ctrls.join(','))
|
618
649
|
.unbind('click.pager')
|
619
650
|
.bind('click.pager', function(e){
|
651
|
+
e.stopPropagation();
|
620
652
|
var i, $t = $(this), l = ctrls.length;
|
621
653
|
if ( !$t.hasClass(p.cssDisabled) ) {
|
622
654
|
for (i = 0; i < l; i++) {
|
@@ -626,7 +658,6 @@
|
|
626
658
|
}
|
627
659
|
}
|
628
660
|
}
|
629
|
-
return false;
|
630
661
|
});
|
631
662
|
|
632
663
|
// goto selector
|
@@ -1,5 +1,5 @@
|
|
1
1
|
/**!
|
2
|
-
* TableSorter 2.13.
|
2
|
+
* TableSorter 2.13.3 - 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.13.
|
27
|
+
ts.version = "2.13.3";
|
28
28
|
|
29
29
|
ts.parsers = [];
|
30
30
|
ts.widgets = [];
|
@@ -122,7 +122,8 @@
|
|
122
122
|
};
|
123
123
|
|
124
124
|
/* debuging utils */
|
125
|
-
function log(
|
125
|
+
function log() {
|
126
|
+
var s = arguments.length > 1 ? Array.prototype.slice.call(arguments) : arguments[0];
|
126
127
|
if (typeof console !== "undefined" && typeof console.log !== "undefined") {
|
127
128
|
console.log(s);
|
128
129
|
} else {
|
@@ -201,9 +202,12 @@
|
|
201
202
|
var c = table.config,
|
202
203
|
// update table bodies in case we start with an empty table
|
203
204
|
tb = c.$tbodies = c.$table.children('tbody:not(.' + c.cssInfoBlock + ')'),
|
204
|
-
rows, list, l, i, h, ch, p, parsersDebug = "";
|
205
|
+
rows, list, l, i, h, ch, p, time, parsersDebug = "";
|
205
206
|
if ( tb.length === 0) {
|
206
207
|
return c.debug ? log('*Empty table!* Not building a parser cache') : '';
|
208
|
+
} else if (c.debug) {
|
209
|
+
time = new Date();
|
210
|
+
log('Detecting parsers for each column');
|
207
211
|
}
|
208
212
|
rows = tb[0].rows;
|
209
213
|
if (rows[0]) {
|
@@ -233,6 +237,7 @@
|
|
233
237
|
}
|
234
238
|
if (c.debug) {
|
235
239
|
log(parsersDebug);
|
240
|
+
benchmark("Completed detecting parsers", time);
|
236
241
|
}
|
237
242
|
c.parsers = list;
|
238
243
|
}
|
@@ -301,11 +306,12 @@
|
|
301
306
|
// init flag (true) used by pager plugin to prevent widget application
|
302
307
|
function appendToTable(table, init) {
|
303
308
|
var c = table.config,
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
+
wo = c.widgetOptions,
|
310
|
+
b = table.tBodies,
|
311
|
+
rows = [],
|
312
|
+
c2 = c.cache,
|
313
|
+
r, n, totalRows, checkCell, $bk, $tb,
|
314
|
+
i, j, k, l, pos, appendTime;
|
309
315
|
if (isEmptyObject(c2)) { return; } // empty table - fixes #206/#346
|
310
316
|
if (c.debug) {
|
311
317
|
appendTime = new Date();
|
@@ -322,8 +328,8 @@
|
|
322
328
|
for (i = 0; i < totalRows; i++) {
|
323
329
|
pos = n[i][checkCell];
|
324
330
|
rows.push(r[pos]);
|
325
|
-
// removeRows used by the pager plugin
|
326
|
-
if (!c.appender || !c.removeRows) {
|
331
|
+
// removeRows used by the pager plugin; don't render if using ajax - fixes #411
|
332
|
+
if (!c.appender || (c.pager && (!c.pager.removeRows || !wo.pager_removeRows) && !c.pager.ajax)) {
|
327
333
|
l = r[pos].length;
|
328
334
|
for (j = 0; j < l; j++) {
|
329
335
|
$tb.append(r[pos][j]);
|
@@ -340,8 +346,8 @@
|
|
340
346
|
if (c.debug) {
|
341
347
|
benchmark("Rebuilt table", appendTime);
|
342
348
|
}
|
343
|
-
// apply table widgets
|
344
|
-
if (!init) { ts.applyWidget(table); }
|
349
|
+
// apply table widgets; but not before ajax completes
|
350
|
+
if (!init && !c.appender) { ts.applyWidget(table); }
|
345
351
|
// trigger sortend
|
346
352
|
$(table).trigger("sortEnd", table);
|
347
353
|
$(table).trigger("updateComplete", table);
|
@@ -517,7 +523,7 @@
|
|
517
523
|
// ensure all sortList values are numeric - fixes #127
|
518
524
|
s = [ parseInt(v[0], 10), parseInt(v[1], 10) ];
|
519
525
|
// make sure header exists
|
520
|
-
o = c
|
526
|
+
o = c.$headers[s[0]];
|
521
527
|
if (o) { // prevents error if sorton array is wrong
|
522
528
|
c.sortList.push(s);
|
523
529
|
t = $.inArray(s[1], o.order); // fixes issue #167
|
@@ -584,12 +590,13 @@
|
|
584
590
|
}
|
585
591
|
// the user has clicked on an already sorted column
|
586
592
|
if (ts.isValueInArray(i, c.sortList)) {
|
587
|
-
// reverse the sorting direction
|
593
|
+
// reverse the sorting direction
|
588
594
|
for (j = 0; j < c.sortList.length; j++) {
|
589
595
|
s = c.sortList[j];
|
590
|
-
o = c
|
596
|
+
o = c.$headers[s[0]];
|
591
597
|
if (s[0] === i) {
|
592
|
-
|
598
|
+
// o.count seems to be incorrect when compared to cell.count
|
599
|
+
s[1] = o.order[cell.count];
|
593
600
|
if (s[1] === 2) {
|
594
601
|
c.sortList.splice(j,1);
|
595
602
|
o.count = -1;
|
data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets-filter-formatter.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
/*! Filter widget formatter functions - updated
|
1
|
+
/*! Filter widget formatter functions - updated 11/9/2013
|
2
2
|
* requires: tableSorter 2.7.7+ and jQuery 1.4.3+
|
3
3
|
*
|
4
4
|
* uiSpinner (jQuery UI spinner)
|
@@ -92,7 +92,7 @@ $.tablesorter.filterFormatter = {
|
|
92
92
|
.val(o.value)
|
93
93
|
.appendTo($cell)
|
94
94
|
.spinner(o)
|
95
|
-
.bind('change keyup', function(
|
95
|
+
.bind('change keyup', function(){
|
96
96
|
updateSpinner();
|
97
97
|
});
|
98
98
|
|
@@ -113,7 +113,7 @@ $.tablesorter.filterFormatter = {
|
|
113
113
|
.val(o.value)
|
114
114
|
.appendTo($shcell)
|
115
115
|
.spinner(o)
|
116
|
-
.bind('change keyup', function(
|
116
|
+
.bind('change keyup', function(){
|
117
117
|
$cell.find('.spinner').val( this.value );
|
118
118
|
updateSpinner();
|
119
119
|
});
|
@@ -228,7 +228,7 @@ $.tablesorter.filterFormatter = {
|
|
228
228
|
.val(o.value)
|
229
229
|
.appendTo($shcell)
|
230
230
|
.slider(o)
|
231
|
-
.bind('change keyup', function(
|
231
|
+
.bind('change keyup', function(){
|
232
232
|
$cell.find('.slider').val( this.value );
|
233
233
|
updateSlider();
|
234
234
|
});
|
@@ -337,7 +337,7 @@ $.tablesorter.filterFormatter = {
|
|
337
337
|
.val(o.value)
|
338
338
|
.appendTo($shcell)
|
339
339
|
.slider(o)
|
340
|
-
.bind('change keyup', function(
|
340
|
+
.bind('change keyup', function(){
|
341
341
|
$cell.find('.range').val( this.value );
|
342
342
|
updateUiRange();
|
343
343
|
});
|
@@ -630,8 +630,7 @@ $.tablesorter.filterFormatter = {
|
|
630
630
|
var compare = ( $cell.find('.compare').val() || o.compare);
|
631
631
|
$cell.find('input[type=hidden]')
|
632
632
|
// add equal to the beginning, so we filter exact numbers
|
633
|
-
.val( !o.addToggle || chkd ? (
|
634
|
-
.val( !o.addToggle || chkd ? compare + v : '' )
|
633
|
+
.val( !o.addToggle || chkd ? (compare ? compare : o.exactMatch ? '=' : '') + v : '' )
|
635
634
|
.trigger('search', delayed ? delayed : o.delayed).end()
|
636
635
|
.find('.number').val(v);
|
637
636
|
if ($cell.find('.number').length) {
|
@@ -732,7 +731,7 @@ $.tablesorter.filterFormatter = {
|
|
732
731
|
HTML5 range slider
|
733
732
|
\**********************/
|
734
733
|
html5Range : function($cell, indx, def5Range) {
|
735
|
-
var
|
734
|
+
var o = $.extend({
|
736
735
|
value : 0,
|
737
736
|
min : 0,
|
738
737
|
max : 100,
|
@@ -1,4 +1,4 @@
|
|
1
|
-
/*! tableSorter 2.8+ widgets - updated 11/
|
1
|
+
/*! tableSorter 2.8+ widgets - updated 11/9/2013
|
2
2
|
*
|
3
3
|
* Column Styles
|
4
4
|
* Column Filters
|
@@ -17,6 +17,7 @@ var ts = $.tablesorter = $.tablesorter || {};
|
|
17
17
|
ts.themes = {
|
18
18
|
"bootstrap" : {
|
19
19
|
table : 'table table-bordered table-striped',
|
20
|
+
caption : 'caption',
|
20
21
|
header : 'bootstrap-header', // give the header a gradient background
|
21
22
|
footerRow : '',
|
22
23
|
footerCells: '',
|
@@ -32,6 +33,7 @@ ts.themes = {
|
|
32
33
|
},
|
33
34
|
"jui" : {
|
34
35
|
table : 'ui-widget ui-widget-content ui-corner-all', // table classes
|
36
|
+
caption : 'ui-widget-content ui-corner-all',
|
35
37
|
header : 'ui-widget-header ui-corner-all ui-state-default', // header classes
|
36
38
|
footerRow : '',
|
37
39
|
footerCells: '',
|
@@ -167,10 +169,13 @@ ts.addWidget({
|
|
167
169
|
sh = 'tr.' + (wo.stickyHeaders || 'tablesorter-stickyHeader'),
|
168
170
|
rmv = o.sortNone + ' ' + o.sortDesc + ' ' + o.sortAsc;
|
169
171
|
if (c.debug) { time = new Date(); }
|
172
|
+
// initialization code - run once
|
170
173
|
if (!$t.hasClass('tablesorter-' + theme) || c.theme === theme || !table.hasInitialized){
|
171
174
|
// update zebra stripes
|
172
175
|
if (o.even !== '') { wo.zebra[0] += ' ' + o.even; }
|
173
176
|
if (o.odd !== '') { wo.zebra[1] += ' ' + o.odd; }
|
177
|
+
// add caption style
|
178
|
+
$t.find('caption').addClass(o.caption);
|
174
179
|
// add table/footer class names
|
175
180
|
t = $t
|
176
181
|
// remove other selected themes; use widgetOptions.theme_remove
|
@@ -191,7 +196,7 @@ ts.addWidget({
|
|
191
196
|
$(this)[ e.type === 'mouseenter' ? 'addClass' : 'removeClass' ](o.hover);
|
192
197
|
});
|
193
198
|
if (!$h.find('.tablesorter-wrapper').length) {
|
194
|
-
// Firefox needs this inner div to position the resizer correctly
|
199
|
+
// Firefox needs this inner div to position the icon/resizer correctly
|
195
200
|
$h.wrapInner('<div class="tablesorter-wrapper" style="position:relative;height:100%;width:100%"></div>');
|
196
201
|
}
|
197
202
|
if (c.cssIcon){
|
@@ -327,6 +332,7 @@ ts.addWidget({
|
|
327
332
|
id: "filter",
|
328
333
|
priority: 50,
|
329
334
|
options : {
|
335
|
+
filter_anyMatch : false, // if true overrides default find rows behaviours and if any column matches query it returns that row
|
330
336
|
filter_childRows : false, // if true, filter includes child row content in the search
|
331
337
|
filter_columnFilters : true, // if true, a filter will be added to the top of each table column
|
332
338
|
filter_cssFilter : '', // css class name added to the filter row & each input in the row (tablesorter-filter is ALWAYS added)
|
@@ -342,504 +348,663 @@ ts.addWidget({
|
|
342
348
|
filter_startsWith : false, // if true, filter start from the beginning of the cell contents
|
343
349
|
filter_useParsedData : false, // filter all data using parsed content
|
344
350
|
filter_serversideFiltering : false, // if true, server-side filtering should be performed because client-side filtering will be disabled, but the ui and events will still be used.
|
345
|
-
filter_defaultAttrib : 'data-value'
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
"type" : /undefined|number/, // check type
|
353
|
-
"exact" : /(^[\"|\'|=]+)|([\"|\'|=]+$)/g, // exact match (allow '==')
|
354
|
-
"nondigit" : /[^\w,. \-()]/g, // replace non-digits (from digit & currency parser)
|
355
|
-
"operators" : /[<>=]/g // replace operators
|
351
|
+
filter_defaultAttrib : 'data-value' // data attribute in the header cell that contains the default filter value
|
352
|
+
},
|
353
|
+
format: function(table, c, wo) {
|
354
|
+
if (!c.$table.hasClass('hasFilters')) {
|
355
|
+
if (c.parsers || !c.parsers && wo.filter_serversideFiltering) {
|
356
|
+
ts.filter.init(table, c, wo);
|
357
|
+
}
|
356
358
|
}
|
357
359
|
},
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
360
|
+
remove: function(table, c, wo) {
|
361
|
+
var tbodyIndex, $tbody,
|
362
|
+
$table = c.$table,
|
363
|
+
$tbodies = c.$tbodies;
|
364
|
+
$table
|
365
|
+
.removeClass('hasFilters')
|
366
|
+
// add .tsfilter namespace to all BUT search
|
367
|
+
.unbind('addRows updateCell update updateComplete appendCache search filterStart filterEnd '.split(' ').join('.tsfilter '))
|
368
|
+
.find('.tablesorter-filter-row').remove();
|
369
|
+
for (tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) {
|
370
|
+
$tbody = ts.processTbody(table, $tbodies.eq(tbodyIndex), true); // remove tbody
|
371
|
+
$tbody.children().removeClass(wo.filter_filteredRow).show();
|
372
|
+
ts.processTbody(table, $tbody, false); // restore tbody
|
373
|
+
}
|
374
|
+
if (wo.filter_reset) {
|
375
|
+
$(document).undelegate(wo.filter_reset, 'click.tsfilter');
|
376
|
+
}
|
377
|
+
}
|
378
|
+
});
|
379
|
+
|
380
|
+
ts.filter = {
|
372
381
|
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
382
|
+
// regex used in filter "check" functions - not for general use and not documented
|
383
|
+
regex: {
|
384
|
+
regex : /^\/((?:\\\/|[^\/])+)\/([mig]{0,3})?$/, // regex to test for regex
|
385
|
+
child : /tablesorter-childRow/, // child row class name; this gets updated in the script
|
386
|
+
filtered : /filtered/, // filtered (hidden) row class name; updated in the script
|
387
|
+
type : /undefined|number/, // check type
|
388
|
+
exact : /(^[\"|\'|=]+)|([\"|\'|=]+$)/g, // exact match (allow '==')
|
389
|
+
nondigit : /[^\w,. \-()]/g, // replace non-digits (from digit & currency parser)
|
390
|
+
operators : /[<>=]/g // replace operators
|
391
|
+
},
|
392
|
+
// function( filter, iFilter, exact, iExact, cached, index, table, wo, parsed )
|
393
|
+
// filter = array of filter input values; iFilter = same array, except lowercase
|
394
|
+
// exact = table cell text (or parsed data if column parser enabled)
|
395
|
+
// iExact = same as exact, except lowercase
|
396
|
+
// cached = table cell text from cache, so it has been parsed
|
397
|
+
// index = column index; table = table element (DOM)
|
398
|
+
// wo = widget options (table.config.widgetOptions)
|
399
|
+
// parsed = array (by column) of boolean values (from filter_useParsedData or "filter-parsed" class)
|
400
|
+
types: {
|
401
|
+
// Look for regex
|
402
|
+
regex: function( filter, iFilter, exact, iExact ) {
|
403
|
+
if ( ts.filter.regex.regex.test(iFilter) ) {
|
404
|
+
var matches,
|
405
|
+
regex = ts.filter.regex.regex.exec(iFilter);
|
406
|
+
try {
|
407
|
+
matches = new RegExp(regex[1], regex[2]).test( iExact );
|
408
|
+
} catch (error) {
|
409
|
+
matches = false;
|
381
410
|
}
|
382
|
-
|
383
|
-
|
384
|
-
|
411
|
+
return matches;
|
412
|
+
}
|
413
|
+
return null;
|
414
|
+
},
|
415
|
+
// Look for quotes or equals to get an exact match; ignore type since iExact could be numeric
|
416
|
+
exact: function( filter, iFilter, exact, iExact ) {
|
417
|
+
/*jshint eqeqeq:false */
|
418
|
+
if ( iFilter.replace(ts.filter.regex.exact, '') == iExact ) {
|
419
|
+
return true;
|
420
|
+
}
|
421
|
+
return null;
|
422
|
+
},
|
423
|
+
// Look for a not match
|
424
|
+
notMatch: function( filter, iFilter, exact, iExact, cached, index, table, wo ) {
|
425
|
+
if ( /^\!/.test(iFilter) ) {
|
426
|
+
iFilter = iFilter.replace('!', '');
|
427
|
+
var indx = iExact.search( $.trim(iFilter) );
|
428
|
+
return iFilter === '' ? true : !(wo.filter_startsWith ? indx === 0 : indx >= 0);
|
429
|
+
}
|
430
|
+
return null;
|
431
|
+
},
|
432
|
+
// Look for operators >, >=, < or <=
|
433
|
+
operators: function( filter, iFilter, exact, iExact, cached, index, table, wo, parsed ) {
|
434
|
+
if ( /^[<>]=?/.test(iFilter) ) {
|
435
|
+
var cachedValue, result,
|
436
|
+
c = table.config,
|
437
|
+
query = ts.formatFloat( iFilter.replace(ts.filter.regex.operators, ''), table ),
|
438
|
+
parser = c.parsers[index],
|
439
|
+
savedSearch = query;
|
440
|
+
// parse filter value in case we're comparing numbers (dates)
|
441
|
+
if (parsed[index] || parser.type === 'numeric') {
|
442
|
+
cachedValue = parser.format( '' + iFilter.replace(ts.filter.regex.operators, ''), table, c.$headers.eq(index), index );
|
443
|
+
query = ( typeof query === "number" && cachedValue !== '' && !isNaN(cachedValue) ) ? cachedValue : query;
|
385
444
|
}
|
386
|
-
//
|
387
|
-
//
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
445
|
+
// iExact may be numeric - see issue #149;
|
446
|
+
// check if cached is defined, because sometimes j goes out of range? (numeric columns)
|
447
|
+
cachedValue = ( parsed[index] || parser.type === 'numeric' ) && !isNaN(query) && cached ? cached :
|
448
|
+
isNaN(iExact) ? ts.formatFloat( iExact.replace(ts.filter.regex.nondigit, ''), table) :
|
449
|
+
ts.formatFloat( iExact, table );
|
450
|
+
if ( />/.test(iFilter) ) { result = />=/.test(iFilter) ? cachedValue >= query : cachedValue > query; }
|
451
|
+
if ( /</.test(iFilter) ) { result = /<=/.test(iFilter) ? cachedValue <= query : cachedValue < query; }
|
452
|
+
// keep showing all rows if nothing follows the operator
|
453
|
+
if ( !result && savedSearch === '' ) { result = true; }
|
454
|
+
return result;
|
455
|
+
}
|
456
|
+
return null;
|
457
|
+
},
|
458
|
+
// Look for an AND or && operator (logical and)
|
459
|
+
and : function( filter, iFilter, exact, iExact ) {
|
460
|
+
if ( /\s+(AND|&&)\s+/g.test(filter) ) {
|
461
|
+
var query = iFilter.split( /(?:\s+(?:and|&&)\s+)/g ),
|
462
|
+
result = iExact.search( $.trim(query[0]) ) >= 0,
|
463
|
+
indx = query.length - 1;
|
464
|
+
while (result && indx) {
|
465
|
+
result = result && iExact.search( $.trim(query[indx]) ) >= 0;
|
466
|
+
indx--;
|
399
467
|
}
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
if (wo.filter_functions && wo.filter_functions[i]){
|
451
|
-
if (wo.filter_functions[i] === true){
|
452
|
-
// default selector; no "filter-select" class
|
453
|
-
ff = ($ths.filter('[data-column="' + i + '"]:last').hasClass('filter-match')) ? xi.search(val) >= 0 : v[i] === x;
|
454
|
-
} else if (typeof wo.filter_functions[i] === 'function'){
|
455
|
-
// filter callback( exact cell content, parser normalized content, filter input value, column index )
|
456
|
-
ff = wo.filter_functions[i](x, c.cache[k].normalized[j][i], v[i], i, $tr.eq(j));
|
457
|
-
} else if (typeof wo.filter_functions[i][v[i]] === 'function'){
|
458
|
-
// selector option function
|
459
|
-
ff = wo.filter_functions[i][v[i]](x, c.cache[k].normalized[j][i], v[i], i, $tr.eq(j));
|
460
|
-
}
|
461
|
-
// Look for regex
|
462
|
-
} else if (wo.filter_regex.regex.test(val)){
|
463
|
-
rg = wo.filter_regex.regex.exec(val);
|
464
|
-
try {
|
465
|
-
ff = new RegExp(rg[1], rg[2]).test(xi);
|
466
|
-
} catch (err){
|
467
|
-
ff = false;
|
468
|
-
}
|
469
|
-
// Look for quotes or equals to get an exact match; ignore type since xi could be numeric
|
470
|
-
/*jshint eqeqeq:false */
|
471
|
-
} else if (val.replace(wo.filter_regex.exact, '') == xi){
|
472
|
-
ff = true;
|
473
|
-
// Look for a not match
|
474
|
-
} else if (/^\!/.test(val)){
|
475
|
-
val = val.replace('!','');
|
476
|
-
s = xi.search($.trim(val));
|
477
|
-
ff = val === '' ? true : !(wo.filter_startsWith ? s === 0 : s >= 0);
|
478
|
-
// Look for operators >, >=, < or <=
|
479
|
-
} else if (/^[<>]=?/.test(val)){
|
480
|
-
s = fr = fmt(val.replace(wo.filter_regex.nondigit, '').replace(wo.filter_regex.operators,''), table);
|
481
|
-
// parse filter value in case we're comparing numbers (dates)
|
482
|
-
if (parsed[i] || c.parsers[i].type === 'numeric') {
|
483
|
-
rg = c.parsers[i].format('' + val.replace(wo.filter_regex.operators,''), table, $ths.eq(i), i);
|
484
|
-
s = (isNaN(s) && rg !== '' && !isNaN(rg)) ? rg : s;
|
485
|
-
}
|
486
|
-
// xi may be numeric - see issue #149;
|
487
|
-
// check if c.cache[k].normalized[j] is defined, because sometimes j goes out of range? (numeric columns)
|
488
|
-
rg = ( parsed[i] || c.parsers[i].type === 'numeric' ) && !isNaN(s) && c.cache[k].normalized[j] ? c.cache[k].normalized[j][i] :
|
489
|
-
isNaN(xi) ? fmt(xi.replace(wo.filter_regex.nondigit, ''), table) : fmt(xi, table);
|
490
|
-
if (/>/.test(val)) { ff = />=/.test(val) ? rg >= s : rg > s; }
|
491
|
-
if (/</.test(val)) { ff = /<=/.test(val) ? rg <= s : rg < s; }
|
492
|
-
if (!ff && fr === '') { ff = true; } // keep showing all rows if nothing follows the operator
|
493
|
-
// Look for an AND or && operator (logical and)
|
494
|
-
} else if (/\s+(AND|&&)\s+/g.test(v[i])) {
|
495
|
-
s = val.split(/(?:\s+(?:and|&&)\s+)/g);
|
496
|
-
ff = xi.search($.trim(s[0])) >= 0;
|
497
|
-
r1 = s.length - 1;
|
498
|
-
while (ff && r1) {
|
499
|
-
ff = ff && xi.search($.trim(s[r1])) >= 0;
|
500
|
-
r1--;
|
501
|
-
}
|
502
|
-
// Look for a range (using " to " or " - ") - see issue #166; thanks matzhu!
|
503
|
-
} else if (/\s+(-|to)\s+/.test(val)){
|
504
|
-
s = val.split(/(?: - | to )/); // make sure the dash is for a range and not indicating a negative number
|
505
|
-
r1 = fmt(s[0].replace(wo.filter_regex.nondigit, ''), table);
|
506
|
-
r2 = fmt(s[1].replace(wo.filter_regex.nondigit, ''), table);
|
507
|
-
// parse filter value in case we're comparing numbers (dates)
|
508
|
-
if (parsed[i] || c.parsers[i].type === 'numeric') {
|
509
|
-
rg = c.parsers[i].format('' + s[0], table, $ths.eq(i), i);
|
510
|
-
r1 = (rg !== '' && !isNaN(rg)) ? rg : r1;
|
511
|
-
rg = c.parsers[i].format('' + s[1], table, $ths.eq(i), i);
|
512
|
-
r2 = (rg !== '' && !isNaN(rg)) ? rg : r2;
|
513
|
-
}
|
514
|
-
rg = ( parsed[i] || c.parsers[i].type === 'numeric' ) && !isNaN(r1) && !isNaN(r2) ? c.cache[k].normalized[j][i] :
|
515
|
-
isNaN(xi) ? fmt(xi.replace(wo.filter_regex.nondigit, ''), table) : fmt(xi, table);
|
516
|
-
if (r1 > r2) { ff = r1; r1 = r2; r2 = ff; } // swap
|
517
|
-
ff = (rg >= r1 && rg <= r2) || (r1 === '' || r2 === '') ? true : false;
|
518
|
-
// Look for wild card: ? = single, * = multiple, or | = logical OR
|
519
|
-
} else if ( /[\?|\*]/.test(val) || /\s+OR\s+/.test(v[i]) ){
|
520
|
-
s = val.replace(/\s+OR\s+/gi,"|");
|
521
|
-
// look for an exact match with the "or" unless the "filter-match" class is found
|
522
|
-
if (!$ths.filter('[data-column="' + i + '"]:last').hasClass('filter-match') && /\|/.test(s)) {
|
523
|
-
s = '^(' + s + ')$';
|
524
|
-
}
|
525
|
-
ff = new RegExp( s.replace(/\?/g, '\\S{1}').replace(/\*/g, '\\S*') ).test(xi);
|
526
|
-
// Look for match, and add child row data for matching
|
527
|
-
} else {
|
528
|
-
x = (xi + t).indexOf(val);
|
529
|
-
ff = ( (!wo.filter_startsWith && x >= 0) || (wo.filter_startsWith && x === 0) );
|
530
|
-
}
|
531
|
-
r = (ff) ? (r ? true : false) : false;
|
532
|
-
}
|
533
|
-
}
|
534
|
-
$tr[j].style.display = (r ? '' : 'none');
|
535
|
-
$tr.eq(j)[r ? 'removeClass' : 'addClass'](wo.filter_filteredRow);
|
536
|
-
if (cr.length) {
|
537
|
-
if (c.pager && c.pager.countChildRows || wo.pager_countChildRows) {
|
538
|
-
cr[r ? 'removeClass' : 'addClass'](wo.filter_filteredRow); // see issue #396
|
539
|
-
}
|
540
|
-
cr[r ? 'show' : 'hide']();
|
541
|
-
}
|
542
|
-
}
|
468
|
+
return result;
|
469
|
+
}
|
470
|
+
return null;
|
471
|
+
},
|
472
|
+
// Look for a range (using " to " or " - ") - see issue #166; thanks matzhu!
|
473
|
+
range : function( filter, iFilter, exact, iExact, cached, index, table, wo, parsed ) {
|
474
|
+
if ( /\s+(-|to)\s+/.test(iFilter) ) {
|
475
|
+
var result,
|
476
|
+
c = table.config,
|
477
|
+
query = iFilter.split(/(?: - | to )/), // make sure the dash is for a range and not indicating a negative number
|
478
|
+
range1 = ts.formatFloat(query[0].replace(ts.filter.regex.nondigit, ''), table),
|
479
|
+
range2 = ts.formatFloat(query[1].replace(ts.filter.regex.nondigit, ''), table);
|
480
|
+
// parse filter value in case we're comparing numbers (dates)
|
481
|
+
if (parsed[index] || c.parsers[index].type === 'numeric') {
|
482
|
+
result = c.parsers[index].format('' + query[0], table, c.$headers.eq(index), index);
|
483
|
+
range1 = (result !== '' && !isNaN(result)) ? result : range1;
|
484
|
+
result = c.parsers[index].format('' + query[1], table, c.$headers.eq(index), index);
|
485
|
+
range2 = (result !== '' && !isNaN(result)) ? result : range2;
|
486
|
+
}
|
487
|
+
result = ( parsed[index] || c.parsers[index].type === 'numeric' ) && !isNaN(range1) && !isNaN(range2) ? cached :
|
488
|
+
isNaN(iExact) ? ts.formatFloat( iExact.replace(ts.filter.regex.nondigit, ''), table) :
|
489
|
+
ts.formatFloat( iExact, table );
|
490
|
+
if (range1 > range2) { result = range1; range1 = range2; range2 = result; } // swap
|
491
|
+
return (result >= range1 && result <= range2) || (range1 === '' || range2 === '');
|
492
|
+
}
|
493
|
+
return null;
|
494
|
+
},
|
495
|
+
// Look for wild card: ? = single, * = multiple, or | = logical OR
|
496
|
+
wild : function( filter, iFilter, exact, iExact, cached, index, table ) {
|
497
|
+
if ( /[\?|\*]/.test(iFilter) || /\s+OR\s+/.test(filter) ) {
|
498
|
+
var c = table.config,
|
499
|
+
query = iFilter.replace(/\s+OR\s+/gi,"|");
|
500
|
+
// look for an exact match with the "or" unless the "filter-match" class is found
|
501
|
+
if (!c.$headers.filter('[data-column="' + index + '"]:last').hasClass('filter-match') && /\|/.test(query)) {
|
502
|
+
query = '^(' + query + ')$';
|
503
|
+
}
|
504
|
+
return new RegExp( query.replace(/\?/g, '\\S{1}').replace(/\*/g, '\\S*') ).test(iExact);
|
505
|
+
}
|
506
|
+
return null;
|
507
|
+
},
|
508
|
+
// fuzzy text search; modified from https://github.com/mattyork/fuzzy (MIT license)
|
509
|
+
fuzzy: function( filter, iFilter, exact, iExact ) {
|
510
|
+
if ( /^~/.test(iFilter) ) {
|
511
|
+
var indx,
|
512
|
+
patternIndx = 0,
|
513
|
+
len = iExact.length,
|
514
|
+
pattern = iFilter.slice(1);
|
515
|
+
for (indx = 0; indx < len; indx++) {
|
516
|
+
if (iExact[indx] === pattern[patternIndx]) {
|
517
|
+
patternIndx += 1;
|
543
518
|
}
|
544
|
-
ts.processTbody(table, $tb, false);
|
545
519
|
}
|
546
|
-
|
547
|
-
|
548
|
-
if (c.debug){
|
549
|
-
ts.benchmark("Completed filter widget search", time);
|
520
|
+
if (patternIndx === pattern.length) {
|
521
|
+
return true;
|
550
522
|
}
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
523
|
+
return false;
|
524
|
+
}
|
525
|
+
return null;
|
526
|
+
}
|
527
|
+
},
|
528
|
+
init: function(table, c, wo) {
|
529
|
+
var options, string, $header, column, filters, time;
|
530
|
+
if (c.debug) {
|
531
|
+
time = new Date();
|
532
|
+
}
|
533
|
+
c.$table.addClass('hasFilters');
|
534
|
+
|
535
|
+
ts.filter.regex.child = new RegExp(c.cssChildRow);
|
536
|
+
ts.filter.regex.filtered = new RegExp(wo.filter_filteredRow);
|
537
|
+
|
538
|
+
// don't build filter row if columnFilters is false or all columns are set to "filter-false" - issue #156
|
539
|
+
if (wo.filter_columnFilters !== false && c.$headers.filter('.filter-false').length !== c.$headers.length) {
|
540
|
+
// build filter row
|
541
|
+
ts.filter.buildRow(table, c, wo);
|
542
|
+
}
|
543
|
+
|
544
|
+
c.$table.bind('addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search '.split(' ').join('.tsfilter '), function(event, filter) {
|
545
|
+
if ( !/(search|filterReset|filterEnd)/.test(event.type) ) {
|
546
|
+
event.stopPropagation();
|
547
|
+
ts.filter.buildDefault(table, true);
|
548
|
+
}
|
549
|
+
if (event.type === 'filterReset') {
|
550
|
+
ts.filter.searching(table, []);
|
551
|
+
}
|
552
|
+
if (event.type === 'filterEnd') {
|
553
|
+
ts.filter.buildDefault(table, true);
|
554
|
+
} else {
|
555
|
+
// send false argument to force a new search; otherwise if the filter hasn't changed, it will return
|
556
|
+
filter = event.type === 'search' ? filter : event.type === 'updateComplete' ? c.$table.data('lastSearch') : '';
|
557
|
+
ts.filter.searching(table, filter);
|
558
|
+
}
|
559
|
+
return false;
|
560
|
+
});
|
561
|
+
ts.filter.bindSearch( table, c.$table.find('input.tablesorter-filter') );
|
562
|
+
|
563
|
+
// reset button/link
|
564
|
+
if (wo.filter_reset) {
|
565
|
+
$(document).delegate(wo.filter_reset, 'click.tsfilter', function() {
|
566
|
+
ts.filter.searching(table, []);
|
567
|
+
});
|
568
|
+
}
|
569
|
+
if (wo.filter_functions) {
|
570
|
+
// column = column # (string)
|
571
|
+
for (column in wo.filter_functions) {
|
572
|
+
if (wo.filter_functions.hasOwnProperty(column) && typeof column === 'string') {
|
573
|
+
$header = c.$headers.filter('[data-column="' + column + '"]:last');
|
574
|
+
options = '';
|
575
|
+
if (wo.filter_functions[column] === true && !$header.hasClass('filter-false')) {
|
576
|
+
ts.filter.buildSelect(column);
|
577
|
+
} else if (typeof column === 'string' && !$header.hasClass('filter-false')) {
|
578
|
+
// add custom drop down list
|
579
|
+
for (string in wo.filter_functions[column]) {
|
580
|
+
if (typeof string === 'string') {
|
581
|
+
options += options === '' ?
|
582
|
+
'<option value="">' + ($header.data('placeholder') || $header.attr('data-placeholder') || '') + '</option>' : '';
|
583
|
+
options += '<option value="' + string + '">' + string + '</option>';
|
573
584
|
}
|
574
585
|
}
|
586
|
+
c.$table.find('thead').find('select.tablesorter-filter[data-column="' + column + '"]').append(options);
|
575
587
|
}
|
576
588
|
}
|
589
|
+
}
|
590
|
+
}
|
591
|
+
// not really updating, but if the column has both the "filter-select" class & filter_functions set to true,
|
592
|
+
// it would append the same options twice.
|
593
|
+
ts.filter.buildDefault(table, true);
|
577
594
|
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
arry = $.grep(arry, function(v, k){
|
582
|
-
return $.inArray(v, arry) === k;
|
583
|
-
});
|
584
|
-
arry = (ts.sortNatural) ? arry.sort(function(a, b){ return ts.sortNatural(a, b); }) : arry.sort(true);
|
595
|
+
c.$table.find('select.tablesorter-filter').bind('change search', function(event, filter) {
|
596
|
+
ts.filter.checkFilters(table, filter);
|
597
|
+
});
|
585
598
|
|
586
|
-
|
587
|
-
|
599
|
+
if (wo.filter_hideFilters) {
|
600
|
+
ts.filter.hideFilters(table, c, wo);
|
601
|
+
}
|
588
602
|
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
603
|
+
// show processing icon
|
604
|
+
if (c.showProcessing) {
|
605
|
+
c.$table.bind('filterStart.tsfilter filterEnd.tsfilter', function(event, columns) {
|
606
|
+
// only add processing to certain columns to all columns
|
607
|
+
$header = (columns) ? c.$table.find('.' + ts.css.header).filter('[data-column]').filter(function() {
|
608
|
+
return columns[$(this).data('column')] !== '';
|
609
|
+
}) : '';
|
610
|
+
ts.isProcessing(table, event.type === 'filterStart', columns ? $header : '');
|
611
|
+
});
|
612
|
+
}
|
613
|
+
if (c.debug) {
|
614
|
+
ts.benchmark("Applying Filter widget", time);
|
615
|
+
}
|
616
|
+
// add default values
|
617
|
+
c.$table.bind('tablesorter-initialized pagerInitialized', function() {
|
618
|
+
filters = ts.filter.setDefaults(table, c, wo) || [];
|
619
|
+
if (filters.length) {
|
620
|
+
ts.setFilters(table, filters, true);
|
621
|
+
}
|
622
|
+
});
|
623
|
+
// filter widget initialized
|
624
|
+
wo.filter_Initialized = true;
|
625
|
+
c.$table.trigger('filterInit');
|
626
|
+
ts.filter.checkFilters(table);
|
627
|
+
},
|
628
|
+
setDefaults: function(table, c, wo){
|
629
|
+
var indx,
|
630
|
+
filters = [],
|
631
|
+
columns = c.columns;
|
632
|
+
for (indx = 0; indx < columns; indx++) {
|
633
|
+
filters[indx] = c.$headers.filter('[data-column="' + indx + '"]:last').attr(wo.filter_defaultAttrib) || filters[indx];
|
634
|
+
}
|
635
|
+
$(table).data('lastSearch', filters);
|
636
|
+
return filters;
|
637
|
+
},
|
638
|
+
buildRow: function(table, c, wo) {
|
639
|
+
var column, $header, buildSelect, disabled,
|
640
|
+
// c.columns defined in computeThIndexes()
|
641
|
+
columns = c.columns,
|
642
|
+
buildFilter = '<tr class="tablesorter-filter-row">';
|
643
|
+
for (column = 0; column < columns; column++) {
|
644
|
+
buildFilter += '<td></td>';
|
645
|
+
}
|
646
|
+
c.$filters = $(buildFilter += '</tr>').appendTo( c.$table.find('thead').eq(0) ).find('td');
|
647
|
+
// build each filter input
|
648
|
+
for (column = 0; column < columns; column++) {
|
649
|
+
disabled = false;
|
650
|
+
// assuming last cell of a column is the main column
|
651
|
+
$header = c.$headers.filter('[data-column="' + column + '"]:last');
|
652
|
+
buildSelect = (wo.filter_functions && wo.filter_functions[column] && typeof wo.filter_functions[column] !== 'function') ||
|
653
|
+
$header.hasClass('filter-select');
|
654
|
+
// get data from jQuery data, metadata, headers option or header class name
|
655
|
+
if (ts.getData) {
|
656
|
+
// get data from jQuery data, metadata, headers option or header class name
|
657
|
+
disabled = ts.getData($header[0], c.headers[column], 'filter') === 'false';
|
658
|
+
} else {
|
659
|
+
// only class names and header options - keep this for compatibility with tablesorter v2.0.5
|
660
|
+
disabled = (c.headers[column] && c.headers[column].hasOwnProperty('filter') && c.headers[column].filter === false) ||
|
661
|
+
$header.hasClass('filter-false');
|
662
|
+
}
|
663
|
+
if (buildSelect) {
|
664
|
+
buildFilter = $('<select>').appendTo( c.$filters.eq(column) );
|
665
|
+
} else {
|
666
|
+
if (wo.filter_formatter && $.isFunction(wo.filter_formatter[column])) {
|
667
|
+
buildFilter = wo.filter_formatter[column]( c.$filters.eq(column), column );
|
668
|
+
// no element returned, so lets go find it
|
669
|
+
if (buildFilter && buildFilter.length === 0) {
|
670
|
+
buildFilter = c.$filters.eq(column).children('input');
|
671
|
+
}
|
672
|
+
// element not in DOM, so lets attach it
|
673
|
+
if ( buildFilter && (buildFilter.parent().length === 0 ||
|
674
|
+
(buildFilter.parent().length && buildFilter.parent()[0] !== c.$filters[column])) ) {
|
675
|
+
c.$filters.eq(column).append(buildFilter);
|
606
676
|
}
|
607
|
-
}
|
608
|
-
},
|
609
|
-
searching = function(filter){
|
610
|
-
if (typeof filter === 'undefined' || filter === true){
|
611
|
-
// delay filtering
|
612
|
-
clearTimeout(timer);
|
613
|
-
timer = setTimeout(function(){
|
614
|
-
checkFilters(filter);
|
615
|
-
}, wo.filter_liveSearch ? wo.filter_searchDelay : 10);
|
616
677
|
} else {
|
617
|
-
|
618
|
-
|
678
|
+
buildFilter = $('<input type="search">').appendTo( c.$filters.eq(column) );
|
679
|
+
}
|
680
|
+
if (buildFilter) {
|
681
|
+
buildFilter.attr('placeholder', $header.data('placeholder') || $header.attr('data-placeholder') || '');
|
619
682
|
}
|
620
|
-
};
|
621
|
-
if (c.debug){
|
622
|
-
time = new Date();
|
623
683
|
}
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
if (wo.filter_columnFilters !== false && $ths.filter('.filter-false').length !== $ths.length){
|
629
|
-
// build filter row
|
630
|
-
t = '<tr class="tablesorter-filter-row">';
|
631
|
-
for (i = 0; i < cols; i++){
|
632
|
-
t += '<td></td>';
|
684
|
+
if (buildFilter) {
|
685
|
+
buildFilter.addClass('tablesorter-filter ' + wo.filter_cssFilter).attr('data-column', column);
|
686
|
+
if (disabled) {
|
687
|
+
buildFilter.addClass('disabled')[0].disabled = true; // disabled!
|
633
688
|
}
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
689
|
+
}
|
690
|
+
}
|
691
|
+
},
|
692
|
+
bindSearch: function(table, $el) {
|
693
|
+
table = $(table)[0];
|
694
|
+
var external, wo = table.config.widgetOptions;
|
695
|
+
$el.bind('keyup search', function(event, filter) {
|
696
|
+
// emulate what webkit does.... escape clears the filter
|
697
|
+
if (event.which === 27) {
|
698
|
+
this.value = '';
|
699
|
+
// liveSearch can contain a min value length; ignore arrow and meta keys, but allow backspace
|
700
|
+
} else if ( (typeof wo.filter_liveSearch === 'number' && this.value.length < wo.filter_liveSearch && this.value !== '') ||
|
701
|
+
( event.type === 'keyup' && ( (event.which < 32 && event.which !== 8 && wo.filter_liveSearch === true && event.which !== 13) ||
|
702
|
+
( event.which >= 37 && event.which <= 40 ) || (event.which !== 13 && wo.filter_liveSearch === false) ) ) ) {
|
703
|
+
return;
|
704
|
+
}
|
705
|
+
// external searches won't have a filter parameter, so grab the value
|
706
|
+
external = $(this).hasClass('tablesorter-filter') ? filter : [ $(this).val() ];
|
707
|
+
ts.filter.searching(table, filter, external);
|
708
|
+
});
|
709
|
+
},
|
710
|
+
checkFilters: function(table, filter) {
|
711
|
+
var c = table.config,
|
712
|
+
wo = c.widgetOptions,
|
713
|
+
filterArray = $.isArray(filter),
|
714
|
+
filters = (filterArray) ? filter : ts.getFilters(table),
|
715
|
+
combinedFilters = (filters || []).join(''); // combined filter values
|
716
|
+
// add filter array back into inputs
|
717
|
+
if (filterArray) {
|
718
|
+
ts.setFilters( table, filters );
|
719
|
+
}
|
720
|
+
if (wo.filter_hideFilters) {
|
721
|
+
// show/hide filter row as needed
|
722
|
+
c.$table.find('.tablesorter-filter-row').trigger( combinedFilters === '' ? 'mouseleave' : 'mouseenter' );
|
723
|
+
}
|
724
|
+
// return if the last search is the same; but filter === false when updating the search
|
725
|
+
// see example-widget-filter.html filter toggle buttons
|
726
|
+
if (c.lastCombinedFilter === combinedFilters && filter !== false) { return; }
|
727
|
+
c.$table.trigger('filterStart', [filters]);
|
728
|
+
if (c.showProcessing) {
|
729
|
+
// give it time for the processing icon to kick in
|
730
|
+
setTimeout(function() {
|
731
|
+
ts.filter.findRows(table, filters, combinedFilters);
|
732
|
+
return false;
|
733
|
+
}, 30);
|
734
|
+
} else {
|
735
|
+
ts.filter.findRows(table, filters, combinedFilters);
|
736
|
+
return false;
|
737
|
+
}
|
738
|
+
},
|
739
|
+
hideFilters: function(table, c, wo) {
|
740
|
+
var $filterRow, $filterRow2, timer;
|
741
|
+
c.$table
|
742
|
+
.find('.tablesorter-filter-row')
|
743
|
+
.addClass('hideme')
|
744
|
+
.bind('mouseenter mouseleave', function(e) {
|
745
|
+
// save event object - http://bugs.jquery.com/ticket/12140
|
746
|
+
var event = e;
|
747
|
+
$filterRow = $(this);
|
748
|
+
clearTimeout(timer);
|
749
|
+
timer = setTimeout(function() {
|
750
|
+
if ( /enter|over/.test(event.type) ) {
|
751
|
+
$filterRow.removeClass('hideme');
|
651
752
|
} else {
|
652
|
-
if
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
c.$filters.eq(i).append(t);
|
753
|
+
// don't hide if input has focus
|
754
|
+
// $(':focus') needs jQuery 1.6+
|
755
|
+
if ( $(document.activeElement).closest('tr')[0] !== $filterRow[0] ) {
|
756
|
+
// don't hide row if any filter has a value
|
757
|
+
if (ts.getFilters(table).join('') === '') {
|
758
|
+
$filterRow.addClass('hideme');
|
659
759
|
}
|
660
|
-
} else {
|
661
|
-
t = $('<input type="search">').appendTo( c.$filters.eq(i) );
|
662
|
-
}
|
663
|
-
if (t) {
|
664
|
-
t.attr('placeholder', $th.data('placeholder') || $th.attr('data-placeholder') || '');
|
665
|
-
}
|
666
|
-
}
|
667
|
-
if (t) {
|
668
|
-
t.addClass('tablesorter-filter ' + wo.filter_cssFilter).attr('data-column', i);
|
669
|
-
if (dis) {
|
670
|
-
t.addClass('disabled')[0].disabled = true; // disabled!
|
671
760
|
}
|
672
761
|
}
|
673
|
-
}
|
674
|
-
}
|
675
|
-
$t
|
676
|
-
.bind('addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search '.split(' ').join('.tsfilter '), function(e, filter){
|
677
|
-
if (!/(search|filterReset|filterEnd)/.test(e.type)){
|
678
|
-
e.stopPropagation();
|
679
|
-
buildDefault(true);
|
680
|
-
}
|
681
|
-
if (e.type === 'filterReset') {
|
682
|
-
searching([]);
|
683
|
-
}
|
684
|
-
if (e.type === 'filterEnd') {
|
685
|
-
buildDefault(true);
|
686
|
-
} else {
|
687
|
-
// send false argument to force a new search; otherwise if the filter hasn't changed, it will return
|
688
|
-
filter = e.type === 'search' ? filter : e.type === 'updateComplete' ? $t.data('lastSearch') : '';
|
689
|
-
searching(filter);
|
690
|
-
}
|
691
|
-
return false;
|
762
|
+
}, 200);
|
692
763
|
})
|
693
|
-
.find('input
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
764
|
+
.find('input, select').bind('focus blur', function(e) {
|
765
|
+
$filterRow2 = $(this).closest('tr');
|
766
|
+
clearTimeout(timer);
|
767
|
+
var event = e;
|
768
|
+
timer = setTimeout(function() {
|
769
|
+
// don't hide row if any filter has a value
|
770
|
+
if (ts.getFilters(table).join('') === '') {
|
771
|
+
$filterRow2[ event.type === 'focus' ? 'removeClass' : 'addClass']('hideme');
|
772
|
+
}
|
773
|
+
}, 200);
|
703
774
|
});
|
704
|
-
|
775
|
+
},
|
776
|
+
findRows: function(table, filters, combinedFilters) {
|
777
|
+
var cached, len, $rows, rowIndex, tbodyIndex, $tbody, $cells, columnIndex,
|
778
|
+
childRow, childRowText, exact, iExact, iFilter, lastSearch, matches, result,
|
779
|
+
searchFiltered, filterMatched, showRow, time,
|
780
|
+
c = table.config,
|
781
|
+
wo = c.widgetOptions,
|
782
|
+
columns = c.columns,
|
783
|
+
$tbodies = c.$tbodies,
|
784
|
+
// anyMatch really screws up with these types of filters
|
785
|
+
anyMatchNotAllowedTypes = [ 'range', 'operators' ],
|
705
786
|
// parse columns after formatter, in case the class is added at that point
|
706
|
-
parsed =
|
707
|
-
return (ts.getData) ?
|
787
|
+
parsed = c.$headers.map(function(columnIndex) {
|
788
|
+
return (ts.getData) ?
|
789
|
+
ts.getData(c.$headers.filter('[data-column="' + columnIndex + '"]:last'), c.headers[columnIndex], 'filter') === 'parsed' :
|
790
|
+
$(this).hasClass('filter-parsed');
|
708
791
|
}).get();
|
709
|
-
|
710
|
-
|
711
|
-
if (
|
712
|
-
|
713
|
-
|
792
|
+
if (c.debug) { time = new Date(); }
|
793
|
+
for (tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) {
|
794
|
+
if ($tbodies.eq(tbodyIndex).hasClass(ts.css.info)) { continue; } // ignore info blocks, issue #264
|
795
|
+
$tbody = ts.processTbody(table, $tbodies.eq(tbodyIndex), true);
|
796
|
+
$rows = $tbody.children('tr').not('.' + c.cssChildRow);
|
797
|
+
len = $rows.length;
|
798
|
+
if (combinedFilters === '' || wo.filter_serversideFiltering) {
|
799
|
+
$tbody.children().show().removeClass(wo.filter_filteredRow);
|
800
|
+
} else {
|
801
|
+
// optimize searching only through already filtered rows - see #313
|
802
|
+
searchFiltered = true;
|
803
|
+
lastSearch = c.lastSearch || c.$table.data('lastSearch') || [];
|
804
|
+
$.each(filters, function(indx, val) {
|
805
|
+
// check for changes from beginning of filter; but ignore if there is a logical "or" in the string
|
806
|
+
searchFiltered = (val || '').indexOf(lastSearch[indx] || '') === 0 && searchFiltered && !/(\s+or\s+|\|)/g.test(val || '');
|
714
807
|
});
|
715
|
-
|
716
|
-
|
717
|
-
//
|
718
|
-
for (
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
808
|
+
// can't search when all rows are hidden - this happens when looking for exact matches
|
809
|
+
if (searchFiltered && $rows.filter(':visible').length === 0) { searchFiltered = false; }
|
810
|
+
// loop through the rows
|
811
|
+
for (rowIndex = 0; rowIndex < len; rowIndex++) {
|
812
|
+
childRow = $rows[rowIndex].className;
|
813
|
+
// skip child rows & already filtered rows
|
814
|
+
if ( ts.filter.regex.child.test(childRow) || (searchFiltered && ts.filter.regex.filtered.test(childRow)) ) { continue; }
|
815
|
+
showRow = true;
|
816
|
+
// *** nextAll/nextUntil not supported by Zepto! ***
|
817
|
+
childRow = $rows.eq(rowIndex).nextUntil('tr:not(.' + c.cssChildRow + ')');
|
818
|
+
// so, if "table.config.widgetOptions.filter_childRows" is true and there is
|
819
|
+
// a match anywhere in the child row, then it will make the row visible
|
820
|
+
// checked here so the option can be changed dynamically
|
821
|
+
childRowText = (childRow.length && wo.filter_childRows) ? childRow.text() : '';
|
822
|
+
childRowText = wo.filter_ignoreCase ? childRowText.toLocaleLowerCase() : childRowText;
|
823
|
+
$cells = $rows.eq(rowIndex).children('td');
|
824
|
+
for (columnIndex = 0; columnIndex < columns; columnIndex++) {
|
825
|
+
// ignore if filter is empty or disabled
|
826
|
+
if (filters[columnIndex] || wo.filter_anyMatch) {
|
827
|
+
cached = c.cache[tbodyIndex].normalized[rowIndex][columnIndex];
|
828
|
+
// check if column data should be from the cell or from parsed data
|
829
|
+
if (wo.filter_useParsedData || parsed[columnIndex]) {
|
830
|
+
exact = cached;
|
831
|
+
} else {
|
832
|
+
// using older or original tablesorter
|
833
|
+
exact = $.trim($cells.eq(columnIndex).text());
|
834
|
+
exact = c.sortLocaleCompare ? ts.replaceAccents(exact) : exact; // issue #405
|
731
835
|
}
|
732
|
-
|
733
|
-
|
734
|
-
}
|
735
|
-
}
|
736
|
-
}
|
737
|
-
// not really updating, but if the column has both the "filter-select" class & filter_functions set to true,
|
738
|
-
// it would append the same options twice.
|
739
|
-
buildDefault(true);
|
836
|
+
iExact = !ts.filter.regex.type.test(typeof exact) && wo.filter_ignoreCase ? exact.toLocaleLowerCase() : exact;
|
837
|
+
result = showRow; // if showRow is true, show that row
|
740
838
|
|
741
|
-
|
742
|
-
|
743
|
-
|
839
|
+
if (typeof filters[columnIndex] === "undefined" || filters[columnIndex] === null) {
|
840
|
+
filters[columnIndex] = wo.filter_anyMatch ? combinedFilters : filters[columnIndex];
|
841
|
+
}
|
744
842
|
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
756
|
-
|
843
|
+
// replace accents - see #357
|
844
|
+
filters[columnIndex] = c.sortLocaleCompare ? ts.replaceAccents(filters[columnIndex]) : filters[columnIndex];
|
845
|
+
// val = case insensitive, filters[columnIndex] = case sensitive
|
846
|
+
iFilter = wo.filter_ignoreCase ? filters[columnIndex].toLocaleLowerCase() : filters[columnIndex];
|
847
|
+
if (wo.filter_functions && wo.filter_functions[columnIndex]) {
|
848
|
+
if (wo.filter_functions[columnIndex] === true) {
|
849
|
+
// default selector; no "filter-select" class
|
850
|
+
result = (c.$headers.filter('[data-column="' + columnIndex + '"]:last').hasClass('filter-match')) ?
|
851
|
+
iExact.search(iFilter) >= 0 : filters[columnIndex] === exact;
|
852
|
+
} else if (typeof wo.filter_functions[columnIndex] === 'function') {
|
853
|
+
// filter callback( exact cell content, parser normalized content, filter input value, column index, jQuery row object )
|
854
|
+
result = wo.filter_functions[columnIndex](exact, cached, filters[columnIndex], columnIndex, $rows.eq(rowIndex));
|
855
|
+
} else if (typeof wo.filter_functions[columnIndex][filters[columnIndex]] === 'function') {
|
856
|
+
// selector option function
|
857
|
+
result = wo.filter_functions[columnIndex][filters[columnIndex]](exact, cached, filters[columnIndex], columnIndex, $rows.eq(rowIndex));
|
858
|
+
}
|
757
859
|
} else {
|
758
|
-
|
759
|
-
//
|
760
|
-
if
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
860
|
+
filterMatched = null;
|
861
|
+
// cycle through the different filters
|
862
|
+
// filters return a boolean or null if nothing matches
|
863
|
+
$.each(ts.filter.types, function(type, typeFunction) {
|
864
|
+
if (!wo.filter_anyMatch || (wo.filter_anyMatch && anyMatchNotAllowedTypes.indexOf(type) < 0)) {
|
865
|
+
matches = typeFunction( filters[columnIndex], iFilter, exact, iExact, cached, columnIndex, table, wo, parsed );
|
866
|
+
if (matches !== null) {
|
867
|
+
filterMatched = matches;
|
868
|
+
return false;
|
869
|
+
}
|
766
870
|
}
|
871
|
+
});
|
872
|
+
if (filterMatched !== null) {
|
873
|
+
result = filterMatched;
|
874
|
+
// Look for match, and add child row data for matching
|
875
|
+
} else {
|
876
|
+
exact = (iExact + childRowText).indexOf(iFilter);
|
877
|
+
result = ( (!wo.filter_startsWith && exact >= 0) || (wo.filter_startsWith && exact === 0) );
|
767
878
|
}
|
768
879
|
}
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
if (ts.getFilters(table).join('') === ''){
|
777
|
-
ft2[ e.type === 'focus' ? 'removeClass' : 'addClass']('hideme');
|
880
|
+
if (wo.filter_anyMatch) {
|
881
|
+
showRow = result;
|
882
|
+
if (showRow){
|
883
|
+
break;
|
884
|
+
}
|
885
|
+
} else {
|
886
|
+
showRow = (result) ? showRow : false;
|
778
887
|
}
|
779
|
-
}
|
780
|
-
}
|
888
|
+
}
|
889
|
+
}
|
890
|
+
$rows[rowIndex].style.display = (showRow ? '' : 'none');
|
891
|
+
$rows.eq(rowIndex)[showRow ? 'removeClass' : 'addClass'](wo.filter_filteredRow);
|
892
|
+
if (childRow.length) {
|
893
|
+
if (c.pager && c.pager.countChildRows || wo.pager_countChildRows) {
|
894
|
+
childRow[showRow ? 'removeClass' : 'addClass'](wo.filter_filteredRow); // see issue #396
|
895
|
+
}
|
896
|
+
childRow.toggle(showRow);
|
897
|
+
}
|
898
|
+
}
|
781
899
|
}
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
900
|
+
ts.processTbody(table, $tbody, false);
|
901
|
+
}
|
902
|
+
c.lastCombinedFilter = combinedFilters; // save last search
|
903
|
+
c.lastSearch = filters;
|
904
|
+
c.$table.data('lastSearch', filters);
|
905
|
+
if (c.debug) {
|
906
|
+
ts.benchmark("Completed filter widget search", time);
|
907
|
+
}
|
908
|
+
c.$table.trigger('applyWidgets'); // make sure zebra widget is applied
|
909
|
+
c.$table.trigger('filterEnd');
|
910
|
+
},
|
911
|
+
buildSelect: function(table, column, updating, onlyavail) {
|
912
|
+
column = parseInt(column, 10);
|
913
|
+
var indx, rowIndex, tbodyIndex, len, currentValue, txt,
|
914
|
+
c = table.config,
|
915
|
+
wo = c.widgetOptions,
|
916
|
+
$tbodies = c.$tbodies,
|
917
|
+
arry = [],
|
918
|
+
node = c.$headers.filter('[data-column="' + column + '"]:last'),
|
919
|
+
// t.data('placeholder') won't work in jQuery older than 1.4.3
|
920
|
+
options = '<option value="">' + ( node.data('placeholder') || node.attr('data-placeholder') || '' ) + '</option>';
|
921
|
+
for (tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) {
|
922
|
+
len = c.cache[tbodyIndex].row.length;
|
923
|
+
// loop through the rows
|
924
|
+
for (rowIndex = 0; rowIndex < len; rowIndex++) {
|
925
|
+
// check if has class filtered
|
926
|
+
if (onlyavail && c.cache[tbodyIndex].row[rowIndex][0].className.match(wo.filter_filteredRow)) { continue; }
|
927
|
+
// get non-normalized cell content
|
928
|
+
if (wo.filter_useParsedData) {
|
929
|
+
arry.push( '' + c.cache[tbodyIndex].normalized[rowIndex][column] );
|
930
|
+
} else {
|
931
|
+
node = c.cache[tbodyIndex].row[rowIndex][0].cells[column];
|
932
|
+
if (node) {
|
933
|
+
arry.push( $.trim( node.textContent || node.innerText || $(node).text() ) );
|
934
|
+
}
|
935
|
+
}
|
791
936
|
}
|
937
|
+
}
|
938
|
+
// get unique elements and sort the list
|
939
|
+
// if $.tablesorter.sortText exists (not in the original tablesorter),
|
940
|
+
// then natural sort the list otherwise use a basic sort
|
941
|
+
arry = $.grep(arry, function(value, indx) {
|
942
|
+
return $.inArray(value, arry) === indx;
|
943
|
+
});
|
944
|
+
arry = (ts.sortNatural) ? arry.sort(function(a, b) { return ts.sortNatural(a, b); }) : arry.sort(true);
|
792
945
|
|
793
|
-
|
794
|
-
|
946
|
+
// Get curent filter value
|
947
|
+
currentValue = c.$table.find('thead').find('select.tablesorter-filter[data-column="' + column + '"]').val();
|
948
|
+
|
949
|
+
// build option list
|
950
|
+
for (indx = 0; indx < arry.length; indx++) {
|
951
|
+
txt = arry[indx].replace(/\"/g, """);
|
952
|
+
// replace quotes - fixes #242 & ignore empty strings - see http://stackoverflow.com/q/14990971/145346
|
953
|
+
options += arry[indx] !== '' ? '<option value="' + txt + '"' + (currentValue === txt ? ' selected="selected"' : '') +
|
954
|
+
'>' + arry[indx] + '</option>' : '';
|
955
|
+
}
|
956
|
+
c.$table.find('thead').find('select.tablesorter-filter[data-column="' + column + '"]')[ updating ? 'html' : 'append' ](options);
|
957
|
+
},
|
958
|
+
buildDefault: function(table, updating) {
|
959
|
+
var columnIndex, $header,
|
960
|
+
c = table.config,
|
961
|
+
wo = c.widgetOptions,
|
962
|
+
columns = c.columns;
|
963
|
+
// build default select dropdown
|
964
|
+
for (columnIndex = 0; columnIndex < columns; columnIndex++) {
|
965
|
+
$header = c.$headers.filter('[data-column="' + columnIndex + '"]:last');
|
966
|
+
// look for the filter-select class; build/update it if found
|
967
|
+
if (($header.hasClass('filter-select') || wo.filter_functions && wo.filter_functions[columnIndex] === true) &&
|
968
|
+
!$header.hasClass('filter-false')) {
|
969
|
+
if (!wo.filter_functions) { wo.filter_functions = {}; }
|
970
|
+
wo.filter_functions[columnIndex] = true; // make sure this select gets processed by filter_functions
|
971
|
+
ts.filter.buildSelect(table, columnIndex, updating, $header.hasClass(wo.filter_onlyAvail));
|
795
972
|
}
|
796
|
-
// add default values
|
797
|
-
$t.bind('tablesorter-initialized', function(){
|
798
|
-
ff = ts.getFilters(table);
|
799
|
-
// ff is undefined when filter_columnFilters = false
|
800
|
-
if (ff) {
|
801
|
-
for (i = 0; i < ff.length; i++) {
|
802
|
-
ff[i] = $ths.filter('[data-column="' + i + '"]:last').attr(wo.filter_defaultAttrib) || ff[i];
|
803
|
-
}
|
804
|
-
ts.setFilters(table, ff, true);
|
805
|
-
}
|
806
|
-
});
|
807
|
-
// filter widget initialized
|
808
|
-
$t.trigger('filterInit');
|
809
|
-
checkFilters();
|
810
973
|
}
|
811
974
|
},
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
.
|
818
|
-
|
819
|
-
.
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
$tb.children().removeClass(wo.filter_filteredRow).show();
|
824
|
-
ts.processTbody(table, $tb, false); // restore tbody
|
975
|
+
searching: function(table, filter, external) {
|
976
|
+
if (typeof filter === 'undefined' || filter === true || external) {
|
977
|
+
var wo = table.config.widgetOptions;
|
978
|
+
// delay filtering
|
979
|
+
clearTimeout(wo.searchTimer);
|
980
|
+
wo.searchTimer = setTimeout(function() {
|
981
|
+
ts.filter.checkFilters(table, external || filter);
|
982
|
+
}, wo.filter_liveSearch ? wo.filter_searchDelay : 10);
|
983
|
+
} else {
|
984
|
+
// skip delay
|
985
|
+
ts.filter.checkFilters(table, filter);
|
825
986
|
}
|
826
|
-
if (wo.filter_reset) { $(document).undelegate(wo.filter_reset, 'click.tsfilter'); }
|
827
987
|
}
|
828
|
-
}
|
988
|
+
};
|
989
|
+
|
829
990
|
ts.getFilters = function(table) {
|
830
991
|
var c = table ? $(table)[0].config : {};
|
831
|
-
if (c && c.widgetOptions && !c.widgetOptions.filter_columnFilters) {
|
832
|
-
|
992
|
+
if (c && c.widgetOptions && !c.widgetOptions.filter_columnFilters) {
|
993
|
+
// no filter row
|
994
|
+
return $(table).data('lastSearch');
|
995
|
+
}
|
996
|
+
return c && c.$filters ? c.$filters.map(function(indx, el) {
|
833
997
|
return $(el).find('.tablesorter-filter').val() || '';
|
834
998
|
}).get() || [] : false;
|
835
999
|
};
|
1000
|
+
|
836
1001
|
ts.setFilters = function(table, filter, apply) {
|
837
|
-
var $
|
838
|
-
c = $
|
839
|
-
valid = c && c.$filters ? c.$filters.each(function(
|
840
|
-
$(el).find('.tablesorter-filter').val(filter[
|
841
|
-
}) || false : false;
|
842
|
-
if (apply) { $
|
1002
|
+
var $table = $(table),
|
1003
|
+
c = $table.length ? $table[0].config : {},
|
1004
|
+
valid = c && c.$filters ? c.$filters.each(function(indx, el) {
|
1005
|
+
$(el).find('.tablesorter-filter').val(filter[indx] || '');
|
1006
|
+
}).trigger('change.tsfilter') || false : false;
|
1007
|
+
if (apply) { $table.trigger('search', [filter, false]); }
|
843
1008
|
return !!valid;
|
844
1009
|
};
|
845
1010
|
|