Is there a way to switch the classList between various buttons using a single JavaScript function?

I'm currently developing a straightforward add to cart container that also has the ability to toggle between different product sizes.

However, I am facing difficulties in achieving this functionality without having to create separate functions for each button.

Below is the JavaScript code snippet:

const sizeBtn = document.getElementById("sizebutton");
const sizeBtnTwo = document.getElementById("sizebutton1");
const sizeBtnThree = document.getElementById("sizebutton2");

sizeBtn.addEventListener('click', sizeBtnActive);
sizeBtnTwo.addEventListener('click', sizeBtnActive);
sizeBtnThree.addEventListener('click', sizeBtnActive);

function sizeBtnActive () {
  sizeBtn.classList.toggle('active');
  sizeBtnTwo.classList.toggle('active');
  sizeBtnThree.classList.toggle('active');
}

Including CSS styles for better understanding:

.size-btn.faded,
.size-btn.active {
  font-size: 12px;
  color: #c2c2c2;
  background-color: #f0f0f0;
  width: 38px;
  height: 42px;
  border-radius: 0.5rem;
  border: none;
  margin-right: 10px;
  margin-bottom: 35px;
  cursor: none;
}

.size-btn.active {
  color: #ffff;
  background-color: #000000;
  box-shadow: 1px 2px 10px rgba(0, 0, 0, 0.3);
  transition: 1.5s ease;
  cursor: pointer;
}

If you can provide any guidance or suggestions on how to improve this code, it would be highly appreciated.

I have attempted to find solutions by researching similar issues online, but none of them have been effective so far. My goal is to toggle between each button individually without activating all of them at once.

Answer №1

One way to simulate a radio button group is by creating a button group and toggling a data attribute on the active button.

Simply add a global listener for the button group and log the value after each change.

// Global button group listener
window.addEventListener('click', (e) => {
  if (e.target.closest('.button-group')) {
    toggleButtonGroup(e.target);
  }
});

// Log the new value after each change
document.querySelector('.size').addEventListener('click', (e) => {
  setTimeout((buttonGroup) => {
    console.log('Value:', getButonGroupValue(buttonGroup));
  }, 100, e.currentTarget);
});

// Toggle active state of buttons
function toggleButtonGroup(button) {
  const buttonGroup = button.closest('.button-group');
  buttonGroup.querySelectorAll('button').forEach((currButton) => {
    if (currButton === button && !currButton.dataset.active) {
      currButton.dataset.active = true;
    } else {
      delete currButton.dataset.active;
    }
  });
}

// Value accessor
function getButonGroupValue(buttonGroup) {
  return buttonGroup?.querySelector('[data-active]')?.value;
}
.button-group {
  display: inline-flex;
  border: thin solid grey;
  width: fit-content;
}

.button-group button {
  background: #CCC;
  border: none;
  min-width: 2.5rem;
  padding: 0.25rem;
}

.button-group button:hover {
  background: #DDA;
  cursor: pointer;
}

.button-group button[data-active] {
  background: #FFF;
}

.button-group button[data-active]:hover {
  background: #FFA;
}
<label>Size: </label>
<div class="button-group size">
  <button type="button" value="xs">XS</button>
  <button type="button" value="s">S</button>
  <button type="button" value="m" data-active>M</button>
  <button type="button" value="l">L</button>
  <button type="button" value="xl">XL</button>
  <button type="button" value="xxl">XXL</button>
</div>

Answer №2

I am looking to create a toggle functionality where each button can be activated individually, without activating all at once.

The most efficient way to achieve this is by assigning a common class name to all the buttons first.

<button class="btn"></button>
<button class="btn"></button>
<button class="btn"></button>

Then, we can select all these buttons using querySelectorAll and use a forEach loop to deactivate all of them initially, and then activate only the selected one:

const btns = document.querySelectorAll(".btn")

function disableAllButtons() {
    btns.forEach(btn => {
        btn.classList.remove("active")
    })
}

btns.forEach(btn => {
    btn.addEventListener(() => {
        disableAllButtons()

        btn.classList.add("active")
    })
})

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Ensure that all floating divs have uniform height

How can I ensure that two divs placed side by side will always have the same height, even when one of them changes based on content, using only CSS? I created a fiddle to demonstrate. I want both the red and blue divs to have equal heights... http://jsfi ...

What methods can be used to ensure a required minimum delay time between function executions?

For my node function, I am aiming for a specific execution delay of around 5 seconds. The minimum delay needs to be implemented within the function itself, not externally, so external users are unaware of the delay. Therefore, I cannot rely on modules l ...

Having a flash video load on a new page in the same position as it was on the previous page

On my website, I have a subtle flash video playing in the background that loops every 30 seconds. It's not necessary for navigation, just a nice visual touch. However, every time a new page is loaded, the video restarts from the beginning. I'm l ...

Issue with res.redirect not functioning as expected

I am having some difficulty with the use of res.redirect() in my express application. After searching through other questions, I haven't found a solution that directly addresses my specific issue or is detailed enough to be useful. app.get(/\d& ...

[server-auth]: The `useSession` function is required to be enclosed within a <SessionProvider /> component to avoid the error occurring in the current JavaScript file

While trying to validate authentication by following the next-auth documentation, I encountered an error stating "[next-auth]: useSession must be wrapped in a SessionProvider". I am using GitHub credentials for the validations. Here is my code: Currently ...

Can you explain the distinction between bodyparser.urlencoded and bodyparser.json?

I'm a bit confused about the use of bodyparser. Why is it necessary when we can simply use json.stringify (to convert an object to a string) and json.parse (to convert JSON to an object)? Is it because by using app.use() with bodyparser, the middlewa ...

Aligning the Twitter and Facebook buttons

Issue with Social Media Button Alignment I'm encountering a problem with aligning Twitter and Facebook buttons on my website. The alignment seems to be off and I need some help fixing it. Code Snippet html: <span id="social"> ...

Using Javascript to create a radio button group

Is there a way to trigger an alert message when all radio buttons are checked as 'no'? I currently am only able to check each radio button individually. //The method I currently know $('#attraction1').change( function(){ if ($(this ...

responsive mega menu with multiple levels in Bootstrap 3

I specialize in creating mega menu navigation using Bootstrap 3. HTML: <div class="container"> <nav class="navbar navbar-default"> <div class="navbar-header"> <button class="navbar-toggle" type="button" data- ...

Is VueJS2 using the computed property/method to modify Vue data?

My form in Vue is almost complete, but I'm facing an issue with an array that seems to be affecting my Vue.data object directly. Here's the situation: In my code, I have a method called getParams() which returns an object containing all the data ...

What is the process for incorporating a custom button for selecting the date and closing the calendar in bootstrap-datepicker?

I successfully coded a simple project, but I'm struggling to figure out how to add a custom button to the bootstrap-datepicker. <!DOCTYPE html> <html> <head> <title>JS</title> <link rel="stylesheet" href="http ...

What are some effective ways to integrate the WordPress API with ReactJS?

Wordpress recently introduced an API that allows you to make HTTP requests without worrying about routes, as the backend is handled for you. I'm curious, how can I integrate ReactJs with Wordpress API? This has been a frustrating challenge for me be ...

How can you ensure a script runs only once another script has completed its execution?

Consider the following code snippet I created to illustrate my idea: var extract = require("./postextract.js"); var rescore = require("./standardaddress.js"); RunFunc(); function RunFunc() { extract.Start(); console.log("Extraction complete"); ...

Choosing a single radio button value within a nested ng-repeat loop in AngularJS

Help needed with selecting only one radio button value in nested ng-repeat. Please review the source code and suggest any potential mistakes. <form ng-submit="save()"> <div ng-repeat="x in surveyLst"> <div class="row"> < ...

dividing values for future angular use

Within my code, I have the following snippet: color: {{item.color}} This setup functions well when dealing with single items. However, there are instances where I encounter a value such as: white|black Is there a way to separate these values into indiv ...

The footer menu fails to glide upwards

I designed a top menu for my website that includes 2 key features: Sticky navigation bar when scrolling Slide toggle navbar You can view the demo here: JSBIN However, I am facing 2 issues: When the page is at the top and the menu is in its default pos ...

Retrieve the file from Amazon S3 and download it

I'm having an issue with downloading a file from a directory outside of the root. Whenever I try, it defaults to looking in the root directory. I need users to be able to download these files on my site. The file was initially uploaded to Amazon S3 a ...

I encountered an issue with the "props map error" while working on this

Hello everyone, I am currently in the process of learning React by creating a toggle button for switching between light and dark modes. However, I have encountered an issue when attempting to map through the state and display the data in card format (altho ...

Press the jQuery button and inform me once it has been activated

My jQuery code is set up to automatically press buttons for me every second. Occasionally, some pages take a long time to load until the button appears. Here is the current code I am using: (function($){ setInterval(function(){ $('.play-b ...

Are you familiar with using double conditional rendering in a React application?

Currently, I am in the process of creating a small clothing store application using React as a way to expand my skills. One feature I have implemented is a filter by price section. However, I am looking for a solution to handle cases where no items fall wi ...