Home | History | Annotate | Download | only in front-end
      1 /*
      2  * Copyright (C) 2011 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 WebInspector.AuditLauncherView = function(runnerCallback)
     32 {
     33     WebInspector.View.call(this);
     34     this._runnerCallback = runnerCallback;
     35     this._categoryIdPrefix = "audit-category-item-";
     36     this._auditRunning = false;
     37 
     38     this.element.addStyleClass("audit-launcher-view");
     39 
     40     this._contentElement = document.createElement("div");
     41     this._contentElement.className = "audit-launcher-view-content";
     42     this.element.appendChild(this._contentElement);
     43     this._boundCategoryClickListener = this._categoryClicked.bind(this);
     44 
     45     this._resetResourceCount();
     46 
     47     this._sortedCategories = [];
     48 
     49     this._headerElement = document.createElement("h1");
     50     this._headerElement.className = "no-audits";
     51     this._headerElement.textContent = WebInspector.UIString("No audits to run");
     52     this._contentElement.appendChild(this._headerElement);
     53 
     54     WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceStarted, this._onResourceStarted, this);
     55     WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceFinished, this._onResourceFinished, this);
     56 }
     57 
     58 WebInspector.AuditLauncherView.prototype = {
     59     _resetResourceCount: function()
     60     {
     61         this._loadedResources = 0;
     62         this._totalResources = 0;
     63     },
     64 
     65     _onResourceStarted: function(event)
     66     {
     67         var resource = event.data;
     68         // Ignore long-living WebSockets for the sake of progress indicator, as we won't be waiting them anyway.
     69         if (resource.type === WebInspector.Resource.Type.WebSocket)
     70             return;
     71         ++this._totalResources;
     72         this._updateResourceProgress();
     73     },
     74 
     75     _onResourceFinished: function(event)
     76     {
     77         var resource = event.data;
     78         // See resorceStarted for details.
     79         if (resource.type === WebInspector.Resource.Type.WebSocket)
     80             return;
     81         ++this._loadedResources;
     82         this._updateResourceProgress();
     83     },
     84 
     85     addCategory: function(category)
     86     {
     87         if (!this._sortedCategories.length)
     88             this._createLauncherUI();
     89 
     90         var categoryElement = this._createCategoryElement(category.displayName, category.id);
     91         category._checkboxElement = categoryElement.firstChild;
     92         if (this._selectAllCheckboxElement.checked) {
     93             category._checkboxElement.checked = true;
     94             ++this._currentCategoriesCount;
     95         }
     96 
     97         function compareCategories(a, b)
     98         {
     99             var aTitle = a.displayName || "";
    100             var bTitle = b.displayName || "";
    101             return aTitle.localeCompare(bTitle);
    102         }
    103         var insertBefore = insertionIndexForObjectInListSortedByFunction(category, this._sortedCategories, compareCategories);
    104         this._categoriesElement.insertBefore(categoryElement, this._categoriesElement.children[insertBefore]);
    105         this._sortedCategories.splice(insertBefore, 0, category);
    106         this._updateButton();
    107     },
    108 
    109     _setAuditRunning: function(auditRunning)
    110     {
    111         if (this._auditRunning === auditRunning)
    112             return;
    113         this._auditRunning = auditRunning;
    114         this._updateButton();
    115         this._updateResourceProgress();
    116     },
    117 
    118     _launchButtonClicked: function(event)
    119     {
    120         var catIds = [];
    121         var childNodes = this._categoriesElement.childNodes;
    122         for (var category = 0; category < this._sortedCategories.length; ++category) {
    123             if (this._sortedCategories[category]._checkboxElement.checked)
    124                 catIds.push(this._sortedCategories[category].id);
    125         }
    126 
    127         this._setAuditRunning(true);
    128         this._runnerCallback(catIds, this._auditPresentStateElement.checked, this._setAuditRunning.bind(this, false));
    129     },
    130 
    131     _selectAllClicked: function(checkCategories)
    132     {
    133         var childNodes = this._categoriesElement.childNodes;
    134         for (var i = 0, length = childNodes.length; i < length; ++i)
    135             childNodes[i].firstChild.checked = checkCategories;
    136         this._currentCategoriesCount = checkCategories ? this._sortedCategories.length : 0;
    137         this._updateButton();
    138     },
    139 
    140     _categoryClicked: function(event)
    141     {
    142         this._currentCategoriesCount += event.target.checked ? 1 : -1;
    143         this._selectAllCheckboxElement.checked = this._currentCategoriesCount === this._sortedCategories.length;
    144         this._updateButton();
    145     },
    146 
    147     _createCategoryElement: function(title, id)
    148     {
    149         var labelElement = document.createElement("label");
    150         labelElement.id = this._categoryIdPrefix + id;
    151 
    152         var element = document.createElement("input");
    153         element.type = "checkbox";
    154         if (id !== "")
    155             element.addEventListener("click", this._boundCategoryClickListener, false);
    156         labelElement.appendChild(element);
    157         labelElement.appendChild(document.createTextNode(title));
    158 
    159         return labelElement;
    160     },
    161 
    162     _createLauncherUI: function()
    163     {
    164         this._headerElement = document.createElement("h1");
    165         this._headerElement.textContent = WebInspector.UIString("Select audits to run");
    166 
    167         for (var child = 0; child < this._contentElement.children.length; ++child)
    168             this._contentElement.removeChild(this._contentElement.children[child]);
    169 
    170         this._contentElement.appendChild(this._headerElement);
    171 
    172         function handleSelectAllClick(event)
    173         {
    174             this._selectAllClicked(event.target.checked);
    175         }
    176         var categoryElement = this._createCategoryElement(WebInspector.UIString("Select All"), "");
    177         categoryElement.id = "audit-launcher-selectall";
    178         this._selectAllCheckboxElement = categoryElement.firstChild;
    179         this._selectAllCheckboxElement.checked = true;
    180         this._selectAllCheckboxElement.addEventListener("click", handleSelectAllClick.bind(this), false);
    181         this._contentElement.appendChild(categoryElement);
    182 
    183         this._categoriesElement = document.createElement("div");
    184         this._categoriesElement.className = "audit-categories-container";
    185         this._contentElement.appendChild(this._categoriesElement);
    186 
    187         this._currentCategoriesCount = 0;
    188 
    189         var flexibleSpaceElement = document.createElement("div");
    190         flexibleSpaceElement.className = "flexible-space";
    191         this._contentElement.appendChild(flexibleSpaceElement);
    192 
    193         this._buttonContainerElement = document.createElement("div");
    194         this._buttonContainerElement.className = "button-container";
    195 
    196         var labelElement = document.createElement("label");
    197         this._auditPresentStateElement = document.createElement("input");
    198         this._auditPresentStateElement.name = "audit-mode";
    199         this._auditPresentStateElement.type = "radio";
    200         this._auditPresentStateElement.checked = true;
    201         this._auditPresentStateLabelElement = document.createTextNode(WebInspector.UIString("Audit Present State"));
    202         labelElement.appendChild(this._auditPresentStateElement);
    203         labelElement.appendChild(this._auditPresentStateLabelElement);
    204         this._buttonContainerElement.appendChild(labelElement);
    205 
    206         labelElement = document.createElement("label");
    207         this.auditReloadedStateElement = document.createElement("input");
    208         this.auditReloadedStateElement.name = "audit-mode";
    209         this.auditReloadedStateElement.type = "radio";
    210         labelElement.appendChild(this.auditReloadedStateElement);
    211         labelElement.appendChild(document.createTextNode("Reload Page and Audit on Load"));
    212         this._buttonContainerElement.appendChild(labelElement);
    213 
    214         this._launchButton = document.createElement("button");
    215         this._launchButton.type = "button";
    216         this._launchButton.textContent = WebInspector.UIString("Run");
    217         this._launchButton.addEventListener("click", this._launchButtonClicked.bind(this), false);
    218         this._buttonContainerElement.appendChild(this._launchButton);
    219 
    220         this._resourceProgressContainer = document.createElement("span");
    221         this._resourceProgressContainer.className = "resource-progress";
    222         var resourceProgressImage = document.createElement("img");
    223         this._resourceProgressContainer.appendChild(resourceProgressImage);
    224         this._resourceProgressTextElement = document.createElement("span");
    225         this._resourceProgressContainer.appendChild(this._resourceProgressTextElement);
    226         this._buttonContainerElement.appendChild(this._resourceProgressContainer);
    227 
    228         this._contentElement.appendChild(this._buttonContainerElement);
    229 
    230         this._selectAllClicked(this._selectAllCheckboxElement.checked);
    231         this._updateButton();
    232         this._updateResourceProgress();
    233     },
    234 
    235     _updateResourceProgress: function()
    236     {
    237         if (!this._resourceProgressContainer)
    238             return;
    239 
    240         if (!this._auditRunning) {
    241             this._resetResourceCount();
    242             this._resourceProgressContainer.addStyleClass("hidden");
    243         } else
    244             this._resourceProgressContainer.removeStyleClass("hidden");
    245         this._resourceProgressTextElement.textContent = WebInspector.UIString("Loading (%d of %d)", this._loadedResources, this._totalResources);
    246     },
    247 
    248     _updateButton: function()
    249     {
    250         this._launchButton.disabled = !this._currentCategoriesCount || this._auditRunning;
    251     }
    252 }
    253 
    254 WebInspector.AuditLauncherView.prototype.__proto__ = WebInspector.View.prototype;
    255