| 1 | var addSorting = (function () {
|
|---|
| 2 | "use strict";
|
|---|
| 3 | var cols,
|
|---|
| 4 | currentSort = {
|
|---|
| 5 | index: 0,
|
|---|
| 6 | desc: false
|
|---|
| 7 | };
|
|---|
| 8 |
|
|---|
| 9 | // returns the summary table element
|
|---|
| 10 | function getTable() { return document.querySelector('.coverage-summary table'); }
|
|---|
| 11 | // returns the thead element of the summary table
|
|---|
| 12 | function getTableHeader() { return getTable().querySelector('thead tr'); }
|
|---|
| 13 | // returns the tbody element of the summary table
|
|---|
| 14 | function getTableBody() { return getTable().querySelector('tbody'); }
|
|---|
| 15 | // returns the th element for nth column
|
|---|
| 16 | function getNthColumn(n) { return getTableHeader().querySelectorAll('th')[n]; }
|
|---|
| 17 |
|
|---|
| 18 | // loads all columns
|
|---|
| 19 | function loadColumns() {
|
|---|
| 20 | var colNodes = getTableHeader().querySelectorAll('th'),
|
|---|
| 21 | colNode,
|
|---|
| 22 | cols = [],
|
|---|
| 23 | col,
|
|---|
| 24 | i;
|
|---|
| 25 |
|
|---|
| 26 | for (i = 0; i < colNodes.length; i += 1) {
|
|---|
| 27 | colNode = colNodes[i];
|
|---|
| 28 | col = {
|
|---|
| 29 | key: colNode.getAttribute('data-col'),
|
|---|
| 30 | sortable: !colNode.getAttribute('data-nosort'),
|
|---|
| 31 | type: colNode.getAttribute('data-type') || 'string'
|
|---|
| 32 | };
|
|---|
| 33 | cols.push(col);
|
|---|
| 34 | if (col.sortable) {
|
|---|
| 35 | col.defaultDescSort = col.type === 'number';
|
|---|
| 36 | colNode.innerHTML = colNode.innerHTML + '<span class="sorter"></span>';
|
|---|
| 37 | }
|
|---|
| 38 | }
|
|---|
| 39 | return cols;
|
|---|
| 40 | }
|
|---|
| 41 | // attaches a data attribute to every tr element with an object
|
|---|
| 42 | // of data values keyed by column name
|
|---|
| 43 | function loadRowData(tableRow) {
|
|---|
| 44 | var tableCols = tableRow.querySelectorAll('td'),
|
|---|
| 45 | colNode,
|
|---|
| 46 | col,
|
|---|
| 47 | data = {},
|
|---|
| 48 | i,
|
|---|
| 49 | val;
|
|---|
| 50 | for (i = 0; i < tableCols.length; i += 1) {
|
|---|
| 51 | colNode = tableCols[i];
|
|---|
| 52 | col = cols[i];
|
|---|
| 53 | val = colNode.getAttribute('data-value');
|
|---|
| 54 | if (col.type === 'number') {
|
|---|
| 55 | val = Number(val);
|
|---|
| 56 | }
|
|---|
| 57 | data[col.key] = val;
|
|---|
| 58 | }
|
|---|
| 59 | return data;
|
|---|
| 60 | }
|
|---|
| 61 | // loads all row data
|
|---|
| 62 | function loadData() {
|
|---|
| 63 | var rows = getTableBody().querySelectorAll('tr'),
|
|---|
| 64 | i;
|
|---|
| 65 |
|
|---|
| 66 | for (i = 0; i < rows.length; i += 1) {
|
|---|
| 67 | rows[i].data = loadRowData(rows[i]);
|
|---|
| 68 | }
|
|---|
| 69 | }
|
|---|
| 70 | // sorts the table using the data for the ith column
|
|---|
| 71 | function sortByIndex(index, desc) {
|
|---|
| 72 | var key = cols[index].key,
|
|---|
| 73 | sorter = function (a, b) {
|
|---|
| 74 | a = a.data[key];
|
|---|
| 75 | b = b.data[key];
|
|---|
| 76 | return a < b ? -1 : a > b ? 1 : 0;
|
|---|
| 77 | },
|
|---|
| 78 | finalSorter = sorter,
|
|---|
| 79 | tableBody = document.querySelector('.coverage-summary tbody'),
|
|---|
| 80 | rowNodes = tableBody.querySelectorAll('tr'),
|
|---|
| 81 | rows = [],
|
|---|
| 82 | i;
|
|---|
| 83 |
|
|---|
| 84 | if (desc) {
|
|---|
| 85 | finalSorter = function (a, b) {
|
|---|
| 86 | return -1 * sorter(a, b);
|
|---|
| 87 | };
|
|---|
| 88 | }
|
|---|
| 89 |
|
|---|
| 90 | for (i = 0; i < rowNodes.length; i += 1) {
|
|---|
| 91 | rows.push(rowNodes[i]);
|
|---|
| 92 | tableBody.removeChild(rowNodes[i]);
|
|---|
| 93 | }
|
|---|
| 94 |
|
|---|
| 95 | rows.sort(finalSorter);
|
|---|
| 96 |
|
|---|
| 97 | for (i = 0; i < rows.length; i += 1) {
|
|---|
| 98 | tableBody.appendChild(rows[i]);
|
|---|
| 99 | }
|
|---|
| 100 | }
|
|---|
| 101 | // removes sort indicators for current column being sorted
|
|---|
| 102 | function removeSortIndicators() {
|
|---|
| 103 | var col = getNthColumn(currentSort.index),
|
|---|
| 104 | cls = col.className;
|
|---|
| 105 |
|
|---|
| 106 | cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, '');
|
|---|
| 107 | col.className = cls;
|
|---|
| 108 | }
|
|---|
| 109 | // adds sort indicators for current column being sorted
|
|---|
| 110 | function addSortIndicators() {
|
|---|
| 111 | getNthColumn(currentSort.index).className += currentSort.desc ? ' sorted-desc' : ' sorted';
|
|---|
| 112 | }
|
|---|
| 113 | // adds event listeners for all sorter widgets
|
|---|
| 114 | function enableUI() {
|
|---|
| 115 | var i,
|
|---|
| 116 | el,
|
|---|
| 117 | ithSorter = function ithSorter(i) {
|
|---|
| 118 | var col = cols[i];
|
|---|
| 119 |
|
|---|
| 120 | return function () {
|
|---|
| 121 | var desc = col.defaultDescSort;
|
|---|
| 122 |
|
|---|
| 123 | if (currentSort.index === i) {
|
|---|
| 124 | desc = !currentSort.desc;
|
|---|
| 125 | }
|
|---|
| 126 | sortByIndex(i, desc);
|
|---|
| 127 | removeSortIndicators();
|
|---|
| 128 | currentSort.index = i;
|
|---|
| 129 | currentSort.desc = desc;
|
|---|
| 130 | addSortIndicators();
|
|---|
| 131 | };
|
|---|
| 132 | };
|
|---|
| 133 | for (i =0 ; i < cols.length; i += 1) {
|
|---|
| 134 | if (cols[i].sortable) {
|
|---|
| 135 | el = getNthColumn(i).querySelector('.sorter');
|
|---|
| 136 | if (el.addEventListener) {
|
|---|
| 137 | el.addEventListener('click', ithSorter(i));
|
|---|
| 138 | } else {
|
|---|
| 139 | el.attachEvent('onclick', ithSorter(i));
|
|---|
| 140 | }
|
|---|
| 141 | }
|
|---|
| 142 | }
|
|---|
| 143 | }
|
|---|
| 144 | // adds sorting functionality to the UI
|
|---|
| 145 | return function () {
|
|---|
| 146 | if (!getTable()) {
|
|---|
| 147 | return;
|
|---|
| 148 | }
|
|---|
| 149 | cols = loadColumns();
|
|---|
| 150 | loadData(cols);
|
|---|
| 151 | addSortIndicators();
|
|---|
| 152 | enableUI();
|
|---|
| 153 | };
|
|---|
| 154 | })();
|
|---|
| 155 |
|
|---|
| 156 | window.addEventListener('load', addSorting);
|
|---|