Я написал простой код для списка часто задаваемых вопросов; каждый вопрос открывается по событию клика и должен быть закрыт вручную. Есть ли способ переделать этот код так, чтобы в случае нажатия на вопрос, который нужно открыть (слайдон), те, которые были ранее открыты, автоматически сдвигаются, чтобы закрыться?
{% 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 является чередующимся шаблоном .question
и .question
.
<ul class="faq">
<li class="question">...</li>
<li class="answer">...</li>
...
</ul>
.faq
основной селектор до .faq
. $("body")
и $(document)
должны использоваться для определенных событий, таких как типы событий "key"
или "load"
не для обычных событий, таких как "click"
.
Второй параметр 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>