| **`delimiter`** | `","` | The delimiting character. Must be a string with length 1. Can be any character except `\n` and `"`.
| **`header`** | `true` | If true, interpret the first row of parsed data as column titles; fields are returned separately from the data, and data will be returned keyed to its field name. Duplicate field names would be problematic. If false, the parser simply returns an array (list) of arrays (rows), including the first row.
| **`dynamicTyping`** | `true` | If true, fields that are only numeric will be converted to a number type. If false, each parsed datum is returned as a string.
### Parsing strings
To parse a delimited text string with default settings, simply do:
In order to be parsed, a file must have "text" in its MIME type.
#### Callbacks
As indicated above, there are callbacks you can use when parsing files.
##### `before(file, inputElem)`
If the next file in the queue is found to be some sort of "text" MIME type, this callback will be executed immediately before setting up the FileReader, loading the file, and parsing it. It receives the file object and the `<input>` element so you can inspect the file to be parsed.
You can change what happens next depending on what you return:
- Return `"skip"` to skip parsing this file.
- Return `false` to abort parsing this and all other files in the queue.
- Return a config object to alter the options for parsing this file only.
Returning anything else, including `undefined`, continues without any changes.
##### `error(err, file, inputElem)`
Invoked if there is an error loading the file. It receives an object that implements the [`DOMError`](https://developer.mozilla.org/en-US/docs/Web/API/DOMError) interface (i.e. call `err.name` to get the error), the file object at hand, and the `<input>` element from which the file was selected.
Errors can occur before reading the file if:
- the HTML element has no files chosen
- a file chosen is not a "text" type (e.g. "text/csv" or "text/plain")
- a user-defined callback function (`before`) aborted the process
Otherwise, errors are invoked by FileReader when opening the file. *Parse errors are not reported here, but are reported in the results later on.*
##### `complete(results, file, inputElem, event)`
Invoked when parsing a file completes. It receives the results of the parse (including errors), the file object, the `<input>` element from which the file was chosen, and the FileReader-generated event.
Output
------
Whether you're parsing strings or files, the results returned by the parser are the same since, under the hood, the FileReader loads a file as a string.
The results will always have this basic structure:
### Results if `header: true` and `dynamicTyping: true`
With a header row, each value is keyed to its field name, so the result is an object with `fields` and `rows`. The fields are an array of strings, and the rows are an array of objects:
Notice how the numeric values were converted to numbers. That is what `dynamicTyping` does.
With a header row, the field count must be the same on each row, or a FieldMismatch error will be produced for that row. (Without a header row, lines can have variable number of fields without errors.)
### Results if `header: false` and `dynamicTyping: false`
Without a header row, the result is an array (list) of arrays (rows).
If the header row is disabled, field counting does not occur because there is no need to key the data to the field name. Thus we only get a Quotes error:
Since files with headers are supposed to have the same number of fields per row, any extra fields are parsed into a special array field named "__parsed_extra" in the order that the remaining line was parsed.
Tests
-----
The Parser component is under test. Download this repository and open `tests.html` in your browser to run them.
Inside this jQuery plugin is a `Parser` function that actually performs the parsing of delimited text. It does not depend upon jQuery. This plugin uses jQuery to attach to `<input type="file">` elements and to make it more convenient to activate the parsing mechanism.
Please feel free to chip in! If you'd like to see a feature or fix, pull down the code and submit a pull request. But remember, if you're changing anything in the Parser function, a pull request, *with test*, is best. (All changes to the parser component should be validated with tests.)