jquery-tablesorter 1.17.2 → 1.17.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/jquery-tablesorter/version.rb +1 -1
  4. data/vendor/assets/javascripts/jquery-tablesorter/addons/pager/jquery.tablesorter.pager.js +76 -71
  5. data/vendor/assets/javascripts/jquery-tablesorter/extras/jquery.dragtable.mod.js +1 -1
  6. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.combined.js +2647 -2576
  7. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.js +174 -119
  8. data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.widgets.js +2487 -2471
  9. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-extract.js +15 -15
  10. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-iso8601.js +1 -1
  11. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-month.js +4 -4
  12. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-range.js +1 -1
  13. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-two-digit-year.js +12 -12
  14. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-weekday.js +4 -4
  15. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date.js +1 -1
  16. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-duration.js +1 -1
  17. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-feet-inch-fraction.js +6 -6
  18. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-file-type.js +22 -22
  19. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-globalize.js +1 -1
  20. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-ignore-articles.js +15 -15
  21. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-image.js +3 -3
  22. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-input-select.js +10 -3
  23. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-metric.js +2 -2
  24. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-named-numbers.js +3 -3
  25. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-network.js +1 -1
  26. data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-roman.js +4 -4
  27. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-alignChar.js +122 -121
  28. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-build-table.js +13 -13
  29. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-chart.js +2 -2
  30. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-columnSelector.js +324 -324
  31. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-columns.js +60 -60
  32. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-editable.js +219 -219
  33. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter-formatter-html5.js +360 -361
  34. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter-formatter-jui.js +666 -666
  35. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter-formatter-select2.js +124 -124
  36. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter-type-insideRange.js +1 -1
  37. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-filter.js +1448 -1433
  38. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-formatter.js +1 -1
  39. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-grouping.js +213 -213
  40. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-headerTitles.js +3 -3
  41. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-math.js +271 -216
  42. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-output.js +339 -320
  43. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-pager.js +1057 -1045
  44. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-print.js +109 -109
  45. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-reflow.js +114 -115
  46. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-resizable.js +360 -359
  47. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-saveSort.js +59 -59
  48. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-scroller.js +818 -806
  49. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-sort2Hash.js +128 -0
  50. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-sortTbodies.js +195 -195
  51. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-staticRow.js +90 -90
  52. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-stickyHeaders.js +257 -257
  53. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-storage.js +76 -76
  54. data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-uitheme.js +170 -170
  55. metadata +3 -3
  56. data/vendor/assets/javascripts/jquery-tablesorter/extras/jquery.quicksearch.js +0 -195
@@ -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