159 lines
5.1 KiB
JavaScript
159 lines
5.1 KiB
JavaScript
|
var addSorting = (function () {
|
||
|
"use strict";
|
||
|
var cols,
|
||
|
currentSort = {
|
||
|
index: 0,
|
||
|
desc: false
|
||
|
};
|
||
|
|
||
|
// returns the summary table element
|
||
|
function getTable() { return document.querySelector('.coverage-summary'); }
|
||
|
// returns the thead element of the summary table
|
||
|
function getTableHeader() { return getTable().querySelector('thead tr'); }
|
||
|
// returns the tbody element of the summary table
|
||
|
function getTableBody() { return getTable().querySelector('tbody'); }
|
||
|
// returns the th element for nth column
|
||
|
function getNthColumn(n) { return getTableHeader().querySelectorAll('th')[n]; }
|
||
|
|
||
|
// loads all columns
|
||
|
function loadColumns() {
|
||
|
var colNodes = getTableHeader().querySelectorAll('th'),
|
||
|
colNode,
|
||
|
cols = [],
|
||
|
col,
|
||
|
i;
|
||
|
|
||
|
for (i = 0; i < colNodes.length; i += 1) {
|
||
|
colNode = colNodes[i];
|
||
|
col = {
|
||
|
key: colNode.getAttribute('data-col'),
|
||
|
sortable: !colNode.getAttribute('data-nosort'),
|
||
|
type: colNode.getAttribute('data-type') || 'string'
|
||
|
};
|
||
|
cols.push(col);
|
||
|
if (col.sortable) {
|
||
|
col.defaultDescSort = col.type === 'number';
|
||
|
colNode.innerHTML = colNode.innerHTML + '<span class="sorter"></span>';
|
||
|
}
|
||
|
}
|
||
|
return cols;
|
||
|
}
|
||
|
// attaches a data attribute to every tr element with an object
|
||
|
// of data values keyed by column name
|
||
|
function loadRowData(tableRow) {
|
||
|
var tableCols = tableRow.querySelectorAll('td'),
|
||
|
colNode,
|
||
|
col,
|
||
|
data = {},
|
||
|
i,
|
||
|
val;
|
||
|
for (i = 0; i < tableCols.length; i += 1) {
|
||
|
colNode = tableCols[i];
|
||
|
col = cols[i];
|
||
|
val = colNode.getAttribute('data-value');
|
||
|
if (col.type === 'number') {
|
||
|
val = Number(val);
|
||
|
}
|
||
|
data[col.key] = val;
|
||
|
}
|
||
|
return data;
|
||
|
}
|
||
|
// loads all row data
|
||
|
function loadData() {
|
||
|
var rows = getTableBody().querySelectorAll('tr'),
|
||
|
i;
|
||
|
|
||
|
for (i = 0; i < rows.length; i += 1) {
|
||
|
rows[i].data = loadRowData(rows[i]);
|
||
|
}
|
||
|
}
|
||
|
// sorts the table using the data for the ith column
|
||
|
function sortByIndex(index, desc) {
|
||
|
var key = cols[index].key,
|
||
|
sorter = function (a, b) {
|
||
|
a = a.data[key];
|
||
|
b = b.data[key];
|
||
|
return a < b ? -1 : a > b ? 1 : 0;
|
||
|
},
|
||
|
finalSorter = sorter,
|
||
|
tableBody = document.querySelector('.coverage-summary tbody'),
|
||
|
rowNodes = tableBody.querySelectorAll('tr'),
|
||
|
rows = [],
|
||
|
i;
|
||
|
|
||
|
if (desc) {
|
||
|
finalSorter = function (a, b) {
|
||
|
return -1 * sorter(a, b);
|
||
|
};
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < rowNodes.length; i += 1) {
|
||
|
rows.push(rowNodes[i]);
|
||
|
tableBody.removeChild(rowNodes[i]);
|
||
|
}
|
||
|
|
||
|
rows.sort(finalSorter);
|
||
|
|
||
|
for (i = 0; i < rows.length; i += 1) {
|
||
|
tableBody.appendChild(rows[i]);
|
||
|
}
|
||
|
}
|
||
|
// removes sort indicators for current column being sorted
|
||
|
function removeSortIndicators() {
|
||
|
var col = getNthColumn(currentSort.index),
|
||
|
cls = col.className;
|
||
|
|
||
|
cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, '');
|
||
|
col.className = cls;
|
||
|
}
|
||
|
// adds sort indicators for current column being sorted
|
||
|
function addSortIndicators() {
|
||
|
getNthColumn(currentSort.index).className += currentSort.desc ? ' sorted-desc' : ' sorted';
|
||
|
}
|
||
|
// adds event listeners for all sorter widgets
|
||
|
function enableUI() {
|
||
|
var i,
|
||
|
el,
|
||
|
ithSorter = function ithSorter(i) {
|
||
|
var col = cols[i];
|
||
|
|
||
|
return function () {
|
||
|
var desc = col.defaultDescSort;
|
||
|
|
||
|
if (currentSort.index === i) {
|
||
|
desc = !currentSort.desc;
|
||
|
}
|
||
|
sortByIndex(i, desc);
|
||
|
removeSortIndicators();
|
||
|
currentSort.index = i;
|
||
|
currentSort.desc = desc;
|
||
|
addSortIndicators();
|
||
|
};
|
||
|
};
|
||
|
for (i =0 ; i < cols.length; i += 1) {
|
||
|
if (cols[i].sortable) {
|
||
|
// add the click event handler on the th so users
|
||
|
// dont have to click on those tiny arrows
|
||
|
el = getNthColumn(i).querySelector('.sorter').parentElement;
|
||
|
if (el.addEventListener) {
|
||
|
el.addEventListener('click', ithSorter(i));
|
||
|
} else {
|
||
|
el.attachEvent('onclick', ithSorter(i));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
// adds sorting functionality to the UI
|
||
|
return function () {
|
||
|
if (!getTable()) {
|
||
|
return;
|
||
|
}
|
||
|
cols = loadColumns();
|
||
|
loadData(cols);
|
||
|
addSortIndicators();
|
||
|
enableUI();
|
||
|
};
|
||
|
})();
|
||
|
|
||
|
window.addEventListener('load', addSorting);
|