2 * Copyright (C) 2011 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
33 * @param {!WebInspector.AuditController} auditController
34 * @extends {WebInspector.VBox}
36 WebInspector
.AuditLauncherView = function(auditController
)
38 WebInspector
.VBox
.call(this);
39 this.setMinimumSize(100, 25);
41 this._auditController
= auditController
;
43 this._categoryIdPrefix
= "audit-category-item-";
44 this._auditRunning
= false;
46 this.element
.classList
.add("audit-launcher-view");
47 this.element
.classList
.add("panel-enabler-view");
49 this._contentElement
= createElement("div");
50 this._contentElement
.className
= "audit-launcher-view-content";
51 this.element
.appendChild(this._contentElement
);
52 this._boundCategoryClickListener
= this._categoryClicked
.bind(this);
54 this._resetResourceCount();
56 this._sortedCategories
= [];
58 this._headerElement
= createElement("h1");
59 this._headerElement
.className
= "no-audits";
60 this._headerElement
.textContent
= WebInspector
.UIString("No audits to run");
61 this._contentElement
.appendChild(this._headerElement
);
63 WebInspector
.targetManager
.addModelListener(WebInspector
.NetworkManager
, WebInspector
.NetworkManager
.EventTypes
.RequestStarted
, this._onRequestStarted
, this);
64 WebInspector
.targetManager
.addModelListener(WebInspector
.NetworkManager
, WebInspector
.NetworkManager
.EventTypes
.RequestFinished
, this._onRequestFinished
, this);
66 var defaultSelectedAuditCategory
= {};
67 defaultSelectedAuditCategory
[WebInspector
.AuditLauncherView
.AllCategoriesKey
] = true;
68 this._selectedCategoriesSetting
= WebInspector
.settings
.createSetting("selectedAuditCategories", defaultSelectedAuditCategory
);
71 WebInspector
.AuditLauncherView
.AllCategoriesKey
= "__AllCategories";
73 WebInspector
.AuditLauncherView
.prototype = {
74 _resetResourceCount: function()
76 this._loadedResources
= 0;
77 this._totalResources
= 0;
80 _onRequestStarted: function(event
)
82 var request
= /** @type {!WebInspector.NetworkRequest} */ (event
.data
);
83 // Ignore long-living WebSockets for the sake of progress indicator, as we won't be waiting them anyway.
84 if (request
.resourceType() === WebInspector
.resourceTypes
.WebSocket
)
86 ++this._totalResources
;
87 this._updateResourceProgress();
90 _onRequestFinished: function(event
)
92 var request
= /** @type {!WebInspector.NetworkRequest} */ (event
.data
);
93 // See resorceStarted for details.
94 if (request
.resourceType() === WebInspector
.resourceTypes
.WebSocket
)
96 ++this._loadedResources
;
97 this._updateResourceProgress();
101 * @param {!WebInspector.AuditCategory} category
103 addCategory: function(category
)
105 if (!this._sortedCategories
.length
)
106 this._createLauncherUI();
108 var selectedCategories
= this._selectedCategoriesSetting
.get();
109 var categoryElement
= this._createCategoryElement(category
.displayName
, category
.id
);
110 category
._checkboxElement
= categoryElement
.checkboxElement
;
111 if (this._selectAllCheckboxElement
.checked
|| selectedCategories
[category
.displayName
]) {
112 category
._checkboxElement
.checked
= true;
113 ++this._currentCategoriesCount
;
117 * @param {!WebInspector.AuditCategory} a
118 * @param {!WebInspector.AuditCategory} b
121 function compareCategories(a
, b
)
123 var aTitle
= a
.displayName
|| "";
124 var bTitle
= b
.displayName
|| "";
125 return aTitle
.localeCompare(bTitle
);
127 var insertBefore
= insertionIndexForObjectInListSortedByFunction(category
, this._sortedCategories
, compareCategories
);
128 this._categoriesElement
.insertBefore(categoryElement
, this._categoriesElement
.children
[insertBefore
]);
129 this._sortedCategories
.splice(insertBefore
, 0, category
);
130 this._selectedCategoriesUpdated();
133 _startAudit: function()
135 this._auditRunning
= true;
136 this._updateButton();
137 this._toggleUIComponents(this._auditRunning
);
140 for (var category
= 0; category
< this._sortedCategories
.length
; ++category
) {
141 if (this._sortedCategories
[category
]._checkboxElement
.checked
)
142 catIds
.push(this._sortedCategories
[category
].id
);
145 this._resetResourceCount();
146 this._progressIndicator
= new WebInspector
.ProgressIndicator();
147 this._buttonContainerElement
.appendChild(this._progressIndicator
.element
);
148 this._displayResourceLoadingProgress
= true;
151 * @this {WebInspector.AuditLauncherView}
153 function onAuditStarted()
155 this._displayResourceLoadingProgress
= false;
157 this._auditController
.initiateAudit(catIds
, new WebInspector
.ProgressProxy(this._progressIndicator
, this._auditsDone
.bind(this)), this._auditPresentStateElement
.checked
, onAuditStarted
.bind(this));
160 _auditsDone: function()
162 this._displayResourceLoadingProgress
= false;
163 delete this._progressIndicator
;
164 this._launchButton
.disabled
= false;
165 this._auditRunning
= false;
166 this._updateButton();
167 this._toggleUIComponents(this._auditRunning
);
171 * @param {boolean} disable
173 _toggleUIComponents: function(disable
)
175 this._selectAllCheckboxElement
.disabled
= disable
;
176 for (var child
= this._categoriesElement
.firstChild
; child
; child
= child
.nextSibling
)
177 child
.checkboxElement
.disabled
= disable
;
178 this._auditPresentStateElement
.disabled
= disable
;
179 this._auditReloadedStateElement
.disabled
= disable
;
182 _launchButtonClicked: function(event
)
184 if (this._auditRunning
) {
185 this._launchButton
.disabled
= true;
186 this._progressIndicator
.cancel();
192 _clearButtonClicked: function()
194 this._auditController
.clearResults();
198 * @param {boolean} checkCategories
199 * @param {boolean=} userGesture
201 _selectAllClicked: function(checkCategories
, userGesture
)
203 var childNodes
= this._categoriesElement
.childNodes
;
204 for (var i
= 0, length
= childNodes
.length
; i
< length
; ++i
)
205 childNodes
[i
].checkboxElement
.checked
= checkCategories
;
206 this._currentCategoriesCount
= checkCategories
? this._sortedCategories
.length
: 0;
207 this._selectedCategoriesUpdated(userGesture
);
210 _categoryClicked: function(event
)
212 this._currentCategoriesCount
+= event
.target
.checked
? 1 : -1;
213 this._selectAllCheckboxElement
.checked
= this._currentCategoriesCount
=== this._sortedCategories
.length
;
214 this._selectedCategoriesUpdated(true);
218 * @param {string} title
219 * @param {string=} id
221 _createCategoryElement: function(title
, id
)
223 var labelElement
= createCheckboxLabel(title
);
225 labelElement
.id
= this._categoryIdPrefix
+ id
;
226 labelElement
.checkboxElement
.addEventListener("click", this._boundCategoryClickListener
, false);
228 labelElement
.__displayName
= title
;
233 _createLauncherUI: function()
235 this._headerElement
= createElement("h1");
236 this._headerElement
.textContent
= WebInspector
.UIString("Select audits to run");
238 this._contentElement
.removeChildren();
239 this._contentElement
.appendChild(this._headerElement
);
242 * @param {!Event} event
243 * @this {WebInspector.AuditLauncherView}
245 function handleSelectAllClick(event
)
247 this._selectAllClicked(event
.target
.checked
, true);
249 var categoryElement
= this._createCategoryElement(WebInspector
.UIString("Select All"), "");
250 categoryElement
.id
= "audit-launcher-selectall";
251 this._selectAllCheckboxElement
= categoryElement
.checkboxElement
;
252 this._selectAllCheckboxElement
.checked
= this._selectedCategoriesSetting
.get()[WebInspector
.AuditLauncherView
.AllCategoriesKey
];
253 this._selectAllCheckboxElement
.addEventListener("click", handleSelectAllClick
.bind(this), false);
254 this._contentElement
.appendChild(categoryElement
);
256 this._categoriesElement
= this._contentElement
.createChild("fieldset", "audit-categories-container");
257 this._currentCategoriesCount
= 0;
259 this._contentElement
.createChild("div", "flexible-space");
261 this._buttonContainerElement
= this._contentElement
.createChild("div", "button-container");
263 var radio
= createRadioLabel("audit-mode", WebInspector
.UIString("Audit Present State"), true);
264 this._buttonContainerElement
.appendChild(radio
);
265 this._auditPresentStateElement
= radio
.radioElement
;
267 radio
= createRadioLabel("audit-mode", WebInspector
.UIString("Reload Page and Audit on Load"));
268 this._buttonContainerElement
.appendChild(radio
);
269 this._auditReloadedStateElement
= radio
.radioElement
;
271 this._launchButton
= createTextButton(WebInspector
.UIString("Run"), this._launchButtonClicked
.bind(this));
272 this._buttonContainerElement
.appendChild(this._launchButton
);
274 this._clearButton
= createTextButton(WebInspector
.UIString("Clear"), this._clearButtonClicked
.bind(this));
275 this._buttonContainerElement
.appendChild(this._clearButton
);
277 this._selectAllClicked(this._selectAllCheckboxElement
.checked
);
280 _updateResourceProgress: function()
282 if (this._displayResourceLoadingProgress
)
283 this._progressIndicator
.setTitle(WebInspector
.UIString("Loading (%d of %d)", this._loadedResources
, this._totalResources
));
287 * @param {boolean=} userGesture
289 _selectedCategoriesUpdated: function(userGesture
)
291 // Save present categories only upon user gesture to clean up junk from past versions and removed extensions.
292 // Do not remove old categories if not handling a user gesture, as there's chance categories will be added
293 // later during start-up.
294 var selectedCategories
= userGesture
? {} : this._selectedCategoriesSetting
.get();
295 var childNodes
= this._categoriesElement
.childNodes
;
296 for (var i
= 0, length
= childNodes
.length
; i
< length
; ++i
)
297 selectedCategories
[childNodes
[i
].__displayName
] = childNodes
[i
].checkboxElement
.checked
;
298 selectedCategories
[WebInspector
.AuditLauncherView
.AllCategoriesKey
] = this._selectAllCheckboxElement
.checked
;
299 this._selectedCategoriesSetting
.set(selectedCategories
);
300 this._updateButton();
303 _updateButton: function()
305 this._launchButton
.textContent
= this._auditRunning
? WebInspector
.UIString("Stop") : WebInspector
.UIString("Run");
306 this._launchButton
.disabled
= !this._currentCategoriesCount
;
309 __proto__
: WebInspector
.VBox
.prototype