Crimpy
Crimpy

Reputation: 195

source of a line return character in csv file exported with jquery?

I've been working on an app that uploads a csv file, does some math on it, then allows a user to download it. Everything works great, but there's an annoying bug I'm trying to work out.

The file uploads to an html table and a new column of checkboxes are added to the end. Don't be concerned with that now. (I'll probably have questions about this later.) You can upload any csv file (just text with commas, no quotes) and then click the export csv file link. The new file you have, when looked at in some text editors, has a line break character in it that doesn't belong. It happens on the second row on the final td.

here's a fiddle I made that demos the action.

it looks like this when I look at the code in the console:

<tr>
<td>Text1</td>
<td>text2</td>
<td>text3>
</td>

but all of the other tds are working fine. Anyone have any ideas on this?

Thanks!

Upvotes: 0

Views: 713

Answers (1)

Tomalak
Tomalak

Reputation: 338228

Since you are in desperate need of an HTML templating solution (at the very least), I'll give you a nudge into the right direction.

The following depends on gkindel/CSV-JS for CSV parsing and Handlebars for HTML creation:

$(function () {
    var csvTemplateSrc = $('#csvTemplate').html(),
        csvTemplate = Handlebars.compile(csvTemplateSrc);

    $("#upload").click(function () {
        var filename = $("#fileUpload").val().toLowerCase(),
            reader;

        if (typeof (FileReader) === "undefined") {
            alert("This browser does not support HTML5.");
            return;
        }

        if (!/^[a-zA-Z0-9\s_\\.:-]+\.(csv|txt)$/.test(filename)) {
            alert("Please upload a valid CSV file.");
            return;
        }
        
        reader = new FileReader();
        reader.onload = function (e) {
            var rows;
            try {
                rows = CSV.parse(e.target.result);
            } catch (ex) {
                alert("Your CSV is has errors.\n\n" + ex.message);
                return;
            }
            $("#dvCSV").html(csvTemplate(rows));
        };
        reader.readAsText($("#fileUpload")[0].files[0]);
    });
    
    $(".export").click(function (event) {
        exportTableToCSV($('#dvCSV>table'), 'export.csv');
        $('a.export').css({"background-color": "#ddd"});
    });
});

Handlebars.registerHelper('first', function(context, options) {
    return options.fn(context[0]);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/gkindel/CSV-JS/master/csv.js"></script>
<script src="https://cdn.jsdelivr.net/handlebarsjs/3.0.0/handlebars.min.js"></script>

<input type="file" id="fileUpload" />
<input type="button" id="upload" value="Upload" />
<a href="#" class="export">Export Data to CSV</a>
<div id="dvCSV"></div>

<script id="csvTemplate" type="text/x-handlebars-template">
<table width="100%" class="sortable">
    {{#first .}}
    <tr width="100%">
        {{#each .}}
        <td>
            <select id="Value_{{@index}}">
                <option value="None">N/A</option>
                <option value="name">Name</option>
                <option value="Lat">Lat</option>
                <option value="Lon">Long</option>
            </select>
        </td>
        {{/each}}
        <td></td>
    </tr>
    {{/first}}
    {{#each .}}
    <tr>
        {{#each .}}
        <td>{{.}}</td>
        {{/each}}
        <td><input type="checkbox" checked></td>
    </tr>
    {{/each}}
</table>
</script>

Notes

  • I think you can drop the filename check. If the CSV parser succeeds in parsing the file content that's proof enough that the file is OK.
  • Note the use of {{@index}} to create uniqe HTML IDs. Your code created duplicate IDs, which defies the point of having IDs in the first place (and it's not allowed in HTML)
  • You should think about switching to an MVVM framework for the whole application. Frameworks like knockout handle all HTML templating and DOM manipulation (you could drop Handlebars and almost all of your jQuery) and you would not need any "convert HTML to CSV" functionality anymore, either. Give it a look.

Upvotes: 3

Related Questions