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