Filter/sort table demo

Filter/sort table

by mrjordy

HTML

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tinysort/2.2.2/tinysort.min.js"></script>
<ul class="tabs" role="toolbar" aria-label="backpack sorting options" aria-controls="backpackGrid">
    <li class="selected"> <a class="viewAll" aria-selected="true" data-filter="" href="javascript: void(0);">View All</a>

    </li>
    <li> <a aria-selected="false" data-filter="group1" href="javascript: void(0);">group 1</a>

    </li>
    <li> <a aria-selected="false" data-filter="group2" href="javascript: void(0);">group 2</a>

    </li>
    <li> <a aria-selected="false" data-filter="group3" href="javascript: void(0);">group 3</a>

    </li>
</ul>

<table id="backpackGrid" summary="Filterable & sortable backpack selection table">
    <caption id="backpackCaption" role="status" aria-live="polite">Filterable & sortable backpack selection table (this needs to be offscreen - avoid display:none)</caption>
    <thead>
        <tr>
            <th role="columnheader" aria-sort="none" scope="col"><a>product</a>

            </th>
            <th role="columnheader" aria-sort="none" scope="col"><a>price</a>

            </th>
            <th role="columnheader" aria-sort="none" scope="col"><a>capacity</a>

            </th>
            <th role="columnheader" aria-sort="none" scope="col"><a>monogrammable</a>

            </th>
        </tr>
    </thead>
    <tbody>
        <tr class="group1" scope="row">
            <td role="rowheader">Junior Original</td>
            <td>$39</td>
            <td>6 liters</td>
            <td class="monogram-false">not monogrammable</td>
        </tr>
        <tr class="group2" scope="row">
            <td role="rowheader">Bean's Pal Packs</td>
            <td>$45</td>
            <td>9 liters</td>
            <td class="monogram-true">monogrammable</td>
        </tr>
        <tr class="group1 group3" scope="row">
            <td...

CSS

td.monogram-true, td.monogram-false {
    text-indent: -9999px;
}
td, th {
    border: 1px solid #e9e9e9;
    padding: 10px;
    background: #fff;
}
td.monogram-true {
    background: url('http://vignette3.wikia.nocookie.net/roblox/images/5/57/Very-Basic-Checkmark-icon.png') center center no-repeat;
    background-size: contain;
    width: 10px;
    height: 10px;
}

.hidden {
    display: none;
}

#backpackGrid th {
    background: #d9d9d9  url('http://www.ssa.gov/accessibility/bpl/bps/tables/basic/example/css/img/bg.gif') no-repeat right;
    text-align: left;
    min-width: 130px;
}

#backpackGrid th.asc {
    background-image: url('http://www.ssa.gov/accessibility/bpl/bps/tables/basic/example/css/img/asc.gif');
}

#backpackGrid th.desc {
    background-image: url('http://www.ssa.gov/accessibility/bpl/bps/tables/basic/example/css/img/desc.gif');
}

.tabs {
    padding-bottom: 20px;
}
.tabs li {
    display: inline;
    padding: 10px;
    border: 1px solid #e9e9e9;
    margin: 5px;
}

.tabs li.selected {
    background: gold;
}

JavaScript

//sort table w/ tinysort - pulled from: http://tinysort.sjeiti.com/#sorting-tables

var table = document.getElementById('backpackGrid'),
    tableHead = table.querySelector('thead'),
    tableHeaders = tableHead.querySelectorAll('th'),
    tableBody = table.querySelector('tbody');


tableHead.addEventListener('click', function (e) {
    var tableHeader = e.target,
        textContent = tableHeader.textContent,
        tableHeaderIndex, isAscending, order;
    while (tableHeader.nodeName !== 'TH') {
        tableHeader = tableHeader.parentNode;
    }
    tableHeaderIndex = Array.prototype.indexOf.call(tableHeaders, tableHeader);
    isAscending = tableHeader.getAttribute('data-order') === 'asc';
    order = isAscending ? 'desc' : 'asc';

    //reset other columns
    $('#backpackGrid').find('th').removeClass('asc desc').attr('data-order','none').attr('aria-sort','none');


    //set order on clicked header
    tableHeader.setAttribute('data-order', order);

    /* accessibility */
    //set aria sort attr
    tableHeader.setAttribute('aria-sort', order);
    tableHeader.setAttribute("class", order);
    // build aria-live message
    var sortOrder;
    if (isAscending) {
        sortOrder = "Ascending order";
    } else {
        sortOrder = "Descending order";
    }
    $('#backpackCaption').empty().append("Backpacks sorted by " + textContent + ": " + sortOrder);
    /* end accessibility */
    
    // call tinysort
    tinysort(
    tableBody.querySelectorAll('tr'), {
        selector: 'td:nth-child(' + (tableHeaderIndex + 1) + ')',
        order: order
    });
});



// filter table & update accessible table caption
$('.tabs li a').on('click', function(){
    var $this = $(this),
        $group = $this.attr('data-filter');
    if(!$this.hasClass('viewAll')){
        $('#backpackGrid').find('.' + $group).addClass('hidden');
        $('#backpackGrid').find('tr').not('.' + $group).removeClass('hidden');
        //update table caption
       ...