Sortable Table In HTML Javascript (In Ascending/Descending Order)

Once upon a time, Master Coffee created a report in a table. Joe wanted to sort by the ID in ascending order. Then, Jon wanted to sort by the name in descending order. Then, Joy wanted to sort by the email in ascending order. Master Coffee got fed up and gave them a sortable table instead. So here it is, my simple version of a sortable table – Let’s go!

 

CODE DOWNLOAD

I have released this under the MIT license, feel free to use it in your own project – Personal or commercial. Some form of credits will be nice though. 🙂

 

 

VIDEO TUTORIAL

 

 

SORTABLE TABLE DEMO

Breed Size
Hummingbird Small
Budgie Medium
Cockatiel Medium
Ostrich Large
Robin Medium
Blue Jay Medium
Turkey Vulture Large
Zebra Finch Small
Crow Medium
Chicken Large

Go ahead – Click on a table header to sort in ascending/descending order.

 

 

PART 1) THE HTML – A REGULAR TABLE

sortable.html
<table id="demo">
  <!-- (PART A) TABLE HEADER -->
  <thead>
    <tr>
      <th>Breed</th> <th>Size</th>
    </tr>
  </thead>
 
  <!-- (PART B) TABLE BODY -->
  <tbody>
    <tr>
      <td>Hummingbird</td> <td>Small</td>
    </tr>
    <tr>
      <td>Budgie</td> <td>Medium</td>
    </tr>
    <tr>
      <td>Cockatiel</td> <td>Medium</td>
    </tr>
    <tr>
      <td>Ostrich</td> <td>Large</td>
    </tr>
    <tr>
      <td>Robin</td> <td>Medium</td>
    </tr>
    <tr>
      <td>Blue Jay</td> <td>Medium</td>
    </tr>
    <tr>
      <td>Turkey Vulture</td> <td>Large</td>
    </tr>
    <tr>
      <td>Zebra Finch</td> <td>Small</td>
    </tr>
    <tr>
      <td>Crow</td> <td>Medium</td>
    </tr>
    <tr>
      <td>Chicken</td> <td>Large</td>
    </tr>
  </tbody>
</table>

All you need for the HTML is a “regular well-formed table”.

  • <thead><tbody> It must have a header and body section.
  • <th><td> Use header cells in the header, and normal cells in the body section.

 

 

PART 2) THE JAVASCRIPT – SORT MECHANICS

sortable.js
window.addEventListener("load", () => {
  // (PART A) GET TABLE & ATTACH CUSTOM PROPERTIES
  var stable = document.getElementById("demo");
      stable.sortBy = null; // sort by this column
      stable.sortAsc = null; // sort in ascending order
      stable.data = {}; // table data

  // (PART B) SORT MECHANISM
  stable.sort = by => {
    // (B1) SORT BY & DIRECTION
    if (stable.sortBy == by) { stable.sortAsc = !stable.sortAsc; }
    else { stable.sortBy = by; stable.sortAsc = true; }

    // (B2) UPDATE HTML TABLE HEADER
    for (let th of stable.getElementsByTagName("th")) {
      if (th == by) { th.className = stable.sortAsc ? "asc" : "desc"; }
      else { th.className = ""; }
    }

    // (B3) CREATE A "SORT ORDER MAP"
    let map = stable.data[by.innerHTML].map((v, i) => { return { i: i, v: v }; });

    // (B4) SORT ROWS IN ASCENDING/DESCENDING ORDER
    if (stable.sortAsc) {
      map.sort((a, b) => a.v > b.v ? 1 : (a.v < b.v ? -1 : 0));
    } else {
      map.sort((a, b) => a.v < b.v ? 1 : (a.v > b.v ? -1 : 0));
    }

    // (B5) UPDATE HTML TABLE BODY
    let tbody = stable.getElementsByTagName("tbody")[0];
    tbody.innerHTML = "";
    for (let m of map) {
      let row = tbody.insertRow();
      for (let col of Object.keys(stable.data)) {
        let cell = row.insertCell();
        cell.innerHTML = stable.data[col][m.i];
      }
    }
  };

  // (PART C) INIT SORTABLE TABLE
  let i = 1;
  for (let th of stable.getElementsByTagName("th")) {
    // (C1) "CLICK TO SORT"
    th.addEventListener("click", () => stable.sort(th));

    // (C2) GET TABLE DATA
    stable.data[th.innerHTML] = [];
    for (let td of stable.querySelectorAll(`td:nth-child(${i})`)) {
      stable.data[th.innerHTML].push(td.innerHTML);
    }
    i++;
  }
});

Beginners, keep calm and drink coffee. It will be easier if you trace through in the following order:

  • (A) On window load, get the table and attach custom properties to it.
  • (C) Loop through all the header cells.
    • (C1) Click on a header cell to sort.
    • (C2) Adapt the table data into an object, in the format of HEADER : [CELL, CELL, CELL, ...]
  • (B) When the user clicks on a header cell, this function will do the sorting.
    • (B1 & B2) Set the “sort by this column” and “sort in this order”.
    • (B3) Part 1 of the sort. Create a temporary map array of the selected column and their “original position”. Taking the first column as an example – { i:0, v:Hummingbird }, { i:1, v:Budgie }, { i:2, v:Cockatiel }, ...
    • (B4) Part 2 of the sort. Sort map in ascending/descending order accordingly. Taking the first column in ascending order as an example – {i:5, v:Blue Jay}, {i:1, v:Budgie}, {i:9, v:Chicken}, ...
    • (B5) Part 3 of the sort. Loop through map and update the HTML table accordingly.

 

 

PART 3) THE CSS – COSMETICS

sortable.css
#demo { width: 400px; border-collapse: collapse; }
#demo tr:nth-child(even) { background: #f2f2f2; }
#demo td, #demo th {
  text-align: left; padding: 10px;
  border: 1px solid #ccc;
}
#demo th {
  color: #fff; background: #51759a;
  position: relative; cursor: pointer;
}
#demo th::after { position: absolute; right: 5px; }
#demo th.asc::after { content: "\25BC"; }
#demo th.desc::after { content: "\25B2"; }

Finally, the CSS is not really important. Just some cosmetics, feel free to style the table however you wish.

 

 

THE END – A NOTE ON SORT PERFORMANCE

That’s all for this short tutorial and sharing. But a small note before we end – While most modern devices can work with “reasonably sized tables”, you have to remember that “every device has limited system resources”.

TLDR – Avoid creating massive sortable tables. It is especially bad on mobile devices.

 

 

CHEAT SHEET

Sortable Table In HTML Javascript (click to enlarge)