Home > OS >  Close previously opened accordion with pure JavaScript
Close previously opened accordion with pure JavaScript

Time:04-19

In a Shopify product page that has three accordions, I'm trying to add some JavaScript code to ensure only the first accordion is open by default on page load and all previously opened ones are closed.

With the following, I could only get the first accordion to appear open when the page loads. I need to add ability to close all previously open accordions when another one is clicked on. Could you please help with that? I'm looking only for a pure JS solution. The page I need to do this on is here

window.onload = function() {
  // Keep the first accordion open by default.
  let allAccordionElements = document.querySelectorAll(".accordion__item");
  if (allAccordionElements.length > 0) {
    allAccordionElements[0].click(); 
  }
};

The HTML extract from the page linked above is:

<div >
    <input type="radio" id="a66f79b6-abe9-4e4e-9e91-0994a9c01b1b--close" name="a66f79b6-abe9-4e4e-9e91-0994a9c01b1b">
    <label >
        <input type="radio" name="a66f79b6-abe9-4e4e-9e91-0994a9c01b1b">
        <span >Description<label  for="a66f79b6-abe9-4e4e-9e91-0994a9c01b1b--close"></label></span>
        <div >
                        <div><p>Send them a standout gift that’s environmentally friendly and multi-functional. We’ve paired our classic cedar wood journal with a black precision-point pen to add even more beauty to the written word. A sleek, double-insulated travel tumbler helps bring their favorite beverage along for the ride—and keeps it hot or cold—from coffee to wine. Choose this gift to celebrate a colleague, relative, or friend while also supporting reforestation efforts and eco-friendly production.<br></p>
<p>Each gift is packaged in our recyclable Packed with Purpose box and includes:<br></p>
<style type="text/css"><!--
td {border: 1px solid #ccc;}br {mso-data-placement:same-cell;}
--></style>
<ul>
<li>Handcrafted classic wood journal, USA-Made (6" x 9")</li>
<li>Quick-drying, smudge-resistant fine point pen in black</li>
<li>Insulated stainless steel black beverage tumbler with removable drinking lid, 10 oz.<br>
</li>
<li>An artful booklet that showcases the stories of our Impact Partners and the meaningful impact our gifts create</li>
</ul>
<p></p></div>
        </div>
    </label>
</div>
<div >
    <input type="radio" id="cfa26ceb-62c7-4683-996a-6a3f79898c4d--close" name="cfa26ceb-62c7-4683-996a-6a3f79898c4d">
    <label >
        <input type="radio" name="cfa26ceb-62c7-4683-996a-6a3f79898c4d">
        <span >Impact<label  for="cfa26ceb-62c7-4683-996a-6a3f79898c4d--close"></label></span>
        <div >
<div><p></p>
<style type="text/css"><!--
td {border: 1px solid #ccc;}br {mso-data-placement:same-cell;}
--></style>
<p><strong><a href="https://packedwithpurpose.gifts/our-impact/purposeful-purveyors/woodchuck-usa/" target="_blank"><span data-sheets-userformat="{&quot;2&quot;:513,&quot;3&quot;:{&quot;1&quot;:0},&quot;12&quot;:0}" data-sheets-value="{&quot;1&quot;:2,&quot;2&quot;:&quot;WOODCHUCK USA&quot;}">WOODCHUCK US</span>A</a></strong>&nbsp;-&nbsp;Creates eco-friendly wood products and plants one tree for every purchase made to help reforest the world; made in the USA</p>
<p><strong><a href="https://packedwithpurpose.gifts/our-impact/purposeful-purveyors/uchida/" data-mce-href="https://packedwithpurpose.gifts/our-impact/purposeful-purveyors/uchida/">Marvy Uchida</a>&nbsp;</strong>- Inspires art and creativity for all through their high-quality arts, crafts, and office products for more than 40 years</p>
<p><span data-sheets-value="{&quot;1&quot;:2,&quot;2&quot;:&quot;Reduces waste and energy consumption across the entire supply chain, and packages with 100% recycled cardboard. &quot;}" data-sheets-userformat="{&quot;2&quot;:13185,&quot;3&quot;:{&quot;1&quot;:0},&quot;10&quot;:2,&quot;11&quot;:4,&quot;12&quot;:0,&quot;15&quot;:&quot;Calibri&quot;,&quot;16&quot;:8}"><a href="https://packedwithpurpose.gifts/our-impact/purposeful-purveyors/ecovessel/"><strong>Ecovessel</strong></a>&nbsp;- Creates premium reusable drinkware to reduce the world's dependence on single-use plastics; 1% for the Planet member, woman-founded </span></p></div>
        </div>
    </label>
</div>
<div >
    <input type="radio" id="04f337be-f8e2-41b0-9f06-740077e6b722--close" name="04f337be-f8e2-41b0-9f06-740077e6b722">
    <label >
        <input type="radio" name="04f337be-f8e2-41b0-9f06-740077e6b722">
        <span >Additional Info<label  for="04f337be-f8e2-41b0-9f06-740077e6b722--close"></label></span>
        <div >
                <p>Given the highly seasonal nature of gifting and the unique supply chain challenges presented by COVID-19, Packed with Purpose requests flexibility on the flavors, scents, and specific products featured in each gift. Our team thoroughly vets all products to guarantee any substitutions are of equal quality and impact and encompass the high standards we require of all our purveyors.</p>
        </div>
    </label>
</div>

CodePudding user response:

I would do it like this. The helper functions act directly on the DOM elements, rather than simulating a click.

//  an array of elements
const allAccordionElements = Array.from(document.querySelectorAll(".accordion__item"));

const run_code = () => {

  //  some helper functions
  const showTab = (el) => {
    el.style.display = "flex";
  };
  const hideTab = (el) => {
    el.style.display = "none";
  };

  if (allAccordionElements.length > 0) {
    
    // open the first one
    showTab(allAccordionElements[0]);
    
    //  hide all others
    allAccordionElements.slice(1).forEach(thisTab => {
      hideTab(thisTab);
    });  
  
  }
  
};

document.getElementById('run').addEventListener('click',run_code);
.accordion__item {
  padding: 0.5em;
  margin: 0.5em;
  border: 2px dotted green;
  background-color: silver;
  display: flex;
}
<div >

  <div >
    item one
  </div>
  <div >
    item two
  </div>
  <div >
    item three
  </div>

</div>

<button id="run">run code</button>

CodePudding user response:

The accordion controls set the max-height CSS property to either 0 or 420. It is as simple as setting each accordion accordingly (hehe).

To OPEN:

.accordion__item .accordion__item--content { max-height: 420; }

To CLOSE:

.accordion__item .accordion__item--content { max-height: 0; }

Solution is to replace the click event with this:

EDIT: I made a typo in the first post. Remove [0] and replace with the forEach loop as shown below.

window.onload = function() {
  let allAccordionElements = document.querySelectorAll(".accordion__item");
  if (allAccordionElements.length > 0) {
    // Close all to start
    allAccordionElements.forEach(a=>a.style.maxHeight = "0"); 
    // Open the first
    allAccordionElements[0].style.maxHeight = "420"; 
  } 
};
  • Related