|
|
@ -1,38 +1,54 @@ |
|
|
|
/*! |
|
|
|
/*! |
|
|
|
Papa Parse |
|
|
|
Papa Parse |
|
|
|
v4.1.0 |
|
|
|
v4.1.1 |
|
|
|
https://github.com/mholt/PapaParse
|
|
|
|
https://github.com/mholt/PapaParse
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
(function(global) |
|
|
|
(function(global) |
|
|
|
{ |
|
|
|
{ |
|
|
|
"use strict"; |
|
|
|
"use strict"; |
|
|
|
|
|
|
|
|
|
|
|
var IS_WORKER = !global.document, LOADED_SYNC = false, AUTO_SCRIPT_PATH; |
|
|
|
var IS_WORKER = (!global.document && !!global.postMessage), LOADED_SYNC = false, AUTO_SCRIPT_PATH; |
|
|
|
var workers = {}, workerIdCounter = 0; |
|
|
|
var workers = {}, workerIdCounter = 0; |
|
|
|
|
|
|
|
|
|
|
|
global.Papa = {}; |
|
|
|
var Papa = {}; |
|
|
|
|
|
|
|
|
|
|
|
global.Papa.parse = CsvToJson; |
|
|
|
Papa.parse = CsvToJson; |
|
|
|
global.Papa.unparse = JsonToCsv; |
|
|
|
Papa.unparse = JsonToCsv; |
|
|
|
|
|
|
|
|
|
|
|
global.Papa.RECORD_SEP = String.fromCharCode(30); |
|
|
|
Papa.RECORD_SEP = String.fromCharCode(30); |
|
|
|
global.Papa.UNIT_SEP = String.fromCharCode(31); |
|
|
|
Papa.UNIT_SEP = String.fromCharCode(31); |
|
|
|
global.Papa.BYTE_ORDER_MARK = "\ufeff"; |
|
|
|
Papa.BYTE_ORDER_MARK = "\ufeff"; |
|
|
|
global.Papa.BAD_DELIMITERS = ["\r", "\n", "\"", global.Papa.BYTE_ORDER_MARK]; |
|
|
|
Papa.BAD_DELIMITERS = ["\r", "\n", "\"", Papa.BYTE_ORDER_MARK]; |
|
|
|
global.Papa.WORKERS_SUPPORTED = !!global.Worker; |
|
|
|
Papa.WORKERS_SUPPORTED = !!global.Worker; |
|
|
|
global.Papa.SCRIPT_PATH = null; // Must be set manually if using workers and Papa Parse is loaded asynchronously
|
|
|
|
Papa.SCRIPT_PATH = null; // Must be set by your code if you use workers and this lib is loaded asynchronously
|
|
|
|
|
|
|
|
|
|
|
|
// Configurable chunk sizes for local and remote files, respectively
|
|
|
|
// Configurable chunk sizes for local and remote files, respectively
|
|
|
|
global.Papa.LocalChunkSize = 1024 * 1024 * 10; // 10 MB
|
|
|
|
Papa.LocalChunkSize = 1024 * 1024 * 10; // 10 MB
|
|
|
|
global.Papa.RemoteChunkSize = 1024 * 1024 * 5; // 5 MB
|
|
|
|
Papa.RemoteChunkSize = 1024 * 1024 * 5; // 5 MB
|
|
|
|
global.Papa.DefaultDelimiter = ","; // Used if not specified and detection fails
|
|
|
|
Papa.DefaultDelimiter = ","; // Used if not specified and detection fails
|
|
|
|
|
|
|
|
|
|
|
|
// Exposed for testing and development only
|
|
|
|
// Exposed for testing and development only
|
|
|
|
global.Papa.Parser = Parser; |
|
|
|
Papa.Parser = Parser; |
|
|
|
global.Papa.ParserHandle = ParserHandle; |
|
|
|
Papa.ParserHandle = ParserHandle; |
|
|
|
global.Papa.NetworkStreamer = NetworkStreamer; |
|
|
|
Papa.NetworkStreamer = NetworkStreamer; |
|
|
|
global.Papa.FileStreamer = FileStreamer; |
|
|
|
Papa.FileStreamer = FileStreamer; |
|
|
|
global.Papa.StringStreamer = StringStreamer; |
|
|
|
Papa.StringStreamer = StringStreamer; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (typeof module !== 'undefined' && module.exports) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Export to Node...
|
|
|
|
|
|
|
|
module.exports = Papa; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else if (isFunction(global.define) && global.define.amd) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Wireup with RequireJS
|
|
|
|
|
|
|
|
global.define(function() { return Papa; }); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// ...or as browser global
|
|
|
|
|
|
|
|
global.Papa = Papa; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (global.jQuery) |
|
|
|
if (global.jQuery) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -253,7 +269,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
if (typeof _config.delimiter === 'string' |
|
|
|
if (typeof _config.delimiter === 'string' |
|
|
|
&& _config.delimiter.length == 1 |
|
|
|
&& _config.delimiter.length == 1 |
|
|
|
&& global.Papa.BAD_DELIMITERS.indexOf(_config.delimiter) == -1) |
|
|
|
&& Papa.BAD_DELIMITERS.indexOf(_config.delimiter) == -1) |
|
|
|
{ |
|
|
|
{ |
|
|
|
_delimiter = _config.delimiter; |
|
|
|
_delimiter = _config.delimiter; |
|
|
|
} |
|
|
|
} |
|
|
@ -334,7 +350,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
var needsQuotes = (typeof _quotes === 'boolean' && _quotes) |
|
|
|
var needsQuotes = (typeof _quotes === 'boolean' && _quotes) |
|
|
|
|| (_quotes instanceof Array && _quotes[col]) |
|
|
|
|| (_quotes instanceof Array && _quotes[col]) |
|
|
|
|| hasAny(str, global.Papa.BAD_DELIMITERS) |
|
|
|
|| hasAny(str, Papa.BAD_DELIMITERS) |
|
|
|
|| str.indexOf(_delimiter) > -1 |
|
|
|
|| str.indexOf(_delimiter) > -1 |
|
|
|
|| str.charAt(0) == ' ' |
|
|
|
|| str.charAt(0) == ' ' |
|
|
|
|| str.charAt(str.length - 1) == ' '; |
|
|
|
|| str.charAt(str.length - 1) == ' '; |
|
|
@ -363,6 +379,11 @@ |
|
|
|
this._rowCount = 0; |
|
|
|
this._rowCount = 0; |
|
|
|
this._start = 0; |
|
|
|
this._start = 0; |
|
|
|
this._nextChunk = null; |
|
|
|
this._nextChunk = null; |
|
|
|
|
|
|
|
this._completeResults = { |
|
|
|
|
|
|
|
data: [], |
|
|
|
|
|
|
|
errors: [], |
|
|
|
|
|
|
|
meta: {} |
|
|
|
|
|
|
|
}; |
|
|
|
replaceConfig.call(this, config); |
|
|
|
replaceConfig.call(this, config); |
|
|
|
|
|
|
|
|
|
|
|
this.parseChunk = function(chunk) |
|
|
|
this.parseChunk = function(chunk) |
|
|
@ -373,7 +394,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
var results = this._handle.parse(aggregate, this._baseIndex, !this._finished); |
|
|
|
var results = this._handle.parse(aggregate, this._baseIndex, !this._finished); |
|
|
|
|
|
|
|
|
|
|
|
if (this._handle.paused()) |
|
|
|
if (this._handle.paused() || this._handle.aborted()) |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
var lastIndex = results.meta.cursor; |
|
|
|
var lastIndex = results.meta.cursor; |
|
|
@ -403,10 +424,17 @@ |
|
|
|
if (this._paused) |
|
|
|
if (this._paused) |
|
|
|
return; |
|
|
|
return; |
|
|
|
results = undefined; |
|
|
|
results = undefined; |
|
|
|
|
|
|
|
this._completeResults = undefined; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!this._config.step && !this._config.chunk) { |
|
|
|
|
|
|
|
this._completeResults.data = this._completeResults.data.concat(results.data); |
|
|
|
|
|
|
|
this._completeResults.errors = this._completeResults.errors.concat(results.errors); |
|
|
|
|
|
|
|
this._completeResults.meta = results.meta; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (finishedIncludingPreview && isFunction(this._config.complete) && (!results || !results.meta.aborted)) |
|
|
|
if (finishedIncludingPreview && isFunction(this._config.complete) && (!results || !results.meta.aborted)) |
|
|
|
this._config.complete(results); |
|
|
|
this._config.complete(this._completeResults); |
|
|
|
|
|
|
|
|
|
|
|
if (!finishedIncludingPreview && (!results || !results.meta.paused)) |
|
|
|
if (!finishedIncludingPreview && (!results || !results.meta.paused)) |
|
|
|
this._nextChunk(); |
|
|
|
this._nextChunk(); |
|
|
@ -489,7 +517,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
xhr.open("GET", this._input, !IS_WORKER); |
|
|
|
xhr.open("GET", this._input, !IS_WORKER); |
|
|
|
|
|
|
|
|
|
|
|
if (this._config.step || this._config.chunk) |
|
|
|
if (this._config.chunkSize) |
|
|
|
{ |
|
|
|
{ |
|
|
|
var end = this._start + this._config.chunkSize - 1; // minus one because byte range is inclusive
|
|
|
|
var end = this._start + this._config.chunkSize - 1; // minus one because byte range is inclusive
|
|
|
|
xhr.setRequestHeader("Range", "bytes="+this._start+"-"+end); |
|
|
|
xhr.setRequestHeader("Range", "bytes="+this._start+"-"+end); |
|
|
@ -520,7 +548,7 @@ |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this._finished = (!this._config.step && !this._config.chunk) || this._start > getFileSize(xhr); |
|
|
|
this._finished = !this._config.chunkSize || this._start > getFileSize(xhr); |
|
|
|
this.parseChunk(xhr.responseText); |
|
|
|
this.parseChunk(xhr.responseText); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -577,9 +605,14 @@ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this._readChunk = function() |
|
|
|
this._readChunk = function() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var input = this._input; |
|
|
|
|
|
|
|
if (this._config.chunkSize) |
|
|
|
{ |
|
|
|
{ |
|
|
|
var end = Math.min(this._start + this._config.chunkSize, this._input.size); |
|
|
|
var end = Math.min(this._start + this._config.chunkSize, this._input.size); |
|
|
|
var txt = reader.readAsText(slice.call(this._input, this._start, end), this._config.encoding); |
|
|
|
input = slice.call(input, this._start, end); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
var txt = reader.readAsText(input, this._config.encoding); |
|
|
|
if (!usingAsyncReader) |
|
|
|
if (!usingAsyncReader) |
|
|
|
this._chunkLoaded({ target: { result: txt } }); // mimic the async signature
|
|
|
|
this._chunkLoaded({ target: { result: txt } }); // mimic the async signature
|
|
|
|
} |
|
|
|
} |
|
|
@ -588,7 +621,7 @@ |
|
|
|
{ |
|
|
|
{ |
|
|
|
// Very important to increment start each time before handling results
|
|
|
|
// Very important to increment start each time before handling results
|
|
|
|
this._start += this._config.chunkSize; |
|
|
|
this._start += this._config.chunkSize; |
|
|
|
this._finished = this._start >= this._input.size; |
|
|
|
this._finished = !this._config.chunkSize || this._start >= this._input.size; |
|
|
|
this.parseChunk(event.target.result); |
|
|
|
this.parseChunk(event.target.result); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -641,6 +674,7 @@ |
|
|
|
var _input; // The input being parsed
|
|
|
|
var _input; // The input being parsed
|
|
|
|
var _parser; // The core parser being used
|
|
|
|
var _parser; // The core parser being used
|
|
|
|
var _paused = false; // Whether we are paused or not
|
|
|
|
var _paused = false; // Whether we are paused or not
|
|
|
|
|
|
|
|
var _aborted = false; // Whether the parser has aborted or not
|
|
|
|
var _delimiterError; // Temporary state between delimiter detection and processing results
|
|
|
|
var _delimiterError; // Temporary state between delimiter detection and processing results
|
|
|
|
var _fields = []; // Fields are from the header row of the input, if there is one
|
|
|
|
var _fields = []; // Fields are from the header row of the input, if there is one
|
|
|
|
var _results = { // The last results returned from the parser
|
|
|
|
var _results = { // The last results returned from the parser
|
|
|
@ -726,9 +760,15 @@ |
|
|
|
self.streamer.parseChunk(_input); |
|
|
|
self.streamer.parseChunk(_input); |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.aborted = function () { |
|
|
|
|
|
|
|
return _aborted; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this.abort = function() |
|
|
|
this.abort = function() |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
_aborted = true; |
|
|
|
_parser.abort(); |
|
|
|
_parser.abort(); |
|
|
|
|
|
|
|
_results.meta.aborted = true; |
|
|
|
if (isFunction(_config.complete)) |
|
|
|
if (isFunction(_config.complete)) |
|
|
|
_config.complete(_results); |
|
|
|
_config.complete(_results); |
|
|
|
_input = ""; |
|
|
|
_input = ""; |
|
|
@ -784,9 +824,9 @@ |
|
|
|
if (_config.dynamicTyping) |
|
|
|
if (_config.dynamicTyping) |
|
|
|
{ |
|
|
|
{ |
|
|
|
var value = _results.data[i][j]; |
|
|
|
var value = _results.data[i][j]; |
|
|
|
if (value == "true") |
|
|
|
if (value == "true" || value == "TRUE") |
|
|
|
_results.data[i][j] = true; |
|
|
|
_results.data[i][j] = true; |
|
|
|
else if (value == "false") |
|
|
|
else if (value == "false" || value == "FALSE") |
|
|
|
_results.data[i][j] = false; |
|
|
|
_results.data[i][j] = false; |
|
|
|
else |
|
|
|
else |
|
|
|
_results.data[i][j] = tryParseFloat(value); |
|
|
|
_results.data[i][j] = tryParseFloat(value); |
|
|
@ -925,7 +965,6 @@ |
|
|
|
|
|
|
|
|
|
|
|
// Delimiter must be valid
|
|
|
|
// Delimiter must be valid
|
|
|
|
if (typeof delim !== 'string' |
|
|
|
if (typeof delim !== 'string' |
|
|
|
|| delim.length != 1 |
|
|
|
|
|
|
|
|| Papa.BAD_DELIMITERS.indexOf(delim) > -1) |
|
|
|
|| Papa.BAD_DELIMITERS.indexOf(delim) > -1) |
|
|
|
delim = ","; |
|
|
|
delim = ","; |
|
|
|
|
|
|
|
|
|
|
@ -1324,13 +1363,11 @@ |
|
|
|
|
|
|
|
|
|
|
|
function bindFunction(f, self) |
|
|
|
function bindFunction(f, self) |
|
|
|
{ |
|
|
|
{ |
|
|
|
return function() { |
|
|
|
return function() { f.apply(self, arguments); }; |
|
|
|
f.apply(self, arguments); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function isFunction(func) |
|
|
|
function isFunction(func) |
|
|
|
{ |
|
|
|
{ |
|
|
|
return typeof func === 'function'; |
|
|
|
return typeof func === 'function'; |
|
|
|
} |
|
|
|
} |
|
|
|
})(this); |
|
|
|
})(typeof window !== 'undefined' ? window : this); |
|
|
|