| OLD | NEW |
| (Empty) | |
| 1 "use strict"; |
| 2 |
| 3 var dom = (function() { |
| 4 return { |
| 5 add: function(parent, tagName, optText, optClassName) { |
| 6 var node = parent.ownerDocument.createElement(tagName); |
| 7 parent.appendChild(node); |
| 8 |
| 9 if (optText != undefined) |
| 10 dom.addText(node, optText); |
| 11 if (optClassName != undefined) |
| 12 node.className = optClassName; |
| 13 |
| 14 return node; |
| 15 }, |
| 16 |
| 17 addLink: function(parent, text, href) { |
| 18 var node = dom.add(parent, 'a'); |
| 19 dom.addText(node, text); |
| 20 node.href = href; |
| 21 return node; |
| 22 }, |
| 23 |
| 24 addActionLink: function(parent, text, onclick) { |
| 25 var node = dom.addLink(parent, text, 'javascript:void(0)'); |
| 26 node.onclick = onclick; |
| 27 return node; |
| 28 }, |
| 29 |
| 30 addText: function(parent, text) { |
| 31 var textNode = parent.ownerDocument.createTextNode(text); |
| 32 parent.appendChild(textNode); |
| 33 return textNode; |
| 34 }, |
| 35 |
| 36 clear: function(node) { |
| 37 node.innerHTML = ''; |
| 38 }, |
| 39 }; |
| 40 })(); |
| 41 |
| 42 function changeSort(parent, metricsItem, newSort) { |
| 43 setSort(metricsItem, newSort); |
| 44 drawMetricsItem(parent, metricsItem); |
| 45 } |
| 46 |
| 47 function setSort(metricsItem, newSort) { |
| 48 function getSortProperty(bucket) { |
| 49 let prop = metricsItem.sort || SORT_BY_COUNT; |
| 50 |
| 51 switch (Math.abs(prop)) { |
| 52 case SORT_BY_COUNT: |
| 53 return bucket.total; |
| 54 case SORT_BY_NAME: |
| 55 return bucket.name; |
| 56 } |
| 57 return undefined; |
| 58 } |
| 59 |
| 60 if (metricsItem.sort && Math.abs(metricsItem.sort) == Math.abs(newSort)) { |
| 61 // Reverse sort order. |
| 62 metricsItem.sort *= -1; |
| 63 } else { |
| 64 metricsItem.sort = newSort; |
| 65 } |
| 66 |
| 67 metricsItem.buckets.sort(function(a, b) { |
| 68 var multiplier = metricsItem.sort < 0 ? -1 : 1; |
| 69 |
| 70 var propA = getSortProperty(a); |
| 71 var propB = getSortProperty(b); |
| 72 |
| 73 var result = 0; |
| 74 |
| 75 if (propA < propB) { |
| 76 result = -1; |
| 77 } else if (propA > propB) { |
| 78 result = 1; |
| 79 } |
| 80 |
| 81 return result * multiplier; |
| 82 }); |
| 83 } |
| 84 |
| 85 function drawOverviewPage() { |
| 86 var parent = document.body; |
| 87 dom.clear(parent); |
| 88 |
| 89 for (let metricsItem of g_data.metrics) { |
| 90 let div = dom.add(parent, 'div', undefined, 'metricsItem'); |
| 91 drawMetricsItem(div, metricsItem); |
| 92 } |
| 93 } |
| 94 |
| 95 function prettyPrintBigNumber(x) { |
| 96 let origStr = x + ''; |
| 97 let result = ''; |
| 98 |
| 99 for (let i = 0; i < origStr.length; ++i) { |
| 100 let ch = origStr.charAt(origStr.length - 1 - i); |
| 101 |
| 102 if (i > 0 && i % 3 == 0) |
| 103 result = ',' + result; |
| 104 |
| 105 result = ch + result |
| 106 } |
| 107 |
| 108 return result; |
| 109 } |
| 110 |
| 111 function drawMetricsItem(parent, metricsItem) { |
| 112 dom.clear(parent); |
| 113 |
| 114 let includeSamplesColumn = false; |
| 115 for (let bucket of metricsItem.buckets) { |
| 116 if (bucket.samples.length > 0) |
| 117 includeSamplesColumn = true; |
| 118 } |
| 119 |
| 120 dom.add(parent, 'h3', metricsItem.name); |
| 121 dom.add(parent, 'p', 'Total: ' + prettyPrintBigNumber(metricsItem.total)); |
| 122 |
| 123 var table = dom.add(parent, 'table'); |
| 124 var thead = dom.add(table, 'thead'); |
| 125 var theadTr = dom.add(thead, 'tr'); |
| 126 |
| 127 var countTh = dom.add(theadTr, 'th'); |
| 128 countTh.colSpan = 2; |
| 129 let countSortIndicator = ''; |
| 130 let nameSortIndicator = ''; |
| 131 |
| 132 let kUp = ' \u25B2'; |
| 133 let kDown = ' \u25BC'; |
| 134 |
| 135 if (metricsItem.sort == SORT_BY_COUNT) { |
| 136 countSortIndicator = kUp; |
| 137 } else if (metricsItem.sort == -SORT_BY_COUNT) { |
| 138 countSortIndicator = kDown; |
| 139 } else if (metricsItem.sort == SORT_BY_NAME) { |
| 140 nameSortIndicator = kUp; |
| 141 } else if (metricsItem.sort == -SORT_BY_NAME) { |
| 142 nameSortIndicator = kDown; |
| 143 } |
| 144 |
| 145 var countSortCol = dom.addActionLink(countTh, 'Count' + countSortIndicator, ch
angeSort.bind(null, parent, metricsItem, SORT_BY_COUNT)); |
| 146 |
| 147 var samplesTh; |
| 148 if (includeSamplesColumn) |
| 149 samplesTh = dom.add(theadTr, 'th'); |
| 150 |
| 151 var descriptionTh = dom.add(theadTr, 'th'); |
| 152 var descriptionSortCol = dom.addActionLink(descriptionTh, 'Name' + nameSortInd
icator, changeSort.bind(null, parent, metricsItem, SORT_BY_NAME)); |
| 153 |
| 154 var tbody = dom.add(table, 'tbody'); |
| 155 |
| 156 for (let bucket of metricsItem.buckets) { |
| 157 var tr = dom.add(tbody, 'tr'); |
| 158 dom.add(tr, 'td', prettyPrintBigNumber(bucket.total), 'colTotal'); |
| 159 dom.add(tr, 'td', (100 * bucket.total / metricsItem.total).toFixed(3) + ' %'
, 'colPercent'); |
| 160 |
| 161 if (includeSamplesColumn) { |
| 162 var samplesTd = dom.add(tr, 'td', undefined, 'colSamples'); |
| 163 if (bucket.samples.length > 0) |
| 164 dom.addLink(samplesTd, bucket.samples.length + ' samples', '#samples/' +
encodeURIComponent(bucket.id)); |
| 165 } |
| 166 |
| 167 dom.add(tr, 'td', bucket.name, 'colName'); |
| 168 } |
| 169 } |
| 170 |
| 171 function getQueryParams() { |
| 172 var params = {}; |
| 173 |
| 174 var parts = window.location.hash.substr(1).split('&'); |
| 175 for(var i = 0; i < parts.length; i++) { |
| 176 var keyAndValue = parts[i].split('='); |
| 177 params[decodeURIComponent(keyAndValue[0])] = decodeURIComponent(keyAndValue[
1]); |
| 178 } |
| 179 |
| 180 return params; |
| 181 } |
| 182 |
| 183 function findSamplesForBucket(bucketId) { |
| 184 for (let metricsItem of g_data.metrics) { |
| 185 for (let bucket of metricsItem.buckets) { |
| 186 if (bucket.id == bucketId) |
| 187 return bucket.samples; |
| 188 } |
| 189 } |
| 190 return null; |
| 191 } |
| 192 |
| 193 function drawSamplesPage(bucketId) { |
| 194 var parent = document.body; |
| 195 dom.clear(parent); |
| 196 |
| 197 parent = dom.add(parent, 'div', undefined, 'samplesDiv'); |
| 198 |
| 199 let samples = findSamplesForBucket(bucketId); |
| 200 if (!samples) { |
| 201 dom.add(parent, 'h3', 'No bucket for id=' + bucketId); |
| 202 return; |
| 203 } |
| 204 |
| 205 dom.add(parent, 'h3', 'Samples'); |
| 206 |
| 207 var ul = dom.add(parent, 'ul'); |
| 208 |
| 209 for (let sampleUrl of samples) { |
| 210 var li = dom.add(ul, 'li'); |
| 211 dom.addLink(li, sampleUrl, sampleUrl); |
| 212 } |
| 213 } |
| 214 |
| 215 function onHashChange() { |
| 216 let hash = window.location.hash; |
| 217 |
| 218 // Draw the samples page. |
| 219 let regex = /^#samples\/([0-9]+)$/; |
| 220 let match = regex.exec(hash); |
| 221 |
| 222 if (match) { |
| 223 drawSamplesPage(parseInt(match[1])); |
| 224 return; |
| 225 } |
| 226 |
| 227 // Otherwise draw the overview page. |
| 228 drawOverviewPage(); |
| 229 } |
| 230 |
| 231 function onLoad() { |
| 232 // Do an initial sorting of the data, and also assign an ID to each bucket. |
| 233 let bucketId = 0; |
| 234 for (let metricsItem of g_data.metrics) { |
| 235 for (let bucket of metricsItem.buckets) { |
| 236 bucket.id = bucketId++; |
| 237 } |
| 238 setSort(metricsItem, -SORT_BY_COUNT); |
| 239 } |
| 240 |
| 241 // Draw the current page based on the URL. |
| 242 onHashChange(); |
| 243 } |
| 244 |
| 245 var SORT_BY_COUNT = 1; |
| 246 var SORT_BY_NAME = 2; |
| 247 |
| 248 document.addEventListener("DOMContentLoaded", onLoad); |
| 249 window.addEventListener("hashchange", onHashChange); |
| 250 |
| OLD | NEW |