const table = document.getElementById("test"),
th = test.querySelectorAll("th"),
sortDefault = 0, //default sorted column number
orderDefault = 0; //default order: 0 = ascending, 1 = descending
table.dataset.sort = sortDefault;
table.dataset.order = orderDefault;
/* add click listeners on table headers */
for(let i = 0; i < th.length; i++)
{
th[i].addEventListener("click", e =>
{
/* if this column was sorted, change it's order */
if (+table.dataset.sort == e.target.cellIndex)
table.dataset.order = +table.dataset.order ? 0 : 1;
/* tell table which column is currently sorted */
table.dataset.sort = e.target.cellIndex;
sortColumn();
});
}
populateTable(); //fill table with random data
sortColumn(); //initial sort of the table
function sortColumn()
{
const rows = Array.from(table.children);
rows.splice(0, 1); //remove header from the list
rows.sort((a, b) =>
{
a = a.children[table.dataset.sort].textContent;
b = b.children[table.dataset.sort].textContent;
a = a.replace(/\W/g, ""); //remove non alphanumerical characters
b = b.replace(/\W/g, ""); //remove non alphanumerical characters
a = a.replace(/0x[a-fA-F0-9]+/, n => Number(n)); //convert 0xHEX to decimal
b = b.replace(/0x[a-fA-F0-9]+/, n => Number(n)); //convert 0xHEX to decimal
return a.localeCompare(b, undefined, {numeric: true, sensitivity: 'base'})
});
if (+table.dataset.order)
rows.reverse();
for(let i = 0; i < rows.length; i++)
{
table.appendChild(rows[i]);
}
}
function populateTable()
{
for(let i = 0, _tr = document.createElement("tr"), _td = document.createElement("td"); i < 10; i++)
{
const tr = _tr.cloneNode(true);
let td = _td.cloneNode(true);
td.textContent = "reg " + rand(0, 199);
tr.appendChild(td);
td = _td.cloneNode(true);
td.textContent = "address 0x" + rand(0, 255).toString(16);
if (rand(0,1))
td.textContent = td.textContent.replace(/ (.*)/, ' "$1"');
tr.appendChild(td);
td = _td.cloneNode(true);
td.textContent = "desc " + rand(0, 99999).toString(16);
tr.appendChild(td);
table.appendChild(tr);
}
function rand(min, max)
{
return Math.floor(Math.random() * (max - min + 1)) + min;
}
}
#test
{
border-collapse: collapse;
}
#test tr td
{
border: 1px solid black;
}
#test td
{
padding: 0.5em 1em;
}
#test th
{
user-select: none;
cursor: pointer;
}
#test th:after
{
visibility: hidden;
}
#test[data-order="0"] th:after
{
content: "▲";
}
#test[data-order="1"] th:after
{
content: "▼";
}
#test[data-sort="0"] th:nth-child(1):after,
#test[data-sort="1"] th:nth-child(2):after,
#test[data-sort="2"] th:nth-child(3):after
{
visibility: visible;
}
<table id="test">
<tr>
<th>Register</th>
<th>Address</th>
<th>Description</th>
</tr>
</table>