rubycritic 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -1
  3. data/CONTRIBUTING.md +2 -1
  4. data/README.md +1 -0
  5. data/lib/rubycritic/cli/options.rb +17 -1
  6. data/lib/rubycritic/commands/ci.rb +2 -3
  7. data/lib/rubycritic/commands/default.rb +2 -3
  8. data/lib/rubycritic/configuration.rb +4 -1
  9. data/lib/rubycritic/core/analysed_module.rb +19 -0
  10. data/lib/rubycritic/core/location.rb +11 -0
  11. data/lib/rubycritic/core/rating.rb +8 -0
  12. data/lib/rubycritic/core/smell.rb +16 -0
  13. data/lib/rubycritic/{report_generators → generators/html}/assets/javascripts/application.js +0 -0
  14. data/lib/rubycritic/{report_generators → generators/html}/assets/javascripts/highcharts.src-4.0.1.js +0 -0
  15. data/lib/rubycritic/{report_generators → generators/html}/assets/javascripts/jquery-2.1.0.js +0 -0
  16. data/lib/rubycritic/{report_generators → generators/html}/assets/javascripts/jquery.floatThead-v1.2.7.js +0 -0
  17. data/lib/rubycritic/{report_generators → generators/html}/assets/javascripts/jquery.scrollTo-1.4.11.js +0 -0
  18. data/lib/rubycritic/generators/html/assets/javascripts/jquery.tablesorter.js +2089 -0
  19. data/lib/rubycritic/{report_generators → generators/html}/assets/javascripts/jquery.timeago-v1.4.1.js +0 -0
  20. data/lib/rubycritic/{report_generators → generators/html}/assets/javascripts/prettify-4-Mar-2013.js +0 -0
  21. data/lib/rubycritic/{report_generators → generators/html}/assets/stylesheets/application.css +87 -25
  22. data/lib/rubycritic/{report_generators → generators/html}/assets/stylesheets/prettify.custom_theme.css +0 -0
  23. data/lib/rubycritic/generators/html/base.rb +52 -0
  24. data/lib/rubycritic/generators/html/code_file.rb +40 -0
  25. data/lib/rubycritic/generators/html/code_index.rb +26 -0
  26. data/lib/rubycritic/generators/html/line.rb +37 -0
  27. data/lib/rubycritic/generators/html/overview.rb +27 -0
  28. data/lib/rubycritic/generators/html/smells_index.rb +38 -0
  29. data/lib/rubycritic/{report_generators → generators/html}/templates/code_file.html.erb +4 -2
  30. data/lib/rubycritic/{report_generators → generators/html}/templates/code_index.html.erb +8 -4
  31. data/lib/rubycritic/{report_generators → generators/html}/templates/layouts/application.html.erb +12 -8
  32. data/lib/rubycritic/{report_generators → generators/html}/templates/line.html.erb +0 -0
  33. data/lib/rubycritic/{report_generators → generators/html}/templates/overview.html.erb +0 -0
  34. data/lib/rubycritic/{report_generators → generators/html}/templates/smells_index.html.erb +4 -4
  35. data/lib/rubycritic/{report_generators → generators/html}/templates/smelly_line.html.erb +0 -0
  36. data/lib/rubycritic/{report_generators → generators/html}/turbulence.rb +0 -0
  37. data/lib/rubycritic/{report_generators → generators/html}/view_helpers.rb +0 -0
  38. data/lib/rubycritic/generators/html_report.rb +66 -0
  39. data/lib/rubycritic/generators/json/simple.rb +30 -0
  40. data/lib/rubycritic/generators/json_report.rb +23 -0
  41. data/lib/rubycritic/reporter.rb +20 -0
  42. data/lib/rubycritic/version.rb +1 -1
  43. data/test/lib/rubycritic/analysers/churn_test.rb +12 -13
  44. data/test/lib/rubycritic/analysers/complexity_test.rb +9 -5
  45. data/test/lib/rubycritic/analysers/smells/flay_test.rb +27 -20
  46. data/test/lib/rubycritic/analysers/smells/flog_test.rb +17 -15
  47. data/test/lib/rubycritic/analysers/smells/reek_test.rb +2 -2
  48. data/test/lib/rubycritic/report_generators/turbulence_test.rb +1 -1
  49. data/test/lib/rubycritic/report_generators/view_helpers_test.rb +1 -1
  50. data/test/lib/rubycritic/source_control_systems/base_test.rb +2 -2
  51. data/test/lib/rubycritic/source_locator_test.rb +1 -1
  52. data/test/samples/flay/smelly.rb +0 -9
  53. data/test/samples/flay/smelly2.rb +8 -0
  54. metadata +33 -31
  55. data/lib/rubycritic/report_generators/assets/javascripts/jquery.tablesorter-2.0.js +0 -1031
  56. data/lib/rubycritic/report_generators/base.rb +0 -50
  57. data/lib/rubycritic/report_generators/code_file.rb +0 -38
  58. data/lib/rubycritic/report_generators/code_index.rb +0 -24
  59. data/lib/rubycritic/report_generators/current_code_file.rb +0 -17
  60. data/lib/rubycritic/report_generators/line.rb +0 -31
  61. data/lib/rubycritic/report_generators/overview.rb +0 -25
  62. data/lib/rubycritic/report_generators/smells_index.rb +0 -36
  63. data/lib/rubycritic/reporters/base.rb +0 -24
  64. data/lib/rubycritic/reporters/main.rb +0 -51
  65. data/lib/rubycritic/reporters/mini.rb +0 -30
@@ -9,7 +9,7 @@ describe Rubycritic::SourceControlSystem::Base do
9
9
  end
10
10
 
11
11
  describe "::create" do
12
- describe "when a source control system is found" do
12
+ context "when a source control system is found" do
13
13
  it "creates an instance of that source control system" do
14
14
  Rubycritic::SourceControlSystem::Git.stubs(:supported?).returns(true)
15
15
  system = Rubycritic::SourceControlSystem::Base.create
@@ -17,7 +17,7 @@ describe Rubycritic::SourceControlSystem::Base do
17
17
  end
18
18
  end
19
19
 
20
- describe "when no source control system is found" do
20
+ context "when no source control system is found" do
21
21
  it "creates a source control system double" do
22
22
  capture_output_streams do
23
23
  system = Rubycritic::SourceControlSystem::Base.create
@@ -31,7 +31,7 @@ describe Rubycritic::SourceLocator do
31
31
  end
32
32
 
33
33
  context "when configured to deduplicate symlinks" do
34
- it "it favors a file over a symlink if they both point to the same target" do
34
+ it "favors a file over a symlink if they both point to the same target" do
35
35
  Rubycritic::Config.stubs(:deduplicate_symlinks).returns(true)
36
36
  initial_paths = ["file0.rb", "file0_symlink.rb"]
37
37
  final_paths = ["file0.rb"]
@@ -6,12 +6,3 @@ class Ramsay
6
6
  parts -= 4
7
7
  end
8
8
  end
9
-
10
- class Roose
11
- def flay(parts)
12
- parts -= 1
13
- parts -= 2
14
- parts -= 3
15
- parts -= 4
16
- end
17
- end
@@ -0,0 +1,8 @@
1
+ class Roose
2
+ def flay(parts)
3
+ parts -= 1
4
+ parts -= 2
5
+ parts -= 3
6
+ parts -= 4
7
+ end
8
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubycritic
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Guilherme Simoes
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-16 00:00:00.000000000 Z
11
+ date: 2015-03-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: virtus
@@ -202,35 +202,35 @@ files:
202
202
  - lib/rubycritic/core/location.rb
203
203
  - lib/rubycritic/core/rating.rb
204
204
  - lib/rubycritic/core/smell.rb
205
- - lib/rubycritic/report_generators/assets/javascripts/application.js
206
- - lib/rubycritic/report_generators/assets/javascripts/highcharts.src-4.0.1.js
207
- - lib/rubycritic/report_generators/assets/javascripts/jquery-2.1.0.js
208
- - lib/rubycritic/report_generators/assets/javascripts/jquery.floatThead-v1.2.7.js
209
- - lib/rubycritic/report_generators/assets/javascripts/jquery.scrollTo-1.4.11.js
210
- - lib/rubycritic/report_generators/assets/javascripts/jquery.tablesorter-2.0.js
211
- - lib/rubycritic/report_generators/assets/javascripts/jquery.timeago-v1.4.1.js
212
- - lib/rubycritic/report_generators/assets/javascripts/prettify-4-Mar-2013.js
213
- - lib/rubycritic/report_generators/assets/stylesheets/application.css
214
- - lib/rubycritic/report_generators/assets/stylesheets/prettify.custom_theme.css
215
- - lib/rubycritic/report_generators/base.rb
216
- - lib/rubycritic/report_generators/code_file.rb
217
- - lib/rubycritic/report_generators/code_index.rb
218
- - lib/rubycritic/report_generators/current_code_file.rb
219
- - lib/rubycritic/report_generators/line.rb
220
- - lib/rubycritic/report_generators/overview.rb
221
- - lib/rubycritic/report_generators/smells_index.rb
222
- - lib/rubycritic/report_generators/templates/code_file.html.erb
223
- - lib/rubycritic/report_generators/templates/code_index.html.erb
224
- - lib/rubycritic/report_generators/templates/layouts/application.html.erb
225
- - lib/rubycritic/report_generators/templates/line.html.erb
226
- - lib/rubycritic/report_generators/templates/overview.html.erb
227
- - lib/rubycritic/report_generators/templates/smells_index.html.erb
228
- - lib/rubycritic/report_generators/templates/smelly_line.html.erb
229
- - lib/rubycritic/report_generators/turbulence.rb
230
- - lib/rubycritic/report_generators/view_helpers.rb
231
- - lib/rubycritic/reporters/base.rb
232
- - lib/rubycritic/reporters/main.rb
233
- - lib/rubycritic/reporters/mini.rb
205
+ - lib/rubycritic/generators/html/assets/javascripts/application.js
206
+ - lib/rubycritic/generators/html/assets/javascripts/highcharts.src-4.0.1.js
207
+ - lib/rubycritic/generators/html/assets/javascripts/jquery-2.1.0.js
208
+ - lib/rubycritic/generators/html/assets/javascripts/jquery.floatThead-v1.2.7.js
209
+ - lib/rubycritic/generators/html/assets/javascripts/jquery.scrollTo-1.4.11.js
210
+ - lib/rubycritic/generators/html/assets/javascripts/jquery.tablesorter.js
211
+ - lib/rubycritic/generators/html/assets/javascripts/jquery.timeago-v1.4.1.js
212
+ - lib/rubycritic/generators/html/assets/javascripts/prettify-4-Mar-2013.js
213
+ - lib/rubycritic/generators/html/assets/stylesheets/application.css
214
+ - lib/rubycritic/generators/html/assets/stylesheets/prettify.custom_theme.css
215
+ - lib/rubycritic/generators/html/base.rb
216
+ - lib/rubycritic/generators/html/code_file.rb
217
+ - lib/rubycritic/generators/html/code_index.rb
218
+ - lib/rubycritic/generators/html/line.rb
219
+ - lib/rubycritic/generators/html/overview.rb
220
+ - lib/rubycritic/generators/html/smells_index.rb
221
+ - lib/rubycritic/generators/html/templates/code_file.html.erb
222
+ - lib/rubycritic/generators/html/templates/code_index.html.erb
223
+ - lib/rubycritic/generators/html/templates/layouts/application.html.erb
224
+ - lib/rubycritic/generators/html/templates/line.html.erb
225
+ - lib/rubycritic/generators/html/templates/overview.html.erb
226
+ - lib/rubycritic/generators/html/templates/smells_index.html.erb
227
+ - lib/rubycritic/generators/html/templates/smelly_line.html.erb
228
+ - lib/rubycritic/generators/html/turbulence.rb
229
+ - lib/rubycritic/generators/html/view_helpers.rb
230
+ - lib/rubycritic/generators/html_report.rb
231
+ - lib/rubycritic/generators/json/simple.rb
232
+ - lib/rubycritic/generators/json_report.rb
233
+ - lib/rubycritic/reporter.rb
234
234
  - lib/rubycritic/revision_comparator.rb
235
235
  - lib/rubycritic/serializer.rb
236
236
  - lib/rubycritic/smells_status_setter.rb
@@ -267,6 +267,7 @@ files:
267
267
  - test/lib/rubycritic/version_test.rb
268
268
  - test/samples/empty.rb
269
269
  - test/samples/flay/smelly.rb
270
+ - test/samples/flay/smelly2.rb
270
271
  - test/samples/flog/complex.rb
271
272
  - test/samples/flog/smelly.rb
272
273
  - test/samples/location/dir1/file1.rb
@@ -331,6 +332,7 @@ test_files:
331
332
  - test/lib/rubycritic/version_test.rb
332
333
  - test/samples/empty.rb
333
334
  - test/samples/flay/smelly.rb
335
+ - test/samples/flay/smelly2.rb
334
336
  - test/samples/flog/complex.rb
335
337
  - test/samples/flog/smelly.rb
336
338
  - test/samples/location/dir1/file1.rb
@@ -1,1031 +0,0 @@
1
- /*
2
- *
3
- * TableSorter 2.0 - Client-side table sorting with ease!
4
- * Version 2.0.5b
5
- * @requires jQuery v1.2.3
6
- *
7
- * Copyright (c) 2007 Christian Bach
8
- * Examples and docs at: http://tablesorter.com
9
- * Dual licensed under the MIT and GPL licenses:
10
- * http://www.opensource.org/licenses/mit-license.php
11
- * http://www.gnu.org/licenses/gpl.html
12
- *
13
- */
14
- /**
15
- *
16
- * @description Create a sortable table with multi-column sorting capabilitys
17
- *
18
- * @example $('table').tablesorter();
19
- * @desc Create a simple tablesorter interface.
20
- *
21
- * @example $('table').tablesorter({ sortList:[[0,0],[1,0]] });
22
- * @desc Create a tablesorter interface and sort on the first and secound column column headers.
23
- *
24
- * @example $('table').tablesorter({ headers: { 0: { sorter: false}, 1: {sorter: false} } });
25
- *
26
- * @desc Create a tablesorter interface and disableing the first and second column headers.
27
- *
28
- *
29
- * @example $('table').tablesorter({ headers: { 0: {sorter:"integer"}, 1: {sorter:"currency"} } });
30
- *
31
- * @desc Create a tablesorter interface and set a column parser for the first
32
- * and second column.
33
- *
34
- *
35
- * @param Object
36
- * settings An object literal containing key/value pairs to provide
37
- * optional settings.
38
- *
39
- *
40
- * @option String cssHeader (optional) A string of the class name to be appended
41
- * to sortable tr elements in the thead of the table. Default value:
42
- * "header"
43
- *
44
- * @option String cssAsc (optional) A string of the class name to be appended to
45
- * sortable tr elements in the thead on a ascending sort. Default value:
46
- * "headerSortUp"
47
- *
48
- * @option String cssDesc (optional) A string of the class name to be appended
49
- * to sortable tr elements in the thead on a descending sort. Default
50
- * value: "headerSortDown"
51
- *
52
- * @option String sortInitialOrder (optional) A string of the inital sorting
53
- * order can be asc or desc. Default value: "asc"
54
- *
55
- * @option String sortMultisortKey (optional) A string of the multi-column sort
56
- * key. Default value: "shiftKey"
57
- *
58
- * @option String textExtraction (optional) A string of the text-extraction
59
- * method to use. For complex html structures inside td cell set this
60
- * option to "complex", on large tables the complex option can be slow.
61
- * Default value: "simple"
62
- *
63
- * @option Object headers (optional) An array containing the forces sorting
64
- * rules. This option let's you specify a default sorting rule. Default
65
- * value: null
66
- *
67
- * @option Array sortList (optional) An array containing the forces sorting
68
- * rules. This option let's you specify a default sorting rule. Default
69
- * value: null
70
- *
71
- * @option Array sortForce (optional) An array containing forced sorting rules.
72
- * This option let's you specify a default sorting rule, which is
73
- * prepended to user-selected rules. Default value: null
74
- *
75
- * @option Boolean sortLocaleCompare (optional) Boolean flag indicating whatever
76
- * to use String.localeCampare method or not. Default set to true.
77
- *
78
- *
79
- * @option Array sortAppend (optional) An array containing forced sorting rules.
80
- * This option let's you specify a default sorting rule, which is
81
- * appended to user-selected rules. Default value: null
82
- *
83
- * @option Boolean widthFixed (optional) Boolean flag indicating if tablesorter
84
- * should apply fixed widths to the table columns. This is usefull when
85
- * using the pager companion plugin. This options requires the dimension
86
- * jquery plugin. Default value: false
87
- *
88
- * @option Boolean cancelSelection (optional) Boolean flag indicating if
89
- * tablesorter should cancel selection of the table headers text.
90
- * Default value: true
91
- *
92
- * @option Boolean debug (optional) Boolean flag indicating if tablesorter
93
- * should display debuging information usefull for development.
94
- *
95
- * @type jQuery
96
- *
97
- * @name tablesorter
98
- *
99
- * @cat Plugins/Tablesorter
100
- *
101
- * @author Christian Bach/christian.bach@polyester.se
102
- */
103
-
104
- (function ($) {
105
- $.extend({
106
- tablesorter: new
107
- function () {
108
-
109
- var parsers = [],
110
- widgets = [];
111
-
112
- this.defaults = {
113
- cssHeader: "header",
114
- cssAsc: "headerSortUp",
115
- cssDesc: "headerSortDown",
116
- cssChildRow: "expand-child",
117
- sortInitialOrder: "asc",
118
- sortMultiSortKey: "shiftKey",
119
- sortForce: null,
120
- sortAppend: null,
121
- sortLocaleCompare: true,
122
- textExtraction: "simple",
123
- parsers: {}, widgets: [],
124
- widgetZebra: {
125
- css: ["even", "odd"]
126
- }, headers: {}, widthFixed: false,
127
- cancelSelection: true,
128
- sortList: [],
129
- headerList: [],
130
- dateFormat: "us",
131
- decimal: '/\.|\,/g',
132
- onRenderHeader: null,
133
- selectorHeaders: 'thead th',
134
- debug: false
135
- };
136
-
137
- /* debuging utils */
138
-
139
- function benchmark(s, d) {
140
- log(s + "," + (new Date().getTime() - d.getTime()) + "ms");
141
- }
142
-
143
- this.benchmark = benchmark;
144
-
145
- function log(s) {
146
- if (typeof console != "undefined" && typeof console.debug != "undefined") {
147
- console.log(s);
148
- } else {
149
- alert(s);
150
- }
151
- }
152
-
153
- /* parsers utils */
154
-
155
- function buildParserCache(table, $headers) {
156
-
157
- if (table.config.debug) {
158
- var parsersDebug = "";
159
- }
160
-
161
- if (table.tBodies.length == 0) return; // In the case of empty tables
162
- var rows = table.tBodies[0].rows;
163
-
164
- if (rows[0]) {
165
-
166
- var list = [],
167
- cells = rows[0].cells,
168
- l = cells.length;
169
-
170
- for (var i = 0; i < l; i++) {
171
-
172
- var p = false;
173
-
174
- if ($.metadata && ($($headers[i]).metadata() && $($headers[i]).metadata().sorter)) {
175
-
176
- p = getParserById($($headers[i]).metadata().sorter);
177
-
178
- } else if ((table.config.headers[i] && table.config.headers[i].sorter)) {
179
-
180
- p = getParserById(table.config.headers[i].sorter);
181
- }
182
- if (!p) {
183
-
184
- p = detectParserForColumn(table, rows, -1, i);
185
- }
186
-
187
- if (table.config.debug) {
188
- parsersDebug += "column:" + i + " parser:" + p.id + "\n";
189
- }
190
-
191
- list.push(p);
192
- }
193
- }
194
-
195
- if (table.config.debug) {
196
- log(parsersDebug);
197
- }
198
-
199
- return list;
200
- };
201
-
202
- function detectParserForColumn(table, rows, rowIndex, cellIndex) {
203
- var l = parsers.length,
204
- node = false,
205
- nodeValue = false,
206
- keepLooking = true;
207
- while (nodeValue == '' && keepLooking) {
208
- rowIndex++;
209
- if (rows[rowIndex]) {
210
- node = getNodeFromRowAndCellIndex(rows, rowIndex, cellIndex);
211
- nodeValue = trimAndGetNodeText(table.config, node);
212
- if (table.config.debug) {
213
- log('Checking if value was empty on row:' + rowIndex);
214
- }
215
- } else {
216
- keepLooking = false;
217
- }
218
- }
219
- for (var i = 1; i < l; i++) {
220
- if (parsers[i].is(nodeValue, table, node)) {
221
- return parsers[i];
222
- }
223
- }
224
- // 0 is always the generic parser (text)
225
- return parsers[0];
226
- }
227
-
228
- function getNodeFromRowAndCellIndex(rows, rowIndex, cellIndex) {
229
- return rows[rowIndex].cells[cellIndex];
230
- }
231
-
232
- function trimAndGetNodeText(config, node) {
233
- return $.trim(getElementText(config, node));
234
- }
235
-
236
- function getParserById(name) {
237
- var l = parsers.length;
238
- for (var i = 0; i < l; i++) {
239
- if (parsers[i].id.toLowerCase() == name.toLowerCase()) {
240
- return parsers[i];
241
- }
242
- }
243
- return false;
244
- }
245
-
246
- /* utils */
247
-
248
- function buildCache(table) {
249
-
250
- if (table.config.debug) {
251
- var cacheTime = new Date();
252
- }
253
-
254
- var totalRows = (table.tBodies[0] && table.tBodies[0].rows.length) || 0,
255
- totalCells = (table.tBodies[0].rows[0] && table.tBodies[0].rows[0].cells.length) || 0,
256
- parsers = table.config.parsers,
257
- cache = {
258
- row: [],
259
- normalized: []
260
- };
261
-
262
- for (var i = 0; i < totalRows; ++i) {
263
-
264
- /** Add the table data to main data array */
265
- var c = $(table.tBodies[0].rows[i]),
266
- cols = [];
267
-
268
- // if this is a child row, add it to the last row's children and
269
- // continue to the next row
270
- if (c.hasClass(table.config.cssChildRow)) {
271
- cache.row[cache.row.length - 1] = cache.row[cache.row.length - 1].add(c);
272
- // go to the next for loop
273
- continue;
274
- }
275
-
276
- cache.row.push(c);
277
-
278
- for (var j = 0; j < totalCells; ++j) {
279
- cols.push(parsers[j].format(getElementText(table.config, c[0].cells[j]), table, c[0].cells[j]));
280
- }
281
-
282
- cols.push(cache.normalized.length); // add position for rowCache
283
- cache.normalized.push(cols);
284
- cols = null;
285
- };
286
-
287
- if (table.config.debug) {
288
- benchmark("Building cache for " + totalRows + " rows:", cacheTime);
289
- }
290
-
291
- return cache;
292
- };
293
-
294
- function getElementText(config, node) {
295
-
296
- var text = "";
297
-
298
- if (!node) return "";
299
-
300
- if (!config.supportsTextContent) config.supportsTextContent = node.textContent || false;
301
-
302
- if (config.textExtraction == "simple") {
303
- if (config.supportsTextContent) {
304
- text = node.textContent;
305
- } else {
306
- if (node.childNodes[0] && node.childNodes[0].hasChildNodes()) {
307
- text = node.childNodes[0].innerHTML;
308
- } else {
309
- text = node.innerHTML;
310
- }
311
- }
312
- } else {
313
- if (typeof(config.textExtraction) == "function") {
314
- text = config.textExtraction(node);
315
- } else {
316
- text = $(node).text();
317
- }
318
- }
319
- return text;
320
- }
321
-
322
- function appendToTable(table, cache) {
323
-
324
- if (table.config.debug) {
325
- var appendTime = new Date()
326
- }
327
-
328
- var c = cache,
329
- r = c.row,
330
- n = c.normalized,
331
- totalRows = n.length,
332
- checkCell = (n[0].length - 1),
333
- tableBody = $(table.tBodies[0]),
334
- rows = [];
335
-
336
-
337
- for (var i = 0; i < totalRows; i++) {
338
- var pos = n[i][checkCell];
339
-
340
- rows.push(r[pos]);
341
-
342
- if (!table.config.appender) {
343
-
344
- //var o = ;
345
- var l = r[pos].length;
346
- for (var j = 0; j < l; j++) {
347
- tableBody[0].appendChild(r[pos][j]);
348
- }
349
-
350
- //
351
- }
352
- }
353
-
354
-
355
-
356
- if (table.config.appender) {
357
-
358
- table.config.appender(table, rows);
359
- }
360
-
361
- rows = null;
362
-
363
- if (table.config.debug) {
364
- benchmark("Rebuilt table:", appendTime);
365
- }
366
-
367
- // apply table widgets
368
- applyWidget(table);
369
-
370
- // trigger sortend
371
- setTimeout(function () {
372
- $(table).trigger("sortEnd");
373
- }, 0);
374
-
375
- };
376
-
377
- function buildHeaders(table) {
378
-
379
- if (table.config.debug) {
380
- var time = new Date();
381
- }
382
-
383
- var meta = ($.metadata) ? true : false;
384
-
385
- var header_index = computeTableHeaderCellIndexes(table);
386
-
387
- $tableHeaders = $(table.config.selectorHeaders, table).each(function (index) {
388
-
389
- this.column = header_index[this.parentNode.rowIndex + "-" + this.cellIndex];
390
- // this.column = index;
391
- this.order = formatSortingOrder(table.config.sortInitialOrder);
392
-
393
-
394
- this.count = this.order;
395
-
396
- if (checkHeaderMetadata(this) || checkHeaderOptions(table, index)) this.sortDisabled = true;
397
- if (checkHeaderOptionsSortingLocked(table, index)) this.order = this.lockedOrder = checkHeaderOptionsSortingLocked(table, index);
398
-
399
- if (!this.sortDisabled) {
400
- var $th = $(this).addClass(table.config.cssHeader);
401
- if (table.config.onRenderHeader) table.config.onRenderHeader.apply($th);
402
- }
403
-
404
- // add cell to headerList
405
- table.config.headerList[index] = this;
406
- });
407
-
408
- if (table.config.debug) {
409
- benchmark("Built headers:", time);
410
- log($tableHeaders);
411
- }
412
-
413
- return $tableHeaders;
414
-
415
- };
416
-
417
- // from:
418
- // http://www.javascripttoolbox.com/lib/table/examples.php
419
- // http://www.javascripttoolbox.com/temp/table_cellindex.html
420
-
421
-
422
- function computeTableHeaderCellIndexes(t) {
423
- var matrix = [];
424
- var lookup = {};
425
- var thead = t.getElementsByTagName('THEAD')[0];
426
- var trs = thead.getElementsByTagName('TR');
427
-
428
- for (var i = 0; i < trs.length; i++) {
429
- var cells = trs[i].cells;
430
- for (var j = 0; j < cells.length; j++) {
431
- var c = cells[j];
432
-
433
- var rowIndex = c.parentNode.rowIndex;
434
- var cellId = rowIndex + "-" + c.cellIndex;
435
- var rowSpan = c.rowSpan || 1;
436
- var colSpan = c.colSpan || 1
437
- var firstAvailCol;
438
- if (typeof(matrix[rowIndex]) == "undefined") {
439
- matrix[rowIndex] = [];
440
- }
441
- // Find first available column in the first row
442
- for (var k = 0; k < matrix[rowIndex].length + 1; k++) {
443
- if (typeof(matrix[rowIndex][k]) == "undefined") {
444
- firstAvailCol = k;
445
- break;
446
- }
447
- }
448
- lookup[cellId] = firstAvailCol;
449
- for (var k = rowIndex; k < rowIndex + rowSpan; k++) {
450
- if (typeof(matrix[k]) == "undefined") {
451
- matrix[k] = [];
452
- }
453
- var matrixrow = matrix[k];
454
- for (var l = firstAvailCol; l < firstAvailCol + colSpan; l++) {
455
- matrixrow[l] = "x";
456
- }
457
- }
458
- }
459
- }
460
- return lookup;
461
- }
462
-
463
- function checkCellColSpan(table, rows, row) {
464
- var arr = [],
465
- r = table.tHead.rows,
466
- c = r[row].cells;
467
-
468
- for (var i = 0; i < c.length; i++) {
469
- var cell = c[i];
470
-
471
- if (cell.colSpan > 1) {
472
- arr = arr.concat(checkCellColSpan(table, headerArr, row++));
473
- } else {
474
- if (table.tHead.length == 1 || (cell.rowSpan > 1 || !r[row + 1])) {
475
- arr.push(cell);
476
- }
477
- // headerArr[row] = (i+row);
478
- }
479
- }
480
- return arr;
481
- };
482
-
483
- function checkHeaderMetadata(cell) {
484
- if (($.metadata) && ($(cell).metadata().sorter === false)) {
485
- return true;
486
- };
487
- return false;
488
- }
489
-
490
- function checkHeaderOptions(table, i) {
491
- if ((table.config.headers[i]) && (table.config.headers[i].sorter === false)) {
492
- return true;
493
- };
494
- return false;
495
- }
496
-
497
- function checkHeaderOptionsSortingLocked(table, i) {
498
- if ((table.config.headers[i]) && (table.config.headers[i].lockedOrder)) return table.config.headers[i].lockedOrder;
499
- return false;
500
- }
501
-
502
- function applyWidget(table) {
503
- var c = table.config.widgets;
504
- var l = c.length;
505
- for (var i = 0; i < l; i++) {
506
-
507
- getWidgetById(c[i]).format(table);
508
- }
509
-
510
- }
511
-
512
- function getWidgetById(name) {
513
- var l = widgets.length;
514
- for (var i = 0; i < l; i++) {
515
- if (widgets[i].id.toLowerCase() == name.toLowerCase()) {
516
- return widgets[i];
517
- }
518
- }
519
- };
520
-
521
- function formatSortingOrder(v) {
522
- if (typeof(v) != "Number") {
523
- return (v.toLowerCase() == "desc") ? 1 : 0;
524
- } else {
525
- return (v == 1) ? 1 : 0;
526
- }
527
- }
528
-
529
- function isValueInArray(v, a) {
530
- var l = a.length;
531
- for (var i = 0; i < l; i++) {
532
- if (a[i][0] == v) {
533
- return true;
534
- }
535
- }
536
- return false;
537
- }
538
-
539
- function setHeadersCss(table, $headers, list, css) {
540
- // remove all header information
541
- $headers.removeClass(css[0]).removeClass(css[1]);
542
-
543
- var h = [];
544
- $headers.each(function (offset) {
545
- if (!this.sortDisabled) {
546
- h[this.column] = $(this);
547
- }
548
- });
549
-
550
- var l = list.length;
551
- for (var i = 0; i < l; i++) {
552
- h[list[i][0]].addClass(css[list[i][1]]);
553
- }
554
- }
555
-
556
- function fixColumnWidth(table, $headers) {
557
- var c = table.config;
558
- if (c.widthFixed) {
559
- var colgroup = $('<colgroup>');
560
- $("tr:first td", table.tBodies[0]).each(function () {
561
- colgroup.append($('<col>').css('width', $(this).width()));
562
- });
563
- $(table).prepend(colgroup);
564
- };
565
- }
566
-
567
- function updateHeaderSortCount(table, sortList) {
568
- var c = table.config,
569
- l = sortList.length;
570
- for (var i = 0; i < l; i++) {
571
- var s = sortList[i],
572
- o = c.headerList[s[0]];
573
- o.count = s[1];
574
- o.count++;
575
- }
576
- }
577
-
578
- /* sorting methods */
579
-
580
- function multisort(table, sortList, cache) {
581
-
582
- if (table.config.debug) {
583
- var sortTime = new Date();
584
- }
585
-
586
- var dynamicExp = "var sortWrapper = function(a,b) {",
587
- l = sortList.length;
588
-
589
- // TODO: inline functions.
590
- for (var i = 0; i < l; i++) {
591
-
592
- var c = sortList[i][0];
593
- var order = sortList[i][1];
594
- // var s = (getCachedSortType(table.config.parsers,c) == "text") ?
595
- // ((order == 0) ? "sortText" : "sortTextDesc") : ((order == 0) ?
596
- // "sortNumeric" : "sortNumericDesc");
597
- // var s = (table.config.parsers[c].type == "text") ? ((order == 0)
598
- // ? makeSortText(c) : makeSortTextDesc(c)) : ((order == 0) ?
599
- // makeSortNumeric(c) : makeSortNumericDesc(c));
600
- var s = (table.config.parsers[c].type == "text") ? ((order == 0) ? makeSortFunction("text", "asc", c) : makeSortFunction("text", "desc", c)) : ((order == 0) ? makeSortFunction("numeric", "asc", c) : makeSortFunction("numeric", "desc", c));
601
- var e = "e" + i;
602
-
603
- dynamicExp += "var " + e + " = " + s; // + "(a[" + c + "],b[" + c
604
- // + "]); ";
605
- dynamicExp += "if(" + e + ") { return " + e + "; } ";
606
- dynamicExp += "else { ";
607
-
608
- }
609
-
610
- // if value is the same keep orignal order
611
- var orgOrderCol = cache.normalized[0].length - 1;
612
- dynamicExp += "return a[" + orgOrderCol + "]-b[" + orgOrderCol + "];";
613
-
614
- for (var i = 0; i < l; i++) {
615
- dynamicExp += "}; ";
616
- }
617
-
618
- dynamicExp += "return 0; ";
619
- dynamicExp += "}; ";
620
-
621
- if (table.config.debug) {
622
- benchmark("Evaling expression:" + dynamicExp, new Date());
623
- }
624
-
625
- eval(dynamicExp);
626
-
627
- cache.normalized.sort(sortWrapper);
628
-
629
- if (table.config.debug) {
630
- benchmark("Sorting on " + sortList.toString() + " and dir " + order + " time:", sortTime);
631
- }
632
-
633
- return cache;
634
- };
635
-
636
- function makeSortFunction(type, direction, index) {
637
- var a = "a[" + index + "]",
638
- b = "b[" + index + "]";
639
- if (type == 'text' && direction == 'asc') {
640
- return "(" + a + " == " + b + " ? 0 : (" + a + " === null ? Number.POSITIVE_INFINITY : (" + b + " === null ? Number.NEGATIVE_INFINITY : (" + a + " < " + b + ") ? -1 : 1 )));";
641
- } else if (type == 'text' && direction == 'desc') {
642
- return "(" + a + " == " + b + " ? 0 : (" + a + " === null ? Number.POSITIVE_INFINITY : (" + b + " === null ? Number.NEGATIVE_INFINITY : (" + b + " < " + a + ") ? -1 : 1 )));";
643
- } else if (type == 'numeric' && direction == 'asc') {
644
- return "(" + a + " === null && " + b + " === null) ? 0 :(" + a + " === null ? Number.POSITIVE_INFINITY : (" + b + " === null ? Number.NEGATIVE_INFINITY : " + a + " - " + b + "));";
645
- } else if (type == 'numeric' && direction == 'desc') {
646
- return "(" + a + " === null && " + b + " === null) ? 0 :(" + a + " === null ? Number.POSITIVE_INFINITY : (" + b + " === null ? Number.NEGATIVE_INFINITY : " + b + " - " + a + "));";
647
- }
648
- };
649
-
650
- function makeSortText(i) {
651
- return "((a[" + i + "] < b[" + i + "]) ? -1 : ((a[" + i + "] > b[" + i + "]) ? 1 : 0));";
652
- };
653
-
654
- function makeSortTextDesc(i) {
655
- return "((b[" + i + "] < a[" + i + "]) ? -1 : ((b[" + i + "] > a[" + i + "]) ? 1 : 0));";
656
- };
657
-
658
- function makeSortNumeric(i) {
659
- return "a[" + i + "]-b[" + i + "];";
660
- };
661
-
662
- function makeSortNumericDesc(i) {
663
- return "b[" + i + "]-a[" + i + "];";
664
- };
665
-
666
- function sortText(a, b) {
667
- if (table.config.sortLocaleCompare) return a.localeCompare(b);
668
- return ((a < b) ? -1 : ((a > b) ? 1 : 0));
669
- };
670
-
671
- function sortTextDesc(a, b) {
672
- if (table.config.sortLocaleCompare) return b.localeCompare(a);
673
- return ((b < a) ? -1 : ((b > a) ? 1 : 0));
674
- };
675
-
676
- function sortNumeric(a, b) {
677
- return a - b;
678
- };
679
-
680
- function sortNumericDesc(a, b) {
681
- return b - a;
682
- };
683
-
684
- function getCachedSortType(parsers, i) {
685
- return parsers[i].type;
686
- }; /* public methods */
687
- this.construct = function (settings) {
688
- return this.each(function () {
689
- // if no thead or tbody quit.
690
- if (!this.tHead || !this.tBodies) return;
691
- // declare
692
- var $this, $document, $headers, cache, config, shiftDown = 0,
693
- sortOrder;
694
- // new blank config object
695
- this.config = {};
696
- // merge and extend.
697
- config = $.extend(this.config, $.tablesorter.defaults, settings);
698
- // store common expression for speed
699
- $this = $(this);
700
- // save the settings where they read
701
- $.data(this, "tablesorter", config);
702
- // build headers
703
- $headers = buildHeaders(this);
704
- // try to auto detect column type, and store in tables config
705
- this.config.parsers = buildParserCache(this, $headers);
706
- // build the cache for the tbody cells
707
- cache = buildCache(this);
708
- // get the css class names, could be done else where.
709
- var sortCSS = [config.cssDesc, config.cssAsc];
710
- // fixate columns if the users supplies the fixedWidth option
711
- fixColumnWidth(this);
712
- // apply event handling to headers
713
- // this is to big, perhaps break it out?
714
- $headers.click(
715
-
716
- function (e) {
717
- var totalRows = ($this[0].tBodies[0] && $this[0].tBodies[0].rows.length) || 0;
718
- if (!this.sortDisabled && totalRows > 0) {
719
- // Only call sortStart if sorting is
720
- // enabled.
721
- $this.trigger("sortStart");
722
- // store exp, for speed
723
- var $cell = $(this);
724
- // get current column index
725
- var i = this.column;
726
- // get current column sort order
727
- this.order = this.count++ % 2;
728
- // always sort on the locked order.
729
- if(this.lockedOrder) this.order = this.lockedOrder;
730
-
731
- // user only whants to sort on one
732
- // column
733
- if (!e[config.sortMultiSortKey]) {
734
- // flush the sort list
735
- config.sortList = [];
736
- if (config.sortForce != null) {
737
- var a = config.sortForce;
738
- for (var j = 0; j < a.length; j++) {
739
- if (a[j][0] != i) {
740
- config.sortList.push(a[j]);
741
- }
742
- }
743
- }
744
- // add column to sort list
745
- config.sortList.push([i, this.order]);
746
- // multi column sorting
747
- } else {
748
- // the user has clicked on an all
749
- // ready sortet column.
750
- if (isValueInArray(i, config.sortList)) {
751
- // revers the sorting direction
752
- // for all tables.
753
- for (var j = 0; j < config.sortList.length; j++) {
754
- var s = config.sortList[j],
755
- o = config.headerList[s[0]];
756
- if (s[0] == i) {
757
- o.count = s[1];
758
- o.count++;
759
- s[1] = o.count % 2;
760
- }
761
- }
762
- } else {
763
- // add column to sort list array
764
- config.sortList.push([i, this.order]);
765
- }
766
- };
767
- setTimeout(function () {
768
- // set css for headers
769
- setHeadersCss($this[0], $headers, config.sortList, sortCSS);
770
- appendToTable(
771
- $this[0], multisort(
772
- $this[0], config.sortList, cache)
773
- );
774
- }, 1);
775
- // stop normal event by returning false
776
- return false;
777
- }
778
- // cancel selection
779
- }).mousedown(function () {
780
- if (config.cancelSelection) {
781
- this.onselectstart = function () {
782
- return false
783
- };
784
- return false;
785
- }
786
- });
787
- // apply easy methods that trigger binded events
788
- $this.bind("update", function () {
789
- var me = this;
790
- setTimeout(function () {
791
- // rebuild parsers.
792
- me.config.parsers = buildParserCache(
793
- me, $headers);
794
- // rebuild the cache map
795
- cache = buildCache(me);
796
- }, 1);
797
- }).bind("updateCell", function (e, cell) {
798
- var config = this.config;
799
- // get position from the dom.
800
- var pos = [(cell.parentNode.rowIndex - 1), cell.cellIndex];
801
- // update cache
802
- cache.normalized[pos[0]][pos[1]] = config.parsers[pos[1]].format(
803
- getElementText(config, cell), cell);
804
- }).bind("sorton", function (e, list) {
805
- $(this).trigger("sortStart");
806
- config.sortList = list;
807
- // update and store the sortlist
808
- var sortList = config.sortList;
809
- // update header count index
810
- updateHeaderSortCount(this, sortList);
811
- // set css for headers
812
- setHeadersCss(this, $headers, sortList, sortCSS);
813
- // sort the table and append it to the dom
814
- appendToTable(this, multisort(this, sortList, cache));
815
- }).bind("appendCache", function () {
816
- appendToTable(this, cache);
817
- }).bind("applyWidgetId", function (e, id) {
818
- getWidgetById(id).format(this);
819
- }).bind("applyWidgets", function () {
820
- // apply widgets
821
- applyWidget(this);
822
- });
823
- if ($.metadata && ($(this).metadata() && $(this).metadata().sortlist)) {
824
- config.sortList = $(this).metadata().sortlist;
825
- }
826
- // if user has supplied a sort list to constructor.
827
- if (config.sortList.length > 0) {
828
- $this.trigger("sorton", [config.sortList]);
829
- }
830
- // apply widgets
831
- applyWidget(this);
832
- });
833
- };
834
- this.addParser = function (parser) {
835
- var l = parsers.length,
836
- a = true;
837
- for (var i = 0; i < l; i++) {
838
- if (parsers[i].id.toLowerCase() == parser.id.toLowerCase()) {
839
- a = false;
840
- }
841
- }
842
- if (a) {
843
- parsers.push(parser);
844
- };
845
- };
846
- this.addWidget = function (widget) {
847
- widgets.push(widget);
848
- };
849
- this.formatFloat = function (s) {
850
- var i = parseFloat(s);
851
- return (isNaN(i)) ? 0 : i;
852
- };
853
- this.formatInt = function (s) {
854
- var i = parseInt(s);
855
- return (isNaN(i)) ? 0 : i;
856
- };
857
- this.isDigit = function (s, config) {
858
- // replace all an wanted chars and match.
859
- return /^[-+]?\d*$/.test($.trim(s.replace(/[,.']/g, '')));
860
- };
861
- this.clearTableBody = function (table) {
862
- if ($.browser.msie) {
863
- function empty() {
864
- while (this.firstChild)
865
- this.removeChild(this.firstChild);
866
- }
867
- empty.apply(table.tBodies[0]);
868
- } else {
869
- table.tBodies[0].innerHTML = "";
870
- }
871
- };
872
- }
873
- });
874
-
875
- // extend plugin scope
876
- $.fn.extend({
877
- tablesorter: $.tablesorter.construct
878
- });
879
-
880
- // make shortcut
881
- var ts = $.tablesorter;
882
-
883
- // add default parsers
884
- ts.addParser({
885
- id: "text",
886
- is: function (s) {
887
- return true;
888
- }, format: function (s) {
889
- return $.trim(s.toLocaleLowerCase());
890
- }, type: "text"
891
- });
892
-
893
- ts.addParser({
894
- id: "digit",
895
- is: function (s, table) {
896
- var c = table.config;
897
- return $.tablesorter.isDigit(s, c);
898
- }, format: function (s) {
899
- return $.tablesorter.formatFloat(s);
900
- }, type: "numeric"
901
- });
902
-
903
- ts.addParser({
904
- id: "currency",
905
- is: function (s) {
906
- return /^[£$€?.]/.test(s);
907
- }, format: function (s) {
908
- return $.tablesorter.formatFloat(s.replace(new RegExp(/[£$€]/g), ""));
909
- }, type: "numeric"
910
- });
911
-
912
- ts.addParser({
913
- id: "ipAddress",
914
- is: function (s) {
915
- return /^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s);
916
- }, format: function (s) {
917
- var a = s.split("."),
918
- r = "",
919
- l = a.length;
920
- for (var i = 0; i < l; i++) {
921
- var item = a[i];
922
- if (item.length == 2) {
923
- r += "0" + item;
924
- } else {
925
- r += item;
926
- }
927
- }
928
- return $.tablesorter.formatFloat(r);
929
- }, type: "numeric"
930
- });
931
-
932
- ts.addParser({
933
- id: "url",
934
- is: function (s) {
935
- return /^(https?|ftp|file):\/\/$/.test(s);
936
- }, format: function (s) {
937
- return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//), ''));
938
- }, type: "text"
939
- });
940
-
941
- ts.addParser({
942
- id: "isoDate",
943
- is: function (s) {
944
- return /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s);
945
- }, format: function (s) {
946
- return $.tablesorter.formatFloat((s != "") ? new Date(s.replace(
947
- new RegExp(/-/g), "/")).getTime() : "0");
948
- }, type: "numeric"
949
- });
950
-
951
- ts.addParser({
952
- id: "percent",
953
- is: function (s) {
954
- return /\%$/.test($.trim(s));
955
- }, format: function (s) {
956
- return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g), ""));
957
- }, type: "numeric"
958
- });
959
-
960
- ts.addParser({
961
- id: "usLongDate",
962
- is: function (s) {
963
- return s.match(new RegExp(/^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/));
964
- }, format: function (s) {
965
- return $.tablesorter.formatFloat(new Date(s).getTime());
966
- }, type: "numeric"
967
- });
968
-
969
- ts.addParser({
970
- id: "shortDate",
971
- is: function (s) {
972
- return /\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}/.test(s);
973
- }, format: function (s, table) {
974
- var c = table.config;
975
- s = s.replace(/\-/g, "/");
976
- if (c.dateFormat == "us") {
977
- // reformat the string in ISO format
978
- s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/, "$3/$1/$2");
979
- } else if (c.dateFormat == "uk") {
980
- // reformat the string in ISO format
981
- s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/, "$3/$2/$1");
982
- } else if (c.dateFormat == "dd/mm/yy" || c.dateFormat == "dd-mm-yy") {
983
- s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/, "$1/$2/$3");
984
- }
985
- return $.tablesorter.formatFloat(new Date(s).getTime());
986
- }, type: "numeric"
987
- });
988
- ts.addParser({
989
- id: "time",
990
- is: function (s) {
991
- return /^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s);
992
- }, format: function (s) {
993
- return $.tablesorter.formatFloat(new Date("2000/01/01 " + s).getTime());
994
- }, type: "numeric"
995
- });
996
- ts.addParser({
997
- id: "metadata",
998
- is: function (s) {
999
- return false;
1000
- }, format: function (s, table, cell) {
1001
- var c = table.config,
1002
- p = (!c.parserMetadataName) ? 'sortValue' : c.parserMetadataName;
1003
- return $(cell).metadata()[p];
1004
- }, type: "numeric"
1005
- });
1006
- // add default widgets
1007
- ts.addWidget({
1008
- id: "zebra",
1009
- format: function (table) {
1010
- if (table.config.debug) {
1011
- var time = new Date();
1012
- }
1013
- var $tr, row = -1,
1014
- odd;
1015
- // loop through the visible rows
1016
- $("tr:visible", table.tBodies[0]).each(function (i) {
1017
- $tr = $(this);
1018
- // style children rows the same way the parent
1019
- // row was styled
1020
- if (!$tr.hasClass(table.config.cssChildRow)) row++;
1021
- odd = (row % 2 == 0);
1022
- $tr.removeClass(
1023
- table.config.widgetZebra.css[odd ? 0 : 1]).addClass(
1024
- table.config.widgetZebra.css[odd ? 1 : 0])
1025
- });
1026
- if (table.config.debug) {
1027
- $.tablesorter.benchmark("Applying Zebra widget", time);
1028
- }
1029
- }
1030
- });
1031
- })(jQuery);