So, I'm creating this navigation thing using Bootstrap which will be present in the form of tabs in desktop and for mobile it will be an accordion. It's almost finished except there's this error I am not able to resolve.
Problem: If I click on any of the tabs (say Link #3) in the desktop version and then I switch to mobile, the correct tab is opened (i.e. Link #3) BUT when I click on it to close the tab and hide the content even though the content gets hidden, the button and toggle remains in "open state". This problem can be seen in desktops or tablets (as they'll show the navtabs). To view the problem on desktop just decrease the viewport size after clicking the nav tab.
I thought that if I could use "classList.contains()" to somehow keep track of when the content has "show" class and when it does not I'd be able to control it. But, I think it only keeps track of the class if I mentioned the class inline (it keeps on alerting true for the first content element and false for the rest of them). If I don't have the class mentioned inline it doesn't keep track of it even though Bootstrap is internally toggling between those classes. Or maybe I'm using the contains function in wrong fashion. Idk.
I also thought that maybe if I can keep track of the clicks i.e. if navtabs are being clicked and then if accordion is being clicked then class ("collapse") should be removed or added from or to the accordion button. But this then disrupts the other situations in which the toggle is working correctly.
I'm also unable to use the toggle() for Bootstrap accordion's "collapse" or "show".
I couldn't figure out anything so here I am at last asking you to help me. Please help me resolve this issue.
EDIT: So, I have managed to get .contains() to work BUT then I need to add a recursive function to get the "collapsed" class to toggle which is making the page slower and eventually unresponsive.
Here's what I did:
- added a click event (for accordion btn #2) that should be checked after Link #2 is clicked in navtab
- if the accordion btn (Link #2) is clicked after clicking the navtab (Link #2), it should check if the content is visible, if it is then a recursive function btn2Toggle() is called. (I think I made a pretty terrible recursive function)
PS: I wouldn't have to do this if toggle() worked but it isn't working. Also, I feel like I'm making it more complex than it needs to be. Am I going right or am I making it more complex?
const btn1 = document.getElementById('btn-1');
const btn2 = document.getElementById('btn-2');
const btn3 = document.getElementById('btn-3');
const tab1 = document.getElementById('nl-1');
const tab2 = document.getElementById('nl-2');
const tab3 = document.getElementById('nl-3');
const content1 = document.getElementById('flush-collapseOne');
const content2 = document.getElementById('flush-collapseTwo');
const content3 = document.getElementById('flush-collapseThree');
// this function will add and remove the collapsed class from btn
function btn2Toggle() {
btn2.addEventListener('click', function() {
btn2.classList.add('collapsed');
btn2.addEventListener('click', function() {
btn2.classList.remove('collapsed');
if (btn2.onclick) {
btn2Toggle();
}
else {
return;
}
})
});
// or I could simply have this line of code if toggle() worked
// btn2.addEventListener('click', function() {
// btn2.classList.toggle('collapsed');
// })
}
function contentVisible() {
if (content1.classList.contains("show")) {
// alert('content 1 visible');
};
if (content2.classList.contains("show")) {
// alert('content 2 visible');
btn2Toggle();
};
if (content3.classList.contains("show")) {
// alert('content 3 visible');
};
}
function callTab() {
// if tab1 is clicked on desktop, show only the content associated with btn1, collapse the rest of them
if (tab1.addEventListener('click', function() {
btn2.classList.add('collapsed');
btn3.classList.add('collapsed');
btn1.classList.remove('collapsed');
}));
// if tab2 is clicked on desktop, show only the content associated with btn2, collapse the rest of them
if (tab2.addEventListener('click', function() {
btn1.classList.add('collapsed');
btn3.classList.add('collapsed');
btn2.classList.remove('collapsed');
// if navtab #2 (i.e. Link #2) is clicked and then if accordion
// button #2 (i.e. Link #2) is clicked then contentVisible()
// will be called
document.querySelectorAll('.accordion-button').addEventListener('click', contentVisible());
}));
// if tab3 is clicked on desktop, show only the content associated with btn3, collapse the rest of them
if (tab3.addEventListener('click', function() {
btn1.classList.add('collapsed');
btn2.classList.add('collapsed');
btn3.classList.remove('collapsed');
}));
};
function myFunction(x) {
if (x.matches) { // If media query matches
document.querySelectorAll('.nav-link').addEventListener('click', callTab());
}
}
var x = window.matchMedia("(min-width: 992px)")
myFunction(x) // Call listener function at run time
x.addListener(myFunction) // Attach listener function on state changes
.container .nav-tabs {
display: none;
}
/* MEDIA QUERY */
@media screen and (min-width: 992px) {
.container .nav-tabs {
display: flex;
}
.accordion-item h2 {
display: none;
}
.container .accordion-item {
border: none;
}
}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap demo</title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
</head>
<body>
<div class="container">
<ul class="nav nav-tabs">
<li class="nav-item">
<a class="nav-link active" id="nl-1" aria-current="page" href="#flush-collapseOne" data-bs-toggle="tab">Link #1</a>
</li>
<li class="nav-item">
<a class="nav-link" id="nl-2" href="#flush-collapseTwo" data-bs-toggle="tab">Link #2</a>
</li>
<li class="nav-item">
<a class="nav-link" id="nl-3" href="#flush-collapseThree" data-bs-toggle="tab">Link #3</a>
</li>
</ul>
<div class="accordion accordion-flush" id="accordionFlushExample">
<div class="accordion-item">
<h2 class="accordion-header">
<button id="btn-1" onclick="document.querySelector('#nl-1').click()" class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#flush-collapseOne" aria-expanded="false" aria-controls="flush-collapseOne">
Link #1
</button>
</h2>
<div id="flush-collapseOne" class="accordion-collapse collapse show" data-bs-parent="#accordionFlushExample">
<div class="accordion-body">content 1</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header">
<button id="btn-2" onclick="document.querySelector('#nl-2').click()" class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#flush-collapseTwo" aria-expanded="false" aria-controls="flush-collapseTwo">
Link #2
</button>
</h2>
<div id="flush-collapseTwo" class="accordion-collapse collapse" data-bs-parent="#accordionFlushExample">
<div class="accordion-body">content 2</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header">
<button id="btn-3" onclick="document.querySelector('#nl-3').click()" class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#flush-collapseThree" aria-expanded="false" aria-controls="flush-collapseThree">
Link #3
</button>
</h2>
<div id="flush-collapseThree" class="accordion-collapse collapse" data-bs-parent="#accordionFlushExample">
<div class="accordion-body">content 3</div>
</div>
</div>
</div>
</div>
<!-- Bootstrap JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script>
</body>
</html>
Comments
Post a Comment