jquery-tablesorter 1.17.2 → 1.17.3

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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/jquery-tablesorter/version.rb +1 -1
  4. data/vendor/assets/javascripts/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.js +76 -71
  5. data/vendor/assets/javascripts/jquery-tablesorter/extras/jquery.dragtable.mod.js +1 -1
  6. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.combined.js +2647 -2576
  7. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.js +174 -119
  8. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets.js +2487 -2471
  9. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-extract.js +15 -15
  10. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-iso8601.js +1 -1
  11. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-month.js +4 -4
  12. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-range.js +1 -1
  13. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-two-digit-year.js +12 -12
  14. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-weekday.js +4 -4
  15. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date.js +1 -1
  16. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-duration.js +1 -1
  17. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-feet-inch-fraction.js +6 -6
  18. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-file-type.js +22 -22
  19. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-globalize.js +1 -1
  20. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-ignore-articles.js +15 -15
  21. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-image.js +3 -3
  22. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-input-select.js +10 -3
  23. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-metric.js +2 -2
  24. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-named-numbers.js +3 -3
  25. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-network.js +1 -1
  26. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-roman.js +4 -4
  27. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-alignChar.js +122 -121
  28. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-build-table.js +13 -13
  29. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-chart.js +2 -2
  30. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-columnSelector.js +324 -324
  31. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-columns.js +60 -60
  32. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-editable.js +219 -219
  33. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter-formatter-html5.js +360 -361
  34. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter-formatter-jui.js +666 -666
  35. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter-formatter-select2.js +124 -124
  36. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter-type-insideRange.js +1 -1
  37. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter.js +1448 -1433
  38. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-formatter.js +1 -1
  39. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-grouping.js +213 -213
  40. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-headerTitles.js +3 -3
  41. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-math.js +271 -216
  42. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-output.js +339 -320
  43. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-pager.js +1057 -1045
  44. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-print.js +109 -109
  45. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-reflow.js +114 -115
  46. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-resizable.js +360 -359
  47. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-saveSort.js +59 -59
  48. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-scroller.js +818 -806
  49. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-sort2Hash.js +128 -0
  50. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-sortTbodies.js +195 -195
  51. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-staticRow.js +90 -90
  52. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-stickyHeaders.js +257 -257
  53. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-storage.js +76 -76
  54. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-uitheme.js +170 -170
  55. metadata +3 -3
  56. data/vendor/assets/javascripts/jquery-tablesorter/extras/jquery.quicksearch.js +0 -195
@@ -1,4 +1,4 @@
1
- /*! TableSorter (FORK) v2.22.3 *//*
1
+ /*! TableSorter (FORK) v2.22.4 *//*
2
2
  * Client-side table sorting with ease!
3
3
  * @requires jQuery v1.2.6+
4
4
  *
@@ -26,7 +26,7 @@
26
26
 
27
27
  var ts = this;
28
28
 
29
- ts.version = '2.22.3';
29
+ ts.version = '2.22.4';
30
30
 
31
31
  ts.parsers = [];
32
32
  ts.widgets = [];
@@ -154,24 +154,6 @@
154
154
  // These methods can be applied on table.config instance
155
155
  ts.instanceMethods = {};
156
156
 
157
- /* debuging utils */
158
- function log() {
159
- var a = arguments[0],
160
- s = arguments.length > 1 ? Array.prototype.slice.call(arguments) : a;
161
- if (typeof console !== 'undefined' && typeof console.log !== 'undefined') {
162
- console[ /error/i.test(a) ? 'error' : /warn/i.test(a) ? 'warn' : 'log' ](s);
163
- } else {
164
- alert(s);
165
- }
166
- }
167
-
168
- function benchmark(s, d) {
169
- log(s + ' (' + (new Date().getTime() - d.getTime()) + 'ms)');
170
- }
171
-
172
- ts.log = log;
173
- ts.benchmark = benchmark;
174
-
175
157
  // $.isEmptyObject from jQuery v1.4
176
158
  function isEmptyObject(obj) {
177
159
  /*jshint forin: false */
@@ -188,7 +170,7 @@
188
170
  // node could be a jquery object
189
171
  // http://jsperf.com/jquery-vs-instanceof-jquery/2
190
172
  $node = node.jquery ? node : $(node);
191
- if (typeof(t) === 'string') {
173
+ if (typeof t === 'string') {
192
174
  // check data-attribute first when set to 'basic'; don't use node.innerText - it's really slow!
193
175
  // http://www.kellegous.com/j/2013/02/27/innertext-vs-textcontent/
194
176
  if ( t === 'basic' && typeof ( te = $node.attr(c.textAttribute) ) !== 'undefined' ) {
@@ -196,7 +178,7 @@
196
178
  }
197
179
  return $.trim( node.textContent || $node.text() );
198
180
  } else {
199
- if (typeof(t) === 'function') {
181
+ if (typeof t === 'function') {
200
182
  return $.trim( t($node[0], c.table, cellIndex) );
201
183
  } else if (typeof (te = ts.getColumnData( c.table, t, cellIndex )) === 'function') {
202
184
  return $.trim( te($node[0], c.table, cellIndex) );
@@ -219,7 +201,7 @@
219
201
  nodeValue = ts.getElementText(c, node, cellIndex);
220
202
  $node = $(node);
221
203
  if (c.debug) {
222
- log('Checking if value was empty on row ' + rowIndex + ', column: ' + cellIndex + ': "' + nodeValue + '"');
204
+ console.log('Checking if value was empty on row ' + rowIndex + ', column: ' + cellIndex + ': "' + nodeValue + '"');
223
205
  }
224
206
  } else {
225
207
  keepLooking = false;
@@ -256,7 +238,7 @@
256
238
  // make sure txt is a string (extractor may have converted it)
257
239
  parser.format( '' + txt, c.table, cell, colIndex );
258
240
  if ( c.ignoreCase && typeof val === 'string' ) {
259
- val = val.toLowerCase();
241
+ val = val.toLowerCase();
260
242
  }
261
243
  }
262
244
  return val;
@@ -266,16 +248,16 @@
266
248
  var rows, list, l, i, h, ch, np, p, e, time, tb, len,
267
249
  table = c.table,
268
250
  j = 0,
269
- parsersDebug = '';
251
+ debug = {};
270
252
  // update table bodies in case we start with an empty table
271
253
  c.$tbodies = c.$table.children('tbody:not(.' + c.cssInfoBlock + ')');
272
254
  tb = typeof $tbodies === 'undefined' ? c.$tbodies : $tbodies;
273
255
  len = tb.length;
274
256
  if ( len === 0) {
275
- return c.debug ? log('Warning: *Empty table!* Not building a parser cache') : '';
257
+ return c.debug ? console.warn('Warning: *Empty table!* Not building a parser cache') : '';
276
258
  } else if (c.debug) {
277
259
  time = new Date();
278
- log('Detecting parsers for each column');
260
+ console[ console.group ? 'group' : 'log' ]('Detecting parsers for each column');
279
261
  }
280
262
  list = {
281
263
  extractors: [],
@@ -308,7 +290,12 @@
308
290
  p = detectParserForColumn(c, rows, -1, i);
309
291
  }
310
292
  if (c.debug) {
311
- parsersDebug += 'column:' + i + '; extractor:' + e.id + '; parser:' + p.id + '; string:' + c.strings[i] + '; empty: ' + c.empties[i] + '\n';
293
+ debug[ '(' + i + ') ' + h.text() ] = {
294
+ parser : p.id,
295
+ extractor : e ? e.id : 'none',
296
+ string : c.strings[i],
297
+ empty : c.empties[i]
298
+ };
312
299
  }
313
300
  list.parsers[i] = p;
314
301
  list.extractors[i] = e;
@@ -316,9 +303,14 @@
316
303
  }
317
304
  j += (list.parsers.length) ? len : 1;
318
305
  }
319
- if (c.debug) {
320
- log(parsersDebug ? parsersDebug : 'No parsers detected');
321
- benchmark('Completed detecting parsers', time);
306
+ if ( c.debug ) {
307
+ if ( !isEmptyObject( debug ) ) {
308
+ console[ console.table ? 'table' : 'log' ]( debug );
309
+ } else {
310
+ console.warn( ' No parsers detected!' );
311
+ }
312
+ console.log( 'Completed detecting parsers' + ts.benchmark( time ) );
313
+ if ( console.groupEnd ) { console.groupEnd(); }
322
314
  }
323
315
  c.parsers = list.parsers;
324
316
  c.extractors = list.extractors;
@@ -337,7 +329,7 @@
337
329
  c.totalRows = 0;
338
330
  // if no parsers found, return - it's an empty table.
339
331
  if (!parsers) {
340
- return c.debug ? log('Warning: *Empty table!* Not building a cache') : '';
332
+ return c.debug ? console.warn('Warning: *Empty table!* Not building a cache') : '';
341
333
  }
342
334
  if (c.debug) {
343
335
  cacheTime = new Date();
@@ -390,7 +382,7 @@
390
382
  for ( j = 0; j < c.columns; ++j ) {
391
383
  if (typeof parsers[ j ] === 'undefined') {
392
384
  if ( c.debug ) {
393
- log( 'No parser found for cell:', $row[ 0 ].cells[ j ], 'does it have a header?' );
385
+ console.warn( 'No parser found for cell:', $row[ 0 ].cells[ j ], 'does it have a header?' );
394
386
  }
395
387
  continue;
396
388
  }
@@ -416,7 +408,7 @@
416
408
  ts.isProcessing( table ); // remove processing icon
417
409
  }
418
410
  if ( c.debug ) {
419
- benchmark( 'Building cache for ' + totalRows + ' rows', cacheTime );
411
+ console.log( 'Building cache for ' + totalRows + ' rows' + ts.benchmark( cacheTime ) );
420
412
  }
421
413
  }
422
414
 
@@ -460,7 +452,7 @@
460
452
  c.appender(table, rows);
461
453
  }
462
454
  if (c.debug) {
463
- benchmark('Rebuilt table', appendTime);
455
+ console.log( 'Rebuilt table' + ts.benchmark(appendTime) );
464
456
  }
465
457
  // apply table widgets; but not before ajax completes
466
458
  if (!init && !c.appender) { ts.applyWidget(table); }
@@ -500,20 +492,22 @@
500
492
  // set up header template
501
493
  t = c.headerTemplate.replace(/\{content\}/g, $t.html()).replace(/\{icon\}/g, $t.find('.' + ts.css.icon).length ? '' : i);
502
494
  if (c.onRenderTemplate) {
503
- h = c.onRenderTemplate.apply($t, [index, t]);
495
+ h = c.onRenderTemplate.apply( $t, [ index, t ] );
504
496
  if (h && typeof h === 'string') { t = h; } // only change t if something is returned
505
497
  }
506
498
  $t.html('<div class="' + ts.css.headerIn + '">' + t + '</div>'); // faster than wrapInner
507
499
  }
508
- if (c.onRenderHeader) { c.onRenderHeader.apply($t, [index, c, c.$table]); }
500
+ if (c.onRenderHeader) { c.onRenderHeader.apply( $t, [ index, c, c.$table ] ); }
509
501
  // *** remove this.column value if no conflicts found
510
502
  elem.column = parseInt( $t.attr('data-column'), 10);
511
- elem.order = formatSortingOrder( ts.getData($t, ch, 'sortInitialOrder') || c.sortInitialOrder ) ? [1,0,2] : [0,1,2];
503
+ elem.order = formatSortingOrder( ts.getData( $t, ch, 'sortInitialOrder' ) || c.sortInitialOrder ) ?
504
+ [ 1, 0, 2 ] : // desc, asc, unsorted
505
+ [ 0, 1, 2 ]; // asc, desc, unsorted
512
506
  elem.count = -1; // set to -1 because clicking on the header automatically adds one
513
507
  elem.lockedOrder = false;
514
508
  lock = ts.getData($t, ch, 'lockedOrder') || false;
515
509
  if (typeof lock !== 'undefined' && lock !== false) {
516
- elem.order = elem.lockedOrder = formatSortingOrder(lock) ? [1,1,1] : [0,0,0];
510
+ elem.order = elem.lockedOrder = formatSortingOrder(lock) ? [ 1, 1, 1 ] : [ 0, 0, 0 ];
517
511
  }
518
512
  $t.addClass(ts.css.header + ' ' + c.cssHeader);
519
513
  // add cell to headerList
@@ -539,8 +533,8 @@
539
533
  // enable/disable sorting
540
534
  updateHeader(table);
541
535
  if (c.debug) {
542
- benchmark('Built headers:', time);
543
- log(c.$headers);
536
+ console.log( 'Built headers:' + ts.benchmark( time ) );
537
+ console.log( c.$headers );
544
538
  }
545
539
  }
546
540
 
@@ -583,9 +577,9 @@
583
577
  list = c.sortList,
584
578
  len = list.length,
585
579
  none = ts.css.sortNone + ' ' + c.cssNone,
586
- css = [ts.css.sortAsc + ' ' + c.cssAsc, ts.css.sortDesc + ' ' + c.cssDesc],
580
+ css = [ ts.css.sortAsc + ' ' + c.cssAsc, ts.css.sortDesc + ' ' + c.cssDesc ],
587
581
  cssIcon = [ c.cssIconAsc, c.cssIconDesc, c.cssIconNone ],
588
- aria = ['ascending', 'descending'],
582
+ aria = [ 'ascending', 'descending' ],
589
583
  // find the footer
590
584
  $t = $(table).find('tfoot tr').children()
591
585
  .add( $( c.namespace + '_extra_headers' ) )
@@ -655,7 +649,7 @@
655
649
  dir = ('' + val[1]).match(/^(1|d|s|o|n)/);
656
650
  dir = dir ? dir[0] : '';
657
651
  // 0/(a)sc (default), 1/(d)esc, (s)ame, (o)pposite, (n)ext
658
- switch(dir) {
652
+ switch (dir) {
659
653
  case '1': case 'd': // descending
660
654
  dir = 1;
661
655
  break;
@@ -731,11 +725,11 @@
731
725
  // add column to sort list
732
726
  order = cell.order[cell.count];
733
727
  if (order < 2) {
734
- c.sortList.push([indx, order]);
728
+ c.sortList.push([ indx, order ]);
735
729
  // add other columns if header spans across multiple
736
730
  if (cell.colSpan > 1) {
737
731
  for (col = 1; col < cell.colSpan; col++) {
738
- c.sortList.push([indx + col, order]);
732
+ c.sortList.push([ indx + col, order ]);
739
733
  }
740
734
  }
741
735
  }
@@ -746,7 +740,7 @@
746
740
  for (col = 0; col < c.sortAppend.length; col++) {
747
741
  s = ts.isValueInArray(c.sortAppend[col][0], c.sortList);
748
742
  if (s >= 0) {
749
- c.sortList.splice(s,1);
743
+ c.sortList.splice(s, 1);
750
744
  }
751
745
  }
752
746
  }
@@ -760,7 +754,7 @@
760
754
  // order.count seems to be incorrect when compared to cell.count
761
755
  s[1] = order.order[cell.count];
762
756
  if (s[1] === 2) {
763
- c.sortList.splice(col,1);
757
+ c.sortList.splice(col, 1);
764
758
  order.count = -1;
765
759
  }
766
760
  }
@@ -769,11 +763,11 @@
769
763
  // add column to sort list array
770
764
  order = cell.order[cell.count];
771
765
  if (order < 2) {
772
- c.sortList.push([indx, order]);
766
+ c.sortList.push([ indx, order ]);
773
767
  // add other columns if header spans across multiple
774
768
  if (cell.colSpan > 1) {
775
769
  for (col = 1; col < cell.colSpan; col++) {
776
- c.sortList.push([indx + col, order]);
770
+ c.sortList.push([ indx + col, order ]);
777
771
  }
778
772
  }
779
773
  }
@@ -847,10 +841,10 @@
847
841
  x = dir ? a : b;
848
842
  y = dir ? b : a;
849
843
  // text sort function
850
- if (typeof(cts) === 'function') {
844
+ if (typeof cts === 'function') {
851
845
  // custom OVERALL text sorter
852
846
  sort = cts(x[col], y[col], dir, col, table);
853
- } else if (typeof(cts) === 'object' && cts.hasOwnProperty(col)) {
847
+ } else if (typeof cts === 'object' && cts.hasOwnProperty(col)) {
854
848
  // custom text sorter for a SPECIFIC COLUMN
855
849
  sort = cts[col](x[col], y[col], dir, col, table);
856
850
  } else {
@@ -863,7 +857,9 @@
863
857
  return a[c.columns].order - b[c.columns].order;
864
858
  });
865
859
  }
866
- if (c.debug) { benchmark('Sorting on ' + sortList.toString() + ' and dir ' + order + ' time', sortTime); }
860
+ if (c.debug) {
861
+ console.log( 'Sorting on ' + sortList.toString() + ' and dir ' + order + ' time' + ts.benchmark(sortTime) );
862
+ }
867
863
  }
868
864
 
869
865
  function resortComplete(c, callback){
@@ -883,14 +879,14 @@
883
879
  // this will catch spamming of the updateCell method
884
880
  if (resrt !== false && !c.serverSideSorting && !c.table.isProcessing) {
885
881
  if (sl.length) {
886
- c.$table.trigger('sorton', [sl, function(){
882
+ c.$table.trigger('sorton', [ sl, function(){
887
883
  resortComplete(c, callback);
888
- }, true]);
884
+ }, true ]);
889
885
  } else {
890
- c.$table.trigger('sortReset', [function(){
886
+ c.$table.trigger('sortReset', [ function(){
891
887
  resortComplete(c, callback);
892
888
  ts.applyWidget(c.table, false);
893
- }]);
889
+ } ]);
894
890
  }
895
891
  } else {
896
892
  resortComplete(c, callback);
@@ -1090,10 +1086,10 @@
1090
1086
  ts.construct = function(settings) {
1091
1087
  return this.each(function() {
1092
1088
  var table = this,
1093
- // merge & extend config options
1094
- c = $.extend(true, {}, ts.defaults, settings, ts.instanceMethods);
1095
- // save initial settings
1096
- c.originalSettings = settings;
1089
+ // merge & extend config options
1090
+ c = $.extend(true, {}, ts.defaults, settings, ts.instanceMethods);
1091
+ // save initial settings
1092
+ c.originalSettings = settings;
1097
1093
  // create a table from data (build table widget)
1098
1094
  if (!table.hasInitialized && ts.buildTable && this.nodeName !== 'TABLE') {
1099
1095
  // return the table (in case the original target is the table's container)
@@ -1107,7 +1103,14 @@
1107
1103
  ts.setup = function(table, c) {
1108
1104
  // if no thead or tbody, or tablesorter is already present, quit
1109
1105
  if (!table || !table.tHead || table.tBodies.length === 0 || table.hasInitialized === true) {
1110
- return c.debug ? log('ERROR: stopping initialization! No table, thead, tbody or tablesorter has already been initialized') : '';
1106
+ if ( c.debug ) {
1107
+ if ( table.hasInitialized ) {
1108
+ console.warn( 'Stopping initialization. Tablesorter has already been initialized' );
1109
+ } else {
1110
+ console.error( 'Stopping initialization! No table, thead or tbody' );
1111
+ }
1112
+ }
1113
+ return;
1111
1114
  }
1112
1115
 
1113
1116
  var k = '',
@@ -1121,7 +1124,10 @@
1121
1124
  table.config = c;
1122
1125
  // save the settings where they read
1123
1126
  $.data(table, 'tablesorter', c);
1124
- if (c.debug) { $.data( table, 'startoveralltimer', new Date()); }
1127
+ if (c.debug) {
1128
+ console[ console.group ? 'group' : 'log' ]( 'Initializing tablesorter' );
1129
+ $.data( table, 'startoveralltimer', new Date());
1130
+ }
1125
1131
 
1126
1132
  // removing this in version 3 (only supports jQuery 1.7+)
1127
1133
  c.supportsDataObject = (function(version) {
@@ -1148,7 +1154,7 @@
1148
1154
  c.namespace = '.tablesorter' + Math.random().toString(16).slice(2);
1149
1155
  } else {
1150
1156
  // make sure namespace starts with a period & doesn't have weird characters
1151
- c.namespace = '.' + c.namespace.replace(/\W/g,'');
1157
+ c.namespace = '.' + c.namespace.replace(/\W/g, '');
1152
1158
  }
1153
1159
 
1154
1160
  c.$table.children().children('tr').attr('role', 'row');
@@ -1192,7 +1198,7 @@
1192
1198
  ts.applyWidget(table, true);
1193
1199
  // if user has supplied a sort list to constructor
1194
1200
  if (c.sortList.length > 0) {
1195
- $table.trigger('sorton', [c.sortList, {}, !c.initWidgets, true]);
1201
+ $table.trigger('sorton', [ c.sortList, {}, !c.initWidgets, true ]);
1196
1202
  } else {
1197
1203
  setHeadersCss(table);
1198
1204
  if (c.initWidgets) {
@@ -1220,7 +1226,8 @@
1220
1226
  table.hasInitialized = true;
1221
1227
  table.isProcessing = false;
1222
1228
  if (c.debug) {
1223
- ts.benchmark('Overall initialization time', $.data( table, 'startoveralltimer'));
1229
+ console.log( 'Overall initialization time: ' + ts.benchmark( $.data( table, 'startoveralltimer') ) );
1230
+ if ( c.debug && console.groupEnd ) { console.groupEnd(); }
1224
1231
  }
1225
1232
  $table.trigger('tablesorter-initialized', table);
1226
1233
  if (typeof c.initialized === 'function') { c.initialized(table); }
@@ -1231,22 +1238,22 @@
1231
1238
  table = $(table)[0];
1232
1239
  var overallWidth, percent, $tbodies, len, index,
1233
1240
  c = table.config,
1234
- colgroup = c.$table.children('colgroup');
1241
+ $colgroup = c.$table.children('colgroup');
1235
1242
  // remove plugin-added colgroup, in case we need to refresh the widths
1236
- if (colgroup.length && colgroup.hasClass(ts.css.colgroup)) {
1237
- colgroup.remove();
1243
+ if ($colgroup.length && $colgroup.hasClass(ts.css.colgroup)) {
1244
+ $colgroup.remove();
1238
1245
  }
1239
1246
  if (c.widthFixed && c.$table.children('colgroup').length === 0) {
1240
- colgroup = $('<colgroup class="' + ts.css.colgroup + '">');
1247
+ $colgroup = $('<colgroup class="' + ts.css.colgroup + '">');
1241
1248
  overallWidth = c.$table.width();
1242
1249
  // only add col for visible columns - fixes #371
1243
- $tbodies = c.$tbodies.find('tr:first').children(':visible'); //.each(function()
1250
+ $tbodies = c.$tbodies.find('tr:first').children(':visible'); // .each(function()
1244
1251
  len = $tbodies.length;
1245
1252
  for ( index = 0; index < len; index++ ) {
1246
1253
  percent = parseInt( ( $tbodies.eq( index ).width() / overallWidth ) * 1000, 10 ) / 10 + '%';
1247
- colgroup.append( $('<col>').css('width', percent) );
1254
+ $colgroup.append( $('<col>').css('width', percent) );
1248
1255
  }
1249
- c.$table.prepend(colgroup);
1256
+ c.$table.prepend($colgroup);
1250
1257
  }
1251
1258
  };
1252
1259
 
@@ -1293,12 +1300,12 @@
1293
1300
  cellId = rowIndex + '-' + $cell.index();
1294
1301
  rowSpan = cell.rowSpan || 1;
1295
1302
  colSpan = cell.colSpan || 1;
1296
- if (typeof(matrix[rowIndex]) === 'undefined') {
1303
+ if (typeof matrix[rowIndex] === 'undefined') {
1297
1304
  matrix[rowIndex] = [];
1298
1305
  }
1299
1306
  // Find first available column in the first row
1300
1307
  for (k = 0; k < matrix[rowIndex].length + 1; k++) {
1301
- if (typeof(matrix[rowIndex][k]) === 'undefined') {
1308
+ if (typeof matrix[rowIndex][k] === 'undefined') {
1302
1309
  firstAvailCol = k;
1303
1310
  break;
1304
1311
  }
@@ -1307,7 +1314,7 @@
1307
1314
  // add data-column
1308
1315
  $cell.attr({ 'data-column' : firstAvailCol }); // 'data-row' : rowIndex
1309
1316
  for (k = rowIndex; k < rowIndex + rowSpan; k++) {
1310
- if (typeof(matrix[k]) === 'undefined') {
1317
+ if (typeof matrix[k] === 'undefined') {
1311
1318
  matrix[k] = [];
1312
1319
  }
1313
1320
  matrixrow = matrix[k];
@@ -1322,23 +1329,23 @@
1322
1329
 
1323
1330
  // *** Process table ***
1324
1331
  // add processing indicator
1325
- ts.isProcessing = function(table, toggle, $ths) {
1326
- table = $(table);
1327
- var c = table[0].config,
1332
+ ts.isProcessing = function( $table, toggle, $ths ) {
1333
+ $table = $( $table );
1334
+ var c = $table[0].config,
1328
1335
  // default to all headers
1329
- $h = $ths || table.find('.' + ts.css.header);
1336
+ $h = $ths || $table.find('.' + ts.css.header);
1330
1337
  if (toggle) {
1331
1338
  // don't use sortList if custom $ths used
1332
1339
  if (typeof $ths !== 'undefined' && c.sortList.length > 0) {
1333
1340
  // get headers from the sortList
1334
1341
  $h = $h.filter(function(){
1335
- // get data-column from attr to keep compatibility with jQuery 1.2.6
1342
+ // get data-column from attr to keep compatibility with jQuery 1.2.6
1336
1343
  return this.sortDisabled ? false : ts.isValueInArray( parseFloat($(this).attr('data-column')), c.sortList) >= 0;
1337
1344
  });
1338
1345
  }
1339
- table.add($h).addClass(ts.css.processing + ' ' + c.cssProcessing);
1346
+ $table.add($h).addClass(ts.css.processing + ' ' + c.cssProcessing);
1340
1347
  } else {
1341
- table.add($h).removeClass(ts.css.processing + ' ' + c.cssProcessing);
1348
+ $table.add($h).removeClass(ts.css.processing + ' ' + c.cssProcessing);
1342
1349
  }
1343
1350
  };
1344
1351
 
@@ -1349,11 +1356,11 @@
1349
1356
  var holdr;
1350
1357
  if (getIt) {
1351
1358
  table.isProcessing = true;
1352
- $tb.before('<span class="tablesorter-savemyplace"/>');
1359
+ $tb.before('<colgroup class="tablesorter-savemyplace"/>');
1353
1360
  holdr = ($.fn.detach) ? $tb.detach() : $tb.remove();
1354
1361
  return holdr;
1355
1362
  }
1356
- holdr = $(table).find('span.tablesorter-savemyplace');
1363
+ holdr = $(table).find('colgroup.tablesorter-savemyplace');
1357
1364
  $tb.insertAfter( holdr );
1358
1365
  holdr.remove();
1359
1366
  table.isProcessing = false;
@@ -1463,13 +1470,14 @@
1463
1470
  var events,
1464
1471
  $t = $(table),
1465
1472
  c = table.config,
1473
+ debug = c.debug,
1466
1474
  $h = $t.find('thead:first'),
1467
1475
  $r = $h.find('tr.' + ts.css.headerRow).removeClass(ts.css.headerRow + ' ' + c.cssHeaderRow),
1468
1476
  $f = $t.find('tfoot:first > tr').children('th, td');
1469
1477
  if (removeClasses === false && $.inArray('uitheme', c.widgets) >= 0) {
1470
1478
  // reapply uitheme classes, in case we want to maintain appearance
1471
- $t.trigger('applyWidgetId', ['uitheme']);
1472
- $t.trigger('applyWidgetId', ['zebra']);
1479
+ $t.trigger('applyWidgetId', [ 'uitheme' ]);
1480
+ $t.trigger('applyWidgetId', [ 'zebra' ]);
1473
1481
  }
1474
1482
  // remove widget added rows, just in case
1475
1483
  $h.find('tr').not($r).remove();
@@ -1481,7 +1489,7 @@
1481
1489
  .removeData('tablesorter')
1482
1490
  .unbind( events.replace(/\s+/g, ' ') );
1483
1491
  c.$headers.add($f)
1484
- .removeClass( [ts.css.header, c.cssHeader, c.cssAsc, c.cssDesc, ts.css.sortAsc, ts.css.sortDesc, ts.css.sortNone].join(' ') )
1492
+ .removeClass( [ ts.css.header, c.cssHeader, c.cssAsc, c.cssDesc, ts.css.sortAsc, ts.css.sortDesc, ts.css.sortNone ].join(' ') )
1485
1493
  .removeAttr('data-column')
1486
1494
  .removeAttr('aria-label')
1487
1495
  .attr('aria-disabled', 'true');
@@ -1494,6 +1502,9 @@
1494
1502
  if (typeof callback === 'function') {
1495
1503
  callback(table);
1496
1504
  }
1505
+ if (debug) {
1506
+ console.log( 'tablesorter has been removed' );
1507
+ }
1497
1508
  };
1498
1509
 
1499
1510
  // *** sort functions ***
@@ -1642,10 +1653,11 @@
1642
1653
  };
1643
1654
 
1644
1655
  // *** utilities ***
1645
- ts.isValueInArray = function(column, arry) {
1646
- var indx, len = arry.length;
1647
- for (indx = 0; indx < len; indx++) {
1648
- if (arry[indx][0] === column) {
1656
+ ts.isValueInArray = function( column, arry ) {
1657
+ var indx,
1658
+ len = arry && arry.length || 0;
1659
+ for ( indx = 0; indx < len; indx++ ) {
1660
+ if ( arry[ indx ][ 0 ] === column ) {
1649
1661
  return indx;
1650
1662
  }
1651
1663
  }
@@ -1686,9 +1698,9 @@
1686
1698
  ts.widgets.push(widget);
1687
1699
  };
1688
1700
 
1689
- ts.hasWidget = function(table, name){
1690
- table = $(table);
1691
- return table.length && table[0].config && table[0].config.widgetInit[name] || false;
1701
+ ts.hasWidget = function( $table, name ) {
1702
+ $table = $( $table );
1703
+ return $table.length && $table[0].config && $table[0].config.widgetInit[name] || false;
1692
1704
  };
1693
1705
 
1694
1706
  ts.getWidgetById = function(name) {
@@ -1717,7 +1729,7 @@
1717
1729
 
1718
1730
  ts.applyWidget = function(table, init, callback) {
1719
1731
  table = $(table)[0]; // in case this is called externally
1720
- var indx, len, name,
1732
+ var indx, len, names, widget, name, applied,
1721
1733
  c = table.config,
1722
1734
  wo = c.widgetOptions,
1723
1735
  tableClass = ' ' + c.table.className + ' ',
@@ -1728,7 +1740,7 @@
1728
1740
  if (c.debug) { time = new Date(); }
1729
1741
  // look for widgets to apply from in table class
1730
1742
  // stop using \b otherwise this matches 'ui-widget-content' & adds 'content' widget
1731
- wd = new RegExp( '\\s' + c.widgetClass.replace( /\{name\}/i, '([\\w-]+)' )+ '\\s', 'g' );
1743
+ wd = new RegExp( '\\s' + c.widgetClass.replace( /\{name\}/i, '([\\w-]+)' ) + '\\s', 'g' );
1732
1744
  if ( tableClass.match( wd ) ) {
1733
1745
  // extract out the widget id from the table class (widget id's can include dashes)
1734
1746
  w = tableClass.match( wd );
@@ -1745,11 +1757,11 @@
1745
1757
  c.widgets = $.grep(c.widgets, function(v, k){
1746
1758
  return $.inArray(v, c.widgets) === k;
1747
1759
  });
1748
- name = c.widgets || [];
1749
- len = name.length;
1760
+ names = c.widgets || [];
1761
+ len = names.length;
1750
1762
  // build widget array & add priority as needed
1751
1763
  for (indx = 0; indx < len; indx++) {
1752
- wd = ts.getWidgetById(name[indx]);
1764
+ wd = ts.getWidgetById(names[indx]);
1753
1765
  if (wd && wd.id) {
1754
1766
  // set priority to 10 if not defined
1755
1767
  if (!wd.priority) { wd.priority = 10; }
@@ -1762,28 +1774,47 @@
1762
1774
  });
1763
1775
  // add/update selected widgets
1764
1776
  len = widgets.length;
1777
+ if (c.debug) {
1778
+ console[ console.group ? 'group' : 'log' ]( 'Start ' + ( init ? 'initializing' : 'applying' ) + ' widgets' );
1779
+ }
1765
1780
  for (indx = 0; indx < len; indx++) {
1766
- if (widgets[indx]) {
1767
- if ( init || !( c.widgetInit[ widgets[indx].id ] ) ) {
1781
+ widget = widgets[indx];
1782
+ if (widget) {
1783
+ name = widget.id;
1784
+ applied = false;
1785
+ if (c.debug) { time2 = new Date(); }
1786
+
1787
+ if ( init || !( c.widgetInit[ name ] ) ) {
1768
1788
  // set init flag first to prevent calling init more than once (e.g. pager)
1769
- c.widgetInit[ widgets[indx].id ] = true;
1789
+ c.widgetInit[ name ] = true;
1770
1790
  if (table.hasInitialized) {
1771
1791
  // don't reapply widget options on tablesorter init
1772
1792
  ts.applyWidgetOptions( table, c );
1773
1793
  }
1774
- if ( 'init' in widgets[indx] ) {
1775
- if (c.debug) { time2 = new Date(); }
1776
- widgets[indx].init(table, widgets[indx], c, wo);
1777
- if (c.debug) { ts.benchmark('Initializing ' + widgets[indx].id + ' widget', time2); }
1794
+ if ( 'init' in widget ) {
1795
+ applied = true;
1796
+ if (c.debug) {
1797
+ console[ console.group ? 'group' : 'log' ]( 'Initializing ' + name + ' widget' );
1798
+ }
1799
+ widget.init(table, widget, c, wo);
1778
1800
  }
1779
1801
  }
1780
- if ( !init && 'format' in widgets[indx] ) {
1781
- if (c.debug) { time2 = new Date(); }
1782
- widgets[indx].format(table, c, wo, false);
1783
- if (c.debug) { ts.benchmark( ( init ? 'Initializing ' : 'Applying ' ) + widgets[indx].id + ' widget', time2); }
1802
+ if ( !init && 'format' in widget ) {
1803
+ applied = true;
1804
+ if (c.debug) {
1805
+ console[ console.group ? 'group' : 'log' ]( 'Updating ' + name + ' widget' );
1806
+ }
1807
+ widget.format(table, c, wo, false);
1808
+ }
1809
+ if (c.debug) {
1810
+ if (applied) {
1811
+ console.log( 'Completed ' + ( init ? 'initializing ' : 'applying ' ) + name + ' widget' + ts.benchmark( time2 ) );
1812
+ if ( console.groupEnd ) { console.groupEnd(); }
1813
+ }
1784
1814
  }
1785
1815
  }
1786
1816
  }
1817
+ if ( c.debug && console.groupEnd ) { console.groupEnd(); }
1787
1818
  // callback executed on init only
1788
1819
  if (!init && typeof callback === 'function') {
1789
1820
  callback(table);
@@ -1795,7 +1826,7 @@
1795
1826
  }, 0);
1796
1827
  if (c.debug) {
1797
1828
  w = c.widgets.length;
1798
- benchmark('Completed ' + (init === true ? 'initializing ' : 'applying ') + w + ' widget' + (w !== 1 ? 's' : ''), time);
1829
+ console.log( 'Completed ' + (init === true ? 'initializing ' : 'applying ') + w + ' widget' + (w !== 1 ? 's' : '') + ts.benchmark(time) );
1799
1830
  }
1800
1831
  };
1801
1832
 
@@ -1823,7 +1854,10 @@
1823
1854
  widget = ts.getWidgetById(name[i]);
1824
1855
  indx = $.inArray( name[i], c.widgets );
1825
1856
  if ( widget && 'remove' in widget ) {
1826
- if (c.debug && indx >= 0) { log( 'Removing "' + name[i] + '" widget' ); }
1857
+ if (c.debug && indx >= 0) { console.log( 'Removing "' + name[i] + '" widget' ); }
1858
+ if ( c.debug ) {
1859
+ console.log( ( refreshing ? 'Refreshing' : 'Removing' ) + ' "' + name[i] + '" widget' );
1860
+ }
1827
1861
  widget.remove(table, c, c.widgetOptions, refreshing);
1828
1862
  c.widgetInit[ name[i] ] = false;
1829
1863
  }
@@ -1871,7 +1905,11 @@
1871
1905
  allColumns = column === 'all',
1872
1906
  data = { raw : [], parsed: [], $cell: [] },
1873
1907
  c = table.config;
1874
- if ( !isEmptyObject( c ) ) {
1908
+ if ( isEmptyObject( c ) ) {
1909
+ if ( c.debug ) {
1910
+ console.warn( 'No cache found - aborting getColumnText function!' );
1911
+ }
1912
+ } else {
1875
1913
  tbodyLen = c.$tbodies.length;
1876
1914
  for ( tbodyIndex = 0; tbodyIndex < tbodyLen; tbodyIndex++ ) {
1877
1915
  cache = c.cache[ tbodyIndex ].normalized;
@@ -1936,13 +1974,13 @@
1936
1974
  typeof table !== 'undefined' ? table : true;
1937
1975
  if (t) {
1938
1976
  // US Format - 1,234,567.89 -> 1234567.89
1939
- s = s.replace(/,/g,'');
1977
+ s = s.replace(/,/g, '');
1940
1978
  } else {
1941
1979
  // German Format = 1.234.567,89 -> 1234567.89
1942
1980
  // French Format = 1 234 567,89 -> 1234567.89
1943
- s = s.replace(/[\s|\.]/g,'').replace(/,/g,'.');
1981
+ s = s.replace(/[\s|\.]/g, '').replace(/,/g, '.');
1944
1982
  }
1945
- if(/^\s*\([.\d]+\)/.test(s)) {
1983
+ if (/^\s*\([.\d]+\)/.test(s)) {
1946
1984
  // make (#) into a negative number -> (10) = -10
1947
1985
  s = s.replace(/^\s*\(([.\d]+)\)/, '-$1');
1948
1986
  }
@@ -1967,6 +2005,23 @@
1967
2005
  tablesorter: ts.construct
1968
2006
  });
1969
2007
 
2008
+ // set up debug logs
2009
+ if ( !( console && console.log ) ) {
2010
+ ts.logs = [];
2011
+ /*jshint -W020 */
2012
+ console = {};
2013
+ console.log = console.warn = console.error = console.table = function() {
2014
+ ts.logs.push( [ Date.now(), arguments ] );
2015
+ };
2016
+ }
2017
+
2018
+ ts.log = function(){
2019
+ console.log( arguments );
2020
+ };
2021
+ ts.benchmark = function( diff ) {
2022
+ return ( ' (' + ( new Date().getTime() - diff.getTime() ) + 'ms)' );
2023
+ };
2024
+
1970
2025
  // add default parsers
1971
2026
  ts.addParser({
1972
2027
  id: 'no-parser',
@@ -2010,7 +2065,7 @@
2010
2065
  ts.addParser({
2011
2066
  id: 'currency',
2012
2067
  is: function(s) {
2013
- return (/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/).test((s || '').replace(/[+\-,. ]/g,'')); // £$€¤¥¢
2068
+ return (/^\(?\d+[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]|[\u00a3$\u20ac\u00a4\u00a5\u00a2?.]\d+\)?$/).test((s || '').replace(/[+\-,. ]/g, '')); // £$€¤¥¢
2014
2069
  },
2015
2070
  format: function(s, table) {
2016
2071
  var n = ts.formatFloat((s || '').replace(/[^\w,. \-()]/g, ''), table);
@@ -2085,7 +2140,7 @@
2085
2140
  id: 'shortDate', // 'mmddyyyy', 'ddmmyyyy' or 'yyyymmdd'
2086
2141
  is: function(s) {
2087
2142
  // testing for ##-##-#### or ####-##-##, so it's not perfect; time can be included
2088
- 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, '/'));
2143
+ 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, '/'));
2089
2144
  },
2090
2145
  format: function(s, table, cell, cellIndex) {
2091
2146
  if (s) {