My client wants a website that includes importing CSV data WITHOUT it being hosted on a server. The idea is so that their sales people can demonstrate their products without having web access or hosting set up on their PCs. They will also be able to update the data by exporting a new CSV file from the original Excel document, without any knowledge of HTML or Javascript.
I've found quite a few solutions online - like Papa Parse (http://papaparse.com/) but all of them require the user to select a file using <input type="file" />
. As an example, the following script, using Papa Parse, works perfectly well:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Test CSV</title>
</head>
<body>
<input type="file" />
</body>
<script src="js/jquery-1.10.1.min.js"></script>
<script src="js/jquery.parse.min.js"></script>
<script language="javascript">
$('input').change(function(e) {
$('input[type=file]').parse({
complete: function(data) {
console.log('Parse results:', data.results);
}
});
});
</script>
</html>
My problem is that I need to be able to hard-code the CSV file's location so that, when the web page is opened, the data is automatically displayed, without any further interaction by the user. Is this possible? Or have I overlooked something really basic?
Hardcode the values inside a script tag of a non-javascript type
such as text/csv
then extract it with innerHTML or $("#unparsed").html()
<script type="text/csv" id="unparsed">
url,title,size
images/address-book.png?1354486198, Address Book, 1904 KB
images/front-row.png?1354486198, Front Row, 401 KB
images/google-pokemon.png?1354486198, Google Pokémon, 12875 KB
...
</script>
$(function parseData(){
$("#file").hide();
var data = $("#unparsed").html();
var parsed = $.parse(data);
$("#parsed").val(JSON.stringify(parsed));
})
http://jsbin.com/racanefi/10/edit
Hardcode the values inside a textarea.
$(function parseData(){
$("#file").hide();
var data = $("#unparsed").val();
var parsed = $.parse(data);
$("#parsed").val(JSON.stringify(parsed));
})
http://jsbin.com/racanefi/8/edit
OR
Store the value in localStorage.
var storage = localStorage;
var key = 'unparsed_text_file';
function getFile(){
$("#file").change(function(){
var file = $(this).eq(0)[0].files[0],
reader = new FileReader();
reader.onload = function(e) {
var text = reader.result;
storage.setItem(key,text);
parseData();
};
reader.readAsText(file);
});
}
function parseData(){
$("#file").hide();
var data = storage.getItem(key);
var parsed = $.parse(data);
$("#unparsed").val(data);
$("#parsed").val(JSON.stringify(parsed));
}
if(storage.getItem(key))
parseData();
else
getFile();
http://jsbin.com/racanefi/6/edit
Browser Compatibility:
http://caniuse.com/namevalue-storage
This is a rough draft, you should probably QA it well before implementing it.
edit: I had it backwards sessionStorage is temporary across sessions. localStorage is more permanent. I created a variable that lets you assign your storage to a var storage
PapaParse is good quality stuff but for completion sake here's how it's done with jquery-csv
<html>
<head>
<meta charset="utf-8" />
<title>Demo - CSV-to-Table</title>
</head>
<body>
<div id="inputs" class="clearfix">
<input type="file" id="files" name="files[]" multiple />
</div>
<hr />
<output id="list">
</output>
<hr />
<table id="contents" style="width:100%; height:400px;" border>
</table>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="http://evanplaice.github.io/jquery-csv/src/jquery.csv.js"></script>
<script>
$(document).ready(function() {
if(isAPIAvailable()) {
$('#files').bind('change', handleFileSelect);
}
});
function isAPIAvailable() {
// Check for the various File API support.
if (window.File && window.FileReader && window.FileList && window.Blob) {
// Great success! All the File APIs are supported.
return true;
} else {
// source: File API availability - http://caniuse.com/#feat=fileapi
// source: <output> availability - http://html5doctor.com/the-output-element/
document.writeln('The HTML5 APIs used in this form are only available in the following browsers:<br />');
// 6.0 File API & 13.0 <output>
document.writeln(' - Google Chrome: 13.0 or later<br />');
// 3.6 File API & 6.0 <output>
document.writeln(' - Mozilla Firefox: 6.0 or later<br />');
// 10.0 File API & 10.0 <output>
document.writeln(' - Internet Explorer: Not supported (partial support expected in 10.0)<br />');
// ? File API & 5.1 <output>
document.writeln(' - Safari: Not supported<br />');
// ? File API & 9.2 <output>
document.writeln(' - Opera: Not supported');
return false;
}
}
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
var file = files[0];
// read the file metadata
var output = ''
output += '<span style="font-weight:bold;">' + escape(file.name) + '</span><br />\n';
output += ' - FileType: ' + (file.type || 'n/a') + '<br />\n';
output += ' - FileSize: ' + file.size + ' bytes<br />\n';
output += ' - LastModified: ' + (file.lastModifiedDate ? file.lastModifiedDate.toLocaleDateString() : 'n/a') + '<br />\n';
// read the file contents
printTable(file);
// post the results
$('#list').append(output);
}
function printTable(file) {
var reader = new FileReader();
reader.readAsText(file);
reader.onload = function(event){
var csv = event.target.result;
var data = $.csv.toArrays(csv);
var html = '';
for(var row in data) {
html += '<tr>\r\n';
for(var item in data[row]) {
html += '<td>' + data[row][item] + '</td>\r\n';
}
html += '</tr>\r\n';
}
$('#contents').html(html);
};
reader.onerror = function(){ alert('Unable to read ' + file.fileName); };
}
</script>
</body>
</html>
Feature detection (ie which browsers won't work) is built-in, and the file has to be loaded via a file dialog because the sandbox protections block scripts from accessing the filesystem directly.
Disclaimer: I'm the author of jquery-csv.