Reputation: 4214
I am trying to write a general-purpose map so that any new csv will change the data visualization. I was able to plot the map, join csv with geojson and even print csv data on mouseover. However, when I try to use this data to apply colors to the map, I get undefined
all the time - I guess due to the asynchronous nature of js. How can I fix that most efficiently?
Here is my code:
// Community colors
var comm_colors = [ "red", "blue", "green", "yellow", "purple" ];
// CSV
function parse_add_csv(cts){
var new_cts = cts
console.log('parsing csv');
d3.csv("data/communities.csv", function(comms)
{ csv = comms.map(function(d)
{
return {"community": d.community, "label": d.BoroCT2010} ;
})
csv.forEach(function(d, i) {
new_cts.forEach(function(e, j) {
if (d.label === e.properties.BoroCT2010) {
e.properties.community = parseInt(d.community)
}
})
})
})
return new_cts
}
d3.json("data/nyct2010_17a3_topo.json", function(error, nyb) {
console.log('tracts uploaded, v3')
var ctss = topojson.feature(nyb, nyb.objects.nyct2010_17a3).features;
ctss = parse_add_csv(ctss); // match data from csv by BoroCT2010
cts.selectAll(".tract")
.data(ctss)
.enter().append("path")
.attr("class", "tract")
.attr("d", path)
.attr("id", function(d) {
return d.properties.BoroCT2010;})
.attr("nhd_name", function(d) {
return d.properties.NTAName;})
.style('fill', function(d){
console.log(comm_colors[d.properties.community])
return comm_colors[d.properties.community];})
.on("mouseover", handleMouseOver)
.on("mouseout", handleMouseOut)
.style('fill', function(d) {return
comm_colors[d.properties.community]});
})
Here, I am trying to match community column from csv to the geojson and then use it to select a color from the list. It works perfectly when I print color in the mouseover event but does not work within the chain:
.style('fill', function(d){
console.log(comm_colors[d.properties.community])
return comm_colors[d.properties.community];})
Upvotes: 1
Views: 1222
Reputation: 102198
Your guess is only partially correct:
I get undefined all the time - I guess due to the asynchronous nature of js.
There is no "asynchronous nature of js". JavaScript is always synchronous and single-threaded. However, AJAX calls and D3 functions like d3.json
and d3.csv
are asynchronous.
That being said, there are a couple of solutions. You can use d3.queue. The easiest solution, though, is simply nesting the asynchronous functions:
d3.json("data/nyct2010_17a3_topo.json", function(error, nyb){
d3.csv("data/communities.csv", function(comms){
//here goes all code that uses both 'nyb' and 'comms'
})
})
After nesting them, put all the code that deals with the GeoJSON and with the CSV inside the inner callback.
Upvotes: 1