frontend-helpers 0.0.2 → 0.0.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.
data/README.md CHANGED
@@ -125,7 +125,7 @@ All of these can be added to your manifest file for Sprockets like this
125
125
  //= require jquery.async
126
126
  //= require jquery.cookie
127
127
  //= require jquery.lifestream
128
- //= require jquery.vaidate
128
+ //= require jquery.validate
129
129
  //= require log
130
130
  //= require modernizr
131
131
  //= require shortcut
data/Rakefile CHANGED
@@ -19,7 +19,7 @@ Jeweler::Tasks.new do |gem|
19
19
  gem.description = %Q{Large collection of useful Rails 3.1 helpers for SEO, Metatags, Facebook OG tags, integration for analytics services like google, woopra, olark, mixpanel and much much more...}
20
20
  gem.email = "me@christopherhein.com"
21
21
  gem.authors = ["Christopher Hein"]
22
- gem.version = "0.0.2"
22
+ gem.version = "0.0.3"
23
23
  # dependencies defined in Gemfile
24
24
  end
25
25
  Jeweler::RubygemsDotOrgTasks.new
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{frontend-helpers}
8
- s.version = "0.0.2"
8
+ s.version = "0.0.3"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Christopher Hein"]
12
- s.date = %q{2011-07-11}
12
+ s.date = %q{2011-07-17}
13
13
  s.description = %q{Large collection of useful Rails 3.1 helpers for SEO, Metatags, Facebook OG tags, integration for analytics services like google, woopra, olark, mixpanel and much much more...}
14
14
  s.email = %q{me@christopherhein.com}
15
15
  s.extra_rdoc_files = [
@@ -75,12 +75,15 @@ Gem::Specification.new do |s|
75
75
  "vendor/assets/javascripts/ie/reverse_zindex.js",
76
76
  "vendor/assets/javascripts/jquery.async.js",
77
77
  "vendor/assets/javascripts/jquery.cookie.js",
78
+ "vendor/assets/javascripts/jquery.easing.js",
78
79
  "vendor/assets/javascripts/jquery.lifestream.js",
80
+ "vendor/assets/javascripts/jquery.tablesorter.js",
79
81
  "vendor/assets/javascripts/jquery.validate.js",
80
82
  "vendor/assets/javascripts/log.js",
81
83
  "vendor/assets/javascripts/modernizr.js",
82
84
  "vendor/assets/javascripts/shortcut.js",
83
85
  "vendor/assets/javascripts/swfobject.js",
86
+ "vendor/assets/javascripts/tempo.js",
84
87
  "vendor/assets/stylesheets/reset.css.sass",
85
88
  "vendor/assets/stylesheets/variables.css.sass"
86
89
  ]
@@ -0,0 +1,205 @@
1
+ /*
2
+ * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
3
+ *
4
+ * Uses the built in easing capabilities added In jQuery 1.1
5
+ * to offer multiple easing options
6
+ *
7
+ * TERMS OF USE - jQuery Easing
8
+ *
9
+ * Open source under the BSD License.
10
+ *
11
+ * Copyright © 2008 George McGinley Smith
12
+ * All rights reserved.
13
+ *
14
+ * Redistribution and use in source and binary forms, with or without modification,
15
+ * are permitted provided that the following conditions are met:
16
+ *
17
+ * Redistributions of source code must retain the above copyright notice, this list of
18
+ * conditions and the following disclaimer.
19
+ * Redistributions in binary form must reproduce the above copyright notice, this list
20
+ * of conditions and the following disclaimer in the documentation and/or other materials
21
+ * provided with the distribution.
22
+ *
23
+ * Neither the name of the author nor the names of contributors may be used to endorse
24
+ * or promote products derived from this software without specific prior written permission.
25
+ *
26
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
27
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
28
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
31
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
32
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
34
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
35
+ *
36
+ */
37
+
38
+ // t: current time, b: begInnIng value, c: change In value, d: duration
39
+ jQuery.easing['jswing'] = jQuery.easing['swing'];
40
+
41
+ jQuery.extend( jQuery.easing,
42
+ {
43
+ def: 'easeOutQuad',
44
+ swing: function (x, t, b, c, d) {
45
+ //alert(jQuery.easing.default);
46
+ return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
47
+ },
48
+ easeInQuad: function (x, t, b, c, d) {
49
+ return c*(t/=d)*t + b;
50
+ },
51
+ easeOutQuad: function (x, t, b, c, d) {
52
+ return -c *(t/=d)*(t-2) + b;
53
+ },
54
+ easeInOutQuad: function (x, t, b, c, d) {
55
+ if ((t/=d/2) < 1) return c/2*t*t + b;
56
+ return -c/2 * ((--t)*(t-2) - 1) + b;
57
+ },
58
+ easeInCubic: function (x, t, b, c, d) {
59
+ return c*(t/=d)*t*t + b;
60
+ },
61
+ easeOutCubic: function (x, t, b, c, d) {
62
+ return c*((t=t/d-1)*t*t + 1) + b;
63
+ },
64
+ easeInOutCubic: function (x, t, b, c, d) {
65
+ if ((t/=d/2) < 1) return c/2*t*t*t + b;
66
+ return c/2*((t-=2)*t*t + 2) + b;
67
+ },
68
+ easeInQuart: function (x, t, b, c, d) {
69
+ return c*(t/=d)*t*t*t + b;
70
+ },
71
+ easeOutQuart: function (x, t, b, c, d) {
72
+ return -c * ((t=t/d-1)*t*t*t - 1) + b;
73
+ },
74
+ easeInOutQuart: function (x, t, b, c, d) {
75
+ if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
76
+ return -c/2 * ((t-=2)*t*t*t - 2) + b;
77
+ },
78
+ easeInQuint: function (x, t, b, c, d) {
79
+ return c*(t/=d)*t*t*t*t + b;
80
+ },
81
+ easeOutQuint: function (x, t, b, c, d) {
82
+ return c*((t=t/d-1)*t*t*t*t + 1) + b;
83
+ },
84
+ easeInOutQuint: function (x, t, b, c, d) {
85
+ if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
86
+ return c/2*((t-=2)*t*t*t*t + 2) + b;
87
+ },
88
+ easeInSine: function (x, t, b, c, d) {
89
+ return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
90
+ },
91
+ easeOutSine: function (x, t, b, c, d) {
92
+ return c * Math.sin(t/d * (Math.PI/2)) + b;
93
+ },
94
+ easeInOutSine: function (x, t, b, c, d) {
95
+ return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
96
+ },
97
+ easeInExpo: function (x, t, b, c, d) {
98
+ return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
99
+ },
100
+ easeOutExpo: function (x, t, b, c, d) {
101
+ return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
102
+ },
103
+ easeInOutExpo: function (x, t, b, c, d) {
104
+ if (t==0) return b;
105
+ if (t==d) return b+c;
106
+ if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
107
+ return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
108
+ },
109
+ easeInCirc: function (x, t, b, c, d) {
110
+ return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
111
+ },
112
+ easeOutCirc: function (x, t, b, c, d) {
113
+ return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
114
+ },
115
+ easeInOutCirc: function (x, t, b, c, d) {
116
+ if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
117
+ return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
118
+ },
119
+ easeInElastic: function (x, t, b, c, d) {
120
+ var s=1.70158;var p=0;var a=c;
121
+ if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
122
+ if (a < Math.abs(c)) { a=c; var s=p/4; }
123
+ else var s = p/(2*Math.PI) * Math.asin (c/a);
124
+ return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
125
+ },
126
+ easeOutElastic: function (x, t, b, c, d) {
127
+ var s=1.70158;var p=0;var a=c;
128
+ if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
129
+ if (a < Math.abs(c)) { a=c; var s=p/4; }
130
+ else var s = p/(2*Math.PI) * Math.asin (c/a);
131
+ return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
132
+ },
133
+ easeInOutElastic: function (x, t, b, c, d) {
134
+ var s=1.70158;var p=0;var a=c;
135
+ if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5);
136
+ if (a < Math.abs(c)) { a=c; var s=p/4; }
137
+ else var s = p/(2*Math.PI) * Math.asin (c/a);
138
+ if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
139
+ return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
140
+ },
141
+ easeInBack: function (x, t, b, c, d, s) {
142
+ if (s == undefined) s = 1.70158;
143
+ return c*(t/=d)*t*((s+1)*t - s) + b;
144
+ },
145
+ easeOutBack: function (x, t, b, c, d, s) {
146
+ if (s == undefined) s = 1.70158;
147
+ return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
148
+ },
149
+ easeInOutBack: function (x, t, b, c, d, s) {
150
+ if (s == undefined) s = 1.70158;
151
+ if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
152
+ return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
153
+ },
154
+ easeInBounce: function (x, t, b, c, d) {
155
+ return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
156
+ },
157
+ easeOutBounce: function (x, t, b, c, d) {
158
+ if ((t/=d) < (1/2.75)) {
159
+ return c*(7.5625*t*t) + b;
160
+ } else if (t < (2/2.75)) {
161
+ return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
162
+ } else if (t < (2.5/2.75)) {
163
+ return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
164
+ } else {
165
+ return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
166
+ }
167
+ },
168
+ easeInOutBounce: function (x, t, b, c, d) {
169
+ if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
170
+ return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
171
+ }
172
+ });
173
+
174
+ /*
175
+ *
176
+ * TERMS OF USE - EASING EQUATIONS
177
+ *
178
+ * Open source under the BSD License.
179
+ *
180
+ * Copyright © 2001 Robert Penner
181
+ * All rights reserved.
182
+ *
183
+ * Redistribution and use in source and binary forms, with or without modification,
184
+ * are permitted provided that the following conditions are met:
185
+ *
186
+ * Redistributions of source code must retain the above copyright notice, this list of
187
+ * conditions and the following disclaimer.
188
+ * Redistributions in binary form must reproduce the above copyright notice, this list
189
+ * of conditions and the following disclaimer in the documentation and/or other materials
190
+ * provided with the distribution.
191
+ *
192
+ * Neither the name of the author nor the names of contributors may be used to endorse
193
+ * or promote products derived from this software without specific prior written permission.
194
+ *
195
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
196
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
197
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
198
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
199
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
200
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
201
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
202
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
203
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
204
+ *
205
+ */
@@ -0,0 +1,1031 @@
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);