• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2013 Google Inc. All rights reserved.
2//
3// Redistribution and use in source and binary forms, with or without
4// modification, are permitted provided that the following conditions are
5// met:
6//
7//         * Redistributions of source code must retain the above copyright
8// notice, this list of conditions and the following disclaimer.
9//         * Redistributions in binary form must reproduce the above
10// copyright notice, this list of conditions and the following disclaimer
11// in the documentation and/or other materials provided with the
12// distribution.
13//         * Neither the name of Google Inc. nor the names of its
14// contributors may be used to endorse or promote products derived from
15// this software without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29var ui = ui || {};
30
31(function() {
32
33ui.popup = {};
34
35ui.popup.hide = function()
36{
37    var popup = $('popup');
38    if (popup) {
39        popup.parentNode.removeChild(popup);
40        document.removeEventListener('mousedown', ui.popup._handleMouseDown, false);
41    }
42}
43
44ui.popup.show = function(target, html)
45{
46    var popup = $('popup');
47    if (!popup) {
48        popup = document.createElement('div');
49        popup.id = 'popup';
50        document.body.appendChild(popup);
51        document.addEventListener('mousedown', ui.popup._handleMouseDown, false);
52    }
53
54    // Set html first so that we can get accurate size metrics on the popup.
55    popup.innerHTML = html;
56
57    var targetRect = target.getBoundingClientRect();
58
59    var x = Math.min(targetRect.left - 10, document.documentElement.clientWidth - popup.offsetWidth);
60    x = Math.max(0, x);
61    popup.style.left = x + document.body.scrollLeft + 'px';
62
63    var y = targetRect.top + targetRect.height;
64    if (y + popup.offsetHeight > document.documentElement.clientHeight)
65        y = targetRect.top - popup.offsetHeight;
66    y = Math.max(0, y);
67    popup.style.top = y + document.body.scrollTop + 'px';
68}
69
70ui.popup._handleMouseDown = function(e) {
71    // Clear the open popup, unless the click was inside the popup.
72    var popup = $('popup');
73    if (popup && e.target != popup && !(popup.compareDocumentPosition(e.target) & 16))
74        ui.popup.hide();
75}
76
77ui.html = {};
78
79ui.html.checkbox = function(queryParameter, label, isChecked, opt_extraJavaScript)
80{
81    var js = opt_extraJavaScript || '';
82    return '<label style="padding-left: 2em">' +
83        '<input type="checkbox" onchange="g_history.toggleQueryParameter(\'' + queryParameter + '\');' + js + '" ' +
84            (isChecked ? 'checked' : '') + '>' + label +
85        '</label>';
86}
87
88ui.html.range = function(queryParameter, label, min, max, initialValue)
89{
90    return '<label>' +
91        label +
92        '<input type=range onchange="g_history.setQueryParameter(\'' + queryParameter + '\', this.value)" min=' + min + ' max=' + max + ' value=' + initialValue + '>' +
93    '</label>';
94}
95
96ui.html.select = function(label, queryParameter, options)
97{
98    var html = '<label style="padding-left: 2em">' + label + ': ' +
99        '<select onchange="g_history.setQueryParameter(\'' + queryParameter + '\', this[this.selectedIndex].value)">';
100
101    for (var i = 0; i < options.length; i++) {
102        var value = options[i];
103        html += '<option value="' + value + '" ' +
104            (g_history.queryParameterValue(queryParameter) == value ? 'selected' : '') +
105            '>' + value + '</option>'
106    }
107    html += '</select></label> ';
108    return html;
109}
110
111ui.html.navbar = function(opt_extraHtml)
112{
113    var html = '<div style="border-bottom:1px dashed">';
114    html = ui.html._dashboardLink('Overview', 'overview.html') +
115        ui.html._dashboardLink('Results', 'flakiness_dashboard.html') +
116        ui.html._dashboardLink('Times', 'treemap.html') +
117        ui.html._dashboardLink('Stats', 'aggregate_results.html') +
118        ui.html._dashboardLink('Stats Timeline', 'timeline_explorer.html');
119
120    if (opt_extraHtml)
121        html += opt_extraHtml;
122
123    if (!history.isTreeMap())
124        html += ui.html.checkbox('showAllRuns', 'Use all recorded runs', g_history.crossDashboardState.showAllRuns);
125
126    return html + '</div>';
127}
128
129// Returns the HTML for the select element to switch to different testTypes.
130ui.html.testTypeSwitcher = function(opt_noBuilderMenu, opt_extraHtml, opt_includeNoneBuilder)
131{
132    var html = ui.html.select('Test type', 'testType', builders.testTypes);
133    if (!opt_noBuilderMenu) {
134        var buildersForMenu = Object.keys(currentBuilders());
135        if (opt_includeNoneBuilder)
136            buildersForMenu.unshift('--------------');
137        html += ui.html.select('Builder', 'builder', buildersForMenu);
138    }
139
140    html += ui.html.select('Group', 'group', builders.groupNamesForTestType(g_history.crossDashboardState.testType));
141
142    if (opt_extraHtml)
143        html += opt_extraHtml;
144    return ui.html.navbar(html);
145}
146
147ui.html._loadDashboard = function(fileName)
148{
149    var pathName = window.location.pathname;
150    pathName = pathName.substring(0, pathName.lastIndexOf('/') + 1);
151    window.location = pathName + fileName + window.location.hash;
152}
153
154ui.html._topLink = function(html, onClick, isSelected)
155{
156    var cssText = isSelected ? 'font-weight: bold;' : 'color:blue;text-decoration:underline;cursor:pointer;';
157    cssText += 'margin: 0 5px;';
158    return '<span style="' + cssText + '" onclick="' + onClick + '">' + html + '</span>';
159}
160
161ui.html._dashboardLink = function(html, fileName)
162{
163    var pathName = window.location.pathname;
164    var currentFileName = pathName.substring(pathName.lastIndexOf('/') + 1);
165    var isSelected = currentFileName == fileName;
166    var onClick = 'ui.html._loadDashboard(\'' + fileName + '\')';
167    return ui.html._topLink(html, onClick, isSelected);
168}
169
170ui.html._revisionLink = function(resultsKey, testResults, index)
171{
172    var currentRevision = parseInt(testResults[resultsKey][index], 10);
173    var previousRevision = parseInt(testResults[resultsKey][index + 1], 10);
174
175    var isChrome = resultsKey == results.CHROME_REVISIONS;
176    var singleUrl = 'http://src.chromium.org/viewvc/' + (isChrome ? 'chrome' : 'blink') + '?view=rev&revision=' + currentRevision;
177
178    if (currentRevision == previousRevision)
179        return 'At <a href="' + singleUrl + '">r' + currentRevision    + '</a>';
180
181    if (currentRevision - previousRevision == 1)
182        return '<a href="' + singleUrl + '">r' + currentRevision    + '</a>';
183
184    var rangeUrl = 'http://build.chromium.org/f/chromium/perf/dashboard/ui/changelog' +
185        (isChrome ? '' : '_blink') + '.html?url=/trunk' + (isChrome ? '/src' : '') +
186        '&range=' + (previousRevision + 1) + ':' + currentRevision + '&mode=html';
187    return '<a href="' + rangeUrl + '">r' + (previousRevision + 1) + ' to r' + currentRevision + '</a>';
188}
189
190ui.html.chromiumRevisionLink = function(testResults, index)
191{
192    return ui.html._revisionLink(results.CHROME_REVISIONS, testResults, index);
193}
194
195ui.html.blinkRevisionLink = function(testResults, index)
196{
197    return ui.html._revisionLink(results.BLINK_REVISIONS, testResults, index);
198}
199
200
201ui.Errors = function() {
202    this._messages = '';
203    // Element to display the errors within.
204    this._containerElement = null;
205}
206
207ui.Errors.prototype = {
208    show: function()
209    {
210        if (!this._containerElement) {
211            this._containerElement = document.createElement('H2');
212            this._containerElement.style.color = 'red';
213            this._containerElement.id = 'errors';
214            document.documentElement.insertBefore(this._containerElement, document.body);
215        }
216
217        this._containerElement.innerHTML = this._messages;
218    },
219    // Record a new error message.
220    addError: function(message)
221    {
222        this._messages += message + '<br>';
223    },
224    hasErrors: function()
225    {
226        return !!this._messages;
227    }
228}
229
230})();
231