jquery-tablesorter 1.4.1 → 1.5.0
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 +7 -0
- data/MIT-LICENSE +1 -1
- data/README.markdown +3 -3
- data/lib/jquery-tablesorter/version.rb +1 -1
- data/vendor/assets/javascripts/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.js +177 -115
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.metadata.js +1 -1
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.js +461 -376
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets-filter-formatter.js +924 -0
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets.js +499 -270
- data/vendor/assets/stylesheets/jquery-tablesorter/filter.formatter.css +183 -0
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.black-ice.css +12 -1
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.blue.css +12 -1
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.bootstrap.css +17 -2
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.dark.css +12 -1
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.default.css +14 -2
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.dropbox.css +19 -9
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.green.css +12 -1
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.grey.css +12 -1
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.ice.css +12 -1
- data/vendor/assets/stylesheets/jquery-tablesorter/theme.jui.css +12 -1
- metadata +55 -56
@@ -1,5 +1,5 @@
|
|
1
1
|
/*!
|
2
|
-
* TableSorter 2.
|
2
|
+
* TableSorter 2.10.8 - 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.10.8";
|
28
28
|
|
29
29
|
ts.parsers = [];
|
30
30
|
ts.widgets = [];
|
@@ -118,6 +118,7 @@
|
|
118
118
|
log(s + " (" + (new Date().getTime() - d.getTime()) + "ms)");
|
119
119
|
}
|
120
120
|
|
121
|
+
ts.log = log;
|
121
122
|
ts.benchmark = benchmark;
|
122
123
|
|
123
124
|
function getElementText(table, node, cellIndex) {
|
@@ -131,9 +132,9 @@
|
|
131
132
|
text = $(node).text();
|
132
133
|
}
|
133
134
|
} else {
|
134
|
-
if (typeof
|
135
|
+
if (typeof t === "function") {
|
135
136
|
text = t(node, table, cellIndex);
|
136
|
-
} else if (typeof
|
137
|
+
} else if (typeof t === "object" && t.hasOwnProperty(cellIndex)) {
|
137
138
|
text = t[cellIndex](node, table, cellIndex);
|
138
139
|
} else {
|
139
140
|
text = c.supportsTextContent ? node.textContent : $(node).text();
|
@@ -143,7 +144,8 @@
|
|
143
144
|
}
|
144
145
|
|
145
146
|
function detectParserForColumn(table, rows, rowIndex, cellIndex) {
|
146
|
-
var
|
147
|
+
var cur,
|
148
|
+
i = ts.parsers.length,
|
147
149
|
node = false,
|
148
150
|
nodeValue = '',
|
149
151
|
keepLooking = true;
|
@@ -153,19 +155,21 @@
|
|
153
155
|
node = rows[rowIndex].cells[cellIndex];
|
154
156
|
nodeValue = getElementText(table, node, cellIndex);
|
155
157
|
if (table.config.debug) {
|
156
|
-
log('Checking if value was empty on row ' + rowIndex + ', column: ' + cellIndex + ': ' + nodeValue);
|
158
|
+
log('Checking if value was empty on row ' + rowIndex + ', column: ' + cellIndex + ': "' + nodeValue + '"');
|
157
159
|
}
|
158
160
|
} else {
|
159
161
|
keepLooking = false;
|
160
162
|
}
|
161
163
|
}
|
162
|
-
|
163
|
-
|
164
|
-
|
164
|
+
while (--i >= 0) {
|
165
|
+
cur = ts.parsers[i];
|
166
|
+
// ignore the default text parser because it will always be true
|
167
|
+
if (cur && cur.id !== 'text' && cur.is && cur.is(nodeValue, table, node)) {
|
168
|
+
return cur;
|
165
169
|
}
|
166
170
|
}
|
167
|
-
//
|
168
|
-
return ts.
|
171
|
+
// nothing found, return the generic parser (text)
|
172
|
+
return ts.getParserById('text');
|
169
173
|
}
|
170
174
|
|
171
175
|
function buildParserCache(table) {
|
@@ -205,7 +209,7 @@
|
|
205
209
|
if (c.debug) {
|
206
210
|
log(parsersDebug);
|
207
211
|
}
|
208
|
-
|
212
|
+
c.parsers = list;
|
209
213
|
}
|
210
214
|
|
211
215
|
/* utils */
|
@@ -252,7 +256,7 @@
|
|
252
256
|
v = parsers[j].format(t, table, c[0].cells[j], j);
|
253
257
|
cols.push(v);
|
254
258
|
if ((parsers[j].type || '').toLowerCase() === "numeric") {
|
255
|
-
colMax[j] = Math.max(Math.abs(v), colMax[j] || 0); // determine column max value (ignore sign)
|
259
|
+
colMax[j] = Math.max(Math.abs(v) || 0, colMax[j] || 0); // determine column max value (ignore sign)
|
256
260
|
}
|
257
261
|
}
|
258
262
|
cols.push(tc.cache[k].normalized.length); // add position for rowCache
|
@@ -283,7 +287,7 @@
|
|
283
287
|
}
|
284
288
|
for (k = 0; k < b.length; k++) {
|
285
289
|
$bk = $(b[k]);
|
286
|
-
if (!$bk.hasClass(c.cssInfoBlock)) {
|
290
|
+
if ($bk.length && !$bk.hasClass(c.cssInfoBlock)) {
|
287
291
|
// get tbody
|
288
292
|
$tb = ts.processTbody(table, $bk, true);
|
289
293
|
r = c2[k].row;
|
@@ -370,13 +374,14 @@
|
|
370
374
|
|
371
375
|
function buildHeaders(table) {
|
372
376
|
var header_index = computeThIndexes(table), ch, $t,
|
373
|
-
h, i, t, lock, time,
|
374
|
-
|
377
|
+
h, i, t, lock, time, c = table.config;
|
378
|
+
c.headerList = [];
|
379
|
+
c.headerContent = [];
|
375
380
|
if (c.debug) {
|
376
381
|
time = new Date();
|
377
382
|
}
|
378
383
|
i = c.cssIcon ? '<i class="' + c.cssIcon + '"></i>' : ''; // add icon if cssIcon option exists
|
379
|
-
|
384
|
+
c.$headers = $(table).find(c.selectorHeaders).each(function(index) {
|
380
385
|
$t = $(this);
|
381
386
|
ch = c.headers[index];
|
382
387
|
c.headerContent[index] = this.innerHTML; // save original header content
|
@@ -393,28 +398,45 @@
|
|
393
398
|
this.column = header_index[this.parentNode.rowIndex + "-" + this.cellIndex];
|
394
399
|
this.order = formatSortingOrder( ts.getData($t, ch, 'sortInitialOrder') || c.sortInitialOrder ) ? [1,0,2] : [0,1,2];
|
395
400
|
this.count = -1; // set to -1 because clicking on the header automatically adds one
|
396
|
-
if (ts.getData($t, ch, 'sorter') === 'false') {
|
397
|
-
this.sortDisabled = true;
|
398
|
-
$t.addClass('sorter-false');
|
399
|
-
} else {
|
400
|
-
$t.removeClass('sorter-false');
|
401
|
-
}
|
402
401
|
this.lockedOrder = false;
|
403
402
|
lock = ts.getData($t, ch, 'lockedOrder') || false;
|
404
|
-
if (typeof
|
403
|
+
if (typeof lock !== 'undefined' && lock !== false) {
|
405
404
|
this.order = this.lockedOrder = formatSortingOrder(lock) ? [1,1,1] : [0,0,0];
|
406
405
|
}
|
407
|
-
$t.addClass(
|
406
|
+
$t.addClass(c.cssHeader);
|
408
407
|
// add cell to headerList
|
409
408
|
c.headerList[index] = this;
|
410
409
|
// add to parent in case there are multiple rows
|
411
410
|
$t.parent().addClass(c.cssHeaderRow);
|
411
|
+
// allow keyboard cursor to focus on element
|
412
|
+
$t.attr("tabindex", 0);
|
412
413
|
});
|
413
|
-
|
414
|
+
// enable/disable sorting
|
415
|
+
updateHeader(table);
|
416
|
+
if (c.debug) {
|
414
417
|
benchmark("Built headers:", time);
|
415
|
-
log(
|
418
|
+
log(c.$headers);
|
416
419
|
}
|
417
|
-
|
420
|
+
}
|
421
|
+
|
422
|
+
function commonUpdate(table, resort, callback) {
|
423
|
+
var c = table.config;
|
424
|
+
// remove rows/elements before update
|
425
|
+
c.$table.find(c.selectorRemove).remove();
|
426
|
+
// rebuild parsers
|
427
|
+
buildParserCache(table);
|
428
|
+
// rebuild the cache map
|
429
|
+
buildCache(table);
|
430
|
+
checkResort(c.$table, resort, callback);
|
431
|
+
}
|
432
|
+
|
433
|
+
function updateHeader(table) {
|
434
|
+
var s, c = table.config;
|
435
|
+
c.$headers.each(function(index, th){
|
436
|
+
s = ts.getData( th, c.headers[index], 'sorter' ) === 'false';
|
437
|
+
th.sortDisabled = s;
|
438
|
+
$(th)[ s ? 'addClass' : 'removeClass' ]('sorter-false');
|
439
|
+
});
|
418
440
|
}
|
419
441
|
|
420
442
|
function setHeadersCss(table) {
|
@@ -449,23 +471,13 @@
|
|
449
471
|
|
450
472
|
// automatically add col group, and column sizes if set
|
451
473
|
function fixColumnWidth(table) {
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
$
|
459
|
-
if (c.widthFixed) {
|
460
|
-
$c.css('width', parseInt(($(this).width()/overallWidth)*1000, 10)/10 + '%');
|
461
|
-
}
|
462
|
-
$cg.append($c);
|
463
|
-
});
|
464
|
-
// replace colgroup contents
|
465
|
-
if ($cgo.length) {
|
466
|
-
$cgo.html( $cg.html() );
|
467
|
-
} else {
|
468
|
-
c.$table.prepend( $cg );
|
474
|
+
if (table.config.widthFixed && $(table).find('colgroup').length === 0) {
|
475
|
+
var colgroup = $('<colgroup>'),
|
476
|
+
overallWidth = $(table).width();
|
477
|
+
$(table.tBodies[0]).find("tr:first").children("td").each(function() {
|
478
|
+
colgroup.append($('<col>').css('width', parseInt(($(this).width()/overallWidth)*1000, 10)/10 + '%'));
|
479
|
+
});
|
480
|
+
$(table).prepend(colgroup);
|
469
481
|
}
|
470
482
|
}
|
471
483
|
|
@@ -490,11 +502,110 @@
|
|
490
502
|
return (parsers && parsers[i]) ? parsers[i].type || '' : '';
|
491
503
|
}
|
492
504
|
|
505
|
+
function initSort(table, cell, e){
|
506
|
+
var a, i, j, o, s,
|
507
|
+
c = table.config,
|
508
|
+
k = !e[c.sortMultiSortKey],
|
509
|
+
$this = $(table);
|
510
|
+
// Only call sortStart if sorting is enabled
|
511
|
+
$this.trigger("sortStart", table);
|
512
|
+
// get current column sort order
|
513
|
+
cell.count = e[c.sortResetKey] ? 2 : (cell.count + 1) % (c.sortReset ? 3 : 2);
|
514
|
+
// reset all sorts on non-current column - issue #30
|
515
|
+
if (c.sortRestart) {
|
516
|
+
i = cell;
|
517
|
+
c.$headers.each(function() {
|
518
|
+
// only reset counts on columns that weren't just clicked on and if not included in a multisort
|
519
|
+
if (this !== i && (k || !$(this).is('.' + c.cssDesc + ',.' + c.cssAsc))) {
|
520
|
+
this.count = -1;
|
521
|
+
}
|
522
|
+
});
|
523
|
+
}
|
524
|
+
// get current column index
|
525
|
+
i = cell.column;
|
526
|
+
// user only wants to sort on one column
|
527
|
+
if (k) {
|
528
|
+
// flush the sort list
|
529
|
+
c.sortList = [];
|
530
|
+
if (c.sortForce !== null) {
|
531
|
+
a = c.sortForce;
|
532
|
+
for (j = 0; j < a.length; j++) {
|
533
|
+
if (a[j][0] !== i) {
|
534
|
+
c.sortList.push(a[j]);
|
535
|
+
}
|
536
|
+
}
|
537
|
+
}
|
538
|
+
// add column to sort list
|
539
|
+
o = cell.order[cell.count];
|
540
|
+
if (o < 2) {
|
541
|
+
c.sortList.push([i, o]);
|
542
|
+
// add other columns if header spans across multiple
|
543
|
+
if (cell.colSpan > 1) {
|
544
|
+
for (j = 1; j < cell.colSpan; j++) {
|
545
|
+
c.sortList.push([i + j, o]);
|
546
|
+
}
|
547
|
+
}
|
548
|
+
}
|
549
|
+
// multi column sorting
|
550
|
+
} else {
|
551
|
+
// get rid of the sortAppend before adding more - fixes issue #115
|
552
|
+
if (c.sortAppend && c.sortList.length > 1) {
|
553
|
+
if (ts.isValueInArray(c.sortAppend[0][0], c.sortList)) {
|
554
|
+
c.sortList.pop();
|
555
|
+
}
|
556
|
+
}
|
557
|
+
// the user has clicked on an already sorted column
|
558
|
+
if (ts.isValueInArray(i, c.sortList)) {
|
559
|
+
// reverse the sorting direction for all tables
|
560
|
+
for (j = 0; j < c.sortList.length; j++) {
|
561
|
+
s = c.sortList[j];
|
562
|
+
o = c.headerList[s[0]];
|
563
|
+
if (s[0] === i) {
|
564
|
+
s[1] = o.order[o.count];
|
565
|
+
if (s[1] === 2) {
|
566
|
+
c.sortList.splice(j,1);
|
567
|
+
o.count = -1;
|
568
|
+
}
|
569
|
+
}
|
570
|
+
}
|
571
|
+
} else {
|
572
|
+
// add column to sort list array
|
573
|
+
o = cell.order[cell.count];
|
574
|
+
if (o < 2) {
|
575
|
+
c.sortList.push([i, o]);
|
576
|
+
// add other columns if header spans across multiple
|
577
|
+
if (cell.colSpan > 1) {
|
578
|
+
for (j = 1; j < cell.colSpan; j++) {
|
579
|
+
c.sortList.push([i + j, o]);
|
580
|
+
}
|
581
|
+
}
|
582
|
+
}
|
583
|
+
}
|
584
|
+
}
|
585
|
+
if (c.sortAppend !== null) {
|
586
|
+
a = c.sortAppend;
|
587
|
+
for (j = 0; j < a.length; j++) {
|
588
|
+
if (a[j][0] !== i) {
|
589
|
+
c.sortList.push(a[j]);
|
590
|
+
}
|
591
|
+
}
|
592
|
+
}
|
593
|
+
// sortBegin event triggered immediately before the sort
|
594
|
+
$this.trigger("sortBegin", table);
|
595
|
+
// setTimeout needed so the processing icon shows up
|
596
|
+
setTimeout(function(){
|
597
|
+
// set css for headers
|
598
|
+
setHeadersCss(table);
|
599
|
+
multisort(table);
|
600
|
+
appendToTable(table);
|
601
|
+
}, 1);
|
602
|
+
}
|
603
|
+
|
493
604
|
// sort multiple columns
|
494
605
|
function multisort(table) { /*jshint loopfunc:true */
|
495
|
-
var
|
606
|
+
var dir = 0, tc = table.config,
|
496
607
|
sortList = tc.sortList, l = sortList.length, bl = table.tBodies.length,
|
497
|
-
sortTime, i,
|
608
|
+
sortTime, i, k, c, colMax, cache, lc, s, order, orgOrderCol;
|
498
609
|
if (tc.serverSideSorting || !tc.cache[0]) { // empty table - fixes #206
|
499
610
|
return;
|
500
611
|
}
|
@@ -537,7 +648,9 @@
|
|
537
648
|
}
|
538
649
|
|
539
650
|
function checkResort($table, flag, callback) {
|
540
|
-
if
|
651
|
+
// don't try to resort if the table is still processing
|
652
|
+
// this will catch spamming of the updateCell method
|
653
|
+
if (flag !== false && !$table[0].isProcessing) {
|
541
654
|
$table.trigger("sorton", [$table[0].config.sortList, function(){
|
542
655
|
resortComplete($table, callback);
|
543
656
|
}]);
|
@@ -546,26 +659,177 @@
|
|
546
659
|
}
|
547
660
|
}
|
548
661
|
|
662
|
+
function bindEvents(table){
|
663
|
+
var c = table.config,
|
664
|
+
$this = c.$table,
|
665
|
+
j, downTime;
|
666
|
+
// apply event handling to headers
|
667
|
+
c.$headers
|
668
|
+
// http://stackoverflow.com/questions/5312849/jquery-find-self;
|
669
|
+
.find(c.selectorSort).add( c.$headers.filter(c.selectorSort) )
|
670
|
+
.unbind('mousedown.tablesorter mouseup.tablesorter sort.tablesorter keypress.tablesorter')
|
671
|
+
.bind('mousedown.tablesorter mouseup.tablesorter sort.tablesorter keypress.tablesorter', function(e, external) {
|
672
|
+
// only recognize left clicks or enter
|
673
|
+
if ( ((e.which || e.button) !== 1 && !/sort|keypress/.test(e.type)) || (e.type === 'keypress' && e.which !== 13) ) {
|
674
|
+
return false;
|
675
|
+
}
|
676
|
+
// ignore long clicks (prevents resizable widget from initializing a sort)
|
677
|
+
if (e.type === 'mouseup' && external !== true && (new Date().getTime() - downTime > 250)) { return false; }
|
678
|
+
// set timer on mousedown
|
679
|
+
if (e.type === 'mousedown') {
|
680
|
+
downTime = new Date().getTime();
|
681
|
+
return e.target.tagName === "INPUT" ? '' : !c.cancelSelection;
|
682
|
+
}
|
683
|
+
if (c.delayInit && !c.cache) { buildCache(table); }
|
684
|
+
// jQuery v1.2.6 doesn't have closest()
|
685
|
+
var $cell = /TH|TD/.test(this.tagName) ? $(this) : $(this).parents('th, td').filter(':first'), cell = $cell[0];
|
686
|
+
if (!cell.sortDisabled) {
|
687
|
+
initSort(table, cell, e);
|
688
|
+
}
|
689
|
+
});
|
690
|
+
if (c.cancelSelection) {
|
691
|
+
// cancel selection
|
692
|
+
c.$headers
|
693
|
+
.attr('unselectable', 'on')
|
694
|
+
.bind('selectstart', false)
|
695
|
+
.css({
|
696
|
+
'user-select': 'none',
|
697
|
+
'MozUserSelect': 'none' // not needed for jQuery 1.8+
|
698
|
+
});
|
699
|
+
}
|
700
|
+
// apply easy methods that trigger bound events
|
701
|
+
$this
|
702
|
+
.unbind('sortReset update updateRows updateCell updateAll addRows sorton appendCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave '.split(' ').join('.tablesorter '))
|
703
|
+
.bind("sortReset.tablesorter", function(e){
|
704
|
+
e.stopPropagation();
|
705
|
+
c.sortList = [];
|
706
|
+
setHeadersCss(table);
|
707
|
+
multisort(table);
|
708
|
+
appendToTable(table);
|
709
|
+
})
|
710
|
+
.bind("updateAll.tablesorter", function(e, resort, callback){
|
711
|
+
e.stopPropagation();
|
712
|
+
ts.refreshWidgets(table, true, true);
|
713
|
+
ts.restoreHeaders(table);
|
714
|
+
buildHeaders(table);
|
715
|
+
bindEvents(table);
|
716
|
+
commonUpdate(table, resort, callback);
|
717
|
+
})
|
718
|
+
.bind("update.tablesorter updateRows.tablesorter", function(e, resort, callback) {
|
719
|
+
e.stopPropagation();
|
720
|
+
// update sorting (if enabled/disabled)
|
721
|
+
updateHeader(table);
|
722
|
+
commonUpdate(table, resort, callback);
|
723
|
+
})
|
724
|
+
.bind("updateCell.tablesorter", function(e, cell, resort, callback) {
|
725
|
+
e.stopPropagation();
|
726
|
+
$this.find(c.selectorRemove).remove();
|
727
|
+
// get position from the dom
|
728
|
+
var l, row, icell,
|
729
|
+
$tb = $this.find('tbody'),
|
730
|
+
// update cache - format: function(s, table, cell, cellIndex)
|
731
|
+
// no closest in jQuery v1.2.6 - tbdy = $tb.index( $(cell).closest('tbody') ),$row = $(cell).closest('tr');
|
732
|
+
tbdy = $tb.index( $(cell).parents('tbody').filter(':first') ),
|
733
|
+
$row = $(cell).parents('tr').filter(':first');
|
734
|
+
cell = $(cell)[0]; // in case cell is a jQuery object
|
735
|
+
// tbody may not exist if update is initialized while tbody is removed for processing
|
736
|
+
if ($tb.length && tbdy >= 0) {
|
737
|
+
row = $tb.eq(tbdy).find('tr').index( $row );
|
738
|
+
icell = cell.cellIndex;
|
739
|
+
l = c.cache[tbdy].normalized[row].length - 1;
|
740
|
+
c.cache[tbdy].row[table.config.cache[tbdy].normalized[row][l]] = $row;
|
741
|
+
c.cache[tbdy].normalized[row][icell] = c.parsers[icell].format( getElementText(table, cell, icell), table, cell, icell );
|
742
|
+
checkResort($this, resort, callback);
|
743
|
+
}
|
744
|
+
})
|
745
|
+
.bind("addRows.tablesorter", function(e, $row, resort, callback) {
|
746
|
+
e.stopPropagation();
|
747
|
+
var i, rows = $row.filter('tr').length,
|
748
|
+
dat = [], l = $row[0].cells.length,
|
749
|
+
tbdy = $this.find('tbody').index( $row.parents('tbody').filter(':first') );
|
750
|
+
// fixes adding rows to an empty table - see issue #179
|
751
|
+
if (!c.parsers) {
|
752
|
+
buildParserCache(table);
|
753
|
+
}
|
754
|
+
// add each row
|
755
|
+
for (i = 0; i < rows; i++) {
|
756
|
+
// add each cell
|
757
|
+
for (j = 0; j < l; j++) {
|
758
|
+
dat[j] = c.parsers[j].format( getElementText(table, $row[i].cells[j], j), table, $row[i].cells[j], j );
|
759
|
+
}
|
760
|
+
// add the row index to the end
|
761
|
+
dat.push(c.cache[tbdy].row.length);
|
762
|
+
// update cache
|
763
|
+
c.cache[tbdy].row.push([$row[i]]);
|
764
|
+
c.cache[tbdy].normalized.push(dat);
|
765
|
+
dat = [];
|
766
|
+
}
|
767
|
+
// resort using current settings
|
768
|
+
checkResort($this, resort, callback);
|
769
|
+
})
|
770
|
+
.bind("sorton.tablesorter", function(e, list, callback, init) {
|
771
|
+
e.stopPropagation();
|
772
|
+
$this.trigger("sortStart", this);
|
773
|
+
// update header count index
|
774
|
+
updateHeaderSortCount(table, list);
|
775
|
+
// set css for headers
|
776
|
+
setHeadersCss(table);
|
777
|
+
$this.trigger("sortBegin", this);
|
778
|
+
// sort the table and append it to the dom
|
779
|
+
multisort(table);
|
780
|
+
appendToTable(table, init);
|
781
|
+
if (typeof callback === "function") {
|
782
|
+
callback(table);
|
783
|
+
}
|
784
|
+
})
|
785
|
+
.bind("appendCache.tablesorter", function(e, callback, init) {
|
786
|
+
e.stopPropagation();
|
787
|
+
appendToTable(table, init);
|
788
|
+
if (typeof callback === "function") {
|
789
|
+
callback(table);
|
790
|
+
}
|
791
|
+
})
|
792
|
+
.bind("applyWidgetId.tablesorter", function(e, id) {
|
793
|
+
e.stopPropagation();
|
794
|
+
ts.getWidgetById(id).format(table, c, c.widgetOptions);
|
795
|
+
})
|
796
|
+
.bind("applyWidgets.tablesorter", function(e, init) {
|
797
|
+
e.stopPropagation();
|
798
|
+
// apply widgets
|
799
|
+
ts.applyWidget(table, init);
|
800
|
+
})
|
801
|
+
.bind("refreshWidgets.tablesorter", function(e, all, dontapply){
|
802
|
+
e.stopPropagation();
|
803
|
+
ts.refreshWidgets(table, all, dontapply);
|
804
|
+
})
|
805
|
+
.bind("destroy.tablesorter", function(e, c, cb){
|
806
|
+
e.stopPropagation();
|
807
|
+
ts.destroy(table, c, cb);
|
808
|
+
});
|
809
|
+
}
|
810
|
+
|
549
811
|
/* public methods */
|
550
812
|
ts.construct = function(settings) {
|
551
813
|
return this.each(function() {
|
552
814
|
// if no thead or tbody, or tablesorter is already present, quit
|
553
815
|
if (!this.tHead || this.tBodies.length === 0 || this.hasInitialized === true) {
|
554
|
-
return (this.config.debug) ? log('stopping initialization! No thead, tbody or tablesorter has already been initialized') : '';
|
816
|
+
return (this.config && this.config.debug) ? log('stopping initialization! No thead, tbody or tablesorter has already been initialized') : '';
|
555
817
|
}
|
556
818
|
// declare
|
557
|
-
var $
|
558
|
-
c,
|
819
|
+
var $this = $(this), table = this,
|
820
|
+
c, k = '',
|
559
821
|
m = $.metadata;
|
560
822
|
// initialization flag
|
561
|
-
|
823
|
+
table.hasInitialized = false;
|
824
|
+
// table is being processed flag
|
825
|
+
table.isProcessing = true;
|
562
826
|
// new blank config object
|
563
|
-
|
827
|
+
table.config = {};
|
564
828
|
// merge and extend
|
565
|
-
c = $.extend(true,
|
829
|
+
c = $.extend(true, table.config, ts.defaults, settings);
|
566
830
|
// save the settings where they read
|
567
|
-
$.data(
|
568
|
-
if (c.debug) { $.data(
|
831
|
+
$.data(table, "tablesorter", c);
|
832
|
+
if (c.debug) { $.data( table, 'startoveralltimer', new Date()); }
|
569
833
|
// constants
|
570
834
|
c.supportsTextContent = $('<span>x</span>')[0].textContent === 'x';
|
571
835
|
c.supportsDataObject = parseFloat($.fn.jquery) >= 1.4;
|
@@ -578,234 +842,17 @@
|
|
578
842
|
c.$table = $this.addClass(c.tableClass + k);
|
579
843
|
c.$tbodies = $this.children('tbody:not(.' + c.cssInfoBlock + ')');
|
580
844
|
// build headers
|
581
|
-
|
845
|
+
buildHeaders(table);
|
582
846
|
// fixate columns if the users supplies the fixedWidth option
|
583
847
|
// do this after theme has been applied
|
584
|
-
fixColumnWidth(
|
848
|
+
fixColumnWidth(table);
|
585
849
|
// try to auto detect column type, and store in tables config
|
586
|
-
|
850
|
+
buildParserCache(table);
|
587
851
|
// build the cache for the tbody cells
|
588
852
|
// delayInit will delay building the cache until the user starts a sort
|
589
|
-
if (!c.delayInit) { buildCache(
|
590
|
-
//
|
591
|
-
|
592
|
-
c.$headers
|
593
|
-
// http://stackoverflow.com/questions/5312849/jquery-find-self
|
594
|
-
.find('*').andSelf().filter(c.selectorSort)
|
595
|
-
.unbind('mousedown.tablesorter mouseup.tablesorter')
|
596
|
-
.bind('mousedown.tablesorter mouseup.tablesorter', function(e, external) {
|
597
|
-
// jQuery v1.2.6 doesn't have closest()
|
598
|
-
var $cell = this.tagName.match('TH|TD') ? $(this) : $(this).parents('th, td').filter(':last'), cell = $cell[0];
|
599
|
-
// only recognize left clicks
|
600
|
-
if ((e.which || e.button) !== 1) { return false; }
|
601
|
-
// set timer on mousedown
|
602
|
-
if (e.type === 'mousedown') {
|
603
|
-
downTime = new Date().getTime();
|
604
|
-
return e.target.tagName === "INPUT" ? '' : !c.cancelSelection;
|
605
|
-
}
|
606
|
-
// ignore long clicks (prevents resizable widget from initializing a sort)
|
607
|
-
if (external !== true && (new Date().getTime() - downTime > 250)) { return false; }
|
608
|
-
if (c.delayInit && !c.cache) { buildCache($t0); }
|
609
|
-
if (!cell.sortDisabled) {
|
610
|
-
// Only call sortStart if sorting is enabled
|
611
|
-
$this.trigger("sortStart", $t0);
|
612
|
-
// store exp, for speed
|
613
|
-
// $cell = $(this);
|
614
|
-
k = !e[c.sortMultiSortKey];
|
615
|
-
// get current column sort order
|
616
|
-
cell.count = e[c.sortResetKey] ? 2 : (cell.count + 1) % (c.sortReset ? 3 : 2);
|
617
|
-
// reset all sorts on non-current column - issue #30
|
618
|
-
if (c.sortRestart) {
|
619
|
-
i = cell;
|
620
|
-
c.$headers.each(function() {
|
621
|
-
// only reset counts on columns that weren't just clicked on and if not included in a multisort
|
622
|
-
if (this !== i && (k || !$(this).is('.' + c.cssDesc + ',.' + c.cssAsc))) {
|
623
|
-
this.count = -1;
|
624
|
-
}
|
625
|
-
});
|
626
|
-
}
|
627
|
-
// get current column index
|
628
|
-
i = cell.column;
|
629
|
-
// user only wants to sort on one column
|
630
|
-
if (k) {
|
631
|
-
// flush the sort list
|
632
|
-
c.sortList = [];
|
633
|
-
if (c.sortForce !== null) {
|
634
|
-
a = c.sortForce;
|
635
|
-
for (j = 0; j < a.length; j++) {
|
636
|
-
if (a[j][0] !== i) {
|
637
|
-
c.sortList.push(a[j]);
|
638
|
-
}
|
639
|
-
}
|
640
|
-
}
|
641
|
-
// add column to sort list
|
642
|
-
o = cell.order[cell.count];
|
643
|
-
if (o < 2) {
|
644
|
-
c.sortList.push([i, o]);
|
645
|
-
// add other columns if header spans across multiple
|
646
|
-
if (cell.colSpan > 1) {
|
647
|
-
for (j = 1; j < cell.colSpan; j++) {
|
648
|
-
c.sortList.push([i + j, o]);
|
649
|
-
}
|
650
|
-
}
|
651
|
-
}
|
652
|
-
// multi column sorting
|
653
|
-
} else {
|
654
|
-
// get rid of the sortAppend before adding more - fixes issue #115
|
655
|
-
if (c.sortAppend && c.sortList.length > 1) {
|
656
|
-
if (ts.isValueInArray(c.sortAppend[0][0], c.sortList)) {
|
657
|
-
c.sortList.pop();
|
658
|
-
}
|
659
|
-
}
|
660
|
-
// the user has clicked on an already sorted column
|
661
|
-
if (ts.isValueInArray(i, c.sortList)) {
|
662
|
-
// reverse the sorting direction for all tables
|
663
|
-
for (j = 0; j < c.sortList.length; j++) {
|
664
|
-
s = c.sortList[j];
|
665
|
-
o = c.headerList[s[0]];
|
666
|
-
if (s[0] === i) {
|
667
|
-
s[1] = o.order[o.count];
|
668
|
-
if (s[1] === 2) {
|
669
|
-
c.sortList.splice(j,1);
|
670
|
-
o.count = -1;
|
671
|
-
}
|
672
|
-
}
|
673
|
-
}
|
674
|
-
} else {
|
675
|
-
// add column to sort list array
|
676
|
-
o = cell.order[cell.count];
|
677
|
-
if (o < 2) {
|
678
|
-
c.sortList.push([i, o]);
|
679
|
-
// add other columns if header spans across multiple
|
680
|
-
if (cell.colSpan > 1) {
|
681
|
-
for (j = 1; j < cell.colSpan; j++) {
|
682
|
-
c.sortList.push([i + j, o]);
|
683
|
-
}
|
684
|
-
}
|
685
|
-
}
|
686
|
-
}
|
687
|
-
}
|
688
|
-
if (c.sortAppend !== null) {
|
689
|
-
a = c.sortAppend;
|
690
|
-
for (j = 0; j < a.length; j++) {
|
691
|
-
if (a[j][0] !== i) {
|
692
|
-
c.sortList.push(a[j]);
|
693
|
-
}
|
694
|
-
}
|
695
|
-
}
|
696
|
-
// sortBegin event triggered immediately before the sort
|
697
|
-
$this.trigger("sortBegin", $t0);
|
698
|
-
// setTimeout needed so the processing icon shows up
|
699
|
-
setTimeout(function(){
|
700
|
-
// set css for headers
|
701
|
-
setHeadersCss($t0);
|
702
|
-
multisort($t0);
|
703
|
-
appendToTable($t0);
|
704
|
-
}, 1);
|
705
|
-
}
|
706
|
-
});
|
707
|
-
if (c.cancelSelection) {
|
708
|
-
// cancel selection
|
709
|
-
c.$headers.each(function() {
|
710
|
-
this.onselectstart = function() {
|
711
|
-
return false;
|
712
|
-
};
|
713
|
-
});
|
714
|
-
}
|
715
|
-
// apply easy methods that trigger binded events
|
716
|
-
$this
|
717
|
-
.unbind('sortReset update updateCell addRows sorton appendCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave')
|
718
|
-
.bind("sortReset", function(){
|
719
|
-
c.sortList = [];
|
720
|
-
setHeadersCss($t0);
|
721
|
-
multisort($t0);
|
722
|
-
appendToTable($t0);
|
723
|
-
})
|
724
|
-
.bind("update updateRows", function(e, resort, callback) {
|
725
|
-
// remove rows/elements before update
|
726
|
-
$(c.selectorRemove, $t0).remove();
|
727
|
-
// rebuild parsers
|
728
|
-
c.parsers = buildParserCache($t0);
|
729
|
-
// rebuild the cache map
|
730
|
-
buildCache($t0);
|
731
|
-
checkResort($this, resort, callback);
|
732
|
-
})
|
733
|
-
.bind("updateCell", function(e, cell, resort, callback) {
|
734
|
-
// get position from the dom
|
735
|
-
var l, row, icell,
|
736
|
-
$tb = $this.find('tbody'),
|
737
|
-
// update cache - format: function(s, table, cell, cellIndex)
|
738
|
-
// no closest in jQuery v1.2.6 - tbdy = $tb.index( $(cell).closest('tbody') ),$row = $(cell).closest('tr');
|
739
|
-
tbdy = $tb.index( $(cell).parents('tbody').filter(':last') ),
|
740
|
-
$row = $(cell).parents('tr').filter(':last');
|
741
|
-
cell = $(cell)[0]; // in case cell is a jQuery object
|
742
|
-
// tbody may not exist if update is initialized while tbody is removed for processing
|
743
|
-
if ($tb.length && tbdy >= 0) {
|
744
|
-
row = $tb.eq(tbdy).find('tr').index( $row );
|
745
|
-
icell = cell.cellIndex;
|
746
|
-
l = $t0.config.cache[tbdy].normalized[row].length - 1;
|
747
|
-
$t0.config.cache[tbdy].row[$t0.config.cache[tbdy].normalized[row][l]] = $row;
|
748
|
-
$t0.config.cache[tbdy].normalized[row][icell] = c.parsers[icell].format( getElementText($t0, cell, icell), $t0, cell, icell );
|
749
|
-
checkResort($this, resort, callback);
|
750
|
-
}
|
751
|
-
})
|
752
|
-
.bind("addRows", function(e, $row, resort, callback) {
|
753
|
-
var i, rows = $row.filter('tr').length,
|
754
|
-
dat = [], l = $row[0].cells.length,
|
755
|
-
tbdy = $this.find('tbody').index( $row.closest('tbody') );
|
756
|
-
// fixes adding rows to an empty table - see issue #179
|
757
|
-
if (!c.parsers) {
|
758
|
-
c.parsers = buildParserCache($t0);
|
759
|
-
}
|
760
|
-
// add each row
|
761
|
-
for (i = 0; i < rows; i++) {
|
762
|
-
// add each cell
|
763
|
-
for (j = 0; j < l; j++) {
|
764
|
-
dat[j] = c.parsers[j].format( getElementText($t0, $row[i].cells[j], j), $t0, $row[i].cells[j], j );
|
765
|
-
}
|
766
|
-
// add the row index to the end
|
767
|
-
dat.push(c.cache[tbdy].row.length);
|
768
|
-
// update cache
|
769
|
-
c.cache[tbdy].row.push([$row[i]]);
|
770
|
-
c.cache[tbdy].normalized.push(dat);
|
771
|
-
dat = [];
|
772
|
-
}
|
773
|
-
// resort using current settings
|
774
|
-
checkResort($this, resort, callback);
|
775
|
-
})
|
776
|
-
.bind("sorton", function(e, list, callback, init) {
|
777
|
-
$this.trigger("sortStart", this);
|
778
|
-
// update header count index
|
779
|
-
updateHeaderSortCount($t0, list);
|
780
|
-
// set css for headers
|
781
|
-
setHeadersCss($t0);
|
782
|
-
// sort the table and append it to the dom
|
783
|
-
multisort($t0);
|
784
|
-
appendToTable($t0, init);
|
785
|
-
if (typeof callback === "function") {
|
786
|
-
callback($t0);
|
787
|
-
}
|
788
|
-
})
|
789
|
-
.bind("appendCache", function(e, callback, init) {
|
790
|
-
appendToTable($t0, init);
|
791
|
-
if (typeof callback === "function") {
|
792
|
-
callback($t0);
|
793
|
-
}
|
794
|
-
})
|
795
|
-
.bind("applyWidgetId", function(e, id) {
|
796
|
-
ts.getWidgetById(id).format($t0, c, c.widgetOptions);
|
797
|
-
})
|
798
|
-
.bind("applyWidgets", function(e, init) {
|
799
|
-
// apply widgets
|
800
|
-
ts.applyWidget($t0, init);
|
801
|
-
})
|
802
|
-
.bind("refreshWidgets", function(e, all, dontapply){
|
803
|
-
ts.refreshWidgets($t0, all, dontapply);
|
804
|
-
})
|
805
|
-
.bind("destroy", function(e, c, cb){
|
806
|
-
ts.destroy($t0, c, cb);
|
807
|
-
});
|
808
|
-
|
853
|
+
if (!c.delayInit) { buildCache(table); }
|
854
|
+
// bind all header events and methods
|
855
|
+
bindEvents(table);
|
809
856
|
// get sort list from jQuery data or metadata
|
810
857
|
// in jQuery < 1.4, an error occurs when calling $this.data()
|
811
858
|
if (c.supportsDataObject && typeof $this.data().sortlist !== 'undefined') {
|
@@ -814,40 +861,42 @@
|
|
814
861
|
c.sortList = $this.metadata().sortlist;
|
815
862
|
}
|
816
863
|
// apply widget init code
|
817
|
-
ts.applyWidget(
|
864
|
+
ts.applyWidget(table, true);
|
818
865
|
// if user has supplied a sort list to constructor
|
819
866
|
if (c.sortList.length > 0) {
|
820
867
|
$this.trigger("sorton", [c.sortList, {}, !c.initWidgets]);
|
821
868
|
} else if (c.initWidgets) {
|
822
869
|
// apply widget format
|
823
|
-
ts.applyWidget(
|
870
|
+
ts.applyWidget(table);
|
824
871
|
}
|
825
872
|
|
826
873
|
// show processesing icon
|
827
874
|
if (c.showProcessing) {
|
828
875
|
$this
|
829
|
-
.unbind('sortBegin sortEnd')
|
830
|
-
.bind('sortBegin sortEnd', function(e) {
|
831
|
-
ts.isProcessing(
|
876
|
+
.unbind('sortBegin.tablesorter sortEnd.tablesorter')
|
877
|
+
.bind('sortBegin.tablesorter sortEnd.tablesorter', function(e) {
|
878
|
+
ts.isProcessing(table, e.type === 'sortBegin');
|
832
879
|
});
|
833
880
|
}
|
834
881
|
|
835
882
|
// initialized
|
836
|
-
|
883
|
+
table.hasInitialized = true;
|
884
|
+
table.isProcessing = false;
|
837
885
|
if (c.debug) {
|
838
|
-
ts.benchmark("Overall initialization time", $.data(
|
886
|
+
ts.benchmark("Overall initialization time", $.data( table, 'startoveralltimer'));
|
839
887
|
}
|
840
|
-
$this.trigger('tablesorter-initialized',
|
841
|
-
if (typeof c.initialized === 'function') { c.initialized(
|
888
|
+
$this.trigger('tablesorter-initialized', table);
|
889
|
+
if (typeof c.initialized === 'function') { c.initialized(table); }
|
842
890
|
});
|
843
891
|
};
|
844
892
|
|
845
893
|
// *** Process table ***
|
846
894
|
// add processing indicator
|
847
895
|
ts.isProcessing = function(table, toggle, $ths) {
|
848
|
-
|
896
|
+
table = $(table);
|
897
|
+
var c = table[0].config,
|
849
898
|
// default to all headers
|
850
|
-
$h = $ths ||
|
899
|
+
$h = $ths || table.find('.' + c.cssHeader);
|
851
900
|
if (toggle) {
|
852
901
|
if (c.sortList.length > 0) {
|
853
902
|
// get headers from the sortList
|
@@ -865,8 +914,9 @@
|
|
865
914
|
// detach tbody but save the position
|
866
915
|
// don't use tbody because there are portions that look for a tbody index (updateCell)
|
867
916
|
ts.processTbody = function(table, $tb, getIt){
|
868
|
-
var
|
917
|
+
var holdr;
|
869
918
|
if (getIt) {
|
919
|
+
table.isProcessing = true;
|
870
920
|
$tb.before('<span class="tablesorter-savemyplace"/>');
|
871
921
|
holdr = ($.fn.detach) ? $tb.detach() : $tb.remove();
|
872
922
|
return holdr;
|
@@ -874,13 +924,28 @@
|
|
874
924
|
holdr = $(table).find('span.tablesorter-savemyplace');
|
875
925
|
$tb.insertAfter( holdr );
|
876
926
|
holdr.remove();
|
927
|
+
table.isProcessing = false;
|
877
928
|
};
|
878
929
|
|
879
930
|
ts.clearTableBody = function(table) {
|
880
|
-
table.config.$tbodies.empty();
|
931
|
+
$(table)[0].config.$tbodies.empty();
|
932
|
+
};
|
933
|
+
|
934
|
+
// restore headers
|
935
|
+
ts.restoreHeaders = function(table){
|
936
|
+
var c = table.config;
|
937
|
+
// don't use c.$headers here in case header cells were swapped
|
938
|
+
c.$table.find(c.selectorHeaders).each(function(i){
|
939
|
+
// only restore header cells if it is wrapped
|
940
|
+
// because this is also used by the updateAll method
|
941
|
+
if ($(this).find('.tablesorter-header-inner').length){
|
942
|
+
$(this).html( c.headerContent[i] );
|
943
|
+
}
|
944
|
+
});
|
881
945
|
};
|
882
946
|
|
883
947
|
ts.destroy = function(table, removeClasses, callback){
|
948
|
+
table = $(table)[0];
|
884
949
|
if (!table.hasInitialized) { return; }
|
885
950
|
// remove all widgets
|
886
951
|
ts.refreshWidgets(table, true, true);
|
@@ -893,15 +958,12 @@
|
|
893
958
|
// disable tablesorter
|
894
959
|
$t
|
895
960
|
.removeData('tablesorter')
|
896
|
-
.unbind('sortReset update updateCell addRows sorton appendCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave');
|
961
|
+
.unbind('sortReset update updateAll updateRows updateCell addRows sorton appendCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave keypress sortBegin sortEnd '.split(' ').join('.tablesorter '));
|
897
962
|
c.$headers.add($f)
|
898
963
|
.removeClass(c.cssHeader + ' ' + c.cssAsc + ' ' + c.cssDesc)
|
899
964
|
.removeAttr('data-column');
|
900
|
-
$r.find(c.selectorSort).unbind('mousedown.tablesorter mouseup.tablesorter');
|
901
|
-
|
902
|
-
$r.children().each(function(i){
|
903
|
-
$(this).html( c.headerContent[i] );
|
904
|
-
});
|
965
|
+
$r.find(c.selectorSort).unbind('mousedown.tablesorter mouseup.tablesorter keypress.tablesorter');
|
966
|
+
ts.restoreHeaders(table);
|
905
967
|
if (removeClasses !== false) {
|
906
968
|
$t.removeClass(c.tableClass + ' tablesorter-' + c.theme);
|
907
969
|
}
|
@@ -915,7 +977,7 @@
|
|
915
977
|
// *** sort functions ***
|
916
978
|
// regex used in natural sort
|
917
979
|
ts.regex = [
|
918
|
-
/(
|
980
|
+
/(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi, // chunk/tokenize numbers & letters
|
919
981
|
/(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/, //date
|
920
982
|
/^0x[0-9a-f]+$/i // hex
|
921
983
|
];
|
@@ -925,8 +987,8 @@
|
|
925
987
|
if (a === b) { return 0; }
|
926
988
|
var c = table.config, e = c.string[ (c.empties[col] || c.emptyTo ) ],
|
927
989
|
r = ts.regex, xN, xD, yN, yD, xF, yF, i, mx;
|
928
|
-
if (a === '' && e !== 0) { return
|
929
|
-
if (b === '' && e !== 0) { return
|
990
|
+
if (a === '' && e !== 0) { return typeof e === 'boolean' ? (e ? -1 : 1) : -e || -1; }
|
991
|
+
if (b === '' && e !== 0) { return typeof e === 'boolean' ? (e ? 1 : -1) : e || 1; }
|
930
992
|
if (typeof c.textSorter === 'function') { return c.textSorter(a, b, table, col); }
|
931
993
|
// chunk/tokenize
|
932
994
|
xN = a.replace(r[0], '\\0$1\\0').replace(/\\0$/, '').replace(/^\\0/, '').split('\\0');
|
@@ -961,8 +1023,8 @@
|
|
961
1023
|
ts.sortTextDesc = function(table, a, b, col) {
|
962
1024
|
if (a === b) { return 0; }
|
963
1025
|
var c = table.config, e = c.string[ (c.empties[col] || c.emptyTo ) ];
|
964
|
-
if (a === '' && e !== 0) { return
|
965
|
-
if (b === '' && e !== 0) { return
|
1026
|
+
if (a === '' && e !== 0) { return typeof e === 'boolean' ? (e ? -1 : 1) : e || 1; }
|
1027
|
+
if (b === '' && e !== 0) { return typeof e === 'boolean' ? (e ? 1 : -1) : -e || -1; }
|
966
1028
|
if (typeof c.textSorter === 'function') { return c.textSorter(b, a, table, col); }
|
967
1029
|
return ts.sortText(table, b, a);
|
968
1030
|
};
|
@@ -973,7 +1035,7 @@
|
|
973
1035
|
ts.getTextValue = function(a, mx, d) {
|
974
1036
|
if (mx) {
|
975
1037
|
// make sure the text value is greater than the max numerical value (mx)
|
976
|
-
var i, l = a.length, n = mx + d;
|
1038
|
+
var i, l = a ? a.length : 0, n = mx + d;
|
977
1039
|
for (i = 0; i < l; i++) {
|
978
1040
|
n += a.charCodeAt(i);
|
979
1041
|
}
|
@@ -985,8 +1047,8 @@
|
|
985
1047
|
ts.sortNumeric = function(table, a, b, col, mx, d) {
|
986
1048
|
if (a === b) { return 0; }
|
987
1049
|
var c = table.config, e = c.string[ (c.empties[col] || c.emptyTo ) ];
|
988
|
-
if (a === '' && e !== 0) { return
|
989
|
-
if (b === '' && e !== 0) { return
|
1050
|
+
if (a === '' && e !== 0) { return typeof e === 'boolean' ? (e ? -1 : 1) : -e || -1; }
|
1051
|
+
if (b === '' && e !== 0) { return typeof e === 'boolean' ? (e ? 1 : -1) : e || 1; }
|
990
1052
|
if (isNaN(a)) { a = ts.getTextValue(a, mx, d); }
|
991
1053
|
if (isNaN(b)) { b = ts.getTextValue(b, mx, d); }
|
992
1054
|
return a - b;
|
@@ -995,8 +1057,8 @@
|
|
995
1057
|
ts.sortNumericDesc = function(table, a, b, col, mx, d) {
|
996
1058
|
if (a === b) { return 0; }
|
997
1059
|
var c = table.config, e = c.string[ (c.empties[col] || c.emptyTo ) ];
|
998
|
-
if (a === '' && e !== 0) { return
|
999
|
-
if (b === '' && e !== 0) { return
|
1060
|
+
if (a === '' && e !== 0) { return typeof e === 'boolean' ? (e ? -1 : 1) : e || 1; }
|
1061
|
+
if (b === '' && e !== 0) { return typeof e === 'boolean' ? (e ? 1 : -1) : -e || -1; }
|
1000
1062
|
if (isNaN(a)) { a = ts.getTextValue(a, mx, d); }
|
1001
1063
|
if (isNaN(b)) { b = ts.getTextValue(b, mx, d); }
|
1002
1064
|
return b - a;
|
@@ -1089,36 +1151,55 @@
|
|
1089
1151
|
};
|
1090
1152
|
|
1091
1153
|
ts.applyWidget = function(table, init) {
|
1154
|
+
table = $(table)[0]; // in case this is called externally
|
1092
1155
|
var c = table.config,
|
1093
1156
|
wo = c.widgetOptions,
|
1094
|
-
|
1095
|
-
time, i, w,
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
c.widgets.
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
1109
|
-
if (init === true && w.hasOwnProperty('init')) {
|
1110
|
-
w.init(table, w, c, wo);
|
1111
|
-
} else if (!init && w.hasOwnProperty('format')) {
|
1112
|
-
w.format(table, c, wo);
|
1157
|
+
widgets = [],
|
1158
|
+
time, i, w, wd;
|
1159
|
+
if (c.debug) { time = new Date(); }
|
1160
|
+
if (c.widgets.length) {
|
1161
|
+
// ensure unique widget ids
|
1162
|
+
c.widgets = $.grep(c.widgets, function(v, k){
|
1163
|
+
return $.inArray(v, c.widgets) === k;
|
1164
|
+
});
|
1165
|
+
// build widget array & add priority as needed
|
1166
|
+
$.each(c.widgets || [], function(i,n){
|
1167
|
+
wd = ts.getWidgetById(n);
|
1168
|
+
if (wd && wd.id) {
|
1169
|
+
// set priority to 10 if not defined
|
1170
|
+
if (!wd.priority) { wd.priority = 10; }
|
1171
|
+
widgets[i] = wd;
|
1113
1172
|
}
|
1114
|
-
}
|
1173
|
+
});
|
1174
|
+
// sort widgets by priority
|
1175
|
+
widgets.sort(function(a, b){
|
1176
|
+
return a.priority < b.priority ? -1 : a.priority === b.priority ? 0 : 1;
|
1177
|
+
});
|
1178
|
+
|
1179
|
+
// add/update selected widgets
|
1180
|
+
$.each(widgets, function(i,w){
|
1181
|
+
if (w) {
|
1182
|
+
if (init) {
|
1183
|
+
if (w.hasOwnProperty('options')) {
|
1184
|
+
wo = table.config.widgetOptions = $.extend( true, {}, w.options, wo );
|
1185
|
+
}
|
1186
|
+
if (w.hasOwnProperty('init')) {
|
1187
|
+
w.init(table, w, c, wo);
|
1188
|
+
}
|
1189
|
+
} else if (!init && w.hasOwnProperty('format')) {
|
1190
|
+
w.format(table, c, wo, false);
|
1191
|
+
}
|
1192
|
+
}
|
1193
|
+
});
|
1115
1194
|
}
|
1116
1195
|
if (c.debug) {
|
1117
|
-
|
1196
|
+
w = c.widgets.length;
|
1197
|
+
benchmark("Completed " + (init === true ? "initializing " : "applying ") + w + " widget" + (w !== 1 ? "s" : ""), time);
|
1118
1198
|
}
|
1119
1199
|
};
|
1120
1200
|
|
1121
1201
|
ts.refreshWidgets = function(table, doAll, dontapply) {
|
1202
|
+
table = $(table)[0]; // see issue #243
|
1122
1203
|
var i, c = table.config,
|
1123
1204
|
cw = c.widgets,
|
1124
1205
|
w = ts.widgets, l = w.length;
|
@@ -1151,14 +1232,14 @@
|
|
1151
1232
|
} else if (ch && typeof ch[key] !== 'undefined') {
|
1152
1233
|
val += ch[key];
|
1153
1234
|
} else if (cl !== ' ' && cl.match(' ' + key + '-')) {
|
1154
|
-
// include sorter class name "sorter-text", etc
|
1155
|
-
val = cl.match( new RegExp('
|
1235
|
+
// include sorter class name "sorter-text", etc; now works with "sorter-my-custom-parser"
|
1236
|
+
val = cl.match( new RegExp('\\s' + key + '-([\\w-]+)') )[1] || '';
|
1156
1237
|
}
|
1157
1238
|
return $.trim(val);
|
1158
1239
|
};
|
1159
1240
|
|
1160
1241
|
ts.formatFloat = function(s, table) {
|
1161
|
-
if (typeof
|
1242
|
+
if (typeof s !== 'string' || s === '') { return s; }
|
1162
1243
|
// allow using formatFloat without a table; defaults to US number format
|
1163
1244
|
var i,
|
1164
1245
|
t = table && table.config ? table.config.usNumberFormat !== false :
|
@@ -1199,24 +1280,40 @@
|
|
1199
1280
|
// add default parsers
|
1200
1281
|
ts.addParser({
|
1201
1282
|
id: "text",
|
1202
|
-
is: function(
|
1283
|
+
is: function() {
|
1203
1284
|
return true;
|
1204
1285
|
},
|
1205
|
-
format: function(s, table
|
1286
|
+
format: function(s, table) {
|
1206
1287
|
var c = table.config;
|
1207
|
-
|
1208
|
-
|
1288
|
+
if (s) {
|
1289
|
+
s = $.trim( c.ignoreCase ? s.toLocaleLowerCase() : s );
|
1290
|
+
s = c.sortLocaleCompare ? ts.replaceAccents(s) : s;
|
1291
|
+
}
|
1292
|
+
return s;
|
1209
1293
|
},
|
1210
1294
|
type: "text"
|
1211
1295
|
});
|
1212
1296
|
|
1297
|
+
ts.addParser({
|
1298
|
+
id: "digit",
|
1299
|
+
is: function(s) {
|
1300
|
+
return ts.isDigit(s);
|
1301
|
+
},
|
1302
|
+
format: function(s, table) {
|
1303
|
+
var n = ts.formatFloat((s || '').replace(/[^\w,. \-()]/g, ""), table);
|
1304
|
+
return s && typeof n === 'number' ? n : s ? $.trim( s && table.config.ignoreCase ? s.toLocaleLowerCase() : s ) : s;
|
1305
|
+
},
|
1306
|
+
type: "numeric"
|
1307
|
+
});
|
1308
|
+
|
1213
1309
|
ts.addParser({
|
1214
1310
|
id: "currency",
|
1215
1311
|
is: function(s) {
|
1216
|
-
return (/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/).test(s); // £$€¤¥¢
|
1312
|
+
return (/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/).test((s || '').replace(/[,. ]/g,'')); // £$€¤¥¢
|
1217
1313
|
},
|
1218
1314
|
format: function(s, table) {
|
1219
|
-
|
1315
|
+
var n = ts.formatFloat((s || '').replace(/[^\w,. \-()]/g, ""), table);
|
1316
|
+
return s && typeof n === 'number' ? n : s ? $.trim( s && table.config.ignoreCase ? s.toLocaleLowerCase() : s ) : s;
|
1220
1317
|
},
|
1221
1318
|
type: "numeric"
|
1222
1319
|
});
|
@@ -1227,13 +1324,13 @@
|
|
1227
1324
|
return (/^\d{1,3}[\.]\d{1,3}[\.]\d{1,3}[\.]\d{1,3}$/).test(s);
|
1228
1325
|
},
|
1229
1326
|
format: function(s, table) {
|
1230
|
-
var i, a = s.split("."),
|
1327
|
+
var i, a = s ? s.split(".") : '',
|
1231
1328
|
r = "",
|
1232
1329
|
l = a.length;
|
1233
1330
|
for (i = 0; i < l; i++) {
|
1234
1331
|
r += ("00" + a[i]).slice(-3);
|
1235
1332
|
}
|
1236
|
-
return ts.formatFloat(r, table);
|
1333
|
+
return s ? ts.formatFloat(r, table) : s;
|
1237
1334
|
},
|
1238
1335
|
type: "numeric"
|
1239
1336
|
});
|
@@ -1244,7 +1341,7 @@
|
|
1244
1341
|
return (/^(https?|ftp|file):\/\//).test(s);
|
1245
1342
|
},
|
1246
1343
|
format: function(s) {
|
1247
|
-
return $.trim(s.replace(/(https?|ftp|file):\/\//, ''));
|
1344
|
+
return s ? $.trim(s.replace(/(https?|ftp|file):\/\//, '')) : s;
|
1248
1345
|
},
|
1249
1346
|
type: "text"
|
1250
1347
|
});
|
@@ -1255,7 +1352,7 @@
|
|
1255
1352
|
return (/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/).test(s);
|
1256
1353
|
},
|
1257
1354
|
format: function(s, table) {
|
1258
|
-
return ts.formatFloat((s !== "") ? (new Date(s.replace(/-/g, "/")).getTime() || "") : "", table);
|
1355
|
+
return s ? ts.formatFloat((s !== "") ? (new Date(s.replace(/-/g, "/")).getTime() || "") : "", table) : s;
|
1259
1356
|
},
|
1260
1357
|
type: "numeric"
|
1261
1358
|
});
|
@@ -1263,10 +1360,10 @@
|
|
1263
1360
|
ts.addParser({
|
1264
1361
|
id: "percent",
|
1265
1362
|
is: function(s) {
|
1266
|
-
return (/(\d\s
|
1363
|
+
return (/(\d\s*?%|%\s*?\d)/).test(s) && s.length < 15;
|
1267
1364
|
},
|
1268
1365
|
format: function(s, table) {
|
1269
|
-
return ts.formatFloat(s.replace(/%/g, ""), table);
|
1366
|
+
return s ? ts.formatFloat(s.replace(/%/g, ""), table) : s;
|
1270
1367
|
},
|
1271
1368
|
type: "numeric"
|
1272
1369
|
});
|
@@ -1279,7 +1376,7 @@
|
|
1279
1376
|
return (/^[A-Z]{3,10}\.?\s+\d{1,2},?\s+(\d{4})(\s+\d{1,2}:\d{2}(:\d{2})?(\s+[AP]M)?)?$/i).test(s) || (/^\d{1,2}\s+[A-Z]{3,10}\s+\d{4}/i).test(s);
|
1280
1377
|
},
|
1281
1378
|
format: function(s, table) {
|
1282
|
-
return ts.formatFloat( (new Date(s.replace(/(\S)([AP]M)$/i, "$1 $2")).getTime() || ''), table);
|
1379
|
+
return s ? ts.formatFloat( (new Date(s.replace(/(\S)([AP]M)$/i, "$1 $2")).getTime() || ''), table) : s;
|
1283
1380
|
},
|
1284
1381
|
type: "numeric"
|
1285
1382
|
});
|
@@ -1287,25 +1384,23 @@
|
|
1287
1384
|
ts.addParser({
|
1288
1385
|
id: "shortDate", // "mmddyyyy", "ddmmyyyy" or "yyyymmdd"
|
1289
1386
|
is: function(s) {
|
1290
|
-
// testing for
|
1291
|
-
return (
|
1387
|
+
// testing for ##-##-#### or ####-##-##, so it's not perfect; time can be included
|
1388
|
+
return (/(^\d{1,2}[\/\s]\d{1,2}[\/\s]\d{4})|(^\d{4}[\/\s]\d{1,2}[\/\s]\d{1,2})/).test((s || '').replace(/\s+/g," ").replace(/[\-.,]/g, "/"));
|
1292
1389
|
},
|
1293
1390
|
format: function(s, table, cell, cellIndex) {
|
1294
|
-
|
1295
|
-
|
1296
|
-
|
1297
|
-
//
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
1301
|
-
|
1302
|
-
|
1303
|
-
|
1304
|
-
|
1305
|
-
} else if (format === "yyyymmdd") {
|
1306
|
-
s = s.replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/, "$1/$2/$3");
|
1391
|
+
if (s) {
|
1392
|
+
var c = table.config, ci = c.headerList[cellIndex],
|
1393
|
+
format = ci.dateFormat || ts.getData( ci, c.headers[cellIndex], 'dateFormat') || c.dateFormat;
|
1394
|
+
s = s.replace(/\s+/g," ").replace(/[\-.,]/g, "/"); // escaped - because JSHint in Firefox was showing it as an error
|
1395
|
+
if (format === "mmddyyyy") {
|
1396
|
+
s = s.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$3/$1/$2");
|
1397
|
+
} else if (format === "ddmmyyyy") {
|
1398
|
+
s = s.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$3/$2/$1");
|
1399
|
+
} else if (format === "yyyymmdd") {
|
1400
|
+
s = s.replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/, "$1/$2/$3");
|
1401
|
+
}
|
1307
1402
|
}
|
1308
|
-
return ts.formatFloat( (new Date(s).getTime() || ''), table);
|
1403
|
+
return s ? ts.formatFloat( (new Date(s).getTime() || ''), table) : s;
|
1309
1404
|
},
|
1310
1405
|
type: "numeric"
|
1311
1406
|
});
|
@@ -1316,25 +1411,14 @@
|
|
1316
1411
|
return (/^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i).test(s);
|
1317
1412
|
},
|
1318
1413
|
format: function(s, table) {
|
1319
|
-
return ts.formatFloat( (new Date("2000/01/01 " + s.replace(/(\S)([AP]M)$/i, "$1 $2")).getTime() || ""), table);
|
1320
|
-
},
|
1321
|
-
type: "numeric"
|
1322
|
-
});
|
1323
|
-
|
1324
|
-
ts.addParser({
|
1325
|
-
id: "digit",
|
1326
|
-
is: function(s) {
|
1327
|
-
return ts.isDigit(s);
|
1328
|
-
},
|
1329
|
-
format: function(s, table) {
|
1330
|
-
return ts.formatFloat(s.replace(/[^\w,. \-()]/g, ""), table);
|
1414
|
+
return s ? ts.formatFloat( (new Date("2000/01/01 " + s.replace(/(\S)([AP]M)$/i, "$1 $2")).getTime() || ""), table) : s;
|
1331
1415
|
},
|
1332
1416
|
type: "numeric"
|
1333
1417
|
});
|
1334
1418
|
|
1335
1419
|
ts.addParser({
|
1336
1420
|
id: "metadata",
|
1337
|
-
is: function(
|
1421
|
+
is: function() {
|
1338
1422
|
return false;
|
1339
1423
|
},
|
1340
1424
|
format: function(s, table, cell) {
|
@@ -1348,6 +1432,7 @@
|
|
1348
1432
|
// add default widgets
|
1349
1433
|
ts.addWidget({
|
1350
1434
|
id: "zebra",
|
1435
|
+
priority: 90,
|
1351
1436
|
format: function(table, c, wo) {
|
1352
1437
|
var $tb, $tv, $tr, row, even, time, k, l,
|
1353
1438
|
child = new RegExp(c.cssChildRow, 'i'),
|
@@ -1380,7 +1465,7 @@
|
|
1380
1465
|
remove: function(table, c, wo){
|
1381
1466
|
var k, $tb,
|
1382
1467
|
b = c.$tbodies,
|
1383
|
-
rmv = (
|
1468
|
+
rmv = (wo.zebra || [ "even", "odd" ]).join(' ');
|
1384
1469
|
for (k = 0; k < b.length; k++ ){
|
1385
1470
|
$tb = $.tablesorter.processTbody(table, b.eq(k), true); // remove tbody
|
1386
1471
|
$tb.children().removeClass(rmv);
|
@@ -1389,4 +1474,4 @@
|
|
1389
1474
|
}
|
1390
1475
|
});
|
1391
1476
|
|
1392
|
-
})(jQuery);
|
1477
|
+
})(jQuery);
|