Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Side by Side Diff: chrome_frame/tools/test/reference_build/chrome/resources/inspector/ResourcesPanel.js

Issue 218019: Initial import of the Chrome Frame codebase. Integration in chrome.gyp coming... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2008, 2009 Anthony Ricaud <rik@webkit.org>
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 WebInspector.ResourcesPanel = function()
31 {
32 WebInspector.Panel.call(this);
33
34 this.element.addStyleClass("resources");
35
36 this.filterBarElement = document.createElement("div");
37 this.filterBarElement.id = "resources-filter";
38 this.element.appendChild(this.filterBarElement);
39
40 this.viewsContainerElement = document.createElement("div");
41 this.viewsContainerElement.id = "resource-views";
42 this.element.appendChild(this.viewsContainerElement);
43
44 this.containerElement = document.createElement("div");
45 this.containerElement.id = "resources-container";
46 this.containerElement.addEventListener("scroll", this._updateDividersLabelBa rPosition.bind(this), false);
47 this.element.appendChild(this.containerElement);
48
49 this.sidebarElement = document.createElement("div");
50 this.sidebarElement.id = "resources-sidebar";
51 this.sidebarElement.className = "sidebar";
52 this.containerElement.appendChild(this.sidebarElement);
53
54 this.sidebarResizeElement = document.createElement("div");
55 this.sidebarResizeElement.className = "sidebar-resizer-vertical";
56 this.sidebarResizeElement.addEventListener("mousedown", this._startSidebarDr agging.bind(this), false);
57 this.element.appendChild(this.sidebarResizeElement);
58
59 this.containerContentElement = document.createElement("div");
60 this.containerContentElement.id = "resources-container-content";
61 this.containerElement.appendChild(this.containerContentElement);
62
63 this.summaryBar = new WebInspector.SummaryBar(this.categories);
64 this.summaryBar.element.id = "resources-summary";
65 this.containerContentElement.appendChild(this.summaryBar.element);
66
67 this.resourcesGraphsElement = document.createElement("div");
68 this.resourcesGraphsElement.id = "resources-graphs";
69 this.containerContentElement.appendChild(this.resourcesGraphsElement);
70
71 this.dividersElement = document.createElement("div");
72 this.dividersElement.id = "resources-dividers";
73 this.containerContentElement.appendChild(this.dividersElement);
74
75 this.dividersLabelBarElement = document.createElement("div");
76 this.dividersLabelBarElement.id = "resources-dividers-label-bar";
77 this.containerContentElement.appendChild(this.dividersLabelBarElement);
78
79 this.sidebarTreeElement = document.createElement("ol");
80 this.sidebarTreeElement.className = "sidebar-tree";
81 this.sidebarElement.appendChild(this.sidebarTreeElement);
82
83 this.sidebarTree = new TreeOutline(this.sidebarTreeElement);
84
85 var timeGraphItem = new WebInspector.SidebarTreeElement("resources-time-grap h-sidebar-item", WebInspector.UIString("Time"));
86 timeGraphItem.onselect = this._graphSelected.bind(this);
87
88 var transferTimeCalculator = new WebInspector.ResourceTransferTimeCalculator ();
89 var transferDurationCalculator = new WebInspector.ResourceTransferDurationCa lculator();
90
91 timeGraphItem.sortingOptions = [
92 { name: WebInspector.UIString("Sort by Start Time"), sortingFunction: We bInspector.ResourceSidebarTreeElement.CompareByAscendingStartTime, calculator: t ransferTimeCalculator },
93 { name: WebInspector.UIString("Sort by Response Time"), sortingFunction: WebInspector.ResourceSidebarTreeElement.CompareByAscendingResponseReceivedTime, calculator: transferTimeCalculator },
94 { name: WebInspector.UIString("Sort by End Time"), sortingFunction: WebI nspector.ResourceSidebarTreeElement.CompareByAscendingEndTime, calculator: trans ferTimeCalculator },
95 { name: WebInspector.UIString("Sort by Duration"), sortingFunction: WebI nspector.ResourceSidebarTreeElement.CompareByDescendingDuration, calculator: tra nsferDurationCalculator },
96 { name: WebInspector.UIString("Sort by Latency"), sortingFunction: WebIn spector.ResourceSidebarTreeElement.CompareByDescendingLatency, calculator: trans ferDurationCalculator },
97 ];
98
99 timeGraphItem.selectedSortingOptionIndex = 1;
100
101 var sizeGraphItem = new WebInspector.SidebarTreeElement("resources-size-grap h-sidebar-item", WebInspector.UIString("Size"));
102 sizeGraphItem.onselect = this._graphSelected.bind(this);
103
104 var transferSizeCalculator = new WebInspector.ResourceTransferSizeCalculator ();
105 sizeGraphItem.sortingOptions = [
106 { name: WebInspector.UIString("Sort by Size"), sortingFunction: WebInspe ctor.ResourceSidebarTreeElement.CompareByDescendingSize, calculator: transferSiz eCalculator },
107 ];
108
109 sizeGraphItem.selectedSortingOptionIndex = 0;
110
111 this.graphsTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspe ctor.UIString("GRAPHS"), {}, true);
112 this.sidebarTree.appendChild(this.graphsTreeElement);
113
114 this.graphsTreeElement.appendChild(timeGraphItem);
115 this.graphsTreeElement.appendChild(sizeGraphItem);
116 this.graphsTreeElement.expand();
117
118 this.resourcesTreeElement = new WebInspector.SidebarSectionTreeElement(WebIn spector.UIString("RESOURCES"), {}, true);
119 this.sidebarTree.appendChild(this.resourcesTreeElement);
120
121 this.resourcesTreeElement.expand();
122
123 var panelEnablerHeading = WebInspector.UIString("You need to enable resource tracking to use this panel.");
124 var panelEnablerDisclaimer = WebInspector.UIString("Enabling resource tracki ng will reload the page and make page loading slower.");
125 var panelEnablerButton = WebInspector.UIString("Enable resource tracking");
126
127 this.panelEnablerView = new WebInspector.PanelEnablerView("resources", panel EnablerHeading, panelEnablerDisclaimer, panelEnablerButton);
128 this.panelEnablerView.addEventListener("enable clicked", this._enableResourc eTracking, this);
129
130 this.element.appendChild(this.panelEnablerView.element);
131
132 this.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggl e-status-bar-item");
133 this.enableToggleButton.addEventListener("click", this._toggleResourceTracki ng.bind(this), false);
134
135 this.largerResourcesButton = new WebInspector.StatusBarButton(WebInspector.U IString("Use small resource rows."), "resources-larger-resources-status-bar-item ");
136 this.largerResourcesButton.toggled = true;
137 this.largerResourcesButton.addEventListener("click", this._toggleLargerResou rces.bind(this), false);
138
139 this.sortingSelectElement = document.createElement("select");
140 this.sortingSelectElement.className = "status-bar-item";
141 this.sortingSelectElement.addEventListener("change", this._changeSortingFunc tion.bind(this), false);
142
143 var createFilterElement = function (category) {
144 var categoryElement = document.createElement("li");
145 categoryElement.category = category;
146 categoryElement.addStyleClass(category);
147 var label = WebInspector.UIString("All");
148 if (WebInspector.resourceCategories[category])
149 label = WebInspector.resourceCategories[category].title;
150 categoryElement.appendChild(document.createTextNode(label));
151 categoryElement.addEventListener("click", this._updateFilter.bind(this), false);
152 this.filterBarElement.appendChild(categoryElement);
153 return categoryElement;
154 };
155
156 var allElement = createFilterElement.call(this, "all");
157 this.filter(allElement.category);
158 for (var category in this.categories)
159 createFilterElement.call(this, category);
160
161 this.reset();
162
163 timeGraphItem.select();
164 }
165
166 WebInspector.ResourcesPanel.prototype = {
167 toolbarItemClass: "resources",
168
169 get categories()
170 {
171 if (!this._categories) {
172 this._categories = {documents: {color: {r: 47, g: 102, b: 236}}, sty lesheets: {color: {r: 157, g: 231, b: 119}}, images: {color: {r: 164, g: 60, b: 255}}, scripts: {color: {r: 255, g: 121, b: 0}}, xhr: {color: {r: 231, g: 231, b : 10}}, fonts: {color: {r: 255, g: 82, b: 62}}, other: {color: {r: 186, g: 186, b: 186}}};
173 for (var category in this._categories) {
174 this._categories[category].title = WebInspector.resourceCategori es[category].title;
175 }
176 }
177 return this._categories;
178 },
179
180 filter: function (category) {
181 if (this._filterCategory && this._filterCategory === category)
182 return;
183
184 if (this._filterCategory) {
185 var filterElement = this.filterBarElement.getElementsByClassName(thi s._filterCategory)[0];
186 filterElement.removeStyleClass("selected");
187 var oldClass = "filter-" + this._filterCategory;
188 this.resourcesTreeElement.childrenListElement.removeStyleClass(oldCl ass);
189 this.resourcesGraphsElement.removeStyleClass(oldClass);
190 }
191 this._filterCategory = category;
192 var filterElement = this.filterBarElement.getElementsByClassName(this._f ilterCategory)[0];
193 filterElement.addStyleClass("selected");
194 var newClass = "filter-" + this._filterCategory;
195 this.resourcesTreeElement.childrenListElement.addStyleClass(newClass);
196 this.resourcesGraphsElement.addStyleClass(newClass);
197 },
198
199 _updateFilter: function (e) {
200 this.filter(e.target.category);
201 },
202
203 get toolbarItemLabel()
204 {
205 return WebInspector.UIString("Resources");
206 },
207
208 get statusBarItems()
209 {
210 return [this.enableToggleButton.element, this.largerResourcesButton.elem ent, this.sortingSelectElement];
211 },
212
213 show: function()
214 {
215 WebInspector.Panel.prototype.show.call(this);
216
217 this._updateDividersLabelBarPosition();
218 this._updateSidebarWidth();
219 this.refreshIfNeeded();
220
221 var visibleView = this.visibleView;
222 if (visibleView) {
223 visibleView.headersVisible = true;
224 visibleView.show(this.viewsContainerElement);
225 }
226
227 // Hide any views that are visible that are not this panel's current vis ible view.
228 // This can happen when a ResourceView is visible in the Scripts panel t hen switched
229 // to the this panel.
230 var resourcesLength = this._resources.length;
231 for (var i = 0; i < resourcesLength; ++i) {
232 var resource = this._resources[i];
233 var view = resource._resourcesView;
234 if (!view || view === visibleView)
235 continue;
236 view.visible = false;
237 }
238 },
239
240 resize: function()
241 {
242 this._updateGraphDividersIfNeeded();
243
244 var visibleView = this.visibleView;
245 if (visibleView && "resize" in visibleView)
246 visibleView.resize();
247 },
248
249 get searchableViews()
250 {
251 var views = [];
252
253 const visibleView = this.visibleView;
254 if (visibleView && visibleView.performSearch)
255 views.push(visibleView);
256
257 var resourcesLength = this._resources.length;
258 for (var i = 0; i < resourcesLength; ++i) {
259 var resource = this._resources[i];
260 if (!resource._resourcesTreeElement)
261 continue;
262 var resourceView = this.resourceViewForResource(resource);
263 if (!resourceView.performSearch || resourceView === visibleView)
264 continue;
265 views.push(resourceView);
266 }
267
268 return views;
269 },
270
271 get searchResultsSortFunction()
272 {
273 const resourceTreeElementSortFunction = this.sortingFunction;
274
275 function sortFuction(a, b)
276 {
277 return resourceTreeElementSortFunction(a.resource._resourcesTreeElem ent, b.resource._resourcesTreeElement);
278 }
279
280 return sortFuction;
281 },
282
283 searchMatchFound: function(view, matches)
284 {
285 view.resource._resourcesTreeElement.searchMatches = matches;
286 },
287
288 searchCanceled: function(startingNewSearch)
289 {
290 WebInspector.Panel.prototype.searchCanceled.call(this, startingNewSearch );
291
292 if (startingNewSearch || !this._resources)
293 return;
294
295 for (var i = 0; i < this._resources.length; ++i) {
296 var resource = this._resources[i];
297 if (resource._resourcesTreeElement)
298 resource._resourcesTreeElement.updateErrorsAndWarnings();
299 }
300 },
301
302 performSearch: function(query)
303 {
304 for (var i = 0; i < this._resources.length; ++i) {
305 var resource = this._resources[i];
306 if (resource._resourcesTreeElement)
307 resource._resourcesTreeElement.resetBubble();
308 }
309
310 WebInspector.Panel.prototype.performSearch.call(this, query);
311 },
312
313 get visibleView()
314 {
315 if (this.visibleResource)
316 return this.visibleResource._resourcesView;
317 return null;
318 },
319
320 get calculator()
321 {
322 return this._calculator;
323 },
324
325 set calculator(x)
326 {
327 if (!x || this._calculator === x)
328 return;
329
330 this._calculator = x;
331 this._calculator.reset();
332
333 this._staleResources = this._resources;
334 this.refresh();
335 },
336
337 get sortingFunction()
338 {
339 return this._sortingFunction;
340 },
341
342 set sortingFunction(x)
343 {
344 this._sortingFunction = x;
345 this._sortResourcesIfNeeded();
346 },
347
348 get needsRefresh()
349 {
350 return this._needsRefresh;
351 },
352
353 set needsRefresh(x)
354 {
355 if (this._needsRefresh === x)
356 return;
357
358 this._needsRefresh = x;
359
360 if (x) {
361 if (this.visible && !("_refreshTimeout" in this))
362 this._refreshTimeout = setTimeout(this.refresh.bind(this), 500);
363 } else {
364 if ("_refreshTimeout" in this) {
365 clearTimeout(this._refreshTimeout);
366 delete this._refreshTimeout;
367 }
368 }
369 },
370
371 refreshIfNeeded: function()
372 {
373 if (this.needsRefresh)
374 this.refresh();
375 },
376
377 refresh: function()
378 {
379 this.needsRefresh = false;
380
381 var staleResourcesLength = this._staleResources.length;
382 var boundariesChanged = false;
383
384 for (var i = 0; i < staleResourcesLength; ++i) {
385 var resource = this._staleResources[i];
386 if (!resource._resourcesTreeElement) {
387 // Create the resource tree element and graph.
388 resource._resourcesTreeElement = new WebInspector.ResourceSideba rTreeElement(resource);
389 resource._resourcesTreeElement._resourceGraph = new WebInspector .ResourceGraph(resource);
390
391 this.resourcesTreeElement.appendChild(resource._resourcesTreeEle ment);
392 this.resourcesGraphsElement.appendChild(resource._resourcesTreeE lement._resourceGraph.graphElement);
393 }
394
395 resource._resourcesTreeElement.refresh();
396
397 if (this.calculator.updateBoundaries(resource))
398 boundariesChanged = true;
399 }
400
401 if (boundariesChanged) {
402 // The boundaries changed, so all resource graphs are stale.
403 this._staleResources = this._resources;
404 staleResourcesLength = this._staleResources.length;
405 }
406
407 for (var i = 0; i < staleResourcesLength; ++i)
408 this._staleResources[i]._resourcesTreeElement._resourceGraph.refresh (this.calculator);
409
410 this._staleResources = [];
411
412 this._updateGraphDividersIfNeeded();
413 this._sortResourcesIfNeeded();
414 this._updateSummaryGraph();
415 },
416
417 resourceTrackingWasEnabled: function()
418 {
419 this.reset();
420 },
421
422 resourceTrackingWasDisabled: function()
423 {
424 this.reset();
425 },
426
427 reset: function()
428 {
429 this.closeVisibleResource();
430
431 this.containerElement.scrollTop = 0;
432
433 delete this.currentQuery;
434 this.searchCanceled();
435
436 if (this._calculator)
437 this._calculator.reset();
438
439 if (this._resources) {
440 var resourcesLength = this._resources.length;
441 for (var i = 0; i < resourcesLength; ++i) {
442 var resource = this._resources[i];
443
444 resource.warnings = 0;
445 resource.errors = 0;
446
447 delete resource._resourcesTreeElement;
448 delete resource._resourcesView;
449 }
450 }
451
452 this._resources = [];
453 this._staleResources = [];
454
455 this.resourcesTreeElement.removeChildren();
456 this.viewsContainerElement.removeChildren();
457 this.resourcesGraphsElement.removeChildren();
458 this.summaryBar.reset();
459
460 this._updateGraphDividersIfNeeded(true);
461
462 if (InspectorController.resourceTrackingEnabled()) {
463 this.enableToggleButton.title = WebInspector.UIString("Resource trac king enabled. Click to disable.");
464 this.enableToggleButton.toggled = true;
465 this.largerResourcesButton.visible = true;
466 this.sortingSelectElement.removeStyleClass("hidden");
467 this.panelEnablerView.visible = false;
468 } else {
469 this.enableToggleButton.title = WebInspector.UIString("Resource trac king disabled. Click to enable.");
470 this.enableToggleButton.toggled = false;
471 this.largerResourcesButton.visible = false;
472 this.sortingSelectElement.addStyleClass("hidden");
473 this.panelEnablerView.visible = true;
474 }
475 },
476
477 addResource: function(resource)
478 {
479 this._resources.push(resource);
480 this.refreshResource(resource);
481 },
482
483 removeResource: function(resource)
484 {
485 if (this.visibleView === resource._resourcesView)
486 this.closeVisibleResource();
487
488 this._resources.remove(resource, true);
489
490 if (resource._resourcesTreeElement) {
491 this.resourcesTreeElement.removeChild(resource._resourcesTreeElement );
492 this.resourcesGraphsElement.removeChild(resource._resourcesTreeEleme nt._resourceGraph.graphElement);
493 }
494
495 resource.warnings = 0;
496 resource.errors = 0;
497
498 delete resource._resourcesTreeElement;
499 delete resource._resourcesView;
500
501 this._adjustScrollPosition();
502 },
503
504 addMessageToResource: function(resource, msg)
505 {
506 if (!resource)
507 return;
508
509 switch (msg.level) {
510 case WebInspector.ConsoleMessage.MessageLevel.Warning:
511 resource.warnings += msg.repeatDelta;
512 break;
513 case WebInspector.ConsoleMessage.MessageLevel.Error:
514 resource.errors += msg.repeatDelta;
515 break;
516 }
517
518 if (!this.currentQuery && resource._resourcesTreeElement)
519 resource._resourcesTreeElement.updateErrorsAndWarnings();
520
521 var view = this.resourceViewForResource(resource);
522 if (view.addMessage)
523 view.addMessage(msg);
524 },
525
526 clearMessages: function()
527 {
528 var resourcesLength = this._resources.length;
529 for (var i = 0; i < resourcesLength; ++i) {
530 var resource = this._resources[i];
531 resource.warnings = 0;
532 resource.errors = 0;
533
534 if (!this.currentQuery && resource._resourcesTreeElement)
535 resource._resourcesTreeElement.updateErrorsAndWarnings();
536
537 var view = resource._resourcesView;
538 if (!view || !view.clearMessages)
539 continue;
540 view.clearMessages();
541 }
542 },
543
544 refreshResource: function(resource)
545 {
546 this._staleResources.push(resource);
547 this.needsRefresh = true;
548 },
549
550 recreateViewForResourceIfNeeded: function(resource)
551 {
552 if (!resource || !resource._resourcesView)
553 return;
554
555 var newView = this._createResourceView(resource);
556 if (newView.prototype === resource._resourcesView.prototype)
557 return;
558
559 resource.warnings = 0;
560 resource.errors = 0;
561
562 if (!this.currentQuery && resource._resourcesTreeElement)
563 resource._resourcesTreeElement.updateErrorsAndWarnings();
564
565 var oldView = resource._resourcesView;
566
567 resource._resourcesView.detach();
568 delete resource._resourcesView;
569
570 resource._resourcesView = newView;
571
572 newView.headersVisible = oldView.headersVisible;
573
574 if (oldView.visible && oldView.element.parentNode)
575 newView.show(oldView.element.parentNode);
576 },
577
578 showResource: function(resource, line)
579 {
580 if (!resource)
581 return;
582
583 this.containerElement.addStyleClass("viewing-resource");
584
585 if (this.visibleResource && this.visibleResource._resourcesView)
586 this.visibleResource._resourcesView.hide();
587
588 var view = this.resourceViewForResource(resource);
589 view.headersVisible = true;
590 view.show(this.viewsContainerElement);
591
592 if (line) {
593 if (view.revealLine)
594 view.revealLine(line);
595 if (view.highlightLine)
596 view.highlightLine(line);
597 }
598
599 if (resource._resourcesTreeElement) {
600 resource._resourcesTreeElement.reveal();
601 resource._resourcesTreeElement.select(true);
602 }
603
604 this.visibleResource = resource;
605
606 this._updateSidebarWidth();
607 },
608
609 showView: function(view)
610 {
611 if (!view)
612 return;
613 this.showResource(view.resource);
614 },
615
616 closeVisibleResource: function()
617 {
618 this.containerElement.removeStyleClass("viewing-resource");
619 this._updateDividersLabelBarPosition();
620
621 if (this.visibleResource && this.visibleResource._resourcesView)
622 this.visibleResource._resourcesView.hide();
623 delete this.visibleResource;
624
625 if (this._lastSelectedGraphTreeElement)
626 this._lastSelectedGraphTreeElement.select(true);
627
628 this._updateSidebarWidth();
629 },
630
631 resourceViewForResource: function(resource)
632 {
633 if (!resource)
634 return null;
635 if (!resource._resourcesView)
636 resource._resourcesView = this._createResourceView(resource);
637 return resource._resourcesView;
638 },
639
640 sourceFrameForResource: function(resource)
641 {
642 var view = this.resourceViewForResource(resource);
643 if (!view)
644 return null;
645
646 if (!view.setupSourceFrameIfNeeded)
647 return null;
648
649 // Setting up the source frame requires that we be attached.
650 if (!this.element.parentNode)
651 this.attach();
652
653 view.setupSourceFrameIfNeeded();
654 return view.sourceFrame;
655 },
656
657 handleKeyEvent: function(event)
658 {
659 this.sidebarTree.handleKeyEvent(event);
660 },
661
662 _sortResourcesIfNeeded: function()
663 {
664 var sortedElements = [].concat(this.resourcesTreeElement.children);
665 sortedElements.sort(this.sortingFunction);
666
667 var sortedElementsLength = sortedElements.length;
668 for (var i = 0; i < sortedElementsLength; ++i) {
669 var treeElement = sortedElements[i];
670 if (treeElement === this.resourcesTreeElement.children[i])
671 continue;
672
673 var wasSelected = treeElement.selected;
674 this.resourcesTreeElement.removeChild(treeElement);
675 this.resourcesTreeElement.insertChild(treeElement, i);
676 if (wasSelected)
677 treeElement.select(true);
678
679 var graphElement = treeElement._resourceGraph.graphElement;
680 this.resourcesGraphsElement.insertBefore(graphElement, this.resource sGraphsElement.children[i]);
681 }
682 },
683
684 _updateGraphDividersIfNeeded: function(force)
685 {
686 if (!this.visible) {
687 this.needsRefresh = true;
688 return;
689 }
690
691 if (document.body.offsetWidth <= 0) {
692 // The stylesheet hasn't loaded yet or the window is closed,
693 // so we can't calculate what is need. Return early.
694 return;
695 }
696
697 var dividerCount = Math.round(this.dividersElement.offsetWidth / 64);
698 var slice = this.calculator.boundarySpan / dividerCount;
699 if (!force && this._currentDividerSlice === slice)
700 return;
701
702 this._currentDividerSlice = slice;
703
704 this.dividersElement.removeChildren();
705 this.dividersLabelBarElement.removeChildren();
706
707 for (var i = 1; i <= dividerCount; ++i) {
708 var divider = document.createElement("div");
709 divider.className = "resources-divider";
710 if (i === dividerCount)
711 divider.addStyleClass("last");
712 divider.style.left = ((i / dividerCount) * 100) + "%";
713
714 this.dividersElement.appendChild(divider.cloneNode());
715
716 var label = document.createElement("div");
717 label.className = "resources-divider-label";
718 if (!isNaN(slice))
719 label.textContent = this.calculator.formatValue(slice * i);
720 divider.appendChild(label);
721
722 this.dividersLabelBarElement.appendChild(divider);
723 }
724 },
725
726 _updateSummaryGraph: function()
727 {
728 this.summaryBar.update(this._resources);
729 },
730
731 _updateDividersLabelBarPosition: function()
732 {
733 var scrollTop = this.containerElement.scrollTop;
734 var dividersTop = (scrollTop < this.summaryBar.element.offsetHeight ? th is.summaryBar.element.offsetHeight : scrollTop);
735 this.dividersElement.style.top = scrollTop + "px";
736 this.dividersLabelBarElement.style.top = dividersTop + "px";
737 },
738
739 _graphSelected: function(treeElement)
740 {
741 if (this._lastSelectedGraphTreeElement)
742 this._lastSelectedGraphTreeElement.selectedSortingOptionIndex = this .sortingSelectElement.selectedIndex;
743
744 this._lastSelectedGraphTreeElement = treeElement;
745
746 this.sortingSelectElement.removeChildren();
747 for (var i = 0; i < treeElement.sortingOptions.length; ++i) {
748 var sortingOption = treeElement.sortingOptions[i];
749 var option = document.createElement("option");
750 option.label = sortingOption.name;
751 option.sortingFunction = sortingOption.sortingFunction;
752 option.calculator = sortingOption.calculator;
753 this.sortingSelectElement.appendChild(option);
754 }
755
756 this.sortingSelectElement.selectedIndex = treeElement.selectedSortingOpt ionIndex;
757 this._changeSortingFunction();
758
759 this.closeVisibleResource();
760 this.containerElement.scrollTop = 0;
761 },
762
763 _toggleLargerResources: function()
764 {
765 if (!this.resourcesTreeElement._childrenListNode)
766 return;
767
768 this.resourcesTreeElement.smallChildren = !this.resourcesTreeElement.sma llChildren;
769
770 if (this.resourcesTreeElement.smallChildren) {
771 this.resourcesGraphsElement.addStyleClass("small");
772 this.largerResourcesButton.title = WebInspector.UIString("Use large resource rows.");
773 this.largerResourcesButton.toggled = false;
774 this._adjustScrollPosition();
775 } else {
776 this.resourcesGraphsElement.removeStyleClass("small");
777 this.largerResourcesButton.title = WebInspector.UIString("Use small resource rows.");
778 this.largerResourcesButton.toggled = true;
779 }
780 },
781
782 _adjustScrollPosition: function()
783 {
784 // Prevent the container from being scrolled off the end.
785 if ((this.containerElement.scrollTop + this.containerElement.offsetHeigh t) > this.sidebarElement.offsetHeight)
786 this.containerElement.scrollTop = (this.sidebarElement.offsetHeight - this.containerElement.offsetHeight);
787 },
788
789 _changeSortingFunction: function()
790 {
791 var selectedOption = this.sortingSelectElement[this.sortingSelectElement .selectedIndex];
792 this.sortingFunction = selectedOption.sortingFunction;
793 this.calculator = this.summaryBar.calculator = selectedOption.calculator ;
794 },
795
796 _createResourceView: function(resource)
797 {
798 switch (resource.category) {
799 case WebInspector.resourceCategories.documents:
800 case WebInspector.resourceCategories.stylesheets:
801 case WebInspector.resourceCategories.scripts:
802 case WebInspector.resourceCategories.xhr:
803 return new WebInspector.SourceView(resource);
804 case WebInspector.resourceCategories.images:
805 return new WebInspector.ImageView(resource);
806 case WebInspector.resourceCategories.fonts:
807 return new WebInspector.FontView(resource);
808 default:
809 return new WebInspector.ResourceView(resource);
810 }
811 },
812
813 _startSidebarDragging: function(event)
814 {
815 WebInspector.elementDragStart(this.sidebarResizeElement, this._sidebarDr agging.bind(this), this._endSidebarDragging.bind(this), event, "col-resize");
816 },
817
818 _sidebarDragging: function(event)
819 {
820 this._updateSidebarWidth(event.pageX);
821
822 event.preventDefault();
823 },
824
825 _endSidebarDragging: function(event)
826 {
827 WebInspector.elementDragEnd(event);
828 },
829
830 _updateSidebarWidth: function(width)
831 {
832 if (this.sidebarElement.offsetWidth <= 0) {
833 // The stylesheet hasn't loaded yet or the window is closed,
834 // so we can't calculate what is need. Return early.
835 return;
836 }
837
838 if (!("_currentSidebarWidth" in this))
839 this._currentSidebarWidth = this.sidebarElement.offsetWidth;
840
841 if (typeof width === "undefined")
842 width = this._currentSidebarWidth;
843
844 width = Number.constrain(width, Preferences.minSidebarWidth, window.inne rWidth / 2);
845
846 this._currentSidebarWidth = width;
847
848 if (this.visibleResource) {
849 this.containerElement.style.width = width + "px";
850 this.sidebarElement.style.removeProperty("width");
851 } else {
852 this.sidebarElement.style.width = width + "px";
853 this.containerElement.style.removeProperty("width");
854 }
855
856 this.containerContentElement.style.left = width + "px";
857 this.viewsContainerElement.style.left = width + "px";
858 this.sidebarResizeElement.style.left = (width - 3) + "px";
859
860 this._updateGraphDividersIfNeeded();
861
862 var visibleView = this.visibleView;
863 if (visibleView && "resize" in visibleView)
864 visibleView.resize();
865 },
866
867 _enableResourceTracking: function()
868 {
869 if (InspectorController.resourceTrackingEnabled())
870 return;
871 this._toggleResourceTracking(this.panelEnablerView.alwaysEnabled);
872 },
873
874 _toggleResourceTracking: function(optionalAlways)
875 {
876 if (InspectorController.resourceTrackingEnabled()) {
877 this.largerResourcesButton.visible = false;
878 this.sortingSelectElement.visible = false;
879 InspectorController.disableResourceTracking(true);
880 } else {
881 this.largerResourcesButton.visible = true;
882 this.sortingSelectElement.visible = true;
883 InspectorController.enableResourceTracking(!!optionalAlways);
884 }
885 }
886 }
887
888 WebInspector.ResourcesPanel.prototype.__proto__ = WebInspector.Panel.prototype;
889
890 WebInspector.ResourceCalculator = function()
891 {
892 }
893
894 WebInspector.ResourceCalculator.prototype = {
895 computeSummaryValues: function(resources)
896 {
897 var total = 0;
898 var categoryValues = {};
899
900 var resourcesLength = resources.length;
901 for (var i = 0; i < resourcesLength; ++i) {
902 var resource = resources[i];
903 var value = this._value(resource);
904 if (typeof value === "undefined")
905 continue;
906 if (!(resource.category.name in categoryValues))
907 categoryValues[resource.category.name] = 0;
908 categoryValues[resource.category.name] += value;
909 total += value;
910 }
911
912 return {categoryValues: categoryValues, total: total};
913 },
914
915 computeBarGraphPercentages: function(resource)
916 {
917 return {start: 0, middle: 0, end: (this._value(resource) / this.boundary Span) * 100};
918 },
919
920 computeBarGraphLabels: function(resource)
921 {
922 const label = this.formatValue(this._value(resource));
923 var tooltip = label;
924 if (resource.cached)
925 tooltip = WebInspector.UIString("%s (from cache)", tooltip);
926 return {left: label, right: label, tooltip: tooltip};
927 },
928
929 get boundarySpan()
930 {
931 return this.maximumBoundary - this.minimumBoundary;
932 },
933
934 updateBoundaries: function(resource)
935 {
936 this.minimumBoundary = 0;
937
938 var value = this._value(resource);
939 if (typeof this.maximumBoundary === "undefined" || value > this.maximumB oundary) {
940 this.maximumBoundary = value;
941 return true;
942 }
943
944 return false;
945 },
946
947 reset: function()
948 {
949 delete this.minimumBoundary;
950 delete this.maximumBoundary;
951 },
952
953 _value: function(resource)
954 {
955 return 0;
956 },
957
958 formatValue: function(value)
959 {
960 return value.toString();
961 }
962 }
963
964 WebInspector.ResourceTimeCalculator = function(startAtZero)
965 {
966 WebInspector.ResourceCalculator.call(this);
967 this.startAtZero = startAtZero;
968 }
969
970 WebInspector.ResourceTimeCalculator.prototype = {
971 computeSummaryValues: function(resources)
972 {
973 var resourcesByCategory = {};
974 var resourcesLength = resources.length;
975 for (var i = 0; i < resourcesLength; ++i) {
976 var resource = resources[i];
977 if (!(resource.category.name in resourcesByCategory))
978 resourcesByCategory[resource.category.name] = [];
979 resourcesByCategory[resource.category.name].push(resource);
980 }
981
982 var earliestStart;
983 var latestEnd;
984 var categoryValues = {};
985 for (var category in resourcesByCategory) {
986 resourcesByCategory[category].sort(WebInspector.Resource.CompareByTi me);
987 categoryValues[category] = 0;
988
989 var segment = {start: -1, end: -1};
990
991 var categoryResources = resourcesByCategory[category];
992 var resourcesLength = categoryResources.length;
993 for (var i = 0; i < resourcesLength; ++i) {
994 var resource = categoryResources[i];
995 if (resource.startTime === -1 || resource.endTime === -1)
996 continue;
997
998 if (typeof earliestStart === "undefined")
999 earliestStart = resource.startTime;
1000 else
1001 earliestStart = Math.min(earliestStart, resource.startTime);
1002
1003 if (typeof latestEnd === "undefined")
1004 latestEnd = resource.endTime;
1005 else
1006 latestEnd = Math.max(latestEnd, resource.endTime);
1007
1008 if (resource.startTime <= segment.end) {
1009 segment.end = Math.max(segment.end, resource.endTime);
1010 continue;
1011 }
1012
1013 categoryValues[category] += segment.end - segment.start;
1014
1015 segment.start = resource.startTime;
1016 segment.end = resource.endTime;
1017 }
1018
1019 // Add the last segment
1020 categoryValues[category] += segment.end - segment.start;
1021 }
1022
1023 return {categoryValues: categoryValues, total: latestEnd - earliestStart };
1024 },
1025
1026 computeBarGraphPercentages: function(resource)
1027 {
1028 if (resource.startTime !== -1)
1029 var start = ((resource.startTime - this.minimumBoundary) / this.boun darySpan) * 100;
1030 else
1031 var start = 0;
1032
1033 if (resource.responseReceivedTime !== -1)
1034 var middle = ((resource.responseReceivedTime - this.minimumBoundary) / this.boundarySpan) * 100;
1035 else
1036 var middle = (this.startAtZero ? start : 100);
1037
1038 if (resource.endTime !== -1)
1039 var end = ((resource.endTime - this.minimumBoundary) / this.boundary Span) * 100;
1040 else
1041 var end = (this.startAtZero ? middle : 100);
1042
1043 if (this.startAtZero) {
1044 end -= start;
1045 middle -= start;
1046 start = 0;
1047 }
1048
1049 return {start: start, middle: middle, end: end};
1050 },
1051
1052 computeBarGraphLabels: function(resource)
1053 {
1054 var leftLabel = "";
1055 if (resource.latency > 0)
1056 leftLabel = this.formatValue(resource.latency);
1057
1058 var rightLabel = "";
1059 if (resource.responseReceivedTime !== -1 && resource.endTime !== -1)
1060 rightLabel = this.formatValue(resource.endTime - resource.responseRe ceivedTime);
1061
1062 if (leftLabel && rightLabel) {
1063 var total = this.formatValue(resource.duration);
1064 var tooltip = WebInspector.UIString("%s latency, %s download (%s tot al)", leftLabel, rightLabel, total);
1065 } else if (leftLabel)
1066 var tooltip = WebInspector.UIString("%s latency", leftLabel);
1067 else if (rightLabel)
1068 var tooltip = WebInspector.UIString("%s download", rightLabel);
1069
1070 if (resource.cached)
1071 tooltip = WebInspector.UIString("%s (from cache)", tooltip);
1072
1073 return {left: leftLabel, right: rightLabel, tooltip: tooltip};
1074 },
1075
1076 updateBoundaries: function(resource)
1077 {
1078 var didChange = false;
1079
1080 var lowerBound;
1081 if (this.startAtZero)
1082 lowerBound = 0;
1083 else
1084 lowerBound = this._lowerBound(resource);
1085
1086 if (lowerBound !== -1 && (typeof this.minimumBoundary === "undefined" || lowerBound < this.minimumBoundary)) {
1087 this.minimumBoundary = lowerBound;
1088 didChange = true;
1089 }
1090
1091 var upperBound = this._upperBound(resource);
1092 if (upperBound !== -1 && (typeof this.maximumBoundary === "undefined" || upperBound > this.maximumBoundary)) {
1093 this.maximumBoundary = upperBound;
1094 didChange = true;
1095 }
1096
1097 return didChange;
1098 },
1099
1100 formatValue: function(value)
1101 {
1102 return Number.secondsToString(value, WebInspector.UIString.bind(WebInspe ctor));
1103 },
1104
1105 _lowerBound: function(resource)
1106 {
1107 return 0;
1108 },
1109
1110 _upperBound: function(resource)
1111 {
1112 return 0;
1113 },
1114 }
1115
1116 WebInspector.ResourceTimeCalculator.prototype.__proto__ = WebInspector.ResourceC alculator.prototype;
1117
1118 WebInspector.ResourceTransferTimeCalculator = function()
1119 {
1120 WebInspector.ResourceTimeCalculator.call(this, false);
1121 }
1122
1123 WebInspector.ResourceTransferTimeCalculator.prototype = {
1124 formatValue: function(value)
1125 {
1126 return Number.secondsToString(value, WebInspector.UIString.bind(WebInspe ctor));
1127 },
1128
1129 _lowerBound: function(resource)
1130 {
1131 return resource.startTime;
1132 },
1133
1134 _upperBound: function(resource)
1135 {
1136 return resource.endTime;
1137 }
1138 }
1139
1140 WebInspector.ResourceTransferTimeCalculator.prototype.__proto__ = WebInspector.R esourceTimeCalculator.prototype;
1141
1142 WebInspector.ResourceTransferDurationCalculator = function()
1143 {
1144 WebInspector.ResourceTimeCalculator.call(this, true);
1145 }
1146
1147 WebInspector.ResourceTransferDurationCalculator.prototype = {
1148 formatValue: function(value)
1149 {
1150 return Number.secondsToString(value, WebInspector.UIString.bind(WebInspe ctor));
1151 },
1152
1153 _upperBound: function(resource)
1154 {
1155 return resource.duration;
1156 }
1157 }
1158
1159 WebInspector.ResourceTransferDurationCalculator.prototype.__proto__ = WebInspect or.ResourceTimeCalculator.prototype;
1160
1161 WebInspector.ResourceTransferSizeCalculator = function()
1162 {
1163 WebInspector.ResourceCalculator.call(this);
1164 }
1165
1166 WebInspector.ResourceTransferSizeCalculator.prototype = {
1167 _value: function(resource)
1168 {
1169 return resource.contentLength;
1170 },
1171
1172 formatValue: function(value)
1173 {
1174 return Number.bytesToString(value, WebInspector.UIString.bind(WebInspect or));
1175 }
1176 }
1177
1178 WebInspector.ResourceTransferSizeCalculator.prototype.__proto__ = WebInspector.R esourceCalculator.prototype;
1179
1180 WebInspector.ResourceSidebarTreeElement = function(resource)
1181 {
1182 this.resource = resource;
1183
1184 this.createIconElement();
1185
1186 WebInspector.SidebarTreeElement.call(this, "resource-sidebar-tree-item", "", "", resource);
1187
1188 this.refreshTitles();
1189 }
1190
1191 WebInspector.ResourceSidebarTreeElement.prototype = {
1192 onattach: function()
1193 {
1194 WebInspector.SidebarTreeElement.prototype.onattach.call(this);
1195
1196 var link = document.createElement("a");
1197 link.href = this.resource.url;
1198 link.className = "invisible";
1199 while (this._listItemNode.firstChild)
1200 link.appendChild(this._listItemNode.firstChild);
1201 this._listItemNode.appendChild(link);
1202 this._listItemNode.addStyleClass("resources-category-" + this.resource.c ategory.name);
1203 },
1204
1205 onselect: function()
1206 {
1207 WebInspector.panels.resources.showResource(this.resource);
1208 },
1209
1210 ondblclick: function(treeElement, event)
1211 {
1212 InjectedScriptAccess.openInInspectedWindow(this.resource.url);
1213 },
1214
1215 get mainTitle()
1216 {
1217 return this.resource.displayName;
1218 },
1219
1220 set mainTitle(x)
1221 {
1222 // Do nothing.
1223 },
1224
1225 get subtitle()
1226 {
1227 var subtitle = this.resource.displayDomain;
1228
1229 if (this.resource.path && this.resource.lastPathComponent) {
1230 var lastPathComponentIndex = this.resource.path.lastIndexOf("/" + th is.resource.lastPathComponent);
1231 if (lastPathComponentIndex != -1)
1232 subtitle += this.resource.path.substring(0, lastPathComponentInd ex);
1233 }
1234
1235 return subtitle;
1236 },
1237
1238 set subtitle(x)
1239 {
1240 // Do nothing.
1241 },
1242
1243 get selectable()
1244 {
1245 return WebInspector.panels.resources._filterCategory == "all" || WebInsp ector.panels.resources._filterCategory == this.resource.category.name;
1246 },
1247
1248 createIconElement: function()
1249 {
1250 var previousIconElement = this.iconElement;
1251
1252 if (this.resource.category === WebInspector.resourceCategories.images) {
1253 var previewImage = document.createElement("img");
1254 previewImage.className = "image-resource-icon-preview";
1255 previewImage.src = this.resource.url;
1256
1257 this.iconElement = document.createElement("div");
1258 this.iconElement.className = "icon";
1259 this.iconElement.appendChild(previewImage);
1260 } else {
1261 this.iconElement = document.createElement("img");
1262 this.iconElement.className = "icon";
1263 }
1264
1265 if (previousIconElement)
1266 previousIconElement.parentNode.replaceChild(this.iconElement, previo usIconElement);
1267 },
1268
1269 refresh: function()
1270 {
1271 this.refreshTitles();
1272
1273 if (!this._listItemNode.hasStyleClass("resources-category-" + this.resou rce.category.name)) {
1274 this._listItemNode.removeMatchingStyleClasses("resources-category-\\ w+");
1275 this._listItemNode.addStyleClass("resources-category-" + this.resour ce.category.name);
1276
1277 this.createIconElement();
1278 }
1279 },
1280
1281 resetBubble: function()
1282 {
1283 this.bubbleText = "";
1284 this.bubbleElement.removeStyleClass("search-matches");
1285 this.bubbleElement.removeStyleClass("warning");
1286 this.bubbleElement.removeStyleClass("error");
1287 },
1288
1289 set searchMatches(matches)
1290 {
1291 this.resetBubble();
1292
1293 if (!matches)
1294 return;
1295
1296 this.bubbleText = matches;
1297 this.bubbleElement.addStyleClass("search-matches");
1298 },
1299
1300 updateErrorsAndWarnings: function()
1301 {
1302 this.resetBubble();
1303
1304 if (this.resource.warnings || this.resource.errors)
1305 this.bubbleText = (this.resource.warnings + this.resource.errors);
1306
1307 if (this.resource.warnings)
1308 this.bubbleElement.addStyleClass("warning");
1309
1310 if (this.resource.errors)
1311 this.bubbleElement.addStyleClass("error");
1312 }
1313 }
1314
1315 WebInspector.ResourceSidebarTreeElement.CompareByAscendingStartTime = function(a , b)
1316 {
1317 return WebInspector.Resource.CompareByStartTime(a.resource, b.resource)
1318 || WebInspector.Resource.CompareByEndTime(a.resource, b.resource)
1319 || WebInspector.Resource.CompareByResponseReceivedTime(a.resource, b.res ource);
1320 }
1321
1322 WebInspector.ResourceSidebarTreeElement.CompareByAscendingResponseReceivedTime = function(a, b)
1323 {
1324 return WebInspector.Resource.CompareByResponseReceivedTime(a.resource, b.res ource)
1325 || WebInspector.Resource.CompareByStartTime(a.resource, b.resource)
1326 || WebInspector.Resource.CompareByEndTime(a.resource, b.resource);
1327 }
1328
1329 WebInspector.ResourceSidebarTreeElement.CompareByAscendingEndTime = function(a, b)
1330 {
1331 return WebInspector.Resource.CompareByEndTime(a.resource, b.resource)
1332 || WebInspector.Resource.CompareByStartTime(a.resource, b.resource)
1333 || WebInspector.Resource.CompareByResponseReceivedTime(a.resource, b.res ource);
1334 }
1335
1336 WebInspector.ResourceSidebarTreeElement.CompareByDescendingDuration = function(a , b)
1337 {
1338 return -1 * WebInspector.Resource.CompareByDuration(a.resource, b.resource);
1339 }
1340
1341 WebInspector.ResourceSidebarTreeElement.CompareByDescendingLatency = function(a, b)
1342 {
1343 return -1 * WebInspector.Resource.CompareByLatency(a.resource, b.resource);
1344 }
1345
1346 WebInspector.ResourceSidebarTreeElement.CompareByDescendingSize = function(a, b)
1347 {
1348 return -1 * WebInspector.Resource.CompareBySize(a.resource, b.resource);
1349 }
1350
1351 WebInspector.ResourceSidebarTreeElement.prototype.__proto__ = WebInspector.Sideb arTreeElement.prototype;
1352
1353 WebInspector.ResourceGraph = function(resource)
1354 {
1355 this.resource = resource;
1356
1357 this._graphElement = document.createElement("div");
1358 this._graphElement.className = "resources-graph-side";
1359 this._graphElement.addEventListener("mouseover", this.refreshLabelPositions. bind(this), false);
1360
1361 if (resource.cached)
1362 this._graphElement.addStyleClass("resource-cached");
1363
1364 this._barAreaElement = document.createElement("div");
1365 this._barAreaElement.className = "resources-graph-bar-area hidden";
1366 this._graphElement.appendChild(this._barAreaElement);
1367
1368 this._barLeftElement = document.createElement("div");
1369 this._barLeftElement.className = "resources-graph-bar waiting";
1370 this._barAreaElement.appendChild(this._barLeftElement);
1371
1372 this._barRightElement = document.createElement("div");
1373 this._barRightElement.className = "resources-graph-bar";
1374 this._barAreaElement.appendChild(this._barRightElement);
1375
1376 this._labelLeftElement = document.createElement("div");
1377 this._labelLeftElement.className = "resources-graph-label waiting";
1378 this._barAreaElement.appendChild(this._labelLeftElement);
1379
1380 this._labelRightElement = document.createElement("div");
1381 this._labelRightElement.className = "resources-graph-label";
1382 this._barAreaElement.appendChild(this._labelRightElement);
1383
1384 this._graphElement.addStyleClass("resources-category-" + resource.category.n ame);
1385 }
1386
1387 WebInspector.ResourceGraph.prototype = {
1388 get graphElement()
1389 {
1390 return this._graphElement;
1391 },
1392
1393 refreshLabelPositions: function()
1394 {
1395 this._labelLeftElement.style.removeProperty("left");
1396 this._labelLeftElement.style.removeProperty("right");
1397 this._labelLeftElement.removeStyleClass("before");
1398 this._labelLeftElement.removeStyleClass("hidden");
1399
1400 this._labelRightElement.style.removeProperty("left");
1401 this._labelRightElement.style.removeProperty("right");
1402 this._labelRightElement.removeStyleClass("after");
1403 this._labelRightElement.removeStyleClass("hidden");
1404
1405 const labelPadding = 10;
1406 const rightBarWidth = (this._barRightElement.offsetWidth - labelPadding) ;
1407 const leftBarWidth = ((this._barLeftElement.offsetWidth - this._barRight Element.offsetWidth) - labelPadding);
1408
1409 var labelBefore = (this._labelLeftElement.offsetWidth > leftBarWidth);
1410 var labelAfter = (this._labelRightElement.offsetWidth > rightBarWidth);
1411
1412 if (labelBefore) {
1413 if ((this._graphElement.offsetWidth * (this._percentages.start / 100 )) < (this._labelLeftElement.offsetWidth + 10))
1414 this._labelLeftElement.addStyleClass("hidden");
1415 this._labelLeftElement.style.setProperty("right", (100 - this._perce ntages.start) + "%");
1416 this._labelLeftElement.addStyleClass("before");
1417 } else {
1418 this._labelLeftElement.style.setProperty("left", this._percentages.s tart + "%");
1419 this._labelLeftElement.style.setProperty("right", (100 - this._perce ntages.middle) + "%");
1420 }
1421
1422 if (labelAfter) {
1423 if ((this._graphElement.offsetWidth * ((100 - this._percentages.end) / 100)) < (this._labelRightElement.offsetWidth + 10))
1424 this._labelRightElement.addStyleClass("hidden");
1425 this._labelRightElement.style.setProperty("left", this._percentages. end + "%");
1426 this._labelRightElement.addStyleClass("after");
1427 } else {
1428 this._labelRightElement.style.setProperty("left", this._percentages. middle + "%");
1429 this._labelRightElement.style.setProperty("right", (100 - this._perc entages.end) + "%");
1430 }
1431 },
1432
1433 refresh: function(calculator)
1434 {
1435 var percentages = calculator.computeBarGraphPercentages(this.resource);
1436 var labels = calculator.computeBarGraphLabels(this.resource);
1437
1438 this._percentages = percentages;
1439
1440 this._barAreaElement.removeStyleClass("hidden");
1441
1442 if (!this._graphElement.hasStyleClass("resources-category-" + this.resou rce.category.name)) {
1443 this._graphElement.removeMatchingStyleClasses("resources-category-\\ w+");
1444 this._graphElement.addStyleClass("resources-category-" + this.resour ce.category.name);
1445 }
1446
1447 this._barLeftElement.style.setProperty("left", percentages.start + "%");
1448 this._barLeftElement.style.setProperty("right", (100 - percentages.end) + "%");
1449
1450 this._barRightElement.style.setProperty("left", percentages.middle + "%" );
1451 this._barRightElement.style.setProperty("right", (100 - percentages.end) + "%");
1452
1453 this._labelLeftElement.textContent = labels.left;
1454 this._labelRightElement.textContent = labels.right;
1455
1456 var tooltip = (labels.tooltip || "");
1457 this._barLeftElement.title = tooltip;
1458 this._labelLeftElement.title = tooltip;
1459 this._labelRightElement.title = tooltip;
1460 this._barRightElement.title = tooltip;
1461 }
1462 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698