I am currently trying to use the d3 framework for a university visualisation approach.
For testing purpose I want to read a csv-file and parse the rows to objects inside an array.
My csv looks like:
ID, Referred To, TimeStamp, Votes, Comment
So I want to read it with the following lines:
d3.csv("test_comments.csv", function(data) {
commentlist = data.map(function(d) {
return[+d["ID"],
+d["Referred To"],
+d["TimeStamp"],
+d["Votes"],
+d["Comment"]
]
});
});
But if I want to readout the values afterwards I am just getting "undefined"
I also tried the way mbostock described in this thread:
csv to array in d3.js
but working with a global variable is not working either.
var commentlist;
d3.csv("test_comments.csv", function(data) {
commentlist = data.map(function(d) {
return[+d["ID"],
+d["Referred To"],
+d["TimeStamp"],
+d["Votes"],
+d["Comment"]
]
});
});
console.log(commentlist);
Am I understanding something wrong?
Maybe you have a solution for me.
var commentlist=[];
d3.csv("test_comments.csv", function(data) {
commentlist=data;
});
console.log(commentlist);
What I know is, In the call back data object will contain array of JSON objects of csv file's all rows of data, that each row data is pushed as a JSON format into the data array.
As below
[{"ID": valueFromtheRow, "Referred To": value, "TimeStamp": value, "Votes":value, "Comment":value}]
The call back function is called by passing the array of JSONs.
So data object will look like
data=[{"ID": valueFromtheRow, "Referred To": value, "TimeStamp": value, "Votes":value, "Comment":value}];
Hope you understood...If not ask me.
I think the reason you got { console.log(commentlist) } undefined is that inside d3.csv the callback function is parsed and called last by browser, and { console.log(commentlist) } is called earlier even though it appears at the bottom of your code. So the moment when { console.log(commentlist) } is called, { commentlist } is actually undefined (only declared).
That being said, just try putting { console.log(commentlist) } inside the callback and it should do the job.
Related
I'm building this website: http://collections.design
The way it works is by reading all tools data from a JSON, using jQuery (I don't know much javascript). Then, you can click on an item and a side panels opens with further information. But there's a lot of repeated code, so I'm trying to optimise it a bit.
First I parse the JSON:
// The data source
var data_source = "../data/tools/tools.json";
// Parsing the JSON
$.getJSON(data_source, function(data) {
$.each(data, function(key,val) {
// And I'm storing all of its values in variables, to make them easier to read:
var name = val.availability.name;
var linux = val.os.linux;
// Then I'm using all that to render each item on screen
…
});
});
Each of the items has a button that calls another function to create and open the side panel. The side panel reuses that item's data from the JSON. This function to create the side panel is using the name variable as parameter, but then inside is parsing the JSON again to get the rest of the values it needs.
My question is:
How can I "encapsulate" all variables when I do the JSON parsing, then pass it as a parameter to the other function; and finally, individually read each of those values in the other function?
I tried working with arrays. But didn't manage it to work, also keeping in mind that I'm trying to simplify things, not repeat myself, and keep short names…
Maybe I'm asking too much, but any pointers or links to doc will be appreciated.
I see two ways of doing this.
1) Save the JSON data outside the scope so you can reuse it and pass the index of the data you want.
Something like this
// The data source
var data_source = "../data/tools/tools.json";
var all_data;
// Parsing the JSON
$.getJSON(data_source, function(data) {
all_data = data;
$.each(data, function(key,val) {
$('.button').on('click', function() { callToOtherFunction(key) })
});
});
function callToOtherFunction(key) {
console.log(all_data[key]);
}
2) As Sam Axe said, pass the data directly to the function
// The data source
var data_source = "../data/tools/tools.json";
// Parsing the JSON
$.getJSON(data_source, function(data) {
$.each(data, function(key,val) {
$('.button').on('click', function() { callToOtherFunction(key) })
});
});
function callToOtherFunction(val) {
console.log(val);
}
Here's a working fiddle.
The data is already "encapsulated" in the data object. Pass that object to the function that you want to use the data in.
You could always construct a new object - but what's the point - it's already in the data object.
I have a div that's being populated by GET request data. I want to make it so that if certain conditions are not met (there isn't any data) then the div is hidden. It was working when I was using a local JSON file, but since I switched to REST and axios I've had to convert what I have.
When I run console.log(admText.length) I'm getting a 0 and the div is hidden in the browser, but the user's data that I've rendered does contain data. Therefore, their page should show that div.
I have a feeling that my if statement is in the wrong place, but I'm not sure where it could go. Putting it in the let admText block results in an error.
JS snippet:
import $ from 'jquery';
import DataTable from 'datatables.net';
export default class {
constructor() {
}
loadAdmData(response) {
let admText = response.map(function(val) {
return {
"Status": val.AdmStatus,
"Classification": val.Classification
}
})
if (admText.length == "") $("#adm-tab").hide();
// if (!admText.length) $("#adm-tab").hide(); // was working w/ local JSON file
console.log(admText.length); // shows `0`, which isn't correct
$('#adm-table').DataTable({
columns: [
{ data: "Status" },
{ data: "Classification" }
... etc
Are you sure response is an array? if you're getting it from a GET it could be a JSON string.
.map() is going to return an array so admText is an array and since you're getting .length as '0' that means your mapping function is failing for some reason.
you should try console.log(response); and console.log(admText); to see what you're putting inside of the map and what you're getting out of it.
I'm new at this. Im trying to make a simple interactive chart using jaavascript. The idea is that when I change the values in the selector, the chart change the data is using.
However, I´m having troubles with the data switching. The data come´s frome different urls. Those urls are in a CSV file. My code extracts the urls from th CSV file and makes an array. Then it proceed to call the CSV file from the adequate element of the array. Simplifying the code:
functionThatReturnsArray(){
d3.csv("http//URL.COM", function(){
SomeMoreCode;
return ArrayOfStrings
};)
}
A = functionThatReturnsArray();
MoreCode;
//For example, the first value from A is selected
d3.csv(A[0], function(error, data) {
MoreCode;
})
The problem is that it seems that this isn´t a valid input to d3.csv, because it doesn´t work. I don´t know if i´m missing something or it just can´t be done this way.
I searched and it might be from the fact that d3.csv is an asynchronous method, but I´m not sure if that´s the problem.
Any suggestion will be apreciated
Your first CSV data is loading asynchronously, so this function will not return anything
functionThatReturnsArray(){
d3.csv("http//URL.COM", function(){
SomeMoreCode;
return ArrayOfStrings
};)
}
You can put following code in function
function processArray(A){
MoreCode;
//For example, the first value from A is selected
d3.csv(A[0], function(error, data) {
MoreCode;
})
}
and invoke this function in first csv loading callback
functionThatReturnsArray(){
d3.csv("http//URL.COM", function(){
SomeMoreCode;
processArray(ArrayOfStrings) //add this
};)
}
I have an application in which I am making multiple API calls and caching that data for later. Then someone else in the app, I want to retrieve that data and list it in a drop down using ng-option.
To get the cached data for each call, I am doing
var httpCache = $cacheFactory.get('$http');
var cachedImpactedEntities = httpCache.get('my api url');
This returns an object of an array in an array like so:
[200,"[ {
"entity_id": 1,"entity_desc": "test1" },
{"entity_id": 2,"entity_desc": "test2"}]",
{"content-type":"application/json;
charset=utf-8"},"OK"]
What would be a good way to extract just the inside array in quotes and output each "entity_desc" to the drop down using ng-option like:
test1
test2
...
The way the cached information comes back is confusing me.
Thanks.
If I understand you correctly the following shall be sufficient:
$scope.cachedEntities = eval(cachedImpactedEntities[1]);
<select ng-options="item as item.entity_desc for item in cachedEntities track by item.entity_id" ng-model="selected"></select>
But that means you will need to update "manually" the cachedEntities each time you get the data back from api call.
Consider of using promise construct:
$http.get("url+parameters").then(function(data) { $scope.cachedEntities = data}, function(){ // do something on error });
This is the json file I am working with
?(
{
"title":"1",
"description":"description",
"site":"site",
"image_s":"/Becki.jpg",
"image_l":"aurel"
},
{
"title":"2",
"description":"2",
"site":"1",
"image_s":"8.jpg",
"image_l":"aurel"
})
The question mark is replaced with a dynamic number in order to over come cross-domain restrictions. And I think this is why I am having trouble
I am trying to get both image_s but I can only read the data of the first item (if that's the right word):
$.getJSON(surl, function(data) {
$.each(data, function(tete, i){
$.each(data, function(tete, i){
$("<div>").addClass("box").append(
$("<img/>").attr("src", [this]))
).appendTo("#showdata");
});
})
});
I know there is something wrong with $("<img/>").attr("src", [this])) but that is not the problem. The problem is that the above loop only get the content of the first item (title:1 to the end not title:2)
I think if the name of the question mark wasn't dynamic I could have done the loop from there and got its children, but I dont know how to do that in this case
And in case you need to know, I can not use server-side programing for this particular project
Can you help in any way?
You have to put your items (called objects in JavaScript) into array:
[
{
"title":"1",
"description":"description",
"site":"site",
"image_s":"/Becki.jpg",
"image_l":"aurel"
},
{
"title":"2",
"description":"2",
"site":"1",
"image_s":"8.jpg",
"image_l":"aurel"
}
]
And also change your JS:
$.each(data, function(index, item){
$("<div>").addClass("box")
.append($("<img/>").attr("src", [item.image_s]))
.appendTo("#showdata");
});
Running example is shown in this JSFiddle.
If you're passing data through another domain, you're probably using JSONP. JSONP requires the server to return the values wrapped in a function; in your case, the function is a random string of numbers.
If your post is accurate, you'll have to update the server to return the JSON object properly:
Currently it is returning multiple objects wrapped by a function: 235235({one object}, {two object})
When it should be returning one JSON object, wrapped by a function: 235235([{first object in array}, {second object in array}])