Simple Sortable Table With HTML Javascript (Free Download)

Welcome to a tutorial on how to create a simple sortable table with Javascript. So you have an array or HTML table that needs some sortable action? Sadly, there is no way we can do it with just pure HTML. We need to define data arrays and do array sorting in Javascript instead – This guide will walk you through the exact steps on how to do it, read on to find out!

ⓘ I have included a zip file with all the example source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.

 

TABLE OF CONTENTS

 

 

DOWNLOAD & DEMO

Firstly, here is the download link to the example code as promised.

 

QUICK NOTES

If you spot a bug, feel free to comment below. I try to answer short questions too, but it is one person versus the entire world… If you need answers urgently, please check out my list of websites to get help with programming.

 

EXAMPLE CODE DOWNLOAD

Click here to download the source code, I have released it under the MIT license, so feel free to build on top of it or use it in your own project.

 

QUICKSTART & DEMO

SORTABLE TABLE ON AN EXISTING TABLE

1-existing.html
<!-- (A) JS + CSS -->
<link rel="stylesheet" href="sorta.css">
<script src="sorta.js"></script>
 
<!-- (B) TABLE : NEEDS PROPER THEAD/TBODY -->
<table id="demoA">
  <thead>
    <tr>
      <td>Fruit</td>
      <td>Color</td>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Durian</td>
      <td>Green</td>
    </tr>
    <tr>
      <td>Orange</td>
      <td>Orange</td>
    </tr>
    <tr>
      <td>Apple</td>
      <td>Red</td>
    </tr>
    <tr>
      <td>Grape</td>
      <td>Red</td>
    </tr>
    <tr>
      <td>Blueberry</td>
      <td>Blue</td>
    </tr>
    <tr>
      <td>Pear</td>
      <td>Green</td>
    </tr>
  </tbody>
</table>
 
 <!-- (C) INITIALIZE -->
<script>
sorta(document.getElementById("demoA"));
</script>
Fruit Color
Durian Green
Orange Orange
Apple Red
Grape Red
Blueberry Blue
Pear Green
  1. Load the Javascript sorta.js, the CSS is not essential.
  2. Create your HTML table as usual. Just make sure that it has a proper <thead> and <tbody> section.
  3. Call sorta(HTML TABLE) to turn it into a sortable table.

 

 

SORTABLE TABLE WITH OBJECT DATA

2-data-object.html
<!-- (B) EMPTY TABLE -->
<table id="demoB"></table>
 
<!-- (C) INITIALIZE -->
<script>
sorta(document.getElementById("demoB"), {
  ID : [44, 11, 7, 5, 2],
  Name : ["John Doe", "Jane Doe", "Aaron Doe", "Zoe Doe", "Derrick Doe"],
  Color : ["Red", "Green", "Blue", "White", "Red"]
});
</script>

Yes, it’s the same sorta(), except that we pass in an object data in the second parameter.

P.S. The object must be in the format of { HEAD : [ROWS], HEAD : [ROWS], ETC... }

 

SORTABLE TABLE JAVASCRIPT

With that, let us now get into more details of how the sortable table work in this section – This is for you guys who want to “deep customize” it.

 

PART 1) ADDING FLAGS TO THE TABLE

sorta.js
function sorta (instance, data) {
  // (A) ATTACH FLAGS TO TABLE
  instance.sBy = null; // sort by this field
  instance.sDirection = true; // ascending/descending
  instance.sOrder = []; // calculated sort order
 
  // ...
}

The entire Javascript file only has a function sorta(), which you have seen in the above demo. A quick reminder on the parameters:

  • instance The HTML table itself.
  • data Optional, object data.

So the first thing we do is to initialize the sort mechanics by adding flags to the table. Yes, beginners, we can add variables to HTML elements in modern Javascript.

  • sBy Sort by which column.
  • sDirection Sort in ascending (true) or descending (false) order.
  • sOrder The calculated sort order.

 

 

PART 2) SORT FUNCTION

sorta.js
// (B) ATTACH SORT FUNCTION TO TABLE
instance.sort = selected => {
  // (B1) UPDATE SORT FLAGS
  if (instance.sBy == selected.innerHTML) {
    instance.sDirection = !instance.sDirection;
  } else {
    instance.sBy = selected.innerHTML;
    instance.sDirection = true;
  }
 
  // (B2) UPDATE CSS OF HEADER CELLS
  for (let c of instance.head.rows[0].cells) {
    c.classList.remove("sortup");
    c.classList.remove("sortdown");
    if (c == selected) {
      c.classList.add((instance.sDirection ? "sortup" : "sortdown"));
    }
  }
 
  // (B3) MAP OUT DATA OF THE SELECTED COLUMN
  // I.E. WE NEED TO RETAIN THE INDEX POSITIONS WHILE SORTING
  let map = data[selected.innerHTML].map((v, i) => { return { i: i, v: v }; });
 
  // (B4) SORT ARRAY
  if (instance.sDirection) {
    map.sort((a, b) => {
      if (a.v > b.v) { return 1; }
      if (a.v < b.v) { return -1; }
      return 0;
    });
  } else {
    map.sort((a, b) => {
      if (a.v < b.v) { return 1; }
      if (a.v > b.v) { return -1; }
      return 0;
    });
  }
 
  // (B5) REDRAW TABLE WITH NEW SORT ORDER
  instance.sOrder = [];
  for (let idx in map) { instance.sOrder.push(map[idx].i); }
  delete(map); instance.draw();
};

Yikes, the next piece of confusion is called “sort”. Not going to explain this line-by-line, but the essentials are:

  • As above. Keep in mind that the table data is kept in the format of { HEAD : [ITEM, ITEM, ITEM] }.
  • We will not mess with data directly, but calculate the sort order for [ITEM, ITEM, ITEM] separately in sOrder.
  • When the user clicks on a header cell to sort:
    • (B1) We set the “sort by this column” sBy and sort direction sDirection.
    • (B3)  Create a temporary var map with both the index and value of the items – var map = [{i:INDEX, v:ITEM}, {i:INDEX, v:ITEM}].
    • (B4) Sort the map.
    • (B5) Loop through map, extract only the index into sOrder.

 

 

PART 3) DRAW TABLE ROWS

sorta.js
// (C) FUNCTION TO REDRAW TABLE DATA
instance.draw = () => {
  // (C1) REMOVE OLD SORT ORDER
  instance.body.innerHTML = "";
 
  // (C2) DRAW NEW SORT ORDER
  let r, c;
  for (let i of instance.sOrder) {
    r = instance.body.insertRow();
    for (let key in data) {
      c = r.insertCell();
      c.innerHTML = data[key][i];
    }
  }
};

Once we have the sort order, we simply loop through sOrder and draw the table rows.

 

PART 4) READ EXISTING TABLE

sorta.js
// (D) ADAPT EXISTING TABLE TO SORTABLE TABLE
if (data==undefined) {
  // (D1) GET TABLE SECTIONS
  instance.head = instance.querySelector("thead");
  instance.body = instance.querySelector("tbody");
 
  // (D2) GET DATA FROM HEADER
  data = {}; keys = [];
  for (let c of instance.head.rows[0].cells) {
    data[c.innerHTML] = [];
    keys.push(c.innerHTML);
  }
 
  // (D3) GET DATA FROM BODY
  for (let r of instance.body.rows) { for (let i=0; i<r.cells.length; i++) {
    data[keys[i]].push(r.cells[i].innerHTML);
  }}
  delete(keys);
}

Remember the data parameter? For existing tables, we simply run through the table and adapt the data.

 

 

PART 5) BUILD SORTABLE TABLE FROM OBJECT

sorta.js
// (E) DRAW SORTABLE TABLE FROM OBJECT
else {
  // (E1) CREATE TABLE SECTIONS
  instance.head = instance.createTHead();
  instance.body = instance.createTBody();
 
  // (E2) HEADER CELLS
  let r = instance.head.insertRow();
  r = instance.head.rows[0];
  for (let key in data) {
    let c = r.insertCell();
    c.innerHTML = key;
  }
 
  // (E3) DEFAULT SORT ORDER & DRAW BODY
  for (let i=0; i<data[Object.keys(data)[0]].length; i++) { instance.sOrder.push(i); }
  instance.draw();
}

If an object data is specified, we simply build the HTML from it.

 

PART 6) CSS CLASS & CLICK TO SORT

sorta.js
// (F) ADD CSS CLASS + ATTACH CLICK TO SORT
instance.classList.add("sorta");
  for (let r of instance.head.rows) { for (let c of r.cells) {
  c.onclick = () => instance.sort(c);
}} 

This final part should be self-explanatory. We attach the “click to sort” on all header cells.

 

 

EXTRA BITS & LINKS

That’s all for this project, and here is a small section on some extras and links that may be useful to you.

 

LIMITATIONS & PERFORMANCE

This sortable table relies on ARRAY.sort() – It should work pretty well and fast with most modern computers these days… But yep, it is not the most effective way to do sorting, and you will probably get hit with performance issues with large datasets.

 

NO “ERROR CHECKING”

Please make sure that your dataset and number of columns are correct on your own. I have contemplated adding an “auto check and fix”, but came to a simple conclusion:

  • Checking massive datasets takes resources, it is simply not efficient to do so for the sake of “dummy proofing”.
  • This is a “simple sortable table” tutorial, not “how to automatically fix your screw-up”.
  • As a developer (or even as a user), you are responsible for the integrity of your own datasets.
  • If there is a missing column or extra columns – Only you know what needs to be fixed.

 

COMPATIBILITY CHECKS

All the required features are well-supported on modern browsers.

 

LINKS & REFERENCES

 

THE END

Thank you for reading, and we have come to the end of this guide. I hope that it has helped you with your project, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!

3 thoughts on “Simple Sortable Table With HTML Javascript (Free Download)”

  1. Hello, I am JS enthusiast but not a pro.
    Well done but it crash when more column in bodythat in header (well ok that’s not supposed to be). Correction to allow more body column that header 🙂

    // (D3) GET DATA FROM BODY
    var cx=0;
    for (let r of instance.body.rows) { for (let i=0; i<r.cells.length; i++) {
      if (keys[i]) {
        data[keys[i]].push(r.cells[i].innerHTML);
      } else {
        newColName="_"+cx;
        keys[i]=(newColName); 
        if (! Array.isArray(data[cx])){ data[newColName]=[]; }
        data[newColName][i]=(r.cells[i].innerHTML);	
        cx++;
      }
    }}
    delete(keys);
    1. Thanks for sharing. I will assume you mean “when the number of columns in the head and body doesn’t match”. I will add a check and throw errors in the future, but not “automatically fix it” by generating empty cells – Users should verify the data by themselves.

Leave a Comment

Your email address will not be published. Required fields are marked *