Sort Table
Sort an HTML/CSS table using Plain Old Vanilla Javascript
by Stephen Irving
HTML
<div class="tile ttzc-tile">
<header class="tile-header">
<h2 class="tile-header-title">Top Ten ZIP Codes</h2>
</header>
<div class="ttzc-table-wrap">
<table class="ttzc-table" id="ttzc_table">
<thead class="ttzc-head">
<tr class="ttzc-row">
<th class="ttzc-header ttzc-zip" scope="col" title="Click to sort numerically">ZIP Code</th>
<th class="ttzc-header ttzc-city" scope="col" title="Click to sort alphabetically">City</th>
<th class="ttzc-header ttzc-state" scope="col" title="Click to sort alphabetically">State</th>
<th class="ttzc-header ttzc-pcentvis" scope="col" title="Click to sort numerically">Percent Visits</th>
<th class="ttzc-header ttzc-cumpcentvis" scope="col" title="Click to sort numerically">Cumulative<br>Percent<br>Visits</th>
<th class="ttzc-header ttzc-tothouse" scope="col" title="Click to sort numerically">Total<br>Households</th>
<th class="ttzc-header ttzc-totpop" scope="col" title="Click to sort numerically">Total<br>Population</th>
<th class="ttzc-header ttzc-avghouseinc" scope="col" title="Click to sort numerically">Avg<br>Household<br>Income</th>
<th class="ttzc-header ttzc-popgrow" scope="col" title="Click to sort numerically">Population<br>Growth</th>
</tr>
</thead>
<tbody class="ttzc-tbody">
<tr class="ttzc-row">
<td class="ttzc-cell ttzc-zip">01736</td>
<td class="ttzc-cell ttzc-city">Southwick</td>
<td class="ttzc-cell ttzc-state">MA</td>
<td class="ttzc-cell ttzc-pcentvis">32.8%</td>
<td class="ttzc-cell ttzc-cumpcentvis">32.8%</td>
<td class="ttzc-cell ttzc-tothouse">3,792</td>
<td class="ttzc-cell ttzc-totpop">9,629</td>
<td class="ttzc-cell ttzc-avghouseinc">$85,876</td>
<td class="ttzc-cell ttzc-popgrow">1.1%</td>
</tr>
<tr class="ttzc-row">
<td class="ttzc-cell ttzc-zip">01739</td>
<td class="ttzc-cell ttzc-city">Winchendon</td>
<td class="ttzc-cell...
SCSS
$fontFamily: 'Roboto',
'Helvetica Neue',
HelveticaNeue,
Helvetica-Neue,
Helvetica,
-apple-system,
BlinkMacSystemFont,
BBAlpha Sans,
'Segoe UI',
Arial,
'Noto Sans',
sans-serif;
$latoFamily: 'Lato',
Verdana,
Geneva,
-apple-system,
BlinkMacSystemFont,
sans-serif;
// Colors
$darkBlue : #2A3C68;
$blue : #4FA2D9;
$lightBlue : #8ED8F8;
$lightPurple: #EDEDF6;
$lightYellow: #FCE6A3;
$black : #000;
$offBlack : #414042;
$gray : #6D6E71;
$silver : #BCBEC0;
$offWhite : #F1F2F2;
$white : #FFF;
$brown : #A29490;
// PinPoint Colors
$darkRed : #A11D27;
$red : #D51F27;
$lightRed : lighten($red, 15%);
$almond : #ECD8C0;
$gutters: (
'lg': 1.6%,
'md': 1%,
'sm': .75%
);
$h-gutter-lg: 1.6%;
$h-gutter-md: 1%;
$h-gutter-sm: .75%;
$v-gutter: .75%;
// _helpers.scss
$rem-base: 16 !default;
@function strip-unit($num) {
@return $num / ($num * 0 + 1);
}
@function conv-to-rem($pixels) {
$rem-vals: ();
@each $val in $pixels {
$val-in-rems: strip-unit($val) / $rem-base * 1rem;
$rem-vals: append($rem-vals, $val-in-rems);
}
@if length($rem-vals) == 1 {
@return nth($rem-vals, 1);
}
@else {
@return $rem-vals;
}
}
@function conv-to-px($rems) {
$px-vals: ();
@each $val in $rems {
$val-in-pixels: strip-unit($val) * $rem-base * 1px;
$px-vals: append($px-vals, $val-in-pixels)
}
@if length($px-vals) == 1 {
@return nth($px-vals, 1);
}
@else {
@return $px-vals;
}
}
/// Replace `$search` with `$replace` in `$string`
/// @param {String} $string - Initial string
/// @param {String} $search - Substring to replace
/// @param {String} $replace ('') - New value
/// @return {String} - Updated string
@function str-replace($string, $search, $replace: '') {
...
JavaScript
/**
* @name sortTable
* @description Takes a given table and column, as well as whether or not the
* column has already been reversed, as input, and then sorts the table column
*
* @param {HTMLElement} table
* @param {HTMLElement} col
* @param {number} reverse - 1 for true 0 for false
* @todo Refactor logic for optimization & implement a datetime sorting solution
*/
function sortTable(table, col, reverse) {
const T_BODY = table.tBodies[0], // ignore `<thead>` and `<tfoot>` rows
IS_NUM = /^[0-9]*\.?[0-9]+$/;
let tRows = Array.prototype.slice.call(T_BODY.rows, 0); // Put rows into array
reverse = -((+reverse) || -1);
tRows = tRows.sort(function(a, b) { // Sort rows
let tempA = a.cells[col].textContent.trim(),
tempB = b.cells[col].textContent.trim();
if (tempA.slice(-1) === '%' || tempB.slice(-1) === '%') {
if (tempA.slice(-1) === '%') {
tempA = tempA.slice(0, tempA.length - 1);
}
if (tempB.slice(-1) === '%') {
tempB = tempB.slice(0, tempB.length - 1);
}
[tempA, tempB] = fixComparison(tempA, tempB);
}
else if (tempA.substr(0, 1) === '$' || tempB.substr(0, 1) === '$') {
if (tempA.substr(0, 1) === '$') {
tempA = tempA.slice(1, tempA.length);
}
if (tempB.substr(0, 1) === '$') {
tempB = tempB.slice(1, tempB.length);
}
[tempA, tempB] = fixComparison(tempA, tempB);
}
else if (IS_NUM.test(stripCommas(tempA)) || IS_NUM.test(stripCommas(tempB))) {
if (IS_NUM.test(stripCommas(tempA))) {
tempA = stripCommas(tempA) + '';
}
if (IS_NUM.test(stripCommas(tempB))) {
tempB = stripCommas(tempB) + '';
}
[tempA, tempB] = fixComparison(tempA, tempB);
}
return reverse * (tempA.localeCompare(tempB));
});
for (let i = 0; i < tRows.length; ++i) {
T_BODY.appendChild(tRows[i]); // append each row in order
}
}
/**
* @name makeSortable
* @description Makes a table sortable
*
...