Reputation: 25
I need help with closing other panels once I open a click on a different panel. I have been trying to get my head around it for the past week but I'm just not able to.
I don't want to use a jquery library, I want to be able to code this code directly into my website.
I think the javascript code needed is simple in concept but hard to write for someone like me. I still don't exactly understand how javascript commands, functions, etc. work.
Any help or guidance is greatly appreciated!
Here is my code:
HTML
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="accordion.css">
</head>
<body>
<h3 class="accordion">Basics of Sailing</h3>
<div class="panel">
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Before Choosing a Sailboat</h4>
<p>Before looking for a boat to buy, you need to first know what you want to do with the boat, whether that is to go on vacation, learn how to sail, competitions or recreational sailing.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Car Topping & Trailing</h4>
<p>It's a good practice to carry the boat upside-down to allow the sides to rest on the side of the roof racks and to prevent the hull from getting damaged.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Safety Equipment</h4>
<p>You have to always have to think: safety first. Sailing is a dangerous and could result in severe injuries or death if the proper precautions are not taken.</p>
</div>
</div>
<h3 class="accordion">Basics of Sailing</h3>
<div class="panel">
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Before Choosing a Sailboat</h4>
<p>Before looking for a boat to buy, you need to first know what you want to do with the boat, whether that is to go on vacation, learn how to sail, competitions or recreational sailing.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Car Topping & Trailing</h4>
<p>It's a good practice to carry the boat upside-down to allow the sides to rest on the side of the roof racks and to prevent the hull from getting damaged.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Safety Equipment</h4>
<p>You have to always have to think: safety first. Sailing is a dangerous and could result in severe injuries or death if the proper precautions are not taken.</p>
</div>
</div>
<script src="accordion.js"></script>
</body>
</html>
CSS
.accordion {
background-color: #2364aa;
color: #ffffff;
cursor: pointer;
padding: 18px;
border: none;
text-align: left;
outline: none;
font-size: 21px;
transition: 0.4s;
}
.open, .accordion:hover {
background-color: #205A99;
}
.accordion:after {
content: '\f067';
font-family: "Font Awesome 5 Free";
color: #ffffff;
float: right;
font-size: 1.25em;
line-height: 25px;
}
.open:after {
content: "\2212";
}
.panel {
max-height: 0;
overflow: hidden;
transition: 0.2s ease-out;
}
.panel-body {
padding: 18px 0;
}
@media only screen and (min-width: 960px) {
.container {
display: table;
box-sizing: border-box;
}
.row .col {
margin: 10px 0;
}
.col {
display: table-cell;
}
.col.middle {
vertical-align: middle;
}
.col-2 {
width: 50%;
padding-right: 72px;
}
.col-4 {
width: 33.33333333333333333%;
padding-right: 72px;
}
}
Javascript
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function() {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.maxHeight) {
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight + "px";
}
});
}
Upvotes: 0
Views: 3757
Reputation: 21
This is a class called Accordion in Vanilla js. It mostly shows the functionality in javascript , style is not good :)
class Accordion {
constructor(AccordionData) {
// State
this.data = AccordionData;
// View Layer
this.mainContainer = document.querySelector('.container');
this.allAccordionDetailsElements = [];
this.init();
}
init() {
this.createAccordions();
this.bindEvents();
}
createAccordions() {
this.data.forEach(acc => {
let accordionHTML = this.generateHTML(acc);
this.mainContainer.appendChild(accordionHTML);
});
this.allAccordionDetailsElements = document.querySelectorAll('.accordion-details');
}
checkIfCurrentTarget(targetEl, detailsEl) {
return detailsEl.dataset.target === targetEl.id;
}
getDisplayStatus(element) {
return element.style.display;
}
toggleDetailsVisibility(detailsEl) {
const isVisible = this.getDisplayStatus(detailsEl) === 'block';
if (!isVisible) {
detailsEl.style.display = 'block';
} else {
detailsEl.style.display = 'none';
}
}
hideAllDetails() {
this.allAccordionDetailsElements.forEach(detailsSection => {
detailsSection.style.display = 'none';
});
}
bindEvents() {
this.mainContainer.addEventListener('click', (e) => {
if (typeof e === 'undefined') return;
const targetEl = e.target;
const isAccordionHeader = targetEl.classList.contains('accordion-header');
if (isAccordionHeader) {
this.hideAllDetails();
this.allAccordionDetailsElements.forEach(detailsSection => {
if (this.checkIfCurrentTarget(targetEl, detailsSection)) {
this.toggleDetailsVisibility(detailsSection)
}
});
}
});
}
generateHTML(accordionElData) {
const { id, headerText, detailsText } = accordionElData;
const sectionEl = document.createElement('section');
sectionEl.className = 'accordion-container';
const headerEl = document.createElement('button');
headerEl.type = 'button';
headerEl.className = 'accordion-header';
headerEl.textContent = headerText;
headerEl.id = id;
const articleEl = document.createElement('article');
articleEl.className = 'accordion-details';
articleEl.textContent = detailsText;
articleEl.dataset.target = id;
sectionEl.appendChild(headerEl);
sectionEl.appendChild(articleEl);
return sectionEl;
}
}
const AccordionData = [
{
id: 'acc-1',
headerText: 'Section 1',
detailsText: 'This is dummy Text for Section 1'
},
{
id: 'acc-2',
headerText: 'Section 2',
detailsText: 'This is dummy Text for Section 2'
},
{
id: 'acc-3',
headerText: 'Section 3',
detailsText: 'This is dummy Text for Section 3'
}
];
window.addEventListener('DOMContentLoaded', () => {
const accordion = new Accordion(AccordionData);
});
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
.accordion-details {
display: none;
}
<main class="container"></main>
Upvotes: 0
Reputation: 5488
I hope this function helps you
function closeAll() {
var accs = document.querySelectorAll('.accordion');
for(var i = 0; i < accs.length; i ++) {
accs[i].classList.remove('active');
var panel = accs[i].nextElementSibling;
panel.style.maxHeight = null;
}
}
Update We can skip closing clicked element by adding this condition to closeAll
function:
if (accs[i] == tar) {
continue;
}
Full code here
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function(ev) {
closeAll(ev.target);
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.maxHeight) {
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight + "px";
}
});
}
function closeAll(tar) {
var accs = document.querySelectorAll('.accordion');
for (var i = 0; i < accs.length; i++) {
if (accs[i] == tar) {
continue;
}
accs[i].classList.remove('active');
var panel = accs[i].nextElementSibling;
panel.style.maxHeight = null;
}
}
.accordion {
background-color: #2364aa;
color: #ffffff;
cursor: pointer;
padding: 18px;
border: none;
text-align: left;
outline: none;
font-size: 21px;
transition: 0.4s;
}
.open,
.accordion:hover {
background-color: #205A99;
}
.accordion:after {
content: '\f067';
font-family: "Font Awesome 5 Free";
color: #ffffff;
float: right;
font-size: 1.25em;
line-height: 25px;
}
.open:after {
content: "\2212";
}
.panel {
max-height: 0;
overflow: hidden;
transition: 0.2s ease-out;
}
.panel-body {
padding: 18px 0;
}
@media only screen and (min-width: 960px) {
.container {
display: table;
box-sizing: border-box;
}
.row .col {
margin: 10px 0;
}
.col {
display: table-cell;
}
.col.middle {
vertical-align: middle;
}
.col-2 {
width: 50%;
padding-right: 72px;
}
.col-4 {
width: 33.33333333333333333%;
padding-right: 72px;
}
}
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="accordion.css">
</head>
<body>
<h3 class="accordion">Basics of Sailing</h3>
<div class="panel">
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Before Choosing a Sailboat</h4>
<p>Before looking for a boat to buy, you need to first know what you want to do with the boat, whether that is to go on vacation, learn how to sail, competitions or recreational sailing.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Car Topping & Trailing</h4>
<p>It's a good practice to carry the boat upside-down to allow the sides to rest on the side of the roof racks and to prevent the hull from getting damaged.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Safety Equipment</h4>
<p>You have to always have to think: safety first. Sailing is a dangerous and could result in severe injuries or death if the proper precautions are not taken.</p>
</div>
</div>
<h3 class="accordion">Basics of Sailing</h3>
<div class="panel">
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Before Choosing a Sailboat</h4>
<p>Before looking for a boat to buy, you need to first know what you want to do with the boat, whether that is to go on vacation, learn how to sail, competitions or recreational sailing.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Car Topping & Trailing</h4>
<p>It's a good practice to carry the boat upside-down to allow the sides to rest on the side of the roof racks and to prevent the hull from getting damaged.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Safety Equipment</h4>
<p>You have to always have to think: safety first. Sailing is a dangerous and could result in severe injuries or death if the proper precautions are not taken.</p>
</div>
</div>
<script src="accordion.js"></script>
</body>
</html>
Upvotes: 2
Reputation: 43880
Wrap everything in a block element.
var main = document.querySelector(`main`)
Add an EventListener to that "parent" element
main.addEventListener('click', ....
Now if main
or any descendants of main
are clicked, a callback function will be invoked. So we have only one EventListener listening for a click event on the behalf of each .accordion
. We determine which .accordion
was actually clicked by using an if
condition and the event.target
property.
The rule of mutual exclusivity applies to how an accordion works:
Only one .accordion + .panel
combo can have the .active
class.
Whenever it's time to change (in this case, e.target
(the clicked element) has been clicked), all .accordion
s will remove the .active
class (whether they actually had it or not).
After there are no element with the .active
class, you then give it to e.target
.
.accordion + .panel.active
instead of .accordion.active
.
.style.maxHeight
replaced by class .active
:
.panel.active {
max-height: 2000px;
height:auto;
overflow: hidden;
transition: 0.2s ease-out;
}
Details are commented in Demo
// Reference the parent of all .accordion
var main = document.querySelector('main');
/* Register main to click events...
|| when main or any of its descendant elements are clicked...
*/
main.addEventListener("click", function(e) {
/* Collect all .accordion into a NodeList and convert it into
|| an array.
*/
var acc = Array.from(document.querySelectorAll(".accordion"));
/* Loop thru each .accordion to remove the .active class
|| from each .panel
*/
for (let a = 0; a < acc.length; a++) {
var panel = acc[a].nextElementSibling;
panel.classList.remove('active');
}
/* After nothing has class .active, assign .active to the
|| .panel of the clicked element (e.target)
*/
if (e.target !== e.currentTarget) {
var tgt = e.target.nextElementSibling;
tgt.classList.add("active");
}
});
.accordion {
background-color: #2364aa;
color: #ffffff;
cursor: pointer;
padding: 18px;
border: none;
text-align: left;
outline: none;
font-size: 21px;
transition: 0.4s;
}
.open,
.accordion:hover {
background-color: #205A99;
}
.accordion:after {
content: '\f067';
font-family: "Font Awesome 5 Free";
color: #ffffff;
float: right;
font-size: 1.25em;
line-height: 25px;
}
.open:after {
content: "\2212";
}
.panel {
max-height: 0;
overflow: hidden;
transition: 0.2s ease-out;
}
.panel.active {
max-height: 2000px;
height:auto;
overflow: hidden;
transition: 0.2s ease-out;
}
@media only screen and (min-width: 960px) {
.container {
display: table;
box-sizing: border-box;
}
.row .col {
margin: 10px 0;
}
.col {
display: table-cell;
}
.col.middle {
vertical-align: middle;
}
.col-2 {
width: 50%;
padding-right: 72px;
}
.col-4 {
width: 33.33333333333333333%;
padding-right: 72px;
}
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<main>
<h3 class="accordion">Basics of Sailing</h3>
<div class="panel">
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Before Choosing a Sailboat</h4>
<p>Before looking for a boat to buy, you need to first know what you want to do with the boat, whether that is to go on vacation, learn how to sail, competitions or recreational sailing.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Car Topping & Trailing</h4>
<p>It's a good practice to carry the boat upside-down to allow the sides to rest on the side of the roof racks and to prevent the hull from getting damaged.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Safety Equipment</h4>
<p>You have to always have to think: safety first. Sailing is a dangerous and could result in severe injuries or death if the proper precautions are not taken.</p>
</div>
</div>
<h3 class="accordion">Basics of Sailing</h3>
<div class="panel">
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Before Choosing a Sailboat</h4>
<p>Before looking for a boat to buy, you need to first know what you want to do with the boat, whether that is to go on vacation, learn how to sail, competitions or recreational sailing.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Car Topping & Trailing</h4>
<p>It's a good practice to carry the boat upside-down to allow the sides to rest on the side of the roof racks and to prevent the hull from getting damaged.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Safety Equipment</h4>
<p>You have to always have to think: safety first. Sailing is a dangerous and could result in severe injuries or death if the proper precautions are not taken.</p>
</div>
</div>
<h3 class="accordion">Basics of Sailing</h3>
<div class="panel">
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Before Choosing a Sailboat</h4>
<p>Before looking for a boat to buy, you need to first know what you want to do with the boat, whether that is to go on vacation, learn how to sail, competitions or recreational sailing.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Car Topping & Trailing</h4>
<p>It's a good practice to carry the boat upside-down to allow the sides to rest on the side of the roof racks and to prevent the hull from getting damaged.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Safety Equipment</h4>
<p>You have to always have to think: safety first. Sailing is a dangerous and could result in severe injuries or death if the proper precautions are not taken.</p>
</div>
</div>
<h3 class="accordion">Basics of Sailing</h3>
<div class="panel">
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Before Choosing a Sailboat</h4>
<p>Before looking for a boat to buy, you need to first know what you want to do with the boat, whether that is to go on vacation, learn how to sail, competitions or recreational sailing.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Car Topping & Trailing</h4>
<p>It's a good practice to carry the boat upside-down to allow the sides to rest on the side of the roof racks and to prevent the hull from getting damaged.</p>
</div>
<div class="col col-4 middle">
<!-- <div class="space"></div> -->
<h4>Safety Equipment</h4>
<p>You have to always have to think: safety first. Sailing is a dangerous and could result in severe injuries or death if the proper precautions are not taken.</p>
</div>
</div>
</main>
</body>
</html>
Upvotes: 2