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