'Creating tabs with html and javascript
I'm new in these things so this might be an easy one. I want to create tabs with the following code from w3schools. The original one is here: https://www.w3schools.com/howto/howto_js_tabs.asp
I don't want images to be in the tabcontent section. So I made a new class named tabimage and added it to the javascript. Also I've added new events with the image's ids at the html. But it keeps showing other tabs when clicked. Can anyone help?
function openCity(evt, cityName) {
var i, tabcontent, tablinks;
tabcontent = document.getElementsByClassName("tabcontent tabimage");
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(cityName).style.display = "block";
evt.currentTarget.className += "active";
}
body {font-family: Open Sans;}
.order {
display: grid;
/* grid-template-columns: 1fr 1fr;*/
}
/* Style the tab */
.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
/* Style the buttons inside the tab */
.tab button {
background-color: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 14px 16px;
transition: 0.3s;
font-size: 17px;
}
/* Change background color of buttons on hover */
.tab button:hover {
background-color: #ddd;
}
/* Create an active/current tablink class */
.tab button.active {
background-color: #ccc;
}
/* Style the tab content */
.tabcontent {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
.tabimage {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
<div class="order">
<div class="tab">
<button class="tablinks" onclick="openCity(event, 'London'); openCity(event, 'London1')">London</button>
<button class="tablinks" onclick="openCity(event, 'Paris'); openCity(event, 'Paris1')">Paris</button>
<button class="tablinks" onclick="openCity(event, 'Tokyo')">Tokyo</button>
</div>
<div id="London" class="tabcontent">
<h3>London</h3>
<p>London is the capital city of England.</p>
</div>
<div id="Paris" class="tabcontent">
<h3>Paris</h3>
<p>Paris is the capital of France.</p>
</div>
<div id="Tokyo" class="tabcontent">
<h3>Tokyo</h3>
<p>Tokyo is the capital of Japan.</p>
</div>
<img src="https://cdn.shopify.com/s/files/1/0044/8718/4457/files/800x600_Wallpaper_Blue_Sky.png?v=1646897329" class="tabimage" id="London1">
<img src="https://cdn.shopify.com/s/files/1/0044/8718/4457/files/Auckland_Skyline_800x600_80c6b2c0-28bc-4885-8440-a6da7de39c82.jpg?v=1646897329" class="tabimage" id="Paris1">
</div>
Solution 1:[1]
As @Cbroe pointed out in the comments:
If you use multiple classes with the function getElementsByClassName then this function will only return elements which have all of the defined classes.
You need to switch to the function querySelectorAll, with this function you are able to select multiple elements defined by multiple rules. You separate the selectors with a comma, e.g.
document.querySelectorAll(".tabcontent, .tabimage");
Here is an example with querySelectorAll. Do notice I've changed the function openCity to show the city as the image, if there is any.
function openCity(evt, cityName) {
var i, tabcontent, tablinks;
tabcontent = document.querySelectorAll(".tabcontent, .tabimage");
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(cityName).style.display = "block";
if (document.getElementById('img'+cityName)) {
document.getElementById('img'+cityName).style.display = "block";
}
evt.currentTarget.className += "active";
}
.order {
display: grid;
/* grid-template-columns: 1fr 1fr;*/
}
/* Style the tab */
.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
/* Style the buttons inside the tab */
.tab button {
background-color: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 14px 16px;
transition: 0.3s;
font-size: 17px;
}
/* Change background color of buttons on hover */
.tab button:hover {
background-color: #ddd;
}
/* Create an active/current tablink class */
.tab button.active {
background-color: #ccc;
}
/* Style the tab content */
.tabcontent {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
.tabimage {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
<div class="order">
<div class="tab">
<button class="tablinks" onclick="openCity(event, 'London');">London</button>
<button class="tablinks" onclick="openCity(event, 'Paris');">Paris</button>
<button class="tablinks" onclick="openCity(event, 'Tokyo')">Tokyo</button>
</div>
<div id="London" class="tabcontent">
<h3>London</h3>
<p>London is the capital city of England.</p>
</div>
<div id="Paris" class="tabcontent">
<h3>Paris</h3>
<p>Paris is the capital of France.</p>
</div>
<div id="Tokyo" class="tabcontent">
<h3>Tokyo</h3>
<p>Tokyo is the capital of Japan.</p>
</div>
<img src="https://cdn.shopify.com/s/files/1/0044/8718/4457/files/800x600_Wallpaper_Blue_Sky.png?v=1646897329" class="tabimage" id="imgLondon">
<img src="https://cdn.shopify.com/s/files/1/0044/8718/4457/files/Auckland_Skyline_800x600_80c6b2c0-28bc-4885-8440-a6da7de39c82.jpg?v=1646897329" class="tabimage" id="imgParis">
</div>
Aternative solution
To create tabbed content you can also work with data-* attributes. Using this you can easily define multiple section to show/hide, instead of relaying on (unique) id's.
It also removes the need to define the event handler for each separate element as you can you query the chosen data-* attribute.
In this case I'm linking the data-origin attribute with elements which have the data-target attribute
var origins = document.querySelectorAll("button[data-origin]");
for (let i = 0; i < origins.length; i++) {
origins[i].addEventListener('click', function(e) {
// Get all elements with data-origin defined
var allOrigins = document.querySelectorAll("*[data-origin]");
for (i = 0; i < allOrigins.length; i++) {
allOrigins[i].classList.remove("active");
}
// Get all elements with data-target defined
var allTargets = document.querySelectorAll("*[data-target]");
for (i = 0; i < allTargets.length; i++) {
allTargets[i].style.display = "none";
}
//Only get elements of which the data-target attribute matches the value of the data-origin of the clicked element
var targets = document.querySelectorAll("*[data-target='"+e.target.dataset.origin+"']");
for (i = 0; i < targets.length; i++) {
targets[i].style.display = "block";
}
e.target.classList.add("active");
});
}
.order {
display: grid;
/* grid-template-columns: 1fr 1fr;*/
}
/* Style the tab */
.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
/* Style the buttons inside the tab */
.tab button {
background-color: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 14px 16px;
transition: 0.3s;
font-size: 17px;
}
/* Change background color of buttons on hover */
.tab button:hover {
background-color: #ddd;
}
/* Create an active/current tablink class */
.tab button.active {
background-color: #ccc;
}
/* Style the tab content */
.tabcontent {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
.tabimage {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
<div class="order">
<div class="tab">
<button class="tablinks" data-origin="London">London</button>
<button class="tablinks" data-origin="Paris">Paris</button>
<button class="tablinks" data-origin="Tokyo">Tokyo</button>
</div>
<div data-target="London" class="tabcontent">
<h3>London</h3>
<p>London is the capital city of England.</p>
</div>
<div data-target="Paris" class="tabcontent">
<h3>Paris</h3>
<p>Paris is the capital of France.</p>
</div>
<div data-target="Tokyo" class="tabcontent">
<h3>Tokyo</h3>
<p>Tokyo is the capital of Japan.</p>
</div>
<img src="https://cdn.shopify.com/s/files/1/0044/8718/4457/files/800x600_Wallpaper_Blue_Sky.png?v=1646897329" class="tabimage" data-target="London">
<img src="https://cdn.shopify.com/s/files/1/0044/8718/4457/files/Auckland_Skyline_800x600_80c6b2c0-28bc-4885-8440-a6da7de39c82.jpg?v=1646897329" class="tabimage" data-target="Paris">
</div>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
