Add Custom Sorting to Tables with the SV-Sortable JS Library

Category: Javascript , Table | February 26, 2024
Author:svivian
Views Total:18 views
Official Page:Go to website
Last Update:February 26, 2024
License:MIT

Preview:

Add Custom Sorting to Tables with the SV-Sortable JS Library

Description:

SV-Sortable is a lightweight and efficient vanilla JavaScript library developed specifically for sorting HTML tables.

Features:

  • Click on headers to sort.
  • Handle any data: Numbers, dates, text, etc.
  • Custom sort types and logic.
  • No heavy dependencies or complex setups.

See Also:

How to use it:

1. Get started by loading the SV-Sortable JS Library in the document.

<script defer src="/src/sv-sortable.js"></script>

2. Initialize the sv-sortable on your HTML table.

document.addEventListener('DOMContentLoaded', function() {
  new SV.Sortable(document.querySelector('table'));
});

3. Specify the data type on a <th> element using the data-sort-type attribute, and the script handles the rest.

<table id="basic">
  <thead>
    <tr>
      <th data-sort-type="int">int</th>
      <th data-sort-type="float">float</th>
      <th data-sort-type="string">string</th>
      <th data-sort-type="string-ins">string-ins</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>15</td>
      <td>-.18</td>
      <td>banana</td>
      <td>Home</td>
    </tr>
    <tr>
      <td>95</td>
      <td>36</td>
      <td>coke</td>
      <td>Hello</td>
    </tr>
    <tr>
      <td>2</td>
      <td>-152.5</td>
      <td>apple</td>
      <td>CSS</td>
    </tr>
    <tr>
      <td>-53</td>
      <td>88.5</td>
      <td>zebra</td>
      <td>Script</td>
    </tr>
    <tr>
      <td>195</td>
      <td>-858</td>
      <td>orange</td>
      <td>Com</td>
    </tr>
  </tbody>
</table>

4. Sort the HTML table by sort values:

<table id="basic">
  <thead>
    <tr>
      <th data-sort-type="int">int</th>
      <th data-sort-type="float">float</th>
      <th data-sort-type="string">string</th>
      <th data-sort-type="string-ins">string-ins</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td data-sort-value="0">C</td>
      <td>-.18</td>
      <td>banana</td>
      <td>Home</td>
    </tr>
    <tr>
      <td data-sort-value="1">s</td>
      <td>36</td>
      <td>coke</td>
      <td>Hello</td>
    </tr>
    <tr>
      <td data-sort-value="2">s</td>
      <td>-152.5</td>
      <td>apple</td>
      <td>CSS</td>
    </tr>
    <tr>
      <td data-sort-value="3">s</td>
      <td>88.5</td>
      <td>zebra</td>
      <td>Script</td>
    </tr>
    <tr>
      <td data-sort-value="4">c</td>
      <td>-858</td>
      <td>orange</td>
      <td>Com</td>
    </tr>
  </tbody>
</table>

5. The sortFns option accepts an object where the keys are sort type IDs and the values are comparator functions. This lets you tailor the sorting behavior for columns containing particular data types like dates, numbers, or strings. For example, you can specify a function to sort dates chronologically instead of alphabetically.

<table>
  <thead>
    <tr>
      <th data-sort-type="int">int</th>
      <th data-sort-type="int">int</th>
      <th data-sort-type="float" data-sort-default="desc">float</th>
      <th data-sort-type="moveBlanks" data-sort-desc="moveBlanksDesc">string</th>
      <th data-sort-type="string-ins">case</th>
      <th>Can't sort me!</th>
      <th data-sort-type="date">date</th>
      <th data-sort-type="int">Letter frequency</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>15</td>
      <td>15</td>
      <td>-.18</td>
      <td>banana</td>
      <td>Homer</td>
      <td>arbitrary</td>
      <td>Sep 15, 2002</td>
      <td data-sort-value="0">E</td>
    </tr>
    <tr>
      <td>95</td>
      <td>95</td>
      <td>36</td>
      <td></td>
      <td>purple</td>
      <td>pointless</td>
      <td>Aug 07, 2004</td>
      <td data-sort-value="1">T</td>
    </tr>
    <tr>
      <td>2</td>
      <td>2</td>
      <td>-152.5</td>
      <td></td>
      <td>is</td>
      <td>silly</td>
      <td>Mar 15, 1986</td>
      <td data-sort-value="2">A</td>
    </tr>
    <tr>
      <td>-53</td>
      <td>-53</td>
      <td>88.5</td>
      <td>hello</td>
      <td>a</td>
      <td>eccentric</td>
      <td>Feb 27, 2086</td>
      <td data-sort-value="3">O</td>
    </tr>
    <tr>
      <td>195</td>
      <td>195</td>
      <td>-858</td>
      <td>orange</td>
      <td>fruit</td>
      <td>garbage</td>
      <td>Mar 15, 1986</td>
      <td data-sort-value="4">I</td>
    </tr>
  </tbody>
</table>
// convert string of the form "Mar 15, 1987" into a Date object.
const dateFromString = function(str) {
  const months = [
    "jan", "feb", "mar", "apr", "may", "jun",
    "jul", "aug", "sep", "oct", "nov", "dec",
  ];
  str = str.trim();
  let pattern = /^([a-zA-Z]{3}) *(\d{1,2}), *(\d{4})$/;
  let regex = new RegExp(pattern);
  let dateParts = regex.exec(str);
  let year = dateParts[3];
  let month = months.indexOf(dateParts[1].toLowerCase());
  let day = dateParts[2];
  return new Date(year, month, day);
};
// blank strings are 'undefined' in sorting, so this moves them to the end
const moveBlanks = function(a, b) {
  if (a < b) {
    if (a == "")
      return 1;
    else
      return -1;
  }
  if (a > b) {
    if (b == "")
      return -1;
    else
      return 1;
  }
  return 0;
};
document.addEventListener('DOMContentLoaded', function() {
  let table = document.querySelector('table');
  let sortable = new SV.Sortable(table, {
    sortFns: {
      "date": function(a, b) {
        let aDate = dateFromString(a);
        let bDate = dateFromString(b);
        return aDate - bDate;
      },
      "moveBlanks": moveBlanks,
    }
  });
});

6. Event handlers.

table.addEventListener('sv.sortable.before', function(ev) {
  document.querySelector('#msg').textContent = "Sorting index " + ev.detail.column;
});
table.addEventListener('sv.sortable.after', function(ev) {
  let thArrows = table.querySelectorAll('th .arrow');
  for (let arrow of thArrows) {
    arrow.remove();
  }
  let arrowEntity = event.detail.dir === sortable.dir.asc ? "&uarr;" : "&darr;";
  event.detail.th.innerHTML += '<span class="arrow">' + arrowEntity + '</span>';
});

Changelog:

02/26/2024

  • v2.1.1: Bugfix

You Might Be Interested In:


Leave a Reply