208

I have a very simple HTML table with 4 columns:

Facility Name, Phone #, City, Specialty

I want the user to be able to sort by Facility Name and City only.

How can I code this using jQuery?

Penny Liu
  • 15,447
  • 5
  • 79
  • 98
tony noriega
  • 7,523
  • 17
  • 53
  • 72

15 Answers15

236

I came across this, and thought I'd throw in my 2 cents. Click on the column headers to sort ascending, and again to sort descending.

  • Works in Chrome, Firefox, Opera AND IE(8)
  • Only uses JQuery
  • Does alpha and numeric sorting - ascending and descending

$('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), 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() }
table, th, td {
    border: 1px solid black;
}
th {
    cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
    <tr><th>Country</th><th>Date</th><th>Size</th></tr>
    <tr><td>France</td><td>2001-01-01</td><td>25</td></tr>
    <tr><td><a href=#>spain</a></td><td>2005-05-05</td><td></td></tr>
    <tr><td>Lebanon</td><td>2002-02-02</td><td>-17</td></tr>
    <tr><td>Argentina</td><td>2005-04-04</td><td>100</td></tr>
    <tr><td>USA</td><td></td><td>-6</td></tr>
</table>

** Update: 2018

Nick Grealy
  • 24,216
  • 9
  • 104
  • 119
  • 1
    Just a warning re: line 4 - extending the dom element is considered bad practice - http://perfectionkills.com/whats-wrong-with-extending-the-dom/ – Nick Grealy Feb 24 '14 at 11:09
  • i think a nice update for this script would be this : var rows = table.find('tbody tr').toArray().sort(comparer($(this).index())) Especially for tables that have more than 1 row inside thead – Q_ro Mar 07 '14 at 22:21
  • @Q_ro, that sounds like a good addition, unfortunately not all tables have tbody (unless I'm mistaken?!). Nice example for others though! – Nick Grealy Mar 10 '14 at 05:52
  • @Nick G Thanks for providing the function above. Any input on how would I modify the function to do a "sub-sort" based on another column in the table for values that match using the initial sorted column? – Twhyler Mar 30 '14 at 21:59
  • @Twhyler, sounds simple enough but can you give me an example? I'm pretty sure if you just click in reverse order, you'll get your desired behaviour. e.g. Try clicking `ColumnB` column first, then `ColumnA`, to sort by `ColumnA, ColumnB`. -> http://jsfiddle.net/nickg1/Zhd2X/131/ – Nick Grealy Mar 31 '14 at 00:41
  • @nick-g How to modify your function so it doesn't die on (and properly sorts) negative numbers? – dylanmac Nov 14 '14 at 00:58
  • @dylanmac, you'll have to be more specific. Are you getting a js error? Is the functionality not working? What browser are you using? Is JavaScript enabled? The jsfiddle "live example" demonstrates sorting positive and negative numbers (and it's working as far as I can tell). Perhaps you can provide a jsfiddle or your own, illustrating the problem you're experiencing? – Nick Grealy Nov 14 '14 at 03:26
  • 11
    Fantastic! Just note that if you have links in the `td`s, e.g. `Test` the sorting regards the ` – Avatar Aug 25 '15 at 10:08
  • This is a great answer, though it does not work with `rowspan` attributes. Please see [my answer](http://stackoverflow.com/a/33179328/304209) to handle this. – Dennis Golomazov Oct 16 '15 at 20:51
  • How to rewrite the code, so it can work with jQuery 3.1.0? – user965748 Aug 01 '16 at 19:26
  • Pretty nice, unfortunately it doesn't sort Date Values (String values with date format) – Daniel Mar 30 '17 at 17:42
  • @Daniel - hmm... which date formats should it support? I imagine "yyyy-MM-dd" would work using the existing code. – Nick Grealy Mar 30 '17 at 22:27
  • @NickGrealy dd/MM/yyyy hh:mm:ss but I ended up using the plugin DataTables mentioned in an answer below – Daniel Mar 31 '17 at 04:32
  • Any idea on how to get it to sort by date? Not sure where to put it in – wubblyjuggly Aug 15 '17 at 13:40
  • 1
    @wubblyjuggly - what have you tried? Currently the table uses the cell data (e.g. html value) to determine the data type (i.e. number or string). Because date strings come in many formats, it's impractical to write a generic date detector/parser (you could rewrite `comparer(..)` if you knew exactly what format you wanted to support). In the meantime, if you use `yyyy-MM-dd`, "`string`" sorting will order the data for you. e.g. http://jsbin.com/pugedip/1 – Nick Grealy Aug 16 '17 at 00:31
  • 1
    This example worked perfectly for me where the chosen solution did not.The chosen answer didn't work for me; I'm not sure if it's because I'm using a thead/tbody or not (the jsfiddle, without these tags, did work). – RalphTheWonderLlama Nov 27 '17 at 19:37
  • @NickGrealy I have just proposed an edit to fix a sorting Bug but it was rejected. Your code is messing with the sort order when dealing with multiple identical values as in `checkbox` columns. You may want to remove `if (!this.asc){rows = rows.reverse()}` and hand a desc parameter to the comparer instead which is multiplying the result with `-1` in case of `desc == true`. – markus s May 09 '18 at 11:35
  • @markuss, thanks for highlighting that, I assume this is the rejected edit? https://stackoverflow.com/review/suggested-edits/19678136 . I like the idea of handling the sorting in the `comparer` function, but I don't understand how this is different from the existing code. Can you please put together a jsfiddle demonstrating the behaviour you describe (so I can see the issue, and test the fix)? – Nick Grealy May 09 '18 at 14:36
  • 1
    @NickGrealy You are right my suggestions in the comment where exactly the rejected edit. Compare https://jsfiddle.net/gn1vtcLq/2/ (my version) with https://jsfiddle.net/0a15ky9u/ (your version). Click on the "Sex" header several times to see the Ids or Names subsequently changing order in your version whereas keeping their inital order in my version. – markus s May 14 '18 at 10:00
  • @NickGrealy this method is illuminating, really very good!! Is it possible to add a column already ordered by default? – Gaetano Apr 09 '20 at 00:13
  • 1
    @Gaetano ... absolutely... pull out the click function and give it a name... replace the `$(this).index()` with a parameter, setup a static reference to the table you're targeting... and then call the function with the column index you want sorted (default) on document load. e.g. `$( document ).ready(function() { sortColumn(2); }` – Nick Grealy Apr 09 '20 at 01:16
  • @DSAQWEWWWWWWWWWWWWWWWWWWWWWW ... yeh, nah... those extra keystrokes slow me down! – Nick Grealy Dec 15 '20 at 03:25
  • To respond to the OP request to not include all columns, I added a class to the heading called sortable. then added the class to the listener. `` and `$('th.sortable').click...` – DanimalReks Feb 28 '21 at 20:09
  • @NickGrealy You saved my time..! – Gajen Dissanayake Jan 24 '22 at 20:16
  • If comparing dates as text (like January 25, 2022, February 10, 2022), it might not be correctly sorted. So, if has the sortValue attribute stated as Ymd, it will be correctly sorted: `function getCellValue(row, index) { var tdVal = $(row).children('td').eq(index); if (tdVal.attr("sortValue")) return tdVal.attr("sortValue"); else return tdVal.text(); }` – Nubian Aug 04 '22 at 19:28
  • I don't understand `this.asc` . . . which element contains asc/ desc property? I don't see it documented as something that TH has. I've added a symbol on the clicked header to indicate sort order, and it gets out of sync when switching columns (old column asc is true, new column will sort as desc but I need it to sort as asc. – Paul Gibson Mar 21 '23 at 07:37
  • @PaulGibson - it's not part of any spec, it's simply adding a field to the existing object, which upon reflection 10 years later, is probably a bad practice. – Nick Grealy Mar 21 '23 at 23:57
166

If you want to avoid all the bells and whistles then may I suggest this simple sortElements plugin. Usage:

var table = $('table');

$('.sortable th')
    .wrapInner('<span title="sort this column"/>')
    .each(function(){

        var th = $(this),
            thIndex = th.index(),
            inverse = false;

        th.click(function(){

            table.find('td').filter(function(){

                return $(this).index() === thIndex;

            }).sortElements(function(a, b){

                if( $.text([a]) == $.text([b]) )
                    return 0;

                return $.text([a]) > $.text([b]) ?
                    inverse ? -1 : 1
                    : inverse ? 1 : -1;

            }, function(){

                // parentNode is the element we want to move
                return this.parentNode; 

            });

            inverse = !inverse;

        });

    });

And a demo. (click the "city" and "facility" column-headers to sort)

Marc Barbeau
  • 826
  • 10
  • 21
James
  • 109,676
  • 31
  • 162
  • 175
  • 6
    The demo was broken because the location of the plugin had changed. I have forked a [fixed jsfiddle to demo sortElements](http://jsfiddle.net/gFzCk/) which at least seems to work for me :) @999 perhaps you could update your answer to link to the fixed demo? – Jake Worrell Dec 05 '11 at 15:56
  • 2
    What if you have multiple tables on a page? I forked the jsfiddle http://jsfiddle.net/CM8bT/ – Marc Mar 23 '12 at 02:29
  • 1
    I'm getting this error `Error: illegal character` the html is not exactly the same, I also have thead and tboy, can you help me with this please? – pahnin Jul 12 '12 at 13:00
  • The demo doesn't support multiple sortable tables, wich was easily fixed. However, I'm having performance issues with a table of 7 columns and 275 rows. I suspect that the problem is looping through all cells. Isn't there a way to just loop cells in that column? – Stefan Bergfeldt Aug 07 '12 at 09:29
  • 2
    The above function will not work in case of case sensitivity. In this plugin 'a' != 'A'. It would work if converting the text to uppercase or lower case and then check & compare. Eg: Instead of `$.text([a]) == $.text([b])` using `$.text([a]).toUpperCase() == $.text([b]).toUpperCase()` will fix it. – nbk Dec 03 '12 at 08:26
  • 1
    Pretty soon you will find that sorting is not a table-specific problem at all - when you do, here's [my teeny-tiny jQuery plug-in](http://jsfiddle.net/H2mrp/) which will sort lists, tables, divs or anything else, in ascending or descending order. I have also used it to sort by different data-types like currency or year - just provide your own function that returns the data to sort by. (I like to keep those functions separate, and give them meaningful names, to build my own little library of "ways to sort things" that are specific to the solution I'm building.) – mindplay.dk Jan 06 '14 at 16:31
  • @JakeWorrell I'm afraid it's broken again, I don't know why, but it's not working for me on Chrome/Linux. – Lucio Crusca May 12 '19 at 17:17
  • 1
    How can i make this work with letters and numbers as well? Right now on this solution 8 > 777 and 777 > 6666 because the first number is bigger. Thanks – EPurpl3 Apr 08 '20 at 19:49
  • there a bug on sort number, it does not take teh correct sort ! – Imen Jul 29 '20 at 09:08
42

By far, the easiest one I've used is: http://datatables.net/

Amazingly simple...just make sure if you go the DOM replacement route (IE, building a table and letting DataTables reformat it) then make sure to format your table with <thead> and <tbody> or it won't work. That's about the only gotcha.

There's also support for AJAX, etc. As with all really good pieces of code, it's also VERY easy to turn it all off. You'd be suprised what you might use, though. I started with a "bare" DataTable that only sorted one field and then realized that some of the features were really relevant to what I'm doing. Clients LOVE the new features.

Bonus points to DataTables for full ThemeRoller support....

I've also had ok luck with tablesorter, but it's not nearly as easy, not quite as well documented, and has only ok features.

bpeterson76
  • 12,918
  • 5
  • 49
  • 82
22

We just started using this slick tool: https://plugins.jquery.com/tablesorter/

There is a video on its use at: http://www.highoncoding.com/Articles/695_Sorting_GridView_Using_JQuery_TableSorter_Plug_in.aspx

    $('#tableRoster').tablesorter({
        headers: {
            0: { sorter: false },
            4: { sorter: false }
        }
    });

With a simple table

<table id="tableRoster">
        <thead> 
                  <tr>
                    <th><input type="checkbox" class="rCheckBox" value="all" id="rAll" ></th>
                    <th>User</th>
                    <th>Verified</th>
                    <th>Recently Accessed</th>
                    <th>&nbsp;</th>
                  </tr>
        </thead>
Ravi Ram
  • 24,078
  • 21
  • 82
  • 113
14

My answer would be "be careful". A lot of jQuery table-sorting add-ons only sort what you pass to the browser. In many cases, you have to keep in mind that tables are dynamic sets of data, and could potentially contain zillions of lines of data.

You do mention that you only have 4 columns, but much more importantly, you don't mention how many rows we're talking about here.

If you pass 5000 lines to the browser from the database, knowing that the actual database-table contains 100,000 rows, my question is: what's the point in making the table sortable? In order to do a proper sort, you'd have to send the query back to the database, and let the database (a tool actually designed to sort data) do the sorting for you.

In direct answer to your question though, the best sorting add-on I've come across is Ingrid. There are many reasons that I don't like this add-on ("unnecessary bells and whistles..." as you call it), but one of it's best features in terms of sort, is that it uses ajax, and doesn't assume that you've already passed it all the data before it does its sort.

I recognise that this answer is probably overkill (and over 2 years late) for your requirements, but I do get annoyed when developers in my field overlook this point. So I hope someone else picks up on it.

I feel better now.

cartbeforehorse
  • 3,045
  • 1
  • 34
  • 49
11

This is a nice way of sorting a table:

$(document).ready(function () {
                $('th').each(function (col) {
                    $(this).hover(
                            function () {
                                $(this).addClass('focus');
                            },
                            function () {
                                $(this).removeClass('focus');
                            }
                    );
                    $(this).click(function () {
                        if ($(this).is('.asc')) {
                            $(this).removeClass('asc');
                            $(this).addClass('desc selected');
                            sortOrder = -1;
                        } else {
                            $(this).addClass('asc selected');
                            $(this).removeClass('desc');
                            sortOrder = 1;
                        }
                        $(this).siblings().removeClass('asc selected');
                        $(this).siblings().removeClass('desc selected');
                        var arrData = $('table').find('tbody >tr:has(td)').get();
                        arrData.sort(function (a, b) {
                            var val1 = $(a).children('td').eq(col).text().toUpperCase();
                            var val2 = $(b).children('td').eq(col).text().toUpperCase();
                            if ($.isNumeric(val1) && $.isNumeric(val2))
                                return sortOrder == 1 ? val1 - val2 : val2 - val1;
                            else
                                return (val1 < val2) ? -sortOrder : (val1 > val2) ? sortOrder : 0;
                        });
                        $.each(arrData, function (index, row) {
                            $('tbody').append(row);
                        });
                    });
                });
            });
            table, th, td {
            border: 1px solid black;
        }
        th {
            cursor: pointer;
        }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
        <tr><th>id</th><th>name</th><th>age</th></tr>
        <tr><td>1</td><td>Julian</td><td>31</td></tr>
        <tr><td>2</td><td>Bert</td><td>12</td></tr>
        <tr><td>3</td><td>Xavier</td><td>25</td></tr>
        <tr><td>4</td><td>Mindy</td><td>32</td></tr>
        <tr><td>5</td><td>David</td><td>40</td></tr>
    </table>

The fiddle can be found here:
https://jsfiddle.net/e3s84Luw/

The explanation can be found here: https://www.learningjquery.com/2017/03/how-to-sort-html-table-using-jquery-code

Julian
  • 4,396
  • 5
  • 39
  • 51
  • This very simple tablesorter works very well with dynamic table data (php + MariaDB). Thank you! – yello Jul 17 '20 at 07:50
6

I love this accepted answer, however, rarely do you get requirements to sort html and not have to add icons indicating the sorting direction. I took the accept answer's usage example and fixed that quickly by simply adding bootstrap to my project, and adding the following code:

<div></div>

inside each <th> so that you have a place to set the icon.

setIcon(this, inverse);

from the accepted answer's Usage, below the line:

th.click(function () {

and by adding the setIcon method:

function setIcon(element, inverse) {

        var iconSpan = $(element).find('div');

        if (inverse == false) {
            $(iconSpan).removeClass();
            $(iconSpan).addClass('icon-white icon-arrow-up');
        } else {
            $(iconSpan).removeClass();
            $(iconSpan).addClass('icon-white icon-arrow-down');
        }
        $(element).siblings().find('div').removeClass();
    }

Here is a demo. --You need to either run the demo in Firefox or IE, or disable Chrome's MIME-type checking for the demo to work. It depends on the sortElements Plugin, linked by the accepted answer, as an external resource. Just a heads up!

4

This one does not hang up the browser/s, easy configurable further:

var table = $('table');

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

function compare(idx) {
    return function(a, b) {
       var A = tableCell(a, idx), B = tableCell(b, idx)
       return $.isNumeric(A) && $.isNumeric(B) ? 
          A - B : A.toString().localeCompare(B)
    }
}

function tableCell(tr, index){ 
    return $(tr).children('td').eq(index).text() 
}
rapttor
  • 396
  • 3
  • 7
  • 1
    This seems the best solution. It does not require a plugin. The first line you can delete, then in your document ready paste the $('th.sortable').click( ... ) block. Give table headers the sortable class and you are done. – pizzamonster Jun 08 '19 at 15:09
  • works fine, thanks, but how to exclude footer in the table from sort function? – Hussein mahyoub Dec 25 '22 at 01:03
4

Here's a chart that may be helpful deciding which to use: http://blog.sematext.com/2011/09/19/top-javascript-dynamic-table-libraries/

SeanDowney
  • 17,368
  • 20
  • 81
  • 90
3

@Nick Grealy's answer is great, but it does not take into account possible rowspan attributes of the table header cells (and probably the other answers don't do it either). Here is an improvement of the @Nick Grealy's answer which fixes that. Based on this answer too (thanks @Andrew Orlov).

I've also replaced the $.isNumeric function with a custom one (thanks @zad) to make it work with older jQuery versions.

To activate it, add class="sortable" to the <table> tag.

$(document).ready(function() {

    $('table.sortable th').click(function(){
        var table = $(this).parents('table').eq(0);
        var column_index = get_column_index(this);
        var rows = table.find('tbody tr').toArray().sort(comparer(column_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), valB = getCellValue(b, index);
        return isNumber(valA) && isNumber(valB) ? valA - valB : valA.localeCompare(valB);
    }
}
function getCellValue(row, index){ return $(row).children('td').eq(index).html() };

function isNumber(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

function get_column_index(element) {
    var clickedEl = $(element);
    var myCol = clickedEl.closest("th").index();
    var myRow = clickedEl.closest("tr").index();
    var rowspans = $("th[rowspan]");
    rowspans.each(function () {
        var rs = $(this);
        var rsIndex = rs.closest("tr").index();
        var rsQuantity = parseInt(rs.attr("rowspan"));
        if (myRow > rsIndex && myRow <= rsIndex + rsQuantity - 1) {
            myCol++;
        }
    });
    // alert('Row: ' + myRow + ', Column: ' + myCol);
    return myCol;
};
Community
  • 1
  • 1
Dennis Golomazov
  • 16,269
  • 5
  • 73
  • 81
2

To the response of James I will only change the sorting function to make it more universal. This way it will sort text alphabetical and numbers like numbers.

if( $.text([a]) == $.text([b]) )
    return 0;
if(isNaN($.text([a])) && isNaN($.text([b]))){
    return $.text([a]) > $.text([b]) ? 
       inverse ? -1 : 1
       : inverse ? 1 : -1;
}
else{
    return parseInt($.text([a])) > parseInt($.text([b])) ? 
      inverse ? -1 : 1
      : inverse ? 1 : -1;
}
Kaloyan Iliev
  • 147
  • 1
  • 2
  • 10
2

You can use a jQuery plugin (breedjs) that provides sort, filter and pagination:

HTML:

<table>
  <thead>
    <tr>
      <th sort='name'>Name</th>
      <th>Phone</th>
      <th sort='city'>City</th>
      <th>Speciality</th>
    </tr>
  </thead>
  <tbody>
    <tr b-scope="people" b-loop="person in people">
      <td b-sort="name">{{person.name}}</td>
      <td>{{person.phone}}</td>
      <td b-sort="city">{{person.city}}</td>
      <td>{{person.speciality}}</td>
    </tr>
  </tbody>
</table>

JS:

$(function(){
  var data = {
    people: [
      {name: 'c', phone: 123, city: 'b', speciality: 'a'},
      {name: 'b', phone: 345, city: 'a', speciality: 'c'},
      {name: 'a', phone: 234, city: 'c', speciality: 'b'},
    ]
  };
  breed.run({
    scope: 'people',
    input: data
  });
  $("th[sort]").click(function(){
    breed.sort({
      scope: 'people',
      selector: $(this).attr('sort')
    });
  });
});

Working example on fiddle

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
João Paulo
  • 6,300
  • 4
  • 51
  • 80
2

I ended up using Nick's answer (the most popular but not accepted) https://stackoverflow.com/a/19947532/5271220

and combined it with the https://stackoverflow.com/a/16819442/5271220 but didn't want to add icons or fontawesome to the project. The CSS styles for sort-column-asc/desc I did color, padding, rounded border.

I also modified it to go by class rather than by any so we could control which ones are sortable. This could also come in handy later if there are two tables although more modifications would need to be done for that.

body:

 html += "<thead>\n";
    html += "<th></th>\n";
    html += "<th class=\"sort-header\">Name <span></span></i></th>\n";
    html += "<th class=\"sort-header\">Status <span></span></th>\n";
    html += "<th class=\"sort-header\">Comments <span></span></th>\n";
    html += "<th class=\"sort-header\">Location <span></span></th>\n";
    html += "<th nowrap class=\"sort-header\">Est. return <span></span></th>\n";
    html += "</thead>\n";
    html += "<tbody>\n"; ...

... further down the body

$("body").on("click", ".sort-header", function (e) {
    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]) }

    setIcon(e.target, this.asc);
});

functions:

function comparer(index) {
        return function (a, b) {
            var valA = getCellValue(a, index), 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()
    }

    function setIcon(element, inverse) {

        var iconSpan = $(element).find('span');

        if (inverse == true) {
            $(iconSpan).removeClass();
            $(iconSpan).addClass('sort-column-asc');
            $(iconSpan)[0].innerHTML = " &#8593 " // arrow up
        } else {
            $(iconSpan).removeClass();
            $(iconSpan).addClass('sort-column-desc');
            $(iconSpan)[0].innerHTML = " &#8595 " // arrow down 
        }

        $(element).siblings().find('span').each(function (i, obj) {
            $(obj).removeClass();
            obj.innerHTML = "";
        });
    }
blind Skwirl
  • 321
  • 3
  • 6
  • The iconSpan rows can be merged into one, for example: `$(iconSpan).removeClass().addClass('sort-column-desc').html(" ↓ ");` – Nubian Aug 04 '22 at 19:25
1

Another approach to sort HTML table. (based on W3.JS HTML Sort)

/* Facility Name */
$('#bioTable th:eq(0)').addClass("control-label pointer");
/* Phone # */
$('#bioTable th:eq(1)').addClass("not-allowed");
/* City */
$('#bioTable th:eq(2)').addClass("control-label pointer");
/* Specialty */
$('#bioTable th:eq(3)').addClass("not-allowed");


var collection = [{
  "FacilityName": "MinION",
  "Phone": "999-8888",
  "City": "France",
  "Specialty": "Genetic Prediction"
}, {
  "FacilityName": "GridION X5",
  "Phone": "999-8812",
  "City": "Singapore",
  "Specialty": "DNA Assembly"
}, {
  "FacilityName": "PromethION",
  "Phone": "929-8888",
  "City": "San Francisco",
  "Specialty": "DNA Testing"
}, {
  "FacilityName": "iSeq 100 System",
  "Phone": "999-8008",
  "City": "Christchurch",
  "Specialty": "gDNA-mRNA sequencing"
}]

$tbody = $("#bioTable").append('<tbody></tbody>');

for (var i = 0; i < collection.length; i++) {
  $tbody = $tbody.append('<tr class="item"><td>' + collection[i]["FacilityName"] + '</td><td>' + collection[i]["Phone"] + '</td><td>' + collection[i]["City"] + '</td><td>' + collection[i]["Specialty"] + '</td></tr>');
}
.control-label:after {
  content: "*";
  color: red;
}

.pointer {
  cursor: pointer;
}

.not-allowed {
  cursor: not-allowed;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://www.w3schools.com/lib/w3.js"></script>
<link href="https://www.w3schools.com/w3css/4/w3.css" rel="stylesheet" />
<p>Click the <strong>table headers</strong> to sort the table accordingly:</p>

<table id="bioTable" class="w3-table-all">
  <thead>
    <tr>
      <th onclick="w3.sortHTML('#bioTable', '.item', 'td:nth-child(1)')">Facility Name</th>
      <th>Phone #</th>
      <th onclick="w3.sortHTML('#bioTable', '.item', 'td:nth-child(3)')">City</th>
      <th>Specialty</th>
    </tr>
  </thead>
</table>
Penny Liu
  • 15,447
  • 5
  • 79
  • 98
-4

My vote! jquery.sortElements.js and simple jquery
Very simple, very easy, thanks nandhp...

            $('th').live('click', function(){

            var th = $(this), thIndex = th.index(), var table = $(this).parent().parent();

                switch($(this).attr('inverse')){
                case 'false': inverse = true; break;
                case 'true:': inverse = false; break;
                default: inverse = false; break;
                }
            th.attr('inverse',inverse)

            table.find('td').filter(function(){
                return $(this).index() === thIndex;
            }).sortElements(function(a, b){
                return $.text([a]) > $.text([b]) ?
                    inverse ? -1 : 1
                    : inverse ? 1 : -1;
            }, function(){
                // parentNode is the element we want to move
                return this.parentNode; 
            });
            inverse = !inverse;     
            });

Dei uma melhorada do código
One cod better! Function for All tables in all Th in all time... Look it!
DEMO

j0k
  • 22,600
  • 28
  • 79
  • 90