A strategy for concealing the selected button within a class of buttons with Vanilla JS HTML and CSS

I have encountered a challenging situation where I am using JavaScript to render data from a data.json file into HTML. Everything seems to be functioning correctly, as the JSON data is being successfully rendered into HTML using a loop, resulting in multiple objects with the same class.

However, due to this setup, every button I create ends up belonging to the same class within the loop. Now, here's my dilemma: I want to hide only the specific button that is clicked, not all buttons of the same class.

var X = document.getElementsByClassName("buttons");
function HideClickedButton() {

  for (let x of X) {
    if (x.style.display === "none") {
      x.style.display = "block";
    
    } else {
      x.style.display = "none";
    }
  }
}

for (const button of X) {
    button.addEventListener('click', HideClickedButton);
}
<button class="buttons">Test</button>
<button class="buttons">Test</button>
<button class="buttons">Test</button>
<button class="buttons">Test</button>

The code above currently hides all buttons with the same class when one is clicked.

If I use just

document.querySelector(".buttons").style.display = "none"
,

it always hides the first button regardless of which button is pressed.

Edited Section:

 <div onclick="addToCart(${product.price})">
    <button class="b1" onclick="hideAddButton(this)" type="button">ADD</button>
  </div>
  <div onclick="addToCartRemove(${product.price})">
    <button class="b2 hidden" onclick="showRemoveButton(this)" type="button">Remove</button>
  </div>

My JavaScript code looks something like this, where I am rendering a list from JSON. After rendering, there are a total of 12 buttons. They are grouped in sets of 6 (see image). Now, I do not want to initially display the remove button. It should only appear when the corresponding ADD button is clicked. Upon clicking the ADD button, it will disappear and the Remove button will take its place, while the other ADD buttons remain visible. Please let me know if you understand.https://i.stack.imgur.com/8A5Ht.png

Answer №1

To handle button clicks, you can either add an event listener to each button individually and hide the clicked element dynamically...

const buttons = document.querySelectorAll('.button');

buttons.forEach(button => {
  addEventListener('click', handleClick)
});

function handleClick(e) {
  e.target.classList.add('hide');
}
.hide { display: none; }
<button class="button">one</button>
<button class="button">two</button>
<button class="button">three</button>
<button class="button">four</button>
<button class="button">five</button>

...or you can wrap all your buttons in a container, employ event delegation, and attach only one listener to that container (which captures events from all child elements as they bubble up the DOM). Ensure the clicked element has the class "button", then hide it.

const buttons = document.querySelector('.buttons');

buttons.addEventListener('click', handleClick);

function handleClick(e) {
  if (e.target.matches('.button')) {
    e.target.classList.add('hide');
  }
}
.hide { display: none; }
<div class="buttons">
  <button class="button">one</button>
  <button class="button">two</button>
  <button class="button">three</button>
  <button class="button">four</button>
  <button class="button">five</button>
</div>

Answer №2

To achieve this functionality, you can utilize the onclick event with "yourfunction(this)", as demonstrated in the snippet below.

Alternatively, you can implement an event listener for a different approach.

function HideClickedButton(x) {
      x.style.display = "none";
}
<div>
  <button onclick="HideClickedButton(this)" class="buttons">Button 1</button>
  <button onclick="HideClickedButton(this)" class="buttons">Button 2</button>
  <button onclick="HideClickedButton(this)" class="buttons">Button 3</button>
  <button onclick="HideClickedButton(this)" class="buttons">Button 4</button>
</div>

EDIT: In response to your question in the comments, here is how you can toggle the display of button 1 when clicking button 8, and vice versa. The buttons' classes are not relevant in this case as the function is triggered by the onclick attribute, not their class definitions.

function HideClickedButton(x) {
      var parent = x.parentNode;
      var index = [].indexOf.call(parent.children, x);
      // if the clicked element is at index 0 in the parent's children (button 1)
      if(index==0){
        // show the element at index 7 (button 8)
        parent.children[7].style.display = "inline-block"; 
      }
      // otherwise, if the clicked element is at index 7 in the parent's children (button 8)
      else if(index==7){
        // hide or show the element at index 0 (button 1)
        parent.children[0].style.display = "inline-block"; 
      }
      // then hide the clicked button
        x.style.display = "none";
}
<div>
  <button onclick="HideClickedButton(this)" class="buttons">Button 1</button>
  <button onclick="HideClickedButton(this)" class="buttons">Button 2</button>
  <button onclick="HideClickedButton(this)" class="buttons">Button 3</button>
  <button onclick="HideClickedButton(this)" class="buttons">Button 4</button>
  <button onclick="HideClickedButton(this)" class="buttons">Button 5</button>
  <button onclick="HideClickedButton(this)" class="buttons">Button 6</button>
  <button onclick="HideClickedButton(this)" class="buttons">Button 7</button>
  <button onclick="HideClickedButton(this)" class="buttons_other_class">Button 8</button>
</div>

Answer №3

To create interaction with your button, you can set up an event listener for the click action.

var btns = document.querySelectorAll(".buttons");
    btns.forEach(function (btn) {
        btn.addEventListener("click", function () {
            this.style.display = "none";
        })
    })

Answer №4

  1. document.querySelector() will only select the first element that matches the selector. To get all elements that match, use document.querySelectorAll().
  2. An easier way to handle this is to attach event handlers to all your buttons once they are rendered.

You seem to imply that when a button is clicked, it should disappear while the other buttons reappear. If this is not the desired behavior, you can comment out the line of code that changes the style of "other" buttons to block.

Edit: e.PreventDefault() and e.StopPropagation() are included to prevent the standard button click behavior (such as submitting forms). If you do not want to suppress this behavior, you can simply remove these lines.

const buttons = document.getElementsByClassName('buttons');

[...buttons].forEach( (button) => {
   button.addEventListener( 
      'click', 
      (e) => HideClickedButton( e, button ), 
      false 
   );
});

function HideClickedButton( e, button ) {
  [...buttons].forEach( (other) => other.style.display = 'block' );
  e.preventDefault();
  e.stopPropagation();
  button.style.display = 'none';
}
<div>
  <button class="buttons">Button 1</button>
  <button class="buttons">Button 2</button>
  <button class="buttons">Button 3</button>
  <button class="buttons">Button 4</button>
</div>

Answer №5

var X = document.getElementsByClassName("buttons");
function ToggleButtonVisibility() {

  for (let x of X) {
    if (x.style.display === "none") {
      x.style.display = "block";
    
    } else {
      x.style.display = "none";
    }
  }
}

for (const button of X) {
    button.addEventListener('click', ToggleButtonVisibility);
}
<button class="buttons">Test</button>
<button class="buttons">Test</button>
<button class="buttons">Test</button>
<button class="buttons">Test</button>

HTML:

<button class="hidden-button">Click me</button>

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

Discovering if an agent is a mobile device in Next.js

I am currently working with nextjs version 10.1.3. Below is the function I am using: import React, {useEffect, useState} from "react"; const useCheckMobileScreen = () => { if (typeof window !== "undefined"){ const [widt ...

As you scroll, the top block in each of the three columns will remain fixed within its

I need assistance with a problem involving three columns and multiple blocks within each column. Specifically, I want the first block in each column to remain fixed at the top when scrolling. However, once you reach the bottom of each column, the first blo ...

Faraday failed to parse the error response even after incorporating the :json middleware

Setting up my Faraday client involves the following steps: @client = Faraday.new(url: BASE_URL) do |faraday| faraday.request :json faraday.response :json faraday.response :raise_error end After rescuing the Faraday::ClientError, the response body ...

Proceed with downloading the file only when a checkbox has been ticked off and the form has been

Is there a way to make a PDF download only when a user checks a checkbox and submits the form, rather than just checking the checkbox and hitting submit? I am limited to using Jquery or plain javascript and do not have access to backend files. The checkbox ...

Don't allow users to switch views without saving their changes

We are working with a Backbone.js application that presents various forms to users. Our goal is simple: if a user navigates away from the page without saving the completed form, we need to show a confirmation dialog. When dealing with traditional forms, i ...

Verification is required for additional elements within the div block once a single checkbox has been selected

Currently, I am working in PHP using the CodeIgniter framework. I have a question regarding implementing a functionality with checkboxes and validation using jQuery. Here is the scenario I want to achieve: There are four checkboxes, and when one checkbox ...

AngularJS Bootstrap CSS implementation for Hand Cursor Grab

Is there a way to ensure the cursor is always a hand / grab for sortable containers in AngularJS & Bootstrap? What specific HTML modification would achieve this change? <div ui-sortable="sortableOptions" ng-model="responses" class="container-f ...

Tips for effectively utilizing the Material-UI Grid component to implement this layout

Currently, I am working on incorporating this design in Material-UI by utilizing the Grid component. To better delineate the boundaries, I have marked the container border in red for clarity. The Add button should be positioned at the far right of the c ...

What is the solution for the error "BREAKING CHANGE: webpack < 5 used to automatically include polyfills for node.js core modules"?

I am trying to use the "web3" and "walletconnect/web3-provider" package in a Vue & Laravel 8 project. I have installed it using the npm i --save web3 @walletconnect/web3-provider command and then added the following code to import into ...

Safari failing to show SVG at correct alignment

I am looking to implement a unique feature on my website where image placeholders are displayed for 1 second before fading out to reveal the actual image. These image containers will be responsive, adjusting to fit the size of their parent container. In a ...

Unveiling Elements as You Scroll Within a Specified Area

I have implemented a jQuery and CSS code to reveal my contact form as I scroll down the page. However, I am facing an issue with setting a specific range for displaying the element while scrolling. Currently, I have only managed to handle the scrolling dow ...

What is the best way to incorporate a minimum width and maximum width in CSS that add up to 100% when necessary?

Can anyone help me find CSS rules that can set a fixed width for an element (width: 500px) but also allow it to be responsive with max-width: 100% if the container is narrower than the element? I saw this example and it works perfectly: .elem { width: 60 ...

Is there a way to use node.js to retrieve a video in mp4 format?

My goal is to allow users to download a video from my AWS S3 bucket in MP4 format: app.get("/download_video", function(req,res) { filename = "s3.xxx.amazon.com/bucketname/folder/video_example.mp4"; // I'm unsure about the next steps }); Whil ...

For unknown reasons, converting a string to JSONArray results in null

I'm experiencing a problem with retrieving JSON data from a URL. After converting it to a string, I attempt to convert it to a JSONArray, but it keeps returning null. The URL in question is: Here's the code snippet: public JSONArray getJsonFrom ...

Unable to convert XML string using Newtonsoft.Json.JsonConvert.DeserializeObject

Greetings! I have a scenario where I am passing an XML as a string <AbcDto xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Abc"> <Id>2</Id> <Description>sample string 4</Des ...

Angular animations: triggered by user interaction

I'm encountering some difficulties with animating elements in my Angular application. The issue involves a grid made up of cells (created using ng-repeat). What I'm aiming to achieve is a simple animation: when a cell is clicked, it should disapp ...

Problem with YouTube iFrame API in IE when using JavaScript

Apologies for the unclear heading, but I'm facing a peculiar issue. The YouTube iFrame API works perfectly on all browsers except Internet Explorer. In IE, none of the JavaScript code runs initially. However, when I open DevTools and refresh the page, ...

The box on my form is leaking my background color outside the 1px border, but only in Internet Explorer

While experimenting with background gradients and borders one day just for the fun of it, I made an interesting observation in Internet Explorer. The issue I encountered was that the background color was overflowing outside the radius border, but this onl ...

What steps are involved in implementing Local fonts in theme UI for Next JS?

I am currently developing an application using next JS with [theme-UI][1]. However, I need to implement local or custom fonts in my project and I'm unsure of how to do this. Below is the current theming setup: const theme = { fonts: { ...

Analyzing two arrays and utilizing ng-style to highlight matching entries within the arrays

My list displays words queried from a database, allowing me to click on a word to add it to another list that I can save. This functionality enables me to create multiple word lists. My goal is to visually distinguish the words in my query list that have a ...