skip to Main Content

I’ve written a simple code for an FAQ list; each question is opened on click event and must be manually closed. Is there a way re-work this code so that in the event of clicking on a question to open (slidedown), ones that have been previously been open, automatically slideup to close?

{% javascript %}
(function() {
  $('body').on('click', '.shopify_explorer_faq__question', function() {
    $(this).next('.shopify_explorer_faq__answer').slideToggle(250).toggleClass('active');
    $(this).toggleClass('active');
  });

  $(document).on('shopify:block:select', '#shopify-section-page-shopify_explorer_faq-template', function(event) {
    $(event.target).find('.shopify_explorer_faq__answer').slideDown(250);
  });

  $(document).on('shopify:block:deselect', '#shopify-section-page-shopify_explorer_faq-template', function(event) {
    $(event.target).find('.shopify_explorer_faq__answer').slideUp(250);
  });
}());
{% endjavascript %}

3

Answers


  1. You can do this keeping track of the current opened FAQ box. Just to fix the idea and make it as simple as possible, let’s say each of the FAQ boxes has an id and the boxes themselves are divs:

    <div id="faq-1" class="faq-box">
      Text of the FAQ 1
    </div>
    
    <div id="faq-2" class="faq-box">
      Text of the FAQ 2
    </div>
    
    ...
    
    <div id="faq-n" class="faq-box">
      Text of the FAQ n
    </div>
    

    You can get the behavior you’re looking for like this:

    var current_faq = ''; // Keep track of the current faq box opened
    
    jQuery( '.faq-box' ).on( 'click', function() {
      // Check if it has been clicked the current box
      if ( jQuery( this ).attr( 'id' ) == current_faq ) {
        // It has been clicked the current box, just slide it up to close
        jQuery( this ).removeClass( 'active' ).slideUp();
        // Set current box opened to empty
        current_faq = '';
      else {
        // Slide down this box
        jQuery( this ).addClass( 'active' ).slideDown();
        // Check if there's a current box opened
        if ( current_faq != '' ) {
          // Slide up the current box
          jQuery( current_faq ).removeClass( 'active' ).slideUp();
        }
        // Set the current box
        current_faq = jQuery( this ).attr( 'id' );
      }
    } );
    
    Login or Signup to reply.
  2. You can achieve your desired behaviour by simply adding a line at the top of your first function that uses the .not() selector:

    $('body').on('click', '.shopify_explorer_faq__question', function() {
      $('.shopify_explorer_faq__question').not(this).next('.shopify_explorer_faq__answer').slideUp(250);
      $(this).next('.shopify_explorer_faq__answer').slideToggle(250).toggleClass('active');
      $(this).toggleClass('active');
    });
    
    Login or Signup to reply.
  3. HTML

    Assuming the HTML is a alternating pattern of .question and .answer scheme.

    <ul class="faq">
      <li class="question">...</li>
      <li class="answer">...</li>
      ...
    </ul>
    

    Narrow down the primary selector to .faq. $("body") and $(document) should be used for certain events like "key" or "load" event types — not common events like "click".


    jQuery

    The second parameter event.data is used to designate this (in this circumstance is also event.target). In the example below .question is this:

    $('.faq').on('click', '.question', function(event) {...
    

    Reference $(this).next('.answer') with a variable. A variable referencing a jQuery Object is commonly prefixed with a $ (recommended but not required).

    let $answer = $(this).next('.answer');
    

    The desired behavior is that of an accordion:

    • When an element among multiple alike element siblings is clicked (.question that is this or event.target), will toggle open (and/or its associated element – $answer) if it was originally closed and vice versa.

      $answer.slideToggle(250).toggleClass('active');
      $(this).toggleClass('active');
      
    • All sibling elements will close with the exception of this (and associated elements if applicable). The exception can be selected by using the .not() method.

      $('.question').not(this).removeClass('active')
      $('.answer').not($answer).slideUp(250).removeClass('active');
      

    'shopify:block:select/deselect' events are non-standard events that are unique to the Shopify platform. Not 100% sure if the following would work, but if they can be delegated with the .on() method, then it could probably be triggered with the .trigger() method.

    if ($(this).hasClass('active')) {
      $answer.trigger('shopify:block:select');
      $('.answer').not($answer).trigger('shopify:block:deselect');
    } else {
      $('.answer').trigger('shopify:block:deselect');
    } 
    

    Demo

    $(function() {
      $('.answer').hide();
      $('.faq').on('click', '.question', function(e) {
        let $answer = $(this).next('.answer');
        $answer.slideToggle(250).toggleClass('active');
        $(this).toggleClass('active');
        $('.question').not(this).removeClass('active');
        $('.answer').not($answer).slideUp(250).removeClass('active');
        if ($(this).hasClass('active')) {
          $answer.trigger('shopify:block:select');
          $('.answer').not($answer).trigger('shopify:block:deselect');
        } else {
          $('.answer').trigger('shopify:block:deselect');
        }
      });
    });
    :root {
      font: 400 3vw/6vh Arial
    }
    
    li {
      padding: 3vh 2vw 1vh;
      margin-bottom: 2vh
    }
    
    .question {
      cursor: pointer
    }
    
    .answer {
      list-style: none;
      color: blue
    }
    
    .active {
      text-decoration: underline;
      font-weight: 900
    }
    <main>
      <section>
        <header>
          <h1>FAQ</h1>
        </header>
        <ul class='faq'>
          <li class='question'>Question?</li>
          <li class='answer'>Answer.</li>
          <li class='question'>Question?</li>
          <li class='answer'>Answer.</li>
          <li class='question'>Question?</li>
          <li class='answer'>Answer.</li>
          <li class='question'>Question?</li>
          <li class='answer'>Answer.</li>
          <li class='question'>Question?</li>
          <li class='answer'>Answer.</li>
        </ul>
      </section>
    </main>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search