jquery-tablesorter 1.10.3 → 1.10.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3456e75e9e3f482d435a7b087e423988098e8a42
4
- data.tar.gz: cc5c3cf899555624f971b133145d3bbe46313706
3
+ metadata.gz: 4e9c4b55e83f583df24a50e72e50dd3193625600
4
+ data.tar.gz: 2242d68bf7499163fd6f4839b673655f703e9df8
5
5
  SHA512:
6
- metadata.gz: 34d92b0bc41faedffd68c7a9e01cb76ff96d325e65286db9d722eb98b7b9a4789c89be0d5df54796d5e0811b3bff97f4bda09ce841cfcd47caa6c895f6d9ef07
7
- data.tar.gz: 93ae0f842b189cc55cd2240f1512ac508b6a53dddc6c6435ea333e16d6fb881a2a3b6c1f006943234fd2e607231e476564e4a41715a90e2f5385e09231ed7793
6
+ metadata.gz: 53eba97a412635392168b9375f97cd76ec45cc0e1c056ad3a07a17bde3fda060724577b03b0b1e923944aa441a674dabc4c37f01c295050819d74a0fd90fb3bf
7
+ data.tar.gz: 702b8fb3e5342484899fa7938e68c4fd1c5be5d9f88c2bd40b8dae7ade36dcb90895c8c2955bd6a0693d501a7e9a50895f2aa3933a5296c54dc604cbb95a4ed5
@@ -4,7 +4,7 @@
4
4
 
5
5
  Simple integration of jquery-tablesorter into the asset pipeline.
6
6
 
7
- Current tablesorter version: 2.15.5 (2/23/2014), [documentation]
7
+ Current tablesorter version: 2.15.6 (3/7/2014), [documentation]
8
8
 
9
9
  Any issue associate with the js/css files, please report to [Mottie's fork].
10
10
 
@@ -25,6 +25,7 @@ Or install it yourself as:
25
25
  ## Requirements
26
26
 
27
27
  Rails 3.1 and higher (tested up to 4.1)
28
+
28
29
  Tested with ruby 1.9.3 - 2.1.0
29
30
 
30
31
  ## Usage
@@ -37,7 +38,7 @@ In your `application.js`
37
38
  //= require jquery-tablesorter
38
39
  ```
39
40
 
40
- This will require all jquery-tablesorter files (exclude addons, widgets, ...).
41
+ This will require all jquery-tablesorter files (excluding addons, widgets, ...).
41
42
 
42
43
  Or you can include single file with:
43
44
 
@@ -48,6 +49,7 @@ Or you can include single file with:
48
49
  //= require jquery-tablesorter/addons/pager/jquery.tablesorter.pager
49
50
  //= require jquery-tablesorter/widgets/widget-repeatheaders
50
51
  //= require jquery-tablesorter/parsers/parser-metric
52
+ //= require jquery-tablesorter/extras/jquery.quicksearch
51
53
  ```
52
54
 
53
55
  ### Stylesheet files
@@ -1,3 +1,3 @@
1
1
  module JqueryTablesorter
2
- VERSION = "1.10.3"
2
+ VERSION = "1.10.4"
3
3
  end
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  * tablesorter pager plugin
3
- * updated 2/22/2014 (v2.15.4)
3
+ * updated 3/7/2014 (v2.15.6)
4
4
  */
5
5
  /*jshint browser:true, jquery:true, unused:false */
6
6
  ;(function($) {
@@ -124,7 +124,7 @@
124
124
  }
125
125
  },
126
126
 
127
- updatePageDisplay = function(table, p, flag) {
127
+ updatePageDisplay = function(table, p, completed) {
128
128
  var i, pg, s, out,
129
129
  c = table.config,
130
130
  f = c.$table.hasClass('hasFilters') && !p.ajaxUrl,
@@ -168,7 +168,7 @@
168
168
  }
169
169
  }
170
170
  pagerArrows(p);
171
- if (p.initialized && flag !== false) {
171
+ if (p.initialized && completed !== false) {
172
172
  c.$table.trigger('pagerComplete', p);
173
173
  // save pager info to storage
174
174
  if (p.savePages && ts.storage) {
@@ -263,6 +263,7 @@
263
263
  exception === 'abort' ? 'Ajax Request aborted' :
264
264
  'Uncaught error: ' + xhr.statusText + ' [' + xhr.status + ']' );
265
265
  c.$tbodies.eq(0).empty();
266
+ p.totalRows = 0;
266
267
  } else {
267
268
  // process ajax object
268
269
  if (!$.isArray(result)) {
@@ -273,7 +274,7 @@
273
274
  } else {
274
275
  // allow [ total, rows, headers ] or [ rows, total, headers ]
275
276
  t = isNaN(result[0]) && !isNaN(result[1]);
276
- //ensure a zero returned row count doesn't fail the logical ||
277
+ // ensure a zero returned row count doesn't fail the logical ||
277
278
  rr_count = result[t ? 1 : 0];
278
279
  p.totalRows = isNaN(rr_count) ? p.totalRows || 0 : rr_count;
279
280
  d = p.totalRows === 0 ? [""] : result[t ? 0 : 1] || []; // row data
@@ -331,7 +332,8 @@
331
332
  }
332
333
  // make sure last pager settings are saved, prevents multiple server side calls with
333
334
  // the same parameters
334
- p.last.totalPages = p.totalPages = Math.ceil( p.totalRows / ( p.size || 10 ) );
335
+ p.totalPages = Math.ceil( p.totalRows / ( p.size || 10 ) );
336
+ p.last.totalRows = p.totalRows;
335
337
  p.last.currentFilters = p.currentFilters;
336
338
  p.last.sortList = (c.sortList || []).join(',');
337
339
  updatePageDisplay(table, p);
@@ -339,10 +341,12 @@
339
341
  $t.trigger('updateCache', [function(){
340
342
  if (p.initialized) {
341
343
  // apply widgets after table has rendered
342
- $t.trigger('applyWidgets');
343
- $t.trigger('pagerChange', p);
344
+ $t
345
+ .trigger('applyWidgets')
346
+ .trigger('pagerChange', p);
344
347
  }
345
348
  }]);
349
+
346
350
  }
347
351
  if (!p.initialized) {
348
352
  p.initialized = true;
@@ -429,6 +433,8 @@
429
433
 
430
434
  renderTable = function(table, rows, p) {
431
435
  var i, $tb,
436
+ $t = $(table),
437
+ c = table.config,
432
438
  l = rows && rows.length || 0, // rows may be undefined
433
439
  s = ( p.page * p.size ),
434
440
  e = ( s + p.size );
@@ -438,7 +444,7 @@
438
444
  moveToLastPage(table, p);
439
445
  }
440
446
  p.isDisabled = false; // needed because sorting will change the page and re-enable the pager
441
- if (p.initialized) { $(table).trigger('pagerChange', p); }
447
+ if (p.initialized) { $t.trigger('pagerChange', p); }
442
448
 
443
449
  if ( !p.removeRows ) {
444
450
  hideRows(table, p);
@@ -447,7 +453,7 @@
447
453
  e = rows.length;
448
454
  }
449
455
  ts.clearTableBody(table);
450
- $tb = ts.processTbody(table, table.config.$tbodies.eq(0), true);
456
+ $tb = ts.processTbody(table, c.$tbodies.eq(0), true);
451
457
  for ( i = s; i < e; i++ ) {
452
458
  $tb.append(rows[i]);
453
459
  }
@@ -456,7 +462,10 @@
456
462
 
457
463
  updatePageDisplay(table, p);
458
464
  if ( !p.isDisabled ) { fixHeight(table, p); }
459
- $(table).trigger('applyWidgets');
465
+ $t.trigger('applyWidgets');
466
+ if (table.isUpdating) {
467
+ $t.trigger("updateComplete", table);
468
+ }
460
469
  },
461
470
 
462
471
  showAllRows = function(table, p){
@@ -484,15 +493,20 @@
484
493
  });
485
494
  },
486
495
 
487
- moveToPage = function(table, p, flag) {
496
+ moveToPage = function(table, p, pageMoved) {
488
497
  if ( p.isDisabled ) { return; }
489
498
  var c = table.config,
499
+ $t = $(table),
490
500
  l = p.last,
491
501
  pg = Math.min( p.totalPages, p.filteredPages );
492
502
  if ( p.page < 0 ) { p.page = 0; }
493
503
  if ( p.page > ( pg - 1 ) && pg !== 0 ) { p.page = pg - 1; }
494
- // don't allow rendering multiple times on the same page/size/totalpages/filters/sorts
495
- if ( l.page === p.page && l.size === p.size && l.totalPages === p.totalPages &&
504
+ // fixes issue where one currentFilter is [] and the other is ['','',''],
505
+ // making the next if comparison think the filters are different (joined by commas). Fixes #202.
506
+ l.currentFilters = (l.currentFilters || []).join('') === '' ? [] : l.currentFilters;
507
+ p.currentFilters = (p.currentFilters || []).join('') === '' ? [] : p.currentFilters;
508
+ // don't allow rendering multiple times on the same page/size/totalRows/filters/sorts
509
+ if ( l.page === p.page && l.size === p.size && l.totalRows === p.totalRows &&
496
510
  (l.currentFilters || []).join(',') === (p.currentFilters || []).join(',') &&
497
511
  l.sortList === (c.sortList || []).join(',') ) { return; }
498
512
  if (c.debug) {
@@ -503,18 +517,22 @@
503
517
  size : p.size,
504
518
  // fixes #408; modify sortList otherwise it auto-updates
505
519
  sortList : (c.sortList || []).join(','),
506
- totalPages : p.totalPages,
520
+ totalRows : p.totalRows,
507
521
  currentFilters : p.currentFilters || []
508
522
  };
509
523
  if (p.ajax) {
510
524
  getAjax(table, p);
511
525
  } else if (!p.ajax) {
512
- renderTable(table, table.config.rowsCopy, p);
526
+ renderTable(table, c.rowsCopy, p);
513
527
  }
514
528
  $.data(table, 'pagerLastPage', p.page);
515
- if (p.initialized && flag !== false) {
516
- c.$table.trigger('pageMoved', p);
517
- c.$table.trigger('applyWidgets');
529
+ if (p.initialized && pageMoved !== false) {
530
+ $t
531
+ .trigger('pageMoved', p)
532
+ .trigger('applyWidgets');
533
+ if (table.isUpdating) {
534
+ $t.trigger('updateComplete');
535
+ }
518
536
  }
519
537
  },
520
538
 
@@ -1,5 +1,5 @@
1
1
  /**!
2
- * TableSorter 2.15.5 - Client-side table sorting with ease!
2
+ * TableSorter 2.15.6 - 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.15.5";
27
+ ts.version = "2.15.6";
28
28
 
29
29
  ts.parsers = [];
30
30
  ts.widgets = [];
@@ -331,7 +331,8 @@
331
331
  // empty table - fixes #206/#346
332
332
  if (isEmptyObject(c2)) {
333
333
  // run pager appender in case the table was just emptied
334
- return c.appender ? c.appender(table, rows) : '';
334
+ return c.appender ? c.appender(table, rows) :
335
+ table.isUpdating ? c.$table.trigger("updateComplete", table) : ''; // Fixes #532
335
336
  }
336
337
  if (c.debug) {
337
338
  appendTime = new Date();
@@ -368,9 +369,9 @@
368
369
  }
369
370
  // apply table widgets; but not before ajax completes
370
371
  if (!init && !c.appender) { ts.applyWidget(table); }
371
- // trigger sortend
372
- $(table).trigger("sortEnd", table);
373
- $(table).trigger("updateComplete", table);
372
+ if (table.isUpdating) {
373
+ c.$table.trigger("updateComplete", table);
374
+ }
374
375
  }
375
376
 
376
377
  // computeTableHeaderCellIndexes from:
@@ -582,92 +583,95 @@
582
583
  return (parsers && parsers[i]) ? parsers[i].type || '' : '';
583
584
  }
584
585
 
585
- function initSort(table, cell, e){
586
- var a, i, j, o, s,
586
+ function initSort(table, cell, event){
587
+ var arry, indx, col, order, s,
587
588
  c = table.config,
588
- k = !e[c.sortMultiSortKey],
589
- $table = $(table);
589
+ key = !event[c.sortMultiSortKey],
590
+ $table = c.$table;
590
591
  // Only call sortStart if sorting is enabled
591
592
  $table.trigger("sortStart", table);
592
593
  // get current column sort order
593
- cell.count = e[c.sortResetKey] ? 2 : (cell.count + 1) % (c.sortReset ? 3 : 2);
594
+ cell.count = event[c.sortResetKey] ? 2 : (cell.count + 1) % (c.sortReset ? 3 : 2);
594
595
  // reset all sorts on non-current column - issue #30
595
596
  if (c.sortRestart) {
596
- i = cell;
597
+ indx = cell;
597
598
  c.$headers.each(function() {
598
599
  // only reset counts on columns that weren't just clicked on and if not included in a multisort
599
- if (this !== i && (k || !$(this).is('.' + ts.css.sortDesc + ',.' + ts.css.sortAsc))) {
600
+ if (this !== indx && (key || !$(this).is('.' + ts.css.sortDesc + ',.' + ts.css.sortAsc))) {
600
601
  this.count = -1;
601
602
  }
602
603
  });
603
604
  }
604
605
  // get current column index
605
- i = cell.column;
606
+ indx = cell.column;
606
607
  // user only wants to sort on one column
607
- if (k) {
608
+ if (key) {
608
609
  // flush the sort list
609
610
  c.sortList = [];
610
611
  if (c.sortForce !== null) {
611
- a = c.sortForce;
612
- for (j = 0; j < a.length; j++) {
613
- if (a[j][0] !== i) {
614
- c.sortList.push(a[j]);
612
+ arry = c.sortForce;
613
+ for (col = 0; col < arry.length; col++) {
614
+ if (arry[col][0] !== indx) {
615
+ c.sortList.push(arry[col]);
615
616
  }
616
617
  }
617
618
  }
618
619
  // add column to sort list
619
- o = cell.order[cell.count];
620
- if (o < 2) {
621
- c.sortList.push([i, o]);
620
+ order = cell.order[cell.count];
621
+ if (order < 2) {
622
+ c.sortList.push([indx, order]);
622
623
  // add other columns if header spans across multiple
623
624
  if (cell.colSpan > 1) {
624
- for (j = 1; j < cell.colSpan; j++) {
625
- c.sortList.push([i + j, o]);
625
+ for (col = 1; col < cell.colSpan; col++) {
626
+ c.sortList.push([indx + col, order]);
626
627
  }
627
628
  }
628
629
  }
629
630
  // multi column sorting
630
631
  } else {
631
- // get rid of the sortAppend before adding more - fixes issue #115
632
+ // get rid of the sortAppend before adding more - fixes issue #115 & #523
632
633
  if (c.sortAppend && c.sortList.length > 1) {
633
- if (ts.isValueInArray(c.sortAppend[0][0], c.sortList)) {
634
- c.sortList.pop();
634
+ for (col = 0; col < c.sortAppend.length; col++) {
635
+ s = ts.isValueInArray(c.sortAppend[col][0], c.sortList);
636
+ if (s >= 0) {
637
+ c.sortList.splice(s,1);
638
+ }
635
639
  }
636
640
  }
637
641
  // the user has clicked on an already sorted column
638
- if (ts.isValueInArray(i, c.sortList)) {
642
+ if (ts.isValueInArray(indx, c.sortList) >= 0) {
639
643
  // reverse the sorting direction
640
- for (j = 0; j < c.sortList.length; j++) {
641
- s = c.sortList[j];
642
- o = c.$headers[s[0]];
643
- if (s[0] === i) {
644
- // o.count seems to be incorrect when compared to cell.count
645
- s[1] = o.order[cell.count];
644
+ for (col = 0; col < c.sortList.length; col++) {
645
+ s = c.sortList[col];
646
+ order = c.$headers[s[0]];
647
+ if (s[0] === indx) {
648
+ // order.count seems to be incorrect when compared to cell.count
649
+ s[1] = order.order[cell.count];
646
650
  if (s[1] === 2) {
647
- c.sortList.splice(j,1);
648
- o.count = -1;
651
+ c.sortList.splice(col,1);
652
+ order.count = -1;
649
653
  }
650
654
  }
651
655
  }
652
656
  } else {
653
657
  // add column to sort list array
654
- o = cell.order[cell.count];
655
- if (o < 2) {
656
- c.sortList.push([i, o]);
658
+ order = cell.order[cell.count];
659
+ if (order < 2) {
660
+ c.sortList.push([indx, order]);
657
661
  // add other columns if header spans across multiple
658
662
  if (cell.colSpan > 1) {
659
- for (j = 1; j < cell.colSpan; j++) {
660
- c.sortList.push([i + j, o]);
663
+ for (col = 1; col < cell.colSpan; col++) {
664
+ c.sortList.push([indx + col, order]);
661
665
  }
662
666
  }
663
667
  }
664
668
  }
665
669
  }
666
670
  if (c.sortAppend !== null) {
667
- a = c.sortAppend;
668
- for (j = 0; j < a.length; j++) {
669
- if (a[j][0] !== i) {
670
- c.sortList.push(a[j]);
671
+ arry = c.sortAppend;
672
+ for (col = 0; col < arry.length; col++) {
673
+ if (arry[col][0] !== indx) {
674
+ c.sortList.push(arry[col]);
671
675
  }
672
676
  }
673
677
  }
@@ -679,6 +683,7 @@
679
683
  setHeadersCss(table);
680
684
  multisort(table);
681
685
  appendToTable(table);
686
+ $table.trigger("sortEnd", table);
682
687
  }, 1);
683
688
  }
684
689
 
@@ -751,8 +756,8 @@
751
756
  }
752
757
 
753
758
  function resortComplete($table, callback){
754
- var c = $table[0].config;
755
- if (c.pager && !c.pager.ajax) {
759
+ var table = $table[0];
760
+ if (table.isUpdating) {
756
761
  $table.trigger('updateComplete');
757
762
  }
758
763
  if (typeof callback === "function") {
@@ -761,12 +766,13 @@
761
766
  }
762
767
 
763
768
  function checkResort($table, flag, callback) {
769
+ var sl = $table[0].config.sortList;
764
770
  // don't try to resort if the table is still processing
765
771
  // this will catch spamming of the updateCell method
766
- if (flag !== false && !$table[0].isProcessing) {
767
- $table.trigger("sorton", [$table[0].config.sortList, function(){
772
+ if (flag !== false && !$table[0].isProcessing && sl.length) {
773
+ $table.trigger("sorton", [sl, function(){
768
774
  resortComplete($table, callback);
769
- }]);
775
+ }, true]);
770
776
  } else {
771
777
  resortComplete($table, callback);
772
778
  }
@@ -777,7 +783,7 @@
777
783
  $table = c.$table;
778
784
  // apply easy methods that trigger bound events
779
785
  $table
780
- .unbind('sortReset update updateRows updateCell updateAll addRows sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave '.split(' ').join('.tablesorter '))
786
+ .unbind('sortReset update updateRows updateCell updateAll addRows updateComplete sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave '.split(' ').join('.tablesorter '))
781
787
  .bind("sortReset.tablesorter", function(e){
782
788
  e.stopPropagation();
783
789
  c.sortList = [];
@@ -787,6 +793,7 @@
787
793
  })
788
794
  .bind("updateAll.tablesorter", function(e, resort, callback){
789
795
  e.stopPropagation();
796
+ table.isUpdating = true;
790
797
  ts.refreshWidgets(table, true, true);
791
798
  ts.restoreHeaders(table);
792
799
  buildHeaders(table);
@@ -796,12 +803,14 @@
796
803
  })
797
804
  .bind("update.tablesorter updateRows.tablesorter", function(e, resort, callback) {
798
805
  e.stopPropagation();
806
+ table.isUpdating = true;
799
807
  // update sorting (if enabled/disabled)
800
808
  updateHeader(table);
801
809
  commonUpdate(table, resort, callback);
802
810
  })
803
811
  .bind("updateCell.tablesorter", function(e, cell, resort, callback) {
804
812
  e.stopPropagation();
813
+ table.isUpdating = true;
805
814
  $table.find(c.selectorRemove).remove();
806
815
  // get position from the dom
807
816
  var l, row, icell,
@@ -823,6 +832,7 @@
823
832
  })
824
833
  .bind("addRows.tablesorter", function(e, $row, resort, callback) {
825
834
  e.stopPropagation();
835
+ table.isUpdating = true;
826
836
  if (isEmptyObject(c.cache)) {
827
837
  // empty table, do an update instead - fixes #450
828
838
  updateHeader(table);
@@ -853,6 +863,9 @@
853
863
  checkResort($table, resort, callback);
854
864
  }
855
865
  })
866
+ .bind("updateComplete.tablesorter", function(){
867
+ table.isUpdating = false;
868
+ })
856
869
  .bind("sorton.tablesorter", function(e, list, callback, init) {
857
870
  var c = table.config;
858
871
  e.stopPropagation();
@@ -867,6 +880,7 @@
867
880
  // sort the table and append it to the dom
868
881
  multisort(table);
869
882
  appendToTable(table, init);
883
+ $table.trigger("sortEnd", this);
870
884
  if (typeof callback === "function") {
871
885
  callback(table);
872
886
  }
@@ -991,7 +1005,7 @@
991
1005
  ts.applyWidget(table, true);
992
1006
  // if user has supplied a sort list to constructor
993
1007
  if (c.sortList.length > 0) {
994
- $table.trigger("sorton", [c.sortList, {}, !c.initWidgets]);
1008
+ $table.trigger("sorton", [c.sortList, {}, !c.initWidgets, true]);
995
1009
  } else {
996
1010
  setHeadersCss(table);
997
1011
  if (c.initWidgets) {
@@ -1032,7 +1046,7 @@
1032
1046
  // get headers from the sortList
1033
1047
  $h = $h.filter(function(){
1034
1048
  // get data-column from attr to keep compatibility with jQuery 1.2.6
1035
- return this.sortDisabled ? false : ts.isValueInArray( parseFloat($(this).attr('data-column')), c.sortList);
1049
+ return this.sortDisabled ? false : ts.isValueInArray( parseFloat($(this).attr('data-column')), c.sortList) >= 0;
1036
1050
  });
1037
1051
  }
1038
1052
  $h.addClass(ts.css.processing + ' ' + c.cssProcessing);
@@ -1132,7 +1146,7 @@
1132
1146
  // disable tablesorter
1133
1147
  $t
1134
1148
  .removeData('tablesorter')
1135
- .unbind('sortReset update updateAll updateRows updateCell addRows sorton appendCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave keypress sortBegin sortEnd '.split(' ').join('.tablesorter '));
1149
+ .unbind('sortReset update updateAll updateRows updateCell addRows updateComplete sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup mouseleave keypress sortBegin sortEnd '.split(' ').join('.tablesorter '));
1136
1150
  c.$headers.add($f)
1137
1151
  .removeClass( [ts.css.header, c.cssHeader, c.cssAsc, c.cssDesc, ts.css.sortAsc, ts.css.sortDesc, ts.css.sortNone].join(' ') )
1138
1152
  .removeAttr('data-column');
@@ -1152,6 +1166,8 @@
1152
1166
  // regex used in natural sort
1153
1167
  ts.regex = {
1154
1168
  chunk : /(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi, // chunk/tokenize numbers & letters
1169
+ schunk: /^\\0/, // start chunk
1170
+ echunk: /\\0$/, // end chunk
1155
1171
  hex: /^0x[0-9a-f]+$/i // hex
1156
1172
  };
1157
1173
 
@@ -1168,8 +1184,8 @@
1168
1184
  if ( xD > yD ) { return 1; }
1169
1185
  }
1170
1186
  // chunk/tokenize
1171
- xN = a.replace(r.chunk, '\\0$1\\0').replace(/\\0$/, '').replace(/^\\0/, '').split('\\0');
1172
- yN = b.replace(r.chunk, '\\0$1\\0').replace(/\\0$/, '').replace(/^\\0/, '').split('\\0');
1187
+ xN = a.replace(r.chunk, '\\0$1\\0').replace(r.echunk, '').replace(r.schunk, '').split('\\0');
1188
+ yN = b.replace(r.chunk, '\\0$1\\0').replace(r.echunk, '').replace(r.schunk, '').split('\\0');
1173
1189
  mx = Math.max(xN.length, yN.length);
1174
1190
  // natural sorting through split numeric strings and default strings
1175
1191
  for (i = 0; i < mx; i++) {
@@ -1291,14 +1307,14 @@
1291
1307
  };
1292
1308
 
1293
1309
  // *** utilities ***
1294
- ts.isValueInArray = function(v, a) {
1295
- var i, l = a.length;
1296
- for (i = 0; i < l; i++) {
1297
- if (a[i][0] === v) {
1298
- return true;
1310
+ ts.isValueInArray = function(column, arry) {
1311
+ var indx, len = arry.length;
1312
+ for (indx = 0; indx < len; indx++) {
1313
+ if (arry[indx][0] === column) {
1314
+ return indx;
1299
1315
  }
1300
1316
  }
1301
- return false;
1317
+ return -1;
1302
1318
  };
1303
1319
 
1304
1320
  ts.addParser = function(parser) {
@@ -1544,7 +1560,7 @@
1544
1560
  return (/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/).test(s);
1545
1561
  },
1546
1562
  format: function(s, table) {
1547
- return s ? ts.formatFloat((s !== "") ? (new Date(s.replace(/-/g, "/")).getTime() || "") : "", table) : s;
1563
+ return s ? ts.formatFloat((s !== "") ? (new Date(s.replace(/-/g, "/")).getTime() || s) : "", table) : s;
1548
1564
  },
1549
1565
  type: "numeric"
1550
1566
  });
@@ -1568,7 +1584,7 @@
1568
1584
  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);
1569
1585
  },
1570
1586
  format: function(s, table) {
1571
- return s ? ts.formatFloat( (new Date(s.replace(/(\S)([AP]M)$/i, "$1 $2")).getTime() || ''), table) : s;
1587
+ return s ? ts.formatFloat( (new Date(s.replace(/(\S)([AP]M)$/i, "$1 $2")).getTime() || s), table) : s;
1572
1588
  },
1573
1589
  type: "numeric"
1574
1590
  });
@@ -1593,7 +1609,7 @@
1593
1609
  s = s.replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/, "$1/$2/$3");
1594
1610
  }
1595
1611
  }
1596
- return s ? ts.formatFloat( (new Date(s).getTime() || ''), table) : s;
1612
+ return s ? ts.formatFloat( (new Date(s).getTime() || s), table) : s;
1597
1613
  },
1598
1614
  type: "numeric"
1599
1615
  });
@@ -1604,7 +1620,7 @@
1604
1620
  return (/^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i).test(s);
1605
1621
  },
1606
1622
  format: function(s, table) {
1607
- return s ? ts.formatFloat( (new Date("2000/01/01 " + s.replace(/(\S)([AP]M)$/i, "$1 $2")).getTime() || ""), table) : s;
1623
+ return s ? ts.formatFloat( (new Date("2000/01/01 " + s.replace(/(\S)([AP]M)$/i, "$1 $2")).getTime() || s), table) : s;
1608
1624
  },
1609
1625
  type: "numeric"
1610
1626
  });
@@ -487,7 +487,7 @@ tsff = ts.filterFormatter = {
487
487
  endOfDay : true,
488
488
  // include ANY jQuery UI spinner options below
489
489
 
490
- defaultDate : '', // ******************************** FIX THIS *******************************************
490
+ defaultDate : '',
491
491
 
492
492
  changeMonth : true,
493
493
  changeYear : true,
@@ -1,4 +1,4 @@
1
- /*! tableSorter 2.8+ widgets - updated 2/21/2014 (v2.15.3)
1
+ /*! tableSorter 2.8+ widgets - updated 3/7/2014 (v2.15.6)
2
2
  *
3
3
  * Column Styles
4
4
  * Column Filters
@@ -654,15 +654,21 @@ ts.filter = {
654
654
  c.$table.trigger('filterInit');
655
655
  },
656
656
  setDefaults: function(table, c, wo) {
657
- var isArray, saved,
657
+ var isArray, saved, indx,
658
658
  // get current (default) filters
659
- filters = ts.getFilters(table);
659
+ filters = ts.getFilters(table) || [];
660
660
  if (wo.filter_saveFilters && ts.storage) {
661
661
  saved = ts.storage( table, 'tablesorter-filters' ) || [];
662
662
  isArray = $.isArray(saved);
663
663
  // make sure we're not just getting an empty array
664
664
  if ( !(isArray && saved.join('') === '' || !isArray) ) { filters = saved; }
665
665
  }
666
+ // if no filters saved, then check default settings
667
+ if (filters.join('') === '') {
668
+ for (indx = 0; indx < c.columns; indx++) {
669
+ filters[indx] = c.$headers.filter('[data-column="' + indx + '"]:last').attr(wo.filter_defaultAttrib) || filters[indx];
670
+ }
671
+ }
666
672
  c.$table.data('lastSearch', filters);
667
673
  return filters;
668
674
  },
@@ -1010,6 +1016,7 @@ ts.filter = {
1010
1016
  c.$table.trigger('filterEnd');
1011
1017
  },
1012
1018
  buildSelect: function(table, column, updating, onlyavail) {
1019
+ if (!table.config.cache || $.isEmptyObject(table.config.cache)) { return; }
1013
1020
  column = parseInt(column, 10);
1014
1021
  var indx, rowIndex, tbodyIndex, len, currentValue, txt, $filters,
1015
1022
  c = table.config,
@@ -26,7 +26,7 @@
26
26
  if (result[12]) { date.setMilliseconds(Number('0.' + result[12]) * 1000); }
27
27
  return date;
28
28
  }
29
- return 0;
29
+ return s;
30
30
  },
31
31
  type : 'numeric'
32
32
  });
@@ -18,10 +18,10 @@
18
18
  return false;
19
19
  },
20
20
  format: function(s, table) {
21
- var j = -1, c = table.config;
22
- s = c.ignoreCase ? s.toLocaleLowerCase() : s;
21
+ var j = -1, c = table.config,
22
+ n = c.ignoreCase ? s.toLocaleLowerCase() : s;
23
23
  $.each(ts.dates[ 'month' + (c.ignoreCase ? 'Lower' : 'Cased') ], function(i,v){
24
- if (j < 0 && s.match(v)) { j = i; }
24
+ if (j < 0 && n.match(v)) { j = i; }
25
25
  });
26
26
  // return s (original string) if there isn't a match
27
27
  // (non-weekdays will sort separately and empty cells will sort as expected)
@@ -18,12 +18,12 @@
18
18
  });
19
19
 
20
20
  ts.formatDate = function(s, regex, format, table){
21
- s = s
22
- // replace separators
23
- .replace(/\s+/g," ").replace(/[-.,]/g, "/")
24
- // reformat xx/xx/xx to mm/dd/19yy;
25
- .replace(regex, format);
26
- var d = new Date(s),
21
+ var n = s
22
+ // replace separators
23
+ .replace(/\s+/g," ").replace(/[-.,]/g, "/")
24
+ // reformat xx/xx/xx to mm/dd/19yy;
25
+ .replace(regex, format),
26
+ d = new Date(n),
27
27
  y = d.getFullYear(),
28
28
  rng = table && table.config.dateRange || range,
29
29
  now = new Date().getFullYear();
@@ -32,7 +32,7 @@
32
32
  while (now - y > rng) {
33
33
  y += 100;
34
34
  }
35
- return d.setFullYear(y);
35
+ return d.setFullYear(y) || s;
36
36
  };
37
37
 
38
38
  $.tablesorter.addParser({
@@ -36,14 +36,15 @@
36
36
  return false;
37
37
  },
38
38
  format: function(s, table, cell, cellIndex) {
39
- var $c = $(cell).find('input'),
40
- isChecked = $c[0].checked;
39
+ var $c = $(cell),
40
+ $input = $c.find('input[type="checkbox"]'),
41
+ isChecked = $input.length ? $input[0].checked : '';
41
42
  // adding class to row, indicating that a checkbox is checked; includes
42
43
  // a column index in case more than one checkbox happens to be in a row
43
44
  $c.closest('tr').toggleClass('checked-' + cellIndex, isChecked);
44
45
  // returning plain language here because this is what is shown in the
45
46
  // group headers - change it as desired
46
- return $c.length ? isChecked ? 'checked' : 'unchecked' : s;
47
+ return $input.length ? isChecked ? 'checked' : 'unchecked' : s;
47
48
  },
48
49
  parsed : true, // filter widget flag
49
50
  type: "text"
@@ -62,18 +62,21 @@ tsColSel = ts.columnSelector = {
62
62
  var $this = $(this),
63
63
  // if no data-priority is assigned, default to 1, but don't remove it from the selector list
64
64
  priority = $this.attr(wo.columnSelector_priority) || 1,
65
- colId = $this.attr('data-column');
65
+ colId = $this.attr('data-column'),
66
+ state = ts.getData(this, c.headers[colId], 'columnSelector');
67
+
66
68
 
67
69
  // if this column not hidable at all
68
70
  // include getData check (includes "columnSelector-false" class, data attribute, etc)
69
- if ( isNaN(priority) && priority.length > 0 || ts.getData(this, c.headers[colId], 'columnSelector') == 'false' ||
71
+ if ( isNaN(priority) && priority.length > 0 || state === 'disable' ||
70
72
  ( wo.columnSelector_columns[colId] && wo.columnSelector_columns[colId] === 'disable') ) {
71
73
  return true; // goto next
72
74
  }
73
75
 
74
- // set default state
76
+ // set default state; storage takes priority
75
77
  colSel.states[colId] = saved && typeof(saved[colId]) !== 'undefined' ?
76
- saved[colId] : typeof(wo.columnSelector_columns[colId]) !== 'undefined' ? wo.columnSelector_columns[colId] : true;
78
+ saved[colId] : typeof(wo.columnSelector_columns[colId]) !== 'undefined' ?
79
+ wo.columnSelector_columns[colId] : state === 'true' || !(state === 'false');
77
80
  colSel.$column[colId] = $(this);
78
81
 
79
82
  // set default col title
@@ -135,8 +138,8 @@ tsColSel = ts.columnSelector = {
135
138
  c.selector.$popup.find('.tablesorter-column-selector')
136
139
  .html( colSel.$container.html() )
137
140
  .find('input').each(function(){
138
- var indx = $(this).attr('data-column')
139
- $(this).prop( 'checked', indx === 'auto' ? wo.columnSelector_mediaqueryState : colSel.states[indx] )
141
+ var indx = $(this).attr('data-column');
142
+ $(this).prop( 'checked', indx === 'auto' ? wo.columnSelector_mediaqueryState : colSel.states[indx] );
140
143
  });
141
144
  }
142
145
  }).change();
@@ -210,8 +213,8 @@ tsColSel = ts.columnSelector = {
210
213
  },
211
214
 
212
215
  attachTo : function(table, elm) {
216
+ table = $(table)[0];
213
217
  var colSel, wo, indx,
214
- table = $(table)[0],
215
218
  c = table.config,
216
219
  $popup = $(elm);
217
220
  if ($popup.length && c) {
@@ -225,7 +228,7 @@ tsColSel = ts.columnSelector = {
225
228
  .html( colSel.$container.html() )
226
229
  .find('input').each(function(){
227
230
  var indx = $(this).attr('data-column');
228
- $(this).prop( 'checked', indx === 'auto' ? wo.columnSelector_mediaqueryState : colSel.states[indx] )
231
+ $(this).prop( 'checked', indx === 'auto' ? wo.columnSelector_mediaqueryState : colSel.states[indx] );
229
232
  });
230
233
  colSel.$popup = $popup.on('change', 'input', function(){
231
234
  // data input
@@ -1,4 +1,4 @@
1
- /*! tablesorter Grouping widget - updated 12/18/2013 (core v2.15.0)
1
+ /*! tablesorter Grouping widget - updated 3/7/2014 (core v2.15.6)
2
2
  * Requires tablesorter v2.8+ and jQuery 1.7+
3
3
  * by Rob Garrison
4
4
  */
@@ -53,9 +53,10 @@ ts.grouping = {
53
53
 
54
54
  update : function(table, c, wo){
55
55
  if ($.isEmptyObject(c.cache)) { return; }
56
- var rowIndex, tbodyIndex, currentGroup, $rows, groupClass, grouping, time, cache,
56
+ var rowIndex, tbodyIndex, currentGroup, $rows, groupClass, grouping, time, cache, saveName, direction,
57
57
  lang = wo.grouping_language,
58
58
  group = '',
59
+ savedGroup = false,
59
60
  column = c.sortList[0] ? c.sortList[0][0] : -1;
60
61
  c.$table
61
62
  .find('tr.group-hidden').removeClass('group-hidden').end()
@@ -66,19 +67,33 @@ ts.grouping = {
66
67
  }
67
68
  if (column >= 0 && !c.$headers.filter('[data-column="' + column + '"]:last').hasClass('group-false')) {
68
69
  if (c.debug){ time = new Date(); }
70
+ wo.group_currentGroup = ''; // save current groups
71
+ wo.group_currentGroups = {};
72
+
73
+ // group class finds "group-{word/separator/letter/number/date/false}-{optional:#/year/month/day/week/time}"
74
+ groupClass = (c.$headers.filter('[data-column="' + column + '"]:last').attr('class') || '').match(/(group-\w+(-\w+)?)/g);
75
+ // grouping = [ 'group', '{word/separator/letter/number/date/false}', '{#/year/month/day/week/time}' ]
76
+ grouping = groupClass ? groupClass[0].split('-') : ['group','letter',1]; // default to letter 1
77
+
78
+ // save current grouping
79
+ if (wo.group_collapsible && wo.group_saveGroups && ts.storage) {
80
+ wo.group_currentGroups = ts.storage( table, 'tablesorter-groups' ) || {};
81
+ // include direction when grouping numbers > 1 (reversed direction shows different range values)
82
+ direction = (grouping[1] === 'number' && grouping[2] > 1) ? 'dir' + c.sortList[0][1] : '';
83
+ // combine column, sort direction & grouping as save key
84
+ saveName = wo.group_currentGroup = '' + column + direction + grouping.join('');
85
+ if (!wo.group_currentGroups[saveName]) {
86
+ wo.group_currentGroups[saveName] = [];
87
+ } else {
88
+ savedGroup = true;
89
+ }
90
+ }
69
91
  for (tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++) {
70
92
  cache = c.cache[tbodyIndex].normalized;
71
93
  group = ''; // clear grouping across tbodies
72
94
  $rows = c.$tbodies.eq(tbodyIndex).children('tr').not('.' + c.cssChildRow);
73
- if (wo.group_collapsed && wo.group_collapsible) {
74
- $rows.addClass('group-hidden');
75
- }
76
95
  for (rowIndex = 0; rowIndex < $rows.length; rowIndex++) {
77
96
  if ( $rows.eq(rowIndex).is(':visible') ) {
78
- // group class finds "group-{word/separator/letter/number/date/false}-{optional:#/year/month/day/week/time}"
79
- groupClass = (c.$headers.filter('[data-column="' + column + '"]:last').attr('class') || '').match(/(group-\w+(-\w+)?)/g);
80
- // grouping = [ 'group', '{word/separator/letter/number/date/false}', '{#/year/month/day/week/time}' ]
81
- grouping = groupClass ? groupClass[0].split('-') : ['','letter',1]; // default to letter 1
82
97
  // fixes #438
83
98
  if (ts.grouping.types[grouping[1]]) {
84
99
  currentGroup = cache[rowIndex] ?
@@ -95,22 +110,29 @@ ts.grouping = {
95
110
  currentGroup = wo.group_formatter((currentGroup || '').toString(), column, table, c, wo) || currentGroup;
96
111
  }
97
112
  $rows.eq(rowIndex).before('<tr class="group-header ' + c.selectorRemove.slice(1) +
98
- (wo.group_collapsed && wo.group_collapsible ? ' collapsed' : '') + '" unselectable="on"><td colspan="' +
113
+ // (wo.group_collapsed && wo.group_collapsible ? ' collapsed' : '') +
114
+ '" unselectable="on"><td colspan="' +
99
115
  c.columns + '">' + (wo.group_collapsible ? '<i/>' : '') + '<span class="group-name">' +
100
116
  currentGroup + '</span><span class="group-count"></span></td></tr>');
117
+ if (wo.group_saveGroups && !savedGroup && wo.group_collapsed && wo.group_collapsible) {
118
+ // all groups start collapsed
119
+ wo.group_currentGroups[wo.group_currentGroup].push(currentGroup);
120
+ }
101
121
  }
102
122
  }
103
123
  }
104
124
  }
105
125
  }
106
- $rows = c.$table.find('tr.group-header').bind('selectstart', false);
107
- if (wo.group_count || $.isFunction(wo.group_callback)) {
108
- $rows.each(function(){
109
- var $rows,
110
- $row = $(this),
111
- $label = $row.find('.group-count');
126
+ c.$table.find('tr.group-header')
127
+ .bind('selectstart', false)
128
+ .each(function(){
129
+ var isHidden, $label,
130
+ $row = $(this),
131
+ name = $row.find('.group-name').text().toLowerCase(),
132
+ $rows = $row.nextUntil('tr.group-header').filter(':visible');
133
+ if (wo.group_count || $.isFunction(wo.group_callback)) {
134
+ $label = $row.find('.group-count');
112
135
  if ($label.length) {
113
- $rows = $row.nextUntil('tr.group-header').filter(':visible');
114
136
  if (wo.group_count) {
115
137
  $label.html( wo.group_count.replace(/\{num\}/g, $rows.length) );
116
138
  }
@@ -118,13 +140,71 @@ ts.grouping = {
118
140
  wo.group_callback($row.find('td'), $rows, column, table);
119
141
  }
120
142
  }
121
- });
122
- }
143
+ }
144
+ if (wo.group_saveGroups && wo.group_currentGroups[wo.group_currentGroup].length) {
145
+ isHidden = $.inArray( name, wo.group_currentGroups[wo.group_currentGroup] ) > -1;
146
+ $row.toggleClass('collapsed', isHidden);
147
+ $rows.toggleClass('group-hidden', isHidden);
148
+ } else if (wo.group_collapsed && wo.group_collapsible) {
149
+ $row.addClass('collapsed');
150
+ $rows.addClass('group-hidden');
151
+ }
152
+ });
123
153
  c.$table.trigger(wo.group_complete);
124
154
  if (c.debug) {
125
155
  $.tablesorter.benchmark("Applying groups widget: ", time);
126
156
  }
127
157
  }
158
+ },
159
+
160
+ bindEvents : function(table, c, wo){
161
+ if (wo.group_collapsible) {
162
+ wo.group_currentGroups = [];
163
+ // .on() requires jQuery 1.7+
164
+ c.$table.on('click toggleGroup', 'tr.group-header', function(event){
165
+ event.stopPropagation();
166
+ var isCollapsed, $groups, indx,
167
+ $this = $(this),
168
+ name = $this.find('.group-name').text();
169
+ // use shift-click to toggle ALL groups
170
+ if (event.type === 'click' && event.shiftKey) {
171
+ $this.siblings('.group-header').trigger('toggleGroup');
172
+ }
173
+ $this.toggleClass('collapsed');
174
+ // nextUntil requires jQuery 1.4+
175
+ $this.nextUntil('tr.group-header').toggleClass('group-hidden', $this.hasClass('collapsed') );
176
+ // save collapsed groups
177
+ if (wo.group_saveGroups && ts.storage) {
178
+ $groups = c.$table.find('.group-header');
179
+ isCollapsed = $this.hasClass('collapsed');
180
+ if (!wo.group_currentGroups[wo.group_currentGroup]) {
181
+ wo.group_currentGroups[wo.group_currentGroup] = [];
182
+ }
183
+ if (isCollapsed && wo.group_currentGroup) {
184
+ wo.group_currentGroups[wo.group_currentGroup].push( name );
185
+ } else if (wo.group_currentGroup) {
186
+ indx = $.inArray( name, wo.group_currentGroups[wo.group_currentGroup] );
187
+ if (indx > -1) {
188
+ wo.group_currentGroups[wo.group_currentGroup].splice( indx, 1 );
189
+ }
190
+ }
191
+ ts.storage( table, 'tablesorter-groups', wo.group_currentGroups );
192
+ }
193
+ });
194
+ }
195
+ $(wo.group_saveReset).on('click', function(){
196
+ ts.grouping.clearSavedGroups(table);
197
+ });
198
+ c.$table.on('pagerChange.tsgrouping', function(){
199
+ ts.grouping.update(table, c, wo);
200
+ });
201
+ },
202
+
203
+ clearSavedGroups: function(table){
204
+ if (table && ts.storage) {
205
+ ts.storage(table, 'tablesorter-groups', '');
206
+ ts.grouping.update(table, table.config, table.config.widgetOptions);
207
+ }
128
208
  }
129
209
 
130
210
  };
@@ -135,6 +215,8 @@ ts.addWidget({
135
215
  options: {
136
216
  group_collapsible : true, // make the group header clickable and collapse the rows below it.
137
217
  group_collapsed : false, // start with all groups collapsed
218
+ group_saveGroups : true, // remember collapsed groups
219
+ group_saveReset : null, // element to clear saved collapsed groups
138
220
  group_count : ' ({num})', // if not false, the "{num}" string is replaced with the number of rows in the group
139
221
  group_separator : '-', // group name separator; used when group-separator-# class is used.
140
222
  group_formatter : null, // function(txt, column, table, c, wo) { return txt; }
@@ -151,23 +233,7 @@ ts.addWidget({
151
233
  group_dateString : function(date) { return date.toLocaleString(); }
152
234
  },
153
235
  init: function(table, thisWidget, c, wo){
154
- if (wo.group_collapsible) {
155
- // .on() requires jQuery 1.7+
156
- c.$table.on('click toggleGroup', 'tr.group-header', function(event){
157
- event.stopPropagation();
158
- var $this = $(this);
159
- // use shift-click to toggle ALL groups
160
- if (event.type === 'click' && event.shiftKey) {
161
- $this.siblings('.group-header').trigger('toggleGroup');
162
- }
163
- $this.toggleClass('collapsed');
164
- // nextUntil requires jQuery 1.4+
165
- $this.nextUntil('tr.group-header').toggleClass('group-hidden', $this.hasClass('collapsed') );
166
- });
167
- }
168
- c.$table.on('pagerChange', function(){
169
- ts.grouping.update(table, c, wo);
170
- });
236
+ ts.grouping.bindEvents(table, c, wo);
171
237
  },
172
238
  format: function(table, c, wo) {
173
239
  ts.grouping.update(table, c, wo);
@@ -175,6 +241,7 @@ ts.addWidget({
175
241
  remove : function(table, c, wo){
176
242
  c.$table
177
243
  .off('click', 'tr.group-header')
244
+ .off('pagerChange.tsgrouping')
178
245
  .find('.group-hidden').removeClass('group-hidden').end()
179
246
  .find('tr.group-header').remove();
180
247
  }
@@ -0,0 +1,32 @@
1
+ /*! tablesorter headerTitles widget - updated 3/5/2014 (core v2.15.6)
2
+ * Requires tablesorter v2.8+ and jQuery 1.7+
3
+ * by Rob Garrison
4
+ */
5
+ /*jshint browser:true, jquery:true, unused:false */
6
+ /*global jQuery: false */
7
+ ;(function($){
8
+ "use strict";
9
+
10
+ $.tablesorter.addWidget({
11
+ id: 'headerTitles',
12
+ options: {
13
+ headerTitle_prefix : 'Sort: ',
14
+ headerTitle_text : [ 'A - Z', 'Z - A' ],
15
+ headerTitle_numeric : [ '0 - 9', '9 - 0' ]
16
+ },
17
+ format: function (table, c, wo) {
18
+ var txt;
19
+ // clear out all titles
20
+ c.$headers.attr('title', '');
21
+ // only add titles to sorted columns
22
+ $.each(c.sortList, function(indx, group) {
23
+ txt = wo.headerTitle_prefix + wo['headerTitle_' + (c.parsers[ group[0] ].type || 'text')][ group[1] ];
24
+ c.$headers.filter('[data-column="' + group[0] + '"]').attr('title', txt);
25
+ });
26
+ },
27
+ remove: function (table, c) {
28
+ c.$headers.attr('title', '');
29
+ }
30
+ });
31
+
32
+ })(jQuery);
@@ -1,4 +1,4 @@
1
- /* Pager widget (beta) for TableSorter 2/23/2014 (v2.15.5) */
1
+ /* Pager widget (beta) for TableSorter 3/7/2014 (v2.15.6) */
2
2
  /*jshint browser:true, jquery:true, unused:false */
3
3
  ;(function($){
4
4
  "use strict";
@@ -150,7 +150,6 @@ tsp = ts.pager = {
150
150
  // page size selector
151
151
  p.$size = p.$container.find(s.pageSize);
152
152
  p.totalRows = c.$tbodies.eq(0).children().length;
153
-
154
153
  p.oldAjaxSuccess = p.oldAjaxSuccess || wo.pager_ajaxObject.success;
155
154
  c.appender = tsp.appender;
156
155
  if (ts.filter && $.inArray('filter', c.widgets) >= 0) {
@@ -315,7 +314,7 @@ tsp = ts.pager = {
315
314
  }
316
315
  },
317
316
 
318
- updatePageDisplay: function(table, c, flag) {
317
+ updatePageDisplay: function(table, c, completed) {
319
318
  var i, pg, s, out,
320
319
  wo = c.widgetOptions,
321
320
  p = c.pager,
@@ -361,7 +360,7 @@ tsp = ts.pager = {
361
360
  }
362
361
  }
363
362
  tsp.pagerArrows(c);
364
- if (p.initialized && flag !== false) {
363
+ if (p.initialized && completed !== false) {
365
364
  c.$table.trigger('pagerComplete', c);
366
365
  // save pager info to storage
367
366
  if (wo.pager_savePages && ts.storage) {
@@ -453,6 +452,7 @@ tsp = ts.pager = {
453
452
  }
454
453
  ts.showError(table, exception.message + ' (' + xhr.status + ')');
455
454
  c.$tbodies.eq(0).empty();
455
+ p.totalRows = 0;
456
456
  } else {
457
457
  // process ajax object
458
458
  if (!$.isArray(result)) {
@@ -463,7 +463,7 @@ tsp = ts.pager = {
463
463
  } else {
464
464
  // allow [ total, rows, headers ] or [ rows, total, headers ]
465
465
  t = isNaN(result[0]) && !isNaN(result[1]);
466
- //ensure a zero returned row count doesn't fail the logical ||
466
+ // ensure a zero returned row count doesn't fail the logical ||
467
467
  rr_count = result[t ? 1 : 0];
468
468
  p.totalRows = isNaN(rr_count) ? p.totalRows || 0 : rr_count;
469
469
  d = p.totalRows === 0 ? [""] : result[t ? 0 : 1] || []; // row data
@@ -521,7 +521,8 @@ tsp = ts.pager = {
521
521
  }
522
522
  // make sure last pager settings are saved, prevents multiple server side calls with
523
523
  // the same parameters
524
- p.last.totalPages = p.totalPages = Math.ceil( p.totalRows / ( p.size || 10 ) );
524
+ p.totalPages = Math.ceil( p.totalRows / ( p.size || 10 ) );
525
+ p.last.totalRows = p.totalRows;
525
526
  p.last.currentFilters = p.currentFilters;
526
527
  p.last.sortList = (c.sortList || []).join(',');
527
528
  tsp.updatePageDisplay(table, c);
@@ -650,6 +651,9 @@ tsp = ts.pager = {
650
651
  wo.pager_startPage = p.page;
651
652
  wo.pager_size = p.size;
652
653
  c.$table.trigger('applyWidgets');
654
+ if (table.isUpdating) {
655
+ c.$table.trigger('updateComplete');
656
+ }
653
657
 
654
658
  },
655
659
 
@@ -680,15 +684,19 @@ tsp = ts.pager = {
680
684
  });
681
685
  },
682
686
 
683
- moveToPage: function(table, p, flag) {
687
+ moveToPage: function(table, p, pageMoved) {
684
688
  if ( p.isDisabled ) { return; }
685
689
  var c = table.config,
686
690
  l = p.last,
687
691
  pg = Math.min( p.totalPages, p.filteredPages );
688
692
  if ( p.page < 0 ) { p.page = 0; }
689
693
  if ( p.page > ( pg - 1 ) && pg !== 0 ) { p.page = pg - 1; }
690
- // don't allow rendering multiple times on the same page/size/totalpages/filters/sorts
691
- if ( l.page === p.page && l.size === p.size && l.totalPages === p.totalPages &&
694
+ // fixes issue where one current filter is [] and the other is ['','',''],
695
+ // making the next if comparison think the filters as different. Fixes #202.
696
+ l.currentFilters = (l.currentFilters || []).join('') === '' ? [] : l.currentFilters;
697
+ p.currentFilters = (p.currentFilters || []).join('') === '' ? [] : p.currentFilters;
698
+ // don't allow rendering multiple times on the same page/size/totalRows/filters/sorts
699
+ if ( l.page === p.page && l.size === p.size && l.totalRows === p.totalRows &&
692
700
  (l.currentFilters || []).join(',') === (p.currentFilters || []).join(',') &&
693
701
  l.sortList === (c.sortList || []).join(',') ) {
694
702
  return;
@@ -701,7 +709,7 @@ tsp = ts.pager = {
701
709
  size : p.size,
702
710
  // fixes #408; modify sortList otherwise it auto-updates
703
711
  sortList : (c.sortList || []).join(','),
704
- totalPages : p.totalPages,
712
+ totalRows : p.totalRows,
705
713
  currentFilters : p.currentFilters || []
706
714
  };
707
715
  if (p.ajax) {
@@ -710,8 +718,11 @@ tsp = ts.pager = {
710
718
  tsp.renderTable(table, c.rowsCopy);
711
719
  }
712
720
  $.data(table, 'pagerLastPage', p.page);
713
- if (p.initialized && flag !== false) {
721
+ if (p.initialized && pageMoved !== false) {
714
722
  c.$table.trigger('pageMoved', c);
723
+ if (!p.ajax && table.isUpdating) {
724
+ c.$table.trigger('updateComplete');
725
+ }
715
726
  }
716
727
  },
717
728
 
@@ -800,6 +811,8 @@ tsp = ts.pager = {
800
811
  tsp.moveToPage(table, p, true);
801
812
  // update display here in case all rows are removed
802
813
  tsp.updatePageDisplay(table, c, false);
814
+ } else {
815
+ tsp.moveToPage(table, p, true);
803
816
  }
804
817
  }
805
818
 
@@ -41,14 +41,14 @@
41
41
  }
42
42
 
43
43
  /* since bootstrap (table-striped) uses nth-child(), we just use this to add a zebra stripe color */
44
- .tablesorter-bootstrap tr.odd td {
44
+ .tablesorter-bootstrap > tbody > tr.odd > td {
45
45
  background-color: #f9f9f9;
46
46
  }
47
- .tablesorter-bootstrap tbody > .odd:hover > td,
48
- .tablesorter-bootstrap tbody > .even:hover > td {
47
+ .tablesorter-bootstrap > tbody > tr.odd:hover > td,
48
+ .tablesorter-bootstrap > tbody > tr.even:hover > td {
49
49
  background-color: #f5f5f5;
50
50
  }
51
- .tablesorter-bootstrap tr.even td {
51
+ .tablesorter-bootstrap > tbody > tr.even > td {
52
52
  background-color: #fff;
53
53
  }
54
54
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jquery-tablesorter
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.3
4
+ version: 1.10.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jun Lin
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-02-23 00:00:00.000000000 Z
12
+ date: 2014-03-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: railties
@@ -39,7 +39,7 @@ extensions: []
39
39
  extra_rdoc_files: []
40
40
  files:
41
41
  - MIT-LICENSE
42
- - README.markdown
42
+ - README.md
43
43
  - Rakefile
44
44
  - lib/jquery-tablesorter.rb
45
45
  - lib/jquery-tablesorter/engine.rb
@@ -99,6 +99,7 @@ files:
99
99
  - vendor/assets/javascripts/jquery-tablesorter/widgets/widget-cssStickyHeaders.js
100
100
  - vendor/assets/javascripts/jquery-tablesorter/widgets/widget-editable.js
101
101
  - vendor/assets/javascripts/jquery-tablesorter/widgets/widget-grouping.js
102
+ - vendor/assets/javascripts/jquery-tablesorter/widgets/widget-headerTitles.js
102
103
  - vendor/assets/javascripts/jquery-tablesorter/widgets/widget-pager.js
103
104
  - vendor/assets/javascripts/jquery-tablesorter/widgets/widget-repeatheaders.js
104
105
  - vendor/assets/javascripts/jquery-tablesorter/widgets/widget-scroller.js
@@ -135,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
136
  version: '0'
136
137
  requirements: []
137
138
  rubyforge_project:
138
- rubygems_version: 2.2.0.rc.1
139
+ rubygems_version: 2.2.2
139
140
  signing_key:
140
141
  specification_version: 4
141
142
  summary: Simple integration of jquery-tablesorter into the asset pipeline.