-1

I Cannot understand the array method sort() logic. I had to write an eventListener for the two elements Age and Letter. By clicking on them we can sort our table by age and letter.

All works fine, but I see something strange in the sort() logic. By clicking on the Letter - table must sort by alphabet for elements in the column Letter. By clicking on the Age - table must sort by digits order for elements in the column Age. But it does not sort right.

tbody = document.getElementById('grid');

function tableSort(event) {

  var target = event.target;
  var action = target.getAttribute('data-type');
  var arr = [].slice.call(grid.rows, 1);
  var self = this;

  this.number = function() {

    arr.sort(function(a, b) { // sort by digits in the column "Age"
      a.cells[0].innerHTML;
      b.cells[0].innerHTML;

      return a - b;
    });

    grid.appendChild(...arr);
  }

  this.string = function() {

    arr.sort(function(a, b) { // sort by words in the column "Letter"
      a.cells[1].innerHTML;
      b.cells[1].innerHTML;

      return a > b;
    });

    grid.appendChild(...arr);
  }

  if (action) {
    self[action]();
  }
}

tbody.addEventListener('click', tableSort);
th {
  cursor: pointer;
}
<table id="grid">
  <thead>
    <tr>
      <th data-type="number">Age</th>
      <th data-type="string">Letter</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>5</td>
      <td>BBBBB</td>
    </tr>
    <tr>
      <td>12</td>
      <td>AAAAA</td>
    </tr>
    <tr>
      <td>1</td>
      <td>DDDDD</td>
    </tr>
    <tr>
      <td>9</td>
      <td>CCCCC</td>
    </tr>
    <tr>
      <td>2</td>
      <td>KKKKK</td>
    </tr>
  </tbody>
</table>

<script>
</script>

5
  • 3
    a.cells[0].innerHTML; is a no-op Commented Jan 27, 2018 at 17:04
  • 1
    return a > b; is not a valid comparison function Commented Jan 27, 2018 at 17:04
  • Btw, the vertical ones are called "columns" not "rows". Commented Jan 27, 2018 at 17:05
  • @Bergi thank you for hightlight my automistakes. But it is not the solution. Previously I had try the another way for letters, but it's also does not help: arr.sort((a, b)=>{ return a.cells[1].innerHTML > b.cells[1].innerHTML ? 1 : -1; }); Commented Jan 27, 2018 at 17:09
  • You can get some inspiration from the documentation, sort - it shows what to do with strings, and for the numbers you will probably need parseInt Commented Jan 27, 2018 at 17:42

2 Answers 2

2

Modified your code and got it working. Here if you need it:

  function tableSort(event) {
    var target = event.target;
    var action = target.getAttribute("data-type");
    var arr = [].slice.call(grid.rows, 1);
    var self = this;

    this.number = function() {
      arr.sort(function(a, b) {
        // sort by digits in the column "Age"
        return Number(a.cells[0].innerHTML) - Number(b.cells[0].innerHTML);
      });

      arr.forEach(function(item, index) {
        grid.appendChild(item);
      });
    };

    this.string = function() {
      arr.sort(function(a, b) {
        // sort by words in the column "Letter"
        var str1 = a.cells[1].innerHTML;
        var str2 = b.cells[1].innerHTML;
        return str1.localeCompare(str2);
      });

      arr.forEach(function(item, index) {
        grid.appendChild(item);
      });
    };

    if (action) {
      self[action]();
    }
  }

  tbody.addEventListener("click", tableSort);
Sign up to request clarification or add additional context in comments.

Comments

1

How about this stackoverflow post Sorting HTML table with JavaScript for clarification and the original external article in which I found it with a full example?

Sorting tables with VanillaJS or JQuery

Example:

/**
 * Modified and more readable version of the answer by Paul S. to sort a table with ASC and DESC order
 * with the <thead> and <tbody> structure easily.
 * 
 * https://stackoverflow.com/a/14268260/4241030
 */
var TableSorter = {
    makeSortable: function(table){
        // Store context of this in the object
        var _this = this;
        var th = table.tHead, i;
        th && (th = th.rows[0]) && (th = th.cells);

        if (th){
            i = th.length;
        }else{
            return; // if no `<thead>` then do nothing
        }

        // Loop through every <th> inside the header
        while (--i >= 0) (function (i) {
            var dir = 1;

            // Append click listener to sort
            th[i].addEventListener('click', function () {
                _this._sort(table, i, (dir = 1 - dir));
            });
        }(i));
    },
    _sort: function (table, col, reverse) {
        var tb = table.tBodies[0], // use `<tbody>` to ignore `<thead>` and `<tfoot>` rows
        tr = Array.prototype.slice.call(tb.rows, 0), // put rows into array
        i;

        reverse = -((+reverse) || -1);

        // Sort rows
        tr = tr.sort(function (a, b) {
            // `-1 *` if want opposite order
            return reverse * (
                // Using `.textContent.trim()` for test
                a.cells[col].textContent.trim().localeCompare(
                    b.cells[col].textContent.trim()
                )
            );
        });

        for(i = 0; i < tr.length; ++i){
            // Append rows in new order
            tb.appendChild(tr[i]);
        }
    }
};

window.onload = function(){
    TableSorter.makeSortable(document.getElementById("myTable"));
};
table thead th {
cursor: pointer;

}
<table id="myTable">
<thead>
    <th data-type="string">Name</th>
    <th data-type="number">Age</th>
</thead>
<tbody>
    <tr>
    <td>John</td>
    <td>42</td>
  </tr>
    <tr>
    <td>Laura</td>
    <td>39</td>
  </tr>
    <tr>
    <td>Fred</td>
    <td>18</td>
  </tr>
    <tr>
    <td>Bod</td>
    <td>26</td>
  </tr>
</tbody>
</table>

2 Comments

I'm had use the examples in your link, but they also not help. Moreover I must use only JS solutions for this case
OP has a numeric column, consider addressing that too.

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.