Reputation: 23
I'm trying to create tabs within a webpage using HTML buttons and vanilla JavaScript. I've come up with this solution:
const tab1 = document.getElementById("tab-1");
const tab2 = document.getElementById("tab-2");
const tab3 = document.getElementById("tab-3");
const tabs = [tab1, tab2, tab3];
const tab1Content = document.getElementById("tab-1-content");
const tab2Content = document.getElementById("tab-2-content");
const tab3Content = document.getElementById("tab-3-content");
const tabContents = [tab1Content, tab2Content, tab3Content];
tab1.addEventListener("click", () => {displayTab(tab1, tab1Content)});
tab2.addEventListener("click", () => {displayTab(tab2, tab2Content)});
tab3.addEventListener("click", () => {displayTab(tab3, tab3Content)});
function displayTab(tab, tabContent) {
for (let i = 0; i < tabs.length; i++) {
if (tabs[i].classList.contains("active")) {
tabs[i].classList.remove("active");
tabContents[i].classList.add("hide");
}
}
tab.classList.add("active");
tabContent.classList.remove("hide");
}
.hide { display: none }
.active { font-weight : bold }
<h1>Tabs</h1>
<div class="tabBtns">
<button id="tab-1" class="active">Tab 1</button>
<button id="tab-2">Tab 2</button>
<button id="tab-3">Tab 3</button>
</div>
<div class="content">
<div id="tab-1-content">
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Dignissimos qui labore, quam dicta voluptate
libero est blanditiis perspiciatis voluptatibus perferendis velit repudiandae. Maxime, eligendi. Vitae
magnam similique harum sunt quibusdam.
</div>
<div id="tab-2-content" class="hide">
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Dolores similique assumenda reprehenderit eaque
itaque in magni vero repudiandae, totam maiores saepe iste culpa labore quam esse ipsam fugit cupiditate
facilis sunt aliquid ad sit voluptatibus veritatis non. Eligendi accusantium libero veniam facere, expedita,
magnam quia assumenda similique quas, voluptatum nostrum.
</div>
<div id="tab-3-content" class="hide">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Culpa, sunt?
</div>
</div>
Is there a more efficient way of doing this? It feels like it might be a little redundant having to manually add each tab and its content into their respective arrays, and then having to apply an event listener to each manually as well. I would appreciate a more elegant solution if one is possible.
Upvotes: 0
Views: 458
Reputation: 22265
You can do that with
classList.toggle()
method with its boolean option to add
or remove
a class
,const buttonsParent = document.querySelector('div#tab-Btns')
, all_tab_elms = document.querySelectorAll('button[data-tab], div[data-tab]')
;
buttonsParent.onclick = ({target}) =>
{
if (!target.matches('button[data-tab]')) return // ignore other click in this area (like spaces between buttons)
all_tab_elms.forEach( elTab => elTab.classList
.toggle('active', (elTab.dataset.tab===target.dataset.tab )))
}
button[data-tab].active { font-weight: bold; }
div[data-tab] { display: none; }
div[data-tab].active { display: block; }
<h1>Tabs</h1>
<div id="tab-Btns">
<button data-tab="tab-1" class="active">Tab 1</button>
<button data-tab="tab-2">Tab 2</button>
<button data-tab="tab-3">Tab 3</button>
</div>
<div id="tab-content">
<div data-tab="tab-1" class="active">
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Dignissimos qui labore, quam dicta voluptate
libero est blanditiis perspiciatis voluptatibus perferendis velit repudiandae. Maxime, eligendi. Vitae
magnam similique harum sunt quibusdam.
</div>
<div data-tab="tab-2">
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Dolores similique assumenda reprehenderit eaque
itaque in magni vero repudiandae, totam maiores saepe iste culpa labore quam esse ipsam fugit cupiditate
facilis sunt aliquid ad sit voluptatibus veritatis non. Eligendi accusantium libero veniam facere, expedita,
magnam quia assumenda similique quas, voluptatum nostrum.
</div>
<div data-tab="tab-3">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Culpa, sunt?
</div>
</div>
Upvotes: 1
Reputation: 59
you could make a little function to build your tabs
function buildTab(content, number, etc...) {
const tab = document.createElement("div")
tab.innerHTML = content
tab.addEventListener...
// whatever else you wanna do
return tab
}
//json containing all the content you wanna display(?)
const tabs = contentArray.map(c => buildTab(...c))
Upvotes: 1
Reputation: 370679
Iterate over all tabs and hide them when a button is clicked. Find the
index of the clicked button and you can get to the associated <div>
, no IDs needed.
const contents = document.querySelectorAll('.content > div');
const buttons = document.querySelectorAll('.tabBtns button');
buttons.forEach((button, i) => {
button.addEventListener('click', () => {
buttons.forEach(button => button.classList.remove('active'));
contents.forEach(content => content.classList.add('hide'));
button.classList.add('active');
contents[i].classList.remove('hide');
});
});
.active {
background-color: yellow;
}
.hide {
display: none;
}
<h1>Tabs</h1>
<div class="tabBtns">
<button class="active">Tab 1</button>
<button>Tab 2</button>
<button>Tab 3</button>
</div>
<div class="content">
<div>
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Dignissimos qui labore, quam dicta voluptate libero est blanditiis perspiciatis voluptatibus perferendis velit repudiandae. Maxime, eligendi. Vitae magnam similique harum sunt quibusdam.
</div>
<div class="hide">
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Dolores similique assumenda reprehenderit eaque itaque in magni vero repudiandae, totam maiores saepe iste culpa labore quam esse ipsam fugit cupiditate facilis sunt aliquid ad sit voluptatibus
veritatis non. Eligendi accusantium libero veniam facere, expedita, magnam quia assumenda similique quas, voluptatum nostrum.
</div>
<div class="hide">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Culpa, sunt?
</div>
</div>
You could also save the index of the last clicked button in a persistent variable instead of looping over each element inside the click handler.
Upvotes: 2