0

I'm using the following code from another stackoverflow question:

$('th').click(function(){
    var table = $(this).parents('table').eq(0)
    var rows = table.find('tr:gt(0)').toArray().sort(comparer($(this).index()))
    this.asc = !this.asc
    if (!this.asc){rows = rows.reverse()}
    for (var i = 0; i < rows.length; i++){table.append(rows[i])}
})
function comparer(index) {
    return function(a, b) {
        var valA = getCellValue(a, index), valB = getCellValue(b, index)
        return $.isNumeric(valA) && $.isNumeric(valB) ? valA - valB : valA.toString().localeCompare(valB)
    }
}
function getCellValue(row, index){ return $(row).children('td').eq(index).text() }
table, th, td {
    border: 1px solid black;
}
th {
    cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
    <tr><th>Country</th><th>Pick</th><th>Size</th></tr>
    <tr><td>France</td><td>2</td><td>25</td></tr>
    <tr><td><a href=#>spain</a></td><td>-</td><td></td></tr>
    <tr><td>Lebanon</td><td>1</td><td>-17</td></tr>
    <tr><td>Argentina</td><td>DH</td><td>100</td></tr>
    <tr><td>USA</td><td>-</td><td>-6</td></tr>
</table>

which works great for most data. My problem is with the "Pick" column. I'd like it to sort so that it looks like this:

Pick
1
2
DH
-
-

I'm assuming it's the comparer function that I'd need to modify. How do I modify this so that it basically always puts "-" at the bottom of the table and then sorts numbers from lowest to highest with "DH" right below the numbers? Is that a pretty simple addition to the function? Or is it a ton of custom code?

2
  • @ibrahimmahrir - I'm not sure the OP will be happy with that. A string sort will sort 1, 10, 11, 2, 21, etc. While a numeric sort (as done) will not do that. Commented May 14, 2018 at 22:15
  • Is it possible to set the cell value to undefined? I quote the docs for sort: "All undefined elements are sorted to the end of the array." Commented May 14, 2018 at 22:17

1 Answer 1

1

You can just add some custom logic to your comparer.

The only part I changed in the snippet below is the function comparer(index) contents.

$('th').click(function(){
    var table = $(this).parents('table').eq(0)
    var rows = table.find('tr:gt(0)').toArray().sort(comparer($(this).index()))
    this.asc = !this.asc
    if (!this.asc){rows = rows.reverse()}
    for (var i = 0; i < rows.length; i++){table.append(rows[i])}
})
function comparer(index) {
    return function(a, b) {
        var valA = getCellValue(a, index), valB = getCellValue(b, index);
        
        if (valA === "-") valA = Number.MAX_SAFE_INTEGER;
        if (valB === "-") valB = Number.MAX_SAFE_INTEGER;
        if (valA === "DH") valA = Number.MAX_SAFE_INTEGER - 1;
        if (valB === "DH") valB = Number.MAX_SAFE_INTEGER - 1;

        return $.isNumeric(valA) && $.isNumeric(valB) ? valA - valB : valA.toString().localeCompare(valB)
    }
}
function getCellValue(row, index){ return $(row).children('td').eq(index).text() }
table, th, td {
    border: 1px solid black;
}
th {
    cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
    <tr><th>Country</th><th>Pick</th><th>Size</th></tr>
    <tr><td>France</td><td>2</td><td>25</td></tr>
    <tr><td><a href=#>spain</a></td><td>-</td><td></td></tr>
    <tr><td>Lebanon</td><td>1</td><td>-17</td></tr>
    <tr><td>Argentina</td><td>DH</td><td>100</td></tr>
    <tr><td>USA</td><td>-</td><td>-6</td></tr>
</table>

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.