1

I have a html table that is made as follows:

<table border="1" id="table">

<tbody>
<tr>
    <th>Month</th>
    <th>Day</th>
</tr>

<tr>
    <td>March</td>
    <td>1</td>
</tr>

<tr>
    <td>February</td>
    <td>21</td>
</tr>

<tr>
    <td>February</td>
    <td>7</td>
</tr>

<tr>
    <td>March</td>
    <td>9</td>
</tr>

<tr>
    <td>February</td>
    <td>4</td>
</tr>

</tbody>
</table>

I'm trying to use jquery to sort the table so they will appear in the correct Month / Day order. ie:

February 4
February 7
February 21
March 1
March 9

I've got an array of months: var months = ['','January','February','March','April','May','June','July','August','September','October','November','December'];

and I've tried ordering the table using:

// Order by Month
var $table=$('#table');
var rows = $table.find('tr').get();
rows.sort(function(a, b) {
    var keyA = $.inArray( $(a).find('td:eq(0)').text(), months)
    var keyB = $.inArray( $(b).find('td:eq(0)').text(), months);
    if ( keyA.length < 2 ) keyA = "0" + keyA
    if ( keyB.length < 2 ) keyB = "0" + keyB
    console.log ( keyA + ' ' + keyB )
    
    if (!keyA || !keyB) return -1;
    if (keyA > keyB) return 1;
    if (keyA < keyB) return -1;
    return 0;
});

// order by day
rows.sort(function(a, b) {
    var keyA = $(a).find('td:eq(1)').text();
    var keyB = $(b).find('td:eq(1)').text();
    if ( keyA.length < 2 ) keyA = "0" + keyA
    if ( keyB.length < 2 ) keyB = "0" + keyB
    console.log ( keyA + ' ' + keyB )
    
    if (!keyA || !keyB) return -1;
    if (keyA > keyB) return 1;
    if (keyA < keyB) return -1;
    return 0;
});

$.each(rows, function(index, row) {
    $table.children('tbody').append(row);
})

But that hasn't worked. I get:

March 1
February 4
February 7
March 9
February 21

How do I get this to order them correctly ?

Thanks

2 Answers 2

1

To sort by two columns you need to separate the sort logic, and call it per column. If the sort logic on the primary column determines that the values are the same, then sort the entities by the secondary column. Try this:

let months = ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
let monthSort = (a, b) => Math.min(1, Math.max(-1, months.indexOf(a) - months.indexOf(b)));
let intSort = (a, b) => Math.min(1, Math.max(-1, a - b));

let $table = $('#table');
$table.find('tbody tr').sort((a, b) => {
  let diff = monthSort(a.cells[0].textContent.trim(), b.cells[0].textContent.trim());
  return diff !== 0 ? diff : intSort(parseInt(a.cells[1].textContent, 10), parseInt(b.cells[1].textContent, 10));
}).appendTo($table);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table border="1" id="table">
  <tbody>
    <tr>
      <th>Month</th>
      <th>Day</th>
    </tr>
    <tr>
      <td>March</td>
      <td>1</td>
    </tr>
    <tr>
      <td>February</td>
      <td>21</td>
    </tr>
    <tr>
      <td>February</td>
      <td>7</td>
    </tr>
    <tr>
      <td>March</td>
      <td>9</td>
    </tr>
    <tr>
      <td>February</td>
      <td>4</td>
    </tr>
  </tbody>
</table>

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

2 Comments

I tried this before the edit and it worked fine in my page, after the edit the order appears to be wrong.
I updated the names of the functions and the data passed to them so it's a better separation of concerns. Try copying the whole thing again.
0

You can also do it in a single sort operation if you translate each tr into a date object:

function dt(tr){
  return new Date([...tr.children].reverse().map(e=>e.textContent).join(" ")+" 2020");
}

const tbd=$('#table tbody');
tbd.find('tr').sort((a, b)=>dt(a)-dt(b)).appendTo(tbd)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table border="1" id="table">
  <tbody>
    <tr>
      <th>Month</th>
      <th>Day</th>
    </tr>
    <tr>
      <td>March</td>
      <td>1</td>
    </tr>
    <tr>
      <td>February</td>
      <td>21</td>
    </tr>
    <tr>
      <td>February</td>
      <td>7</td>
    </tr>
    <tr>
      <td>March</td>
      <td>9</td>
    </tr>
    <tr>
      <td>February</td>
      <td>4</td>
    </tr>
  </tbody>
</table>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.