sorter.js 4.9 KB

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