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

What is the best way to implement next and previous buttons in a slideshow using code?

Looking to enhance my slideshow by replacing the standard "Next" and "Previous" text buttons with custom JPEG images I've created. Anyone familiar with the steps needed to make this switch in the HTML code? Current HTML code in use: <body sty ...

Exploring the functionalities of jQuery and Local Storage: Understanding the Selector's various states

I am currently developing a new feature for font customization on a website. The drop-down menu offers several font options to choose from. When a user clicks on one of these options, the following code is executed: jQuery(function($) { if (localStorage.g ...

When utilizing jQuery to add a <li> element, it suddenly vanishes

? http://jsfiddle.net/AGinther/Ysq4a/ I'm encountering an issue where, upon submitting input, a list item should be created with the content from the text field. Strangely, it briefly appears on my website but not on the fiddle, and no text is appen ...

Resolving the CORS preflight issue with Loopback API in Redux

My current setup involves a client application running on React-Redux and an API app on Loopback. During local testing, I have the client app on port 8080 and the server app on port 3000. While attempting to test Google OAuth (using the loopback-passport ...

Using Zen coding to insert an image source from a selection of options

I am attempting to use zen coding to generate a series of img tags with the src attribute populated by a list of filenames. Below is the list of filenames I have, followed by the desired output: filenameA.jpg someotherone.jpg anotherimage.jpg sample.jpg ...

Is there a way to incorporate the Indian rupee symbol into a Google chart?

I've been trying to incorporate the Indian Rupee symbol into a Google chart using the code below: var formatter = new google.visualization.NumberFormat({ prefix: '&#8377;' }); However, I'm encountering an issue where ...

Avoid Updating State After Adding Row in material-table

When utilizing the material-table library, my goal is to display a different component upon adding a row. Although the code functions as expected, I encountered the following error in the console: Warning: Can't perform a React state update on an unm ...

Jest - Silence greets the test results

Struggling with Jest has been a common theme for me ever since I first attempted to use it. Regardless of the tests I run or the options I try to pass to Jest, I never seem to get the expected 'Pass' or 'Fail' results in the console. In ...

A data table created with Bootstrap is not displayed inline with the pagination feature

Customizing Bootstrap Data Table Code Instructions on how to customize this code: <div class="row"> <div class="col-sm-5"> <div class="dataTables_info" id="example_info" role="status" aria-live="polite"> Showing 1 to 10 of 2 ...

Tips on refreshing a div using jQuery while maintaining the functionality of addEventListener

Hi, I am facing an issue with updating the "div" element. The refresh works fine, but after refreshing when I try to click on the updated "div", the addEventListener in my JavaScript code does not seem to work anymore. Can someone please explain why this i ...

"Enhancing user experience with jQuery hover effects on table

This is an example of the HTML structure: <tr class="row-1 row-first"> <td class="col-1 col-first"> <div class="views-field views-field-field-logo-image"></div> <div class="views-field views-field-field-logo-title"> ...

Tips for utilizing Plunker or JSFiddle to execute Angular2 code

I've been attempting to practice coding programs in Angular 2 using plnkr and jsfiddle. However, every time I try to run them, I encounter issues such as 404 errors or exceptions when I check the developer tools. Can anyone advise on the correct metho ...

The background color is showing the wrong shade

So, I recently created a simple HTML5 website and decided to set the background-color of the header div to #3D7D99. However, when I view it in the browser, it appears as #35728E. Can anyone explain what might be causing this discrepancy? UPDATE: Just to c ...

What is the process for removing a property from the prototype within an array of MongoDB objects?

I have a database in MongoDB/Mongoose where I store user information, including passwords. However, when I want to display a list of contacts on the frontend, I don't want to include the passwords for security reasons. To achieve this, I attempted to ...

The infamous IE7 Bug Caused by CSS HasLayout

Initially, I've reviewed the following articles in order to refresh my knowledge on these topics as I have encountered them before: Position Relative / Absolute / Fixed in IE While the above resources may be helpful for individuals facing these issu ...

Automatically bypassing git conflicts in package.json: A step-by-step guide

We encounter frequent updates to shared npm packages in our app, resulting in multiple pull requests updating the same package version. Consequently, conflicts arise on GitHub when these pulls are merged into the master branch. Is there a way to automati ...

Utilizing Angular to augment existing items in local storage

Hey everyone, I'm facing an issue with localStorage that I can't seem to figure out. I have a form where the first step collects name and gender, and the second step asks for weight and height. The data from step 1 is saved in localStorage, but ...

Error: The function getAuth has not been defined - Firebase

I have included the code snippets from index.html and index.js for reference. The analytics functionality seems to be working fine, but I am facing an issue with authentication due to an error during testing. Thank you for your help. index.html <script ...

What is the best way to ensure that images appear in a square format?

Lately, I've been experimenting with the alpha version of bootstrap 4 for a project. No matter how hard I try, I can't seem to get uploaded images of different sizes to display as squares when displayed. Do you remember how Instagram used to onl ...

personalizing jquery templates

Currently, I am utilizing a jQuery template to showcase specific values. Within this template, I have included an if statement to determine if the age is considered old or not, with the result altering the background color accordingly. Previously, the co ...