1

How to add and remove class on element using onclick on them.

If I click on 1.st symbol for the first time its class will add and if I click on the symbol a second time its class will be removed

If I click on 2.st symbol for the first time its class will add and if I click on the symbol a second time its class will be removed

e.t.c

It working but only on 1.st element

Ploblem is if i click on the first, second, third or fourth symbol it always changes the first one

<!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>
        <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Roboto&display=swap" rel="stylesheet">
        <link rel="stylesheet"href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,[email protected],100..700,0..1,-50..200" />
        <link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined" rel="stylesheet" />
    
        <link rel="stylesheet" href="style.css">
    
        <script src="script.js"></script>
    
    </head>
    <body>
        <Section class="s1">Smartphone <span class="material-symbols-outlined"> <span id="id1" class="favorite" onclick="favourite(this);">favorite </span></span></Section>
        <Section class="s2">Laptop <span class="material-symbols-outlined"> <span id="id1" class="favorite" onclick="favourite(this);">favorite </span></span></Section>
        <Section class="s3">Keyboard <span class="material-symbols-outlined"> <span id="id1" class="favorite" onclick="favourite(this);">favorite </span></span></Section>
        <Section class="s4">Monitor <span class="material-symbols-outlined"> <span id="id1" class="favorite" onclick="favourite(this);">favorite </span></span></Section>
    
    
    </body>
    
    </html>
.favorite{
    color:black;
    font-weight: 1000;
}
.favorite:hover{
    color:red;
        
}
.fill{
    font-variation-settings:
    'FILL' 1;
}

var i=0;
function favourite(elmnt){
    i++;
    var test = document.getElementById(elmnt.id);
    if (i == 1) {
        test.style.color = "red";  
        test.classList.add('fill'); //add fill in class
        
    }
    
    if (i == 2) {
        test.style.color = "black";  
        test.classList.remove('fill'); //remove fill in class

        i =0;
    }
}
4
  • look into classList.toggle. You also proberly also want to look into event delegation. Commented Mar 16, 2023 at 17:08
  • 2
    you problem is that ids are unique, you can't have same id for all elements Commented Mar 16, 2023 at 17:12
  • You don’t need the ids since the needed element is already passed in to the function. Do your operations using elmnt instead of test Commented Mar 16, 2023 at 17:16
  • Both with toggle and with add it works the same, i.e. assigns the class only to the icon in the first section, even when I click on the icon, e.g. from the fourth section Commented Mar 16, 2023 at 17:17

3 Answers 3

1

To add and remove classes on elements using onclick, you can modify your code to use the classList.toggle() method, which will add the class if it doesn't exist, or remove it if it does. You can also simplify your code by using a single function to handle all elements.

Here's an example code snippet that should accomplish what you're trying to do:

// Get all elements with class "favorite"
var favorites = document.querySelectorAll(".favorite");

// Add onclick event listener to each element
favorites.forEach(el => el.addEventListener("click", toggleFavorite));

function toggleFavorite() {
  // Toggle the "fill" class on the clicked element
  this.classList.toggle("fill");

  // Toggle the color between black and red using ternary operator
  this.style.color = (this.style.color === "black") ? "red" : "black";
}

This code loops through all elements with class "favorite" and adds an onclick event listener to each one. When an element is clicked, the toggleFavorite() function is called.

Inside the function, the classList.toggle() method is used to add or remove the "fill" class from the clicked element. The color of the element is also toggled between black and red by checking the current value of the style.color property.

With this code, clicking on any element with class "favorite" should toggle the "fill" class and change the color of the element.

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

3 Comments

use a ternary conditional operator instead of if/else. Also use forEach instead a for loop: favorites.forEach(el => el.addEventListener('click', toggleFavorite));
@tacoshy While a ternary operator would do nicely, it's a form of optimization that isn't necessary. Optimization should always follow getting the code to work.
@ScottMarcus While I agree, I believe it should be mentioned. If you fix and improve a code, you should improve it as well as possible (in a limited scope). This will give beginners the knowledge to improve their coding skills instead of just fixing their errors.
0

This part of the code var test = document.getElementById(elmnt.id); is unnecesary, you already passed the element with your favourite(this) function.

let i=0;
function favourite(elmnt){
    i++;//increment
    if (i == 1) {
        elmnt.style.color = "red";  
        elmnt.classList.add('fill'); //add fill in class
    }
    if (i == 2) {
        elmnt.style.color = "black";  
        elmnt.classList.remove('fill'); //remove fill in class
        i = 0;//resets
    }
}
.favorite{
    color:black;
    font-weight: 1000;
}
.favorite:hover{
    color:red;
        
}
.fill{
    font-variation-settings:
    'FILL' 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>
        <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Roboto&display=swap" rel="stylesheet">
        <link rel="stylesheet"href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,[email protected],100..700,0..1,-50..200" />
        <link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined" rel="stylesheet" />
    
        <link rel="stylesheet" href="style.css">
    
        <script src="script.js"></script>
    
    </head>
    <body>
        <Section class="s1">Smartphone <span class="material-symbols-outlined"> <span id="id1" class="favorite" onclick="favourite(this);">favorite </span></span></Section>
        <Section class="s2">Laptop <span class="material-symbols-outlined"> <span id="id2" class="favorite" onclick="favourite(this);">favorite </span></span></Section>
        <Section class="s3">Keyboard <span class="material-symbols-outlined"> <span id="id3" class="favorite" onclick="favourite(this);">favorite </span></span></Section>
        <Section class="s4">Monitor <span class="material-symbols-outlined"> <span id="id4" class="favorite" onclick="favourite(this);">favorite </span></span></Section>
    
    
    </body>
    
    </html>

Comments

0

Here is an example that toggles classes to do what you ask when you click the hearts. Slight format change just to enhance the example; the script and classes it toggles is what you want to focus on here.

  • Cleaned up the invalid HTML by removal of all the id="id1" since they are not really need here.
  • Moved the onclick="favourite(this); to a proper event handler so removed those
  • Change all the similar class="s1" to class="section-fav" to allow simpler CSS for a style (not part of the answer really)
  • Not part of question but changed the hover color to show the "red" different when it has been clicked previously. color: #FF0000AA; and the slightly lighter grey on the unclicked to not stick out so much.

Credit to some code I borrowed for part of this: https://stackoverflow.com/a/57127781/125981

const toggleCSSclasses = (el, tc) => {
  tc.map(cls => el.classList.toggle(cls));
};
const toggles = document.querySelectorAll('.favorite')
  .forEach(fav => {
    const toggleMe = ["fill", "love-me"];
    fav.addEventListener("click", (event) => {
      toggleCSSclasses(event.target, toggleMe);
    });
  });
.section-fav {
  display: grid;
  place-items: center;
}

.favorite {
  color: #00000088;
  font-weight: 1000;
}

.favorite:hover {
  color: #FF0000AA;
}

.fill {
  font-variation-settings: 'FILL' 1;
}

.love-me {
  color: #FF0000;
}
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Roboto&display=swap" rel="stylesheet">
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,[email protected],100..700,0..1,-50..200" />
  <link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined" rel="stylesheet" />
</head>

<body>
  <Section class="section-fav">Smartphone<span class="material-symbols-outlined"><span class="favorite">favorite</span></span>
  </Section>
  <Section class="section-fav">Laptop<span class="material-symbols-outlined"><span class="favorite">favorite</span></span>
  </Section>
  <Section class="section-fav">Keyboard<span class="material-symbols-outlined"><span class="favorite">favorite</span></span>
  </Section>
  <Section class="section-fav">Monitor<span class="material-symbols-outlined"><span class="favorite">favorite</span></span>
  </Section>
</body>

Comments

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.