Menu

How to add sorting to any table in JavaScript

How to add sorting to any table in JavaScript

In this post I'll be going over how to add the ability to sort any column to any table using JavaScript. All you will need to do is to add a sorting class to the specified table that you wish to add sorting to.

For this particular example, I used the bubble sort algorithm as the custom sorting algorithm, because it is one of the simplest to implement and to showcase. However, it is not the most efficient as far as performance goes. If you are sorting millions of records for example, it might benefit you to find a different algorithm.

Here is a running demo of the final output.

Demo

Number City
7 Los Angeles
4 Chicago
6 San Francisco
2 Long Beach

You can use the following HTML as a test table:

<table class="table sorting">
<tbody><tr>
<th>Number</th>
<th>City</th>
</tr>

<tr>
<td>7</td>
<td>Los Angeles</td>
</tr>

<tr>
<td>4</td>
<td>Chicago</td>
</tr>

<tr>
<td>6</td>
<td>San Francisco</td>
</tr>

<tr>
<td>2</td>
<td>Long Beach</td>
</tr>
</tbody></table>

1. Create sort links

First off, let's start by creating the sorting links that will be added to each header cell in the tables. And we can do that once the page loads by query selecting all elements with the .sorting class. The following function will generate sorting links for each table with the 'sorting' class.

var tables = document.querySelectorAll('.sorting');

    function loadsort()
    {
        for (var i = 0; i < tables.length; i++)
        {
            var headers = tables[i].querySelectorAll('th');

            for (var x = 0; x < headers.length; x++)
            {
                var header = headers[x];
                var sortlink = document.createElement('a');
                var datatype = header.dataset.type;

                sortlink.innerHTML = header.innerHTML + '?';
                sortlink.dataset.column = x;
                sortlink.dataset.name = header.innerHTML;
                sortlink.dataset.direction = 'asc';
                sortlink.addEventListener('click', function (e) {
                        sort(this);
                    });

                headers[x].innerHTML = '';
                headers[x].appendChild(sortlink);
                }
        }
    }

This function will create new links and will replace each header's text with those links. Once a user clicks on the link, the appropriate sorting function will be called. Notice the dataset values that are being added to the sorting link. The direction dataset attribute will determine our initial sorting direction on our table, whether ascending or descending.

2. Create sort function

There are numerous sorting algorithms at your disposal, and rather than listing them all down or defining each one, I'll select the simplest to use as an example. And that would be the infamous Bubble sort. Easy to implement, but not the best when it comes to performance. So feel free to replace it with your sorting algorithm of choice.

function sort(el)
{
    var direction = el.dataset.direction;
    var column = el.dataset.column;

    var table = getTableFromChild(el);
    var rows = table.rows;

    for (var x = 0; x < rows.length; x++)
    {
        var changes = false;

        for (var i = 1; i < rows.length-1; i++)
        {
            var row = rows[i];
            var otherrow = rows[i + 1];
            var parent = row.parentNode;

            var value = rows[i].cells[column].innerHTML;
            var next = rows[i + 1].cells[column].innerHTML;

            if (value > next && direction == 'asc') {
                changes = true;
                parent.insertBefore(otherrow, row);
            }

            else if (value < next && direction == 'desc')
            {
                changes = true;
                parent.insertBefore(otherrow, row);
            }
        }

        if (changes == false)
            break;
    }

    el.dataset.direction = direction == 'asc' ? 'desc' : 'asc';
     el.innerHTML = el.dataset.name + (direction == 'asc' ? ' ?' : ' ?');
}

Just a quick breakdown of the entire thing. We first retrieve the parent table that the clicked header cell belongs to and then we will traverse through each of the rows in that table. That's when the magic of the bubble sort kicks in. I'll sequentially compare values until the end of the table rows collection. And I will do so until there are no more rows to sort.

Once the rows have been sorted, I will set the new sorting-direction of the header to either ascending or descending, depending on the previous value and I will update dataset direction value to the new direction.

The above sorting function makes use of the following helper function. Because I want this sorting functionality to be as generic as possible across any number of tables on a page, I need to be able to return the parent table element that will be sorted based on the header column clicked, and the following function will return just that.

function getTableFromChild(child)
{
    var element = child;
    var type = '';

    while (type.toLowerCase() != 'table')
    {
        element = element.parentNode;

        if (element != null)
        {
            type = element.nodeName;
        }

        else
        {
            break;
        }
    }

    return element;
}

Note that sorting columns with mixed data types will result in random ordering more than likely. So be sure to add this functionality to tables with static data.

You can see the full running demo over on Codepen.io.

Walter G. author of blog post
Walter Guevara is a Computer Scientist, software engineer, startup founder and previous mentor for a coding bootcamp. He has been creating software for the past 20 years.

Get the latest programming news directly in your inbox!

Have a question on this article?

You can leave me a question on this particular article (or any other really).

Ask a question

Community Comments

No comments posted yet
Ad Unit

Current Poll

Total Votes:
Q:
Submit

Add a comment