JSFiddle - React, Tailwind, and code Playground
by Mawel Don
HTML
Click a Column Header
<table>
<tbody>
<tr class="ignore">
<th>Shop Name</th>
<th>Note Gloable</th>
<th>User 0</th>
<th>User 1</th>
<th>User 2</th>
<th>User 3</th>
</tr>
<tr>
<td>Shop 0</td>
<td>3.5714285714285716</td>
<td>25</td>
<td>13</td>
<td>12</td>
<td>32</td>
</tr>
<tr>
<td>Shop 1</td>
<td>2</td>
<td>18.666666666666664</td>
<td>8.333333333333332</td>
<td>5</td>
<td>23.333333333333332</td>
</tr>
<tr>
<td>Shop 3</td>
<td>3.142857142857143</td>
<td>22</td>
<td>13</td>
<td>11</td>
<td>26</td>
</tr>
<tr>
<td>Shop 4</td>
<td>2.6</td>
<td>21.666666666666664</td>
<td>14.333333333333332</td>
<td>12.333333333333332</td>
<td>16.333333333333332</td>
</tr>
<tr>
<td>Shop 5</td>
<td>4.333333333333333</td>
<td>30.333333333333332</td>
<td>10</td>
<td>10</td>
<td>30.333333333333332</td>
</tr>
<tr>
<td>Shop 2</td>
<td>7.5</td>
<td>36.666666666666664</td>
<td>17.333333333333332</td>
<td>14.666666666666666</td>
<td>50.666666666666664</td>
</tr>
</tbody>
</table>
CSS
table {
border-collapse: collapse;
}
table th {
cursor: pointer;
}
table tr,
table td {
padding: 3px;
border-style: dotted;
border: 1px solid #000;
}
JavaScript
[...document.querySelectorAll('th')].forEach(th => {
th.addEventListener('click', () => {
const table = getParentUntil(th, 'table');
let rows = [...table.querySelectorAll('tr:not(.ignore)')]
.sort(sorter([...th.parentElement.children].indexOf(th)));
th.dataset.asc = !(JSON.parse((th.dataset.asc || "true").toLowerCase()));
if (th.dataset.asc === "true") {
rows = rows.reverse();
}
rows.forEach(row => table.appendChild(row));
});
});
function getParentUntil(el, tag) {
while ((el = el.parentElement) && !el.matches(tag));
return el;
}
function sorter(index) {
return (a, b) => {
const aVal = cellValue(a, index);
const bVal = cellValue(b, index);
return isNumber(aVal) && isNumber(bVal) ? aVal - bVal : aVal.localeCompare(bVal);
};
}
function cellValue(row, index) {
return [...row.children][index].innerText;
}
function isNumber(n) {
const number = parseFloat(n);
return !Number.isNaN(number) && Number.isFinite(number);
}