-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>
Brett DeWoody
  • 59,771
  • 29
  • 135
  • 184
Sviat Kuzhelev
  • 1,758
  • 10
  • 28
  • 3
    `a.cells[0].innerHTML;` is a no-op – axiac Jan 27 '18 at 17:04
  • 1
    [`return a > b;` is not a valid comparison function](https://stackoverflow.com/q/24080785/1048572) – Bergi Jan 27 '18 at 17:04
  • Btw, the vertical ones are called "columns" not "rows". – Bergi Jan 27 '18 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; }); ` – Sviat Kuzhelev Jan 27 '18 at 17:09
  • You can get some inspiration from the documentation, [```sort```](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) - it shows what to do with strings, and for the numbers you will probably need [```parseInt```](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt) – tevemadar Jan 27 '18 at 17:42

2 Answers2

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);
NiK648
  • 1,484
  • 1
  • 9
  • 18
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>
suchislife
  • 4,251
  • 10
  • 47
  • 78