Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting multiple html tables with multiple sorts

I have several html tables on my page and I want to be able to sort them based on the value of one of their cell values. Here is an example of my tables

<div id="tables">
    <table class="sortable">
        <tr>
            <td>Comic Book Name</td>
            <td id="comic">Batman</td>
        </tr>
        <tr>
            <td>Main Character</td >
            <td ="character">Bruce Wayne</td>
        </tr>
        <tr>
            <td>Hero Name</td>
            <td id="hero">Batman</td>
        </tr>
        <tr>
            <td>Published</td>
            <td id="publish">05/01/1940</td>
        </tr>
    </table>
    <table class="sortable">
        <tr>
            <td>Comic Book Name</td>
            <td id="comic">Green Arrow</td>
        </tr>
        <tr>
            <td>Main Character</td >
            <td ="character">Oliver Queen</td>
        </tr>
        <tr>
            <td>Hero Name</td>
            <td id="hero">Green Arrow</td>
        </tr>
        <tr>
            <td>Published</td>
            <td id="publish">11/01/1941</td>
        </tr>
    </table>
</div>

I am providing the following drop down to allow users to filter.

<select id="OrderBy">
 <option selected="selected" value="comic">Comic Name</option>
 <option value="character">Character Name</option>
 <option value="hero">Hero Name</option>
 <option value="publish">Earliest Publish Date</option>
</select>

My hopes here are to sort the tables alphabetically by Comic book name when they choose Comic Name, alphabetically by Character Name when they select character name etc. etc.

Here is the javascript/jquery I have come up with so far. I'm sure this could be done better but I'm new to Javascript and Jquery.

$('#OrderBy').on('change', function () {
    _order = $('#OrderBy').val();
    switch (_order) {
        case "comic":
            $('#sortable').sort(function () {

            });
            break;
        case "character":
            $('#sortable').children().sort(function (a, b) {
            });
            break;
        case "publish":
            $('#sortable').sort(function () {
            });
            break;
        case "publish":
            $('#sortable').sort(function () {
                if ($(b).children().find('#Hours').text() - $(a).children().find('#publish').text() <= 0) {
                    return $(a) - $(b);
                }
                return $(b) - $(a);
            });
            break;
    }
});

Everywhere I look someone suggests Sorttables or tableSorter but I've only seen how they would work for a single table whose rows are being sorted. I know what everyone is thinking at this point, don't use tables this way. My problem is there is already a bunch of jquery and javascript supporting the tables and I'm not experienced enough in the languages to re-write all of that.

I like the idea of pushing everything onto a stack as described here but I always generated an error about how my array/stack was not defined.

like image 929
TheDude Avatar asked Nov 10 '22 04:11

TheDude


1 Answers

First, you should not put several times the same id, but use classes instead:

<div id="tables">

    <table class="sortable">
        <tr>
            <td>Comic Book Name</td>
            <td class="comic">Green Arrow</td>
        </tr>
        <tr>
            <td>Main Character</td >
            <td class="character">Oliver Queen</td>
        </tr>
        <tr>
            <td>Hero Name</td>
            <td class="hero">Green Arrow</td>
        </tr>
        <tr>
            <td>Published</td>
            <td class="publish">11/01/1941</td>
        </tr>
    </table>
    <table class="sortable">
        <tr>
            <td>Comic Book Name</td>
            <td class="comic">Batman</td>
        </tr>
        <tr>
            <td>Main Character</td >
            <td class="character">Bruce Wayne</td>
        </tr>
        <tr>
            <td>Hero Name</td>
            <td class="hero">Batman</td>
        </tr>
        <tr>
            <td>Published</td>
            <td class="publish">05/01/1940</td>
        </tr>
    </table>
</div>

For your problem, I would use the native Array.prototype.sort method

var tables = [];
var $tables = $("table.sortable");
var container = $("#tables");
// this is the only specific case, as the date does not start by the year
// it will be used to sort by publish date
function sortByDate(a, b) {
    return new Date(a.publish).getTime() - new Date(b.publish).getTime();
}

function sortTables(order) {
    var sort;
    if (order === "publish") {
        tables = tables.sort(sortByDate);
    } else {
        tables = tables.sort(function(a, b) {
            return a[order] < b[order] ? -1 : 1;
        });
    }
    tables.forEach(function(data,i) {
        tables[i].$el.detach()
        container.append(tables[i].el);
    });
}

function init() {
    //populate the tables array that will be sorted
    $tables.each(function(i, val) {
        var $this = $(this);
        tables.push({
            $el: $this,
            el: this,
            comic: $this.find(".comic").text(),
            character: $this.find(".character").text(),
            hero: $this.find(".hero").text(),
            publish: $this.find(".publish").text()
        });
    });
    $("#OrderBy").on("change", function(event) {
        sortTables(event.currentTarget.value);
    });
    //by default sort by Hero
    sortTables("hero");
}
init();
like image 153
n00dl3 Avatar answered Nov 14 '22 23:11

n00dl3