I am having trouble specifying a class within an SVG using D3.js

I have been facing a strange issue with my script. When I try to execute the following code:

var key="#US"
d3.select(key).style("fill", "red");

it seems like it's not working for me. Interestingly, when I run the same code in the console, it works perfectly fine.

I have tried using functions like document.ready and window.onload, but none of them seem to solve the problem.

After experimenting with different approaches, I came up with this solution:

window.onload = function() {
    Object.keys(countries).forEach(function(key){
        d3.select(key).style("fill", "red");
    });
};

Object.keys(countries).forEach(function(key){
    d3.select(key).style("fill", "red");
    console.log("t")
});

The strange thing is that it only seems to work when the dev console is active, and even then it only works 1 out of every 4 times. This error has got me puzzled.

Answer №1

In this unique scenario, I acquired an SVG world map and addressed the class attributes by substituting spaces with hyphens.

Currently, when presented with a map resembling the following:

const countries = {
  '.United-States': true
};

You can now identify the US and its associated regions, and color them red, using:

Object.keys(countries).forEach(function(key) {
  d3.selectAll(key).style("fill", "red");
});

Innovative demonstration

If there was sufficient time available, all path class names could potentially be converted into a 2 or 3-digit country code for enhanced simplicity to align better with your selection approach.

const svgUrl = 'https://gist.githubusercontent.com/rmkane/4fb74736f090d9145b53e56d7e42989e/raw/e3e6fc625094ab84b3b2381afc447cf109bc601a/world.svg';
const svgContainer = document.querySelector('#svg-container');

const countries = {
  '.United-States': true
};

const parseSvg = (svgText) =>
  new DOMParser().parseFromString(svgText, 'image/svg+xml');

(async () => {
  const response = await fetch(svgUrl);
  let svgText = await response.text();
  // Rectify path class names
  svgText = svgText.replaceAll(/class="(\w+)\s(\w+)"/g, 'class="$1-$2"');
  const svg = parseSvg(svgText).firstElementChild;
  // Integrate the SVG
  svgContainer.append(svg);
  // Prominently feature US and its territories
  Object.keys(countries).forEach(function(key) {
    d3.selectAll(key).style('fill', 'red');
  });
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="svg-container"></div>
<!-- See: https://gist.github.com/rmkane/4fb74736f090d9145b53e56d7e42989e#file-world-svg -->

Alternate illustration

This specific example involves an SVG sourced from MapSVG:

const svgUrl = 'https://gist.githubusercontent.com/rmkane/4fb74736f090d9145b53e56d7e42989e/raw/ce11d29d4595e9c386bac41efaa82d33b8f07aec/world-2.svg';
const svgContainer = document.querySelector('#svg-container');

const countries = {
  '#US': true
};

const parseSvg = (svgText) =>
  new DOMParser().parseFromString(svgText, 'image/svg+xml');

(async () => {
  const response = await fetch(svgUrl);
  let svgText = await response.text();
  const svg = parseSvg(svgText).firstElementChild;
  svgContainer.append(svg);
  Object.keys(countries).forEach(function(key) {
    d3.selectAll(key).style('fill', 'red');
  });
})();
#svg-container svg {
  background: lightblue;
}

#svg-container svg path {
  fill: grey;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="svg-container"></div>
<!-- See: https://gist.github.com/rmkane/4fb74736f090d9145b53e56d7e42989e#file-world-2-svg -->

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using the spread operator in a component's render function could potentially lead to an endless update loop

Although this issue has been addressed before in a discussion about the "You may have an infinite update loop in a component render function" warning in Vue component, the solution provided did not resolve my problem. I am seeking assistance to ...

How can I duplicate or extract all the formatting applied to a specific text selection in Ckeditor?

I am currently utilizing CKEditor version 3.6 within my Asp.net MVC 3 Application. One of my tasks involves creating a Paint format option similar to Google Docs. I am looking to integrate this feature into CKEditor. Is there a way in CKEditor to transfe ...

Encountering a CORS issue while attempting to make a GET request to an API in an

Looking to retrieve HTML data from a website using an API. The target URL is: https://www.linkedin.com/ Trying to fetch the HTML page as text from this specific URL. Here's what I attempted: getData() { const api = "https://www.linkedin. ...

What are the steps for building modules using Vuex and fetching data using mapState()?

I've been experimenting with separating my Vuex code into modules, but I'm having trouble retrieving data using mapState(). What's the most effective approach for creating modules and utilizing mapping? Here's the structure of my stor ...

Every time I click a button, I am trying to add JSON objects into an array and then show the outcomes

Currently, my goal is to create a random selection feature from an array that users can contribute to by clicking a button. I am a bit unsure about how to proceed with this task. The application is developed in React and it utilizes the movieDB's API ...

input value does not change when the "keyup" event is triggered

I'm encountering an issue with the code below. The code is for a simple To Do app using Javascript. I followed a tutorial step by step, but my app isn't functioning as expected. When I press the enter key, the input value should be added to the l ...

Adjust positioning of navigation when hovered over

Need help creating a cool navigation effect like this. Live example: https://hookandbarrelrestaurant.com/ Here is my code: https://codepen.io/Dhaval182/pen/rQPMoW ...

Saving maps on React Native can be done easily using AsyncStorage

I am facing an issue with saving user inputs as a JS map using AsyncStorage in my React Native app. Despite no errors during the saving process, I encountered "[object Map]" when attempting to retrieve the data. Here is a simplified version of my user map ...

Display the datepicker beneath the input field

I successfully integrated the datepicker, but I prefer for the calendar to display below the date input field rather than above it. HTML5 <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv=" ...

Is there a way to manually stop a file upload (stream) using a XMLHttpRequest on the server?

Utilizing XMLHttpRequest (Level 2) to transfer a file to a node.js server, I am currently examining the file-stream for valid headers on the server side. The goal now is to halt the upload if any errors are encountered during streaming. My XMLHttpRequest c ...

Is there a way to directly access the React component that was clicked?

I'm looking to dynamically change the class of a component when clicked. By using state to create a new component with properties such as name and done (initiated as false), which are then added to the todos array, I want to find out how to identify t ...

How do I store the result of an Ajax request as a variable in a different function within a React component?

One of the challenges I'm facing involves making an ajax call that retrieves a list of movies, and then running another function with a separate ajax call to fetch the genre names. Since the first call only provides the genre IDs, I need to match each ...

Sorting of dates in mui-datatables is not accurate

I have dates that are formatted using moment.js, for example ("Sat, Feb 22, 2020 12:55 PM") I retrieve them from firestore, and they appear to come in correctly as I first sort them in descending order. forms.sort(function(left, right) { return moment.u ...

Adjusting the transparency of numerous elements using JavaScript or jQuery

My task involves creating a large form where elements initially have an opacity of 0.5, and when a button is clicked, the opacity changes to 1.0. While I can achieve this using JavaScript, I want to find a more efficient way by avoiding individual if state ...

``The presence of symlink leading to the existence of two different versions of React

Currently, I am working on a project that involves various sub custom npm modules loaded in. We usually work within these submodules, then publish them to a private npm repository and finally pull them into the main platform of the project for use. In orde ...

When the text in a Material UI Textfield is updated using setState in React, the Hinttext may overlap with the newly set

How can I fix the issue of default hintText and floatingLabelText overlapping with text in a textfield when using setState to autofill the textfield upon clicking on an edit button? Here is an image showing the textfield overlap: Below is the code for th ...

Significant delay in processing second jQuery Ajax call

Attempting a simple Ajax call with page content refresh using the following code snippet: $("a.ajaxify-watched").bind("click", function(event) { $item = $(this); $.ajax({ url: $(this).attr("href"), global: false, type: "G ...

React's connect method is causing issues with my test case

Attempting to create a test case for my jsx file... Took a sample test case from another jsx file... The other file does not have the connect method... But this new file contains the connect method... Believe this is causing issues with my test case... Any ...

Trouble with firing the click event using document.createElement('a') in Firefox

I wrote a function that fetches arraybuffer data from my API, generates a temporary anchor element on the webpage, and then triggers a click event to download the file. Interestingly, this function performs as expected in Chrome. @action async loadVouc ...

Tips for sending a Json array to a servlet

[DUPICATE] Here is the JSON code I am using for my POST request: var data_create = JSON.stringify($("#form_create_delegate").serializeArray()); alert("data_create content" + data_create); // console.log(data_create) $.ajax({ ...