Ensure that only one button from the collection is activated

One of the features on my website includes 3 blocks with buttons. These buttons trigger a change in the displayed picture when clicked. However, it is crucial to ensure that when a new track is activated, the previous button returns to its original state.

https://i.sstatic.net/AFsS0.png

let buttons = document.querySelectorAll('.btn-wrapper');

buttons.forEach(function(button) {
  button.addEventListener('click', function(e) {

    button.querySelector('.play__btn').classList.toggle('play__btn-hidden');
    button.querySelector('.pause__btn').classList.toggle('pause__btn-active');

  })
})
.flex {
  display: flex;
  align-items: center;
}

.card__title {
  margin-right: 20px;
}

.btn {
  width: 17px;
  height: 17px;
  cursor: pointer;
}

.play__btn-hidden {
  display: none;
}

.pause__btn {
  display: none;
}

.pause__btn-active {
  display: block;
}
<div class="cards">
  <div class="card flex">
    <h4 class="card__title">Track 01</h4>
    <div class="btn-wrapper">
      <img src="https://cdn-icons-png.flaticon.com/512/153/153752.png" alt="" class="play__btn btn">
      <img src="https://cdn-icons-png.flaticon.com/512/1214/1214679.png" alt="" class="pause__btn btn">
    </div>
  </div>
  <div class="card flex">
    <h4 class="card__title">Track 02</h4>
    <div class="btn-wrapper">
      <img src="https://cdn-icons-png.flaticon.com/512/153/153752.png" alt="" class="play__btn btn">
      <img src="https://cdn-icons-png.flaticon.com/512/1214/1214679.png" alt="" class="pause__btn btn">
    </div>
  </div>
  <div class="card flex">
    <h4 class="card__title">Track 03</h4>
    <div class="btn-wrapper">
      <img src="https://cdn-icons-png.flaticon.com/512/153/153752.png" alt="" class="play__btn btn">
      <img src="https://cdn-icons-png.flaticon.com/512/1214/1214679.png" alt="" class="pause__btn btn">
    </div>
  </div>
</div>

Answer №1

Try this alternative method to manage it:

const buttons = document.querySelectorAll('.button');
buttons.forEach(function(item) {
  item.addEventListener('click', function(event) {
    buttons.forEach((element) => element !== event.target && element.classList.remove('active'));
    event.target.classList.toggle('active');
  })
})
.flex {
  display: flex;
  align-items: center;
}

.card__title {
  margin-right: 20px;
}

.button {
  width: 17px;
  height: 17px;
  cursor: pointer;
  background-size: 17px 17px;
}

.active {
  background-image: url("https://cdn-icons-png.flaticon.com/512/153/153752.png");
}
<div class="cards">
  <div class="card flex">
    <h4 class="card__title">Track 01</h4>
    <div class="button active"></div>
  </div>
  <div class="card flex">
    <h4 class="card__title">Track 02</h4>
    <div class="button"></div>
  </div>
  <div class="card flex">
    <h4 class="card__title">Track 03</h4>
    <div class="button"></div>
  </div>
</div>

Answer №2

I made some adjustments to your code:

const buttons = document.querySelectorAll(".button-container");

const resetAllButtons = () => {
  buttons.forEach((btn) => {
    // reset all buttons
    btn.querySelector(".play-button").classList.remove("play-button-hidden");
    btn.querySelector(".pause-button").classList.remove("pause-button-active");
  });
};

const togglePlayStatus = (classList, buttonContainer) => {
  // toggle the state of the button being clicked
  if (classList.contains("play-button")) {
    classList.add("play-button-hidden");

    buttonContainer.querySelector(".pause-button").classList.add("pause-button-active");
  } else {
    classList.remove("pause-button-active");
    buttonContainer.querySelector(".play-button").classList.remove("play-button-hidden");
  }
};

const onClick = (e) => {
  const buttonContainer = e.target.parentElement;
  const classList = e.target.classList;

  resetAllButtons();
  togglePlayStatus(classList, buttonContainer);
};

buttons.forEach(function(element) {
  element.addEventListener("click", (e) => onClick(e));
});
.flex {
  display: flex;
  align-items: center;
}

.card__title {
  margin-right: 20px;
}

.button {
  width: 17px;
  height: 17px;
  cursor: pointer;
}

.play-button-hidden {
  display: none;
}

.pause-button {
  display: none;
}

.pause-button-active {
  display: block;
}
<div class="cards">
  <div class="card flex">
    <h4 class="card__title">Track 01</h4>
    <div class="button-container">
      <img src="https://cdn-icons-png.flaticon.com/512/153/153752.png" alt="" class="play-button button" />
      <img src="https://cdn-icons-png.flaticon.com/512/1214/1214679.png" alt="" class="pause-button button" />
    </div>
  </div>
  <div class="card flex">
    <h4 class="card__title">Track 02</h4>
    <div class="button-container">
      <img src="https://cdn-icons-png.flaticon.com/512/153/153752.png" alt="" class="play-button button" />
      <img src="https://cdn-icons-png.flaticon.com/512/1214/1214679.png" alt="" class="pause-button button" />
    </div>
  </div>
  <div class="card flex">
    <h4 class="card__title">Track 03</h4>
    <div class="button-container">
      <img src="https://cdn-icons-png.flaticon.com/512/153/153752.png" alt="" class="play-button button" />
      <img src="https://cdn-icons-png.flaticon.com/512/1214/1214679.png" alt="" class="pause-button button" />
    </div>
  </div>
</div>

Here's what's going on in the code:

  1. We reset ALL buttons to their original play state.
  2. After resetting all buttons, we toggle the state of the button that was clicked. This is done by using e.target.parentElement to target the button container and then selecting the buttons inside it to add or remove classes accordingly.

I hope this explanation clarifies things for you!

Answer №3

One way to achieve this is as follows:

function reset() {

 document.querySelectorAll('.play__btn').forEach(function (element) {
element.classList.remove('play__btn-hidden');
});

document.querySelectorAll('.pause__btn').forEach(function (element){
element.classList.remove('pause__btn-active');
});
}

let btn = document.querySelectorAll('.btn-wrapper');

btn.forEach(function(element) {
  element.addEventListener('click', function(e) {

    reset();
element.querySelector('.play__btn').classList.toggle('play__btn-hidden');
    element.querySelector('.pause__btn').classList.toggle('pause__btn-active');

  })
})
.flex {
  display: flex;
  align-items: center;
}

.card__title {
  margin-right: 20px;
}

.btn {
  width: 17px;
  height: 17px;
  cursor: pointer;
}

.play__btn-hidden {
  display: none;
}

.pause__btn {
  display: none;
}

.pause__btn-active {
  display: block;
}
<div class="cards">
  <div class="card flex">
    <h4 class="card__title">Track 01</h4>
    <div class="btn-wrapper">
      <img src="https://cdn-icons-png.flaticon.com/512/153/153752.png" alt="" class="play__btn btn">
      <img src="https://cdn-icons-png.flaticon.com/512/1214/1214679.png" alt="" class="pause__btn btn">
    </div>
  </div>
  <div class="card flex">
    <h4 class="card__title">Track 02</h4>
    <div class="btn-wrapper">
      <img src="https://cdn-icons-png.flaticon.com/512/153/153752.png" alt="" class="play__btn btn">
      <img src="https://cdn-icons-png.flaticon.com/512/1214/1214679.png" alt="" class="pause__btn btn">
    </div>
  </div>
  <div class="card flex">
    <h4 class="card__title">Track 03</h4>
    <div class="btn-wrapper">
      <img src="https://cdn-icons-png.flaticon.com/512/153/153752.png" alt="" class="play__btn btn">
      <img src="https://cdn-icons-png.flaticon.com/512/1214/1214679.png" alt="" class="pause__btn btn">
    </div>
  </div>
</div>

Answer №4

Here's a simplified version of your code where you can change visibility without switching classes on both elements:

To achieve this, you can filter the buttons collection for the active one and remove it.

let btn = document.querySelectorAll('.btn-wrapper');
const activeClass = 'active'

btn.forEach(function(element) {
  element.addEventListener('click', function(e) {
    element.classList.toggle(activeClass)
    const activeBtns = Array.from(btn).filter(el => el != element && el.classList.contains(activeClass))
    if (activeBtns.length) {
      activeBtns.forEach(el => {
            el.classList.remove(activeClass)
      })
    }
 })
})
.flex {
  display: flex;
  align-items: center;
}

.card__title {
  margin-right: 20px;
}

.btn {
  width: 17px;
  height: 17px;
  cursor: pointer;
}

.btn-wrapper .play__btn {
  display: block;
}

.btn-wrapper .pause__btn {
  display: none;
}

.btn-wrapper.active .play__btn {
  display: none;
}

.btn-wrapper.active .pause__btn {
  display: block;
}
<div class="cards">
  <div class="card flex">
    <h4 class="card__title">Track 01</h4>
    <div class="btn-wrapper">
      <img src="https://cdn-icons-png.flaticon.com/512/153/153752.png" alt="" class="play__btn btn">
      <img src="https://cdn-icons-png.flaticon.com/512/1214/1214679.png" alt="" class="pause__btn btn">
    </div>
  </div>
  <div class="card flex">
    <h4 class="card__title">Track 02</h4>
    <div class="btn-wrapper">
      <img src="https://cdn-icons-png.flaticon.com/512/153/153752.png" alt="" class="play__btn btn">
      <img src="https://cdn-icons-png.flaticon.com/512/1214/1214679.png" alt="" class="pause__btn btn">
    </div>
  </div>
  <div class="card flex">
    <h4 class="card__title">Track 03</h4>
    <div class="btn-wrapper">
      <img src="https://cdn-icons-png.flaticon.com/512/153/153752.png" alt="" class="play__btn btn">
      <img src="https://cdn-icons-png.flaticon.com/512/1214/1214679.png" alt="" class="pause__btn btn">
    </div>
  </div>
</div>

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

Is it detrimental to my search engine ranking if I utilize CSS display:none?

Imagine having valuable content that is initially hidden with CSS, and then using javascript to reveal it only when the user clicks on certain links. Even users without javascript enabled can access this content by following the links to a new page where i ...

Retrieve CSS height using Jquery, based on the declared value rather than the computed value

In a previous version of jQuery, the default behavior was different. When I use .css("height") and .height(), it gives me the computed height instead of what I actually want. I only need the height value if it is explicitly declared in the CSS for that ele ...

Issue with playing audio file using HowlerJS

Having trouble playing a .mp3 file in my project directory with Howler. I'm not sure if there's an error in my src. When I tried playing an online hosted audio file, it worked fine. I've placed the audio file in the same directory as Slideon ...

Prevent further triggering of the .click function when the user clicks repeatedly

Is there a way to prevent the .click function from executing if the user clicks too many times? This is my current code: $('button').click(function() { $('#bg').fadeToggle('200'); }); Check out the jsfiddle DEMO ...

The image showcases interactive hover effects that resemble a button popping up

Welcome to my HTML code showcase: <div class="container"> <a target="_self" href="flower_gallery.htm"> <img data-src="holder.js/180x180" style="height:20%;width:100%;float:left;" ...

Accessing specific documents in Firebase cloud functions using a wildcard notation

Currently, I am working on implementing Firebase cloud functions and here are the tasks I need to achieve: Monitoring changes in documents within the 'public_posts' collection. Determining if a change involves switching the value of the &ap ...

Designing the button outline variant with Material-UI styling

I've recently started using Material UI and I'm facing some difficulties. One of the challenges I'm encountering is with a button component export default function TheButton(props: PropsWithChildren<Props>) { const { className, hover ...

choose multiple elements from an array simultaneously

Looking for help with a basic Array question and seeking the most effective solution. The scenario involves having an array: var pathArr = [element1, element2, element3, element4, element5, element6] If I want to select multiple elements from this array ...

Guide to utilizing Reduce for obtaining a fresh Array of Objects in Javascript

I am a beginner in coding, so I apologize if this question seems basic. I am working with an array that contains different types of pies along with their prices: pieArr = [blueberry, strawberry, pumpkin, apple] My goal is to create an array of objects re ...

Update the reference of the 'this' keyword after importing the file

I am currently utilizing react-table to showcase the data. My intention is to house my table columns outside of the react component due to its size and for reusability purposes. I created a table configuration file to contain all of my table configurations ...

What could be the cause of a JSON string only returning the final object when evaluated?

Does anyone have insight into why only the last object in my json string is returned when I use the eval function? ...

Search through an array of objects and assign a new value

I am facing a challenge with an array of objects structured as shown below: [ { "e_id": "1", "total": 0 }, { "e_id": "3", "total": 0 } ] My objecti ...

Is it possible to implement a single lightbox modal that can display multiple images?

I am looking to create a fullscreen lightbox modal for multiple images, but I have been facing issues with finding the right solution. Most lightbox modals out there rely on jQuery and older versions of Bootstrap. Here is what I have tried so far: HTML: ...

Interactive feature allowing all embedded YouTube videos on a webpage to play synchronously, with sound disabled, and on a continuous loop

I am in the process of developing a button that, when clicked by a user, will trigger all embedded YouTube videos on a specific webpage to start playing simultaneously, with sound muted, and set to loop. The target page for this button implementation can ...

Is it possible to combine the :last-child pseudo-class with the universal selector (*) in CSS or Sass

Here is the code I am currently using: .loken5 * padding-right: 5px .loken5:last-child padding: 0 I am wondering if there is a way in SASS to achieve the same effect with just one '.loken5' tag for saving space. Thank you :) ...

Code-based document editing with CouchBase

To test Couchbase, I need to create a servlet that will edit 1,000 JSON documents by changing the value of '"flag": false' to '"flag": true'. How can I achieve this task? Here is my view code for finding documents with '"flag": fa ...

Using Python to Detect a Late-Rendered Image on a Webpage Using JSON

I'm currently in the process of reviewing a list of URLs to verify the presence of a specific image. So far, I have experimented with both selenium and beautiful soup but haven't been able to crack it. The appearance of the image is represented ...

Which SSO framework works best for integrating Facebook and Twitter logins?

I own a website and I'm looking for a way to let users leave reviews and rate products. I need an SSO system that allows them to sign in with their Facebook or Twitter accounts and ensures each user is uniquely identified so they can't rate produ ...

What is the best way to increase a count in MongoDB?

I need to update the quantity count in my database every time I click a specific button. Here is the Angular directive I am using: var count = 0 $scope.postNote = function () { var deferred = $q.defer() var token = $scope.userInfo.$$state.valu ...

Width and left values don't play well with absolute positioning

I am encountering an issue where a div with absolute positioning, which is a child of another absolute positioned element, is not behaving as expected. Despite setting width:100%; left:1px; right:1px on the child element, it extends beyond its parent. < ...