I am currently having an issue with a D3.js map that I built several years ago. It is a map of the US and on hover, I have a tooltip that appears with the state name, state fish, and a link to click on for the user to visit the respective Dept. of Fish and Wildlife for each state. This map is live on a website and the data is currently being pulled from a csv file that I’m hosting in a GitHub gist. The reason for me delving in to this project now is that you’ll notice from the map on the website, that some of the links to the state dept of fish and wildlife have moved their websites to another url, meaning that my links don’t work. I believe that Illinois and Indiana are a couple of them I was attempting to fix.
However, trying to edit the csv file in the github gist is somewhat difficult, so I decided I wanted to take the csv file to my local pc (for easier editing) and then upload it to my server that I host the website on. I didn’t anticipate not being able to populate the data in my D3.js map. The map that is currently active is at www.salmonegg.com.
What am I missing? It literally should work exactly like my github gist. I haven’t changed anything major, except the source of the csv file. In my research, I’m assuming I’m doing this correctly with the d3.csv() function. I’m also assuming that the path is correct in my variable csvdata.
So far, the map builds correctly, but the tooltip doesn’t load with the data. When I run the code, while logging the data to the console to see what data my d3 tooltip is receiving, some of the items return undefined. It only returns about 21 items, then it stops because of the undefined items. But when I log my stateData variable, I can see all of the items for each state loaded correctly.
I should say here as well that the code errors out, showing undefined items right away as it attempts to draw the data point on the map where I can hover and see that tooltip. On the live map on the website, you can see that on the map there’s a small blue circle with the states postal code. You should be able to hover over that and see the tooltip with the data. Of course, I’m using the data from my csv file to populate not only the data points for the tooltip, but that’s where I’m retreiving the postal code for the map.
Here’s my d3.js map code:
//div id for D3.js map is #fishWildlifeMap
function dropdownMenuData(data) {
if (data[0] !== 'District of Columbia') {
var tag = "<a class='dropdown-item' target='_blank' href='" + data[1] + "'>" + data[0] + "</a>";
$('#dropdownMenu').append(tag);
}
}
var usmap = "https://unpkg.com/us-atlas@1/us/10m.json";
var csvdata = "csvformap.csv";
d3.queue()
.defer(d3.json, usmap)
.defer(d3.csv, csvdata)
.await(buildMap);
var width = 1000;
var height = 600;
function buildMap(error, us, dataForStates) {
var data = topojson.feature(us, us.objects.states).features;
var svg = d3.select("#fishWildlifeMap").append('svg')
.attr("viewBox", "0 0 " + width + " " + height)
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("id", "svg-responsive");
var color = d3.scaleSequential(d3.interpolateBlues)
.domain([0, 100]);
var path = d3.geoPath();
var stateData = {};
dataForStates.forEach(function (el, i) {
var key = el.id < 10 ? '0' + el.id : el.id;
stateData[key] = [el.name, el.url, el.statefish, el.code];
dropdownMenuData(stateData[key]);
});
var tooltip = d3.select('body').append('div')
.attr('class', 'tooltip')
.data(dataForStates);
svg.append("g")
.attr("class", "states")
.selectAll("path")
.data(topojson.feature(us, us.objects.states).features)
.enter().append("path")
.attr("d", path)
.style('fill', function (d, i) { return color(i * 2) })
svg.append("path")
.attr("class", "state-borders")
.attr("d", path(topojson.mesh(us, us.objects.states, function (a, b) { return a !== b; })));
svg.append('g')
.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr("cx", function (d) {
if (stateData[d.id][3] !== "DC") {
if (stateData[d.id][3] === "FL") {
return path.centroid(d)[0] + 15;
}
else if (stateData[d.id][3] === "NJ" || stateData[d.id][3] === "RI" || stateData[d.id][3] === "DE") {
return path.centroid(d)[0] + 25;
}
else if (stateData[d.id][3] === "MD" || stateData[d.id][3] === "MA") {
return path.centroid(d)[0] + 45;
}
else if (stateData[d.id][3] === "LA" || stateData[d.id][3] === "HI" || stateData[d.id][3] === "RI") {
return path.centroid(d)[0] - 10;
}
else {
return path.centroid(d)[0];
}
}
})
.attr("cy", function (d) {
if (stateData[d.id][3] !== "DC") {
if (stateData[d.id][3] === "HI") {
return path.centroid(d)[1] + 20;
}
else if (stateData[d.id][3] === "MD" || stateData[d.id][3] === "RI") {
return path.centroid(d)[1] + 25;
}
else {
return path.centroid(d)[1] + 5;
}
}
})
.attr('r', 12)
.style('fill', 'navy')
.style('opacity', function (d) {
if (stateData[d.id][3] === "DC") {
return "0";
}
else {
return ".6";
}
});
svg.append("g")
.selectAll("text")
.data(data)
.enter()
.append("svg:text")
.text(function (d) {
if (stateData[d.id][3] !== "DC") {
return stateData[d.id][3];
}
})
.attr("x", function (d) {
if (stateData[d.id][3] === "FL") {
return path.centroid(d)[0] + 15;
}
else if (stateData[d.id][3] === "NJ" || stateData[d.id][3] === "RI" || stateData[d.id][3] === "DE") {
return path.centroid(d)[0] + 25;
}
else if (stateData[d.id][3] === "MD" || stateData[d.id][3] === "MA") {
return path.centroid(d)[0] + 45;
}
else if (stateData[d.id][3] === "LA" || stateData[d.id][3] === "HI" || stateData[d.id][3] === "RI") {
return path.centroid(d)[0] - 10;
}
else {
return path.centroid(d)[0];
}
})
.attr("y", function (d) {
if (stateData[d.id][3] === "HI") {
return path.centroid(d)[1] + 22;
}
else if (stateData[d.id][3] === "MD" || stateData[d.id][3] === "RI") {
return path.centroid(d)[1] + 27;
}
else {
return path.centroid(d)[1] + 7;
}
})
.attr("text-anchor", "middle")
.attr('font-size', '12px')
.attr('fill', 'white')
.on('mouseover', function (d, i) {
tooltip.transition()
.duration(500)
.style("opacity", 0);
tooltip.transition()
.duration(200)
.style("opacity", 1);
tooltip.html(function () {
if (stateData[d.id][0] !== "District of Columbia") {
return "<div id='text' class='text-center'><a target='_blank' href='" + stateData[d.id][1] + "'>" + stateData[d.id][0] + "</a><br>State Fish: " + stateData[d.id][2] + "</div>";
}
})
.style('left', (d3.event.pageX - 10) + 'px')
.style('top', (d3.event.pageY - 10) + 'px')
});
}
And the csv file here:
id,code,name,url,statefish
1,AL,Alabama,https://www.fws.gov/alabama/,Large-mouth Bass & Fighting Tarpon
2,AK,Alaska,https://www.fws.gov/alaska/,King Salmon
3,AZ,Arizona,https://www.azgfd.com/,Apache Trout
4,AR,Arkansas,https://www.agfc.com/,Not recognized
5,CA,California,https://www.wildlife.ca.gov/,Golden Trout & Garibaldi
6,CO,Colorado,https://www.fws.gov/coloradofishandwildlife/,Greenback Cutthroat Trout
7,CT,Connecticut,https://www.portal.ct.gov/DEEP/Fishing/CT-Fishing/,American Shad
8,DE,Delaware,https://dnrec.delaware.gov/fish-wildlife/,Weakfish
9,FL,Florida,http://myfwc.com/,Largemouth Bass & Atlantic Sailfish
10,GA,Georgia,http://georgiawildlife.com/,Large-mouth Bass
11,HI,Hawaii,http://dlnr.hawaii.gov/dofaw/,Reef Triggerfish
12,ID,Idaho,https://idfg.idaho.gov/,Cutthroat Trout
13,IL,Illinois,http://dnr.illinois.gov/,Bluegill
14,IN,Indiana,https://www.in.gov/dnr/fish-and-wildlife/,River Carpsucker
15,IA,Iowa,http://www.iowadnr.gov/,Channel Catfish
16,KS,Kansas,http://ksoutdoors.com/,Not recognized
17,KY,Kentucky,https://fw.ky.gov/Pages/default.aspx/,Kentucky Spotted Bass
18,LA,Louisiana,http://wlf.louisiana.gov/,White Crappie
19,ME,Maine,https://www.maine.gov/ifw/,Landlocked Atlantic Salmon
20,MD,Maryland,https://dnr.maryland.gov/wildlife/Pages/default.aspx/,Rockfish (striped Bass)
21,MA,Massachusetts,https://www.mass.gov/topics/hunting-fishing/,Cod
22,MI,Michigan,https://www.fws.gov/refuge/Michigan_WMD/,Brook Trout
23,MN,Minnesota,http://www.dnr.state.mn.us/fishwildlife/index.html/,Walleye
24,MO,Missouri,https://huntfish.mdc.mo.gov/fishing/,Channel Catfish & Paddlefish
25,MT,Montana,http://fwp.mt.gov/,Cutthroat Trout
26,NE,Nebraska,https://outdoornebraska.gov/fish/,Channel Catfish
27,NV,Nevada,https://www.fws.gov/nevada/,Lahontan Cutthroat Trout
28,NH,New Hampshire,http://www.wildlife.state.nh.us/,Brook Trout & Striped Bass
29,NJ,New Jersey,http://www.state.nj.us/dep/fgw/,Brook Trout & Striped Bass
30,NM,New Mexico,http://www.wildlife.state.nm.us/,Rio Grande Cutthroat Trout
31,NY,New York,https://dec.ny.gov/regulatory/permits-licenses/,Brook Trout & Striped Bass
32,NC,North Carolina,https://www.ncwildlife.org/Fishing/Fishing-in-North-Carolina/,Channel Bass & Southern Appalachian Brook Trout
33,ND,North Dakota,https://gf.nd.gov/,Northern Pike
34,OH,Ohio,https://www.fws.gov/midwest/Ohio/,Not recognized
35,OK,Oklahoma,https://wildlifedepartment.com/,White Bass
36,OR,Oregon,http://www.dfw.state.or.us/,Chinook Salmon
37,PA,Pennsylvania,https://www.pgc.pa.gov/Wildlife/Pages/default.aspx/,Brook Trout
38,RI,Rhode Island,https://www.dem.ri.gov/programs/fish-wildlife/,Striped Bass
39,SC,South Carolina,https://www.dnr.sc.gov/fishing.html/,Striped Bass
40,SD,South Dakota,http://gfp.sd.gov/,Walleye
41,TN,Tennessee,http://tn.gov/twra/,Largemouth Bass & Channel Catfish
42,TX,Texas,https://tpwd.texas.gov/fishboat/fish/,Guadalupe Bass
43,UT,Utah,https://wildlife.utah.gov/,Bonneville Cutthroat Trout
44,VT,Vermont,http://www.vtfishandwildlife.com/,Brook Trout & Walleye
45,VA,Virginia,http://www.dgif.virginia.gov/,Brook Trout & Striped Bass
46,WA,Washington,http://wdfw.wa.gov/,Steelhead Trout
47,WV,West Virginia,https://www.fws.gov/westvirginiafieldoffice/,West Virginia Golden Brook Trout
48,WI,Wisconsin,http://www.dnr.wi.gov/topic/wildlifehabitat/,Muskellunge
49,WY,Wyoming,https://wgfd.wyo.gov/,Cutthroat Trout
50,MS,Mississippi,http://www.mdwfp.com/,Largemouth Bass