jquery-tablesorter 1.10.2 → 1.10.3
Sign up to get free protection for your applications and to get access to all the features.
- 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);
|