jquery-tablesorter 1.17.2 → 1.17.3

Sign up to get free protection for your applications and to get access to all the features.
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) {