1<!DOCTYPE html> 2<html> 3<head> 4 <meta charset="utf-8"> 5 <title>{{.Title}}</title> 6 {{template "css" .}} 7 <style type="text/css"> 8 </style> 9</head> 10<body> 11 {{template "header" .}} 12 <div id="top"> 13 <table id="toptable"> 14 <thead> 15 <tr> 16 <th id="flathdr1">Flat</th> 17 <th id="flathdr2">Flat%</th> 18 <th>Sum%</th> 19 <th id="cumhdr1">Cum</th> 20 <th id="cumhdr2">Cum%</th> 21 <th id="namehdr">Name</th> 22 <th>Inlined?</th> 23 </tr> 24 </thead> 25 <tbody id="rows"></tbody> 26 </table> 27 </div> 28 {{template "script" .}} 29 <script> 30 function makeTopTable(total, entries) { 31 const rows = document.getElementById('rows'); 32 if (rows == null) return; 33 34 // Store initial index in each entry so we have stable node ids for selection. 35 for (let i = 0; i < entries.length; i++) { 36 entries[i].Id = 'node' + i; 37 } 38 39 // Which column are we currently sorted by and in what order? 40 let currentColumn = ''; 41 let descending = false; 42 sortBy('Flat'); 43 44 function sortBy(column) { 45 // Update sort criteria 46 if (column == currentColumn) { 47 descending = !descending; // Reverse order 48 } else { 49 currentColumn = column; 50 descending = (column != 'Name'); 51 } 52 53 // Sort according to current criteria. 54 function cmp(a, b) { 55 const av = a[currentColumn]; 56 const bv = b[currentColumn]; 57 if (av < bv) return -1; 58 if (av > bv) return +1; 59 return 0; 60 } 61 entries.sort(cmp); 62 if (descending) entries.reverse(); 63 64 function addCell(tr, val) { 65 const td = document.createElement('td'); 66 td.textContent = val; 67 tr.appendChild(td); 68 } 69 70 function percent(v) { 71 return (v * 100.0 / total).toFixed(2) + '%'; 72 } 73 74 // Generate rows 75 const fragment = document.createDocumentFragment(); 76 let sum = 0; 77 for (const row of entries) { 78 const tr = document.createElement('tr'); 79 tr.id = row.Id; 80 sum += row.Flat; 81 addCell(tr, row.FlatFormat); 82 addCell(tr, percent(row.Flat)); 83 addCell(tr, percent(sum)); 84 addCell(tr, row.CumFormat); 85 addCell(tr, percent(row.Cum)); 86 addCell(tr, row.Name); 87 addCell(tr, row.InlineLabel); 88 fragment.appendChild(tr); 89 } 90 91 rows.textContent = ''; // Remove old rows 92 rows.appendChild(fragment); 93 } 94 95 // Make different column headers trigger sorting. 96 function bindSort(id, column) { 97 const hdr = document.getElementById(id); 98 if (hdr == null) return; 99 const fn = function() { sortBy(column) }; 100 hdr.addEventListener('click', fn); 101 hdr.addEventListener('touch', fn); 102 } 103 bindSort('flathdr1', 'Flat'); 104 bindSort('flathdr2', 'Flat'); 105 bindSort('cumhdr1', 'Cum'); 106 bindSort('cumhdr2', 'Cum'); 107 bindSort('namehdr', 'Name'); 108 } 109 110 viewer(new URL(window.location.href), {{.Nodes}}); 111 makeTopTable({{.Total}}, {{.Top}}); 112 </script> 113</body> 114</html> 115