/** A class representing a CSV file reader. */
Lore.CsvFileReader = class CsvFileReader extends Lore.FileReaderBase {
/**
* Creates an instance of CsvFileReader.
* @param {String} source The source of the file. This is either a input element (type=file) or a URL. If it is a URL, set local to true.
* @param {any} options Options. See documentation for details.
* @param {boolean} [local=true] A boolean indicating whether or not the source is local (a file input) or remote (a url).
*/
constructor(source, options, local = true) {
super(source, local);
this.defaults = {
separator: ',',
cols: [],
types: [],
header: true
}
this.opts = Lore.Utils.extend(true, this.defaults, options);
this.columns = {};
this.headers = [];
this.types = this.opts.types;
this.cols = this.opts.cols;
}
/**
* Called when the data is loaded, will raise the "loaded" event.
*
* @param {any} data The data loaded from the file or url.
* @returns {Lore.CsvFileReader} Itself.
*/
loaded(data) {
data = data.replace('\n\n', '\n');
data = data.replace(/^\s+|\s+$/g, '');
let lines = data.split('\n');
let length = lines.length;
let init = true;
let h = this.opts.header ? 1 : 0;
if (this.cols.length !== 0) {
if (this.types.length !== this.cols.length) {
throw 'Types and cols must have the same number of elements.'
}
} else {
if (this.types.length !== this.cols.length || this.types.length + this.cols.length === 0) {
let values = lines[h].split(this.opts.separator);
this.types = [];
for (let i = 0; i < values.length; i++) {
if(Lore.Utils.isFloat(parseFloat(values[i], 10))) {
this.types.push('Float32Array');
} else if (Lore.Utils.isInt(parseFloat(values[i], 10))) {
this.types.push('Int32Array');
} else {
this.types.push('StringArray');
}
}
}
}
if (this.cols.length === 0) {
let values = lines[0].split(this.opts.separator);
for (let i = 0; i < values.length; i++) {
this.cols.push(i);
}
}
if (h) {
let headerNames = lines[0].split(this.opts.separator);
for (let i = 0; i < this.cols.length; i++) {
this.headers[i] = headerNames[this.cols[i]].trim();
}
} else {
for (let i = 0; i < this.cols.length; i++) {
this.headers[i] = i;
}
}
for (let i = h; i < length; i++) {
let values = lines[i].split(this.opts.separator);
if (this.cols.length == 0)
for (let j = 0; j < values.length; j++) {
this.cols.push[j];
}
if (init) {
for (let j = 0; j < this.cols.length; j++) {
this._createArray(this.headers[j], this.types[j], length - h);
}
init = false;
}
for (let j = 0; j < this.cols.length; j++) {
this.columns[this.headers[j]][i - h] = values[this.cols[j]];
}
}
this.raiseEvent('loaded', this.columns);
return this;
}
_createArray(index, type, length) {
if (type == 'Int8Array') {
this.columns[index] = new Int8Array(length);
} else if (type == 'Uint8Array') {
this.columns[index] = new Uint8Array(length);
} else if (type == 'Uint8ClampedArray') {
this.columns[index] = new Uint8ClampedArray(length);
} else if (type == 'Int16Array') {
this.columns[index] = new Int16Array(length);
} else if (type == 'Uint16Array') {
this.columns[index] = new Uint16Array(length);
} else if (type == 'Int32Array') {
this.columns[index] = new Int32Array(length);
} else if (type == 'Uint32Array') {
this.columns[index] = new Uint32Array(length);
} else if (type == 'Float32Array') {
this.columns[index] = new Float32Array(length);
} else if (type == 'Float64Array') {
this.columns[index] = new Float64Array(length);
} else {
this.columns[index] = new Array(length);
}
return this;
}
}