-1

I'm building on a recent question I asked: Change SVG path color using data in JavaScript function

I have an object:

var body_data = { head: 10, left-shoulder: 20, right-shoulder: 40, left-arm: 60, right-arm: 90, left-hand: 100, right-hand: 25, chest: 50, stomach: 15, left-leg: 20, right-leg: 17, left-foot: 42, right-foot: 100}

I also have an ifelse statement that assigns color based on value:

    var color;
    if (value < 25) {
        color = "blue";
    } else if (value < 50) {
        color = "green";
    } else {
        color = "red";
    }

I'd like to apply a function where I loop through each key-value pair, changing the color of the element based on its color value

document.getElementById(key);
if (element) {
        element.style.fill = color;
}

How do I properly use for....in to loop through my object, where the keys are the IDs of elements and the values the color?

MayaGans
  • 1,815
  • 9
  • 30

3 Answers3

1

Check out https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in

Example:

const object = {a: 1, b: 2, c: 3};

for (const property in object) {
  console.log(`${property}: ${object[property]}`);
}

// expected output:
// "a: 1"
// "b: 2"
// "c: 3"

For your example you would use something like:

for (key in body_data){
    const element = document.getElementById(key);
    if (body_data[key] < 25){
        element.style.fill = ‘Blue’;
    } else if (...)
    ...
    //etc.
}

Full minimal verifiable example here: https://codepen.io/Alexander9111/pen/qBdbVNX

output:

enter image description here

JS:

const body_data = {
  'head': 10,
  'left-shoulder': 20,
  'right-shoulder': 40,
  'left-arm': 60,
  'right-arm': 90,
  'left-hand': 100,
  'right-hand': 25,
  'chest': 50,
  'stomach': 15,
  'left-leg': 20,
  'right-leg': 17,
  'left-foot': 42,
  'right-foot': 100
}

const NS = "http://www.w3.org/2000/svg";
const svg = document.querySelector('svg');
let y_offset = 0;

for (const key in body_data){
    const rect = document.createElementNS(NS, 'rect');
    rect.id = key;
    rect.setAttribute('x', 100);
    rect.setAttribute('y', y_offset);
    const text = document.createElementNS(NS, 'text');
    text.setAttribute('x', 0);
    text.setAttribute('y', y_offset);
    text.setAttribute('alignment-baseline', "hanging");
    y_offset += 10;
    text.textContent = key;
    svg.appendChild(text);
    svg.appendChild(rect);
}

for (const key in body_data){
    const element = document.getElementById(key);
    if (body_data[key] < 25){
        element.style.fill = "Blue";
    } else if (body_data[key] < 50) {
        element.style.fill = "green";
    } else {
        element.style.fill = "red";
    }
}
Alex L
  • 4,168
  • 1
  • 9
  • 24
0

You can loop through an object and get the keys and values like this:

for (let key in body_data) {
  let value = body_data[key];
  // some other stuff
}

I haven't tested it, but something like this should work:

const body_data = {
  'head': 10,
  'left-shoulder': 20,
  'right-shoulder': 40,
  'left-arm': 60,
  'right-arm': 90,
  'left-hand:' 100,
  'right-hand': 25,
  'chest': 50,
  'stomach': 15,
  'left-leg': 20,
  'right-leg': 17,
  'left-foot': 42,
  'right-foot': 100
}

const assignColor = (el, value) => {
  if (value < 25) {
      el.style.fill= "blue";
  } else if (value < 50) {
      el.style.fill= "green";
  } else {
      el.style.fill= "red";
  }
}

for (let key in body_data) {
  const el = document.getElementById(key);
  assignColor(el, body_data[key]);
}
Tomer Singal
  • 1
  • 1
  • 1
0

Apply function to each key-value pair in object

Below I provide a solution that first modifies the data (creating a new object) and then applies to dom.

const colorFromValue = (key, value)=>{
    let color;
    if (value < 25) {
        color = "blue";
    } else if (value < 50) {
        color = "green";
    }else{
        color = "red";    
    }
    return [key, color];
}

const mapObject = (o, mapperFunc)=>Object.fromEntries(
    Object.entries(o).map(([key,value])=>mapperFunc(key, value)));

var body_data = { 
    head: 10, 
    "left-shoulder": 20, 
    "right-shoulder": 40, 
    "left-arm": 60, 
    "right-arm": 90, 
    "left-hand": 100, 
    "right-hand": 25, 
    chest: 50, 
    stomach: 15, 
    "left-leg": 20, 
    "right-leg": 17, 
    "left-foot": 42, 
    "right-foot": 100};


let newObject = mapObject(body_data, colorFromValue)

Contents of newObject:

{
    "head": "blue",
    "left-shoulder": "blue",
    "right-shoulder": "green",
    "left-arm": "red",
    "right-arm": "red",
    "left-hand": "red",
    "right-hand": "green",
    "chest": "red",
    "stomach": "blue",
    "left-leg": "blue",
    "right-leg": "blue",
    "left-foot": "green",
    "right-foot": "red"
}

To change the color of dom elements based on ids you can again call again mapObject or more appropriately use a forEach on the entries of new object like below:

Object.entries(newObject).forEach(([key, value])=>{
    document.getElementById(key).style.fill = value;
});

Note: The above solution decouples data from dom manipulation and also nests the iteration part to a resuable function.

Marinos An
  • 9,481
  • 6
  • 63
  • 96