1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/* Counter accessor for Name Node. */
6function getCounterNameFromCounterNode(node) {
7  return node.childNodes[1];
8}
9
10/* Counter accessor for Value Node. */
11function getCounterValueFromCounterNode(node) {
12  return node.childNodes[3];
13}
14
15/* Counter accessor for Delta Node. */
16function getCounterDeltaFromCounterNode(node) {
17  return node.childNodes[5];
18}
19
20/* Timer accessor for Name Node. */
21function getTimerNameFromTimerNode(node) {
22  return node.childNodes[1];
23}
24
25/* Timer accessor for Value Node. */
26function getTimerValueFromTimerNode(node) {
27  return node.childNodes[3];
28}
29
30/* Timer accessor for Time Node. */
31function getTimerTimeFromTimerNode(node) {
32  return node.childNodes[5];
33}
34
35/* Timer accessor for Average Time Node. */
36function getTimerAvgTimeFromTimerNode(node) {
37  return node.childNodes[7];
38}
39
40/* Do the filter work.  Hide all nodes matching node.*/
41function filterMatching(text, nodelist, functionToGetNameNode) {
42  var showAll = text.length == 0;
43  for (var i = 0, node; node = nodelist[i]; i++) {
44    var name = functionToGetNameNode(node).innerHTML.toLowerCase();
45    if (showAll || name.indexOf(text) >= 0)
46      node.style.display = 'table-row';
47    else
48      node.style.display = 'none';
49  }
50}
51
52/* Hides or shows counters based on the user's current filter selection. */
53function doFilter() {
54  var filter = $('filter');
55  var text = filter.value.toLowerCase();
56  var nodes = document.getElementsByName('counter');
57  filterMatching(text, nodes, getCounterNameFromCounterNode);
58  var nodes = document.getElementsByName('timer');
59  filterMatching(text, nodes, getTimerNameFromTimerNode);
60}
61
62/* Colors the counters based on increasing or decreasing value. */
63function doColor() {
64  var nodes = document.getElementsByName('counter');
65  for (var i = 0, node; node = nodes[i]; i++) {
66    var child = getCounterDeltaFromCounterNode(node);
67    var delta = child.innerHTML;
68    if (delta > 0)
69      child.style.color = 'Green';
70    else if (delta == 0)
71      child.style.color = 'Black';
72    else
73      child.style.color = 'Red';
74  }
75}
76
77/* Counters with no values are null. Remove them. */
78function removeNullValues() {
79  var nodes = document.getElementsByName('counter');
80  for (var i = nodes.length - 1; i >= 0; i--) {
81    var node = nodes[i];
82    var value = getCounterValueFromCounterNode(node).innerHTML;
83    if (value == 'null')
84      node.parentNode.removeChild(node);
85  }
86  var nodes = document.getElementsByName('timer');
87  for (var i = 0, node; node = nodes[i]; i++) {
88    var valueNode = getTimerValueFromTimerNode(node);
89    if (valueNode.innerHTML == 'null')
90      valueNode.innerHTML = '';
91  }
92}
93
94/* Compute the average time for timers */
95function computeTimes() {
96  var nodes = document.getElementsByName('timer');
97  for (var i = 0, node; node = nodes[i]; i++) {
98    var count = getTimerValueFromTimerNode(node).innerHTML;
99    if (count.length > 0) {
100      var time = getTimerTimeFromTimerNode(node).innerHTML;
101      var avg = getTimerAvgTimeFromTimerNode(node);
102      avg.innerHTML = Math.round(time / count * 100) / 100;
103    }
104  }
105}
106
107/* All the work we do onload. */
108function onLoadWork() {
109  // This is the javascript code that processes the template:
110  var input = new JsEvalContext(templateData);
111  var output = $('t');
112  jstProcess(input, output);
113
114  // Add handlers to dynamically created HTML elements.
115  var elements = document.getElementsByName('string-sort');
116  for (var i = 0; i < elements.length; ++i)
117    elements[i].onclick = function() { sortTable('string'); };
118
119  elements = document.getElementsByName('number-sort');
120  for (i = 0; i < elements.length; ++i)
121    elements[i].onclick = function() { sortTable('number'); };
122
123  doColor();
124  removeNullValues();
125  computeTimes();
126
127  var filter = $('filter');
128  filter.onkeyup = doFilter;
129  filter.focus();
130}
131
132// The function should only be used as the event handler
133// on a table cell element. To use it, put it in a <td> element:
134//  <td onclick="sort('string')" ...>
135//
136// The function sorts rows after the row with onclick event handler.
137//
138// type: the data type, 'string', 'number'
139function sortTable(type) {
140  var cell = event.target;
141  var cnum = cell.cellIndex;
142
143  var row = cell.parentNode;
144  var startIndex = row.rowIndex + 1;
145
146  var tbody = row.parentNode;
147  var table = tbody.parentNode;
148
149  var rows = new Array();
150
151  var indexes = new Array();
152  // skip the first row
153  for (var i = startIndex; i < table.rows.length; i++)
154    rows.push(table.rows[i]);
155
156  // a, b are strings
157  function compareStrings(a, b) {
158    if (a == b) return 0;
159    if (a < b) return -1;
160    return 1;
161  }
162
163  // a, b are numbers
164  function compareNumbers(a, b) {
165    var x = isNaN(a) ? 0 : a;
166    var y = isNaN(b) ? 0 : b;
167    return x - y;
168  }
169
170  var sortFunc;
171  if (type === 'string') {
172    sortFunc = function(a, b) {
173      var x = a.cells[cnum].innerText;
174      var y = b.cells[cnum].innerText;
175      return compareStrings(x, y);
176    };
177
178  } else if (type === 'number') {
179    sortFunc = function(a, b) {
180      var x = parseFloat(a.cells[cnum].innerText);
181      var y = parseFloat(b.cells[cnum].innerText);
182      return compareNumbers(x, y);
183    };
184  }
185
186  rows.sort(sortFunc);
187
188  // change tables
189  if (cell._reverse) {
190    for (var i = rows.length - 1; i >= 0; i--)
191      tbody.appendChild(rows[i]);
192    cell._reverse = false;
193  } else {
194    for (var i = 0; i < rows.length; i++)
195      tbody.appendChild(rows[i]);
196    cell._reverse = true;
197  }
198}
199
200document.addEventListener('DOMContentLoaded', onLoadWork);
201