Reputation: 11
I have the code below that I'm using to sort the columns on an html table. It works fine for sorting alphabetically. It also works for sorting when the numbers are single digit.
When I try to sort a column that contains a currency then the sort function doesn't sort the numbers in the correct order.
What would I need to change so it would sort the currency column correctly?
function sortTable(n) {
var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
table = document.getElementById("CarTable");
switching = true;
dir = "asc";
while (switching) {
switching = false;
rows = table.getElementsByTagName("TR");
for (i = 1; i < (rows.length - 1); i++) {
shouldSwitch = false;
x = rows[i].getElementsByTagName("TD")[n];
y = rows[i + 1].getElementsByTagName("TD")[n];
if (dir == "asc") {
if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) {
shouldSwitch= true;
break;
}
} else if (dir == "desc") {
if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) {
shouldSwitch= true;
break;
}
}
}
if (shouldSwitch) {
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
switching = true;
switchcount ++;
} else {
if (switchcount == 0 && dir == "asc") {
dir = "desc";
switching = true;
}
}
}
}
table {
border-spacing: 0;
width: 100%;
border: 1px solid #ddd;
}
th {
cursor: pointer;
}
th, td {
text-align: left;
padding: 16px;
}
tr:nth-child(even) {
background-color: #f2f2f2
}
<html>
<head>
</head>
<body>
<table id="CarTable">
<tr>
<th onclick="sortTable(0)">Name</th>
<th onclick="sortTable(1)">Amount1</th>
</tr>
<tr>
<td>Mustang</td>
<td>$2,000.00</td>
</tr>
<tr>
<td>Charger</td>
<td>$300.00</td>
</tr>
<tr>
<td>Corvette</td>
<td>$225.00</td>
</tr>
<tr>
<td>Firebird</td>
<td>$2,600.00</td>
</tr>
<tr>
<td>GTO</td>
<td>$260.00</td>
</tr>
<tr>
<td>Camaro</td>
<td>$1,000.22</td>
</tr>
<tr>
<td>Barracuda</td>
<td>$52.00</td>
</tr>
<tr>
<td>Impala</td>
<td>$25.00</td>
</tr>
</table>
</body>
</html>
Upvotes: 0
Views: 1424
Reputation: 6540
All you need to do is replace the comparing logic. I took the liberty of changing this part in your code with a function that accepts a mode
parameter. You can extend it easily.
function sortTable(n,mode) {
var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
table = document.getElementById("CarTable");
switching = true;
dir = "asc";
while (switching) {
switching = false;
rows = table.getElementsByTagName("TR");
for (i = 1; i < (rows.length - 1); i++) {
shouldSwitch = false;
x = rows[i].getElementsByTagName("TD")[n];
y = rows[i + 1].getElementsByTagName("TD")[n];
if (dir == "asc") {
if (compareValues(x.innerHTML,y.innerHTML,mode)==1) {
shouldSwitch= true;
break;
}
} else if (dir == "desc") {
if (compareValues(x.innerHTML,y.innerHTML,mode)==-1) {
shouldSwitch= true;
break;
}
}
}
if (shouldSwitch) {
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
switching = true;
switchcount ++;
} else {
if (switchcount == 0 && dir == "asc") {
dir = "desc";
switching = true;
}
}
}
}
function compareValues(x,y,mode){
x = parseValue(x,mode)
y = parseValue(y,mode)
if(x<y)
return -1
if(x>y)
return 1
return 0
}
function parseValue(val,mode){
switch(mode){
case 'alphabet':
return val.toLowerCase()
break
case 'currency':
return parseFloat(val.slice(1).replace(',',''))
return
}
}
table {
border-spacing: 0;
width: 100%;
border: 1px solid #ddd;
}
th {
cursor: pointer;
}
th, td {
text-align: left;
padding: 16px;
}
tr:nth-child(even) {
background-color: #f2f2f2
}
<html>
<head>
</head>
<body>
<table id="CarTable">
<tr>
<th onclick="sortTable(0,'alphabet')">Name</th>
<th onclick="sortTable(1,'currency')">Amount1</th>
</tr>
<tr>
<td>Mustang</td>
<td>$2,000.00</td>
</tr>
<tr>
<td>Charger</td>
<td>$300.00</td>
</tr>
<tr>
<td>Corvette</td>
<td>$225.00</td>
</tr>
<tr>
<td>Firebird</td>
<td>$2,600.00</td>
</tr>
<tr>
<td>GTO</td>
<td>$260.00</td>
</tr>
<tr>
<td>Camaro</td>
<td>$1,000.22</td>
</tr>
<tr>
<td>Barracuda</td>
<td>$52.00</td>
</tr>
<tr>
<td>Impala</td>
<td>$25.00</td>
</tr>
</table>
</body>
</html>
Upvotes: 1
Reputation: 5648
I added the next if to extraxt the values depending on the column
if (n == 0) {
xText = x.innerHTML.toLowerCase();
yText = y.innerHTML.toLowerCase();
} else {
xText = parseFloat(x.innerHTML.split('$')[1].replace(/,/g, ''));
yText = parseFloat(y.innerHTML.split('$')[1].replace(/,/g, ''));
}
I also replace x.innerHTML.toLowerCase()
and y.innerHTML.toLowerCase()
for xText
and yText
this to make an easy change of values depending on the column
Finishing with parseFloat(y.innerHTML.split('$')[1].replace(/,/g, ''));
to extract the float value and delete both the $ sign and the commas
Hope this is what you were looking for :)
function sortTable(n) {
var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0;
table = document.getElementById("CarTable");
switching = true;
dir = "asc";
while (switching) {
switching = false;
rows = table.getElementsByTagName("TR");
for (i = 1; i < (rows.length - 1); i++) {
shouldSwitch = false;
x = rows[i].getElementsByTagName("TD")[n];
y = rows[i + 1].getElementsByTagName("TD")[n];
if (n == 0) {
xText = x.innerHTML.toLowerCase();
yText = y.innerHTML.toLowerCase();
} else {
xText = parseFloat(x.innerHTML.split('$')[1].replace(/,/g, ''));
yText = parseFloat(y.innerHTML.split('$')[1].replace(/,/g, ''));
}
if (dir == "asc") {
if (xText > yText) {
shouldSwitch = true;
break;
}
} else if (dir == "desc") {
if (xText < yText) {
shouldSwitch = true;
break;
}
}
}
if (shouldSwitch) {
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
switching = true;
switchcount++;
} else {
if (switchcount == 0 && dir == "asc") {
dir = "desc";
switching = true;
}
}
}
}
table {
border-spacing: 0;
width: 100%;
border: 1px solid #ddd;
}
th {
cursor: pointer;
}
th,
td {
text-align: left;
padding: 16px;
}
tr:nth-child(even) {
background-color: #f2f2f2
}
<html>
<head>
</head>
<body>
<table id="CarTable">
<tr>
<th onclick="sortTable(0)">Name</th>
<th onclick="sortTable(1)">Amount1</th>
</tr>
<tr>
<td>Mustang</td>
<td>$2,000.00</td>
</tr>
<tr>
<td>Charger</td>
<td>$300.00</td>
</tr>
<tr>
<td>Corvette</td>
<td>$225.00</td>
</tr>
<tr>
<td>Firebird</td>
<td>$2,600.00</td>
</tr>
<tr>
<td>GTO</td>
<td>$260.00</td>
</tr>
<tr>
<td>Camaro</td>
<td>$1,000.22</td>
</tr>
<tr>
<td>Barracuda</td>
<td>$52.00</td>
</tr>
<tr>
<td>Impala</td>
<td>$25.00</td>
</tr>
</table>
</body>
</html>
Upvotes: 1