Метод JQuery slideToggle ()

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

{% 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 ответа


Вы можете сделать это, отслеживая текущий открытый FAQ. Просто чтобы исправить идею и сделать ее настолько простой, насколько это возможно, скажем, у каждого из полей FAQ есть идентификатор, а сами блоки - это div:

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

Вы можете получить поведение, которое вы ищете, вот так:

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' );
  }
} );

Вы можете достичь желаемого поведения, просто добавив строку вверху вашей первой функции, которая использует селектор .not() :

$('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');
});

HTML

Предполагая, что HTML является чередующимся шаблоном .question и .question .

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

.faq основной селектор до .faq . $("body") и $(document) должны использоваться для определенных событий, таких как типы событий "key" или "load" не для обычных событий, таких как "click" .


JQuery

Второй параметр event.data используется для обозначения this (в этом случае также является event.target ). В приведенном ниже примере .question this :

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

Ссылка $(this).next('.answer') с переменной. Переменная, ссылающаяся на объект jQuery, обычно имеет префикс $ (рекомендуется, но не обязательно).

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

Желаемое поведение - это поведение аккордеона :

  • Если .question элемент среди нескольких одинаковых элементов .question ( .question который является this или event.target ), откроется переключение (и / или связанный с ним элемент - $answer ), если он был изначально закрыт, и наоборот.

    $answer.slideToggle(250).toggleClass('active');
    $(this).toggleClass('active');
    
  • Все родственные элементы закроются за исключением this (и связанных элементов, если применимо). Исключение можно выбрать с помощью .not() .

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

'shopify:block:select/deselect' это нестандартные события, уникальные для платформы Shopify . Не уверен на 100%, сработает ли следующее, но если их можно делегировать с помощью .on() , то, вероятно, его можно .trigger() с помощью .trigger() .

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

демонстрация

$(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>


Есть идеи?

10000