2 * Copyright (C) 2013, 2015 Apple 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
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
26 WebInspector.Sidebar = class Sidebar extends WebInspector.Object
28 constructor(element, side, sidebarPanels, role, label)
32 console.assert(!side || side === WebInspector.Sidebar.Sides.Left || side === WebInspector.Sidebar.Sides.Right);
33 this._side = side || WebInspector.Sidebar.Sides.Left;
35 this._element = element || document.createElement("div");
36 this._element.classList.add("sidebar", this._side, WebInspector.Sidebar.CollapsedStyleClassName);
38 this._element.setAttribute("role", role || "group");
40 this._element.setAttribute("aria-label", label);
42 this._resizer = new WebInspector.Resizer(WebInspector.Resizer.RuleOrientation.Vertical, this);
43 this._element.insertBefore(this._resizer.element, this._element.firstChild);
45 this._sidebarPanels = [];
48 for (var i = 0; i < sidebarPanels.length; ++i)
49 this.addSidebarPanel(sidebarPanels[i]);
55 addSidebarPanel(sidebarPanel)
57 console.assert(sidebarPanel instanceof WebInspector.SidebarPanel);
58 if (!(sidebarPanel instanceof WebInspector.SidebarPanel))
61 console.assert(!sidebarPanel.parentSidebar);
62 if (sidebarPanel.parentSidebar)
65 sidebarPanel._parentSidebar = this;
67 this._sidebarPanels.push(sidebarPanel);
68 this._element.appendChild(sidebarPanel.element);
75 removeSidebarPanel(sidebarPanelOrIdentifierOrIndex)
77 var sidebarPanel = this.findSidebarPanel(sidebarPanelOrIdentifierOrIndex);
81 sidebarPanel.willRemove();
83 sidebarPanel._parentSidebar = null;
85 if (this._selectedSidebarPanel === sidebarPanel) {
86 var index = this._sidebarPanels.indexOf(sidebarPanel);
87 this.selectedSidebarPanel = this._sidebarPanels[index - 1] || this._sidebarPanels[index + 1] || null;
90 this._sidebarPanels.remove(sidebarPanel);
91 this._element.removeChild(sidebarPanel.element);
93 sidebarPanel.removed();
98 get selectedSidebarPanel()
100 return this._selectedSidebarPanel || null;
103 set selectedSidebarPanel(sidebarPanelOrIdentifierOrIndex)
105 var sidebarPanel = this.findSidebarPanel(sidebarPanelOrIdentifierOrIndex);
106 if (this._selectedSidebarPanel === sidebarPanel)
109 if (this._selectedSidebarPanel) {
110 var wasVisible = this._selectedSidebarPanel.visible;
112 this._selectedSidebarPanel.selected = false;
115 this._selectedSidebarPanel.hidden();
116 this._selectedSidebarPanel.visibilityDidChange();
120 this._selectedSidebarPanel = sidebarPanel || null;
122 if (this._selectedSidebarPanel) {
123 this._selectedSidebarPanel.selected = true;
125 if (this._selectedSidebarPanel.visible) {
126 this._selectedSidebarPanel.shown();
127 this._selectedSidebarPanel.visibilityDidChange();
131 this.dispatchEventToListeners(WebInspector.Sidebar.Event.SidebarPanelSelected);
136 return WebInspector.Sidebar.AbsoluteMinimumWidth;
141 // FIXME: This is kind of arbitrary and ideally would be a more complex calculation based on the
142 // available space for the sibling elements.
143 return Math.round(window.innerWidth / 3);
148 return this._element.offsetWidth;
153 if (newWidth === this.width)
156 newWidth = Math.max(this.minimumWidth, Math.min(newWidth, this.maximumWidth));
158 this._element.style.width = newWidth + "px";
160 if (!this.collapsed && this._selectedSidebarPanel)
161 this._selectedSidebarPanel.widthDidChange();
163 this.dispatchEventToListeners(WebInspector.Sidebar.Event.WidthDidChange);
168 return this._element.classList.contains(WebInspector.Sidebar.CollapsedStyleClassName);
173 if (flag === this.collapsed)
177 this._element.classList.add(WebInspector.Sidebar.CollapsedStyleClassName);
179 this._element.classList.remove(WebInspector.Sidebar.CollapsedStyleClassName);
181 if (this._selectedSidebarPanel) {
182 if (this._selectedSidebarPanel.visible)
183 this._selectedSidebarPanel.shown();
185 this._selectedSidebarPanel.hidden();
187 this._selectedSidebarPanel.visibilityDidChange();
189 this._selectedSidebarPanel.widthDidChange();
192 this.dispatchEventToListeners(WebInspector.Sidebar.Event.CollapsedStateDidChange);
193 this.dispatchEventToListeners(WebInspector.Sidebar.Event.WidthDidChange);
198 return this._sidebarPanels;
203 return this._element;
211 findSidebarPanel(sidebarPanelOrIdentifierOrIndex)
213 var sidebarPanel = null;
215 if (sidebarPanelOrIdentifierOrIndex instanceof WebInspector.SidebarPanel) {
216 if (this._sidebarPanels.includes(sidebarPanelOrIdentifierOrIndex))
217 sidebarPanel = sidebarPanelOrIdentifierOrIndex;
218 } else if (typeof sidebarPanelOrIdentifierOrIndex === "number") {
219 sidebarPanel = this._sidebarPanels[sidebarPanelOrIdentifierOrIndex];
220 } else if (typeof sidebarPanelOrIdentifierOrIndex === "string") {
221 for (var i = 0; i < this._sidebarPanels.length; ++i) {
222 if (this._sidebarPanels[i].identifier === sidebarPanelOrIdentifierOrIndex) {
223 sidebarPanel = this._sidebarPanels[i];
234 resizerDragStarted(resizer)
236 this._widthBeforeResize = this.width;
239 resizerDragging(resizer, positionDelta)
241 if (this._side === WebInspector.Sidebar.Sides.Left)
244 var newWidth = positionDelta + this._widthBeforeResize;
245 this.width = newWidth;
246 this.collapsed = (newWidth < (this.minimumWidth / 2));
249 resizerDragEnded(resizer)
251 delete this._widthBeforeResize;
256 _navigationItemSelected(event)
258 this.selectedSidebarPanel = event.target.selectedNavigationItem ? event.target.selectedNavigationItem.identifier : null;
262 WebInspector.Sidebar.CollapsedStyleClassName = "collapsed";
263 WebInspector.Sidebar.AbsoluteMinimumWidth = 200;
265 WebInspector.Sidebar.Sides = {
270 WebInspector.Sidebar.Event = {
271 SidebarPanelSelected: "sidebar-panel-selected",
272 CollapsedStateDidChange: "sidebar-collapsed-state-did-change",
273 WidthDidChange: "sidebar-width-did-change",