I have the following html structure
<div class="accordion-container">
<ul class="accordion">
<li class="accordion-header">
<a class="is-active link">Accordion header<i class="accordion-header-icon"></i></a>
<div class="accordion-content js-accordion-content">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eum, quos!</p>
</div>
</li>
<li class="accordion-header">
<a class="link">Accordion header<i class="accordion-header-icon"></i></a>
<div class="accordion-content js-accordion-content">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nulla sed ducimus iusto, atque veniam, laborum ratione quibusdam sapiente. Sint.</p>
</div>
</li>
<li class="accordion-header">
<a class="link">Accordion header<i class="accordion-header-icon"></i></a>
<div class="accordion-content js-accordion-content">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nulla sed ducimus iusto, atque veniam, laborum ratione quibusdam sapiente. Sint.</p>
</div>
</li>
<li class="accordion-header">
<a class="link">Accordion header<i class="accordion-header-icon"></i></a>
<div class="accordion-content js-accordion-content">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nulla sed ducimus iusto, atque veniam, laborum ratione quibusdam sapiente. Sint.</p>
</div>
</li>
</ul>
</div>
and this css
.accordion-content {
display: none; }
I'm trying to populate the accordion-content with content from a json file only when click on each accordion header (.link)
I've tried this but it doesn't work as intended. When I click on a header it populates all the other accordion-content.
$(document).ready(function () {
$('.accordion').each(function (index) {
$(this).children('li').first().children('a').addClass('is-active').next().addClass('is-open').show();
});
$('.accordion').on('click', 'li > a', function (event) {
if (!$(this).hasClass('is-active')) {
event.preventDefault();
var accordionTabs = $(this).closest('.accordion');
accordionTabs.find('.is-open').removeClass('is-open').slideUp('fast');
$(this).next().toggleClass('is-open').slideToggle('fast');
accordionTabs.find('.is-active').removeClass('is-active');
$(this).addClass('is-active').closest('.accordion-content', function () {
$.getJSON('public/js/result.json', function (jd) {
$('.js-accordion-content').html('<p>Name: ' + jd.name + '</p>');
$('.js-accordion-content').append('<p>Age : ' + jd.age+ '</p>');
$('.js-accordion-content').append('<p>Sex: ' + jd.sex+ '</p>');
});
});
} else {
event.preventDefault();
}
});
});
The json looks like this:
{
"name": "Zara Ali",
"age" : "67",
"sex": "female"
}
jQuery's closest
method does not accept an anonymous function as the 2nd argument, and therefore this never fires in your code.
$(this).addClass('is-active').closest('.accordion-content', function () {
I don't see you doing anything with the .accordion-content
selector anyway, so just omit it.
$(this).addClass('is-active');
$.getJSON(....
You will also need to cache a reference to your element that fired the click event in order to reference in within the result of your ajax callback:
var self = $(this);
We need to natively wrap it as a jQuery object because the 2nd argument we pass in as context needs to apply .parent()
in order to actually get the .js-accordion-content
element.
$('.js-accordion-content', self.parent()).html('<p>Name: ' + jd.name + '</p>');
$('.js-accordion-content', self.parent()).append('<p>Age : ' + jd.age + '</p>');
$('.js-accordion-content', self.parent()).append('<p>Sex: ' + jd.sex + '</p>');
The query ".js-accordion-content" is ambiguous to all similar elements with the same class name. Isolate it to the current "accordion"
replace:
$(this).addClass('is-active').closest('.accordion-content', function () {
$.getJSON('public/js/result.json', function (jd) {
$('.js-accordion-content').html('<p>Name: ' + jd.name + '</p>');
$('.js-accordion-content').append('<p>Age : ' + jd.age+ '</p>');
$('.js-accordion-content').append('<p>Sex: ' + jd.sex+ '</p>');
});
with
var self = this;
$(this).addClass('is-active').closest('.accordion-content', function () {
$.getJSON('public/js/result.json', function (jd) {
$('.js-accordion-content', self).html('<p>Name: ' + jd.name + '</p>');
$('.js-accordion-content', self).append('<p>Age : ' + jd.age+ '</p>');
$('.js-accordion-content', self).append('<p>Sex: ' + jd.sex+ '</p>');
});
Notice the use of self
referencing the accordion.