2

I'm trying to get an D3.js interactive map that, on hovering on a certain municipality (divided into svg paths), will return the name and the number of escape room themes in said municipality. However, I can't get selectAll("path") or any variation to work on it.

Here's my code:

d3.json("data/seoul_municipalities_topo_simple.json", function(error, data) {
  var features = topojson.feature(data, data.objects.seoul_municipalities_geo).features;
  seoulmap.selectAll("path")
    .data(features)
    .enter().append("path")
    .attr("class", function(d) {
      console.log();
      return "municipality c" + d.properties.SIG_CD
    })
    .attr("id", function(d) {
      return d.properties.SIG_KOR_NM
    })
    .attr("d", path); /* the path variable holds the geoPath from my topojson file*/
});

//tooltip displays
var mouselocation;
var tooltip = d3.select(".tooltip");
var mappath = d3.selectAll("path"); /* this doesn't work */

mappath.on('mouseenter', function() {
  tooltip.style('display', 'block');
  let textID = this.id;
  tooltip.select(".tooltip-city")
    .html("<strong>" + textID + "</strong></br>");

  tooltip.select(".tooltip-num")
    .html("# of Themes: ");
}).on('mousemove', function() {
  mouselocation = d3.mouse(d3.select('body').node());
  tooltip.style("left", mouselocation[0] + 160 + "px")
    .style("top", mouselocation[1] + 10 + "px");
}).on('mouseleave', function() {
  tooltip.style('display', 'none');
});

when I run my site on console, each element in the svg is divided into paths that hold the class .municipality. Selecting through that doesn't work either. But if I replace the selector to something else, say "svg", works like a charm. I'm not sure what I'm doing wrong here??

(I'm using D3.js v4!)

  • 2
    Your problem is a variation of [*"How do I return the response from an asynchronous call?"*](/q/14220321). Since `d3.json()` is asynchronous the paths aren't there yet when you try to select them. All the code relying on the loaded data and the created paths has to go into the callback to `d3.json()`. – altocumulus Feb 27 '19 at 15:40
  • @altocumulus huh, so basically if I can load 'svg' but not 'path' it means that it was only partially loaded, thus the inconsistent functionality? I'm not really experienced with the asynchronous aspect of javascript yet so I'll check out the link you gave me! thanks for the help :) – heatherfeather Feb 27 '19 at 17:24
  • 2
    Not exactly, the SVG is already there (somewhere in the missing parts of your code) in variable `seoulmap`. The paths, however, are created not before the JSON has been fully loaded and the callback is executed. Try moving the `d3.selectAll("path")` inside that callback right after appending the paths and you'll see what I mean. The code below the comment `//tooltip displays` is actually executed **before** `seoulmap.selectAll("path") ...` inside the callback! That's what asynchronous execution is all about. – altocumulus Feb 27 '19 at 19:30

0 Answers0