Home | History | Annotate | Download | only in static-dashboards
      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 
     29 var ui = ui || {};
     30 
     31 (function() {
     32 
     33 ui.popup = {};
     34 
     35 ui.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 
     44 ui.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 
     70 ui.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 
     77 ui.html = {};
     78 
     79 ui.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 
     88 ui.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 
     96 ui.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 
    111 ui.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.
    130 ui.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 
    147 ui.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 
    154 ui.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 
    161 ui.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 
    170 ui.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 
    190 ui.html.chromiumRevisionLink = function(testResults, index)
    191 {
    192     return ui.html._revisionLink(results.CHROME_REVISIONS, testResults, index);
    193 }
    194 
    195 ui.html.blinkRevisionLink = function(testResults, index)
    196 {
    197     return ui.html._revisionLink(results.BLINK_REVISIONS, testResults, index);
    198 }
    199 
    200 
    201 ui.Errors = function() {
    202     this._messages = '';
    203     // Element to display the errors within.
    204     this._containerElement = null;
    205 }
    206 
    207 ui.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