jquery-tablesorter 1.12.8 → 1.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) 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 +115 -67
  5. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.js +62 -40
  6. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets.js +251 -118
  7. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-extract.js +48 -24
  8. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-iso8601.js +5 -4
  9. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-month.js +16 -10
  10. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-two-digit-year.js +26 -19
  11. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-weekday.js +16 -10
  12. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date.js +7 -4
  13. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-named-numbers.js +121 -0
  14. data/vendor/assets/javascripts/jquery-tablesorter/parsers/{parser-ipv6.js → parser-network.js} +66 -17
  15. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-columnSelector.js +10 -7
  16. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-cssStickyHeaders.js +62 -35
  17. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-editable.js +197 -174
  18. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-grouping.js +3 -6
  19. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-pager.js +145 -62
  20. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-repeatheaders.js +1 -1
  21. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-scroller.js +16 -14
  22. data/vendor/assets/stylesheets/jquery-tablesorter/theme.black-ice.css +2 -2
  23. data/vendor/assets/stylesheets/jquery-tablesorter/theme.blue.css +2 -2
  24. data/vendor/assets/stylesheets/jquery-tablesorter/theme.bootstrap_2.css +2 -2
  25. data/vendor/assets/stylesheets/jquery-tablesorter/theme.dark.css +2 -2
  26. data/vendor/assets/stylesheets/jquery-tablesorter/theme.default.css +2 -2
  27. data/vendor/assets/stylesheets/jquery-tablesorter/theme.dropbox.css +2 -2
  28. data/vendor/assets/stylesheets/jquery-tablesorter/theme.green.css +2 -2
  29. data/vendor/assets/stylesheets/jquery-tablesorter/theme.grey.css +2 -2
  30. data/vendor/assets/stylesheets/jquery-tablesorter/theme.ice.css +2 -2
  31. data/vendor/assets/stylesheets/jquery-tablesorter/theme.jui.css +4 -1
  32. data/vendor/assets/stylesheets/jquery-tablesorter/theme.metro-dark.css +4 -4
  33. metadata +4 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3f537540ad9cb3ae7519f0ede00b10a967df49b5
4
- data.tar.gz: 4e043ff89f30abfa0bb964799a352dbe63d61b81
3
+ metadata.gz: 352f918783831cc401eb8b3c9a8ed8d0b1dbf1aa
4
+ data.tar.gz: 8d49de1c504051729de9cb5a9434542c479a9f0c
5
5
  SHA512:
6
- metadata.gz: a1ee4421ddd5364f2f8471cdfa0ca6c1a9ef3794f53721092a859236b7492e756c3a925a7e9d4e6c5bc2725d2d8ba29be917ff82c9bb85972c218090ad54bf1a
7
- data.tar.gz: c71c7fd64e88115f2a3fb66a3205c050001c4da2cfed4cf0a1178a4a18932d2ede7d40cc0b43b2ae25cfa3d1ad9e21bc32880acf0ceb5f001d2887817d54a4f3
6
+ metadata.gz: 4e11a4e7722b7eb97301d93caa25eefcade3a83750f68cb0a9608947e0d728537db07e408af70ec553269994569b6b66819467fec67aa0e96da1d5ef27cb32de
7
+ data.tar.gz: 9e1d3646f6ce66a39135020b2a94359018c96f824834046fb21e302879b336d98a7b50e18252fa52f518824db5a184969cf981232a273cfc14adbf6725deb125
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  Simple integration of jquery-tablesorter into the asset pipeline.
6
6
 
7
- Current tablesorter version: 2.17.8 (9/15/2014), [documentation]
7
+ Current tablesorter version: 2.18.0 (10/26/2014), [documentation]
8
8
 
9
9
  Any issue associated with the js/css files, please report to [Mottie's fork].
10
10
 
@@ -1,3 +1,3 @@
1
1
  module JqueryTablesorter
2
- VERSION = '1.12.8'
2
+ VERSION = '1.13.0'
3
3
  end
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  * tablesorter pager plugin
3
- * updated 9/15/2014 (v2.17.8)
3
+ * updated 10/26/2014 (v2.18.0)
4
4
  */
5
5
  /*jshint browser:true, jquery:true, unused:false */
6
6
  ;(function($) {
@@ -131,16 +131,10 @@
131
131
  }
132
132
  },
133
133
 
134
- updatePageDisplay = function(table, p, completed) {
135
- var i, pg, s, $out, regex,
136
- c = table.config,
137
- f = c.$table.hasClass('hasFilters'),
138
- t = [],
139
- sz = p.size || 10; // don't allow dividing by zero
140
- t = [ (c.widgetOptions && c.widgetOptions.filter_filteredRow || 'filtered'), c.selectorRemove.replace(/^(\w+\.)/g,'') ];
141
- if (p.countChildRows) { t.push(c.cssChildRow); }
142
- regex = new RegExp( '(' + t.join('|') + ')' );
143
- if (f && !p.ajaxUrl) {
134
+ calcFilters = function(table, p) {
135
+ var c = table.config,
136
+ hasFilters = c.$table.hasClass('hasFilters');
137
+ if (hasFilters && !p.ajaxUrl) {
144
138
  if ($.isEmptyObject(c.cache)) {
145
139
  // delayInit: true so nothing is in the cache
146
140
  p.filteredRows = p.totalRows = c.$tbodies.eq(0).children('tr').not( p.countChildRows ? '' : '.' + c.cssChildRow ).length;
@@ -150,11 +144,20 @@
150
144
  p.filteredRows += p.regexRows.test(el[c.columns].$row[0].className) ? 0 : 1;
151
145
  });
152
146
  }
153
- } else if (!f) {
147
+ } else if (!hasFilters) {
154
148
  p.filteredRows = p.totalRows;
155
149
  }
150
+ },
151
+
152
+ updatePageDisplay = function(table, p, completed) {
153
+ if ( !p.initialized ) { return; }
154
+ var s, t, $out,
155
+ c = table.config,
156
+ sz = p.size || 10; // don't allow dividing by zero
157
+ if (p.countChildRows) { t.push(c.cssChildRow); }
156
158
  p.totalPages = Math.ceil( p.totalRows / sz ); // needed for "pageSize" method
157
159
  c.totalRows = p.totalRows;
160
+ calcFilters(table, p);
158
161
  c.filteredRows = p.filteredRows;
159
162
  p.filteredPages = Math.ceil( p.filteredRows / sz ) || 0;
160
163
  if ( Math.min( p.totalPages, p.filteredPages ) >= 0 ) {
@@ -188,38 +191,11 @@
188
191
  $out[ ($out[0].tagName === 'INPUT') ? 'val' : 'html' ](s);
189
192
  if ( p.$goto.length ) {
190
193
  t = '';
191
- pg = Math.min( p.totalPages, p.filteredPages );
192
- // Filter the options page number link array if it's larger than 'maxOptionSize'
193
- // as large page set links will slow the browser on large dom inserts
194
- var skip_set_size = Math.floor(pg / p.maxOptionSize),
195
- large_collection = pg > p.maxOptionSize,
196
- current_page = p.page + 1,
197
- start_page = 1,
198
- end_page = pg,
199
- option_pages = [];
200
- //construct default options pages array
201
- var option_pages_start_page = (large_collection && current_page == 1) ? skip_set_size : 1;
202
- for (i = option_pages_start_page; i <= pg;) {
203
- option_pages.push(i);
204
- i = large_collection ? i + skip_set_size : i++;
205
- }
206
- if (large_collection) {
207
- var central_focus_size = Math.floor(p.maxOptionSize / 2) - 1,
208
- lower_focus_window = Math.abs(Math.floor(current_page - central_focus_size/2)),
209
- focus_option_pages = [];
210
- start_page = Math.min(current_page, lower_focus_window);
211
- end_page = start_page + central_focus_size;
212
- //construct an array to get a focus set around the current page
213
- for (i = start_page; i <= end_page ; i++) focus_option_pages.push(i);
214
- var insert_index = Math.floor(option_pages.length / 2) - Math.floor(focus_option_pages.length / 2);
215
- Array.prototype.splice.apply(option_pages, [ insert_index, focus_option_pages.length ].concat(focus_option_pages));
216
- option_pages.sort(function sortNumber(a,b) { return a - b; });
217
- }
218
- for ( i = 0; i < option_pages.length; i++) {
219
- t += '<option>' + option_pages[i] + '</option>';
220
- }
221
- p.$goto[0].innerHTML = t;
222
- p.$goto[0].value = current_page;
194
+ $.each(buildPageSelect(p), function(i, opt){
195
+ t += '<option value="' + opt + '">' + opt + '</option>';
196
+ });
197
+ // innerHTML doesn't work in IE9 - http://support2.microsoft.com/kb/276228
198
+ p.$goto.html(t).val( p.page + 1 );
223
199
  }
224
200
  // rebind startRow/page inputs
225
201
  $out.find('.ts-startRow, .ts-page').unbind('change').bind('change', function(){
@@ -230,6 +206,7 @@
230
206
  }
231
207
  }
232
208
  pagerArrows(p);
209
+ fixHeight(table, p);
233
210
  if (p.initialized && completed !== false) {
234
211
  c.$table.trigger('pagerComplete', p);
235
212
  // save pager info to storage
@@ -242,26 +219,92 @@
242
219
  }
243
220
  },
244
221
 
222
+ buildPageSelect = function(p) {
223
+ // Filter the options page number link array if it's larger than 'maxOptionSize'
224
+ // as large page set links will slow the browser on large dom inserts
225
+ var i, central_focus_size, focus_option_pages, insert_index, option_length, focus_length,
226
+ pg = Math.min( p.totalPages, p.filteredPages ) || 1,
227
+ // make skip set size multiples of 5
228
+ skip_set_size = Math.ceil( ( pg / p.maxOptionSize ) / 5 ) * 5,
229
+ large_collection = pg > p.maxOptionSize,
230
+ current_page = p.page + 1,
231
+ start_page = skip_set_size,
232
+ end_page = pg - skip_set_size,
233
+ option_pages = [1],
234
+ // construct default options pages array
235
+ option_pages_start_page = (large_collection) ? skip_set_size : 1;
236
+
237
+ for ( i = option_pages_start_page; i <= pg; ) {
238
+ option_pages.push(i);
239
+ i = i + ( large_collection ? skip_set_size : 1 );
240
+ }
241
+ option_pages.push(pg);
242
+ if (large_collection) {
243
+ focus_option_pages = [];
244
+ // don't allow central focus size to be > 5 on either side of current page
245
+ central_focus_size = Math.max( Math.floor( p.maxOptionSize / skip_set_size ) - 1, 5 );
246
+
247
+ start_page = current_page - central_focus_size;
248
+ if (start_page < 1) { start_page = 1; }
249
+ end_page = current_page + central_focus_size;
250
+ if (end_page > pg) { end_page = pg; }
251
+ // construct an array to get a focus set around the current page
252
+ for (i = start_page; i <= end_page ; i++) {
253
+ focus_option_pages.push(i);
254
+ }
255
+
256
+ // keep unique values
257
+ option_pages = $.grep(option_pages, function(value, indx) {
258
+ return $.inArray(value, option_pages) === indx;
259
+ });
260
+
261
+ option_length = option_pages.length;
262
+ focus_length = focus_option_pages.length;
263
+
264
+ // make sure at all option_pages aren't replaced
265
+ if (option_length - focus_length > skip_set_size / 2 && option_length + focus_length > p.maxOptionSize ) {
266
+ insert_index = Math.floor(option_length / 2) - Math.floor(focus_length / 2);
267
+ Array.prototype.splice.apply(option_pages, [ insert_index, focus_length ]);
268
+ }
269
+ option_pages = option_pages.concat(focus_option_pages);
270
+
271
+ }
272
+
273
+ // keep unique values again
274
+ option_pages = $.grep(option_pages, function(value, indx) {
275
+ return $.inArray(value, option_pages) === indx;
276
+ })
277
+ .sort(function(a,b) { return a - b; });
278
+
279
+ return option_pages;
280
+ },
281
+
245
282
  fixHeight = function(table, p) {
246
283
  var d, h,
247
284
  c = table.config,
248
285
  $b = c.$tbodies.eq(0);
249
- if (p.fixedHeight) {
250
- $b.find('tr.pagerSavedHeightSpacer').remove();
286
+ $b.find('tr.pagerSavedHeightSpacer').remove();
287
+ if (p.fixedHeight && !p.isDisabled) {
251
288
  h = $.data(table, 'pagerSavedHeight');
252
289
  if (h) {
253
290
  d = h - $b.height();
254
291
  if ( d > 5 && $.data(table, 'pagerLastSize') === p.size && $b.children('tr:visible').length < p.size ) {
255
- $b.append('<tr class="pagerSavedHeightSpacer ' + c.selectorRemove.replace(/^(\w+\.)/g,'') + '" style="height:' + d + 'px;"></tr>');
292
+ $b.append('<tr class="pagerSavedHeightSpacer ' + c.selectorRemove.slice(1) + '" style="height:' + d + 'px;"></tr>');
256
293
  }
257
294
  }
258
295
  }
259
296
  },
260
297
 
261
298
  changeHeight = function(table, p) {
262
- var $b = table.config.$tbodies.eq(0);
299
+ var h,
300
+ c = table.config,
301
+ $b = c.$tbodies.eq(0);
263
302
  $b.find('tr.pagerSavedHeightSpacer').remove();
264
- $.data(table, 'pagerSavedHeight', $b.height());
303
+ if (!$b.children('tr:visible').length) {
304
+ $b.append('<tr class="pagerSavedHeightSpacer ' + c.selectorRemove.slice(1) + '"><td>&nbsp</td></tr>');
305
+ }
306
+ h = $b.children('tr').eq(0).height() * p.size;
307
+ $.data(table, 'pagerSavedHeight', h);
265
308
  fixHeight(table, p);
266
309
  $.data(table, 'pagerLastSize', p.size);
267
310
  },
@@ -418,8 +461,7 @@
418
461
  p.last.totalRows = p.totalRows;
419
462
  p.last.currentFilters = p.currentFilters;
420
463
  p.last.sortList = (c.sortList || []).join(',');
421
- updatePageDisplay(table, p);
422
- fixHeight(table, p);
464
+ updatePageDisplay(table, p, true);
423
465
  $t.trigger('updateCache', [function(){
424
466
  if (p.initialized) {
425
467
  // apply widgets after table has rendered & after a delay to prevent
@@ -560,8 +602,7 @@
560
602
  }
561
603
  ts.processTbody(table, $tb, false);
562
604
  }
563
- updatePageDisplay(table, p);
564
- if ( !p.isDisabled ) { fixHeight(table, p); }
605
+ updatePageDisplay(table, p, true);
565
606
  if (table.isUpdating) {
566
607
  $t.trigger('updateComplete', [ table, true ]);
567
608
  }
@@ -612,13 +653,14 @@
612
653
 
613
654
  moveToPage = function(table, p, pageMoved) {
614
655
  if ( p.isDisabled ) { return; }
615
- var c = table.config,
656
+ var pg, c = table.config,
616
657
  $t = $(table),
617
- l = p.last,
618
- pg = Math.min( p.totalPages, p.filteredPages );
619
- if ( pageMoved !== false && p.initialized && $.isEmptyObject(table.config.cache)) {
658
+ l = p.last;
659
+ if ( pageMoved !== false && p.initialized && $.isEmptyObject(c.cache)) {
620
660
  return updateCache(table);
621
661
  }
662
+ calcFilters(table, p);
663
+ pg = Math.min( p.totalPages, p.filteredPages );
622
664
  if ( p.page < 0 ) { p.page = 0; }
623
665
  if ( p.page > ( pg - 1 ) && pg !== 0 ) { p.page = pg - 1; }
624
666
  // fixes issue where one currentFilter is [] and the other is ['','',''],
@@ -628,6 +670,10 @@
628
670
  // don't allow rendering multiple times on the same page/size/totalRows/filters/sorts
629
671
  if ( l.page === p.page && l.size === p.size && l.totalRows === p.totalRows &&
630
672
  (l.currentFilters || []).join(',') === (p.currentFilters || []).join(',') &&
673
+ // check for ajax url changes see #730
674
+ (l.ajaxUrl || '') === (p.ajaxObject.url || '') &&
675
+ // & ajax url option changes (dynamically add/remove/rename sort & filter parameters)
676
+ (l.optAjaxUrl || '') === (p.ajaxUrl || '') &&
631
677
  l.sortList === (c.sortList || []).join(',') ) { return; }
632
678
  if (c.debug) {
633
679
  ts.log('Pager changing to page ' + p.page);
@@ -638,7 +684,9 @@
638
684
  // fixes #408; modify sortList otherwise it auto-updates
639
685
  sortList : (c.sortList || []).join(','),
640
686
  totalRows : p.totalRows,
641
- currentFilters : p.currentFilters || []
687
+ currentFilters : p.currentFilters || [],
688
+ ajaxUrl : p.ajaxObject.url || '',
689
+ optAjaxUrl : p.ajaxUrl || ''
642
690
  };
643
691
  if (p.ajax) {
644
692
  getAjax(table, p);
@@ -722,11 +770,11 @@
722
770
  p.$container.find(p.cssPageDisplay).attr('id', info);
723
771
  c.$table.attr('aria-describedby', info);
724
772
  }
773
+ changeHeight(table, p);
725
774
  if ( triggered ) {
726
775
  c.$table.trigger('updateRows');
727
776
  setPageSize(table, p.size, p);
728
777
  hideRowsSetup(table, p);
729
- fixHeight(table, p);
730
778
  if (c.debug) {
731
779
  ts.log('pager enabled');
732
780
  }
@@ -781,7 +829,7 @@
781
829
  p.regexRows = new RegExp('(' + (wo.filter_filteredRow || 'filtered') + '|' + c.selectorRemove.replace(/^(\w+\.)/g,'') + '|' + c.cssChildRow + ')');
782
830
 
783
831
  $t
784
- .unbind('filterStart filterEnd sortEnd disable enable destroy updateComplete pageSize '.split(' ').join('.pager '))
832
+ .unbind('filterStart filterEnd sortEnd disable enable destroy updateComplete pageSize pageSet '.split(' ').join('.pager '))
785
833
  .bind('filterStart.pager', function(e, filters) {
786
834
  p.currentFilters = filters;
787
835
  // don't change page is filters are the same (pager updating, etc)
@@ -796,11 +844,9 @@
796
844
  // make sure we have a copy of all table rows once the cache has been built
797
845
  updateCache(table);
798
846
  }
799
- // update page display first, so we update p.filteredPages
800
- updatePageDisplay(table, p, false);
801
847
  moveToPage(table, p, false);
802
848
  c.$table.trigger('applyWidgets');
803
- fixHeight(table, p);
849
+ updatePageDisplay(table, p, false);
804
850
  }
805
851
  })
806
852
  .bind('disable.pager', function(e){
@@ -819,7 +865,6 @@
819
865
  e.stopPropagation();
820
866
  // table can be unintentionally undefined in tablesorter v2.17.7 and earlier
821
867
  if ( !table || triggered ) { return; }
822
- fixHeight(table, p);
823
868
  var $rows = c.$tbodies.eq(0).children('tr').not(c.selectorRemove);
824
869
  p.totalRows = $rows.length - ( p.countChildRows ? 0 : $rows.filter('.' + c.cssChildRow).length );
825
870
  p.totalPages = Math.ceil( p.totalRows / p.size );
@@ -827,8 +872,12 @@
827
872
  // make a copy of all table rows once the cache has been built
828
873
  updateCache(table);
829
874
  }
830
- updatePageDisplay(table, p);
875
+ if ( p.page >= p.totalPages ) {
876
+ moveToLastPage(table, p);
877
+ }
831
878
  hideRows(table, p);
879
+ changeHeight(table, p);
880
+ updatePageDisplay(table, p, true);
832
881
  })
833
882
  .bind('pageSize.pager', function(e,v){
834
883
  e.stopPropagation();
@@ -912,11 +961,10 @@
912
961
  hideRowsSetup(table, p);
913
962
  }
914
963
 
915
- changeHeight(table, p);
916
-
917
964
  // pager initialized
918
965
  if (!p.ajax) {
919
966
  p.initialized = true;
967
+ updatePageDisplay(table, p, true);
920
968
  $(table).trigger('pagerInitialized', p);
921
969
  }
922
970
  });
@@ -1,5 +1,5 @@
1
1
  /**!
2
- * TableSorter 2.17.8 - Client-side table sorting with ease!
2
+ * TableSorter 2.18.0 - 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.17.8";
27
+ ts.version = "2.18.0";
28
28
 
29
29
  ts.parsers = [];
30
30
  ts.widgets = [];
@@ -75,6 +75,7 @@
75
75
  zebra : [ 'even', 'odd' ] // zebra widget alternating row class names
76
76
  },
77
77
  initWidgets : true, // apply widgets on tablesorter initialization
78
+ widgetClass : 'widget-{name}', // table class name template to match to include a widget
78
79
 
79
80
  // *** callbacks
80
81
  initialized : null, // function(table){},
@@ -187,7 +188,7 @@
187
188
  }
188
189
 
189
190
  function detectParserForColumn(table, rows, rowIndex, cellIndex) {
190
- var cur,
191
+ var cur, $node,
191
192
  i = ts.parsers.length,
192
193
  node = false,
193
194
  nodeValue = '',
@@ -197,6 +198,7 @@
197
198
  if (rows[rowIndex]) {
198
199
  node = rows[rowIndex].cells[cellIndex];
199
200
  nodeValue = getElementText(table, node, cellIndex);
201
+ $node = $(node);
200
202
  if (table.config.debug) {
201
203
  log('Checking if value was empty on row ' + rowIndex + ', column: ' + cellIndex + ': "' + nodeValue + '"');
202
204
  }
@@ -207,7 +209,7 @@
207
209
  while (--i >= 0) {
208
210
  cur = ts.parsers[i];
209
211
  // ignore the default text parser because it will always be true
210
- if (cur && cur.id !== 'text' && cur.is && cur.is(nodeValue, table, node)) {
212
+ if (cur && cur.id !== 'text' && cur.is && cur.is(nodeValue, table, node, $node)) {
211
213
  return cur;
212
214
  }
213
215
  }
@@ -457,7 +459,8 @@
457
459
  }
458
460
  $(this).html('<div class="' + ts.css.headerIn + '">' + t + '</div>'); // faster than wrapInner
459
461
  }
460
- if (c.onRenderHeader) { c.onRenderHeader.apply($t, [index]); }
462
+ if (c.onRenderHeader) { c.onRenderHeader.apply($t, [index, c, c.$table]); }
463
+ // *** remove this.column value if no conflicts found
461
464
  this.column = parseInt( $(this).attr('data-column'), 10);
462
465
  this.order = formatSortingOrder( ts.getData($t, ch, 'sortInitialOrder') || c.sortInitialOrder ) ? [1,0,2] : [0,1,2];
463
466
  this.count = -1; // set to -1 because clicking on the header automatically adds one
@@ -648,7 +651,7 @@
648
651
  });
649
652
  }
650
653
  // get current column index
651
- indx = cell.column;
654
+ indx = parseInt( $(cell).attr('data-column'), 10 );
652
655
  // user only wants to sort on one column
653
656
  if (key) {
654
657
  // flush the sort list
@@ -1078,8 +1081,10 @@
1078
1081
  'aria-live' : 'polite',
1079
1082
  'aria-relevant' : 'all'
1080
1083
  });
1081
- if (c.$table.find('caption').length) {
1082
- c.$table.attr('aria-labelledby', 'theCaption');
1084
+ if (c.$table.children('caption').length) {
1085
+ k = c.$table.children('caption')[0];
1086
+ if (!k.id) { k.id = c.namespace.slice(1) + 'caption'; }
1087
+ c.$table.attr('aria-labelledby', k.id);
1083
1088
  }
1084
1089
  c.widgetInit = {}; // keep a list of initialized widgets
1085
1090
  // change textExtraction via data-attribute
@@ -1556,11 +1561,24 @@
1556
1561
  table = $(table)[0]; // in case this is called externally
1557
1562
  var c = table.config,
1558
1563
  wo = c.widgetOptions,
1564
+ tableClass = ' ' + c.table.className + ' ',
1559
1565
  widgets = [],
1560
- time, w, wd;
1566
+ time, time2, w, wd;
1561
1567
  // prevent numerous consecutive widget applications
1562
1568
  if (init !== false && table.hasInitialized && (table.isApplyingWidgets || table.isUpdating)) { return; }
1563
1569
  if (c.debug) { time = new Date(); }
1570
+ // look for widgets to apply from in table class
1571
+ // stop using \b otherwise this matches "ui-widget-content" & adds "content" widget
1572
+ wd = new RegExp( '\\s' + c.widgetClass.replace( /\{name\}/i, '([\\w-]+)' )+ '\\s', 'g' );
1573
+ if ( tableClass.match( wd ) ) {
1574
+ // extract out the widget id from the table class (widget id's can include dashes)
1575
+ w = tableClass.match( wd );
1576
+ if ( w ) {
1577
+ $.each( w, function( i,n ){
1578
+ c.widgets.push( n.replace( wd, '$1' ) );
1579
+ });
1580
+ }
1581
+ }
1564
1582
  if (c.widgets.length) {
1565
1583
  table.isApplyingWidgets = true;
1566
1584
  // ensure unique widget ids
@@ -1590,17 +1608,22 @@
1590
1608
  wo = table.config.widgetOptions = $.extend( true, {}, w.options, wo );
1591
1609
  }
1592
1610
  if (w.hasOwnProperty('init')) {
1611
+ if (c.debug) { time2 = new Date(); }
1593
1612
  w.init(table, w, c, wo);
1613
+ if (c.debug) { ts.benchmark('Initializing ' + w.id + ' widget', time2); }
1594
1614
  }
1595
1615
  }
1596
1616
  if (!init && w.hasOwnProperty('format')) {
1617
+ if (c.debug) { time2 = new Date(); }
1597
1618
  w.format(table, c, wo, false);
1619
+ if (c.debug) { ts.benchmark( ( init ? 'Initializing ' : 'Applying ' ) + w.id + ' widget', time2); }
1598
1620
  }
1599
1621
  }
1600
1622
  });
1601
1623
  }
1602
1624
  setTimeout(function(){
1603
1625
  table.isApplyingWidgets = false;
1626
+ $.data(table, 'lastWidgetApplication', new Date());
1604
1627
  }, 0);
1605
1628
  if (c.debug) {
1606
1629
  w = c.widgets.length;
@@ -1743,23 +1766,6 @@
1743
1766
  type: "numeric"
1744
1767
  });
1745
1768
 
1746
- ts.addParser({
1747
- id: "ipAddress",
1748
- is: function(s) {
1749
- return (/^\d{1,3}[\.]\d{1,3}[\.]\d{1,3}[\.]\d{1,3}$/).test(s);
1750
- },
1751
- format: function(s, table) {
1752
- var i, a = s ? s.split(".") : '',
1753
- r = "",
1754
- l = a.length;
1755
- for (i = 0; i < l; i++) {
1756
- r += ("00" + a[i]).slice(-3);
1757
- }
1758
- return s ? ts.formatFloat(r, table) : s;
1759
- },
1760
- type: "numeric"
1761
- });
1762
-
1763
1769
  ts.addParser({
1764
1770
  id: "url",
1765
1771
  is: function(s) {
@@ -1778,7 +1784,8 @@
1778
1784
  return (/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}/).test(s);
1779
1785
  },
1780
1786
  format: function(s, table) {
1781
- return s ? ts.formatFloat((s !== "") ? (new Date(s.replace(/-/g, "/")).getTime() || s) : "", table) : s;
1787
+ var date = s ? new Date( s.replace(/-/g, "/") ) : s;
1788
+ return date instanceof Date && isFinite(date) ? date.getTime() : s;
1782
1789
  },
1783
1790
  type: "numeric"
1784
1791
  });
@@ -1794,6 +1801,19 @@
1794
1801
  type: "numeric"
1795
1802
  });
1796
1803
 
1804
+ // added image parser to core v2.17.9
1805
+ ts.addParser({
1806
+ id: "image",
1807
+ is: function(s, table, node, $node){
1808
+ return $node.find('img').length > 0;
1809
+ },
1810
+ format: function(s, table, cell) {
1811
+ return $(cell).find('img').attr(table.config.imgAttr || 'alt') || s;
1812
+ },
1813
+ parsed : true, // filter widget flag
1814
+ type: "text"
1815
+ });
1816
+
1797
1817
  ts.addParser({
1798
1818
  id: "usLongDate",
1799
1819
  is: function(s) {
@@ -1802,7 +1822,8 @@
1802
1822
  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);
1803
1823
  },
1804
1824
  format: function(s, table) {
1805
- return s ? ts.formatFloat( (new Date(s.replace(/(\S)([AP]M)$/i, "$1 $2")).getTime() || s), table) : s;
1825
+ var date = s ? new Date( s.replace(/(\S)([AP]M)$/i, "$1 $2") ) : s;
1826
+ return date instanceof Date && isFinite(date) ? date.getTime() : s;
1806
1827
  },
1807
1828
  type: "numeric"
1808
1829
  });
@@ -1815,19 +1836,22 @@
1815
1836
  },
1816
1837
  format: function(s, table, cell, cellIndex) {
1817
1838
  if (s) {
1818
- var c = table.config,
1839
+ var date, d,
1840
+ c = table.config,
1819
1841
  ci = c.$headers.filter('[data-column=' + cellIndex + ']:last'),
1820
1842
  format = ci.length && ci[0].dateFormat || ts.getData( ci, ts.getColumnData( table, c.headers, cellIndex ), 'dateFormat') || c.dateFormat;
1821
- s = s.replace(/\s+/g," ").replace(/[\-.,]/g, "/"); // escaped - because JSHint in Firefox was showing it as an error
1843
+ d = s.replace(/\s+/g," ").replace(/[\-.,]/g, "/"); // escaped - because JSHint in Firefox was showing it as an error
1822
1844
  if (format === "mmddyyyy") {
1823
- s = s.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$3/$1/$2");
1845
+ d = d.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$3/$1/$2");
1824
1846
  } else if (format === "ddmmyyyy") {
1825
- s = s.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$3/$2/$1");
1847
+ d = d.replace(/(\d{1,2})[\/\s](\d{1,2})[\/\s](\d{4})/, "$3/$2/$1");
1826
1848
  } else if (format === "yyyymmdd") {
1827
- s = s.replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/, "$1/$2/$3");
1849
+ d = d.replace(/(\d{4})[\/\s](\d{1,2})[\/\s](\d{1,2})/, "$1/$2/$3");
1828
1850
  }
1851
+ date = new Date(d);
1852
+ return date instanceof Date && isFinite(date) ? date.getTime() : s;
1829
1853
  }
1830
- return s ? ts.formatFloat( (new Date(s).getTime() || s), table) : s;
1854
+ return s;
1831
1855
  },
1832
1856
  type: "numeric"
1833
1857
  });
@@ -1838,7 +1862,8 @@
1838
1862
  return (/^(([0-2]?\d:[0-5]\d)|([0-1]?\d:[0-5]\d\s?([AP]M)))$/i).test(s);
1839
1863
  },
1840
1864
  format: function(s, table) {
1841
- return s ? ts.formatFloat( (new Date("2000/01/01 " + s.replace(/(\S)([AP]M)$/i, "$1 $2")).getTime() || s), table) : s;
1865
+ var date = s ? new Date( "2000/01/01 " + s.replace(/(\S)([AP]M)$/i, "$1 $2") ) : s;
1866
+ return date instanceof Date && isFinite(date) ? date.getTime() : s;
1842
1867
  },
1843
1868
  type: "numeric"
1844
1869
  });
@@ -1882,18 +1907,15 @@
1882
1907
  $tr.removeClass(wo.zebra[even ? 1 : 0]).addClass(wo.zebra[even ? 0 : 1]);
1883
1908
  });
1884
1909
  }
1885
- if (c.debug) {
1886
- ts.benchmark("Applying Zebra widget", time);
1887
- }
1888
1910
  },
1889
1911
  remove: function(table, c, wo){
1890
1912
  var k, $tb,
1891
1913
  b = c.$tbodies,
1892
1914
  rmv = (wo.zebra || [ "even", "odd" ]).join(' ');
1893
1915
  for (k = 0; k < b.length; k++ ){
1894
- $tb = $.tablesorter.processTbody(table, b.eq(k), true); // remove tbody
1916
+ $tb = ts.processTbody(table, b.eq(k), true); // remove tbody
1895
1917
  $tb.children().removeClass(rmv);
1896
- $.tablesorter.processTbody(table, $tb, false); // restore tbody
1918
+ ts.processTbody(table, $tb, false); // restore tbody
1897
1919
  }
1898
1920
  }
1899
1921
  });