0
\$\begingroup\$

I have an HTML table, and I would like to remove columns where the sum vertically is 0 dynamically.

Four-column table, with a header row followed by three rows of integers

let ths_columns = [...document.querySelectorAll("thead tr th")].map(
 (th) => th.textContent.trim()
); //first row of table header [ "column_1", "column_2", "column_3", "column_4" ]
let trs = [...document.querySelectorAll("tbody tr")]; // three rows of table tbody [ tr, tr, tr ]
//convert table into 2d-array dimension like matrix: trs_rows [[[10, 0, 5, 0]], [[3, 0, 6, 0]], [[8, 0, 2, 0]]];
const trs_rows = [];
for (let tr of trs) {
 trs_rows.push([[...tr.children].map((td) => +td.textContent)]);
}
//make an array looks like ths_columns contains sum of rows vertically
const ths_rows_result = Array.from({ length: ths_columns.length }).fill(
 0
);
for (let i = 0; i < trs_rows.length; i++) {
 const element = trs_rows[i];
 for (let j = 0; j < element.length; j++) {
 for (let k = 0; k < element[j].length; k++) {
 const td = element[j][k];
 //console.log(td);
 ths_rows_result[k] += td;
 }
 }
}
console.log(ths_rows_result); // [21, 0, 13, 0]
// make an array which contains name of columns have
const array_zeros = ths_columns
 .map((th, i) => [th, ths_rows_result[i]])
 .filter((entries) => entries[1] == 0)
 .map((entry) => entry[0]);
//console.log(array_zeros); // ['column_2', 'column_4']
// make the same array but this time contains id instead of column's name
const array_index = [];
for (let i = 0; i < ths_columns.length; i++) {
 const element = ths_columns[i];
 if (array_zeros.includes(element)) {
 array_index.push(i);
 }
}
//console.log(array_index); //[1, 3]
//loop over first row and if a cell is in add to a cell class none (in css .none{display: none;})
let ths = [...document.querySelectorAll("thead tr th")];
for (let i = 0; i < ths.length; i++) {
 const th = ths[i];
 if (array_index.includes(i)) {
 th.classList.add("none");
 }
}
//loop over other rows and do the same process if a cell is in add to a cell class none (in css .none{display: none;})
for (let i = 0; i < trs.length; i++) {
 const element = trs[i];
 let tds = [...element.querySelectorAll("td")];
 for (let j = 0; j < tds.length; j++) {
 if (array_index.includes(j)) {
 tds[j].classList.add("none");
 }
 }
}
table {
 border-collapse: collapse;
 border: 1px solid;
}
tr,
th,
td {
 border: 1px solid;
 text-align: center;
}
.none {
 display: none;
}
<table class="table_pp">
 <thead>
 <tr>
 <th>column_1</th>
 <th>column_2</th>
 <th>column_3</th>
 <th>column_4</th>
 </tr>
 </thead>
 <tbody>
 <tr>
 <td>10</td>
 <td>0</td>
 <td>5</td>
 <td>0</td>
 </tr>
 <tr>
 <td>3</td>
 <td>0</td>
 <td>6</td>
 <td>0</td>
 </tr>
 <tr>
 <td>8</td>
 <td>0</td>
 <td>2</td>
 <td>0</td>
 </tr>
 </tbody>
</table>

Is it the right way of doing it?

200_success
145k22 gold badges190 silver badges478 bronze badges
asked Jun 8, 2022 at 23:41
\$\endgroup\$
2
  • 2
    \$\begingroup\$ Do you have control over the HTML representation of the table or not? \$\endgroup\$ Commented Jun 9, 2022 at 0:13
  • 1
    \$\begingroup\$ I have no idea why you want to do this, but if the idea is to remove columns that contain nothing but zeros, then your code doesn't work. It does work, if your intend is to remove columns that sum up to zero. See: CodePen. Note that column 2 contains [-1, 0, 1] which totals to zero. \$\endgroup\$ Commented Jun 9, 2022 at 8:16

1 Answer 1

1
\$\begingroup\$

Aside from the ambiguity in the question, you are definitely taking a circuitous route to identify the columns. CSS's nth-child would vastly simplify querying the DOM.

// determine column count from th cells in thead
document.querySelectorAll('thead th').forEach((_, i) => {
 // only interested in the nth-child for each column in the tbody
 const cols = [...document.querySelectorAll(`tbody tr td:nth-child(${i+1})`)]
 // get the sum (or whatever determines why to hide
 const total = cols.reduce((acc, col) => acc + parseInt(col.textContent), 0)
 if (total === 0) {
 // add the css class to each tbody column
 cols.forEach(col => {
 col.classList.add('none')
 })
 // also hide the header th
 const headerCol = document.querySelector(`thead th:nth-child(${i+1})`)
 if (headerCol) headerCol.classList.add('none')
 }
 
})
table {
 border-collapse: collapse;
 border: 1px solid;
}
tr,
th,
td {
 border: 1px solid;
 text-align: center;
}
.none {
 display: none;
}
<table class="table_pp">
 <thead>
 <tr>
 <th>column_1</th>
 <th>column_2</th>
 <th>column_3</th>
 <th>column_4</th>
 </tr>
 </thead>
 <tbody>
 <tr>
 <td>10</td>
 <td>0</td>
 <td>5</td>
 <td>0</td>
 </tr>
 <tr>
 <td>3</td>
 <td>0</td>
 <td>6</td>
 <td>0</td>
 </tr>
 <tr>
 <td>8</td>
 <td>0</td>
 <td>2</td>
 <td>0</td>
 </tr>
 </tbody>
</table>

answered Jun 9, 2022 at 8:25
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.