markmarkoh / datamaps

Customizable SVG map visualizations for the web in a single Javascript file using D3.js
http://datamaps.github.io
MIT License
3.78k stars 1.01k forks source link

updateChoropleths not working with international maps #353

Open colin353 opened 7 years ago

colin353 commented 7 years ago

Trying to implement an interactive map of Canada, and I noticed an issue with your id convention for provinces. This issue appears to affect many other international maps where states/provinces have "id" fields of the form XX.YY in their topology definitions.

Example of the issue in action: https://jsfiddle.net/0q8x4eud/

The expected behaviour is for a click on a map region to change that region's colour using the updateChoropleth function. Instead, it does nothing. The reason is found on line 1128 of /src/js/datamaps.js:

svg
  .selectAll('.' + subunit)
  .transition()
  .style('fill', color);

Here, subunit is the "id" field of the province, for example "CA.ON" for Ontario, Canada. The problem is that the svg.selectAll function expects a CSS class selector and the subunit name contains a dot, creating the resulting selector .CA.ON, which searches for a with both class CA and class ON. But if we examine the actually generated svg from the jsfiddle example above, we can see that is not the case:

<path ... class="datamaps-subunit CA.ON" ... />

As a result, the selector fails silently and no choropleth update is applied. In order to get my code working, I changed the code in /src/js/datamaps.js to:

svg
  .selectAll('.' + subunit.replace(".", "\\.")
  .transition()
  .style('fill', color);

This escapes any period inside of the subunit and creates a valid selector. You can see it working here:

https://jsfiddle.net/9moj193t/1/

I created a PR for this: #352

Alex-Devoid commented 5 years ago

I had a simular problem updating the data in popupTemplate while implementing a map of Guatemala. I expected the updateChoropleths function to change the data in popupTemplate, but the popups were blank when I called updateChoropleths. Thanks to this issue, I changed the code in /src/js/datamaps.js to: var geo = this.svg.select('.' + subunit.replace(".", "\\.")).attr('data-info', JSON.stringify(this.options.data[subunit]));

Now the info in each popup changes when updateChoropleths is called.

P.S. @colin353 There's an itty bitty typo in your post, I believe. I changed it to: .selectAll('.' + subunit.replace(".", "\\."))