I have JavaScript code which on button click shows its table. I have 4 buttons (and tables, obviously). Probably there will be more, so making function to each one of them will be bad idea. That being said, I made this code below to slightly minimize the amount of code. But, it doesn't work, and I don't quite understand why.
document.addEventListener('DOMContentLoaded', function() {
const tab1 = document.getElementById('tab1');
const tab2 = document.getElementById('tab2');
const tab3 = document.getElementById('tab3');
const tab4 = document.getElementById('tab4');
const currentTable = ".table";
const tables = Array.from(document.querySelectorAll(currentTable))
const table1 = document.querySelector('.table1');
const table2 = document.querySelector('.table2');
const table3 = document.querySelector('.table3');
const table4 = document.querySelector('.table4');
//this doesnt work
function showTable(e) {
const target = e.target;
if (!target || !target.matches(currentTable)) {
return;
}
tables.forEach(elem => elem.classList.remove('active'));
tables.forEach(elem => elem.classList.remove('op'));
e.target.classList.add('active');
setTimeout(function() {
e.target.classList.add('op');
}, 20);
};
tab1.addEventListener('click', showTable(table1));
tab2.addEventListener('click', showTable(table2));
tab3.addEventListener('click', showTable(table3));
tab4.addEventListener('click', showTable(table4));
});
//this one for buttons
document.addEventListener('DOMContentLoaded', function() {
const selector = '.table_option';
const elems = Array.from(document.querySelectorAll(selector));
const navigation = document.querySelector('.table-nav');
function makeActive(e) {
const target = e.target;
if (!target || !target.matches(selector)) {
return;
}
elems.forEach(elem => elem.classList.remove('active'));
e.target.classList.add('active');
};
navigation.addEventListener('click', makeActive);
});
.table_container {
display: flex;
width: 100%;
}
.table_content-left {
width: 30%;
margin-top: 50px;
}
.table_content-left .table_option {
font-size: 16px;
font-weight: 700;
cursor: pointer;
}
.table_content-left .table-nav li:not(:last-child) {
margin-bottom: 10px;
}
.table_content-left .table_option.active {
color: #eb5e28;
border-left: 2px solid #252422;
padding: 10px 15px;
transition: all 0.8s;
}
.table_content-right {
width: 70%;
}
.table {
display: none;
opacity: 0;
transition: opacity 900ms;
}
.op {
opacity: 1;
}
.table_title {
font-size: 24px;
font-weight: 700;
}
.table_content table {
border-collapse: collapse;
}
.table_content td,
.table_content th {
text-align: left;
padding: 8px;
width: 100%;
font-weight: 600;
}
.table_content td {
background-color: #ccc5b9;
}
.table_content th:first-child {
padding: 8px 0px;
}
.table_content td:nth-child(2n 1) {
background-color: #403d39;
color: #fff;
}
.table_content tr:nth-child(even) {
background-color: #ccc5b9;
color: #fff;
}
.table_content tr:nth-child(even) td:nth-child(1n 1) {
background-color: #403d39;
}
.table_content tr:nth-child(even) td:nth-child(2n 1) {
background-color: #ccc5b9;
color: #252422;
}
.active {
display: block;
}
<div >
<div >
<ul role="list" >
<li><a id="tab1">button1</a></li>
<li><a id="tab2">button2</a></li>
<li><a id="tab3">button3</a></li>
<li><a id="tab4">button4</a></li>
</ul>
</div>
<div >
<div >
<div >1</div>
<table cellspacing="0">
<tr>
<th>Lorem</th>
<th>5</th>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
</table>
</div>
<div >
<div >2</div>
<table cellspacing="0">
<tr>
<th>Lorem</th>
<th>5</th>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
</table>
</div>
<div >
<div >3</div>
<table cellspacing="0">
<tr>
<th>Lorem</th>
<th>5</th>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
</table>
</div>
<div >
<div >4</div>
<table cellspacing="0">
<tr>
<th>Lorem</th>
<th>5</th>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
</table>
</div>
</div>
</div>
Where am I wrong? Can someone point me to the problem I am facing?
CodePudding user response:
I like to take a simple index-based approach to things like this. If that doesn't suit, you could add indices to the tables using data attributes which correspond to tab index.
Some other tips...
- You were creating event listeners in every call of
showTable()
. That would result in a pile of event handlers you don't want. - You were using a rather roundabout way to collect elements (with
Array.from()
. That's not needed. - Multiple classes can be added and removed as a list.
document.addEventListener('DOMContentLoaded', function() {
const tabs = document.querySelectorAll('.table_option');
const tables = document.querySelectorAll('.table');
tabs.forEach(tab => {
tab.addEventListener('click', e => {
const tabEl = e.currentTarget.parentNode;
const tabIndex = [...tabEl.parentNode.children].indexOf(tabEl);
showTable(tabIndex);
});
});
const showTable = index => {
tables.forEach(elem => elem.classList.remove('active', 'op'));
tables[index].classList.add('active');
setTimeout(() => {
tables[index].classList.add('op');
}, 20);
tabs.forEach(elem => elem.classList.remove('active', 'op'));
tabs[index].classList.add('active');
}
});
.table_container {
display: flex;
width: 100%;
}
.table_content-left {
width: 30%;
margin-top: 50px;
}
.table_content-left .table_option {
font-size: 16px;
font-weight: 700;
cursor: pointer;
}
.table_content-left .table-nav li:not(:last-child) {
margin-bottom: 10px;
}
.table_content-left .table_option.active {
color: #eb5e28;
border-left: 2px solid #252422;
padding: 10px 15px;
transition: all 0.8s;
}
.table_content-right {
width: 70%;
}
.table {
display: none;
opacity: 0;
transition: opacity 900ms;
}
.op {
opacity: 1;
}
.table_title {
font-size: 24px;
font-weight: 700;
}
.table_content table {
border-collapse: collapse;
}
.table_content td,
.table_content th {
text-align: left;
padding: 8px;
width: 100%;
font-weight: 600;
}
.table_content td {
background-color: #ccc5b9;
}
.table_content th:first-child {
padding: 8px 0px;
}
.table_content td:nth-child(2n 1) {
background-color: #403d39;
color: #fff;
}
.table_content tr:nth-child(even) {
background-color: #ccc5b9;
color: #fff;
}
.table_content tr:nth-child(even) td:nth-child(1n 1) {
background-color: #403d39;
}
.table_content tr:nth-child(even) td:nth-child(2n 1) {
background-color: #ccc5b9;
color: #252422;
}
.active {
display: block;
}
<div >
<div >
<ul role="list" >
<li><a id="tab1">button1</a></li>
<li><a id="tab2">button2</a></li>
<li><a id="tab3">button3</a></li>
<li><a id="tab4">button4</a></li>
</ul>
</div>
<div >
<div >
<div >1</div>
<table cellspacing="0">
<tr>
<th>Lorem</th>
<th>5</th>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
</table>
</div>
<div >
<div >2</div>
<table cellspacing="0">
<tr>
<th>Lorem</th>
<th>5</th>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
</table>
</div>
<div >
<div >3</div>
<table cellspacing="0">
<tr>
<th>Lorem</th>
<th>5</th>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
</table>
</div>
<div >
<div >4</div>
<table cellspacing="0">
<tr>
<th>Lorem</th>
<th>5</th>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
<tr>
<td>Lorem</td>
<td>5</td>
</tr>
</table>
</div>
</div>
</div>