Switch between Accordions/Tabs with JavaScript (ES6)

Encountering a minor issue with the accordion/tab layout provided in this link:

https://jsfiddle.net/drj3m5tg/

The problem is that on mobile, the "+" icon remains as "-" when opening and closing tabs. Also, in desktop view, sometimes tabs need to be clicked twice to reveal the content below. Upon inspecting in Chrome, it appears that the active class is not removed until clicking again. Is there a solution using JS to address this behavior?

const accordion = document.getElementsByClassName("accordion");
const panel = document.getElementsByClassName("panel");

for(let i = 0; i < accordion.length; i++){
  accordion[i].addEventListener('click', function(){
    removeOpen();
    // add active class to clicked element and open class to next sibling
    const toggleResult = this.classList.toggle('active');
    this.nextElementSibling.classList.toggle('panel-open', toggleResult);

  });
};

// remove open class for all elements
function removeOpen (){
    for(let i = 0; i < panel.length; i++) {
       panel[i].classList.remove('panel-open');
    }
};

Answer №1

To solve the issue of toggling in an accordion, ensure that you remove the "active" class from all other buttons except the one being clicked. Here is a refactored version of the code to achieve this:

(function() {
    const accordion = document.getElementsByClassName("accordion");
    let current = -1;

    for (let i = 0; i < accordion.length; i++) {
        accordion[i].addEventListener('click', function() {
            if (i !== current && current !== -1) {
                accordion[current].classList.remove('active');
                accordion[current].nextElementSibling.classList.remove('panel-open'); 
            }
            this.nextElementSibling.classList.toggle('panel-open');
            current = this.classList.toggle('active') ? i : -1;
        });
    };
})();

JSFiddle

EDIT:

The variable current stores the index of the active accordion element. It is used to keep track of which element is currently active and avoid removing classes unnecessarily. The value of current ranges from 0 to the length of the accordion elements. An inactive element is indicated by a value outside this range, typically -1.

This approach allows us to only remove the active class from one element at a time when another element is clicked. By checking if the clicked element is not already active, we prevent adding and immediately removing the active class during toggling operations.

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

What is the reason for adding CSS styles to a JavaScript file without importing them?

/Navbar.js/ import './navbar.scss'; import {FaBars, FaSearch} from "react-icons/fa"; import { useState } from 'react'; function Navbar(){ const [hide,sethide] = useState(true); const barIcon = document.querySelectorAl ...

Guide on retrieving just the time from an ISO date format using JavaScript

let isoDate = '2018-01-01T18:00:00Z'; My goal is to extract the time of 18:00 from the given ISO date using any available method, including moment.js. ...

Designing a calendar with a grid template

I am attempting to design a calendar that resembles an actual calendar, but I am facing an issue where all created divs (representing days) are being saved in the first cell. I am not sure how to resolve this. Any help would be greatly appreciated. css . ...

Is there a clash between the jQuery slider moving up and down and the Twitter widget

Check out this jsFiddle code that functions well until a Twitter widget is inserted. The code is designed to slide content up and down when the link "click here" is clicked. However, once a default code from get a Twitter widget is added in this version ( ...

How can I create spacing between squares in an HTML div element?

Currently, I am working on my project using Laravel 5. I retrieve some integer values from a database and use them to create square divs in HTML. Below is the current output of my work. https://i.stack.imgur.com/sy2ru.png You may notice that there is spa ...

Tips for concealing an alert using an 'if' statement

There is an alert that pops up on a website only on specific days of the year. My query is: How can I make the alert hidden if the date is not one of those special days? I attempted the code below, but it seems to just delay the alert based on certain con ...

Utilizing AngularJS ng-messages feature across various languages

Utilizing ng-messages to show error messages for form validation in my application. I have a multi-language app, how can I implement ng-messages to support multiple languages? HTML Form <div class="messages" ng-messages="myForm.email.$error"> & ...

Utilizing AngularJS to implement checkbox selection within a table

I'm working on a method that will receive an Id from a table when a checkbox is checked and update the $scope.selected array in my Angular controller. If the checkbox is unchecked, it should remove the corresponding item from $scope.selected. Here&ap ...

Locate a row in an unselected data table using Jquery based on the value in a td

Is there an efficient way with jQuery to locate a td in a "legacy" datatable that contains my search value, and then navigate up the row tr? I am currently using $('#modalTable tbody').dataTable()[0].rows to retrieve all rows and then iterate th ...

switch from material ui lists on/off

Trying to learn React through coding, I've encountered an issue with displaying the 'StarBorder' icon next to folders when clicked. Currently, clicking on any folder displays the 'StarBorder' icon for all folders. Any tips on how t ...

There are various iterations of html2canvas available

After upgrading html2canvas from v0.5.0 to v1.0.0, a specific function ceased to work on iOS. Therefore, I am interested in utilizing v0.5.0 on iOS and v1.0.0 on other devices. Is there a way to incorporate and switch between both versions of html2canvas ...

Necessary within a JavaScript Class

As a newcomer to using classes in JavaScript, I've been exploring the best practices and wondering about how 'requires' work when used within a class. For example, let's say I want to craft an IoT Connection class for connecting to the ...

What is the best way to create a never-ending horizontal animation that moves a logo image from right

I have a dilemma with displaying my logo images. I have more than 10 logos, but I want to showcase only 6 of them on page load. The rest of the logos should slide horizontally from right to left in an infinite loop. Can anyone assist me with creating keyf ...

Undefined jQuery was encountered on the object when using the appropriate selector

Having a jQuery issue with the following HTML code snippet: <div class="side-finder"> <div class="brand"><img src="/img/test.net-logo.png" /></div> <div class="finder-content"> <ul class="nav nav-pills nav-stacked" id= ...

Can you suggest a method to align this form to the center?

Take a look at this image Hello there! I am trying to center the login form on my webpage and I have added this code to my index file: Here is the complete code snippet: <section class="row" justify-content-center> <section class="col-12-sm ...

Combine and blur multiple background images using CSS blending techniques

I am currently working on a website, which is just a demo built in ReactJS: The issue I'm facing is related to the background. The idea behind the app is simple - it consists of 4 parts, with the top part displaying weather information without a bac ...

Vertical scroll bar positioned on the left side of a DIV

Can a vertical scroll bar be placed on the left side of a DIV using CSS? What about JavaScript? ...

Combining and adding together numerous objects within an array using JavaScript

I'm looking to combine two objects into a single total object and calculate the percentage change between the two values. I'm encountering some difficulties while trying to implement this logic, especially since the data is dynamic and there coul ...

Creating a duplicate of a Flex object in HTML without the need to reinitialize

I'm currently developing a flash object that involves processing a large number of images. My goal is to load multiple flash objects on the same page in order to capture an image, make adjustments, and then display it within each flash object. Howeve ...

Utilize Vue.js to send bound data to a click event

I am currently working with a v-for loop that iterates over data fetched from an API, setting the key as the ID of each object. My goal is to create a click event that captures the v-bind:key value of the clicked element. This will allow me to locate all t ...