skip to Main Content

If I have the following table…

<table role="presentation" data="regMultipleTable">
<tbody>
  <tr class="d-none"><td>hide</td><td>hide</td></tr>
  <tr><td class="d-none">item 1</td><td><font>zebra</font></td></tr>
  <tr><td class="d-none">item 2</td><td><font>ape</font></td></tr>
  <tr><td class="d-none">item 3</td><td><font>dog</font></td></tr>
  <tr class="border-none"><td></td><td><h3>other stuff</h3></td></tr>
</tbody>
</table>

…how come my following jQuery logic sorts all the <tr> elements? Should it not be sorting only the mid <tr> elements? How can I exclude the first and the last <tr>, so they stay where they are?

function sortTable(table, order) {
  var asc = order === 'asc',
    tbody = table.find('tbody');
    
    /*IN ADDITION TO SLICE() BELOW, I ALSO TRIED: 
        'tr:not(.d-none,.border-none)'
        'tr:not(:first, :last)'
    */
    tbody.find('tr').slice(1, -1).sort(function(a, b) {
    if (asc) {
      return window.jQuery('td:eq(1) font', a).text().localeCompare(window.jQuery('td:eq(1) font', b).text());
    } else {
      return window.jQuery('td:eq(1) font', b).text().localeCompare(window.jQuery('td:eq(1) font', a).text());
    }
  }).appendTo(tbody);
}

sortTable(window.jQuery('table[data="regMultipleTable"]'), 'asc');

The end result should be…

<table role="presentation" data="regMultipleTable">
<tbody>
  <tr class="d-none"><td>hide</td><td>hide</td></tr>
  <tr><td class="d-none">item 2</td><td><font>ape</font></td></tr>
  <tr><td class="d-none">item 3</td><td><font>dog</font></td></tr>
  <tr><td class="d-none">item 1</td><td><font>zebra</font></td></tr>
  <tr class="border-none"><td></td><td><h3>other stuff</h3></td></tr>
</tbody>
</table>

Many thanks

3

Answers


  1. Since you are already sorting using a user supplied callback, all you need todo is take care that the first and last <tr> always "wins" the comparison by getting -1 or 1 respectively.

    UPDATE: to support firefox which does some sort of sort optimization, need to check both a and b. Refactoring needed.

    function sortTable(table, order) {
      var asc = order === 'asc',
        tbody = table.find('tbody');
      tbody.find('tr').sort(function(a, b) {
        if (asc) {
          if ($(a).is(":first-child")) {
            return -1;
          }
          if ($(a).is(":last-child")) {
            return 1;
          }
          if ($(b).is(":first-child")) {
            return 1;
          }
          if ($(b).is(":last-child")) {
            return -1;
          }      
    
          return window.jQuery('td:eq(1) font', a).text().localeCompare(window.jQuery('td:eq(1) font', b).text());
        } else {
          if ($(a).is(":first-child")) {
            return 1;
          }
          if ($(a).is(":last-child")) {
            return -1;
          }
          if ($(b).is(":first-child")) {
            return -1;
          }
          if ($(b).is(":last-child")) {
            return 1;
          } 
    
          return window.jQuery('td:eq(1) font', b).text().localeCompare(window.jQuery('td:eq(1) font', a).text());
        }
      }).appendTo(tbody);
    }
    
    sortTable(window.jQuery('table[data="regMultipleTable"]'), 'asc');
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
    <table role="presentation" data="regMultipleTable" border=1>
      <tbody>
        <tr class="d-none"><td>hide</td><td>hide</td></tr>
        <tr><td class="d-none">item 2</td><td><font>ape</font></td></tr>
        <tr><td class="d-none">item 3</td><td><font>dog</font></td></tr>
        <tr><td class="d-none">item 1</td><td><font>zebra</font></td></tr>
        <tr class="border-none"><td></td><td><h3>other stuff</h3></td></tr>
      </tbody>
    </table>
    Login or Signup to reply.
  2. or you just can add a class to all the rows you want to sort, like this:

    <tr class='sortMe'>
    

    And then change this line:

    tbody.find('tr').slice(1, -1).sort(function(a, b) {
    

    to this:

    tbody.find('tr.sortMe').slice(1, -1).sort(function(a, b) {
    
    Login or Signup to reply.
  3. Here is another way of achieving the same – with Vanilla JavaScript:

    var [first,...trs]=[...document.querySelector("tbody").children].slice(0,-1);
    document.querySelectorAll("button").forEach((btn,i)=>btn.onclick=ev=>{
     if(first.srt!==i){
      first.srt=i;
      trs.sort((a,b)=>a.children[i].textContent.localeCompare(b.children[i].textContent));
     }
     else trs=trs.reverse();
     first.after(...trs);
    });
    <table role="presentation" data="regMultipleTable">
      <tbody>
        <tr class="d-none"><td><button>sort</button></td><td><button>sort</button></td></tr>
        <tr><td class="d-none">item 3</td><td><font>dog</font></td></tr>
        <tr><td class="d-none">item 2</td><td><font>ape</font></td></tr>
        <tr><td class="d-none">item 1</td><td><font>zebra</font></td></tr>
        <tr class="border-none"><td></td><td><h3>other stuff</h3></td></tr>
     </tbody>
    </table>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search