Javascript loading CSV file into an array - javascript

I am developing a web page in Wordpress. The webpage needs to have a combobox with all counties. I have a dataset in csv format which has some 10k rows for all these counties.
When the user selects a county in the dropdown, I want only the selected county data displayed in the web page. This is my requirement.
In wordpress, my web page I am adding the js file using
<script type="text/javascript" src="http://xxx/wp content/uploads/2014/05/countyList1.js"></script>
and the code for webpage dropdown is
<select name="county" id="county" onload="setCounties();" onchange="getSelectedCountyData();"></select>
In countyList1.js file I have the setCounties() and getSelectedCountyData() functions.
So far I can see the dropdown with counties list. I don't know how to read the CSV file and apply the selected county filter to this list.
I tried the FileReader object and I can load the CSV contents on the web page but I don't want the user to select the CSV. I have the dataset already.
I am trying to use this jquery.csv-0.71 library from this SO post How to read data From *.CSV file using javascript? but I need help.
Here's the code which gets called when a county is selected
function getSelectedCountyData() {
cntrySel = document.getElementById('county');
//selCty = countyList[cntrySel.value];
handleFiles();
}
function handleFiles() {
$(document).ready(function () {
$.ajax({
type: "GET",
url: "D:\Docs\Desktop\csvfile.csv",
dataType: "csv",
success: function (data) { processData(data); }
});
});
}
function processData(allText) {
var allTextLines = allText.split(/\r\n|\n/);
var headers = allTextLines[0].split(',');
var lines = [];
for (var i = 1; i < allTextLines.length; i++) {
var data = allTextLines[i].split(',');
if (data.length == headers.length) {
var tarr = [];
for (var j = 0; j < headers.length; j++) {
tarr.push(headers[j] + ":" + data[j]);
}
lines.push(tarr);
}
}
console.log(lines);
drawOutput(lines);
}
function drawOutput(lines) {
//Clear previous data
document.getElementById("output").innerHTML = "";
var table = document.createElement("table");
for (var i = 0; i < lines.length; i++) {
var row = table.insertRow(-1);
for (var j = 0; j < lines[i].length; j++) {
var firstNameCell = row.insertCell(-1);
firstNameCell.appendChild(document.createTextNode(lines[i][j]));
}
}
document.getElementById("output").appendChild(table);
}

I highly recommend looking into this plugin:
http://github.com/evanplaice/jquery-csv/
I used this for a project handling large CSV files and it handles parsing a CSV into an array quite well. You can use this to call a local file that you specify in your code, also, so you are not dependent on a file upload.
Once you include the plugin above, you can essentially parse the CSV using the following:
$.ajax({
url: "pathto/filename.csv",
async: false,
success: function (csvd) {
data = $.csv.toArrays(csvd);
},
dataType: "text",
complete: function () {
// call a function on complete
}
});
Everything will then live in the array data for you to manipulate as you need. I can provide further examples for handling the array data if you need.
There are a lot of great examples available on the plugin page to do a variety of things, too.

You can't use AJAX to fetch files from the user machine. This is absolutely the wrong way to go about it.
Use the FileReader API:
<input type="file" id="file input">
js:
console.log(document.getElementById("file input").files); // list of File objects
var file = document.getElementById("file input").files[0];
var reader = new FileReader();
content = reader.readAsText(file);
console.log(content);
Then parse content as CSV. Keep in mind that your parser currently does not deal with escaped values in CSV like: value1,value2,"value 3","value ""4"""

If your not overly worried about the size of the file then it may be easier for you to store the data as a JS object in another file and import it in your . Either synchronously or asynchronously using the syntax <script src="countries.js" async></script>. Saves on you needing to import the file and parse it.
However, i can see why you wouldnt want to rewrite 10000 entries so here's a basic object orientated csv parser i wrote.
function requestCSV(f,c){return new CSVAJAX(f,c);};
function CSVAJAX(filepath,callback)
{
this.request = new XMLHttpRequest();
this.request.timeout = 10000;
this.request.open("GET", filepath, true);
this.request.parent = this;
this.callback = callback;
this.request.onload = function()
{
var d = this.response.split('\n'); /*1st separator*/
var i = d.length;
while(i--)
{
if(d[i] !== "")
d[i] = d[i].split(','); /*2nd separator*/
else
d.splice(i,1);
}
this.parent.response = d;
if(typeof this.parent.callback !== "undefined")
this.parent.callback(d);
};
this.request.send();
};
Which can be used like this;
var foo = requestCSV("csvfile.csv",drawlines(lines));
The first parameter is the file, relative to the position of your html file in this case.
The second parameter is an optional callback function the runs when the file has been completely loaded.
If your file has non-separating commmas then it wont get on with this, as it just creates 2d arrays by chopping at returns and commas. You might want to look into regexp if you need that functionality.
//THIS works
"1234","ABCD" \n
"!#£$" \n
//Gives you
[
[
1234,
'ABCD'
],
[
'!#£$'
]
]
//This DOESN'T!
"12,34","AB,CD" \n
"!#,£$" \n
//Gives you
[
[
'"12',
'34"',
'"AB',
'CD'
]
[
'"!#',
'£$'
]
]
If your not used to the OO methods; they create a new object (like a number, string, array) with their own local functions and variables via a 'constructor' function. Very handy in certain situations. This function could be used to load 10 different files with different callbacks all at the same time(depending on your level of csv love! )

This is what I used to use a csv file into an array. Couldn't get the above answers to work, but this worked for me.
$(document).ready(function() {
"use strict";
$.ajax({
type: "GET",
url: "../files/icd10List.csv",
dataType: "text",
success: function(data) {processData(data);}
});
});
function processData(icd10Codes) {
"use strict";
var input = $.csv.toArrays(icd10Codes);
$("#test").append(input);
}
Used the jQuery-CSV Plug-in linked above.

The original code works fine for reading and separating the csv file data but you need to change the data type from csv to text.

Related

replace getJSON jquery function with pure js using local variable

I have a getJSON jquery function that uses data from an external file eg
$.getJSON( "data/dataset.json", function( data ) {
var mygeojson = {
type: "FeatureCollection",
features: [],
};
var waypoints = []
var all_points=[]
for (i = 0; i < data.length; i++) {
var lng = data[i].lng;
.....
I now have a local variable that contains the same data as the external data file.
eg
const dataset = [{..}, {..},......]
The data is in the exact same format.
How can I use a pure js function that references the dataset variable rather than the jquery getjson function?
Lets say you have a file with the following code as the data,
datasetFile.js
export const dataset = [{..}, {..},......];
and you have another file where you want to use this data
useDataset.js
import { dataset } from './datasetFile.js
console.log(dataset);
You should be good to go.

How to Read a CSV file into a 2D array in JavaScript?

I have a huge .csv file. It has about 130,000 rows and 13 columns. I need to create a bunch of graphs using that data in a web app. I am very new to JavaScript. Can anyone help me reading this huge file and store the data into a 2D array?
I think you can use this lib
http://c2fo.io/fast-csv
or
https://www.papaparse.com/
this libs use streams, and you can use huge file and modify each line
If you are working on a node app, try looking for packages on npm,
https://www.npmjs.com/search?q=csv
Else, you might want to take a look at the following link for core javascript code:
How to read data From *.CSV file using javascript?
This code will help you:
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
// Reading csv data from file using get ou post or whateven protocol
$(document).ready(function() {
$.ajax({
type: "GET",
url: "data.txt",
dataType: "text",
success: function(data) {
var lines = processData(data);
console.log(lines);
}
});
});
// Passing csv data direct from text string
csv = "heading1,heading2,heading3,heading4,heading5\nvalue1_1,value2_1,value3_1,value4_1,value5_1\nvalue1_2,value2_2,value3_2,value4_2,value5_2";
var lines = processData(data);
console.log(lines);
function processData(allText) {
var allTextLines = allText.split(/\r\n|\n/);
var headers = allTextLines[0].split(',');
var lines = [];
for (var i=1; i<allTextLines.length; i++) {
var data = allTextLines[i].split(',');
if (data.length == headers.length) {
var tarr = [];
for (var j=0; j<headers.length; j++) {
tarr.push(data[j]);
}
lines.push(tarr);
}
}
return lines;
}
</head>

PHP POST: Setting data variables dynamically from an array

Hi all I'm pretty new to PHP and AJAX and all that good stuff and I'm a little stumped on how to proceed from here in my code.
I have a form that is getting sent and I have an array (subcategories) which contains the form labels to retrieve the values of the fields. The fields and values are getting created dynamically based on a textfile that the user uploads so I don't have any way of knowing what they are.
var arrayLength = subcategories.length;
for (var i = 0; i < arrayLength; i++) {
var eachfield = subcategories[i];
//Do something
//#C: selector is working fine, cleaning input
var eachfield = $('#' + eachfield).val().trim();
//push the appropriate values with the fixed stuff to a new array
values.push(eachfield);
}
What I'm trying to do is now to set these variables to some name and send them through $data using AJAX and POST.
Something like the following if I was setting everything statically.
var data = {
dimitypedata: dimitype,
densitydata: density,
velocitydata: velocity,
temperaturedata: temperature,
submitbtnclicked: "submitted"
};
//using the data and sending it through a post with promise handling
$.ajax({
type: 'POST',
url: "controller.php",
data: data,
success: function(response) {
//alert("worked");
//console.log(response);
alert(response);
},
error: function() {
alert("There was an error submitting the information");
}
});
I'm not quite sure how to mix these two and it may be partially because of getting a confused and not yet being that great with POST and AJAX calls.
EDIT: It looks like my question was a bit unclear (sorry first post lol) I'm trying to dynamically push values that I take out of an HTML form field. The problem is that the form is generated depending on what the user chooses to upload to the site (so both the fields and the forms. My ultimate goal is to enable the user to edit the dynamically generated form based on a text file that they upload and be able to generate a new text file after editing it on the GUI after clicking on the submit button. I can do this if its static but I'm having trouble figuring out how to do the same if I don't know what the form will contain.
I'm trying to to my data object so I can use it in my AJAX call. Here's a little bit of the PHP code that I would use in the next step if the variables were static:
if(isset($_POST['submitbtnclicked']) && $_POST['submitbtnclicked'] == 'submitted') {
//new instance of model for use
$model = new model();
$dimitypedata = $_POST['dimitypedata'];
$densitydata = $_POST['densitydata'];
$velocitydata = $_POST['velocitydata'];
$temperaturedata = $_POST['temperaturedata'];
For an exact answer, we need to see what the "subcategories" array look like.
If I understood correctly, you would like to put the values in an object instead of an array (values). So the first part would look like:
var data = {};
var arrayLength = subcategories.length;
for (var i = 0; i < arrayLength; i++) {
//notice that now field name and field value go in separate variables
var fieldName = subcategories[i];
//#C: selector is working fine, cleaning input
var fieldValue = $('#'+eachfield).val().trim();
//push the appropriate values with the fixed stuff to a data object
data[fieldName] = fieldValue;
}
//and then you send your gathered data
//using the data and sending it through a post with promise handling
$.ajax({
type: 'POST',
url: "controller.php",
data: data,
success: function(response) {
//alert("worked");
//console.log(response);
alert(response);
},
error: function() {
alert("There was an error submitting the information");
}
});
If you want to generate your 'data' object using 'values' variable, you can do the next:
values = []; // here your values collected previously
var data = {};
for (var key in values){
data[key] = values[key];
}
//now you can use your data in AJAX

Use JSON output from Flickr to display images from search

I need to display the images on my site from a JSON request.
I have the JSON:
https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=6a970fbb976a06193676f88ef2722cc8&text=sampletext&sort=relevance&privacy_filter=1&safe_search=1&per_page=5&page=1&format=json&nojsoncallback=1
And I have the format I need to put the photo URL in:
https://www.flickr.com/services/api/misc.urls.html
But I don't know how I would loop through that, I found some examples similar, but I am still having trouble seeing what I need.
I am using JavaScript/jQuery to pull the info.
I figure I would have this in a loop.
CurrentPhotoUrl = 'https://farm'+CurrentPhotoFarm+'.staticflickr.com/'+CurrentPhotoServer+'/'+CurrentPhotoId+'_'+CurrentPhotoSecret+'_n.jpg'
But each of those variables would need to be populated with an value from the element. I would need to loop through all 5 elements that are in the JSON.
Any help on how to create this loop would be greatly appreciated.
Try this code
var n = JSON.parse(x) //x is the json returned from the url.
var _s = n.photos.photo;
for(var z = 0 ; z < n.photos.photo.length ; z++)
{
var CurrentPhotoUrl = 'https://farm'+_s[z]['farm']+'.staticflickr.com/'+_s[z]['server']+'/'+_s[z]['id']+'_'+_s[z]['secret']+'_n.jpg'
console.log(CurrentPhotoUrl);
}
Edit ( With actual JQUERY AJAX call )
var n ='';
$.ajax({url: "https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=6a970fbb976a06193676f88ef2722cc8&text=sampletext&sort=relevance&privacy_filter=1&safe_search=1&per_page=5&page=1&format=json&nojsoncallback=1", success: function(result){
console.log(result);
n = result;
var _s = n.photos.photo;
for(var z = 0 ; z < n.photos.photo.length ; z++)
{
var CurrentPhotoUrl = 'https://farm'+_s[z]['farm']+'.staticflickr.com/'+_s[z]['server']+'/'+_s[z]['id']+'_'+_s[z]['secret']+'_n.jpg'
console.log(CurrentPhotoUrl);
}
}});
Output:
https://farm8.staticflickr.com/7198/6847644027_ed69abc879_n.jpg
https://farm3.staticflickr.com/2517/3905485164_84cb437a29_n.jpg
https://farm1.staticflickr.com/292/32625991395_58d1f16cea_n.jpg
https://farm9.staticflickr.com/8181/7909857670_a64e1dd2b2_n.jpg
https://farm9.staticflickr.com/8143/7682898986_ec78701508_n.jpg
This answer assumes your json data will not change. So inside a .js file, set your json to a variable.
var json = <paste json here>;
// the photos are inside an array, so use forEach to iterate through them
json.photos.photo.forEach((photoObj) => {
// the photo will render via an img dom node
var img = document.createElement('img');
var farmId = photoObj.farm;
// you can fill out the rest of the variables ${} in the url
// using the farm-id as an example
img.src = `https://farm${farmId}.staticflickr.com/${serverId}/${id}_${secret}.jpg`
// add the image to the dom
document.body.appendChild(img);
}
Inside your html file that contains a basic html template, load this javascript file via a script tag, or just paste it inside a script tag.
If you want to get the json from the web page and assuming you have the jquery script loaded...
$.ajax({
type: 'GET',
url: <flicker_url_for_json>,
success: (response) => {
// iterate through json here
},
error: (error) => {
console.log(error);
}
});
I'm not sure if this is the best solution but its is something someone suggested and it worked.
const requestURL = 'https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=6a970fbb976a06193676f88ef2722cc8&text=sampletext&sort=relevance&privacy_filter=1&safe_search=1&per_page=5&page=1&format=json&nojsoncallback=1'
$.ajax(requestURL)
.done(function (data) {
data.photos.photo.forEach(function (currentPhoto) {
console.log('https://farm'+currentPhoto.farm+'.staticflickr.com/'+currentPhoto.server+'/'+currentPhoto.id+'_'+currentPhoto.secret+'_n.jpg')
})
})
Varun's solution worked for me as well. I don't know which one is better but I thought I would post this as well since it looks like they were done fairly differently.

Javascript - Trouble using for...in to iterate through an object

I have a dynamically-generated object that looks like this:
colorArray = {
AR: "#8BBDE1",
AU: "#135D9E",
AT: "#8BBDE1",
... }
I'm trying to use it to color a map by using this plugin and the 'colors' attribute during the call to the plugin. Like this:
$('#iniDensityMap').vectorMap({
backgroundColor: '#c2e2f2',
colors: colorArray,
... (some other params)
});
But it doesn't color in the countries. When I hard code this in, it works fine - but it must be dynamically generated for this project, so something like this won't work for me (although it does in fact color the map):
$('#iniDensityMap').vectorMap({
backgroundColor: '#c2e2f2',
colors: { AR: "#8BBDE1", AU: "#135D9E", AT: "#8BBDE1" },
... (some other params)
});
I've traced the issue far enough into the plugin to find it has something to do with this loop:
setColors: function(key, color) {
if (typeof key == 'string') {
this.countries[key].setFill(color);
} else {
var colors = key; //This is the parameter passed through to the plugin
for (var code in colors) {
//THIS WILL NOT GET CALLED
if (this.countries[code]) {
this.countries[code].setFill(colors[code]);
}
}
}
},
I've also tried iterating through the colorArray object on my own, outside of the plugin and I'm running into the same issue. Whatever sits inside the for ( var x in obj ) isn't firing. I've also noticed that colorArray.length returns undefined. Another important note is that I've instantiated var colorArray = {}; in a separate call, attempting to ensure that it is sitting at the global scope and able to be manipulated.
I'm thinking that the problem is either:
The way I'm dynamically populating the object - colorArray[cCode] =
cColor; (in a jQuery .each call)
I'm once again confusing the differences between Arrays() and Objects() in javascript
It is a scope issue perhaps?
Some combination of everything above.
EDIT #1: I've moved my additional question about Objects in the Console in Firebug to a new post HERE. That question deals more specifically with Firebug than the underlying JS problem I'm asking about here.
Edit #2: Additional info
Here's the code I'm using to dynamically populate the Object:
function parseDensityMapXML() {
$.ajax({
type: "GET",
url: "media/XML/mapCountryData.xml",
dataType: "xml",
success: function (xml) {
$(xml).find("Country").each(function () {
var cName = $(this).find("Name").text();
var cIniCount = $(this).find("InitiativeCount").text();
var cUrl = $(this).find("SearchURL").text();
var cCode = $(this).find("CountryCode").text();
//Populate the JS Object
iniDensityData[cCode] = { "initiatives": cIniCount, "url": cUrl, "name": cName };
//set colors according to values of initiatives count
colorArray[cCode] = getCountryColor(cIniCount);
});
}
});
} //end function parseDensityMapXML();
This function is then called on a click event of a checkbox elsewhere on the page. The Objects iniDensityData and colorArray are declared in the head of the html file - hoping that keeps them in global scope:
<script type="text/javascript">
//Initialize a bunch of variables in the global scope
iniDensityData = {};
colorArray = {};
</script>
And finally, here's a snippet from the XML file that is being read:
<?xml version="1.0" encoding="utf-8"?>
<icapCountryData>
<Country>
<Name>Albania</Name>
<CountryCode>AL</CountryCode>
<InitiativeCount>7</InitiativeCount>
<SearchURL>~/advance_search.aspx?search=6</SearchURL>
</Country>
<Country>
<Name>Argentina</Name>
<CountryCode>AR</CountryCode>
<InitiativeCount>15</InitiativeCount>
<SearchURL>~/advance_search.aspx?search=11</SearchURL>
</Country>
... and so on ...
</icapCountryData>
Solved it! Originally, I was calling the function parseDensityMapXML() and then immediately after it calling another function loadDensityMapXML() which took the object created dynamically in the first function and iterated through it. Problem was, it wasn't called as a callback from the first function, so was firing before the Object had even been built.
To fix, I just amended the first function mentioned above to call the second function after the .each() was finished creating the objects:
function parseDensityMapXML() {
$.ajax({
type: "GET",
url: "media/XML/mapCountryData.xml",
dataType: "xml",
success: function (xml) {
$(xml).find("Country").each(function () {
var cName = $(this).find("Name").text();
var cIniCount = $(this).find("InitiativeCount").text();
var cUrl = $(this).find("SearchURL").text();
var cCode = $(this).find("CountryCode").text();
//Populate the JS Object
iniDensityData[cCode] = { "initiatives": cIniCount, "url": cUrl, "name": cName };
//set colors according to values of initiatives count
colorArray[cCode] = getCountryColor(cIniCount);
});
/* and then call the jVectorMap plugin - this MUST be done as a callback
after the above parsing. If called separately, it will fire before the
objects iniDensityData and colorArray are created! */
loadDensityMapXML();
}
});
} //end function parseDensityMapXML();

Categories

Resources