jquery-tablesorter 1.16.2 → 1.16.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) 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 +8 -6
  5. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.js +30 -20
  6. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets.js +343 -193
  7. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-input-select.js +4 -4
  8. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-build-table.js +3 -2
  9. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter-formatter-select2.js +2 -2
  10. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter.js +26 -23
  11. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-output.js +2 -3
  12. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-pager.js +11 -5
  13. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-resizable.js +277 -139
  14. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-scroller.js +543 -220
  15. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-stickyHeaders.js +3 -10
  16. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-storage.js +28 -15
  17. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-uitheme.js +7 -4
  18. data/vendor/assets/stylesheets/jquery-tablesorter/theme.black-ice.css +5 -4
  19. data/vendor/assets/stylesheets/jquery-tablesorter/theme.blue.css +8 -5
  20. data/vendor/assets/stylesheets/jquery-tablesorter/theme.bootstrap.css +5 -4
  21. data/vendor/assets/stylesheets/jquery-tablesorter/theme.bootstrap_2.css +6 -5
  22. data/vendor/assets/stylesheets/jquery-tablesorter/theme.dark.css +6 -5
  23. data/vendor/assets/stylesheets/jquery-tablesorter/theme.default.css +6 -5
  24. data/vendor/assets/stylesheets/jquery-tablesorter/theme.dropbox.css +5 -5
  25. data/vendor/assets/stylesheets/jquery-tablesorter/theme.green.css +13 -8
  26. data/vendor/assets/stylesheets/jquery-tablesorter/theme.grey.css +8 -5
  27. data/vendor/assets/stylesheets/jquery-tablesorter/theme.ice.css +16 -9
  28. data/vendor/assets/stylesheets/jquery-tablesorter/theme.jui.css +4 -3
  29. data/vendor/assets/stylesheets/jquery-tablesorter/theme.metro-dark.css +5 -4
  30. metadata +3 -3
@@ -1,5 +1,5 @@
1
- /*! input & select parsers for jQuery 1.7+ & tablesorter 2.7.11+
2
- * Updated 3/5/2015 (v2.21.0)
1
+ /*! parser: input & select - updated 3/26/2015 (v2.21.3) *//*
2
+ * for jQuery 1.7+ & tablesorter 2.7.11+
3
3
  * Demo: http://mottie.github.com/tablesorter/docs/example-widget-grouping.html
4
4
  */
5
5
  /*jshint browser: true, jquery:true, unused:false */
@@ -111,7 +111,7 @@
111
111
  // bind to .tablesorter (default class name)
112
112
  $(this).children('tbody')
113
113
  .on('mouseleave', function(e){
114
- restoreValue(e.target.tagName === 'TBODY');
114
+ restoreValue(e.target.nodeName === 'TBODY');
115
115
  })
116
116
  .on('focus', 'select, input, textarea', function(){
117
117
  $(this).data('ts-original-value', this.value);
@@ -129,7 +129,7 @@
129
129
  }
130
130
  // Update cell cache using... select: change, input: enter or textarea: alt + enter
131
131
  if ( ( e.type === 'change' ) ||
132
- ( e.type === 'keyup' && e.which === 13 && ( e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' && e.altKey ) ) ) {
132
+ ( e.type === 'keyup' && e.which === 13 && ( e.target.nodeName === 'INPUT' || e.target.nodeName === 'TEXTAREA' && e.altKey ) ) ) {
133
133
  var undef,
134
134
  $tar = $(e.target),
135
135
  $cell = $tar.closest('td'),
@@ -1,4 +1,5 @@
1
- /*! Build Table widget for tableSorter v2.16.0; updated 2/7/2015 (v2.19.0)
1
+ /*! Widget: Build Table - updated 3/26/2015 (v2.21.3) *//*
2
+ * for tableSorter v2.16.0+
2
3
  * by Rob Garrison
3
4
  */
4
5
  /*jshint browser:true, jquery:true, unused:false */
@@ -12,7 +13,7 @@ var ts = $.tablesorter = $.tablesorter || {},
12
13
  // data.rows contains an array of rows which contains an array of cells
13
14
  bt = ts.buildTable = function(tar, c){
14
15
  // add table if one doesn't exist
15
- var $tbl = tar.tagName === 'TABLE' ? $(tar) : $('<table>').appendTo(tar),
16
+ var $tbl = tar.nodeName === 'TABLE' ? $(tar) : $('<table>').appendTo(tar),
16
17
  table = $tbl[0],
17
18
  wo = c.widgetOptions = $.extend( true, {}, bt.defaults, c.widgetOptions ),
18
19
  p = wo.build_processing,
@@ -1,4 +1,4 @@
1
- /*! Filter widget select2 formatter function - updated 2/7/2015 (v2.19.0)
1
+ /*! Widget: Filter formatter function select2 - updated 3/26/2015 (v2.21.3) *//*
2
2
  * requires: jQuery 1.7.2+, tableSorter (FORK) 2.16+, filter widget 2.16+ and select2 v3.4.6+ plugin
3
3
  */
4
4
  /*jshint browser:true, jquery:true, unused:false */
@@ -52,7 +52,7 @@ ts.filterFormatter.select2 = function($cell, indx, select2Def) {
52
52
  v = v.join('\u0000');
53
53
  }
54
54
  // escape special regex characters (http://stackoverflow.com/a/9310752/145346)
55
- v = v.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
55
+ v = v.replace(/[-[\]{}()*+?.,/\\^$|#\s]/g, '\\$&');
56
56
  // convert string back into an array
57
57
  if (arry) {
58
58
  v = v.split('\u0000');
@@ -1,14 +1,17 @@
1
- /*! Widget: filter - updated 3/5/2015 (v2.21.0) *//*
1
+ /*! Widget: filter - updated 3/26/2015 (v2.21.3) *//*
2
2
  * Requires tablesorter v2.8+ and jQuery 1.7+
3
3
  * by Rob Garrison
4
4
  */
5
5
  ;(function ($) {
6
6
  'use strict';
7
- var ts = $.tablesorter = $.tablesorter || {};
7
+ var ts = $.tablesorter = $.tablesorter || {},
8
+ tscss = ts.css;
8
9
 
9
- $.extend(ts.css, {
10
- filterRow : 'tablesorter-filter-row',
11
- filter : 'tablesorter-filter'
10
+ $.extend(tscss, {
11
+ filterRow : 'tablesorter-filter-row',
12
+ filter : 'tablesorter-filter',
13
+ filterDisabled : 'disabled',
14
+ filterRowHide : 'hideme'
12
15
  });
13
16
 
14
17
  ts.addWidget({
@@ -58,7 +61,7 @@ ts.addWidget({
58
61
  // add .tsfilter namespace to all BUT search
59
62
  .unbind( events.replace(/\s+/g, ' ') )
60
63
  // remove the filter row even if refreshing, because the column might have been moved
61
- .find('.' + ts.css.filterRow).remove();
64
+ .find('.' + tscss.filterRow).remove();
62
65
  if (refreshing) { return; }
63
66
  for (tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) {
64
67
  $tbody = ts.processTbody(table, $tbodies.eq(tbodyIndex), true); // remove tbody
@@ -286,13 +289,13 @@ ts.filter = {
286
289
  c.$table.bind( txt, function(event, filter) {
287
290
  val = (wo.filter_hideEmpty && $.isEmptyObject(c.cache) && !(c.delayInit && event.type === 'appendCache'));
288
291
  // hide filter row using the "filtered" class name
289
- c.$table.find('.' + ts.css.filterRow).toggleClass(wo.filter_filteredRow, val ); // fixes #450
292
+ c.$table.find('.' + tscss.filterRow).toggleClass(wo.filter_filteredRow, val ); // fixes #450
290
293
  if ( !/(search|filter)/.test(event.type) ) {
291
294
  event.stopPropagation();
292
295
  ts.filter.buildDefault(table, true);
293
296
  }
294
297
  if (event.type === 'filterReset') {
295
- c.$table.find('.' + ts.css.filter).add(wo.filter_$externalFilters).val('');
298
+ c.$table.find('.' + tscss.filter).add(wo.filter_$externalFilters).val('');
296
299
  ts.filter.searching(table, []);
297
300
  } else if (event.type === 'filterEnd') {
298
301
  ts.filter.buildDefault(table, true);
@@ -355,7 +358,7 @@ ts.filter = {
355
358
  options += '<option ' + (txt === val ? '' : 'data-function-name="' + string + '" ') + 'value="' + val + '">' + txt + '</option>';
356
359
  }
357
360
  }
358
- c.$table.find('thead').find('select.' + ts.css.filter + '[data-column="' + column + '"]').append(options);
361
+ c.$table.find('thead').find('select.' + tscss.filter + '[data-column="' + column + '"]').append(options);
359
362
  }
360
363
  }
361
364
  }
@@ -364,7 +367,7 @@ ts.filter = {
364
367
  // it would append the same options twice.
365
368
  ts.filter.buildDefault(table, true);
366
369
 
367
- ts.filter.bindSearch( table, c.$table.find('.' + ts.css.filter), true );
370
+ ts.filter.bindSearch( table, c.$table.find('.' + tscss.filter), true );
368
371
  if (wo.filter_external) {
369
372
  ts.filter.bindSearch( table, wo.filter_external );
370
373
  }
@@ -379,7 +382,7 @@ ts.filter = {
379
382
  .unbind( ('filterStart filterEnd '.split(' ').join(c.namespace + 'filter ')).replace(/\s+/g, ' ') )
380
383
  .bind( 'filterStart filterEnd '.split(' ').join(c.namespace + 'filter '), function(event, columns) {
381
384
  // only add processing to certain columns to all columns
382
- $header = (columns) ? c.$table.find('.' + ts.css.header).filter('[data-column]').filter(function() {
385
+ $header = (columns) ? c.$table.find('.' + tscss.header).filter('[data-column]').filter(function() {
383
386
  return columns[$(this).data('column')] !== '';
384
387
  }) : '';
385
388
  ts.isProcessing(table, event.type === 'filterStart', columns ? $header : '');
@@ -493,7 +496,7 @@ ts.filter = {
493
496
  // c.columns defined in computeThIndexes()
494
497
  columns = c.columns,
495
498
  arry = $.isArray(wo.filter_cellFilter),
496
- buildFilter = '<tr role="row" class="' + ts.css.filterRow + '">';
499
+ buildFilter = '<tr role="row" class="' + tscss.filterRow + ' ' + c.cssIgnoreRow + '">';
497
500
  for (column = 0; column < columns; column++) {
498
501
  if (arry) {
499
502
  buildFilter += '<td' + ( wo.filter_cellFilter[column] ? ' class="' + wo.filter_cellFilter[column] + '"' : '' ) + '></td>';
@@ -542,9 +545,9 @@ ts.filter = {
542
545
  name = ( $.isArray(wo.filter_cssFilter) ?
543
546
  (typeof wo.filter_cssFilter[column] !== 'undefined' ? wo.filter_cssFilter[column] || '' : '') :
544
547
  wo.filter_cssFilter ) || '';
545
- buildFilter.addClass( ts.css.filter + ' ' + name ).attr('data-column', column);
548
+ buildFilter.addClass( tscss.filter + ' ' + name ).attr('data-column', column);
546
549
  if (disabled) {
547
- buildFilter.attr('placeholder', '').addClass('disabled')[0].disabled = true; // disabled!
550
+ buildFilter.attr('placeholder', '').addClass(tscss.filterDisabled)[0].disabled = true; // disabled!
548
551
  }
549
552
  }
550
553
  }
@@ -638,7 +641,7 @@ ts.filter = {
638
641
  }
639
642
  if (wo.filter_hideFilters) {
640
643
  // show/hide filter row as needed
641
- c.$table.find('.' + ts.css.filterRow).trigger( combinedFilters === '' ? 'mouseleave' : 'mouseenter' );
644
+ c.$table.find('.' + tscss.filterRow).trigger( combinedFilters === '' ? 'mouseleave' : 'mouseenter' );
642
645
  }
643
646
  // return if the last search is the same; but filter === false when updating the search
644
647
  // see example-widget-filter.html filter toggle buttons
@@ -664,8 +667,8 @@ ts.filter = {
664
667
  hideFilters: function(table, c) {
665
668
  var $filterRow, $filterRow2, timer;
666
669
  $(table)
667
- .find('.' + ts.css.filterRow)
668
- .addClass('hideme')
670
+ .find('.' + tscss.filterRow)
671
+ .addClass(tscss.filterRowHide)
669
672
  .bind('mouseenter mouseleave', function(e) {
670
673
  // save event object - http://bugs.jquery.com/ticket/12140
671
674
  var event = e;
@@ -673,14 +676,14 @@ ts.filter = {
673
676
  clearTimeout(timer);
674
677
  timer = setTimeout(function() {
675
678
  if ( /enter|over/.test(event.type) ) {
676
- $filterRow.removeClass('hideme');
679
+ $filterRow.removeClass(tscss.filterRowHide);
677
680
  } else {
678
681
  // don't hide if input has focus
679
682
  // $(':focus') needs jQuery 1.6+
680
683
  if ( $(document.activeElement).closest('tr')[0] !== $filterRow[0] ) {
681
684
  // don't hide row if any filter has a value
682
685
  if (c.lastCombinedFilter === '') {
683
- $filterRow.addClass('hideme');
686
+ $filterRow.addClass(tscss.filterRowHide);
684
687
  }
685
688
  }
686
689
  }
@@ -693,7 +696,7 @@ ts.filter = {
693
696
  timer = setTimeout(function() {
694
697
  // don't hide row if any filter has a value
695
698
  if (ts.getFilters(c.$table).join('') === '') {
696
- $filterRow2[ event.type === 'focus' ? 'removeClass' : 'addClass']('hideme');
699
+ $filterRow2[ event.type === 'focus' ? 'removeClass' : 'addClass'](tscss.filterRowHide);
697
700
  }
698
701
  }, 200);
699
702
  });
@@ -1181,7 +1184,7 @@ ts.filter = {
1181
1184
  // t.data('placeholder') won't work in jQuery older than 1.4.3
1182
1185
  options = '<option value="">' + ( node.data('placeholder') || node.attr('data-placeholder') || wo.filter_placeholder.select || '' ) + '</option>',
1183
1186
  // Get curent filter value
1184
- currentValue = c.$table.find('thead').find('select.' + ts.css.filter + '[data-column="' + column + '"]').val();
1187
+ currentValue = c.$table.find('thead').find('select.' + tscss.filter + '[data-column="' + column + '"]').val();
1185
1188
  // nothing included in arry (external source), so get the options from filter_selectSource or column data
1186
1189
  if (typeof arry === 'undefined' || arry === '') {
1187
1190
  arry = ts.filter.getOptionSource(table, column, onlyAvail);
@@ -1208,7 +1211,7 @@ ts.filter = {
1208
1211
  }
1209
1212
 
1210
1213
  // update all selects in the same column (clone thead in sticky headers & any external selects) - fixes 473
1211
- $filters = ( c.$filters ? c.$filters : c.$table.children('thead') ).find('.' + ts.css.filter);
1214
+ $filters = ( c.$filters ? c.$filters : c.$table.children('thead') ).find('.' + tscss.filter);
1212
1215
  if (wo.filter_$externalFilters) {
1213
1216
  $filters = $filters && $filters.length ? $filters.add(wo.filter_$externalFilters) : wo.filter_$externalFilters;
1214
1217
  }
@@ -1252,7 +1255,7 @@ ts.getFilters = function(table, getRaw, setFilters, skipFirst) {
1252
1255
  }
1253
1256
  if (c) {
1254
1257
  if (c.$filters) {
1255
- $filters = c.$filters.find('.' + ts.css.filter);
1258
+ $filters = c.$filters.find('.' + tscss.filter);
1256
1259
  }
1257
1260
  if (wo.filter_$externalFilters) {
1258
1261
  $filters = $filters && $filters.length ? $filters.add(wo.filter_$externalFilters) : wo.filter_$externalFilters;
@@ -1,4 +1,4 @@
1
- /* Output widget for TableSorter 3/5/2015 (v2.21.0)
1
+ /*! Widget: Output - updated 3/26/2015 (v2.21.3) *//*
2
2
  * Requires tablesorter v2.8+ and jQuery 1.7+
3
3
  * Modified from:
4
4
  * HTML Table to CSV: http://www.kunalbabre.com/projects/table2CSV.php (License unknown?)
@@ -160,7 +160,7 @@ output = ts.output = {
160
160
  // callback; if true returned, continue processing
161
161
  if ($.isFunction(wo.output_callback) && !wo.output_callback(c, mydata)) { return; }
162
162
 
163
- if ( /p/.test( (wo.output_delivery || '').toLowerCase() ) ) {
163
+ if ( /p/i.test( wo.output_delivery || '' ) ) {
164
164
  output.popup(mydata, wo.output_popupStyle, outputJSON || outputArray);
165
165
  } else {
166
166
  output.download(wo, mydata);
@@ -314,7 +314,6 @@ ts.addWidget({
314
314
  output_callbackJSON : function($cell, txt, cellIndex) { return txt + '(' + (cellIndex) + ')'; },
315
315
  // the need to modify this for Excel no longer exists
316
316
  output_encoding : 'data:application/octet-stream;charset=utf8,'
317
-
318
317
  },
319
318
  init: function(table, thisWidget, c) {
320
319
  output.init(c);
@@ -1,4 +1,7 @@
1
- /* Pager widget for TableSorter 3/5/2015 (v2.21.0) - requires jQuery 1.7+ */
1
+ /*! Widget: Pager - updated 3/26/2015 (v2.21.3) */
2
+ /* Requires tablesorter v2.8+ and jQuery 1.7+
3
+ * by Rob Garrison
4
+ */
2
5
  /*jshint browser:true, jquery:true, unused:false */
3
6
  ;(function($){
4
7
  "use strict";
@@ -143,7 +146,7 @@ tsp = ts.pager = {
143
146
  setSize: wo.pager_size,
144
147
  setPage: wo.pager_startPage,
145
148
  events: 'filterInit filterStart filterEnd sortEnd disable enable destroy updateComplete ' +
146
- 'pageSize pageSet pageAndSize pagerUpdate '
149
+ 'pageSize pageSet pageAndSize pagerUpdate refreshComplete '
147
150
  }, c.pager);
148
151
 
149
152
  // pager initializes multiple times before table has completed initialization
@@ -296,9 +299,12 @@ tsp = ts.pager = {
296
299
  })
297
300
  .on('pageSet.pager pagerUpdate.pager', function(e,v){
298
301
  e.stopPropagation();
299
- p.page = (parseInt(v, 10) || 1) - 1;
300
302
  // force pager refresh
301
- if (e.type === 'pagerUpdate') { p.last.page = true; }
303
+ if (e.type === 'pagerUpdate') {
304
+ v = typeof v === 'undefined' ? p.page + 1 : v;
305
+ p.last.page = true;
306
+ }
307
+ p.page = (parseInt(v, 10) || 1) - 1;
302
308
  tsp.moveToPage(table, p, true);
303
309
  tsp.updatePageDisplay(table, c, false);
304
310
  })
@@ -454,7 +460,7 @@ tsp = ts.pager = {
454
460
  p.$goto.html(t).val( p.page + 1 );
455
461
  }
456
462
  if ($out.length) {
457
- $out[ ($out[0].tagName === 'INPUT') ? 'val' : 'html' ](s);
463
+ $out[ ($out[0].nodeName === 'INPUT') ? 'val' : 'html' ](s);
458
464
  // rebind startRow/page inputs
459
465
  $out.find('.ts-startRow, .ts-page').off('change.pager').on('change.pager', function(){
460
466
  var v = $(this).val(),
@@ -1,176 +1,314 @@
1
- /*! Widget: resizable */
1
+ /*! Widget: resizable - updated 3/26/2015 (v2.21.3) */
2
2
  ;(function ($, window) {
3
3
  'use strict';
4
4
  var ts = $.tablesorter = $.tablesorter || {};
5
5
 
6
6
  $.extend(ts.css, {
7
- resizer : 'tablesorter-resizer' // resizable
7
+ resizableContainer : 'tablesorter-resizable-container',
8
+ resizableHandle : 'tablesorter-resizable-handle',
9
+ resizableNoSelect : 'tablesorter-disableSelection',
10
+ resizableStorage : 'tablesorter-resizable'
8
11
  });
9
12
 
10
- // this widget saves the column widths if
11
- // $.tablesorter.storage function is included
12
- // **************************
13
- ts.addWidget({
14
- id: "resizable",
15
- priority: 40,
16
- options: {
17
- resizable : true,
18
- resizable_addLastColumn : false,
19
- resizable_widths : [],
20
- resizable_throttle : false // set to true (5ms) or any number 0-10 range
13
+ // Add extra scroller css
14
+ $(function(){
15
+ var s = '<style>' +
16
+ 'body.' + ts.css.resizableNoSelect + ' { -ms-user-select: none; -moz-user-select: -moz-none;' +
17
+ '-khtml-user-select: none; -webkit-user-select: none; user-select: none; }' +
18
+ '.' + ts.css.resizableContainer + ' { position: relative; height: 1px; }' +
19
+ // make handle z-index > than stickyHeader z-index, so the handle stays above sticky header
20
+ '.' + ts.css.resizableHandle + ' { position: absolute; display: inline-block; width: 8px; top: 1px;' +
21
+ 'cursor: ew-resize; z-index: 3; user-select: none; -moz-user-select: none; }' +
22
+ '</style>';
23
+ $(s).appendTo('body');
24
+ });
25
+
26
+ ts.resizable = {
27
+ init : function( c, wo ) {
28
+ if ( c.$table.hasClass( 'hasResizable' ) ) { return; }
29
+ c.$table.addClass( 'hasResizable' );
30
+ ts.resizableReset( c.table, true ); // set default widths
31
+
32
+ // internal variables
33
+ wo.resizable_ = {
34
+ $wrap : c.$table.parent(),
35
+ mouseXPosition : 0,
36
+ $target : null,
37
+ $next : null,
38
+ overflow : c.$table.parent().css('overflow') === 'auto',
39
+ fullWidth : Math.abs(c.$table.parent().width() - c.$table.width()) < 20,
40
+ storedSizes : []
41
+ };
42
+
43
+ var noResize, $header, column, storedSizes,
44
+ marginTop = parseInt( c.$table.css( 'margin-top' ), 10 );
45
+
46
+ wo.resizable_.storedSizes = storedSizes = ( ( ts.storage && wo.resizable !== false ) ?
47
+ ts.storage( c.table, ts.css.resizableStorage ) :
48
+ [] ) || [];
49
+ ts.resizable.setWidths( c, wo, storedSizes );
50
+
51
+ wo.$resizable_container = $( '<div class="' + ts.css.resizableContainer + '">' )
52
+ .css({ top : marginTop })
53
+ .insertBefore( c.$table );
54
+ // add container
55
+ for ( column = 0; column < c.columns; column++ ) {
56
+ $header = c.$headerIndexed[ column ];
57
+ noResize = ts.getData( $header, ts.getColumnData( c.table, c.headers, column ), 'resizable' ) === 'false';
58
+ if ( !noResize ) {
59
+ $( '<div class="' + ts.css.resizableHandle + '">' )
60
+ .appendTo( wo.$resizable_container )
61
+ .attr({
62
+ 'data-column' : column,
63
+ 'unselectable' : 'on'
64
+ })
65
+ .data( 'header', $header )
66
+ .bind( 'selectstart', false );
67
+ }
68
+ }
69
+ c.$table.one('tablesorter-initialized', function() {
70
+ ts.resizable.setHandlePosition( c, wo );
71
+ ts.resizable.bindings( this.config, this.config.widgetOptions );
72
+ });
21
73
  },
22
- format: function(table, c, wo) {
23
- if (c.$table.hasClass('hasResizable')) { return; }
24
- c.$table.addClass('hasResizable');
25
- ts.resizableReset(table, true); // set default widths
26
- var $rows, $columns, $column, column, timer,
27
- storedSizes = {},
28
- $table = c.$table,
29
- $wrap = $table.parent(),
30
- overflow = $table.parent().css('overflow') === 'auto',
31
- mouseXPosition = 0,
32
- $target = null,
33
- $next = null,
34
- fullWidth = Math.abs($table.parent().width() - $table.width()) < 20,
35
- mouseMove = function(event){
36
- if (mouseXPosition === 0 || !$target) { return; }
37
- // resize columns
38
- var leftEdge = event.pageX - mouseXPosition,
39
- targetWidth = $target.width();
40
- $target.width( targetWidth + leftEdge );
41
- if ($target.width() !== targetWidth && fullWidth) {
42
- $next.width( $next.width() - leftEdge );
43
- } else if (overflow) {
44
- $table.width(function(i, w){
45
- return w + leftEdge;
46
- });
47
- if (!$next.length) {
48
- // if expanding right-most column, scroll the wrapper
49
- $wrap[0].scrollLeft = $table.width();
50
- }
51
- }
52
- mouseXPosition = event.pageX;
53
- },
54
- stopResize = function() {
55
- if (ts.storage && $target && $next) {
56
- storedSizes = {};
57
- storedSizes[$target.index()] = $target.width();
58
- storedSizes[$next.index()] = $next.width();
59
- $target.width( storedSizes[$target.index()] );
60
- $next.width( storedSizes[$next.index()] );
61
- if (wo.resizable !== false) {
62
- // save all column widths
63
- ts.storage(table, 'tablesorter-resizable', c.$headers.map(function(){ return $(this).width(); }).get() );
64
- }
65
- }
66
- mouseXPosition = 0;
67
- $target = $next = null;
68
- $(window).trigger('resize'); // will update stickyHeaders, just in case
69
- };
70
- storedSizes = (ts.storage && wo.resizable !== false) ? ts.storage(table, 'tablesorter-resizable') : {};
74
+
75
+ setWidth : function( $el, width ) {
76
+ $el.css({
77
+ 'width' : width,
78
+ 'min-width' : '',
79
+ 'max-width' : ''
80
+ });
81
+ },
82
+
83
+ setWidths : function( c, wo, storedSizes ) {
84
+ var column,
85
+ $extra = $( c.namespace + '_extra_headers' ),
86
+ $col = c.$table.children( 'colgroup' ).children( 'col' );
87
+ storedSizes = storedSizes || wo.resizable_.storedSizes || [];
71
88
  // process only if table ID or url match
72
- if (storedSizes) {
73
- for (column in storedSizes) {
74
- if (!isNaN(column) && column < c.$headers.length) {
75
- c.$headers.eq(column).width(storedSizes[column]); // set saved resizable widths
89
+ if ( storedSizes.length ) {
90
+ for ( column = 0; column < c.columns; column++ ) {
91
+ // set saved resizable widths
92
+ c.$headers.eq( column ).width( storedSizes[ column ] );
93
+ if ( $extra.length ) {
94
+ // stickyHeaders needs to modify min & max width as well
95
+ ts.resizable.setWidth( $extra.eq( column ).add( $col.eq( column ) ), storedSizes[ column ] );
76
96
  }
77
97
  }
98
+ if ( $( c.namespace + '_extra_table' ).length && !ts.hasWidget( c.table, 'scroller' ) ) {
99
+ ts.resizable.setWidth( $( c.namespace + '_extra_table' ), c.$table.outerWidth() );
100
+ }
78
101
  }
79
- $rows = $table.children('thead:first').children('tr');
80
- // add resizable-false class name to headers (across rows as needed)
81
- $rows.children().each(function() {
82
- var canResize,
83
- $column = $(this);
84
- column = $column.attr('data-column');
85
- canResize = ts.getData( $column, ts.getColumnData( table, c.headers, column ), 'resizable') === "false";
86
- $rows.children().filter('[data-column="' + column + '"]')[canResize ? 'addClass' : 'removeClass']('resizable-false');
87
- });
88
- // add wrapper inside each cell to allow for positioning of the resizable target block
89
- $rows.each(function() {
90
- $column = $(this).children().not('.resizable-false');
91
- if (!$(this).find('.' + ts.css.wrapper).length) {
92
- // Firefox needs this inner div to position the resizer correctly
93
- $column.wrapInner('<div class="' + ts.css.wrapper + '" style="position:relative;height:100%;width:100%"></div>');
102
+ },
103
+
104
+ setHandlePosition : function( c, wo ) {
105
+ var tableWidth = c.$table.outerWidth(),
106
+ hasScroller = ts.hasWidget( c.table, 'scroller' ),
107
+ tableHeight = c.$table.height(),
108
+ $handles = wo.$resizable_container.children(),
109
+ handleCenter = Math.floor( $handles.width() / 2 - parseFloat( c.$headers.css( 'border-right-width' ) ) * 2 );
110
+
111
+ if ( hasScroller ) {
112
+ tableHeight = 0;
113
+ c.$table.closest( '.' + ts.css.scrollerWrap ).children().each(function(){
114
+ var $this = $(this);
115
+ // center table has a max-height set
116
+ tableHeight += $this.filter('[style*="height"]').length ? $this.height() : $this.children('table').height();
117
+ });
118
+ }
119
+ $handles.each( function() {
120
+ var $this = $(this),
121
+ column = parseInt( $this.attr( 'data-column' ), 10 ),
122
+ columns = c.columns - 1,
123
+ $header = $this.data( 'header' );
124
+ if ( column < columns || column === columns && wo.resizable_addLastColumn ) {
125
+ $this.css({
126
+ height : tableHeight,
127
+ left : $header.position().left + $header.width() - handleCenter
128
+ });
94
129
  }
95
- // don't include the last column of the row
96
- if (!wo.resizable_addLastColumn) { $column = $column.slice(0,-1); }
97
- $columns = $columns ? $columns.add($column) : $column;
98
130
  });
99
- $columns
100
- .each(function() {
101
- var $column = $(this),
102
- padding = parseInt($column.css('padding-right'), 10) + 10; // 10 is 1/2 of the 20px wide resizer
103
- $column
104
- .find('.' + ts.css.wrapper)
105
- .append('<div class="' + ts.css.resizer + '" style="cursor:w-resize;position:absolute;z-index:1;right:-' +
106
- padding + 'px;top:0;height:100%;width:20px;"></div>');
107
- })
108
- .find('.' + ts.css.resizer)
109
- .bind('mousedown', function(event) {
131
+ },
132
+
133
+ // prevent text selection while dragging resize bar
134
+ toggleTextSelection : function( c, toggle ) {
135
+ var namespace = c.namespace + 'tsresize';
136
+ c.widgetOptions.resizable_.disabled = toggle;
137
+ $( 'body' ).toggleClass( ts.css.resizableNoSelect, toggle );
138
+ if ( toggle ) {
139
+ $( 'body' )
140
+ .attr( 'unselectable', 'on' )
141
+ .bind( 'selectstart' + namespace, false );
142
+ } else {
143
+ $( 'body' )
144
+ .removeAttr( 'unselectable' )
145
+ .unbind( 'selectstart' + namespace );
146
+ }
147
+ },
148
+
149
+ bindings : function( c, wo ) {
150
+ var namespace = c.namespace + 'tsresize';
151
+ wo.$resizable_container.children().bind( 'mousedown', function( event ) {
110
152
  // save header cell and mouse position
111
- $target = $(event.target).closest('th');
112
- var $header = c.$headers.filter('[data-column="' + $target.attr('data-column') + '"]');
113
- if ($header.length > 1) { $target = $target.add($header); }
153
+ var column,
154
+ vars = wo.resizable_,
155
+ $extras = $( c.namespace + '_extra_headers' ),
156
+ $header = $( event.target ).data( 'header' );
157
+
158
+ column = parseInt( $header.attr( 'data-column' ), 10 );
159
+ vars.$target = $header = $header.add( $extras.filter('[data-column="' + column + '"]') );
160
+ vars.target = column;
161
+
114
162
  // if table is not as wide as it's parent, then resize the table
115
- $next = event.shiftKey ? $target.parent().find('th').not('.resizable-false').filter(':last') : $target.nextAll(':not(.resizable-false)').eq(0);
116
- mouseXPosition = event.pageX;
163
+ vars.$next = event.shiftKey || wo.resizable_targetLast ?
164
+ $header.parent().children().not( '.resizable-false' ).filter( ':last' ) :
165
+ $header.nextAll( ':not(.resizable-false)' ).eq( 0 );
166
+
167
+ column = parseInt( vars.$next.attr( 'data-column' ), 10 );
168
+ vars.$next = vars.$next.add( $extras.filter('[data-column="' + column + '"]') );
169
+ vars.next = column;
170
+
171
+ vars.mouseXPosition = event.pageX;
172
+ vars.storedSizes = c.$headers.map(function(){ return $(this).width(); }).get();
173
+ ts.resizable.toggleTextSelection( c, true );
117
174
  });
118
- $(document)
119
- .bind('mousemove.tsresize', function(event) {
120
- // ignore mousemove if no mousedown
121
- if (mouseXPosition === 0 || !$target) { return; }
122
- if (wo.resizable_throttle) {
123
- clearTimeout(timer);
124
- timer = setTimeout(function(){
125
- mouseMove(event);
126
- }, isNaN(wo.resizable_throttle) ? 5 : wo.resizable_throttle );
127
- } else {
128
- mouseMove(event);
129
- }
130
- })
131
- .bind('mouseup.tsresize', function() {
132
- stopResize();
175
+
176
+ $( document )
177
+ .bind( 'mousemove' + namespace, function( event ) {
178
+ var vars = wo.resizable_;
179
+ // ignore mousemove if no mousedown
180
+ if ( !vars.disabled || vars.mouseXPosition === 0 || !vars.$target ) { return; }
181
+ if ( wo.resizable_throttle ) {
182
+ clearTimeout( vars.timer );
183
+ vars.timer = setTimeout( function() {
184
+ ts.resizable.mouseMove( c, wo, event );
185
+ }, isNaN( wo.resizable_throttle ) ? 5 : wo.resizable_throttle );
186
+ } else {
187
+ ts.resizable.mouseMove( c, wo, event );
188
+ }
189
+ })
190
+ .bind( 'mouseup' + namespace, function() {
191
+ if (!wo.resizable_.disabled) { return; }
192
+ ts.resizable.toggleTextSelection( c, false );
193
+ ts.resizable.stopResize( c, wo );
194
+ ts.resizable.setHandlePosition( c, wo );
195
+ });
196
+
197
+ // resizeEnd event triggered by scroller widget
198
+ $( window ).bind( 'resize' + namespace + ' resizeEnd' + namespace, function() {
199
+ ts.resizable.setHandlePosition( c, wo );
133
200
  });
134
201
 
135
202
  // right click to reset columns to default widths
136
- $table.find('thead:first').bind('contextmenu.tsresize', function() {
137
- ts.resizableReset(table);
203
+ c.$table.find( 'thead:first' ).add( $( c.namespace + '_extra_table' ).find( 'thead:first' ) )
204
+ .bind( 'contextmenu' + namespace, function() {
138
205
  // $.isEmptyObject() needs jQuery 1.4+; allow right click if already reset
139
- var allowClick = $.isEmptyObject ? $.isEmptyObject(storedSizes) : true;
140
- storedSizes = {};
206
+ var allowClick = wo.resizable_.storedSizes.length === 0;
207
+ ts.resizableReset( c.table );
208
+ ts.resizable.setHandlePosition( c, wo );
209
+ wo.resizable_.storedSizes = [];
141
210
  return allowClick;
142
211
  });
212
+
143
213
  },
144
- remove: function(table, c) {
145
- c.$table
146
- .removeClass('hasResizable')
147
- .children('thead')
148
- .unbind('mouseup.tsresize mouseleave.tsresize contextmenu.tsresize')
149
- .children('tr').children()
150
- .unbind('mousemove.tsresize mouseup.tsresize')
151
- // don't remove "tablesorter-wrapper" as uitheme uses it too
152
- .find('.' + ts.css.resizer).remove();
153
- ts.resizableReset(table);
214
+
215
+ mouseMove : function( c, wo, event ) {
216
+ if ( wo.resizable_.mouseXPosition === 0 || !wo.resizable_.$target ) { return; }
217
+ // resize columns
218
+ var vars = wo.resizable_,
219
+ $target = vars.$target,
220
+ $next = vars.$next,
221
+ leftEdge = event.pageX - vars.mouseXPosition,
222
+ targetWidth = $target.width();
223
+ if ( vars.fullWidth ) {
224
+ vars.storedSizes[ vars.target ] += leftEdge;
225
+ vars.storedSizes[ vars.next ] -= leftEdge;
226
+ ts.resizable.setWidths( c, wo );
227
+
228
+ } else if ( vars.overflow ) {
229
+ c.$table.add( $( c.namespace + '_extra_table' ) ).width(function(i, w){
230
+ return w + leftEdge;
231
+ });
232
+ if ( !$next.length ) {
233
+ // if expanding right-most column, scroll the wrapper
234
+ vars.$wrap[0].scrollLeft = c.$table.width();
235
+ }
236
+ } else {
237
+ vars.storedSizes[ vars.target ] += leftEdge;
238
+ ts.resizable.setWidths( c, wo );
239
+ }
240
+ vars.mouseXPosition = event.pageX;
241
+ },
242
+
243
+ stopResize : function( c, wo ) {
244
+ var vars = wo.resizable_;
245
+ vars.storedSizes = [];
246
+ if ( ts.storage ) {
247
+ vars.storedSizes = c.$headers.map(function(){ return $(this).width(); }).get();
248
+ if ( wo.resizable !== false ) {
249
+ // save all column widths
250
+ ts.storage( c.table, ts.css.resizableStorage, vars.storedSizes );
251
+ }
252
+ }
253
+ vars.mouseXPosition = 0;
254
+ vars.$target = vars.$next = null;
255
+ $(window).trigger('resize'); // will update stickyHeaders, just in case
256
+ }
257
+ };
258
+
259
+ // this widget saves the column widths if
260
+ // $.tablesorter.storage function is included
261
+ // **************************
262
+ ts.addWidget({
263
+ id: "resizable",
264
+ priority: 40,
265
+ options: {
266
+ resizable : true,
267
+ resizable_addLastColumn : false,
268
+ resizable_widths : [],
269
+ resizable_throttle : false, // set to true (5ms) or any number 0-10 range
270
+ resizable_targetLast : false
271
+ },
272
+ init: function(table, thisWidget, c, wo) {
273
+ ts.resizable.init( c, wo );
274
+ },
275
+ remove: function( table, c, wo ) {
276
+ if (wo.$resizable_container) {
277
+ var namespace = c.namespace + 'tsresize';
278
+ c.$table.add( $( c.namespace + '_extra_table' ) )
279
+ .removeClass('hasResizable')
280
+ .children( 'thead' ).unbind( 'contextmenu' + namespace );
281
+
282
+ wo.$resizable_container.remove();
283
+ ts.resizable.toggleTextSelection( c, false );
284
+ ts.resizableReset( table );
285
+ $( document ).unbind( 'mousemove' + namespace + ' mouseup' + namespace );
286
+ }
154
287
  }
155
288
  });
156
- ts.resizableReset = function(table, nosave) {
157
- $(table).each(function(){
289
+
290
+ ts.resizableReset = function( table, nosave ) {
291
+ $( table ).each(function(){
158
292
  var $t,
159
293
  c = this.config,
160
294
  wo = c && c.widgetOptions;
161
- if (table && c) {
162
- c.$headers.each(function(i){
295
+ if ( table && c ) {
296
+ c.$headers.each( function( i ) {
163
297
  $t = $(this);
164
- if (wo.resizable_widths && wo.resizable_widths[i]) {
165
- $t.css('width', wo.resizable_widths[i]);
166
- } else if (!$t.hasClass('resizable-false')) {
298
+ if ( wo.resizable_widths && wo.resizable_widths[ i ] ) {
299
+ $t.css( 'width', wo.resizable_widths[ i ] );
300
+ } else if ( !$t.hasClass( 'resizable-false' ) ) {
167
301
  // don't clear the width of any column that is not resizable
168
- $t.css('width','');
302
+ $t.css( 'width', '' );
169
303
  }
170
304
  });
171
- if (ts.storage && !nosave) { ts.storage(this, 'tablesorter-resizable', {}); }
305
+ // reset stickyHeader widths
306
+ $( window ).trigger( 'resize' );
307
+ if ( ts.storage && !nosave ) {
308
+ ts.storage( this, ts.css.resizableStorage, {} );
309
+ }
172
310
  }
173
311
  });
174
312
  };
175
313
 
176
- })(jQuery, window);
314
+ })( jQuery, window );