|
@@ -142,14 +142,15 @@ button {
|
142
|
142
|
#toptable {
|
143
|
143
|
border-spacing: 0px;
|
144
|
144
|
width: 100%;
|
|
145
|
+ padding-bottom: 1em;
|
145
|
146
|
}
|
146
|
147
|
#toptable tr th {
|
147
|
148
|
border-bottom: 1px solid black;
|
148
|
149
|
text-align: right;
|
149
|
150
|
padding-left: 1em;
|
|
151
|
+ padding-top: 0.2em;
|
|
152
|
+ padding-bottom: 0.2em;
|
150
|
153
|
}
|
151
|
|
-#toptable tr th:nth-child(6) { text-align: left; }
|
152
|
|
-#toptable tr th:nth-child(7) { text-align: left; }
|
153
|
154
|
#toptable tr td {
|
154
|
155
|
padding-left: 1em;
|
155
|
156
|
font: monospace;
|
|
@@ -157,12 +158,19 @@ button {
|
157
|
158
|
white-space: nowrap;
|
158
|
159
|
cursor: default;
|
159
|
160
|
}
|
160
|
|
-#toptable tr td:nth-child(6) {
|
|
161
|
+#toptable tr th:nth-child(6),
|
|
162
|
+#toptable tr th:nth-child(7),
|
|
163
|
+#toptable tr td:nth-child(6),
|
|
164
|
+#toptable tr td:nth-child(7) {
|
161
|
165
|
text-align: left;
|
|
166
|
+}
|
|
167
|
+#toptable tr td:nth-child(6) {
|
162
|
168
|
max-width: 30em; // Truncate very long names
|
163
|
169
|
overflow: hidden;
|
164
|
170
|
}
|
165
|
|
-#toptable tr td:nth-child(7) { text-align: left; }
|
|
171
|
+#flathdr1, #flathdr2, #cumhdr1, #cumhdr2, #namehdr {
|
|
172
|
+ cursor: ns-resize;
|
|
173
|
+}
|
166
|
174
|
.hilite {
|
167
|
175
|
background-color: #ccf;
|
168
|
176
|
}
|
|
@@ -741,6 +749,8 @@ function viewer(baseUrl, nodes) {
|
741
|
749
|
<meta charset="utf-8">
|
742
|
750
|
<title>{{.Title}}</title>
|
743
|
751
|
{{template "css" .}}
|
|
752
|
+<style type="text/css">
|
|
753
|
+</style>
|
744
|
754
|
</head>
|
745
|
755
|
<body>
|
746
|
756
|
|
|
@@ -748,15 +758,104 @@ function viewer(baseUrl, nodes) {
|
748
|
758
|
|
749
|
759
|
<div id="bodycontainer">
|
750
|
760
|
<table id="toptable">
|
751
|
|
-<tr><th>Flat<th>Flat%<th>Sum%<th>Cum<th>Cum%<th>Name<th>Inlined?</tr>
|
752
|
|
-{{range $i,$e := .Top}}
|
753
|
|
- <tr id="node{{$i}}"><td>{{$e.Flat}}<td>{{$e.FlatPercent}}<td>{{$e.SumPercent}}<td>{{$e.Cum}}<td>{{$e.CumPercent}}<td>{{$e.Name}}<td>{{$e.InlineLabel}}</tr>
|
754
|
|
-{{end}}
|
|
761
|
+<tr>
|
|
762
|
+<th id="flathdr1">Flat
|
|
763
|
+<th id="flathdr2">Flat%
|
|
764
|
+<th>Sum%
|
|
765
|
+<th id="cumhdr1">Cum
|
|
766
|
+<th id="cumhdr2">Cum%
|
|
767
|
+<th id="namehdr">Name
|
|
768
|
+<th>Inlined?</tr>
|
|
769
|
+<tbody id="rows">
|
|
770
|
+</tbody>
|
755
|
771
|
</table>
|
756
|
772
|
</div>
|
757
|
773
|
|
758
|
774
|
{{template "script" .}}
|
759
|
|
-<script>viewer({{.BaseURL}}, {{.Nodes}})</script>
|
|
775
|
+<script>
|
|
776
|
+function makeTopTable(total, entries) {
|
|
777
|
+ const rows = document.getElementById("rows")
|
|
778
|
+ if (rows == null) return
|
|
779
|
+
|
|
780
|
+ // Store initial index in each entry so we have stable node ids for selection.
|
|
781
|
+ for (let i = 0; i < entries.length; i++) {
|
|
782
|
+ entries[i].Id = "node" + i
|
|
783
|
+ }
|
|
784
|
+
|
|
785
|
+ // Which column are we currently sorted by and in what order?
|
|
786
|
+ let currentColumn = ""
|
|
787
|
+ let descending = false
|
|
788
|
+ sortBy("Flat")
|
|
789
|
+
|
|
790
|
+ function sortBy(column) {
|
|
791
|
+ // Update sort criteria
|
|
792
|
+ if (column == currentColumn) {
|
|
793
|
+ descending = !descending // Reverse order
|
|
794
|
+ } else {
|
|
795
|
+ currentColumn = column
|
|
796
|
+ descending = (column != "Name")
|
|
797
|
+ }
|
|
798
|
+
|
|
799
|
+ // Sort according to current criteria.
|
|
800
|
+ function cmp(a, b) {
|
|
801
|
+ const av = a[currentColumn]
|
|
802
|
+ const bv = b[currentColumn]
|
|
803
|
+ if (av < bv) return -1
|
|
804
|
+ if (av > bv) return +1
|
|
805
|
+ return 0
|
|
806
|
+ }
|
|
807
|
+ entries.sort(cmp)
|
|
808
|
+ if (descending) entries.reverse()
|
|
809
|
+
|
|
810
|
+ function addCell(tr, val) {
|
|
811
|
+ const td = document.createElement('td')
|
|
812
|
+ td.textContent = val
|
|
813
|
+ tr.appendChild(td)
|
|
814
|
+ }
|
|
815
|
+
|
|
816
|
+ function percent(v) {
|
|
817
|
+ return (v * 100.0 / total).toFixed(2) + "%"
|
|
818
|
+ }
|
|
819
|
+
|
|
820
|
+ // Generate rows
|
|
821
|
+ const fragment = document.createDocumentFragment()
|
|
822
|
+ let sum = 0
|
|
823
|
+ for (const row of entries) {
|
|
824
|
+ const tr = document.createElement('tr')
|
|
825
|
+ tr.id = row.Id
|
|
826
|
+ sum += row.Flat
|
|
827
|
+ addCell(tr, row.FlatFormat)
|
|
828
|
+ addCell(tr, percent(row.Flat))
|
|
829
|
+ addCell(tr, percent(sum))
|
|
830
|
+ addCell(tr, row.CumFormat)
|
|
831
|
+ addCell(tr, percent(row.Cum))
|
|
832
|
+ addCell(tr, row.Name)
|
|
833
|
+ addCell(tr, row.InlineLabel)
|
|
834
|
+ fragment.appendChild(tr)
|
|
835
|
+ }
|
|
836
|
+
|
|
837
|
+ rows.textContent = '' // Remove old rows
|
|
838
|
+ rows.appendChild(fragment)
|
|
839
|
+ }
|
|
840
|
+
|
|
841
|
+ // Make different column headers trigger sorting.
|
|
842
|
+ function bindSort(id, column) {
|
|
843
|
+ const hdr = document.getElementById(id)
|
|
844
|
+ if (hdr == null) return
|
|
845
|
+ const fn = function() { sortBy(column) }
|
|
846
|
+ hdr.addEventListener("click", fn)
|
|
847
|
+ hdr.addEventListener("touch", fn)
|
|
848
|
+ }
|
|
849
|
+ bindSort("flathdr1", "Flat")
|
|
850
|
+ bindSort("flathdr2", "Flat")
|
|
851
|
+ bindSort("cumhdr1", "Cum")
|
|
852
|
+ bindSort("cumhdr2", "Cum")
|
|
853
|
+ bindSort("namehdr", "Name")
|
|
854
|
+}
|
|
855
|
+
|
|
856
|
+viewer({{.BaseURL}}, {{.Nodes}})
|
|
857
|
+makeTopTable({{.Total}}, {{.Top}})
|
|
858
|
+</script>
|
760
|
859
|
</body>
|
761
|
860
|
</html>
|
762
|
861
|
{{end}}
|