Javascript to dynamically select based on another query

Issue

I am working with a svg element as following

const src = [{        
        "Name": "Australia",
        "Year": 1997,
        "Value": 15.540540540540499
    },
    {
        "Name": "Australia",
        "Year": 1998,
        "Value": 15.540540540540499
    },
    {
        "Name": "Australia",
        "Year": 1999,
        "Value": 22.4489795918367
    },
    
    {
        "Name": "Brunei",
        "Year": 1998,
        "Value": 6.4516129032258096
    },
    {
        "Name": "Brunei",
        "Year": 2017,
        "Value": 9.0909090909090899
    },
    {
        "Name": "Brunei",
        "Year": 2018,
        "Value": 9.0909090909090899
    },    
    {
        "Name": "Cambodia",
        "Year": 1997,
        "Value": 5.8333333333333304
    },
    {
        "Name": "Cambodia",
        "Year": 2017,
        "Value": 5.8333333333333304
    },
    {
        "Name": "Cambodia",
        "Year": 2021,
        "Value": 8.1967213114754092
    }
];
//this value gets generated dynamically based on previous calculations
const yr = 1998; 
//pick up the associated data that has the same yr
const filt = src.filter(d => d.Year == yr).sort((x, y) => x.Name.localeCompare(y.Name))

console.log(filt);
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>  
    <div id="container" class="svg-container"></div>
   <svg viewBox="0 0 1280 720">
 
   <g class="travCirc">
   <circle class="Australia" stroke="black" r="10.5" style="fill: red; opacity: 0;"></circle>
   <circle class="Brunei Darussalam" stroke="black" r="10.5" style="fill: green; opacity: 0;" ></circle>
   <circle class="Cambodia" stroke="black" r="10.5" style="fill: blue; opacity: 0;"></circle>
   </g>
</svg>    
    <script src="index2.js"></script>
</body>

</html>

I am running a query that generates a value and based on that value I am picking up associate data as follows.

//this value gets generated dynamically based on previous calculations
const yr = 1998; 
//pick up the associated data that has the same yr
const filt = src.filter(d => d.Year == yr).sort((x, y) => x.Name.localeCompare(y.Name))

Now, based on filt how can I select associated circles only such as '.travCirc>circle.Australia,.Brunei' so that I can dynamically pass on data-driven function for the attributes

For example,

const src = [{        
        "Name": "Australia",
        "Year": 1997,
        "Value": 15.540540540540499
    },
    {
        "Name": "Australia",
        "Year": 1998,
        "Value": 15.540540540540499
    },
    {
        "Name": "Australia",
        "Year": 1999,
        "Value": 22.4489795918367
    },
    
    {
        "Name": "Brunei",
        "Year": 1998,
        "Value": 6.4516129032258096
    },
    {
        "Name": "Brunei",
        "Year": 2017,
        "Value": 9.0909090909090899
    },
    {
        "Name": "Brunei",
        "Year": 2018,
        "Value": 9.0909090909090899
    },    
    {
        "Name": "Cambodia",
        "Year": 1997,
        "Value": 5.8333333333333304
    },
    {
        "Name": "Cambodia",
        "Year": 2017,
        "Value": 5.8333333333333304
    },
    {
        "Name": "Cambodia",
        "Year": 2021,
        "Value": 8.1967213114754092
    }
];
//this value gets generated dynamically based on previous calculations
const yr = 1998; 
//pick up the associated data that has the same yr
const filt = src.filter(d => d.Year == yr).sort((x, y) => x.Name.localeCompare(y.Name))


document.querySelectorAll('.travCirc>circle.Australia,.Brunei')
.forEach
                ((a,i)=>{
                    a.setAttribute('cx',yr/100);
                    a.setAttribute('cy',filt[i].Value*20)   
                    a.style.setProperty('opacity','1');});
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>  
    <div id="container" class="svg-container"></div>
   <svg viewBox="0 0 1280 720">
 
   <g class="travCirc">
   <circle class="Australia" stroke="black" r="10.5" style="fill: red; opacity: 0;"></circle>
   <circle class="Brunei Darussalam" stroke="black" r="10.5" style="fill: green; opacity: 0;" ></circle>
   <circle class="Cambodia" stroke="black" r="10.5" style="fill: blue; opacity: 0;"></circle>
   </g>
</svg>    
    <script src="index2.js"></script>
</body>

I am currently hardcoding as document.querySelectorAll('.travCirc>circle.Australia,.Brunei'), but how can I pass on each of filt.Name values as the class filter for .travCirc>circle

//this value gets generated dynamically based on previous calculations
const yr = 1998; 

//pick up the associated data that has the same yr
const filt = src.filter(d => d.Year == yr).sort((x, y) => x.Name.localeCompare(y.Name))

document.querySelectorAll('.travCirc>circle.Australia,.Brunei')
.forEach
                ((a,i)=>{
                    a.setAttribute('cx',yr/100);
                    a.setAttribute('cy',filt[i].Value*20)   
                    a.style.setProperty('opacity','1');});

Solution

You could use a combination of map and join to add the Names of each array element into the querySelectorAll

const src = [{        
        "Name": "Australia",
        "Year": 1997,
        "Value": 15.540540540540499
    },
    {
        "Name": "Australia",
        "Year": 1998,
        "Value": 15.540540540540499
    },
    {
        "Name": "Australia",
        "Year": 1999,
        "Value": 22.4489795918367
    },
    
    {
        "Name": "Brunei",
        "Year": 1998,
        "Value": 6.4516129032258096
    },
    {
        "Name": "Brunei",
        "Year": 2017,
        "Value": 9.0909090909090899
    },
    {
        "Name": "Brunei",
        "Year": 2018,
        "Value": 9.0909090909090899
    },    
    {
        "Name": "Cambodia",
        "Year": 1997,
        "Value": 5.8333333333333304
    },
    {
        "Name": "Cambodia",
        "Year": 2017,
        "Value": 5.8333333333333304
    },
    {
        "Name": "Cambodia",
        "Year": 2021,
        "Value": 8.1967213114754092
    }
];
//this value gets generated dynamically based on previous calculations
const yr = 1998; 
//pick up the associated data that has the same yr
const filt = src.filter(d => d.Year == yr).sort((x, y) => x.Name.localeCompare(y.Name))


   document.querySelectorAll('.travCirc>circle' + 
   filt.map((a) => '.' + a.Name).join(','))
  .forEach
                ((a,i)=>{
                    a.setAttribute('cx',yr/100);
                    a.setAttribute('cy',filt[i].Value*20)   
                    a.style.setProperty('opacity','1');});
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>  
    <div id="container" class="svg-container"></div>
   <svg viewBox="0 0 1280 720">
 
   <g class="travCirc">
   <circle class="Australia" stroke="black" r="10.5" style="fill: red; opacity: 0;"></circle>
   <circle class="Brunei Darussalam" stroke="black" r="10.5" style="fill: green; opacity: 0;" ></circle>
   <circle class="Cambodia" stroke="black" r="10.5" style="fill: blue; opacity: 0;"></circle>
   </g>
</svg>    
    
</body>

</html>

Answered By – Ryan Wilson

Answer Checked By – Timothy Miller (AngularFixing Admin)

Leave a Reply

Your email address will not be published.