How to change the color of only the clicked element?

Asked

Viewed 332 times

2

This question is similar to change color only of clicked element the difference is that Jquery is used and I need pure JS, I have some elements <summary> and when I click on the element <summary> current it changes color in the red case when I click on another element <summary> (or to stop clicking on the element <summary> current) the previous (that was the current) return with the original color (black):

const summary = document.querySelectorAll('summary');

for (let i = 0; i < summary.length; i++) {
    summary[i].onclick = () => {
        summary[i].style.color = 'red';
    }
}
<html>
<body>
    <details>
        <summary>Title 1</summary>
        <ul>
            <li>Content 1</li>
            <li>Content 2</li>
            <li>Content 3</li>
        </ul>
    </details>
    <details>
        <summary>Title 2</summary>
        <ul>
            <li>Content 1</li>
            <li>Content 2</li>
            <li>Content 3</li>
        </ul>
    </details>
</body>
</html>

The elements <summary> until changes color only if you click on all both will have the color and I do not know how to check the element <summary> that was clicked earlier so that it changes to the original color or in case for me check the elements that were clicked was easy, but and the ones that were not?.

2 answers

2


You can do this with classes. Adding and removing with el.classList.add( and .remove(. But since you’re doing it directly in the element property what you’re missing is, within a loop, reset values at each click.

The idea is to create a variable that remembers the element that receives the onclick and then run a for with all elements inside the click callback. Inside this for check when the sumary[j] is the same as the el that has been clicked and you give it the right color.

Example:

const summary = document.querySelectorAll('summary');

for (let i = 0; i < summary.length; i++) {
  const el = summary[i];
  el.onclick = () => {
    for (let j = 0; j < summary.length; j++) {
      const color = summary[j] === el ? 'red' : 'inherit';
      summary[j].style.color = color;
    }
  }
}
<html>

<body>
  <details>
    <summary>Title 1</summary>
    <ul>
      <li>Content 1</li>
      <li>Content 2</li>
      <li>Content 3</li>
    </ul>
  </details>
  <details>
    <summary>Title 2</summary>
    <ul>
      <li>Content 1</li>
      <li>Content 2</li>
      <li>Content 3</li>
    </ul>
  </details>
</body>

</html>

  • Perfect friend! was just that, thank you very much helped.

  • Only it is being compared all the elements or one in particular?

  • @felipecardozo at each click the code goes through all the elements and changes the color of each one. Inside the loop it checks if the iterated item is what was clicked and to that specific gives the color red

1

An alternative (with limitations, we will already see below) is, whenever you click on a summary, look for if there is already a red (and if there is, change the color back to the original), and then change the color of the element clicked to red:

document.querySelectorAll('summary')
    .forEach(s => s.addEventListener('click', function(event) {
        const vermelhoAtual = document.querySelector('summary[style="color: red;"]');
        if (vermelhoAtual) vermelhoAtual.style.color = 'inherit';
        s.style.color = 'red';
    })
);
<html>
<body>
    <details>
        <summary>Title 1</summary>
        <p>Content 1</p>
    </details>
    <details>
        <summary>Title 2</summary>
        <p>Content 2</p>
    </details>
    <details>
        <summary>Title 3</summary>
        <p>Content 3</p>
    </details>
    <details>
        <summary>Title 4</summary>
        <p>Content 4</p>
    </details>
</body>
</html>

How the idea is that only one summary at a time can be red, would not need to make a loop by all, as suggested to another answer (which is a more general alternative, if you had the possibility of having more than one red element, then it would make more sense to go through them all and change the color one by one - although you could just change querySelector for querySelectorAll in the above code, to search only for red elements).

Anyway, if it is guaranteed that only one element will be red at a time, just search for it using the selector 'summary[style="color: red;"]', and change the color if it exists.


But as already said at the beginning, this solution is somewhat limited.

The limitation is that this only works if the element has no other styles inline. For example, if you have style="font-weight: bold; color: red;, or even if you have style="color: red" (without the semicolon), the selector no longer takes the element.

I could even get around with document.querySelectorAll('summary[style*="color: red"]') (note the *= instead of just =, see here some examples and the documentation for more details), but then it might be better to use classes and search for the elements that have that class, for example.

Another alternative is to store the red element, so we don’t need to pick it up all the time (again, assuming you can’t have more than one red at the same time):

var vermelhoAtual = undefined;

document.querySelectorAll('summary')
    .forEach(s => s.addEventListener('click', function(event) {
        if (s == vermelhoAtual) return; // cliquei no mesmo elemento, não precisa fazer nada
        if (vermelhoAtual) vermelhoAtual.style.color = 'inherit';
        s.style.color = 'red';
        vermelhoAtual = s;
    })
);
<html>
<body>
    <details>
        <summary>Title 1</summary>
        <p>Content 1</p>
    </details>
    <details>
        <summary>Title 2</summary>
        <p>Content 2</p>
    </details>
    <details>
        <summary>Title 3</summary>
        <p>Content 3</p>
    </details>
    <details>
        <summary>Title 4</summary>
        <p>Content 4</p>
    </details>
</body>
</html>

  • 1

    Good, reply! I liked the first possibility.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.