見出し画像

【JS/jQuery編🚩】③世界一簡単なアコーディオン解説!

JSの解説をしていきます!
まだhtml編とcss編をみていない方は先にこちらをみて頂ければと思います⭐️・:*+.\(( °ω° ))/.:+⭐️

今回もりもりになってしまってほんとにっ🍵‼️
ついてきて頂いてますでしょうか🥺感謝。

jsはhtmlにクラスを追加する箇所があるので、htmlの内容も貼っておきます!見ながら照らし合わせて頂けたらと思います。


🔸前回のHTML

<section class="sectionQuestions"> ①
  <div class="questionBlocks"> ②
    <div class="questionBlocks_item"> ③

      <div class="faqQuestion"> ⬅️Aグループ(QA全体を包む)
        <h2 class="question">Q.昨日ご飯何食べましたか?</h2> ❶
        <div class="questionToggle js-faq-toggle"><!-- ここにjs openタグ追加 --> ❷
          <span></span> ❸トグル
          <span></span> ❸トグル
        </div>
        <div class="js-faq-answer-container"> ⬅️Bグループ(Aのみ包む)
          <div class> ❶
            <div class="answerFlexContainer js-faq-answer-content"><!-- ここにjs showタグ追加 --> ❷
              <p class="answer">A.カレーです。</p> ❸
            </div>
          </div>
        </div>
      </div>

    </div>
  </div>  
</section>


1.HTMLにopenクラスを追加したり外したりしていこう!!

Array.prototype.forEach.call(document.querySelectorAll('.question'), function(ele) {
    ele.addEventListener('click', function() {
        let toggle = ele.nextElementSibling;
        if (toggle.classList.contains('open')) {
            closeAnswer(toggle)
        } else {
            openAnswer(toggle)
        }
    }, false);
});

document.querySelectorAll('.question') は、クラス名が .question であるすべての要素を取得します。これにより、FAQの質問要素をリストとして取得します。
ちなみに.question は、HTMLの要素に設定されたクラス名です。
Array.prototype.forEach.call を使用して、querySelectorAll で取得したリストに対して forEach を適用します。

PCさんがどの部分の操作をするのかを理解してもらうために書いてます。この部分を今から動かすからよろしくね!の行程です。

click', function()で前半で取得した.question部分がクリックされたときの動きを書いています。

let toggle = ele.nextElementSibling;で二個目にかかれたトグル部分。つまりアンサーゾーンのtoggle)が open クラスを持っているかどうかを確認し、open クラスがあれば回答を閉じ、なければ回答を開くようにしています。

もうちょっと詳しく、、、⭐️

eleはここでいう.question(html)に当たります。
.nextElementSiblingは同じ親要素の.questionを持つって次に位置する兄弟要素のことです。
ここでいう
<div class="questionToggle js-faq-toggle"><!-- ここにjs openタグ追加 --> ❷の部分です。

let toggle = ele.nextElementSibling;にすることで、” toggle”の箱にele.nextElementSibling;を代入しているイメージです。

let toggle = ele.nextElementSibling;
        if (toggle.classList.contains('open')) {
            closeAnswer(toggle)
        } else {
            openAnswer(toggle)
        }

classList.containsを使って指定されたクラス"open"が要素に追加されます。
これでopenクラスがHTML内でついたり取れたりしてくれます。

もしこのコードがオール日本語でいいなら。楽なのに〜。

Array.prototype.forEach.call(document.querySelectorAll('.question'), function(ele)
😎『PCさんhtmlのquestionの部分とってきて』

{ ele.addEventListener('click', function()
😎『さっきのhtmlのquestionのがクリックされた時にさっ』

{ let toggle = ele.nextElementSibling;
😎『htmlのquestionの同じグループの次に書かれてるもの。toggleってゆう動作のチームにしちゃお!』

if (toggle.classList.contains('open'))
{ closeAnswer(toggle) }else
{ openAnswer(toggle) } }, false); });
😎『もしtoggleがopenを持っていたら。つけたり外したりしてね。』

会話形式にしてみた。

JQueryの方が楽じゃない?

ふぅ。jsってPCに伝えること多すぎじゃない?😂
そう考えたらjQueryって楽だし視覚的にもわかりやすい。
JQuery版はこちら⬇️

$('.question').on('click', function() { 
let toggle = $(this).next(); 
if (toggle.hasClass('open')) {
 closeAnswer(toggle);
 } else {
 openAnswer(toggle);
 } 
});


2. openがついた時の動作を書いていこう!

function openAnswer(toggle) {
    var answerContainer = toggle.parentNode.querySelector('.js-faq-answer-container')
    var answerContent = answerContainer.querySelector('.js-faq-answer-content')
    toggle.classList.add('open');
    answerContainer.style.height = (answerContent.clientHeight + 30) + "px"
    answerContent.classList.add('show')
}

toggle.parentNode.querySelector('.js-faq-answer-container') で、質問の親要素から .js-faq-answer-container クラスを持つ要素を取得します。これがアンサー部分のコンテナになります。

次に、answerContainer.querySelector('.js-faq-answer-content') で、実際のアンサー内容を含む要素を取得します。

toggle.classList.add('open'); で、toggle 要素(回答のコンテナ)に open クラスを追加します。これにより、アンサー部分が開かれます✨

answerContainer.style.height = (answerContent.clientHeight + 30) + "px" で、アンサー部分のコンテナの高さを設定します。この時、30pxの余白を追加しています。この時の余白はお好みでOK🎵

なんでanswerContainer.style.height = (answerContent.clientHeight + 30) + "px"を指定してるのか?

ここでふと疑問。
そういえばCSSに開いた時の高さ書いてない。。
前回のCSSの記事でも、
アンサー部分にはデフォルトでheight:0で見えない状態に指定ます。
jsで高さを追加する事で回答に合わせた高さを支持する事ができるんで!なんて便利✨

検証ツールで見てみよう!

閉じた時
開いた時

じゃあ 30) + "px"これ何?😀
ってゆう話なのですが、これは高さでなく余白部分になります。
これがないと高さキチキチに回答が入ってしまうので。marginやpaddingのように幅をもたす事ができます。

私も作っていく中で、なんか野暮ったい仕上がりだなー。😭ってなる事多いので、余白を上手く使えるようになりたい。


最後に、answerContent.classList.add('show') で、アンサー内容を表示するために show クラスを追加します。
hrmlでいう<div class="answerFlexContainer js-faq-answer-content"><!-- ここにjs showタグ追加 -->部分です。

3. openが外れた時の動作を書いていこう!

function closeAnswer(toggle) {
    toggle.classList.remove('open');
    var answerContainer = toggle.parentNode.querySelector('.js-faq-answer-container')
    answerContainer.style.height = "0"
    answerContainer.querySelector('.js-faq-answer-content').classList.remove('show')
}

toggle.classList.remove('open'); で、toggle 要素から open クラスを削除します。アンサー部分が閉じられた状態になります。

answerContainer.style.height = "0" で、回答コンテナの高さを0に設定し、アンサー部分を隠します。👋サヨナラsayonara!!

answerContainer.querySelector('.js-faq-answer-content').classList.remove('show') で、アンサーの内容の show クラスを削除して、表示されないようにします。

JQueryの方が楽じゃない?パート2!!

function openAnswer($toggle) {
    var $answerContainer = $toggle.closest('.js-faq-answer-container');
    var $answerContent = $answerContainer.find('.js-faq-answer-content');
    
    $toggle.addClass('open');
    $answerContainer.css('height', ($answerContent.outerHeight() + 30) + 'px');
    $answerContent.addClass('show');
}

function closeAnswer($toggle) {
    $toggle.removeClass('open');
    var $answerContainer = $toggle.closest('.js-faq-answer-container');
    
    $answerContainer.css('height', '0');
    $answerContainer.find('.js-faq-answer-content').removeClass('show');
}

クエリーの方がコードがわかりやすい。。。

さ!終わりましょ🍪。

ほんとにお疲れ様です。
参考サイトはJSを使っているのでJQueryの方が好みの方はこちらをコピーしてみてください。

脳が🧠パンクしそうなので私もremoveClass('💻')します。ww
こーゆーコードギャグつくろ。にやにや。

でわっ🌺sayonara!!


最後まで読んでいただきありがとうございます。この記事が良かったらいいね&フォローお願いします。励みになります🙇‍♀️❤️

Xから今回作った動画見れます。dm依頼も📩


いいなと思ったら応援しよう!