0
|
1 /**
|
|
2 * jQuery-tsv (jQuery Plugin)
|
|
3 *
|
|
4 * Inspired by jQuery-csv by Evan Plaice.
|
|
5 *
|
|
6 * Copyright 2012 by Bob Kerns
|
|
7 *
|
|
8 * This software is licensed as free software under the terms of the MIT License:
|
|
9 * http://www.opensource.org/licenses/mit-license.php
|
|
10 */
|
|
11
|
|
12 (function ($) {
|
|
13 // Make sure we have a copy, not original, of $.tsv.options.
|
|
14 function copyOptions(options) {
|
|
15 return $.extend({__copy: true}, options);
|
|
16 }
|
|
17 // Default the options.
|
|
18 function tsvOptions(options) {
|
|
19 if (options) {
|
|
20 if (options.__defaults_applied) {
|
|
21 return options;
|
|
22 }
|
|
23 return $.extend(copyOptions($.tsv.options), options);
|
|
24 }
|
|
25 return copyOptions($.tsv.options);
|
|
26 }
|
|
27
|
|
28 function tsvColumn(options, index) {
|
|
29 var opts = tsvOptions(options);
|
|
30 return String(opts.columns ? opts.columns[index] : index);
|
|
31 }
|
|
32
|
|
33 function tsvColumns(options, top) {
|
|
34 if (options.columns) {
|
|
35 return options.columns;
|
|
36 } else {
|
|
37 var cols = Object.keys(top || {}).sort();
|
|
38 options.columns = cols;
|
|
39 return cols;
|
|
40 }
|
|
41 }
|
|
42
|
|
43 $.tsv = {
|
|
44 version: "0.957",
|
|
45 /**
|
|
46 * The default set of options. It is not recommended to change these, as the impact will be global
|
|
47 */
|
|
48 options: {
|
|
49 /**
|
|
50 * If supplied, a function to format a value on output.
|
|
51 * The returned value is used in the output instead of the supplied value.
|
|
52 * If not supplied, it is simply converted to a string.
|
|
53 *
|
|
54 * @param value the value to be formatted.
|
|
55 * @param the options
|
|
56 * @param colnum the column number
|
|
57 * @param colname the column name, if known, or the column number as a string.
|
|
58 * @param rownum the row number
|
|
59 * @returns the value, formatted
|
|
60 */
|
|
61 formatValue: null,
|
|
62 /**
|
|
63 * If supplied, a function to parse or canonicalize a value on input.
|
|
64 * The returned value is used in place of the input.
|
|
65 *
|
|
66 * @param value the value to be formatted.
|
|
67 * @param the options
|
|
68 * @param colnum the column number
|
|
69 * @param colname the column name, if known, or the column number as a string.
|
|
70 * @param rownum the row number
|
|
71 * @returns the value, parsed
|
|
72 */
|
|
73 parseValue: null,
|
|
74 /**
|
|
75 * The character sequence to use to separate lines.
|
|
76 */
|
|
77 lineSeparator: "\n",
|
|
78 /** A RegExp to recognize line separators */
|
|
79 lineSplitter: /\r?\n/,
|
|
80 /** The character sequence to use to separate values. */
|
|
81 valueSeparator: "\t",
|
|
82 /** A RegExp to recognize value separators. */
|
|
83 valueSplitter: /\t/,
|
|
84 /**
|
|
85 * If supplied, a function of one argument to convert a row to an object.
|
|
86 *
|
|
87 * @param row an array of values, e.g. ["1", "2", "3.14"]
|
|
88 * @param options { columns: ["id", "count", "price"] }
|
|
89 * @returns e.g. {id: "1", count: "2", price: "3.14"}
|
|
90 */
|
|
91 arrayToObject: null,
|
|
92 /**
|
|
93 * If supplied, a function of one argument to convert an object to a row. Typically, this will implement a variant
|
|
94 * of the contract for $.tsv.objectToArray.
|
|
95 *
|
|
96 * @param object an object to be converted to a row, e.g. {id: "1", count: "2", price: "3.14"}
|
|
97 * @param options { columns: ["id", "count", "price"] }
|
|
98 * @returns an array of values, e.g. ["1", "2", "3.14"]. Typically these would be ordered by options.column
|
|
99 */
|
|
100 objectToArray: null,
|
|
101 /**
|
|
102 * If true, when converting from an array of objects to a TSV string, include the column names as the
|
|
103 * first line. For most purposes, you won't want to override this, but if you're working with tables in sections,
|
|
104 * for example, you'd want to suppress this for the latter segments.
|
|
105 *
|
|
106 * But you are strongly encouraged to use column names whenever possible, especially if you work with objects.
|
|
107 */
|
|
108 includeHeader: true,
|
|
109 /**
|
|
110 * The starting row number, not counting the header, if any (which is always numbered -1).
|
|
111 * This can be useful for computing subranges of a table, or appending to a table.
|
|
112 */
|
|
113 startRownum: 0,
|
|
114 // An internal flag, to avoid multiple defaulting steps.
|
|
115 // values are true, if it is this default, or 'copy'.
|
|
116 ___defaults_applied: true,
|
|
117 extend: $.extend
|
|
118 },
|
|
119
|
|
120 /**
|
|
121 * Parse one value. This can be overridden in the options.
|
|
122 * @param value the string to parse
|
|
123 * @param options optional: { parseValue: <substitute function> }
|
|
124 * @param colnum the column number
|
|
125 * @param colname the column name, if known, or the column number as a string.
|
|
126 * @param rownum the row number
|
|
127 * @returns the string
|
|
128 */
|
|
129 parseValue: function parseValue(value, options, colnum, colname, rownum) {
|
|
130 var opts = tsvOptions(options);
|
|
131 if (opts.parseValue) {
|
|
132 // We have an override; use that instead.
|
|
133 return options.parseValue(value, opts, colnum, colname, rownum);
|
|
134 }
|
|
135 return value;
|
|
136 },
|
|
137
|
|
138 /**
|
|
139 * Format one value. This can be overridden in the options.
|
|
140 * @param value the value to format
|
|
141 * @param options optional: { formatValue: <substitute function> }
|
|
142 * @param colnum the column number
|
|
143 * @param colname the column name, if known, or the column number as a string.
|
|
144 * @param rownum the row number
|
|
145 */
|
|
146 formatValue: function formatValue(value, options, rownum, colnum, colname, rownum) {
|
|
147 var opts = tsvOptions(options);
|
|
148 if (opts.formatValue) {
|
|
149 // We have an override; use that instead.
|
|
150 return options.formatValue(value, opts, colnum, colname, rownum);
|
|
151 }
|
|
152 return String(value);
|
|
153 },
|
|
154
|
|
155 /**
|
|
156 * $.tsv.toArray(line, options) parses one line of TSV input into an array of values.
|
|
157 * @param line A line with values separated by single tab characters, e.g. "11\t12\t13"
|
|
158 * @param options optional: { valueSplitter: /\t/, parseValue: <a function to parse each value>}
|
|
159 * @param rownum optional: the row number (defaults to 0);
|
|
160 * @returns an array of values, e.g. ["11" "12", "13"]
|
|
161 */
|
|
162 toArray: function toArray(line, options, rownum) {
|
|
163 var opts = tsvOptions(options);
|
|
164 var valueSplitter = opts.valueSplitter;
|
|
165 rownum = rownum || 0;
|
|
166 var colnum = 0;
|
|
167 function doValue(val) {
|
|
168 var c = colnum++;
|
|
169 return $.tsv.parseValue(val, opts, c, tsvColumn(opts, c), rownum);
|
|
170 }
|
|
171 return line.split(valueSplitter).map(doValue);
|
|
172 },
|
|
173
|
|
174 /**
|
|
175 * $.tsv.fromArray(row, options) returns one line of TSV input from an array of values.
|
|
176 * @param array an array of values, e.g. ["11" "12", "13"]
|
|
177 * @param options optional: { valueSeparator: "\t", formatValue: <a function to format each value>}
|
|
178 * @param rownum optional: the row number (defaults to 0);
|
|
179 * @returns A line with values separated by single tab characters, e.g. "11\t12\t13"
|
|
180 */
|
|
181 fromArray: function fromArray(array, options, rownum) {
|
|
182 var opts = tsvOptions(options);
|
|
183 var valueSeparator = opts.valueSeparator;
|
|
184 var colnum = 0;
|
|
185 function doValue(val) {
|
|
186 var c = colnum++;
|
|
187 return $.tsv.formatValue(val, opts, c, tsvColumn(c), rownum);
|
|
188 }
|
|
189 return array.map(doValue).join(valueSeparator);
|
|
190 },
|
|
191
|
|
192 /**
|
|
193 * $.tsv.toArrays(tsv, options) returns an array of arrays, one per line, each containing values from one row.
|
|
194 * @param tsv a tab-separated-values input, e.g. "11\t\12\t13\n21\t22\t23"
|
|
195 * @param options optional: { valueSplitter: /\t/, lineSplitter: /\r?\n/, parseValue: <a function to parse each value> }
|
|
196 * @returns an array of arrays, e.g. [["11", "12", "13"], ["21", "22", "23"]]
|
|
197 */
|
|
198 toArrays: function toArrays(tsv, options) {
|
|
199 var opts = tsvOptions(options);
|
|
200 var lines = tsv.split(opts.lineSplitter);
|
|
201 var rownum = opts.startRownum || 0;
|
|
202 return lines.map(function doLine(line) {
|
|
203 return $.tsv.toArray(line, opts, rownum++);
|
|
204 });
|
|
205 },
|
|
206
|
|
207 /**
|
|
208 * $.tsv.fromArrays(array, options) returns a TSV string representing the array of row arrays.
|
|
209 * @param array an array of arrays of values. To produce valid TSV, all the arrays should be of the same length.
|
|
210 * @param options optional: { valueSeparator: "\t", lineSeparator: "\n", columns: ["c1", "c2", "c3"], formatValue: <a function to format each value> }
|
|
211 * @returns An tsv string, e.g. "c1\tc2\tc3\n11\t\12\t13\n21\t22\t23"
|
|
212 */
|
|
213 fromArrays: function fromArrays(array, options) {
|
|
214 var opts = tsvOptions(options);
|
|
215 var first = array.length ? array[0] : [];
|
|
216 var cols = tsvColumns(opts, first);
|
|
217 var rownum = opts.startRownum || 0;
|
|
218 var header = opts.includeHeader ? $.tsv.fromArray(cols, opts, -1) : undefined;
|
|
219 function doRow(row) {
|
|
220 return $.tsv.fromArray(row, opts, rownum++);
|
|
221 }
|
|
222 var rtemp = array.map(doRow);
|
|
223 if (header) {
|
|
224 rtemp.unshift(header);
|
|
225 }
|
|
226 return rtemp.join(opts.lineSeparator);
|
|
227 },
|
|
228
|
|
229 /**
|
|
230 * $.tsv.arrayToObject(row, options) returns an object whose fields are named in options.columns, and
|
|
231 * whose values come from the corresponding position in row (an array of values in the same order).
|
|
232 *
|
|
233 * If the columns are not supplied, "0", "1", etc. will be used.
|
|
234 * @param row the values, e.g. ["v1", "v2"]
|
|
235 * @param options optional: { columns: ["name1", "name2"], rowToObject: <optional conversion function to call instead> }
|
|
236 * @param rownum optional: the row number
|
|
237 * @returns an object derived from the elements of the row.
|
|
238 */
|
|
239 arrayToObject: function arrayToObject(row, options, rownum) {
|
|
240 var opts = tsvOptions(options);
|
|
241 rownum = rownum || 0;
|
|
242 var columns = tsvColumns(opts, row);
|
|
243 if (opts.arrayToObject) {
|
|
244 // We have an override; use that instead.
|
|
245 return opts.arrayToObject(row, opts, rownum);
|
|
246 }
|
|
247 var dict = {};
|
|
248 for (var j = 0; j < columns.length; j++) {
|
|
249 dict[columns[j]] = row[j];
|
|
250 }
|
|
251 return dict;
|
|
252 },
|
|
253
|
|
254 /**
|
|
255 * $.tsv.arraysToObjects(array, options) returns an array of objects, derived from the array.
|
|
256 * The array must either have the first row be column names, or columns: ["name1", "name2", ...] must be supplied
|
|
257 * in the options.
|
|
258 * @param array an array of arrays of values. [ ["name1", "name2" ...],? ["val1", "val2" ...] ...]
|
|
259 * @param options optional: { columns: ["name1", "name2", ...] }
|
|
260 * @returns An array of objects, [ { name1: val1, name2: val2 ... } ... ]
|
|
261 */
|
|
262 arraysToObjects: function arraysToObjects(array, options) {
|
|
263 var opts = tsvOptions(options);
|
|
264 if (! opts.columns) {
|
|
265 opts.columns = array.shift();
|
|
266 }
|
|
267 var rownum = opts.startRownum || 0;
|
|
268 return array.map(function convert(row) {
|
|
269 return $.tsv.arrayToObject(row, opts, rownum++);
|
|
270 });
|
|
271 },
|
|
272
|
|
273 /**
|
|
274 * $.tsv.toObjects(tsv, options) returns an array of objects from a tsv string.
|
|
275 * The string must either have the first row be column names, or columns: ["name1", "name2", ...] must be supplied
|
|
276 * in the options.
|
|
277 *
|
|
278 * @param A TSV string, e.g. "val1\tval2..." or "name1\tname2...\n\val1\val2..."
|
|
279 * @param options optional: { columns ["name1", "name2" ...] }
|
|
280 * @returns an array of objects, e.g. [ {name1: val1, name2: val2 ...} ...]
|
|
281 */
|
|
282 toObjects: function toObjects(tsv, options) {
|
|
283 var opts = tsvOptions(options);
|
|
284 return $.tsv.arraysToObjects($.tsv.toArrays(tsv, opts), opts);
|
|
285 },
|
|
286
|
|
287 /**
|
|
288 * $.tsv.objectToArray(obj, options) Convert one object to an array representation for storing as a TSV line.
|
|
289 *
|
|
290 * @param obj an object to convert to an array representations, e.g. { name1: "val1", name2: "val2" ... }
|
|
291 * @param options optional: { columns: ["name1", "name2"], objectToArray: <a function to use instead> }
|
|
292 * @param rownum optional: the row number
|
|
293 * @result an array, e.g. ["val1", "val2"]
|
|
294 */
|
|
295 objectToArray: function objectToArray(obj, options, rownum) {
|
|
296 var opts = tsvOptions(options);
|
|
297 var columns = tsvColumns(opts, obj);
|
|
298 rownum = rownum || 0;
|
|
299 if (opts.objectToArray) {
|
|
300 // We have an override; use that instead.
|
|
301 return opts.objectToArray(obj, opts, rownum);
|
|
302 }
|
|
303 var row = [];
|
|
304 for (var j = 0; j < columns.length; j++) {
|
|
305 row.push(obj[columns[j]]);
|
|
306 }
|
|
307 return row;
|
|
308 },
|
|
309
|
|
310 /**
|
|
311 * $.tsv.objectsToArrays(array, options) converts an array of objects into an array of row arrays.
|
|
312 *
|
|
313 * @param array An array of objects, e.g. [ { name1: "val1", name2: "val2", ...} ...]
|
|
314 * @param options { columns: ["name1", "name2"...], includeHeaders: true, objectToArray: <optional function to convert each object> }
|
|
315 */
|
|
316 objectsToArrays: function objectsToArrays(array, options) {
|
|
317 var opts = tsvOptions(options);
|
|
318 var rownum = options.startRownum;
|
|
319 var result = array.map(function convert(obj) {
|
|
320 return $.tsv.objectToArray(obj, opts, rownum++);
|
|
321 });
|
|
322 return result;
|
|
323 },
|
|
324
|
|
325 fromObject: function fromObject(array, options) {
|
|
326 var opts = tsvOptions(options);
|
|
327 return $.tsv.fromArray($.tsv.objectToArray(array, opts), opts);
|
|
328 },
|
|
329
|
|
330 /**
|
|
331 * $.tsv.fromObjects(array, options) converts an array of objects into a tsv string.
|
|
332 *
|
|
333 * @param array An array of objects, e.g. [ { name1: "val1", name2: "val2", ...} ...]
|
|
334 * @param options { columns: ["name1", "name2"...], includeHeaders: true, objectToArray: <optional function to convert each object> }
|
|
335 */
|
|
336 fromObjects: function fromObjects(array, options) {
|
|
337 var opts = tsvOptions(options);
|
|
338 var first = array.length ? array[0] : {};
|
|
339 // Calculate the columns while we still have the original objects. This is being called for side-effect!
|
|
340 tsvColumns(opts, first);
|
|
341 return $.tsv.fromArrays($.tsv.objectsToArrays(array, opts), opts);
|
|
342 },
|
|
343
|
|
344 extend: $.extend
|
|
345 };
|
|
346 // Compatibility with initial release.
|
|
347 $.tsv.parseRow = $.tsv.toArray;
|
|
348 $.tsv.parseRows = $.tsv.toArrays;
|
|
349 $.tsv.parseObject = $.tsv.toObject;
|
|
350 $.tsv.parseObjects = $.tsv.toObjects;
|
|
351 $.tsv.formatValue = $.tsv.formatValue;
|
|
352 $.tsv.formatRow = $.tsv.fromArray;
|
|
353 $.tsv.formatRows = $.tsv.fromArrays;
|
|
354 $.tsv.formatObject = $.tsv.fromObject;
|
|
355 $.tsv.formatObjects = $.tsv.fromObjects;
|
|
356
|
|
357 })(jQuery);
|