I followed this (Close javascript tabs when clicked again) to create tabs that open and close when clicked. Now, I also have a [x] mark to close the button and want the tab to close when I click EITHER one (or the tab again or the [x]):
<span onclick="this.parentElement.style.display='none'" class="topright">×</span>
When I click on the tab again – it works fine (closes the tab and is ready to open the tab on the next click). But when I close the tab with the [x], I have to click once more on the tab to "re-activate" it before it’s ready to be open with the next click.
Would appreciate your help. Thanks.
function openTab(evt, tabName) {
var activeClass = evt.target.classList.contains("active")
if (!activeClass) {
var i, tabcontent, tablinks;
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
document.getElementById(tabName).style.display = "block";
evt.currentTarget.className += " active";
} else {
document.getElementById(tabName).style.display = "none";
evt.target.classList.remove("active");
}
}
//document.getElementById("defaultOpen").click();
<div class="tab">
<button class="tablinks" onclick="openTab(event, 'London')" id="defaultClosed">Tab name</button>
</div>
<div id="London" class="tabcontent">
<span onclick="this.parentElement.style.display='none'" class="topright">×</span>
<h3>London</h3>
<p>London is the capital city of England.</p>
</div>
3
Answers
It looks like the issue is related to the logic of toggling the active state when you close the tab using the [x] close button. When you close the tab with the [x], the
openTab
function still thinks it’s in the active state, so it requires another click to reset it.Instead of just setting
display
to none, you should also remove the active class from the corresponding tab button.Providing a function that removes the active class and sets display as none, should suffice:
The reason why you face the issue has already been explained in a comment. I not going to repeat it but avoid it by coding clean to modern standards.
First of all, if you use
element.style.[...]
you will look and set inline-styles. The modern solution is to avoid inline-styles but go for CSS-level solutions that useelement.classList
to avoid unattended specificity issues.The next thing is, that in modern JS you not coupling JS with the HTML by using the
onclick
-Attribute in HTML but by decoupling it by using an event listener in JS.I used some kind of event delegation where I just listened to the whole body and checked if the clicked element was either the close button or the close tab.
Hide all
tabcontent
elements by default and only display them if they have the classactive
. That can be done depending if you need the support of older browsers or not with Level-4 Modules (Nesting):Level-4 Selector Module (Nesting):
Level-3 Selector Module (supports older browsers):
If you click on the
x
to close an element you always want to close that element and you can useclassList.remove('active')
.The logic is a little more complex if you click on the tabs to open the elements. There are 2 cases that can appear:
In both cases, you want to hide the currently opened element. In the 1st case, you additionally need to open the selected element.
The logic here is to check if it is case 1 or either 2 or 3. If it is case 1 you need to add the
active
class to the selected element. Means you have a condition here. For adding classes based on a condition you can useclassList.toggle('active', condition)
.The "special case" here is the 3rd case. If no element is open and you use
querySelector('.active')
, it returnsnull
and the script will fail. Here you need to use a?
beforeclassList
so that this part will only execute if such an element exists.