jquery-tablesorter 1.17.2 → 1.17.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/jquery-tablesorter/version.rb +1 -1
  4. data/vendor/assets/javascripts/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.js +76 -71
  5. data/vendor/assets/javascripts/jquery-tablesorter/extras/jquery.dragtable.mod.js +1 -1
  6. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.combined.js +2647 -2576
  7. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.js +174 -119
  8. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets.js +2487 -2471
  9. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-extract.js +15 -15
  10. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-iso8601.js +1 -1
  11. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-month.js +4 -4
  12. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-range.js +1 -1
  13. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-two-digit-year.js +12 -12
  14. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-weekday.js +4 -4
  15. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date.js +1 -1
  16. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-duration.js +1 -1
  17. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-feet-inch-fraction.js +6 -6
  18. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-file-type.js +22 -22
  19. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-globalize.js +1 -1
  20. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-ignore-articles.js +15 -15
  21. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-image.js +3 -3
  22. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-input-select.js +10 -3
  23. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-metric.js +2 -2
  24. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-named-numbers.js +3 -3
  25. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-network.js +1 -1
  26. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-roman.js +4 -4
  27. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-alignChar.js +122 -121
  28. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-build-table.js +13 -13
  29. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-chart.js +2 -2
  30. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-columnSelector.js +324 -324
  31. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-columns.js +60 -60
  32. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-editable.js +219 -219
  33. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter-formatter-html5.js +360 -361
  34. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter-formatter-jui.js +666 -666
  35. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter-formatter-select2.js +124 -124
  36. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter-type-insideRange.js +1 -1
  37. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter.js +1448 -1433
  38. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-formatter.js +1 -1
  39. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-grouping.js +213 -213
  40. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-headerTitles.js +3 -3
  41. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-math.js +271 -216
  42. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-output.js +339 -320
  43. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-pager.js +1057 -1045
  44. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-print.js +109 -109
  45. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-reflow.js +114 -115
  46. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-resizable.js +360 -359
  47. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-saveSort.js +59 -59
  48. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-scroller.js +818 -806
  49. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-sort2Hash.js +128 -0
  50. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-sortTbodies.js +195 -195
  51. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-staticRow.js +90 -90
  52. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-stickyHeaders.js +257 -257
  53. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-storage.js +76 -76
  54. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-uitheme.js +170 -170
  55. metadata +3 -3
  56. data/vendor/assets/javascripts/jquery-tablesorter/extras/jquery.quicksearch.js +0 -195
@@ -5,14 +5,14 @@
5
5
  /*jshint browser:true, jquery:true, unused:false */
6
6
  /*global jQuery: false */
7
7
  ;(function($){
8
- "use strict";
9
- var ts = $.tablesorter;
8
+ 'use strict';
9
+ var ts = $.tablesorter;
10
10
 
11
11
  ts.addWidget({
12
12
  id: 'headerTitles',
13
13
  options: {
14
14
  // use aria-label text
15
- // e.g. "First Name: Ascending sort applied, activate to apply a descending sort"
15
+ // e.g. 'First Name: Ascending sort applied, activate to apply a descending sort'
16
16
  headerTitle_useAria : false,
17
17
  // add tooltip class
18
18
  headerTitle_tooltip : '',
@@ -1,180 +1,220 @@
1
- /*! Widget: math - updated 5/17/2015 (v2.22.0) *//*
1
+ /*! Widget: math - updated 7/28/2015 (v2.22.4) *//*
2
2
  * Requires tablesorter v2.16+ and jQuery 1.7+
3
3
  * by Rob Garrison
4
4
  */
5
5
  /*jshint browser:true, jquery:true, unused:false */
6
6
  /*global jQuery: false */
7
- ;(function($) {
8
- "use strict";
7
+ ;( function( $ ) {
8
+ 'use strict';
9
9
 
10
10
  var ts = $.tablesorter,
11
11
 
12
12
  math = {
13
13
 
14
+ error: {
15
+ 0 : 'Infinity result: Divide by zero',
16
+ 1 : 'Need more than one element to make this calculation',
17
+ 'undef' : 'No elements found'
18
+ },
19
+
20
+ // value returned when calculation is not possible, e.g. no values, dividing by zero, etc.
21
+ invalid : function( name, errorIndex ) {
22
+ // name = function returning invalid results
23
+ // errorIndex = math.error index with an explanation of the error
24
+ console.log( name, math.error[ errorIndex ] );
25
+ return 'none'; // text for cell
26
+ },
27
+
14
28
  events : ( 'tablesorter-initialized update updateAll updateRows addRows updateCell ' +
15
29
  'filterReset filterEnd ' ).split(' ').join('.tsmath '),
16
30
 
31
+ processText : function( c, $cell ) {
32
+ var txt = $cell.attr( c.textAttribute );
33
+ if ( typeof txt === 'undefined' ) {
34
+ txt = $cell[0].textContent || $cell.text();
35
+ }
36
+ txt = ts.formatFloat( txt.replace( /[^\w,. \-()]/g, '' ), c.table ) || 0;
37
+ // isNaN('') => false
38
+ return isNaN( txt ) ? 0 : txt;
39
+ },
40
+
17
41
  // get all of the row numerical values in an arry
18
- getRow : function(table, wo, $el, dataAttrib) {
42
+ getRow : function( c, $el ) {
19
43
  var $t, txt,
20
- c = table.config,
44
+ wo = c.widgetOptions,
21
45
  arry = [],
22
- $row = $el.closest('tr'),
23
- $cells = $row.children().not('[' + dataAttrib + '=ignore]');
24
- if (!$row.hasClass(wo.filter_filteredRow || 'filtered')) {
25
- if (wo.math_ignore.length) {
26
- $cells = $cells.not('[data-column=' + wo.math_ignore.join('],[data-column=') + ']');
46
+ $row = $el.closest( 'tr' ),
47
+ $cells = $row.children().not( '[' + wo.math_dataAttrib + '=ignore]' );
48
+ if ( !$row.hasClass( wo.filter_filteredRow || 'filtered' ) ) {
49
+ if ( wo.math_ignore.length ) {
50
+ $cells = $cells.not( '[data-column=' + wo.math_ignore.join( '],[data-column=' ) + ']' );
27
51
  }
28
- arry = $cells.not($el).map(function(){
29
- $t = $(this);
30
- txt = $t.attr(c.textAttribute);
31
- if (typeof txt === "undefined") {
32
- txt = this.textContent || $t.text();
33
- }
34
- txt = ts.formatFloat(txt.replace(/[^\w,. \-()]/g, ""), table) || 0;
35
- return isNaN(txt) ? 0 : txt;
52
+ arry = $cells.not( $el ).map( function() {
53
+ return math.processText( c, $( this ) );
36
54
  }).get();
37
55
  }
38
56
  return arry;
39
57
  },
40
58
 
41
59
  // get all of the column numerical values in an arry
42
- getColumn : function(table, wo, $el, type, dataAttrib) {
43
- var i, txt, $t, len, mathAbove,
60
+ getColumn : function( c, $el, type ) {
61
+ var index, txt, $t, len, $mathRows, mathAbove,
44
62
  arry = [],
45
- c = table.config,
63
+ wo = c.widgetOptions,
46
64
  filtered = wo.filter_filteredRow || 'filtered',
47
- cIndex = parseInt( $el.attr('data-column'), 10 ),
48
- $rows = c.$table.children('tbody').children(),
49
- $row = $el.closest('tr');
65
+ cIndex = parseInt( $el.attr( 'data-column' ), 10 ),
66
+ $rows = c.$table.children( 'tbody' ).children(),
67
+ $row = $el.closest( 'tr' );
50
68
  // make sure tfoot rows are AFTER the tbody rows
51
- // $rows.add( c.$table.children('tfoot').children() );
52
- if (type === 'above') {
53
- len = $rows.index($row);
54
- i = len;
55
- while (i >= 0) {
56
- $t = $rows.eq(i).children().filter('[data-column=' + cIndex + ']');
57
- mathAbove = $t.filter('[' + dataAttrib + '^=above]').length;
69
+ // $rows.add( c.$table.children( 'tfoot' ).children() );
70
+ if ( type === 'above' ) {
71
+ len = $rows.index( $row );
72
+ index = len;
73
+ while ( index >= 0 ) {
74
+ $t = $rows.eq( index ).children().filter( '[data-column=' + cIndex + ']' );
75
+ mathAbove = $t.filter( '[' + wo.math_dataAttrib + '^=above]' ).length;
58
76
  // ignore filtered rows & rows with data-math="ignore" (and starting row)
59
- if ( ( !$rows.eq(i).hasClass(filtered) && $rows.eq(i).not('[' + dataAttrib + '=ignore]').length && i !== len ) || mathAbove && i !== len ) {
60
- // stop calculating "above", when encountering another "above"
61
- if (mathAbove) {
62
- i = 0;
63
- } else if ($t.length) {
64
- txt = $t.attr(c.textAttribute);
65
- if (typeof txt === "undefined") {
66
- txt = $t[0].textContent || $t.text();
67
- }
68
- txt = ts.formatFloat(txt.replace(/[^\w,. \-()]/g, ""), table) || 0;
69
- arry.push(isNaN(txt) ? 0 : txt);
77
+ if ( ( !$rows.eq( index ).hasClass( filtered ) &&
78
+ $rows.eq( index ).not( '[' + wo.math_dataAttrib + '=ignore]' ).length &&
79
+ index !== len ) ||
80
+ mathAbove && index !== len ) {
81
+ // stop calculating 'above', when encountering another 'above'
82
+ if ( mathAbove ) {
83
+ index = 0;
84
+ } else if ( $t.length ) {
85
+ arry.push( math.processText( c, $t ) );
70
86
  }
71
87
  }
72
- i--;
88
+ index--;
73
89
  }
74
90
  } else {
75
- $rows.each(function(){
76
- $t = $(this).children().filter('[data-column=' + cIndex + ']');
77
- if (!$(this).hasClass(filtered) && $t.not('[' + dataAttrib + '^=above],[' + dataAttrib + '^=col]').length && !$t.is($el)) {
78
- txt = $t.attr(c.textAttribute);
79
- if (typeof txt === "undefined") {
80
- txt = ($t[0] ? $t[0].textContent : '') || $t.text();
81
- }
82
- // isNaN('') => false
83
- txt = ts.formatFloat(txt.replace(/[^\w,. \-()]/g, ""), table) || 0;
84
- arry.push(isNaN(txt) ? 0 : txt);
91
+ $mathRows = $rows.not( '[' + wo.math_dataAttrib + '=ignore]' ); // .each(function(){
92
+ len = $mathRows.length;
93
+ for ( index = 0; index < len; index++ ) {
94
+ $t = $mathRows.eq( index ).children().filter( '[data-column=' + cIndex + ']' );
95
+ if ( !$mathRows.eq( index ).hasClass( filtered ) &&
96
+ $t.not( '[' + wo.math_dataAttrib + '^=above],[' + wo.math_dataAttrib + '^=col]' ).length &&
97
+ !$t.is( $el ) ) {
98
+ arry.push( math.processText( c, $t ) );
85
99
  }
86
- });
100
+ }
87
101
  }
88
102
  return arry;
89
103
  },
90
104
 
91
105
  // get all of the column numerical values in an arry
92
- getAll : function(table, wo, dataAttrib) {
93
- var txt, $t, col,
106
+ getAll : function( c ) {
107
+ var txt, $t, col, $row, rowIndex, rowLen, $cells, cellIndex, cellLen,
94
108
  arry = [],
95
- c = table.config,
109
+ wo = c.widgetOptions,
96
110
  filtered = wo.filter_filteredRow || 'filtered',
97
- $rows = c.$table.children('tbody').children();
98
- $rows.each(function(){
99
- if (!$(this).hasClass(filtered)) {
100
- $(this).children().each(function(){
101
- $t = $(this);
102
- col = parseInt( $t.attr('data-column'), 10);
103
- if (!$t.filter('[' + dataAttrib + ']').length && $.inArray(col, wo.math_ignore) < 0) {
104
- txt = $t.attr(c.textAttribute);
105
- if (typeof txt === "undefined") {
106
- txt = ($t[0] ? $t[0].textContent : '') || $t.text();
107
- }
108
- txt = ts.formatFloat(txt.replace(/[^\w,. \-()]/g, ""), table) || 0;
109
- arry.push(isNaN(txt) ? 0 : txt);
111
+ $rows = c.$table.children( 'tbody' ).children().not( '[' + wo.math_dataAttrib + '=ignore]' );
112
+ rowLen = $rows.length;
113
+ for ( rowIndex = 0; rowIndex < rowLen; rowIndex++ ) {
114
+ $row = $rows.eq( rowIndex );
115
+ if ( !$row.hasClass( filtered ) ) {
116
+ $cells = $row.children().not( '[' + wo.math_dataAttrib + '=ignore]' );
117
+ cellLen = $cells.length;
118
+ // $row.children().each(function(){
119
+ for ( cellIndex = 0; cellIndex < cellLen; cellIndex++ ) {
120
+ $t = $cells.eq( cellIndex );
121
+ col = parseInt( $t.attr( 'data-column' ), 10);
122
+ if ( !$t.filter( '[' + wo.math_dataAttrib + ']' ).length && $.inArray( col, wo.math_ignore ) < 0 ) {
123
+ arry.push( math.processText( c, $t ) );
110
124
  }
111
- });
125
+ }
112
126
  }
113
- });
127
+ }
114
128
  return arry;
115
129
  },
116
130
 
117
131
  recalculate : function(table, c, wo, init) {
118
- if (c && (!wo.math_isUpdating || init)) {
132
+ if ( c && ( !wo.math_isUpdating || init ) ) {
119
133
 
120
134
  // add data-column attributes to all table cells
121
- if (init) {
122
- ts.computeColumnIndex( c.$table.children('tbody').children() );
135
+ if ( init ) {
136
+ ts.computeColumnIndex( c.$table.children( 'tbody' ).children() );
123
137
  }
124
138
 
125
139
  // data-attribute name (defaults to data-math)
126
- var dataAttrib = 'data-' + (wo.math_data || 'math'),
140
+ wo.math_dataAttrib = 'data-' + (wo.math_data || 'math');
127
141
 
128
142
  // all non-info tbody cells
129
- $mathCells = c.$tbodies.find('[' + dataAttrib + ']');
130
- math.mathType( table, wo, $mathCells, wo.math_priority, dataAttrib );
143
+ var $mathCells = c.$tbodies.find( '[' + wo.math_dataAttrib + ']' );
144
+ math.mathType( c, $mathCells, wo.math_priority );
131
145
 
132
146
  // only info tbody cells
133
- $mathCells = c.$table.find('.' + c.cssInfoBlock + ', tfoot').find('[' + dataAttrib + ']');
134
- math.mathType( table, wo, $mathCells, wo.math_priority, dataAttrib );
147
+ $mathCells = c.$table
148
+ .children( '.' + c.cssInfoBlock + ', tfoot' )
149
+ .find( '[' + wo.math_dataAttrib + ']' );
150
+ math.mathType( c, $mathCells, wo.math_priority );
135
151
 
136
- // find the "all" total
137
- math.mathType( table, wo, c.$table.find('[' + dataAttrib + '^=all]'), ['all'], dataAttrib );
152
+ // find the 'all' total
153
+ $mathCells = c.$table.find( '[' + wo.math_dataAttrib + '^=all]' );
154
+ math.mathType( c, $mathCells, [ 'all' ] );
138
155
 
139
156
  wo.math_isUpdating = true;
140
- c.$table.trigger('update');
157
+ if ( c.debug ) {
158
+ console[ console.group ? 'group' : 'log' ]( 'Math widget triggering an update after recalculation' );
159
+ }
160
+ c.$table.trigger( 'update' );
141
161
  }
142
162
  },
143
163
 
144
- mathType : function(table, wo, $cells, priority, dataAttrib) {
145
- if ($cells.length) {
146
- var formula, t, $t, arry, getAll,
147
- eq = ts.equations;
148
- if (priority[0] === 'all') {
164
+ mathType : function( c, $cells, priority ) {
165
+ if ( $cells.length ) {
166
+ var formula, result, $el, arry, getAll, $targetCells, index, len,
167
+ wo = c.widgetOptions,
168
+ equations = ts.equations;
169
+ if ( priority[0] === 'all' ) {
149
170
  // no need to get all cells more than once
150
- getAll = math.getAll(table, wo, dataAttrib);
171
+ getAll = math.getAll( c );
151
172
  }
152
- $.each( priority, function(i, type) {
153
- $cells.filter('[' + dataAttrib + '^=' + type + ']').each(function(){
154
- $t = $(this);
155
- formula = ($t.attr(dataAttrib) || '').replace(type + '-', '');
156
- arry = (type === "row") ? math.getRow(table, wo, $t, dataAttrib) :
157
- (type === "all") ? getAll : math.getColumn(table, wo, $t, type, dataAttrib);
158
- if (eq[formula]) {
159
- t = eq[formula](arry);
160
- if (table.config.debug && console && console.log) {
161
- console.log($t.attr(dataAttrib), arry, '=', t);
173
+ if (c.debug) {
174
+ console[ console.group ? 'group' : 'log' ]( 'Tablesorter Math widget recalculation' );
175
+ }
176
+ // $.each is okay here... only 3 priorities
177
+ $.each( priority, function( i, type ) {
178
+ $targetCells = $cells.filter( '[' + wo.math_dataAttrib + '^=' + type + ']' );
179
+ len = $targetCells.length;
180
+ if ( len ) {
181
+ if (c.debug) {
182
+ console[ console.group ? 'group' : 'log' ]( type );
183
+ }
184
+ for ( index = 0; index < len; index++ ) {
185
+ $el = $targetCells.eq( index );
186
+ formula = ( $el.attr( wo.math_dataAttrib ) || '' ).replace( type + '-', '' );
187
+ arry = ( type === 'row' ) ? math.getRow( c, $el ) :
188
+ ( type === 'all' ) ? getAll : math.getColumn( c, $el, type );
189
+ if ( equations[ formula ] ) {
190
+ if ( arry.length ) {
191
+ result = equations[ formula ]( arry );
192
+ if ( c.debug ) {
193
+ console.log( $el.attr( wo.math_dataAttrib ), arry, '=', result );
194
+ }
195
+ } else {
196
+ // mean will return a divide by zero error, everything else shows an undefined error
197
+ result = math.invalid( formula, formula === 'mean' ? 0 : 'undef' );
198
+ }
199
+ math.output( $el, wo, result, arry );
162
200
  }
163
- math.output( $t, wo, t, arry );
164
201
  }
165
- });
202
+ if ( c.debug && console.groupEnd ) { console.groupEnd(); }
203
+ }
166
204
  });
205
+ if ( c.debug && console.groupEnd ) { console.groupEnd(); }
167
206
  }
168
207
  },
169
208
 
170
- output : function($cell, wo, value, arry) {
209
+ output : function( $cell, wo, value, arry ) {
171
210
  // get mask from cell data-attribute: data-math-mask="#,##0.00"
172
- var result = ts.formatMask( $cell.attr('data-' + wo.math_data + '-mask') || wo.math_mask, value, wo.math_wrapPrefix, wo.math_wrapSuffix );
173
- if ($.isFunction(wo.math_complete)) {
174
- result = wo.math_complete($cell, wo, result, value, arry);
211
+ var mask = $cell.attr( 'data-' + wo.math_data + '-mask' ) || wo.math_mask,
212
+ result = ts.formatMask( mask, value, wo.math_wrapPrefix, wo.math_wrapSuffix );
213
+ if ( typeof wo.math_complete === 'function' ) {
214
+ result = wo.math_complete( $cell, wo, result, value, arry );
175
215
  }
176
- if (result !== false) {
177
- $cell.html(result);
216
+ if ( result !== false ) {
217
+ $cell.html( result );
178
218
  }
179
219
  }
180
220
 
@@ -188,146 +228,153 @@
188
228
  * (c)2011 ecava
189
229
  * Dual licensed under the MIT or GPL Version 2 licenses.
190
230
  */
191
- ts.formatMask = function(m, v, tmpPrefix, tmpSuffix) {
192
- if ( !m || isNaN(+v) ) {
193
- return v; // return as it is.
231
+ ts.formatMask = function( mask, val, tmpPrefix, tmpSuffix ) {
232
+ if ( !mask || isNaN( +val ) ) {
233
+ return val; // return as it is.
194
234
  }
195
235
 
196
236
  var isNegative, result, decimal, group, posLeadZero, posTrailZero, posSeparator, part, szSep,
197
- integer, str, offset, i, l, len, start, tmp, end, inv,
198
- prefix = '',
199
- suffix = '';
200
-
201
- // find prefix/suffix
202
- len = m.length;
203
- start = m.search( /[0-9\-\+#]/ );
204
- tmp = start > 0 ? m.substring(0, start) : '';
205
- prefix = tmp;
237
+ integer, str, offset, index, end, inv,
238
+ suffix = '',
239
+
240
+ // find prefix/suffix
241
+ len = mask.length,
242
+ start = mask.search( /[0-9\-\+#]/ ),
243
+ tmp = start > 0 ? mask.substring( 0, start ) : '',
244
+ prefix = tmp;
245
+
206
246
  if ( start > 0 && tmpPrefix ) {
207
- if ( /\{content\}/.test(tmpPrefix || '') ) {
208
- prefix = (tmpPrefix || '').replace(/\{content\}/g, tmp || '');
247
+ if ( /\{content\}/.test( tmpPrefix || '' ) ) {
248
+ prefix = ( tmpPrefix || '' ).replace( /\{content\}/g, tmp || '' );
209
249
  } else {
210
- prefix = (tmpPrefix || '') + tmp;
250
+ prefix = ( tmpPrefix || '' ) + tmp;
211
251
  }
212
252
  }
213
253
  // reverse string: not an ideal method if there are surrogate pairs
214
- inv = m.split('').reverse().join('');
254
+ inv = mask.split( '' ).reverse().join( '' );
215
255
  end = inv.search( /[0-9\-\+#]/ );
216
- i = len - end;
217
- i += (m.substring( i, i + 1 ) === '.') ? 1 : 0;
218
- tmp = end > 0 ? m.substring( i, len) : '';
256
+ index = len - end;
257
+ index += ( mask.substring( index, index + 1 ) === '.' ) ? 1 : 0;
258
+ tmp = end > 0 ? mask.substring( index, len ) : '';
219
259
  suffix = tmp;
220
- if (tmp !== '' && tmpSuffix) {
221
- if ( /\{content\}/.test(tmpSuffix || '') ) {
222
- suffix = (tmpSuffix || '').replace(/\{content\}/g, tmp || '');
260
+ if ( tmp !== '' && tmpSuffix ) {
261
+ if ( /\{content\}/.test( tmpSuffix || '' ) ) {
262
+ suffix = ( tmpSuffix || '' ).replace( /\{content\}/g, tmp || '' );
223
263
  } else {
224
- suffix = tmp + (tmpSuffix || '');
264
+ suffix = tmp + ( tmpSuffix || '' );
225
265
  }
226
266
  }
227
- m = m.substring(start, i);
267
+ mask = mask.substring( start, index );
228
268
 
229
269
  // convert any string to number according to formation sign.
230
- v = m.charAt(0) == '-' ? -v : +v;
231
- isNegative = v < 0 ? v = -v : 0; // process only abs(), and turn on flag.
270
+ val = mask.charAt( 0 ) == '-' ? -val : +val;
271
+ isNegative = val < 0 ? val = -val : 0; // process only abs(), and turn on flag.
232
272
 
233
273
  // search for separator for grp & decimal, anything not digit, not +/- sign, not #.
234
- result = m.match( /[^\d\-\+#]/g );
235
- decimal = ( result && result[result.length-1] ) || '.'; // treat the right most symbol as decimal
236
- group = ( result && result[1] && result[0] ) || ','; // treat the left most symbol as group separator
274
+ result = mask.match( /[^\d\-\+#]/g );
275
+ decimal = ( result && result[ result.length - 1 ] ) || '.'; // treat the right most symbol as decimal
276
+ group = ( result && result[ 1 ] && result[ 0 ] ) || ','; // treat the left most symbol as group separator
237
277
 
238
278
  // split the decimal for the format string if any.
239
- m = m.split( decimal );
279
+ mask = mask.split( decimal );
240
280
  // Fix the decimal first, toFixed will auto fill trailing zero.
241
- v = v.toFixed( m[1] && m[1].length );
242
- v = +(v) + ''; // convert number to string to trim off *all* trailing decimal zero(es)
281
+ val = val.toFixed( mask[ 1 ] && mask[ 1 ].length );
282
+ val = +( val ) + ''; // convert number to string to trim off *all* trailing decimal zero(es)
243
283
 
244
284
  // fill back any trailing zero according to format
245
- posTrailZero = m[1] && m[1].lastIndexOf('0'); // look for last zero in format
246
- part = v.split('.');
285
+ posTrailZero = mask[ 1 ] && mask[ 1 ].lastIndexOf( '0' ); // look for last zero in format
286
+ part = val.split( '.' );
247
287
  // integer will get !part[1]
248
- if ( !part[1] || ( part[1] && part[1].length <= posTrailZero ) ) {
249
- v = (+v).toFixed( posTrailZero + 1 );
288
+ if ( !part[ 1 ] || ( part[ 1 ] && part[ 1 ].length <= posTrailZero ) ) {
289
+ val = ( +val ).toFixed( posTrailZero + 1 );
250
290
  }
251
- szSep = m[0].split( group ); // look for separator
252
- m[0] = szSep.join(''); // join back without separator for counting the pos of any leading 0.
291
+ szSep = mask[ 0 ].split( group ); // look for separator
292
+ mask[ 0 ] = szSep.join( '' ); // join back without separator for counting the pos of any leading 0.
253
293
 
254
- posLeadZero = m[0] && m[0].indexOf('0');
294
+ posLeadZero = mask[ 0 ] && mask[ 0 ].indexOf( '0' );
255
295
  if ( posLeadZero > -1 ) {
256
- while ( part[0].length < ( m[0].length - posLeadZero ) ) {
257
- part[0] = '0' + part[0];
296
+ while ( part[ 0 ].length < ( mask[ 0 ].length - posLeadZero ) ) {
297
+ part[ 0 ] = '0' + part[ 0 ];
258
298
  }
259
- } else if ( +part[0] === 0 ) {
260
- part[0] = '';
299
+ } else if ( +part[ 0 ] === 0 ) {
300
+ part[ 0 ] = '';
261
301
  }
262
302
 
263
- v = v.split('.');
264
- v[0] = part[0];
303
+ val = val.split( '.' );
304
+ val[ 0 ] = part[ 0 ];
265
305
 
266
306
  // process the first group separator from decimal (.) only, the rest ignore.
267
307
  // get the length of the last slice of split result.
268
- posSeparator = ( szSep[1] && szSep[ szSep.length - 1 ].length );
308
+ posSeparator = ( szSep[ 1 ] && szSep[ szSep.length - 1 ].length );
269
309
  if ( posSeparator ) {
270
- integer = v[0];
310
+ integer = val[ 0 ];
271
311
  str = '';
272
312
  offset = integer.length % posSeparator;
273
- l = integer.length;
274
- for ( i = 0; i < l; i++ ) {
275
- str += integer.charAt(i); // ie6 only support charAt for sz.
313
+ len = integer.length;
314
+ for ( index = 0; index < len; index++ ) {
315
+ str += integer.charAt( index ); // ie6 only support charAt for sz.
276
316
  // -posSeparator so that won't trail separator on full length
277
317
  /*jshint -W018 */
278
- if ( !( ( i - offset + 1 ) % posSeparator ) && i < l - posSeparator ) {
318
+ if ( !( ( index - offset + 1 ) % posSeparator ) && index < l - posSeparator ) {
279
319
  str += group;
280
320
  }
281
321
  }
282
- v[0] = str;
322
+ val[ 0 ] = str;
283
323
  }
284
324
 
285
- v[1] = ( m[1] && v[1] ) ? decimal + v[1] : "";
325
+ val[ 1 ] = ( mask[ 1 ] && val[ 1 ] ) ? decimal + val[ 1 ] : '';
286
326
  // put back any negation, combine integer and fraction, and add back prefix & suffix
287
- return prefix + ( ( isNegative ? '-' : '' ) + v[0] + v[1] ) + suffix;
327
+ return prefix + ( ( isNegative ? '-' : '' ) + val[ 0 ] + val[ 1 ] ) + suffix;
288
328
  };
289
329
 
290
330
  ts.equations = {
291
- count : function(arry) {
331
+ count : function( arry ) {
292
332
  return arry.length;
293
333
  },
294
- sum : function(arry) {
295
- var total = 0;
296
- $.each( arry, function(i) {
297
- total += arry[i];
298
- });
334
+ sum : function( arry ) {
335
+ var index,
336
+ len = arry.length,
337
+ total = 0;
338
+ for ( index = 0; index < len; index++ ) {
339
+ total += arry[ index ];
340
+ }
299
341
  return total;
300
342
  },
301
- mean : function(arry) {
343
+ mean : function( arry ) {
302
344
  var total = ts.equations.sum( arry );
303
345
  return total / arry.length;
304
346
  },
305
- median : function(arry) {
306
- // https://gist.github.com/caseyjustus/1166258
307
- arry.sort( function(a,b){ return a - b; } );
308
- var half = Math.floor( arry.length / 2 );
309
- return (arry.length % 2) ? arry[half] : ( arry[half - 1] + arry[half] ) / 2.0;
347
+ median : function( arry ) {
348
+ var half,
349
+ len = arry.length;
350
+ if ( len > 1 ) {
351
+ // https://gist.github.com/caseyjustus/1166258
352
+ arry.sort( function( a, b ){ return a - b; } );
353
+ half = Math.floor( len / 2 );
354
+ return ( len % 2 ) ? arry[ half ] : ( arry[ half - 1 ] + arry[ half ] ) / 2;
355
+ }
356
+ return math.invalid( 'median', 1 );
310
357
  },
311
- mode : function(arry) {
358
+ mode : function( arry ) {
312
359
  // http://stackoverflow.com/a/3451640/145346
313
- if ( arry.length === 0 ) { return 'none'; }
314
- var i, el,
360
+ var index, el, m,
315
361
  modeMap = {},
316
362
  maxCount = 1,
317
- modes = [arry[0]];
318
- for (i = 0; i < arry.length; i++) {
319
- el = arry[i];
320
- modeMap[el] = modeMap[el] ? modeMap[el] + 1 : 1;
321
- if ( modeMap[el] > maxCount ) {
322
- modes = [el];
323
- maxCount = modeMap[el];
324
- } else if (modeMap[el] === maxCount) {
325
- modes.push(el);
326
- maxCount = modeMap[el];
363
+ modes = [ arry[ 0 ] ];
364
+ for ( index = 0; index < arry.length; index++ ) {
365
+ el = arry[ index ];
366
+ modeMap[ el ] = modeMap[ el ] ? modeMap[ el ] + 1 : 1;
367
+ m = modeMap[ el ];
368
+ if ( m > maxCount ) {
369
+ modes = [ el ];
370
+ maxCount = m;
371
+ } else if ( m === maxCount ) {
372
+ modes.push( el );
373
+ maxCount = m;
327
374
  }
328
375
  }
329
376
  // returns arry of modes if there is a tie
330
- return modes.sort( function(a,b){ return a - b; } );
377
+ return modes.sort( function( a, b ){ return a - b; } );
331
378
  },
332
379
  max : function(arry) {
333
380
  return Math.max.apply( Math, arry );
@@ -336,37 +383,42 @@
336
383
  return Math.min.apply( Math, arry );
337
384
  },
338
385
  range: function(arry) {
339
- var v = arry.sort(function(a,b){ return a - b; });
340
- return v[ arry.length - 1 ] - v[0];
386
+ var v = arry.sort( function( a, b ){ return a - b; } );
387
+ return v[ arry.length - 1 ] - v[ 0 ];
341
388
  },
342
389
  // common variance equation
343
390
  // (not accessible via data-attribute setting)
344
- variance: function(arry, population) {
345
- var avg = ts.equations.mean( arry ),
391
+ variance: function( arry, population ) {
392
+ var divisor,
393
+ avg = ts.equations.mean( arry ),
346
394
  v = 0,
347
395
  i = arry.length;
348
- while (i--) {
349
- v += Math.pow( ( arry[i] - avg ), 2 );
396
+ while ( i-- ) {
397
+ v += Math.pow( ( arry[ i ] - avg ), 2 );
398
+ }
399
+ divisor = ( arry.length - ( population ? 0 : 1 ) );
400
+ if ( divisor === 0 ) {
401
+ return math.invalid( 'variance', 0 );
350
402
  }
351
- v /= ( arry.length - (population ? 0 : 1) );
403
+ v /= divisor;
352
404
  return v;
353
405
  },
354
406
  // variance (population)
355
- varp : function(arry) {
356
- return ts.equations.variance(arry, true);
407
+ varp : function( arry ) {
408
+ return ts.equations.variance( arry, true );
357
409
  },
358
410
  // variance (sample)
359
- vars : function(arry) {
360
- return ts.equations.variance(arry);
411
+ vars : function( arry ) {
412
+ return ts.equations.variance( arry );
361
413
  },
362
414
  // standard deviation (sample)
363
- stdevs : function(arry) {
364
- var vars = ts.equations.variance(arry);
415
+ stdevs : function( arry ) {
416
+ var vars = ts.equations.variance( arry );
365
417
  return Math.sqrt( vars );
366
418
  },
367
419
  // standard deviation (population)
368
- stdevp : function(arry) {
369
- var varp = ts.equations.variance(arry, true);
420
+ stdevp : function( arry ) {
421
+ var varp = ts.equations.variance( arry, true );
370
422
  return Math.sqrt( varp );
371
423
  }
372
424
  };
@@ -374,7 +426,7 @@
374
426
  // add new widget called repeatHeaders
375
427
  // ************************************
376
428
  ts.addWidget({
377
- id: "math",
429
+ id: 'math',
378
430
  priority: 100,
379
431
  options: {
380
432
  math_data : 'math',
@@ -384,7 +436,7 @@
384
436
  math_mask : '#,##0.00',
385
437
  // complete executed after each fucntion
386
438
  math_complete : null, // function($cell, wo, result, value, arry){ return result; },
387
- // order of calculation; "all" is last
439
+ // order of calculation; 'all' is last
388
440
  math_priority : [ 'row', 'above', 'col' ],
389
441
  // template for or just prepend the mask prefix & suffix with this HTML
390
442
  // e.g. '<span class="red">{content}</span>'
@@ -392,33 +444,36 @@
392
444
  math_suffix : '',
393
445
  math_event : 'recalculate'
394
446
  },
395
- init : function(table, thisWidget, c, wo) {
447
+ init : function( table, thisWidget, c, wo ) {
448
+ // filterEnd fires after updateComplete
449
+ var update = ts.hasWidget( table, 'filter' ) ? 'filterEnd' : 'updateComplete';
396
450
  c.$table
397
- .off( (math.events + ' updateComplete.tsmath ' + wo.math_event).replace(/\s+/g, ' ') )
398
- .on(math.events + ' ' + wo.math_event, function(e) {
451
+ .off( ( math.events + ' updateComplete.tsmath ' + wo.math_event ).replace( /\s+/g, ' ' ) )
452
+ .on( math.events + ' ' + wo.math_event, function( e ) {
399
453
  var init = e.type === 'tablesorter-initialized';
400
454
  if ( !wo.math_isUpdating || init ) {
401
- if ( !/filter/.test(e.type) ) {
455
+ if ( !/filter/.test( e.type ) ) {
402
456
  // redo data-column indexes on update
403
457
  ts.computeColumnIndex( c.$table.children('tbody').children() );
404
458
  }
405
459
  math.recalculate( table, c, wo, init );
406
460
  }
407
461
  })
408
- .on('updateComplete.tsmath', function(){
409
- setTimeout(function(){
462
+ .on( update + '.tsmath', function() {
463
+ setTimeout( function(){
464
+ if ( wo.math_isUpdating && c.debug && console.groupEnd ) { console.groupEnd(); }
410
465
  wo.math_isUpdating = false;
411
- }, 20);
466
+ }, 40 );
412
467
  });
413
468
  wo.math_isUpdating = false;
414
469
  },
415
470
  // this remove function is called when using the refreshWidgets method or when destroying the tablesorter plugin
416
471
  // this function only applies to tablesorter v2.4+
417
- remove: function(table, c, wo, refreshing) {
418
- if (refreshing) { return; }
419
- $(table)
420
- .off( (math.events + ' updateComplete.tsmath ' + wo.math_event).replace(/\s+/g, ' ') )
421
- .find('[data-' + wo.math_data + ']').empty();
472
+ remove: function( table, c, wo, refreshing ) {
473
+ if ( refreshing ) { return; }
474
+ c.$table
475
+ .off( ( math.events + ' updateComplete.tsmath ' + wo.math_event ).replace( /\s+/g, ' ' ) )
476
+ .find( '[data-' + wo.math_data + ']' ).empty();
422
477
  }
423
478
  });
424
479