JSFiddle - React, Tailwind, and code Playground

by terby

HTML

<table>
  <tr>
    <th datatype="rate">Rate</th>
    <th datatype="numericonly">Age</th>
    <th datatype="numeric">Size</th>
  </tr>
  <tr>
    <td>3/3</td>
    <td>4yda</td>
    <td>25</td>
  </tr>
  <tr>
    <td><a href=#>1/3</a></td>
    <td>8yak</td>
    <td></td>
  </tr>
  <tr>
    <td>4/5</td>
    <td>5yaa</td>
    <td>-5</td>
  </tr>
  <tr>
    <td>4/4</td>
    <td>12yka</td>
    <td>100</td>
  </tr>
  <tr>
    <td>1/3</td>
    <td></td>
    <td>-6</td>
  </tr>
</table>
<br>

• add datatype="" property to the th's.
• datatypes = rate, numericonly, numeric
• rate: "4/5" converts to 0.8 so it can be sorted correctly
• numericonly: "8yak" converts to 8 so it can be sorted correctly
• numeric: no need to convert, use it right away

CSS

table, th, td {
    border: 1px solid black;
}
th {
    cursor: pointer;
}

JavaScript

$('th').click(function() {
  var datatype = $(this).attr('datatype');
  var table = $(this).parents('table').eq(0);
  var rows = table.find('tr:gt(0)').toArray().sort(comparer($(this).index(), datatype));
  this.asc = !this.asc;
  if (!this.asc) {
    rows = rows.reverse();
  }
  for (var i = 0; i < rows.length; i++) {
    table.append(rows[i]);
  }
});

function comparer(index, datatype) {
  return function(a, b) {
    if (datatype == 'rate') {
			// age is retrieved as a string like "4/5"
			// therefore it needs to be splitted to do math
			// eval("4/5") works well too but it is not safe at all.
			// it could have been valA = eval(valA); but it aint safe.
      var valA = getCellValue(a, index);
      var valB = getCellValue(b, index);
      var valA = valA.split('/')[0]/valA.split('/')[1];
      var valB = valB.split('/')[0]/valB.split('/')[1];
    } else if (datatype == 'numericonly') {
			// age is retrieved as a string like "8yak"
			// therefore it needs to be a numericonly to be sorted correctly
      var valA = getCellValue(a, index).replace(/\D/g,'');
      var valB = getCellValue(b, index).replace(/\D/g,'');
    } else if (datatype == 'numeric') {
      var valA = getCellValue(a, index);
      var valB = getCellValue(b, index);
    } else {
      var valA = getCellValue(a, index);
      var valB = getCellValue(b, index);
    }
    return $.isNumeric(valA) && $.isNumeric(valB) ? valA - valB : valA.toString().localeCompare(valB);
  }
}

function getCellValue(row, index) {
  return $(row).children('td').eq(index).text();
}

/*
$('th').click(function() {
  var table = $(this).parents('table').eq(0);
  var rows = table.find('tr:gt(0)').toArray().sort(comparer($(this).index()));
  this.asc = !this.asc;
  if (!this.asc) {
    rows = rows.reverse();
  }
  for (var i = 0; i < rows.length; i++) {
    table.append(rows[i]);
  }
});

function comparer(index) {
  return function(a, b) {
    var valA = getCellValue(a, index);
    var valB = getCellValue(b,...