Using Javascript to dynamically retrieve accordion content from a dynamically generated ID

I am currently working on developing a more intricate accordion feature. The accordion will consist of 4 buttons (section 0-3) with unique content (lorem ipsum 0-3). Clicking on "section 0" should reveal "lorem ipsum 0", while clicking on "section 1" should replace the content with "lorem ipsum 1".

The final website will have an unknown number of rows, each containing 4 accordions. Therefore, the script needs to be dynamic in nature.

My initial approach involved generating IDs using JavaScript and assigning them to each panel to make the accordion functional. However, I encountered challenges as I was only able to display all the contents at once or just the last one from the loop.

How can I ensure that the content is displayed/replaced for every accordion without disrupting the layout?

Perhaps there is a better approach to achieve this overall?

HTML:

<div class="row">

  <div class="three columns">
    <button class="accordion">Section 0</button>
  </div>  

  <div class="three columns">
    <button class="accordion">Section 1</button>
  </div>  

  <div class="three columns">
    <button class="accordion">Section 2</button>
  </div>    

  <div class="three columns">
    <button class="accordion">Section 3</button>
  </div>  

</div>  

<div class="row">
  <div class="twelve columns">
    <div class="panel">
      <p>Lorem ipsum 0...</p>
    </div>
  </div>
  <div class="twelve columns">
    <div class="panel">
      <p>Lorem ipsum 1...</p>
    </div>
  </div>
  <div class="twelve columns">
    <div class="panel">
      <p>Lorem ipsum 2...</p>
    </div>
  </div>
  <div class="twelve columns">
    <div class="panel">
      <p>Lorem ipsum 3...</p>
    </div>
  </div>
</div>

JS:

var acc = document.getElementsByClassName("accordion");
for (var i = 0; i < acc.length; i++) {
    acc[i].onclick = function() {
        this.classList.toggle("active");

        var writeID = document.getElementsByClassName("panel");
        for (var y = 0; y < writeID.length; y++) {
            var newID = "demo-"+y;
            writeID[y].setAttribute("id", newID);

            var panel = document.getElementById(newID);

            if (panel.style.maxHeight){
                panel.style.maxHeight = null;
            } else {
                panel.style.maxHeight = panel.scrollHeight + "px";
            } 
        }
    }
}

I have also created a JSFiddle.

Any assistance would be greatly appreciated!

Regards, Max

EDIT: I am seeking any form of help concerning this issue. I have attempted using closures and forEach loops but have not been successful. Feel free to ask any questions if clarification is needed regarding the above information.

This is the current state of the code. It displays all the contents, but I aim to show only one for each accordion:

var acc = document.getElementsByClassName("accordion");
for (var i = 0; i < acc.length; i++) {
  acc[i].onclick = function() {
    this.classList.toggle("active");

      for (var i = 0; i < acc.length; i++) {
        var panel = document.getElementById("demo-"+i);
        if (panel.style.maxHeight){
          panel.style.maxHeight = null;
        } else {
          panel.style.maxHeight = panel.scrollHeight + "px";
        }   
      };  
  }
}

In other words, I am trying to accomplish the following dynamically:

var acc = document.getElementsByClassName("accordion");

acc[0].onclick = function() {
  this.classList.toggle("active");
  var panel = document.getElementById("demo-0");
  if (panel.style.maxHeight){
    panel.style.maxHeight = null;
  } else {
    panel.style.maxHeight = panel.scrollHeight + "px";
  }    
}

acc[1].onclick = function() {
  this.classList.toggle("active");
  var panel = document.getElementById("demo-1");
  if (panel.style.maxHeight){
    panel.style.maxHeight = null;
  } else {
    panel.style.maxHeight = panel.scrollHeight + "px";
  }    
} 

Answer №1

You have the ability to enhance your buttons by incorporating a custom attribute that corresponds with the section number (data-section=3). This attribute can then be utilized to unveil the appropriate panel containing the relevant data.

var data = ["lorem ipsum ipsum", "lorem lorem lorem", "blah blah blah"];
formatData(data);

function formatData(data) {
  data.forEach(function(text, index) {
    var buttonHTML = "<div class='three columns'>" +
      "<button class='accordion' data-section=" + index + ">Section " + index + "</button>" +
      "</div>";

    var accordionHTML = "<div class='twelve columns'>" +
      "<div id='panel" + index + "' class='panel'>" +
      "<p>" + text + "</p>" +
      "</div>" +
      "</div>";
    document.getElementById("buttonRow").insertAdjacentHTML('beforeend', buttonHTML);
    document.getElementById("panelRow").insertAdjacentHTML('beforeend', accordionHTML);
  })
  var acc = document.getElementsByClassName("accordion");
  for (var i = 0; i < acc.length; i++) {
    acc[i].onclick = function() {
      this.classList.toggle("active");
      var sectionNum = this.getAttribute("data-section");
      var currentPanel = document.getElementById("panel" + sectionNum);
      if (currentPanel.style.maxHeight) {
        currentPanel.style.maxHeight = null;
      } else {
        currentPanel.style.maxHeight = currentPanel.scrollHeight + "px";
      }
    }
  }
}
.democlass {
  color: red;
}

#demo-0 {
  color: red;
}

#demo-1 {
  color: blue;
}

#demo-2 {
  color: green;
}

#demo-3 {
  color: magenta;
}

/* Accordion
–––––––––––––––––––––––––––––––––––––––––––––––––– 
https://www.w3schools.com/howto/howto_js_accordion.asp
*/

/* Style the buttons that are used to open and close the accordion panel */
button.accordion {
  background-color: #eee;
  color: #444;
  cursor: pointer;
  width: 100%;
  text-align: left;
  border: none;
  outline: none;
  transition: 0.4s;
}

/* Add a background color to the button if it is clicked on (add the .active class with JS), and when you move the mouse over it (hover) */

button.accordion.active,
button.accordion:hover {
  background-color: #ccc;
}

/* Style the accordion panel. Note: hidden by default */
div.panel {
  padding: 0 18px;
  background-color: white;
  /*    display: none;
*/
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.2s ease-out;
}

.container {
  position: relative;
  width: 100%;
  /*max-width: 1200px;*/
  margin: 0 auto;
  padding: 0 20px;
  box-sizing: border-box;
}

.column,
columns {
  width: 100%;
  float: left;
  box-sizing: border-box;
}

/* For devices larger than 400px */
@media (min-width: 400px) {
  .container {
    width: 85%;
    padding: 0;
  }
}

/* For devices larger than 550px */
@media (min-width: 550px) {
  .container {
    width: 95%;
  }
  .column,
  .columns {
    margin-left: 4%;
  }
  .column:first-child,
  .columns:first-child {
    margin-left: 0;
  }
  .one column,
  .one columns {
    width: 4.66666666667%;
  }
  .two columns {
    width: 13.3333333333%;
  }
  .three columns {
    width: 22%;
  }
  .four columns {
    width: 30.6666666667%;
  }
  .five columns {
    width: 39.3333333333%;
  }
  .six columns {
    width: 48%;
  }
  .seven columns {
    width: 56.6666666667%;
  }
  .eight columns {
    width: 65.3333333333%;
  }
  .nine columns {
    width: 74.0%;
  }
  .ten columns {
    width: 82.6666666667%;
  }
  .eleven columns {
    width: 91.3333333333%;
  }
  .twelve columns {
    width: 100%;
    margin-left: 0;
  }
  .one-third column {
    width: 30.6666666667%;
  }
  .two-thirds columns {
    width: 65.3333333333%;
  }
  .one-half column {
    width: 48%;
  }

  /* Offsets */
  .offset-by-one.column,
  .offset-by-one.columns {
    margin-left: 8.66666666667%;
  }
  .offset-by-two.column,
  .offset-by-two.columns {
    margin-left: 17.3333333333%;
  }
  .offset-by-three.column,
  .offset-by-three.columns {
    margin-left: 26%;
  }
  .offset-by-four.column,
  .offset-by-four.columns {
    margin-left: 34.6666666667%;
  }
  .offset-by-five.column,
  .offset-by-five.columns {
    margin-left: 43.3333333333%;
  }
  .offset-by-six.column,
  .offset-by-six.columns {
    margin-left: 52%;
  }
  .offset-by-seven.column,
  .offset-by-seven.columns {
    margin-left: 60.6666666667%;
  }
  .offset-by-eight.column,
  .offset-by-eight.columns {
    margin-left: 69.3333333333%;
  }
  .offset-by-nine.column,
  .offset-by-nine.columns {
    margin-left: 78.0%;
  }
  .offset-by-ten.column,
  .offset-by-ten.columns {
    margin-left: 86.6666666667%;
  }
  .offset-by-eleven.column,
  .offset-by-eleven.columns {
    margin-left: 95.3333333333%;
  }
  .offset-by-one-third.column,
  .offset-by-one-third.columns {
    margin-left: 34.6666666667%;
  }
  .offset-by-two-thirds.column,
  .offset-by-two-thirds.columns {
    margin-left: 69.3333333333%;
  }
  .offset-by-one-half.column,
  .offset-by-one-half.columns {
    margin-left: 52%;
  }
<div class="container">

  <div id="buttonRow" class="row">

  </div>

  <div id="panelRow" class="row">

  </div>

</div>
<!-- /container  -->

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

Guide for using express.js

Similar to how you can use to view the source code of all classes in Java, is there a resource available to view the source code of the express module? ...

What could be the reason for an async function to send an empty object in the request body?

I'm currently utilizing nuxt.js, mongoDB, express, and bodyParser as well Unfortunately, the solutions provided by others do not solve my issue, as having bodyParser does not seem to fix it. The uploadPet function is designed to collect form data an ...

When hovering over the element, child elements remain unaffected by the wrapping behavior

My anchor tag contains a span and an image, but I am having trouble making them hover together. <a href=""> <img src="image"/> <span>Shopping Cart</span> </a> a :hover { opacity: 0.6; } Check out the fiddle ...

How can I line up elements in different divs when the width is adjusting based on the window size?

Trying to align a search input and a result element in separate containers when the window size changes. Looking for a solution without using Javascript. One window size: A smaller window: Currently utilizing but facing challenges with responsive desig ...

Unable to access the newly created object's properties following the instantiation of a new resource in AngularJS

Currently, I am in the process of developing a new Resource utilizing AngularJS that falls under the category of Person. After successfully creating this resource, my goal is to retrieve the id associated with the new resource from the server. it('sh ...

The data point on jqPlot does not display in full

I've been working on creating a chart with jqPlot to display data for each hour. It's mostly going well, but there's an issue where the first and last data points are not showing correctly - part of the circle is getting cut off. Here' ...

CKEditor5: Unable to access the 'pluginName' property because it is undefined

I am facing a challenge in creating a custom image plugin for CKEditor that can seamlessly integrate with my own image upload system. While trying to set up this plugin, I encountered some difficulties. Oddly enough, the "out-of-the-box" plugins work perfe ...

Setting a validation message for a Vuejs username input while enforcing a maximum character limit

<script> export default { name: "Register", props: { msg: String, }, }; </script> <style scoped> * { box-sizing: border-box; } div { padding: 0; margin: 0; font-family: system-ui; } .red { color: red; } <template& ...

Implementing Google Places reviews on a website with the help of JavaScript

Struggling to display the Google reviews for my company on our website, I can't seem to make it work. I've attempted to use this code: <script> $(function() { var people = []; $.getJSON('https://maps.googleapis.com ...

Accessing a key from an object dynamically in a React list and resolving key error issues in React

I encountered two challenges: I am currently retrieving JSON data from APIs. [ { "title": "Basic Structures & Algoritums", "lesson_id": 3, "topics": { "Title": &q ...

Retrieve an array of existing fields in MongoDB by comparing a collection with an array of objects

I'm a newbie when it comes to Mongo and I'm attempting to compare an array with a collection of documents, returning a list of matching records. Let me break it down:First Array I have a collection (user) with the following documents: > db. ...

What is causing this issue? Error: [$compile:nonassign] The expression 'undefined' cannot be assigned! AngularJS 1.5

I'm currently working on developing a component to post "Tweets" on my personal website. However, I am facing an issue where I cannot input any text into the textarea. Below is an image showcasing the error: Please review my code in the file "editor ...

Guide to verify the user selection within a select form

Here is a form with a select field: <form method="post" name="posting_txt" onSubmit="return blank_post_check();" id="post_txt"> <select style="background: transparent; border-bottom:5px;" name="subname" class="required"> ...

The event handler is not defined and is failing to recognize in the React context

Currently, as I delve into the realm of learning React, I find myself facing a perplexing issue regarding the mysterious undefined state of this event handler. Why is it behaving in such an enigmatic manner? const Login = () => { handleSubmit = (e) ...

Strikeout list on click of a mouse

Is there a way to apply strikethrough formatting to text with just a mouse click? The CSS for lists is beyond the form field margin. I've tried multiple methods without success. No matter how many times I change the code, I can't seem to get it r ...

Issue with Angular App: Bootstrap navbar not displaying on smaller screens

I am working on an Angular app (using Angular 11.2.4 with Bootstrap 4.5.3) and facing an issue where the navbar is not rendering correctly on screens smaller than ~580 pixels wide. Even when I click the toggler to 'expand' the collapse region, n ...

Tips for filtering only alpha versions, such as those labeled 1.0.0-alpha.*

Is it possible to specifically target -alpha versions of a package using semver and NPM? The common approaches like using 1.0.0-alpha.x or * do not seem to work as expected due to how the version elements are interpreted. The usage of ~1.0.0-alpha also do ...

Using the conditional rendering technique in a mapped function within a React table cell

I have an array that is being displayed inside a Table, and I need to compare each object's "userName" property with the header in order to determine where to place the value. If there is no match, it should display a "0". Here is a snippet of the ta ...

Is it possible for node.js to execute promises without needing to await their fulfillment?

When I visit the Discord tag, I enjoy solving questions that come my way. While I am quite proficient in Python, my skills in Javascript are just about average. However, I do try my hand at it from time to time. The Discord.py library consists of several ...

What is the best way to incorporate a formArray into a formGroup?

Before anything else, I want to apologize for any errors in my English. I seem to be having trouble adding an array field to a formGroup. My issue arises when attempting to use the push method to add a formArray to my rate formGroup. It appears that the ...