Складные заголовки / аккордеон из разметки, экспортируемой html - PullRequest
0 голосов
/ 22 декабря 2019

Я пытаюсь создать веб-страницу, где каждый h2 выступает в роли гармошки. При нажатии содержимое под заголовком должно расшириться (после того, как оно будет скрыто).

Я прошел через кучу учебных пособий, но они обычно используют определенный HTML (используя ссылки или кнопки), но мой HTML экспортируется изязык разметки (orgmode), поэтому его нельзя настроить таким образом (по крайней мере, я бы предпочел этого не делать). Я не смог изменить ни одну из них в соответствии с моими потребностями.

Я не уверен, что лучшим решением будет использование CSS или JavaScript или обоих. Вот HTML-тело:

  <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">
      </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>

Из того, что я могу сказать, я пытаюсь скрыть / показать класс outline-3 при нажатии h2 в outline-2.

1 Ответ

0 голосов
/ 22 декабря 2019

Поскольку вы не можете контролировать разметку, вот как вы можете решить это:

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>

Делаем содержимое разборным:

Примечание: в этом примере я использую h2 для триггераи брат div для содержания.

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>

Для примечания, в html5 есть элемент [details] , который создает виджет раскрытия, в котором информация видна толькокогда виджет переключается в открытое состояние и должен использоваться здесь для получения семантики, SEO и т. д.

Несколько полезных ссылок MDN, где вы можете узнать гораздо больше:

querySelectorAll

nextElementSibling

: не селектор

Надеюсь, что решить вашу проблему и помочьдругие с похожим вопросом. Наслаждайтесь кодом!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...