| 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); |