skip to Main Content

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() {
  var accItem = document.getElementsByClassName('accordion__item');
  // Keep the first accordion open by default.
  for (i = 0; i < accItem.length; i++) {
    console.log("Within first for loop");
    accItem[i].addEventListener('click', toggleItem, false);
  }
  function toggleItem() {
    var itemClass = this.parentNode.className;
    for (i = 0; i < accItem.length; i++) {
      console.log("Within second for loop");
      accItem[i].className = 'accordion__item close';
    }
    if (itemClass == 'accordion__item close') {
        this.parentNode.className = 'accordion__item open';
    }
  }    
 };

The HTML extract from the page linked above is:

<div class="col-12 accordion product__accordion margin__bottom--reduced">
    <input type="radio" id="a66f79b6-abe9-4e4e-9e91-0994a9c01b1b--close" name="a66f79b6-abe9-4e4e-9e91-0994a9c01b1b">
    <label class="accordion__item">
        <input type="radio" name="a66f79b6-abe9-4e4e-9e91-0994a9c01b1b">
        <span class="accordion__item--title">Description<label class="collapse" for="a66f79b6-abe9-4e4e-9e91-0994a9c01b1b--close"></label></span>
        <div class="accordion__item--content inherit ">
                        <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 class="col-12 accordion product__accordion margin__bottom--reduced">
    <input type="radio" id="cfa26ceb-62c7-4683-996a-6a3f79898c4d--close" name="cfa26ceb-62c7-4683-996a-6a3f79898c4d">
    <label class="accordion__item">
        <input type="radio" name="cfa26ceb-62c7-4683-996a-6a3f79898c4d">
        <span class="accordion__item--title">Impact<label class="collapse" for="cfa26ceb-62c7-4683-996a-6a3f79898c4d--close"></label></span>
        <div class="accordion__item--content inherit ">
<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 class="col-12 accordion product__accordion ">
    <input type="radio" id="04f337be-f8e2-41b0-9f06-740077e6b722--close" name="04f337be-f8e2-41b0-9f06-740077e6b722">
    <label class="accordion__item">
        <input type="radio" name="04f337be-f8e2-41b0-9f06-740077e6b722">
        <span class="accordion__item--title">Additional Info<label class="collapse" for="04f337be-f8e2-41b0-9f06-740077e6b722--close"></label></span>
        <div class="accordion__item--content inherit ">
                <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>

2

Answers


  1. 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 class="accordion">
    
      <div class="accordion__item">
        item one
      </div>
      <div class="accordion__item">
        item two
      </div>
      <div class="accordion__item">
        item three
      </div>
    
    </div>
    
    <button id="run">run code</button>
    Login or Signup to reply.
  2. 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 .accordion__item--content");
      if (allAccordionElements.length > 0) {
        // Close all to start
        allAccordionElements.forEach(a=>a.style.maxHeight = "0"); 
        // Open the first
        allAccordionElements[0].style.maxHeight = "420"; 
      } 
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search