Web Inspector: DOM: provide a way to disable/breakpoint all event listeners for a...
[WebKit-https.git] / Source / WebInspectorUI / UserInterface / Views / DashboardContainerView.js
1 /*
2  * Copyright (C) 2013-2015 Apple 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
6  * are met:
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.
12  *
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.
24  */
25
26 WI.DashboardContainerView = class DashboardContainerView extends WI.Object
27 {
28     constructor()
29     {
30         super();
31
32         this._toolbarItem = new WI.NavigationItem("dashboard-container", "group", WI.UIString("Activity Viewer"));
33
34         this._advanceForwardArrowElement = this._toolbarItem.element.appendChild(document.createElement("div"));
35         this._advanceForwardArrowElement.className = "advance-arrow advance-forward";
36         this._advanceBackwardArrowElement = this._toolbarItem.element.appendChild(document.createElement("div"));
37         this._advanceBackwardArrowElement.className = "advance-arrow advance-backward";
38
39         this._advanceForwardArrowElement.addEventListener("click", this._advanceForwardArrowClicked.bind(this));
40         this._advanceBackwardArrowElement.addEventListener("click", this._advanceBackwardArrowClicked.bind(this));
41
42         // Represents currently open dashboards, with the most recent entries appended to the end.
43         this._dashboardStack = [];
44         this._currentIndex = -1;
45
46         this._updateAdvanceArrowVisibility();
47     }
48
49     // Public
50
51     get toolbarItem()
52     {
53         return this._toolbarItem;
54     }
55
56     get currentDashboardView()
57     {
58         if (this._currentIndex === -1)
59             return null;
60
61         return this._dashboardStack[this._currentIndex];
62     }
63
64     showDashboardViewForRepresentedObject(representedObject)
65     {
66         var dashboardView = this._dashboardViewForRepresentedObject(representedObject);
67         if (!dashboardView)
68             return null;
69
70         if (this.currentDashboardView === dashboardView)
71             return dashboardView;
72
73         var index = this._dashboardStack.indexOf(dashboardView);
74         this._showDashboardAtIndex(index);
75         return dashboardView;
76     }
77
78     hideDashboardViewForRepresentedObject(representedObject)
79     {
80         var onlyReturnExistingViews = true;
81         var dashboardView = this._dashboardViewForRepresentedObject(representedObject, onlyReturnExistingViews);
82
83         if (this.currentDashboardView !== dashboardView)
84             return;
85
86         console.assert(this._currentIndex > 0);
87         this._showDashboardAtIndex(this._currentIndex - 1);
88     }
89
90     closeDashboardViewForRepresentedObject(representedObject)
91     {
92         var onlyReturnExistingViews = true;
93         var dashboardView = this._dashboardViewForRepresentedObject(representedObject, onlyReturnExistingViews);
94         if (!dashboardView)
95             return;
96
97         this._closeDashboardView(dashboardView);
98     }
99
100     // Private
101
102     _advanceForwardArrowClicked()
103     {
104         this._showDashboardAtIndex(this._currentIndex + 1);
105     }
106
107     _advanceBackwardArrowClicked()
108     {
109         this._showDashboardAtIndex(this._currentIndex - 1);
110     }
111
112     _dismissAdvanceArrows()
113     {
114         this._advanceForwardArrowElement.classList.add(WI.DashboardContainerView.InactiveStyleClassName);
115         this._advanceBackwardArrowElement.classList.add(WI.DashboardContainerView.InactiveStyleClassName);
116     }
117
118     _updateAdvanceArrowVisibility()
119     {
120         var canAdvanceForward = this._currentIndex < this._dashboardStack.length - 1;
121         var canAdvanceBackward = this._currentIndex > 0;
122         this._advanceForwardArrowElement.classList.toggle(WI.DashboardContainerView.InactiveStyleClassName, !canAdvanceForward);
123         this._advanceBackwardArrowElement.classList.toggle(WI.DashboardContainerView.InactiveStyleClassName, !canAdvanceBackward);
124     }
125
126     _dashboardViewForRepresentedObject(representedObject, onlyReturnExistingViews)
127     {
128         console.assert(representedObject);
129
130         // Iterate over all known dashboard views and see if any are for this object.
131         for (var dashboardView of this._dashboardStack) {
132             if (dashboardView.representedObject === representedObject)
133                 return dashboardView;
134         }
135
136         if (onlyReturnExistingViews)
137             return null;
138
139         // No existing content view found, make a new one.
140         dashboardView = WI.DashboardView.create(representedObject);
141
142         console.assert(dashboardView, "Unknown representedObject", representedObject);
143         if (!dashboardView)
144             return null;
145
146         this._dashboardStack.push(dashboardView);
147         this._toolbarItem.element.appendChild(dashboardView.element);
148
149         return dashboardView;
150     }
151
152     _showDashboardAtIndex(index)
153     {
154         console.assert(index >= 0 && index <= this._dashboardStack.length - 1);
155
156         if (this._currentIndex === index)
157             return;
158
159         var advanceDirection = null;
160         if (this._currentIndex < index)
161             advanceDirection = WI.DashboardContainerView.AdvanceDirection.Forward;
162         else
163             advanceDirection = WI.DashboardContainerView.AdvanceDirection.Backward;
164         var initialDirection = WI.DashboardContainerView.AdvanceDirection.None;
165         var isInitialDashboard = this._currentIndex === -1;
166         if (!isInitialDashboard)
167             this._hideDashboardView(this.currentDashboardView, advanceDirection);
168
169         this._currentIndex = index;
170         this._showDashboardView(this.currentDashboardView, isInitialDashboard ? initialDirection : advanceDirection);
171     }
172
173     _showDashboardView(dashboardView, advanceDirection)
174     {
175         console.assert(dashboardView instanceof WI.DashboardView);
176
177         dashboardView.shown();
178         this._dismissAdvanceArrows();
179
180         var animationClass = null;
181         if (advanceDirection === WI.DashboardContainerView.AdvanceDirection.Forward)
182             animationClass = WI.DashboardContainerView.ForwardIncomingDashboardStyleClassName;
183         if (advanceDirection === WI.DashboardContainerView.AdvanceDirection.Backward)
184             animationClass = WI.DashboardContainerView.BackwardIncomingDashboardStyleClassName;
185
186         var container = this;
187         dashboardView.element.classList.add(WI.DashboardContainerView.VisibleDashboardStyleClassName);
188
189         function animationEnded(event) {
190             if (event.target !== dashboardView.element)
191                 return;
192
193             dashboardView.element.removeEventListener("animationend", animationEnded);
194             dashboardView.element.classList.remove(animationClass);
195             container._updateAdvanceArrowVisibility();
196         }
197
198         if (animationClass) {
199             dashboardView.element.classList.add(animationClass);
200             dashboardView.element.addEventListener("animationend", animationEnded);
201         }
202
203         return dashboardView;
204     }
205
206     _hideDashboardView(dashboardView, advanceDirection, callback)
207     {
208         console.assert(dashboardView instanceof WI.DashboardView);
209         console.assert(this.currentDashboardView === dashboardView);
210
211         dashboardView.hidden();
212         this._dismissAdvanceArrows();
213
214         var animationClass = null;
215         if (advanceDirection === WI.DashboardContainerView.AdvanceDirection.Forward)
216             animationClass = WI.DashboardContainerView.ForwardOutgoingDashboardStyleClassName;
217         if (advanceDirection === WI.DashboardContainerView.AdvanceDirection.Backward)
218             animationClass = WI.DashboardContainerView.BackwardOutgoingDashboardStyleClassName;
219
220         var container = this;
221
222         function animationEnded(event) {
223             if (event.target !== dashboardView.element)
224                 return;
225
226             dashboardView.element.removeEventListener("animationend", animationEnded);
227             dashboardView.element.classList.remove(animationClass);
228             dashboardView.element.classList.remove(WI.DashboardContainerView.VisibleDashboardStyleClassName);
229             container._updateAdvanceArrowVisibility();
230
231             if (typeof callback === "function")
232                 callback();
233         }
234
235         if (animationClass) {
236             dashboardView.element.classList.add(animationClass);
237             dashboardView.element.addEventListener("animationend", animationEnded);
238         } else
239             dashboardView.element.classList.remove(WI.DashboardContainerView.VisibleDashboardStyleClassName);
240     }
241
242     _closeDashboardView(dashboardView)
243     {
244         console.assert(dashboardView instanceof WI.DashboardView);
245
246         function dissociateDashboardView() {
247             dashboardView.closed();
248             dashboardView.element.parentNode.removeChild(dashboardView.element);
249         }
250
251         var index = this._dashboardStack.indexOf(dashboardView);
252
253         if (this.currentDashboardView === dashboardView) {
254             var direction = WI.DashboardContainerView.AdvanceDirection.Backward;
255             this._hideDashboardView(this.currentDashboardView, direction, dissociateDashboardView);
256             this._dashboardStack.splice(index, 1);
257             --this._currentIndex;
258             this._showDashboardView(this.currentDashboardView, direction);
259             return;
260         }
261
262         this._dashboardStack.splice(index, 1);
263         if (this._currentIndex > index)
264             --this._currentIndex;
265         dissociateDashboardView.call(this);
266
267         this._updateAdvanceArrowVisibility();
268     }
269 };
270
271 WI.DashboardContainerView.VisibleDashboardStyleClassName = "visible";
272 WI.DashboardContainerView.InactiveStyleClassName = "inactive";
273
274 WI.DashboardContainerView.AdvanceDirection = {
275     Forward: Symbol("dashboard-container-view-advance-direction-forward"),
276     Backward: Symbol("dashboard-container-view-advance-direction-backward"),
277     None: Symbol("dashboard-container-view-advance-direction-none")
278 };
279
280 WI.DashboardContainerView.ForwardIncomingDashboardStyleClassName = "slide-in-down";
281 WI.DashboardContainerView.BackwardIncomingDashboardStyleClassName = "slide-in-up";
282 WI.DashboardContainerView.ForwardOutgoingDashboardStyleClassName = "slide-out-down";
283 WI.DashboardContainerView.BackwardOutgoingDashboardStyleClassName = "slide-out-up";