Reputation: 133
Script giving wrong result for numeric values, how can I fix it to work for both numeric and alphabet?
Here is the javascript I used
function sortTableByColumn(table, column, asc = true) {
const dirModifier = asc ? 1 : -1;
const tBody = table.tBodies[0];
const rows = Array.from(tBody.querySelectorAll("tr"));
// Sort each row
const sortedRows = rows.sort((a, b) => {
const aColText = a.querySelector(`td:nth-child(${ column + 1 })`).textContent.trim();
const bColText = b.querySelector(`td:nth-child(${ column + 1 })`).textContent.trim();
return aColText > bColText ? (1 * dirModifier) : (-1 * dirModifier);
});
// Remove all existing TRs from the table
while (tBody.firstChild) {
tBody.removeChild(tBody.firstChild);
}
// Re-add the newly sorted rows
tBody.append(...sortedRows);
// Remember how the column is currently sorted
table.querySelectorAll("th").forEach(th => th.classList.remove("th-sort-asc", "th-sort-desc"));
table.querySelector(`th:nth-child(${ column + 1})`).classList.toggle("th-sort-asc", asc);
table.querySelector(`th:nth-child(${ column + 1})`).classList.toggle("th-sort-desc", !asc);
}
document.querySelectorAll(".table-sortable th").forEach(headerCell => {
headerCell.addEventListener("click", () => {
const tableElement = headerCell.parentElement.parentElement.parentElement;
const headerIndex = Array.prototype.indexOf.call(headerCell.parentElement.children, headerCell);
const currentIsAscending = headerCell.classList.contains("th-sort-asc");
sortTableByColumn(tableElement, headerIndex, !currentIsAscending);
});
});
.table-sortable th {
cursor: pointer;
}
.table-sortable .th-sort-asc::after {
content: "\25b4";
}
.table-sortable .th-sort-desc::after {
content: "\25be";
}
.table-sortable .th-sort-asc::after,
.table-sortable .th-sort-desc::after {
margin-left: 5px;
}
.table-sortable .th-sort-asc,
.table-sortable .th-sort-desc {
background: rgba(0, 0, 0, 0.1);
}
<html>
<head><title>Some table</title></head>
<body>
<table class="table-sortable">
<thead>
<tr>
<th>Roll number</th>
<th>Name</th>
<th>Another number</th>
<tr>
</thead>
<tbody>
<tr><td>34351</td><td>svvfvs</td><td>4551</td></tr>
<tr><td>99</td><td>ghh</td><td>413</td></tr>
<tr><td>6455</td><td>fddfbb</td><td>82</td></tr>
<tr><td>1245</td><td>dfvfdvfdv</td><td>4315</td></tr>
<tr><td>46130</td><td>fvfvfvf</td><td>8846161</td></tr>
</tbody>
</table>
</body>
</html>
The css script is only used for the indication of asc, dec no problem in css though
You can run the code and see the column 1st and the 3rd are just taking 1st character and taking that to sort the numbers too giving wrong result.
Can you please edit the code and post it as a whole, It would really happen. Thanks in advance
Upvotes: 1
Views: 658
Reputation: 882
You can simply check if the aColText
and bColText
are number
or string
in your sort function
function sortTableByColumn(table, column, asc = true) {
const dirModifier = asc ? 1 : -1;
const tBody = table.tBodies[0];
const rows = Array.from(tBody.querySelectorAll("tr"));
// Sort each row
const sortedRows = rows.sort((a, b) => {
const aColText = a.querySelector(`td:nth-child(${ column + 1 })`).textContent.trim();
const bColText = b.querySelector(`td:nth-child(${ column + 1 })`).textContent.trim();
if (isNaN(parseFloat(aColText)) && isNaN(parseFloat(bColText))) {
return aColText > bColText ? (1 * dirModifier) : (-1 * dirModifier);
}
return +aColText > +bColText ? (1 * dirModifier) : (-1 * dirModifier);
});
// Remove all existing TRs from the table
while (tBody.firstChild) {
tBody.removeChild(tBody.firstChild);
}
// Re-add the newly sorted rows
tBody.append(...sortedRows);
// Remember how the column is currently sorted
table.querySelectorAll("th").forEach(th => th.classList.remove("th-sort-asc", "th-sort-desc"));
table.querySelector(`th:nth-child(${ column + 1})`).classList.toggle("th-sort-asc", asc);
table.querySelector(`th:nth-child(${ column + 1})`).classList.toggle("th-sort-desc", !asc);
}
document.querySelectorAll(".table-sortable th").forEach(headerCell => {
headerCell.addEventListener("click", () => {
const tableElement = headerCell.parentElement.parentElement.parentElement;
const headerIndex = Array.prototype.indexOf.call(headerCell.parentElement.children, headerCell);
const currentIsAscending = headerCell.classList.contains("th-sort-asc");
sortTableByColumn(tableElement, headerIndex, !currentIsAscending);
});
});
.table-sortable th {
cursor: pointer;
}
.table-sortable .th-sort-asc::after {
content: "\25b4";
}
.table-sortable .th-sort-desc::after {
content: "\25be";
}
.table-sortable .th-sort-asc::after,
.table-sortable .th-sort-desc::after {
margin-left: 5px;
}
.table-sortable .th-sort-asc,
.table-sortable .th-sort-desc {
background: rgba(0, 0, 0, 0.1);
}
<html>
<head>
<title>Some table</title>
</head>
<body>
<table class="table-sortable">
<thead>
<tr>
<th>Roll number</th>
<th>Name</th>
<th>Another number</th>
<tr>
</thead>
<tbody>
<tr>
<td>34351</td>
<td>svvfvs</td>
<td>4551</td>
</tr>
<tr>
<td>99</td>
<td>ghh</td>
<td>413</td>
</tr>
<tr>
<td>6455</td>
<td>fddfbb</td>
<td>82</td>
</tr>
<tr>
<td>1245</td>
<td>dfvfdvfdv</td>
<td>4315</td>
</tr>
<tr>
<td>46130</td>
<td>fvfvfvf</td>
<td>8846161</td>
</tr>
</tbody>
</table>
</body>
</html>
Upvotes: 1