0

Quick question here, I encountered this problem today while practicing some JS. I wanted to create a basic prototype to loop through a "div" background-color array on click, but I realized that assigning the element property to a variable (instead of using the event target) impedes me to change the actual values.

This is the JS code:

let colors = ["blue", "yellow", "orange", "red"]
let n = 1;

document.querySelectorAll('div').forEach(occurence => {
    occurence.addEventListener('click', (e) => {
        let classes = e.target.className;
        classes = colors[n];
        n++;
        console.log(classes);
        if (n >= 4) {n = 0;}
    });
});

So, changing the actual e.target.className works just fine, but trying to change the assigned "classes" variable does nothing. I feel like this may be a matter of specificity, or JS being unable to access the actual property values, or some akin beginner mistake.

Ferpalaciosd
  • 107
  • 1
  • 11
  • You're saving the className string; if you want to set the property, use `e.target.className = colors[n];`. – mykaf Aug 15 '22 at 14:11
  • Does this answer your question? [Setting a variable equal to another variable](https://stackoverflow.com/questions/50840293/setting-a-variable-equal-to-another-variable) – Ivar Aug 15 '22 at 14:14

3 Answers3

2

e.target.className passes by value when you have let classes = e.target.className, so classes contains a copy of its data. Changing classes just changes the copy, rather than what's stored in e.target.classname.

Addison Schmidt
  • 374
  • 1
  • 7
  • Thanks! I understood declaring variables more as a way to "alias" or shorthand commonly used formulas, but I guess that's not the way that it works. – Ferpalaciosd Aug 17 '22 at 13:28
1

Actually, you are not changing the value of e.target.className. What you do, is assigning the value of e.target.className to the variable/let-binding classes. To assign one of the color values to the className property, the assignment has to be the other way around:

e.target.className = colors[n];
David
  • 3,552
  • 1
  • 13
  • 24
0

let classes = e.target.className will assign the current string value of className to classes. And while you can assign a new colour value to classes that won't assign the new colour value to the className property of the element. For that you want to explicitly assign it: e.target.className = colors[i].

You may also want to remove the need to add a event listener to all the elements. Event delegation allows you to add one listener to a parent element which captures events from its child elements as they "bubble up" the DOM.

Here's an over-wrought example:

const colors = ['blue', 'yellow', 'orange', 'red'];

// Cache the elements first, and add a listener to
// the container
const counter = document.querySelector('.index');
const container = document.querySelector('.container');
container.addEventListener('click', handleClick);

let count = 0;

function handleClick(e) {

  // Check to see if the element that was clicked
  // was a div element
  if (e.target.matches('.container div')) {

    // Update the counter element, the `className` value,
    // and the `textContent of the "box", and then update
    // the count value
    counter.textContent = `Color index: ${count}`;
    e.target.className = colors[count];
    e.target.textContent = colors[count];
    count = count < colors.length - 1 ? ++count : 0;
  }
}
.container { display: grid; gap: 0.4em; grid-template-columns: repeat(2, 50px); }
.container div { display: flex; justify-content: center; align-items: center; height: 50px; width: 50px; border: 1px solid lightgray; }
.container div:hover { cursor: pointer; border: 1px solid darkgray; }
.blue { background-color: lightblue; }
.yellow { background-color: #ffff00; }
.orange { background-color: darkorange; }
.red { background-color: red; }
.index { margin-top: 0.5em; }
<div class="container">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>
<div class="index">Color index:</div>
Andy
  • 61,948
  • 13
  • 68
  • 95