2

I am trying to toggle 'disable' for 'active' CSS class to make the fill property of some SVG change when it is clicked.

I am able to make the first element change correctly but when trying the same with the second and third SVGs it changes the color of the first one inside the first div.

HTML

   <div>
       <svg onclick="toggleColor()" class="home__like disable heart">
           <use xlink:href="img/sprite.svg#icon-heart-full"></use>
       </svg>
   </div>
   <div>
       <svg onclick="toggleColor()" class="home__like disable heart">
           <use xlink:href="img/sprite.svg#icon-heart-full"></use>
       </svg>
   </div>
   <div>
       <svg onclick="toggleColor()" class="home__like disable heart">
           <use xlink:href="img/sprite.svg#icon-heart-full"></use>
       </svg>
   </div>

CSS

.disable {
    fill: #fff;
}

.active {
    fill: $color-primary;
}

JavaScript

function toggleColor() {

    const toggleHeart = document.querySelector('.heart');

    if(toggleHeart.classList.contains('disable')) {
        toggleHeart.classList.remove('disable');
        toggleHeart.classList.add('active');
    } else {
        toggleHeart.classList.remove('active');
        toggleHeart.classList.add('disable');
    }
}
1
  • Did you add the script tag to the document? If so, is it added to the bottom of the page? Commented Nov 3, 2020 at 20:30

2 Answers 2

4

You're using .querySelector() which returns the first element in the document that matches the selector provided.

To get multiple elements, you'd need to use .querySelectorAll() which will return a static NodeList of elements that match the selector. At that point you need to loop through the NodeList and manipulate the classes.

However, since you're trying to target the event-invoking element, I think you could simplify it with a reference to the element.

function toggleColor(el, e) {
    el.classList.toggle('disable');
    el.classList.toggle('active');
}

And change your onclick handler to onclick="toggleColor(this,event);"

Here's a quick snippet:

function toggleColor(el, e) {
    el.classList.toggle('disable');
    el.classList.toggle('active');
}
.disable { color: #ccc }
.active  { color: #0095ee; }
<div>
    <svg class="disable" onclick="toggleColor(this,event);" viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="currentColor" stroke-linecap="round" stroke-linejoin="round" class="css-i6dzq1"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"></path></svg>
 </div>
 <div>
     <svg class="disable" onclick="toggleColor(this,event);" viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="currentColor" stroke-linecap="round" stroke-linejoin="round" class="css-i6dzq1"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"></path></svg>
 </div>
 <div>
     <svg class="disable" onclick="toggleColor(this,event);" viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="currentColor" stroke-linecap="round" stroke-linejoin="round" class="css-i6dzq1"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"></path></svg>
 </div>

Sign up to request clarification or add additional context in comments.

1 Comment

Hey man, just played with your code and worked perfectly. I didn't know about the selector for all same classes and the handler with 'this' and 'event'. I appreciate your time
3

Why is this happening?

Since there are multiple elements with the class of heart, it doesn't know which element to perform the script on! It's like a teacher trying to call Bob, when the class contains 5 people named Bob.

How can we fix this?

You can change the function in onclick, by supplying the element's reference in the script, like so: onclick="myFunction(this)". Now in the javascript, you can do whatever you need with the element.

Try it! Run the example below!

function toggleColor(element) {

    toggleHeart = element;

    if(toggleHeart.classList.contains('disable')) {
        toggleHeart.classList.remove('disable');
        toggleHeart.classList.add('active');
    } else {
        toggleHeart.classList.remove('active');
        toggleHeart.classList.add('disable');
    }
}
.disable {
    color: blue;
}

.active {
    color: red;
}
<!--                      vvv  below we used the "this" keyword which references to the svg element -->
<div onclick="toggleColor(this)" class="disable">
    Click Me!
</div>
<div onclick="toggleColor(this)" class="disable">
    Click Me!
</div>
<div onclick="toggleColor(this)" class="disable">
    Click Me!
</div>
<div onclick="toggleColor(this)" class="disable">
    Click Me!
</div>

1 Comment

Worked with this as well, discovering the many ways to make a simple action work. Thanks a lot!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.