jquery-tablesorter 1.10.2 → 1.10.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.
- checksums.yaml +4 -4
- data/README.markdown +6 -3
- data/Rakefile +30 -16
- data/lib/jquery-tablesorter/version.rb +1 -1
- data/vendor/assets/javascripts/jquery-tablesorter/extras/jquery.quicksearch.js +191 -0
- data/vendor/assets/javascripts/jquery-tablesorter/extras/semver-mod.js +1026 -0
- data/vendor/assets/javascripts/jquery-tablesorter/extras/semver.js +1011 -0
- data/vendor/assets/javascripts/jquery-tablesorter/jquery.tablesorter.js +2 -2
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-iso8601.js +34 -0
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-month.js +33 -0
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-two-digit-year.js +74 -0
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date-weekday.js +33 -0
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-date.js +36 -0
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-feet-inch-fraction.js +63 -0
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-file-type.js +73 -0
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-ignore-articles.js +47 -0
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-input-select.js +86 -0
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-ipv6.js +76 -0
- data/vendor/assets/javascripts/jquery-tablesorter/parsers/parser-metric.js +77 -0
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-build-table.js +441 -0
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-columnSelector.js +291 -0
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-cssStickyHeaders.js +67 -0
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-editable.js +89 -0
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-grouping.js +183 -0
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-pager.js +834 -0
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-repeatheaders.js +50 -0
- data/vendor/assets/javascripts/jquery-tablesorter/widgets/widget-scroller.js +241 -0
- metadata +24 -2
@@ -0,0 +1,76 @@
|
|
1
|
+
/*! IPv6 Address parser (WIP)
|
2
|
+
* IPv6 Address (ffff:0000:0000:0000:0000:0000:0000:0000)
|
3
|
+
* needs to support short versions like "::8" or "1:2::7:8"
|
4
|
+
* and "::00:192.168.10.184" (embedded IPv4 address)
|
5
|
+
* see http://www.intermapper.com/support/tools/IPV6-Validator.aspx
|
6
|
+
*/
|
7
|
+
/*global jQuery: false */
|
8
|
+
;(function($){
|
9
|
+
"use strict";
|
10
|
+
|
11
|
+
var ts = $.tablesorter;
|
12
|
+
|
13
|
+
$.extend( ts.regex, {}, {
|
14
|
+
ipv4Validate : /((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})/,
|
15
|
+
ipv4Extract : /([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/,
|
16
|
+
|
17
|
+
// simplified regex from http://www.intermapper.com/support/tools/IPV6-Validator.aspx
|
18
|
+
// (specifically from http://download.dartware.com/thirdparty/ipv6validator.js)
|
19
|
+
ipv6Validate : /^\s*((([0-9a-f]{1,4}:){7}([0-9a-f]{1,4}|:))|(([0-9a-f]{1,4}:){6}(:[0-9a-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){5}(((:[0-9a-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){4}(((:[0-9a-f]{1,4}){1,3})|((:[0-9a-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){3}(((:[0-9a-f]{1,4}){1,4})|((:[0-9a-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){2}(((:[0-9a-f]{1,4}){1,5})|((:[0-9a-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){1}(((:[0-9a-f]{1,4}){1,6})|((:[0-9a-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9a-f]{1,4}){1,7})|((:[0-9a-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/i
|
20
|
+
});
|
21
|
+
|
22
|
+
ts.addParser({
|
23
|
+
id: "ipv6Address",
|
24
|
+
is: function(s) {
|
25
|
+
return ts.regex.ipv6Validate.test(s);
|
26
|
+
},
|
27
|
+
format: function(address, table) {
|
28
|
+
// code modified from http://forrst.com/posts/JS_Expand_Abbreviated_IPv6_Addresses-1OR
|
29
|
+
var i, t, sides, groups, groupsPresent,
|
30
|
+
hex = table ? (typeof table === "boolean" ? table : table && table.config.ipv6HexFormat || false) : false,
|
31
|
+
fullAddress = '',
|
32
|
+
expandedAddress = '',
|
33
|
+
validGroupCount = 8,
|
34
|
+
validGroupSize = 4;
|
35
|
+
// remove any extra spaces
|
36
|
+
address = address.replace(/\s*/g, '');
|
37
|
+
// look for embedded ipv4
|
38
|
+
if (ts.regex.ipv4Validate.test(address)) {
|
39
|
+
groups = address.match(ts.regex.ipv4Extract);
|
40
|
+
t = '';
|
41
|
+
for (i = 1; i < groups.length; i++){
|
42
|
+
t += ('00' + (parseInt(groups[i], 10).toString(16)) ).slice(-2) + ( i === 2 ? ':' : '' );
|
43
|
+
}
|
44
|
+
address = address.replace( ts.regex.ipv4Extract, t );
|
45
|
+
}
|
46
|
+
|
47
|
+
if (address.indexOf("::") == -1) {
|
48
|
+
// All eight groups are present
|
49
|
+
fullAddress = address;
|
50
|
+
} else {
|
51
|
+
// Consecutive groups of zeroes have been collapsed with "::".
|
52
|
+
sides = address.split("::");
|
53
|
+
groupsPresent = 0;
|
54
|
+
for (i = 0; i < sides.length; i++) {
|
55
|
+
groupsPresent += sides[i].split(":").length;
|
56
|
+
}
|
57
|
+
fullAddress += sides[0] + ":";
|
58
|
+
for (i = 0; i < validGroupCount - groupsPresent; i++) {
|
59
|
+
fullAddress += "0000:";
|
60
|
+
}
|
61
|
+
fullAddress += sides[1];
|
62
|
+
}
|
63
|
+
groups = fullAddress.split(":");
|
64
|
+
for (i = 0; i < validGroupCount; i++) {
|
65
|
+
// it's fastest & easiest for tablesorter to sort decimal values (vs hex)
|
66
|
+
groups[i] = hex ? ('0000' + groups[i]).slice(-4) :
|
67
|
+
('00000' + (parseInt(groups[i], 16) || 0)).slice(-5);
|
68
|
+
expandedAddress += ( i != validGroupCount-1) ? groups[i] + ':' : groups[i];
|
69
|
+
}
|
70
|
+
return hex ? expandedAddress : expandedAddress.replace(/:/g, '');
|
71
|
+
},
|
72
|
+
// uses natural sort hex compare
|
73
|
+
type: "numeric"
|
74
|
+
});
|
75
|
+
|
76
|
+
})(jQuery);
|
@@ -0,0 +1,77 @@
|
|
1
|
+
/*! Metric parser
|
2
|
+
* Demo: http://jsfiddle.net/Mottie/abkNM/382/
|
3
|
+
* Set the metric name in the header (defaults to "m|meter"), e.g.
|
4
|
+
* <th data-metric-name="b|byte">HDD Size</th>
|
5
|
+
* <th data-metric-name="m|meter">Distance</th>
|
6
|
+
*/
|
7
|
+
/*jshint jquery:true */
|
8
|
+
;(function($){
|
9
|
+
"use strict";
|
10
|
+
|
11
|
+
var prefixes = {
|
12
|
+
// "prefix" : [ base 10, base 2 ]
|
13
|
+
// skipping IEEE 1541 defined prefixes: kibibyte, mebibyte, etc, for now.
|
14
|
+
"Y|Yotta|yotta" : [ 1e24, Math.pow(1024, 8) ], // 1024^8
|
15
|
+
"Z|Zetta|zetta" : [ 1e21, Math.pow(1024, 7) ], // 1024^7
|
16
|
+
"E|Exa|exa" : [ 1e18, Math.pow(1024, 6) ], // 1024^6
|
17
|
+
"P|Peta|peta" : [ 1e15, Math.pow(1024, 5) ], // 1024^5
|
18
|
+
"T|Tera|tera" : [ 1e12, Math.pow(1024, 4) ], // 1024^4
|
19
|
+
"G|Giga|giga" : [ 1e9, Math.pow(1024, 3) ], // 1024^3
|
20
|
+
"M|Mega|mega" : [ 1e6, Math.pow(1024, 2) ], // 1024^2
|
21
|
+
"k|Kilo|kilo" : [ 1e3, 1024 ], // 1024
|
22
|
+
// prefixes below here are rarely, if ever, used in binary
|
23
|
+
"h|hecto" : [ 1e2, 1e2 ],
|
24
|
+
"da|deka" : [ 1e1, 1e1 ],
|
25
|
+
"d|deci" : [ 1e-1, 1e-1 ],
|
26
|
+
"c|centi" : [ 1e-2, 1e-2],
|
27
|
+
"m|milli" : [ 1e-3, 1e-3 ],
|
28
|
+
"µ|micro" : [ 1e-6, 1e-6 ],
|
29
|
+
"n|nano" : [ 1e-9, 1e-9 ],
|
30
|
+
"p|pico" : [ 1e-12, 1e-12 ],
|
31
|
+
"f|femto" : [ 1e-15, 1e-15 ],
|
32
|
+
"a|atto" : [ 1e-18, 1e-18 ],
|
33
|
+
"z|zepto" : [ 1e-21, 1e-21 ],
|
34
|
+
"y|yocto" : [ 1e-24, 1e-24 ]
|
35
|
+
},
|
36
|
+
// the \\d+ will not catch digits with spaces, commas or decimals; so use the value from n instead
|
37
|
+
RegLong = "(\\d+)(\\s+)?([Zz]etta|[Ee]xa|[Pp]eta|[Tt]era|[Gg]iga|[Mm]ega|kilo|hecto|deka|deci|centi|milli|micro|nano|pico|femto|atto|zepto|yocto)(",
|
38
|
+
RegAbbr = "(\\d+)(\\s+)?(Z|E|P|T|G|M|k|h|da|d|c|m|µ|n|p|f|a|z|y)(";
|
39
|
+
|
40
|
+
$.tablesorter.addParser({
|
41
|
+
id: 'metric',
|
42
|
+
is: function() {
|
43
|
+
return false;
|
44
|
+
},
|
45
|
+
format: function(s, table, cell, cellIndex) {
|
46
|
+
var v = 'm|meter',
|
47
|
+
b, t,
|
48
|
+
// process number here to get a numerical format (us or eu)
|
49
|
+
n = $.tablesorter.formatFloat(s.replace(/[^\w,. \-()]/g, ""), table),
|
50
|
+
$t = table.config.$headers.filter('[data-column="' + cellIndex + '"]'),
|
51
|
+
m = $t.data('metric');
|
52
|
+
if (!m) {
|
53
|
+
// stored values
|
54
|
+
t = ($t.attr('data-metric-name') || v).split('|');
|
55
|
+
m = [ t[1] || t[0].substring(1), t[0] ];
|
56
|
+
m[2] = new RegExp(RegLong + m[0] + "|" + m[1] + ")");
|
57
|
+
m[3] = new RegExp(RegAbbr + m[1] + ")");
|
58
|
+
$t.data('metric', m);
|
59
|
+
}
|
60
|
+
// find match to full name or abbreviation
|
61
|
+
t = s.match(m[2]) || s.match(m[3]);
|
62
|
+
if (t) {
|
63
|
+
for (v in prefixes) {
|
64
|
+
if (t[3].match(v)) {
|
65
|
+
// exception when using binary prefix
|
66
|
+
// change base for binary use
|
67
|
+
b = /^[b|bit|byte|o|octet]/.test(t[4]) ? 1 : 0;
|
68
|
+
return n * prefixes[v][b];
|
69
|
+
}
|
70
|
+
}
|
71
|
+
}
|
72
|
+
return n;
|
73
|
+
},
|
74
|
+
type: 'numeric'
|
75
|
+
});
|
76
|
+
|
77
|
+
})(jQuery);
|
@@ -0,0 +1,441 @@
|
|
1
|
+
/*! Build Table widget * by Rob Garrison */
|
2
|
+
/*jshint browser:true, jquery:true, unused:false */
|
3
|
+
/*global jQuery: false */
|
4
|
+
;(function($){
|
5
|
+
"use strict";
|
6
|
+
var ts = $.tablesorter = $.tablesorter || {},
|
7
|
+
|
8
|
+
// build a table from data (requires existing <table> tag)
|
9
|
+
// data.header contains an array of header titles
|
10
|
+
// data.rows contains an array of rows which contains an array of cells
|
11
|
+
bt = ts.buildTable = function(tar, c){
|
12
|
+
// add table if one doesn't exist
|
13
|
+
var $tbl = tar.tagName === 'TABLE' ? $(tar) : $('<table>').appendTo(tar),
|
14
|
+
table = $tbl[0],
|
15
|
+
wo = c.widgetOptions = $.extend( true, {}, bt.defaults, c.widgetOptions ),
|
16
|
+
p = wo.build_processing,
|
17
|
+
typ = wo.build_type,
|
18
|
+
d = wo.build_source || c.data,
|
19
|
+
|
20
|
+
// determine type: html, json, array, csv, object
|
21
|
+
runType = function(d){
|
22
|
+
var t = $.type(d),
|
23
|
+
jq = d instanceof jQuery;
|
24
|
+
// run any processing if set
|
25
|
+
if ( typeof p === 'function' ) { d = p(d, wo); }
|
26
|
+
// store processed data in table.config.data
|
27
|
+
c.data = d;
|
28
|
+
// String (html or unprocessed json) or jQuery object
|
29
|
+
if ( jq || t === 'string' ) {
|
30
|
+
// look for </tr> closing tag, then we have an HTML string
|
31
|
+
if ( jq || /<\s*\/tr\s*>/.test(d) ) {
|
32
|
+
return bt.html( table, d, wo );
|
33
|
+
}
|
34
|
+
try {
|
35
|
+
d = $.parseJSON(d);
|
36
|
+
if (d) {
|
37
|
+
// valid JSON!
|
38
|
+
return bt.object( table, d, wo );
|
39
|
+
}
|
40
|
+
} catch(ignore) {}
|
41
|
+
// fall through in case it's a csv string
|
42
|
+
}
|
43
|
+
// Array
|
44
|
+
if (t === 'array' || t === 'string' || typ === 'array' || typ === 'csv') {
|
45
|
+
// build table using an array (csv & array combined script)
|
46
|
+
return bt.csv( table, d, wo );
|
47
|
+
}
|
48
|
+
// if we got here, it's an object, or nothing
|
49
|
+
return bt.object( table, d, wo );
|
50
|
+
};
|
51
|
+
|
52
|
+
// store config
|
53
|
+
table.config = c;
|
54
|
+
|
55
|
+
// even if wo.build_type is undefined, we can try to figure out the type
|
56
|
+
if ( !ts.buildTable.hasOwnProperty(typ) && typ !== '' ) {
|
57
|
+
if (c.debug) { ts.log('aborting build table widget, incorrect build type'); }
|
58
|
+
return false;
|
59
|
+
}
|
60
|
+
|
61
|
+
if ( d instanceof jQuery ) {
|
62
|
+
// get data from within a jQuery object (csv)
|
63
|
+
runType( $.trim( d.html() ) );
|
64
|
+
} else if ( d && ( d.hasOwnProperty('url') || typ === 'json' ) ) {
|
65
|
+
// load data via ajax
|
66
|
+
$.ajax( wo.build_source )
|
67
|
+
.done(function(data) {
|
68
|
+
runType(data);
|
69
|
+
})
|
70
|
+
.fail(function( jqXHR, textStatus, errorThrown) {
|
71
|
+
if (c.debug) { ts.log('aborting build table widget, failed ajax load'); }
|
72
|
+
$tbl.html('<tr><td class="error">' + jqXHR.status + ' ' + textStatus + '</td></tr>');
|
73
|
+
});
|
74
|
+
} else {
|
75
|
+
runType(d);
|
76
|
+
}
|
77
|
+
};
|
78
|
+
|
79
|
+
bt.defaults = {
|
80
|
+
// *** build widget core ***
|
81
|
+
build_type : '', // array, csv, object, json, html
|
82
|
+
build_source : '', // array, object, jQuery Object or ajaxObject { url: '', dataType: 'json' },
|
83
|
+
build_processing : null, // function that returns a useable build_type (e.g. string to array)
|
84
|
+
build_complete : 'tablesorter-build-complete', // triggered event when build completes
|
85
|
+
|
86
|
+
// *** CSV & Array ***
|
87
|
+
build_headers : {
|
88
|
+
rows : 1, // Number of header rows from the csv
|
89
|
+
classes : [], // Header classes to apply to cells
|
90
|
+
text : [], // Header cell text
|
91
|
+
widths : [] // set header cell widths (set in colgroup)
|
92
|
+
},
|
93
|
+
build_footers : {
|
94
|
+
rows : 1, // Number of header rows from the csv
|
95
|
+
classes : [], // Footer classes to apply to cells
|
96
|
+
text : [] // Footer cell text
|
97
|
+
},
|
98
|
+
build_numbers : {
|
99
|
+
addColumn : false, // include row numbering column?
|
100
|
+
sortable : false // make column sortable?
|
101
|
+
},
|
102
|
+
|
103
|
+
// *** CSV only options ***
|
104
|
+
build_csvStartLine : 0, // line within the csv to start adding to table
|
105
|
+
build_csvSeparator : ",", // csv separator
|
106
|
+
|
107
|
+
// *** build object options ***
|
108
|
+
build_objectRowKey : 'rows', // object key containing table rows
|
109
|
+
build_objectCellKey : 'cells', // object key containing table cells (within the rows object)
|
110
|
+
build_objectHeaderKey : 'headers', // object key containing table headers
|
111
|
+
build_objectFooterKey : 'footers' // object key containing table footers
|
112
|
+
};
|
113
|
+
|
114
|
+
bt.build = {
|
115
|
+
colgroup : function(widths) {
|
116
|
+
var t = '';
|
117
|
+
// add colgroup if widths set
|
118
|
+
if (widths && widths.length) {
|
119
|
+
t += '<colgroup>';
|
120
|
+
$.each(widths, function(i, w){
|
121
|
+
t += '<col' + ( w ? ' style="width:' + w + '"' : '' ) + '>';
|
122
|
+
});
|
123
|
+
t += '</colgroup>';
|
124
|
+
}
|
125
|
+
return t;
|
126
|
+
},
|
127
|
+
// d = cell data; typ = 'th' or 'td'; first = save widths from first header row only
|
128
|
+
cell : function(d, wo, typ, col, first){
|
129
|
+
var j, $td,
|
130
|
+
$col = first ? $('<col>') : '',
|
131
|
+
cls = wo.build_headers.classes,
|
132
|
+
cw = wo.build_headers.widths;
|
133
|
+
// d is just an array
|
134
|
+
if (/string|number/.test(typeof d)) {
|
135
|
+
// add classes from options, but not text
|
136
|
+
$td = $('<' + typ + (cls && cls[col] ? ' class="' + cls[col] + '"' : '') + '>' + d + '</' + typ + '>');
|
137
|
+
// get widths from options (only from first row)
|
138
|
+
if (first && cw && cw[col]) {
|
139
|
+
$col.width(cw[col] || '');
|
140
|
+
}
|
141
|
+
} else {
|
142
|
+
// assume we have an object
|
143
|
+
$td = $('<' + typ + '>');
|
144
|
+
for (j in d) {
|
145
|
+
if (d.hasOwnProperty(j)){
|
146
|
+
if (j === 'text' || j === 'html') {
|
147
|
+
$td[j]( d[j] );
|
148
|
+
} else if (first && j === 'width') {
|
149
|
+
// set column width, but only from first row
|
150
|
+
$col.width(d[j] || '');
|
151
|
+
} else {
|
152
|
+
$td.attr(j, d[j]);
|
153
|
+
}
|
154
|
+
}
|
155
|
+
}
|
156
|
+
}
|
157
|
+
return [ $td, $col ];
|
158
|
+
},
|
159
|
+
// h1 = header text from data
|
160
|
+
header : function(h1, wo){
|
161
|
+
var h2 = wo.build_headers.text,
|
162
|
+
cls = wo.build_headers.classes,
|
163
|
+
t = '<tr>' + (wo.build_numbers.addColumn ? '<th' + (wo.build_numbers.sortable ? '' :
|
164
|
+
' class="sorter-false"') + '>' + wo.build_numbers.addColumn + '</th>' : '');
|
165
|
+
$.each(h1, function(i, h) {
|
166
|
+
t += '<th' + (cls && cls[i] ? ' class="' + cls[i] + '"' : '') + '>' +
|
167
|
+
(h2 && h2[i] ? h2[i] : h) + '</th>';
|
168
|
+
});
|
169
|
+
return t + '</tr>';
|
170
|
+
},
|
171
|
+
rows : function(items, txt, c, wo, num, ftr){
|
172
|
+
var h = (ftr ? 'th' : 'td'),
|
173
|
+
t = '<tr>' + (wo.build_numbers.addColumn ? '<' + h + '>' + (ftr ? '' : num) + '</' + h + '>' : '');
|
174
|
+
$.each(items, function(i, item) {
|
175
|
+
t += '<' + (ftr ? h + (c && c[i] ? ' class="' + c[i] + '"' : '') : h) + '>' +
|
176
|
+
(ftr && txt && txt.length && txt[i] ? txt[i] : item) + '</' + h + '>';
|
177
|
+
});
|
178
|
+
return t + '</tr>';
|
179
|
+
}
|
180
|
+
};
|
181
|
+
|
182
|
+
bt.buildComplete = function(table, wo){
|
183
|
+
$(table).trigger(wo.build_complete);
|
184
|
+
ts.setup(table, table.config);
|
185
|
+
};
|
186
|
+
|
187
|
+
/* ==== Array example ====
|
188
|
+
[
|
189
|
+
[ "header1", "header2", ... "headerN" ],
|
190
|
+
[ "row1cell1", "row1cell2", ... "row1cellN" ],
|
191
|
+
[ "row2cell1", "row2cell2", ... "row2cellN" ],
|
192
|
+
...
|
193
|
+
[ "rowNcell1", "rowNcell2", ... "rowNcellN" ]
|
194
|
+
]
|
195
|
+
*/
|
196
|
+
bt.array = function(table, data, wo) {
|
197
|
+
return bt.csv(table, data, wo);
|
198
|
+
};
|
199
|
+
|
200
|
+
/* ==== CSV example ====
|
201
|
+
ID, Name, Age, Date
|
202
|
+
A42b, Parker, 28, "Jul 6, 2006 8:14 AM"
|
203
|
+
A255, Hood, 33, "Dec 10, 2002 5:14 AM"
|
204
|
+
A33, Kent, 18, "Jan 12, 2003 11:14 AM"
|
205
|
+
A1, Franklin, 45, "Jan 18, 2001 9:12 AM"
|
206
|
+
A102, Evans, 22, "Jan 18, 2007 9:12 AM"
|
207
|
+
A42a, Everet, 22, "Jan 18, 2007 9:12 AM"
|
208
|
+
ID, Name, Age, Date
|
209
|
+
*/
|
210
|
+
// Adapted & modified from csvToTable.js by Steve Sobel
|
211
|
+
// MIT license: https://code.google.com/p/jquerycsvtotable/
|
212
|
+
bt.csv = function(table, data, wo) {
|
213
|
+
var c, h,
|
214
|
+
csv = wo.build_type === 'csv' || typeof data === 'string',
|
215
|
+
$t = $(table),
|
216
|
+
lines = csv ? data.replace('\r','').split('\n') : data,
|
217
|
+
len = lines.length,
|
218
|
+
printedLines = 0,
|
219
|
+
infooter = false,
|
220
|
+
r = wo.build_headers.rows + (csv ? wo.build_csvStartLine : 0),
|
221
|
+
f = wo.build_footers.rows,
|
222
|
+
headerCount = 0,
|
223
|
+
error = '',
|
224
|
+
items,
|
225
|
+
tableHTML = bt.build.colgroup( wo.build_headers.widths ) + '<thead>';
|
226
|
+
|
227
|
+
$.each(lines, function(n, line) {
|
228
|
+
if ( n >= len - f ) { infooter = true; }
|
229
|
+
// build header
|
230
|
+
if ( (csv ? n >= wo.build_csvStartLine : true) && ( n < r ) ) {
|
231
|
+
h = csv ? bt.splitCSV( line, wo.build_csvSeparator ) : line;
|
232
|
+
headerCount = h.length;
|
233
|
+
tableHTML += bt.build.header(h, wo);
|
234
|
+
} else if ( n >= r ) {
|
235
|
+
// build tbody & tfoot rows
|
236
|
+
if (n === r) {
|
237
|
+
tableHTML += '</thead><tbody>';
|
238
|
+
}
|
239
|
+
items = csv ? bt.splitCSV( line, wo.build_csvSeparator ) : line;
|
240
|
+
if (infooter && f > 0) {
|
241
|
+
tableHTML += (n === len - f ? '</tbody><tfoot>' : '') +
|
242
|
+
(n === len ? '</tfoot>' : '');
|
243
|
+
}
|
244
|
+
if (items.length > 1) {
|
245
|
+
printedLines++;
|
246
|
+
if ( items.length !== headerCount ) {
|
247
|
+
error += 'error on line ' + n + ': Item count (' + items.length +
|
248
|
+
') does not match header count (' + headerCount + ') \n';
|
249
|
+
}
|
250
|
+
c = infooter ? wo.build_footers.classes : '';
|
251
|
+
tableHTML += bt.build.rows(items, wo.build_footers.text, c, wo, printedLines, infooter);
|
252
|
+
}
|
253
|
+
}
|
254
|
+
});
|
255
|
+
tableHTML += (f > 0 ? '' : '</tbody>');
|
256
|
+
if (error) {
|
257
|
+
$t.html(error);
|
258
|
+
} else {
|
259
|
+
$t.html(tableHTML);
|
260
|
+
bt.buildComplete(table, wo);
|
261
|
+
}
|
262
|
+
};
|
263
|
+
|
264
|
+
// CSV Parser by Brian Huisman (http://www.greywyvern.com/?post=258)
|
265
|
+
bt.splitCSV = function(str, sep) {
|
266
|
+
var x, tl,
|
267
|
+
thisCSV = $.trim(str).split(sep = sep || ",");
|
268
|
+
for ( x = thisCSV.length - 1; x >= 0; x-- ) {
|
269
|
+
if ( thisCSV[x].replace(/\"\s+$/, '"').charAt(thisCSV[x].length - 1) === '"' ) {
|
270
|
+
if ( (tl = thisCSV[x].replace(/^\s+\"/, '"')).length > 1 && tl.charAt(0) === '"' ) {
|
271
|
+
thisCSV[x] = thisCSV[x].replace(/^\s*"|"\s*$/g, '').replace(/""/g, '"');
|
272
|
+
} else if (x) {
|
273
|
+
thisCSV.splice(x - 1, 2, [thisCSV[x - 1], thisCSV[x]].join(sep));
|
274
|
+
} else {
|
275
|
+
thisCSV = thisCSV.shift().split(sep).concat(thisCSV);
|
276
|
+
}
|
277
|
+
} else {
|
278
|
+
thisCSV[x].replace(/""/g, '"');
|
279
|
+
}
|
280
|
+
}
|
281
|
+
return thisCSV;
|
282
|
+
};
|
283
|
+
|
284
|
+
// data may be a jQuery object after processing
|
285
|
+
bt.html = function(table, data, wo) {
|
286
|
+
var $t = $(table);
|
287
|
+
if ( data instanceof jQuery ) {
|
288
|
+
$t.empty().append(data);
|
289
|
+
} else {
|
290
|
+
$t.html(data);
|
291
|
+
}
|
292
|
+
bt.buildComplete(table, wo);
|
293
|
+
};
|
294
|
+
|
295
|
+
/* ==== Object example ====
|
296
|
+
data : {
|
297
|
+
headers : [
|
298
|
+
[
|
299
|
+
{ text: 'First Name', class: 'fname', width: '20%' }, // row 1 cell 1
|
300
|
+
'Last Name',
|
301
|
+
{ text: 'Age', class: 'age', 'data-sorter' : false },
|
302
|
+
'Total',
|
303
|
+
{ text: 'Discount', class : 'sorter-false' },
|
304
|
+
{ text: 'Date', class : 'date' } // row 1 cell 6
|
305
|
+
]
|
306
|
+
],
|
307
|
+
footers : 'clone', // clone headers or assign array like headers
|
308
|
+
rows : [
|
309
|
+
// TBODY 1
|
310
|
+
[ 'Peter', 'Parker', 28, '$9.99', '20%', 'Jul 6, 2006 8:14 AM' ], // row 1
|
311
|
+
[ 'John', 'Hood', 33, '$19.99', '25%', 'Dec 10, 2002 5:14 AM' ], // row 2
|
312
|
+
[ 'Clark', 'Kent', 18, '$15.89', '44%', 'Jan 12, 2003 11:14 AM' ], // row 3
|
313
|
+
|
314
|
+
// TBODY 2
|
315
|
+
{ newTbody: true, class: 'tablesorter-infoOnly' },
|
316
|
+
{ cells : [ { text: 'Info Row', colSpan: 6 } ] }, // row 4
|
317
|
+
|
318
|
+
// TBODY 3
|
319
|
+
{ newTbody: true },
|
320
|
+
[ 'Bruce', 'Evans', 22, '$13.19', '11%', 'Jan 18, 2007 9:12 AM' ], // row 5
|
321
|
+
[ 'Brice', 'Almighty', 45, '$153.19', '44%', 'Jan 18, 2001 9:12 AM' ], // row 6
|
322
|
+
|
323
|
+
{ class: 'specialRow', // row 7
|
324
|
+
cells: [
|
325
|
+
{ text: 'Fred', class: 'fname' },
|
326
|
+
{ text: 'Smith', class: 'lname' },
|
327
|
+
{ text: 18, class: 'age', 'data-info': 'fake ID!, he is really 16' },
|
328
|
+
{ text: '$22.44', class: 'total' },
|
329
|
+
{ text: '8%', class: 'discount' },
|
330
|
+
{ text: 'Aug 20, 2012 10:15 AM', class: 'date' }
|
331
|
+
],
|
332
|
+
'data-info' : 'This row likes turtles'
|
333
|
+
}
|
334
|
+
]
|
335
|
+
}
|
336
|
+
*/
|
337
|
+
bt.object = function(table, data, wo) {
|
338
|
+
// "rows"
|
339
|
+
var j, l, t, $c, $t, $tb, $tr,
|
340
|
+
c = table.config,
|
341
|
+
kh = wo.build_objectHeaderKey,
|
342
|
+
kr = wo.build_objectRowKey,
|
343
|
+
h = data.hasOwnProperty(kh) && !$.isEmptyObject(data.kh) ? data.kh : data.hasOwnProperty('headers') ? data.headers : false,
|
344
|
+
r = data.hasOwnProperty(kr) && !$.isEmptyObject(data.kr) ? data.kr : data.hasOwnProperty('rows') ? data.rows : false;
|
345
|
+
|
346
|
+
if (!h || !r || h.length === 0 || r.length === 0) {
|
347
|
+
if (c.debug) { ts.log('aborting build table widget, missing data for object build'); }
|
348
|
+
return false;
|
349
|
+
}
|
350
|
+
|
351
|
+
$c = $('<colgroup>');
|
352
|
+
$t = $('<table><thead/></table>');
|
353
|
+
|
354
|
+
// Build thead
|
355
|
+
// h = [ ['headerRow1Cell1', 'headerRow1Cell2', ... 'headerRow1CellN' ], ['headerRow2Cell1', ... ] ]
|
356
|
+
// or h = [ [ { text: 'firstCell', class: 'fc', width: '20%' }, ..., { text: 'last Cell' } ], [ /* second row */ ] ]
|
357
|
+
$.each(h, function(i, d){
|
358
|
+
$tr = $('<tr>').appendTo( $t.find('thead') );
|
359
|
+
l = d.length; // header row
|
360
|
+
for ( j = 0; j < l; j++ ) {
|
361
|
+
// cell(cellData, widgetOptions, 'th', first row)
|
362
|
+
t = bt.build.cell(d[j], wo, 'th', j, i === 0);
|
363
|
+
if (t[0] && t[0].length) { t[0].appendTo( $tr ); } // add cell
|
364
|
+
if (i === 0 && t[1]) { t[1].appendTo( $c ); } // add col to colgroup
|
365
|
+
}
|
366
|
+
});
|
367
|
+
if ($c.find('col[style]').length) {
|
368
|
+
// add colgroup if it contains col elements
|
369
|
+
$t.prepend( $c );
|
370
|
+
}
|
371
|
+
|
372
|
+
$tb = $('<tbody>');
|
373
|
+
// Build tbody
|
374
|
+
$.each(r, function(i, d){
|
375
|
+
t = $.type(d) === 'object';
|
376
|
+
// add new tbody
|
377
|
+
if (t && d.newTbody) {
|
378
|
+
$tb = $('<tbody>').appendTo( $t );
|
379
|
+
for (j in d) {
|
380
|
+
if (d.hasOwnProperty(j) && j !== 'newTbody'){
|
381
|
+
$tb.attr(j, d[j]);
|
382
|
+
}
|
383
|
+
}
|
384
|
+
} else {
|
385
|
+
if (i === 0) {
|
386
|
+
// add tbody, if the first item in the object isn't a call for a new tbody
|
387
|
+
$tb.appendTo( $t );
|
388
|
+
}
|
389
|
+
|
390
|
+
$tr = $('<tr>').appendTo( $tb );
|
391
|
+
if (t) {
|
392
|
+
// row defined by object
|
393
|
+
for (j in d) {
|
394
|
+
if (d.hasOwnProperty(j) && j !== wo.build_objectCellKey){
|
395
|
+
$tr.attr(j, d[j]);
|
396
|
+
}
|
397
|
+
}
|
398
|
+
if (d.hasOwnProperty(wo.build_objectCellKey)) {
|
399
|
+
// cells contains each cell info
|
400
|
+
d = d.cells;
|
401
|
+
}
|
402
|
+
}
|
403
|
+
|
404
|
+
l = d.length;
|
405
|
+
for ( j = 0; j < l; j++ ) {
|
406
|
+
// cell(cellData, widgetOptions, 'td')
|
407
|
+
$c = bt.build.cell(d[j], wo, 'td', j);
|
408
|
+
if ($c[0] && $c[0].length) { $c[0].appendTo( $tr ); } // add cell
|
409
|
+
}
|
410
|
+
}
|
411
|
+
});
|
412
|
+
|
413
|
+
// add footer
|
414
|
+
if (data.hasOwnProperty(wo.build_objectFooterKey)) {
|
415
|
+
t = data[wo.build_objectFooterKey];
|
416
|
+
if (t === 'clone') {
|
417
|
+
$c = $t.find('thead').html();
|
418
|
+
$t.append('<tfoot>' + $c + '</tfoot>');
|
419
|
+
} else {
|
420
|
+
$c = $('<tfoot>').appendTo( $t );
|
421
|
+
$.each(t, function(i, d) {
|
422
|
+
$tr = $('<tr>').appendTo( $c );
|
423
|
+
l = d.length; // footer cells
|
424
|
+
for ( j = 0; j < l; j++ ) {
|
425
|
+
// cell(cellData, widgetOptions, 'th')
|
426
|
+
$tb = bt.build.cell(d[j], wo, 'th', j);
|
427
|
+
if ($tb[0] && $tb[0].length) { $tb[0].appendTo( $tr ); } // add cell
|
428
|
+
}
|
429
|
+
});
|
430
|
+
}
|
431
|
+
}
|
432
|
+
|
433
|
+
$(table).html( $t.html() );
|
434
|
+
bt.buildComplete(table, wo);
|
435
|
+
};
|
436
|
+
|
437
|
+
bt.ajax = bt.json = function(table, data, wo) {
|
438
|
+
return bt.object(table, data, wo);
|
439
|
+
};
|
440
|
+
|
441
|
+
})(jQuery);
|