Implementing a feature in JavaScript to close one accordion when another is clicked on

I am seeking assistance in resolving the JavaScript code for my sidebar. While I've noticed that most people use jQuery for this task, I would prefer to stick with plain JavaScript as I am still new to it.

If you are reading this, please refrain from marking it as a duplicate or irrelevant. I have been researching JavaScript for some time now and hope this post will be beneficial not only for me but also for others interested in using regular JavaScript.

Recently, I learned how to create a simple accordion from w3Schools, which you can find here.

Currently, I have successfully designed my custom sidebar. However, I am facing an issue where I want the active accordion to close when I click on another accordion.

Playground:

const sideBar = document.getElementsByClassName('pisti-sidebar');

for (let i = 0; i < sideBar.length; i++) {
  sideBar[i].addEventListener('click', function() {
    const sideBarTitle = this.nextElementSibling;

    sideBarTitle.style.display == 'none';

    if (sideBarTitle.style.display === 'block') {
      sideBarTitle.style.display = 'none';
    } else {
      sideBarTitle.style.display = 'block';
      document.querySelectorAll('.pisti-sidebar')[i].classList.remove('onload-active');
      document.querySelectorAll('.pisti-sidebar-title')[i].classList.remove('onload-active');

    }
  });
}
body {
  background: #000000 !important;
  width: 100vw;
  height: 100vh;
  padding: 20px;
}


/* pisti-sidebar styles */

.pisti-sidebar {
  // Add your styles here
}

.onload-active {
  // Add your styles here
}

.onload-unactive {
  // Add your styles here
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>

<div class="container">
  <div class="row">
    <div class="col-12">
      <button class="pisti-sidebar onload-active" data-pisti-sidebar="pisti-sidebar-1">Appareal</button>
      <div class="pisti-sidebar-title onload-active">
        <a href="#" class="pisti-sidebar-content">Custom shirt</a>
        <a href="#" class="pisti-sidebar-content">Event shirt</a>
        <a href="#" class="pisti-sidebar-content">Corporate shirt</a>

      <button class="pisti-sidebar" data-pisti-sidebar="pisti-sidebar-2">Digital Printing</button>
      
          <a href="#" class="pisti-sidebar-content">Poster</a>
          <a href="#" class="pisti-sidebar-content">Banner</a>
          <a href="#" class="pisti-sidebar-content">Bunting</a>

      <button class="pisti-sidebar" data-pisti-sidebar="pisti-sidebar-3">Offset Printing</button>
      
          <a href="#" class="pisti-sidebar-content">Name card</a>
          <a href="#" class="pisti-sidebar-content">Flyer</a>
          <a href="#" class="pisti-sidebar-content">Booklet</a>

    </div>
  </div>
</div>

In an attempt to address this, I added the following:

document.querySelectorAll('.pisti-sidebar')[0].classList.remove('onload-active');
document.querySelectorAll('.pisti-sidebar-title')[0].classList.remove('onload-active');

This removed the class from the first accordion, causing it to close. However, I am unsure how to close the second accordion when clicking on the third or first accordion.

Answer №1

Modified the CSS and JS to eliminate the list being toggled in the loop. Instead, only toggle the .active class on the button and utilize the adjacent selector .pisti-sidebar.active + .pisti-sidebar-title to display its list.

const sideBars = document.getElementsByClassName('pisti-sidebar');

for (let sideBar of sideBars) {
  sideBar.onclick = e => {
    var thisEl = e.target;
    if (thisEl.classList.contains('active')) {
      thisEl.classList.remove('active');
    } else {
      thisEl.classList.add('active');
      for (activeSideBar of sideBars) {
        if (activeSideBar != thisEl) {
          activeSideBar.classList.remove('active');
        }
      }
    }
  }
}
body {
  background: #000000 !important;
  width: 100vw;
  height: 100vh;
  padding: 20px;
}

.pisti-sidebar {
  background: none !important;
  border: none;
  border-left: 2px solid #888888;
  color: #888888;
  cursor: pointer;
  font-size: 20px;
  font-weight: 400;
  padding: 10px 30px 10px 20px;
  text-align: left;
  transition: 0.3s all ease;
  width: 100%;
}

.pisti-sidebar:first-child {
  padding-top: 0;
}

... (remaining code omitted for brevity)
<div class="container">
  <div class="row">
    <div class="col-12">
      <button class="pisti-sidebar active" data-pisti-sidebar="pisti-sidebar-1">Appareal</button>
		...
      <a href="#" class="pisti-sidebar-content">Booklet</a>
        ...
	  </script>

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

Tips for retrieving the final element from a corrupt JSON string using JavaScript

I've encountered an issue with a nodejs speech recognition API that provides multiple texts in a JSON like structure which renders the data invalid and useless. { "text": "Play" } { "text": "Play astronaut" } ...

What is the best way to implement Bootstrap 5 jQuery plugins in an ES6 project with Webpack?

Currently in the process of transitioning an ES6 project from Bootstrap 4 to Bootstrap 5, encountering the following error: Error: Uncaught TypeError: bootstrapElement.Tooltip is not a function According to the Migration Notes, Bootstrap 5 no longer inc ...

What are the methods for removing the color green with CSS or JavaScript?

Is it possible to isolate only the red and blue color components in an image or text using CSS 'filter' feature? If so, can someone please provide guidance on how to do this? Thank you. ...

Conflict between multiple jQuery files

Currently, I am in the process of creating a test website for an upcoming project. However, I have encountered some issues with jQuery. This is a static HTML5 website that includes a social widget. The problem arises when I remove a particular jQuery lin ...

Is there a way to eliminate the slight blurriness of images in a web browser?

I am developing a game where collisions are determined by the color of pixels on the canvas. If a pixel is red, the player cannot move. However, I have encountered an issue in Firefox where images appear blurred and pixels transition smoothly from white ...

All web resources need to be included in the web_accessible_resources manifest key

I'm encountering an issue with my Angular app. The error message on the client console reads: Denying load of chrome-extension://fiekimdgbphfmnlbiahcfdgcipcopmep/js/lib/angular/angular.min.js.map. Resources must be listed in the web_accessible_resour ...

Follow each step to see the final outcome

I have a Step-by-step form that includes a simple calculation. To calculate section 08, I have a function that subtracts liabilities from assets and displays the result as net equity. $(document).ready(function () { // Calculate section 08 ...

I am facing an issue with Recharts not occupying the full width in my Nextjs/Reactjs project. Despite setting it to 100% width, it does not behave as

I am currently working with Recharts in combination with Next.js and Tailwindcss. I decided to create my own barchart by copying a code snippet from Recharts, but encountered an issue where changing the height to aspect worked fine, however setting the wid ...

Provide a numerical representation of how frequently one object value is found within another object value

Account Object Example in the Accounts Array: const accounts = [ { id: "5f446f2ecfaf0310387c9603", picture: "https://api.adorable.io/avatars/75/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0e6b7d7a666 ...

Transitioning images smoothly and responsively with jQuery, creating a beautiful

Hey there! I'm looking for some help with transforming this jQuery effect. Instead of having fixed sized images, I want to set the size in percentage (width:100%; height:auto) so they can be responsive. Any creative ideas or suggestions? <scri ...

I am encountering a "Not a Number" error

I'm encountering a NaN error in this particular calculator script. Any suggestions? Below is the entire HTML in text format: https://www.example.com/somefile.txt <script language="JavaScript"> var IDs = [22,17425,17426,1223,17428,17429,1225, ...

Tips for capturing the dx dy SVG attribute using CSS

Seeking advice on the most effective way to access the dx dy SVG attribute in CSS. If this is not feasible, what would be the best approach in JavaScript? ...

Create customized validation decorators in class-validator for TypeScript by overriding the `validationOptions` within the `validator` method

Take a look at the example provided in section Custom validation decorators: // Defining a decorator import { registerDecorator, ValidationOptions, ValidationArguments } from 'class-validator'; export function IsLongerThan(property: string, va ...

The getElementBy method is failing to pass the value in the document

Here is the javascript code snippet I am using: document.getElementById('district').value = dist.long_name "this line is passing the value" document.getElementById('city').value = route.long_name "this doesn&apos ...

Difficulty comprehending the fallback for JSON.parse in jQuery.parseJSON

Check out the origin of $.parseJSON function (data) { if (typeof data !== "string" || !data) { return null; } // Remove leading/trailing whitespace for compatibility data = jQuery.trim(data); // Try native JSON parser first ...

Finding the attribute value within a nested array of objects retrieved from an API response

Imagine a scenario where I possess an array of unclassified objects, each of which contains an array of labeled objects: [{id: 123, name: 'Foo', code: 'ABC123', enabled: true},{id: 124, name: 'Bar', code: '123ABC', e ...

The data-tooltip feature displays information as [Object object]

There seems to be an issue with displaying text in the data-tooltip. Instead of showing the intended message, it is displaying [Object object]. import React from "react"; import { FormattedMessage } from "react-intl"; const translate = (id, value={}) = ...

Customize Monaco Editor: Implementing Read-Only Sections

I am currently working on setting up the Monaco Editor so that specific sections of the text content are read-only. Specifically, I want the first and last lines to be read-only. See example below: public something(someArgument) { // This line is read-onl ...

Solving Problems with Inline Tables using Angular, Express, and Mongoose's PUT Method

For the past few days, I've been struggling to figure out why my PUT request in my angular/node train schedule application isn't functioning properly. Everything else - GET, POST, DELETE - is working fine, and I can successfully update using Post ...

Stop a Post Request from being processed once a form has been submitted to an IFrame

Is there a way to cancel a post after submitting a form to an IFrame? $form = jQuery("<form target='iframetarget' method=post><files...></form>"); $form.submit(); I am looking for a method like $form.cancelPost(); to stop the ...