JSFiddle - React, Tailwind, and code Playground

by Twisty

HTML

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css">
<div class="row d-flex justify-content-center">
  <div class="col-md-offset-2 col-md-8">
    <table class="table table-boredered report sortable">
      <thead>
        <tr>
          <th></th>
          <th>Col 1</th>
          <th>Col 2</th>
          <th>Col 3</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <th title="Click to Sort">Row 1</th>
          <td>123</td>
          <td>3</td>
          <td>34</td>
        </tr>
        <tr>
          <th title="Click to Sort">Row 2</th>
          <td>65</td>
          <td>12</td>
          <td>4</td>
        </tr>
        <tr>
          <th title="Click to Sort">Row 3</th>
          <td>43</td>
          <td>54</td>
          <td>65</td>
        </tr>
        <tr>
          <th title="Click to Sort">Row 4</th>
          <td>4</td>
          <td>3</td>
          <td>54</td>
        </tr>
      </tbody>
    </table>
  </div>
</div>

CSS

.sortable tbody tr th {
  cursor: pointer;
}

JavaScript

$(function() {

  var selInd;

  function sortDesc(a, b) {
    return a - b;
  }

  function sortAsc(a, b) {
    return b - a;
  }

  function sortMatrixDesc(a, b) {
    if (a[selInd] === b[selInd]) {
      return 0;
    } else {
      return (a[selInd] < b[selInd]) ? -1 : 1;
    }
  }

  function sortMatrixAsc(a, b) {
    if (a[selInd] === b[selInd]) {
      return 0;
    } else {
      return (a[selInd] > b[selInd]) ? -1 : 1;
    }
  }

  function getTblCont(tb) {
    var cols = [];
    $("tr:first td", tb).each(function(i, el) {
      cols[i] = [];
    });
    for (var c = 0; c < cols.length; c++) {
      $("tr", tb).each(function(i, el) {
        cols[c].push(parseInt($("td", el).eq(c).text().trim()));
      });
    }
    return cols;
  }

  function sortRow(rObj, desc) {
    var tblObj = getTblCont(rObj.parent());
    var rowInd = rObj.index();
    console.log("Pre-Sort", tblObj, selInd);
    if (desc == undefined || desc == true) {
      tblObj.sort(sortMatrixDesc);
    } else {
      tblObj.sort(sortMatrixAsc);
    }
    console.log("Post Sort", tblObj, selInd);
    rObj.parent().find("tr").each(function(r, tr) {
      $("td", tr).each(function(i, el) {
        $(el).html(tblObj[i][r]);
      });
    });
  }

  $(".sortable tbody th").on("click", function(e) {
    var r = $(this).parent();
    selInd = r.index();
    if ($(this).data("sort") == undefined) {
      $(this).data("sort", true);
    }
    sortRow(r, $(this).data("sort"));
    $(this).data("sort", $(this).data("sort") ? false : true);
  });
});