Collapsible headings/accordion from markup exported html

前端 未结 1 1194
忘了有多久
忘了有多久 2021-01-28 19:56

I\'m trying to achieve a webpage with each h2 acting as items of an accordion. When clicked, the contents under the heading should expand (after being hidden).

I\'ve bee

相关标签:
1条回答
  • 2021-01-28 20:05

    Since you can't control the markup, this is how you can solve this:

    const headerH2 = document.querySelectorAll('#content h2'); // first we put all wanted headers on variable
    const outlinContent =  document.querySelectorAll("div[class^=outline]"); // you can use regex to catch all div begining with 'outline-'
    outlinContent.forEach(function(item){  if (item.id !== 'outline-container-org233deb6') { item.classList.add('hide'); }  }); // hide  them, skipping the one contain the trigger
    headerH2[0].addEventListener('click', function() { // adding click listener to the first (or the only one in this example
      outlinContent.forEach(function(item){  if (item.id !== 'outline-container-org233deb6') {item.classList.toggle('hide'); } }); // toggle content display
    });
    .hide {display: none;}
    <div id="content">
      <h1 class="title">Recipes</h1>
      <div id="outline-container-org233deb6" class="outline-2">
        <h2 id="org233deb6">Tea</h2>
        <div class="outline-text-2" id="text-org233deb6">CONTENT</div>
        <div id="outline-container-orgfbba0f7" class="outline-3">
          <h3 id="orgfbba0f7">Ingredients</h3>
          <div class="outline-text-3" id="text-orgfbba0f7">
            <ul class="org-ul">
              <li>1 tbsp tea leaves</li>
              <li>1 cup water</li>
            </ul>
          </div>
        </div>
        <div id="outline-container-orgcc98fa7" class="outline-3">
          <h3 id="orgcc98fa7">Instructions</h3>
          <div class="outline-text-3" id="text-orgcc98fa7">
            <ol class="org-ol">
              <li>Boil some water</li>
              <li>Put in tea leaves</li>
              <li>Strain</li>
            </ol>
          </div>
        </div>
      </div>
    </div>

    Making content collapsible:

    Note: in this example i use h2 for the trigger and sibling div to hold the content.

    const headerH2 = document.querySelectorAll('#content h2'); // first we put all wanted headers on variable
    for (let i=0; i < headerH2.length; i++) { // you can use the modarn forEach, but this is much faster
      let nextDiv = headerH2[i].nextElementSibling; // this is how you select the next element after the header
      nextDiv.classList.add('hide'); // we hide all of them by default
      headerH2[i].addEventListener('click', function() { // now we are adding click listener:
      if (document.querySelector('#content div:not(.hide)')) {document.querySelector('#content div:not(.hide)').classList.add('hide')}; // this will close other open content divs if they exist
      nextDiv.classList.remove('hide'); // this will show the right content when click
      });
    }
    .hide {display: none;}
    <div id="content">
      <h2>TITLE 1</h2>
      <div>CONTENT 1</div>
      <h2>TITLE 2</h2>
      <div>CONTENT 2</div>
      <h2>TITLE 3</h2>
      <div>CONTENT 3</div>
      <h2>TITLE 4</h2>
      <div>CONTENT 4</div>
      <h2>TITLE 5</h2>
      <div>CONTENT 5</div>
      <h2>TITLE 6</h2>
      <div>CONTENT 6</div>
    </div>

    For a side note, html5 has the [details] element that create a disclosure widget in which information is visible only when the widget is toggled into an "open" state, and should be using here in order to get the semantic and SEO etc...

    Some helpful MDN links where you can learn much more:

    querySelectorAll

    nextElementSibling

    :not selector

    Hope that solved your problem and help others with similar question. Enjoy Code!

    0 讨论(0)
提交回复
热议问题