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

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js

Issue 2466123002: DevTools: reformat front-end code to match chromium style. (Closed)
Patch Set: all done Created 4 years, 1 month 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. 2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com> 3 * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
4 * Copyright (C) 2009 Joseph Pecoraro 4 * Copyright (C) 2009 Joseph Pecoraro
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 9 *
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 15 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
16 * its contributors may be used to endorse or promote products derived 16 * its contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission. 17 * from this software without specific prior written permission.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30
31 /** 30 /**
32 * @constructor
33 * @implements {WebInspector.Searchable} 31 * @implements {WebInspector.Searchable}
34 * @implements {WebInspector.TargetManager.Observer} 32 * @implements {WebInspector.TargetManager.Observer}
35 * @implements {WebInspector.ViewLocationResolver} 33 * @implements {WebInspector.ViewLocationResolver}
36 * @extends {WebInspector.Panel} 34 * @unrestricted
37 */ 35 */
38 WebInspector.ElementsPanel = function() 36 WebInspector.ElementsPanel = class extends WebInspector.Panel {
39 { 37 constructor() {
40 WebInspector.Panel.call(this, "elements"); 38 super('elements');
41 this.registerRequiredCSS("elements/elementsPanel.css"); 39 this.registerRequiredCSS('elements/elementsPanel.css');
42 40
43 this._splitWidget = new WebInspector.SplitWidget(true, true, "elementsPanelS plitViewState", 325, 325); 41 this._splitWidget = new WebInspector.SplitWidget(true, true, 'elementsPanelS plitViewState', 325, 325);
44 this._splitWidget.addEventListener(WebInspector.SplitWidget.Events.SidebarSi zeChanged, this._updateTreeOutlineVisibleWidth.bind(this)); 42 this._splitWidget.addEventListener(
43 WebInspector.SplitWidget.Events.SidebarSizeChanged, this._updateTreeOutl ineVisibleWidth.bind(this));
45 this._splitWidget.show(this.element); 44 this._splitWidget.show(this.element);
46 45
47 this._searchableView = new WebInspector.SearchableView(this); 46 this._searchableView = new WebInspector.SearchableView(this);
48 this._searchableView.setMinimumSize(25, 28); 47 this._searchableView.setMinimumSize(25, 28);
49 this._searchableView.setPlaceholder(WebInspector.UIString("Find by string, s elector, or XPath")); 48 this._searchableView.setPlaceholder(WebInspector.UIString('Find by string, s elector, or XPath'));
50 var stackElement = this._searchableView.element; 49 var stackElement = this._searchableView.element;
51 50
52 this._contentElement = createElement("div"); 51 this._contentElement = createElement('div');
53 var crumbsContainer = createElement("div"); 52 var crumbsContainer = createElement('div');
54 stackElement.appendChild(this._contentElement); 53 stackElement.appendChild(this._contentElement);
55 stackElement.appendChild(crumbsContainer); 54 stackElement.appendChild(crumbsContainer);
56 55
57 this._splitWidget.setMainWidget(this._searchableView); 56 this._splitWidget.setMainWidget(this._searchableView);
58 57
59 this._contentElement.id = "elements-content"; 58 this._contentElement.id = 'elements-content';
60 // FIXME: crbug.com/425984 59 // FIXME: crbug.com/425984
61 if (WebInspector.moduleSetting("domWordWrap").get()) 60 if (WebInspector.moduleSetting('domWordWrap').get())
62 this._contentElement.classList.add("elements-wrap"); 61 this._contentElement.classList.add('elements-wrap');
63 WebInspector.moduleSetting("domWordWrap").addChangeListener(this._domWordWra pSettingChanged.bind(this)); 62 WebInspector.moduleSetting('domWordWrap').addChangeListener(this._domWordWra pSettingChanged.bind(this));
64 63
65 crumbsContainer.id = "elements-crumbs"; 64 crumbsContainer.id = 'elements-crumbs';
66 this._breadcrumbs = new WebInspector.ElementsBreadcrumbs(); 65 this._breadcrumbs = new WebInspector.ElementsBreadcrumbs();
67 this._breadcrumbs.show(crumbsContainer); 66 this._breadcrumbs.show(crumbsContainer);
68 this._breadcrumbs.addEventListener(WebInspector.ElementsBreadcrumbs.Events.N odeSelected, this._crumbNodeSelected, this); 67 this._breadcrumbs.addEventListener(
68 WebInspector.ElementsBreadcrumbs.Events.NodeSelected, this._crumbNodeSel ected, this);
69 69
70 this._currentToolbarPane = null; 70 this._currentToolbarPane = null;
71 71
72 this._stylesWidget = new WebInspector.StylesSidebarPane(); 72 this._stylesWidget = new WebInspector.StylesSidebarPane();
73 this._computedStyleWidget = new WebInspector.ComputedStyleWidget(); 73 this._computedStyleWidget = new WebInspector.ComputedStyleWidget();
74 this._metricsWidget = new WebInspector.MetricsSidebarPane(); 74 this._metricsWidget = new WebInspector.MetricsSidebarPane();
75 75
76 this._stylesSidebarToolbar = this._createStylesSidebarToolbar(); 76 this._stylesSidebarToolbar = this._createStylesSidebarToolbar();
77 77
78 WebInspector.moduleSetting("sidebarPosition").addChangeListener(this._update SidebarPosition.bind(this)); 78 WebInspector.moduleSetting('sidebarPosition').addChangeListener(this._update SidebarPosition.bind(this));
79 this._updateSidebarPosition(); 79 this._updateSidebarPosition();
80 80
81 /** @type {!Array.<!WebInspector.ElementsTreeOutline>} */ 81 /** @type {!Array.<!WebInspector.ElementsTreeOutline>} */
82 this._treeOutlines = []; 82 this._treeOutlines = [];
83 WebInspector.targetManager.observeTargets(this); 83 WebInspector.targetManager.observeTargets(this);
84 WebInspector.moduleSetting("showUAShadowDOM").addChangeListener(this._showUA ShadowDOMChanged.bind(this)); 84 WebInspector.moduleSetting('showUAShadowDOM').addChangeListener(this._showUA ShadowDOMChanged.bind(this));
85 WebInspector.targetManager.addModelListener(WebInspector.DOMModel, WebInspec tor.DOMModel.Events.DocumentUpdated, this._documentUpdatedEvent, this); 85 WebInspector.targetManager.addModelListener(
86 WebInspector.extensionServer.addEventListener(WebInspector.ExtensionServer.E vents.SidebarPaneAdded, this._extensionSidebarPaneAdded, this); 86 WebInspector.DOMModel, WebInspector.DOMModel.Events.DocumentUpdated, thi s._documentUpdatedEvent, this);
87 }; 87 WebInspector.extensionServer.addEventListener(
88 88 WebInspector.ExtensionServer.Events.SidebarPaneAdded, this._extensionSid ebarPaneAdded, this);
89 WebInspector.ElementsPanel._elementsSidebarViewTitleSymbol = Symbol("title"); 89 }
90 90
91 WebInspector.ElementsPanel.prototype = { 91 /**
92 * @return {!WebInspector.ElementsPanel}
93 */
94 static instance() {
95 return /** @type {!WebInspector.ElementsPanel} */ (self.runtime.sharedInstan ce(WebInspector.ElementsPanel));
96 }
97
98 /**
99 * @param {!WebInspector.CSSProperty} cssProperty
100 */
101 _revealProperty(cssProperty) {
102 return this.sidebarPaneView.showView(this._stylesViewToReveal).then(() => {
103 this._stylesWidget.revealProperty(/** @type {!WebInspector.CSSProperty} */ (cssProperty));
104 });
105 }
106
107 /**
108 * @return {!Element}
109 */
110 _createStylesSidebarToolbar() {
111 var container = createElementWithClass('div', 'styles-sidebar-pane-toolbar-c ontainer');
112 var hbox = container.createChild('div', 'hbox styles-sidebar-pane-toolbar');
113 var filterContainerElement = hbox.createChild('div', 'styles-sidebar-pane-fi lter-box');
114 var filterInput = WebInspector.StylesSidebarPane.createPropertyFilterElement (
115 WebInspector.UIString('Filter'), hbox, this._stylesWidget.onFilterChange d.bind(this._stylesWidget));
116 filterContainerElement.appendChild(filterInput);
117 var toolbar = new WebInspector.Toolbar('styles-pane-toolbar', hbox);
118 toolbar.makeToggledGray();
119 toolbar.appendLocationItems('styles-sidebarpane-toolbar');
120 var toolbarPaneContainer = container.createChild('div', 'styles-sidebar-tool bar-pane-container');
121 this._toolbarPaneElement = createElementWithClass('div', 'styles-sidebar-too lbar-pane');
122 toolbarPaneContainer.appendChild(this._toolbarPaneElement);
123 return container;
124 }
125
126 /**
127 * @override
128 * @param {string} locationName
129 * @return {?WebInspector.ViewLocation}
130 */
131 resolveLocation(locationName) {
132 return this.sidebarPaneView;
133 }
134
135 /**
136 * @param {?WebInspector.Widget} widget
137 * @param {!WebInspector.ToolbarToggle=} toggle
138 */
139 showToolbarPane(widget, toggle) {
140 if (this._pendingWidgetToggle)
141 this._pendingWidgetToggle.setToggled(false);
142 this._pendingWidgetToggle = toggle;
143
144 if (this._animatedToolbarPane !== undefined)
145 this._pendingWidget = widget;
146 else
147 this._startToolbarPaneAnimation(widget);
148
149 if (widget && toggle)
150 toggle.setToggled(true);
151 }
152
153 /**
154 * @param {?WebInspector.Widget} widget
155 */
156 _startToolbarPaneAnimation(widget) {
157 if (widget === this._currentToolbarPane)
158 return;
159
160 if (widget && this._currentToolbarPane) {
161 this._currentToolbarPane.detach();
162 widget.show(this._toolbarPaneElement);
163 this._currentToolbarPane = widget;
164 this._currentToolbarPane.focus();
165 return;
166 }
167
168 this._animatedToolbarPane = widget;
169
170 if (this._currentToolbarPane)
171 this._toolbarPaneElement.style.animationName = 'styles-element-state-pane- slideout';
172 else if (widget)
173 this._toolbarPaneElement.style.animationName = 'styles-element-state-pane- slidein';
174
175 if (widget)
176 widget.show(this._toolbarPaneElement);
177
178 var listener = onAnimationEnd.bind(this);
179 this._toolbarPaneElement.addEventListener('animationend', listener, false);
180
92 /** 181 /**
93 * @param {!WebInspector.CSSProperty} cssProperty 182 * @this {WebInspector.ElementsPanel}
94 */ 183 */
95 _revealProperty: function(cssProperty) 184 function onAnimationEnd() {
96 { 185 this._toolbarPaneElement.style.removeProperty('animation-name');
97 return this.sidebarPaneView.showView(this._stylesViewToReveal).then(() = > { 186 this._toolbarPaneElement.removeEventListener('animationend', listener, fal se);
98 this._stylesWidget.revealProperty(/** @type {!WebInspector.CSSProper ty} */(cssProperty)); 187
99 }); 188 if (this._currentToolbarPane)
100 }, 189 this._currentToolbarPane.detach();
190
191 this._currentToolbarPane = this._animatedToolbarPane;
192 if (this._currentToolbarPane)
193 this._currentToolbarPane.focus();
194 delete this._animatedToolbarPane;
195
196 if (this._pendingWidget !== undefined) {
197 this._startToolbarPaneAnimation(this._pendingWidget);
198 delete this._pendingWidget;
199 }
200 }
201 }
202
203 /**
204 * @override
205 * @param {!WebInspector.Target} target
206 */
207 targetAdded(target) {
208 var domModel = WebInspector.DOMModel.fromTarget(target);
209 if (!domModel)
210 return;
211 var treeOutline = new WebInspector.ElementsTreeOutline(domModel, true, true) ;
212 treeOutline.setWordWrap(WebInspector.moduleSetting('domWordWrap').get());
213 treeOutline.wireToDOMModel();
214 treeOutline.addEventListener(
215 WebInspector.ElementsTreeOutline.Events.SelectedNodeChanged, this._selec tedNodeChanged, this);
216 treeOutline.addEventListener(
217 WebInspector.ElementsTreeOutline.Events.ElementsTreeUpdated, this._updat eBreadcrumbIfNeeded, this);
218 new WebInspector.ElementsTreeElementHighlighter(treeOutline);
219 this._treeOutlines.push(treeOutline);
220
221 // Perform attach if necessary.
222 if (this.isShowing())
223 this.wasShown();
224 }
225
226 /**
227 * @override
228 * @param {!WebInspector.Target} target
229 */
230 targetRemoved(target) {
231 var domModel = WebInspector.DOMModel.fromTarget(target);
232 if (!domModel)
233 return;
234 var treeOutline = WebInspector.ElementsTreeOutline.forDOMModel(domModel);
235 treeOutline.unwireFromDOMModel();
236 this._treeOutlines.remove(treeOutline);
237 treeOutline.element.remove();
238 }
239
240 _updateTreeOutlineVisibleWidth() {
241 if (!this._treeOutlines.length)
242 return;
243
244 var width = this._splitWidget.element.offsetWidth;
245 if (this._splitWidget.isVertical())
246 width -= this._splitWidget.sidebarSize();
247 for (var i = 0; i < this._treeOutlines.length; ++i) {
248 this._treeOutlines[i].setVisibleWidth(width);
249 }
250 this._breadcrumbs.updateSizes();
251 }
252
253 /**
254 * @override
255 */
256 focus() {
257 if (this._treeOutlines.length)
258 this._treeOutlines[0].focus();
259 }
260
261 /**
262 * @override
263 * @return {!WebInspector.SearchableView}
264 */
265 searchableView() {
266 return this._searchableView;
267 }
268
269 /**
270 * @override
271 */
272 wasShown() {
273 WebInspector.context.setFlavor(WebInspector.ElementsPanel, this);
274
275 for (var i = 0; i < this._treeOutlines.length; ++i) {
276 var treeOutline = this._treeOutlines[i];
277 // Attach heavy component lazily
278 if (treeOutline.element.parentElement !== this._contentElement)
279 this._contentElement.appendChild(treeOutline.element);
280 }
281 super.wasShown();
282 this._breadcrumbs.update();
283
284 for (var i = 0; i < this._treeOutlines.length; ++i) {
285 var treeOutline = this._treeOutlines[i];
286 treeOutline.setVisible(true);
287
288 if (!treeOutline.rootDOMNode)
289 if (treeOutline.domModel().existingDocument())
290 this._documentUpdated(treeOutline.domModel(), treeOutline.domModel().e xistingDocument());
291 else
292 treeOutline.domModel().requestDocument();
293 }
294 this.focus();
295 }
296
297 /**
298 * @override
299 */
300 willHide() {
301 WebInspector.context.setFlavor(WebInspector.ElementsPanel, null);
302
303 WebInspector.DOMModel.hideDOMNodeHighlight();
304 for (var i = 0; i < this._treeOutlines.length; ++i) {
305 var treeOutline = this._treeOutlines[i];
306 treeOutline.setVisible(false);
307 // Detach heavy component on hide
308 this._contentElement.removeChild(treeOutline.element);
309 }
310 if (this._popoverHelper)
311 this._popoverHelper.hidePopover();
312 super.willHide();
313 }
314
315 /**
316 * @override
317 */
318 onResize() {
319 if (WebInspector.moduleSetting('sidebarPosition').get() === 'auto')
320 this.element.window().requestAnimationFrame(this._updateSidebarPosition.bi nd(this)); // Do not force layout.
321 this._updateTreeOutlineVisibleWidth();
322 }
323
324 /**
325 * @param {!WebInspector.Event} event
326 */
327 _selectedNodeChanged(event) {
328 var selectedNode = /** @type {?WebInspector.DOMNode} */ (event.data.node);
329 var focus = /** @type {boolean} */ (event.data.focus);
330 for (var i = 0; i < this._treeOutlines.length; ++i) {
331 if (!selectedNode || selectedNode.domModel() !== this._treeOutlines[i].dom Model())
332 this._treeOutlines[i].selectDOMNode(null);
333 }
334
335 this._breadcrumbs.setSelectedNode(selectedNode);
336
337 WebInspector.context.setFlavor(WebInspector.DOMNode, selectedNode);
338
339 if (!selectedNode)
340 return;
341 selectedNode.setAsInspectedNode();
342 if (focus) {
343 this._selectedNodeOnReset = selectedNode;
344 this._hasNonDefaultSelectedNode = true;
345 }
346
347 var executionContexts = selectedNode.target().runtimeModel.executionContexts ();
348 var nodeFrameId = selectedNode.frameId();
349 for (var context of executionContexts) {
350 if (context.frameId === nodeFrameId) {
351 WebInspector.context.setFlavor(WebInspector.ExecutionContext, context);
352 break;
353 }
354 }
355 }
356
357 _reset() {
358 delete this.currentQuery;
359 }
360
361 /**
362 * @param {!WebInspector.Event} event
363 */
364 _documentUpdatedEvent(event) {
365 this._documentUpdated(
366 /** @type {!WebInspector.DOMModel} */ (event.target), /** @type {?WebIns pector.DOMDocument} */ (event.data));
367 }
368
369 /**
370 * @param {!WebInspector.DOMModel} domModel
371 * @param {?WebInspector.DOMDocument} inspectedRootDocument
372 */
373 _documentUpdated(domModel, inspectedRootDocument) {
374 this._reset();
375 this.searchCanceled();
376
377 var treeOutline = WebInspector.ElementsTreeOutline.forDOMModel(domModel);
378 treeOutline.rootDOMNode = inspectedRootDocument;
379
380 if (!inspectedRootDocument) {
381 if (this.isShowing())
382 domModel.requestDocument();
383 return;
384 }
385
386 this._hasNonDefaultSelectedNode = false;
387 WebInspector.domBreakpointsSidebarPane.restoreBreakpoints(inspectedRootDocum ent);
388
389 if (this._omitDefaultSelection)
390 return;
391
392 var savedSelectedNodeOnReset = this._selectedNodeOnReset;
393 restoreNode.call(this, domModel, this._selectedNodeOnReset);
101 394
102 /** 395 /**
103 * @return {!Element} 396 * @param {!WebInspector.DOMModel} domModel
397 * @param {?WebInspector.DOMNode} staleNode
398 * @this {WebInspector.ElementsPanel}
104 */ 399 */
105 _createStylesSidebarToolbar: function() 400 function restoreNode(domModel, staleNode) {
106 { 401 var nodePath = staleNode ? staleNode.path() : null;
107 var container = createElementWithClass("div", "styles-sidebar-pane-toolb ar-container"); 402 if (!nodePath) {
108 var hbox = container.createChild("div", "hbox styles-sidebar-pane-toolba r"); 403 onNodeRestored.call(this, null);
109 var filterContainerElement = hbox.createChild("div", "styles-sidebar-pan e-filter-box"); 404 return;
110 var filterInput = WebInspector.StylesSidebarPane.createPropertyFilterEle ment(WebInspector.UIString("Filter"), hbox, this._stylesWidget.onFilterChanged.b ind(this._stylesWidget)); 405 }
111 filterContainerElement.appendChild(filterInput); 406 domModel.pushNodeByPathToFrontend(nodePath, onNodeRestored.bind(this));
112 var toolbar = new WebInspector.Toolbar("styles-pane-toolbar", hbox); 407 }
113 toolbar.makeToggledGray();
114 toolbar.appendLocationItems("styles-sidebarpane-toolbar");
115 var toolbarPaneContainer = container.createChild("div", "styles-sidebar- toolbar-pane-container");
116 this._toolbarPaneElement = createElementWithClass("div", "styles-sidebar -toolbar-pane");
117 toolbarPaneContainer.appendChild(this._toolbarPaneElement);
118 return container;
119 },
120 408
121 /** 409 /**
122 * @override 410 * @param {?DOMAgent.NodeId} restoredNodeId
123 * @param {string} locationName 411 * @this {WebInspector.ElementsPanel}
124 * @return {?WebInspector.ViewLocation}
125 */ 412 */
126 resolveLocation: function(locationName) 413 function onNodeRestored(restoredNodeId) {
127 { 414 if (savedSelectedNodeOnReset !== this._selectedNodeOnReset)
128 return this.sidebarPaneView; 415 return;
129 }, 416 var node = restoredNodeId ? domModel.nodeForId(restoredNodeId) : null;
417 if (!node) {
418 var inspectedDocument = domModel.existingDocument();
419 node = inspectedDocument ? inspectedDocument.body || inspectedDocument.d ocumentElement : null;
420 }
421 this._setDefaultSelectedNode(node);
422 this._lastSelectedNodeSelectedForTest();
423 }
424 }
425
426 _lastSelectedNodeSelectedForTest() {
427 }
428
429 /**
430 * @param {?WebInspector.DOMNode} node
431 */
432 _setDefaultSelectedNode(node) {
433 if (!node || this._hasNonDefaultSelectedNode || this._pendingNodeReveal)
434 return;
435 var treeOutline = WebInspector.ElementsTreeOutline.forDOMModel(node.domModel ());
436 if (!treeOutline)
437 return;
438 this.selectDOMNode(node);
439 if (treeOutline.selectedTreeElement)
440 treeOutline.selectedTreeElement.expand();
441 }
442
443 /**
444 * @override
445 */
446 searchCanceled() {
447 delete this._searchQuery;
448 this._hideSearchHighlights();
449
450 this._searchableView.updateSearchMatchesCount(0);
451
452 delete this._currentSearchResultIndex;
453 delete this._searchResults;
454
455 WebInspector.DOMModel.cancelSearch();
456 }
457
458 /**
459 * @override
460 * @param {!WebInspector.SearchableView.SearchConfig} searchConfig
461 * @param {boolean} shouldJump
462 * @param {boolean=} jumpBackwards
463 */
464 performSearch(searchConfig, shouldJump, jumpBackwards) {
465 var query = searchConfig.query;
466 // Call searchCanceled since it will reset everything we need before doing a new search.
467 this.searchCanceled();
468
469 const whitespaceTrimmedQuery = query.trim();
470 if (!whitespaceTrimmedQuery.length)
471 return;
472
473 this._searchQuery = query;
474
475 var promises = [];
476 var domModels = WebInspector.DOMModel.instances();
477 for (var domModel of domModels)
478 promises.push(
479 domModel.performSearchPromise(whitespaceTrimmedQuery, WebInspector.mod uleSetting('showUAShadowDOM').get()));
480 Promise.all(promises).then(resultCountCallback.bind(this));
130 481
131 /** 482 /**
132 * @param {?WebInspector.Widget} widget 483 * @param {!Array.<number>} resultCounts
133 * @param {!WebInspector.ToolbarToggle=} toggle 484 * @this {WebInspector.ElementsPanel}
134 */ 485 */
135 showToolbarPane: function(widget, toggle) 486 function resultCountCallback(resultCounts) {
136 { 487 /**
137 if (this._pendingWidgetToggle) 488 * @type {!Array.<{domModel: !WebInspector.DOMModel, index: number, node: (?WebInspector.DOMNode|undefined)}>}
138 this._pendingWidgetToggle.setToggled(false); 489 */
139 this._pendingWidgetToggle = toggle; 490 this._searchResults = [];
140 491 for (var i = 0; i < resultCounts.length; ++i) {
141 if (this._animatedToolbarPane !== undefined) 492 var resultCount = resultCounts[i];
142 this._pendingWidget = widget; 493 for (var j = 0; j < resultCount; ++j)
143 else 494 this._searchResults.push({domModel: domModels[i], index: j, node: unde fined});
144 this._startToolbarPaneAnimation(widget); 495 }
145 496 this._searchableView.updateSearchMatchesCount(this._searchResults.length);
146 if (widget && toggle) 497 if (!this._searchResults.length)
147 toggle.setToggled(true); 498 return;
148 }, 499 this._currentSearchResultIndex = -1;
500
501 if (shouldJump)
502 this._jumpToSearchResult(jumpBackwards ? -1 : 0);
503 }
504 }
505
506 _domWordWrapSettingChanged(event) {
507 // FIXME: crbug.com/425984
508 this._contentElement.classList.toggle('elements-wrap', event.data);
509 for (var i = 0; i < this._treeOutlines.length; ++i)
510 this._treeOutlines[i].setWordWrap(/** @type {boolean} */ (event.data));
511 }
512
513 switchToAndFocus(node) {
514 // Reset search restore.
515 this._searchableView.cancelSearch();
516 WebInspector.viewManager.showView('elements').then(() => this.selectDOMNode( node, true));
517 }
518
519 /**
520 * @param {!Element} element
521 * @param {!Event} event
522 * @return {!Element|!AnchorBox|undefined}
523 */
524 _getPopoverAnchor(element, event) {
525 var anchor = element.enclosingNodeOrSelfWithClass('webkit-html-resource-link ');
526 if (!anchor || !anchor.href)
527 return;
528
529 return anchor;
530 }
531
532 /**
533 * @param {!Element} anchor
534 * @param {!WebInspector.Popover} popover
535 */
536 _showPopover(anchor, popover) {
537 var node = this.selectedDOMNode();
538 if (node)
539 WebInspector.DOMPresentationUtils.buildImagePreviewContents(node.target(), anchor.href, true, showPopover);
149 540
150 /** 541 /**
151 * @param {?WebInspector.Widget} widget 542 * @param {!Element=} contents
152 */ 543 */
153 _startToolbarPaneAnimation: function(widget) 544 function showPopover(contents) {
154 { 545 if (!contents)
155 if (widget === this._currentToolbarPane) 546 return;
156 return; 547 popover.setCanShrink(false);
157 548 popover.showForAnchor(contents, anchor);
158 if (widget && this._currentToolbarPane) { 549 }
159 this._currentToolbarPane.detach(); 550 }
160 widget.show(this._toolbarPaneElement); 551
161 this._currentToolbarPane = widget; 552 _jumpToSearchResult(index) {
162 this._currentToolbarPane.focus(); 553 this._hideSearchHighlights();
163 return; 554 this._currentSearchResultIndex = (index + this._searchResults.length) % this ._searchResults.length;
164 } 555 this._highlightCurrentSearchResult();
165 556 }
166 this._animatedToolbarPane = widget; 557
167 558 /**
168 if (this._currentToolbarPane) 559 * @override
169 this._toolbarPaneElement.style.animationName = "styles-element-state -pane-slideout"; 560 */
170 else if (widget) 561 jumpToNextSearchResult() {
171 this._toolbarPaneElement.style.animationName = "styles-element-state -pane-slidein"; 562 if (!this._searchResults)
172 563 return;
173 if (widget) 564 this._jumpToSearchResult(this._currentSearchResultIndex + 1);
174 widget.show(this._toolbarPaneElement); 565 }
175 566
176 var listener = onAnimationEnd.bind(this); 567 /**
177 this._toolbarPaneElement.addEventListener("animationend", listener, fals e); 568 * @override
178 569 */
179 /** 570 jumpToPreviousSearchResult() {
180 * @this {WebInspector.ElementsPanel} 571 if (!this._searchResults)
181 */ 572 return;
182 function onAnimationEnd() 573 this._jumpToSearchResult(this._currentSearchResultIndex - 1);
183 { 574 }
184 this._toolbarPaneElement.style.removeProperty("animation-name"); 575
185 this._toolbarPaneElement.removeEventListener("animationend", listene r, false); 576 /**
186 577 * @override
187 if (this._currentToolbarPane) 578 * @return {boolean}
188 this._currentToolbarPane.detach(); 579 */
189 580 supportsCaseSensitiveSearch() {
190 this._currentToolbarPane = this._animatedToolbarPane; 581 return false;
191 if (this._currentToolbarPane) 582 }
192 this._currentToolbarPane.focus(); 583
193 delete this._animatedToolbarPane; 584 /**
194 585 * @override
195 if (this._pendingWidget !== undefined) { 586 * @return {boolean}
196 this._startToolbarPaneAnimation(this._pendingWidget); 587 */
197 delete this._pendingWidget; 588 supportsRegexSearch() {
198 } 589 return false;
199 } 590 }
200 }, 591
592 _highlightCurrentSearchResult() {
593 var index = this._currentSearchResultIndex;
594 var searchResults = this._searchResults;
595 var searchResult = searchResults[index];
596
597 if (searchResult.node === null) {
598 this._searchableView.updateCurrentMatchIndex(index);
599 return;
600 }
201 601
202 /** 602 /**
203 * @override 603 * @param {?WebInspector.DOMNode} node
204 * @param {!WebInspector.Target} target 604 * @this {WebInspector.ElementsPanel}
205 */ 605 */
206 targetAdded: function(target) 606 function searchCallback(node) {
207 { 607 searchResult.node = node;
208 var domModel = WebInspector.DOMModel.fromTarget(target); 608 this._highlightCurrentSearchResult();
209 if (!domModel) 609 }
210 return; 610
211 var treeOutline = new WebInspector.ElementsTreeOutline(domModel, true, t rue); 611 if (typeof searchResult.node === 'undefined') {
212 treeOutline.setWordWrap(WebInspector.moduleSetting("domWordWrap").get()) ; 612 // No data for slot, request it.
213 treeOutline.wireToDOMModel(); 613 searchResult.domModel.searchResult(searchResult.index, searchCallback.bind (this));
214 treeOutline.addEventListener(WebInspector.ElementsTreeOutline.Events.Sel ectedNodeChanged, this._selectedNodeChanged, this); 614 return;
215 treeOutline.addEventListener(WebInspector.ElementsTreeOutline.Events.Ele mentsTreeUpdated, this._updateBreadcrumbIfNeeded, this); 615 }
216 new WebInspector.ElementsTreeElementHighlighter(treeOutline); 616
217 this._treeOutlines.push(treeOutline); 617 this._searchableView.updateCurrentMatchIndex(index);
218 618
219 // Perform attach if necessary. 619 var treeElement = this._treeElementForNode(searchResult.node);
220 if (this.isShowing()) 620 if (treeElement) {
221 this.wasShown(); 621 treeElement.highlightSearchResults(this._searchQuery);
222 622 treeElement.reveal();
223 }, 623 var matches = treeElement.listItemElement.getElementsByClassName(WebInspec tor.highlightedSearchResultClassName);
224 624 if (matches.length)
625 matches[0].scrollIntoViewIfNeeded(false);
626 }
627 }
628
629 _hideSearchHighlights() {
630 if (!this._searchResults || !this._searchResults.length || this._currentSear chResultIndex < 0)
631 return;
632 var searchResult = this._searchResults[this._currentSearchResultIndex];
633 if (!searchResult.node)
634 return;
635 var treeOutline = WebInspector.ElementsTreeOutline.forDOMModel(searchResult. node.domModel());
636 var treeElement = treeOutline.findTreeElement(searchResult.node);
637 if (treeElement)
638 treeElement.hideSearchHighlights();
639 }
640
641 /**
642 * @return {?WebInspector.DOMNode}
643 */
644 selectedDOMNode() {
645 for (var i = 0; i < this._treeOutlines.length; ++i) {
646 var treeOutline = this._treeOutlines[i];
647 if (treeOutline.selectedDOMNode())
648 return treeOutline.selectedDOMNode();
649 }
650 return null;
651 }
652
653 /**
654 * @param {!WebInspector.DOMNode} node
655 * @param {boolean=} focus
656 */
657 selectDOMNode(node, focus) {
658 for (var i = 0; i < this._treeOutlines.length; ++i) {
659 var treeOutline = this._treeOutlines[i];
660 if (treeOutline.domModel() === node.domModel())
661 treeOutline.selectDOMNode(node, focus);
662 else
663 treeOutline.selectDOMNode(null);
664 }
665 }
666
667 /**
668 * @param {!WebInspector.Event} event
669 */
670 _updateBreadcrumbIfNeeded(event) {
671 var nodes = /** @type {!Array.<!WebInspector.DOMNode>} */ (event.data);
672 this._breadcrumbs.updateNodes(nodes);
673 }
674
675 /**
676 * @param {!WebInspector.Event} event
677 */
678 _crumbNodeSelected(event) {
679 var node = /** @type {!WebInspector.DOMNode} */ (event.data);
680 this.selectDOMNode(node, true);
681 }
682
683 /**
684 * @override
685 * @param {!KeyboardEvent} event
686 */
687 handleShortcut(event) {
225 /** 688 /**
226 * @override 689 * @param {!WebInspector.ElementsTreeOutline} treeOutline
227 * @param {!WebInspector.Target} target
228 */ 690 */
229 targetRemoved: function(target) 691 function handleUndoRedo(treeOutline) {
230 { 692 if (WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) && !event.shif tKey &&
231 var domModel = WebInspector.DOMModel.fromTarget(target); 693 (event.key === 'Z' || event.key === 'z')) { // Z key
232 if (!domModel) 694 treeOutline.domModel().undo();
233 return; 695 event.handled = true;
234 var treeOutline = WebInspector.ElementsTreeOutline.forDOMModel(domModel) ; 696 return;
235 treeOutline.unwireFromDOMModel(); 697 }
236 this._treeOutlines.remove(treeOutline); 698
237 treeOutline.element.remove(); 699 var isRedoKey = WebInspector.isMac() ?
238 }, 700 event.metaKey && event.shiftKey && (event.key === 'Z' || event.key === 'z') : // Z key
239 701 event.ctrlKey && (event.key === 'Y' || event.key === 'y'); // Y key
240 _updateTreeOutlineVisibleWidth: function() 702 if (isRedoKey) {
241 { 703 treeOutline.domModel().redo();
242 if (!this._treeOutlines.length) 704 event.handled = true;
243 return; 705 }
244 706 }
245 var width = this._splitWidget.element.offsetWidth; 707
246 if (this._splitWidget.isVertical()) 708 if (WebInspector.isEditing() && event.keyCode !== WebInspector.KeyboardShort cut.Keys.F2.code)
247 width -= this._splitWidget.sidebarSize(); 709 return;
248 for (var i = 0; i < this._treeOutlines.length; ++i) { 710
249 this._treeOutlines[i].setVisibleWidth(width); 711 var treeOutline = null;
250 } 712 for (var i = 0; i < this._treeOutlines.length; ++i) {
251 this._breadcrumbs.updateSizes(); 713 if (this._treeOutlines[i].selectedDOMNode())
252 }, 714 treeOutline = this._treeOutlines[i];
715 }
716 if (!treeOutline)
717 return;
718
719 if (!treeOutline.editing()) {
720 handleUndoRedo.call(null, treeOutline);
721 if (event.handled) {
722 this._stylesWidget.forceUpdate();
723 return;
724 }
725 }
726
727 treeOutline.handleShortcut(event);
728 if (event.handled)
729 return;
730
731 super.handleShortcut(event);
732 }
733
734 /**
735 * @param {?WebInspector.DOMNode} node
736 * @return {?WebInspector.ElementsTreeOutline}
737 */
738 _treeOutlineForNode(node) {
739 if (!node)
740 return null;
741 return WebInspector.ElementsTreeOutline.forDOMModel(node.domModel());
742 }
743
744 /**
745 * @param {!WebInspector.DOMNode} node
746 * @return {?WebInspector.ElementsTreeElement}
747 */
748 _treeElementForNode(node) {
749 var treeOutline = this._treeOutlineForNode(node);
750 return /** @type {?WebInspector.ElementsTreeElement} */ (treeOutline.findTre eElement(node));
751 }
752
753 /**
754 * @param {!WebInspector.DOMNode} node
755 * @return {!WebInspector.DOMNode}
756 */
757 _leaveUserAgentShadowDOM(node) {
758 var userAgentShadowRoot;
759 while ((userAgentShadowRoot = node.ancestorUserAgentShadowRoot()) && userAge ntShadowRoot.parentNode)
760 node = userAgentShadowRoot.parentNode;
761 return node;
762 }
763
764 /**
765 * @param {!WebInspector.DOMNode} node
766 * @return {!Promise}
767 */
768 revealAndSelectNode(node) {
769 if (WebInspector.inspectElementModeController && WebInspector.inspectElement ModeController.isInInspectElementMode())
770 WebInspector.inspectElementModeController.stopInspection();
771
772 this._omitDefaultSelection = true;
773
774 node = WebInspector.moduleSetting('showUAShadowDOM').get() ? node : this._le aveUserAgentShadowDOM(node);
775 node.highlightForTwoSeconds();
776
777 return WebInspector.viewManager.showView('elements').then(() => {
778 this.selectDOMNode(node, true);
779 delete this._omitDefaultSelection;
780
781 if (!this._notFirstInspectElement)
782 InspectorFrontendHost.inspectElementCompleted();
783 this._notFirstInspectElement = true;
784 });
785 }
786
787 _sidebarContextMenuEventFired(event) {
788 var contextMenu = new WebInspector.ContextMenu(event);
789 contextMenu.appendApplicableItems(/** @type {!Object} */ (event.deepElementF romPoint()));
790 contextMenu.show();
791 }
792
793 _showUAShadowDOMChanged() {
794 for (var i = 0; i < this._treeOutlines.length; ++i)
795 this._treeOutlines[i].update();
796 }
797
798 _updateSidebarPosition() {
799 var horizontally;
800 var position = WebInspector.moduleSetting('sidebarPosition').get();
801 if (position === 'right')
802 horizontally = false;
803 else if (position === 'bottom')
804 horizontally = true;
805 else
806 horizontally = WebInspector.inspectorView.element.offsetWidth < 680;
807
808 if (this.sidebarPaneView && horizontally === !this._splitWidget.isVertical() )
809 return;
810
811 if (this.sidebarPaneView && this.sidebarPaneView.tabbedPane().shouldHideOnDe tach())
812 return; // We can't reparent extension iframes.
813
814 var extensionSidebarPanes = WebInspector.extensionServer.sidebarPanes();
815 if (this.sidebarPaneView) {
816 this.sidebarPaneView.tabbedPane().detach();
817 this._splitWidget.uninstallResizer(this.sidebarPaneView.tabbedPane().heade rElement());
818 }
819
820 this._splitWidget.setVertical(!horizontally);
821 this.showToolbarPane(null);
822
823 var matchedStylesContainer = new WebInspector.VBox();
824 matchedStylesContainer.element.appendChild(this._stylesSidebarToolbar);
825 var matchedStylePanesWrapper = new WebInspector.VBox();
826 matchedStylePanesWrapper.element.classList.add('style-panes-wrapper');
827 matchedStylePanesWrapper.show(matchedStylesContainer.element);
828 this._stylesWidget.show(matchedStylePanesWrapper.element);
829
830 var computedStylePanesWrapper = new WebInspector.VBox();
831 computedStylePanesWrapper.element.classList.add('style-panes-wrapper');
832 this._computedStyleWidget.show(computedStylePanesWrapper.element);
253 833
254 /** 834 /**
255 * @override 835 * @param {boolean} inComputedStyle
836 * @this {WebInspector.ElementsPanel}
256 */ 837 */
257 focus: function() 838 function showMetrics(inComputedStyle) {
258 { 839 if (inComputedStyle)
259 if (this._treeOutlines.length) 840 this._metricsWidget.show(computedStylePanesWrapper.element, this._comput edStyleWidget.element);
260 this._treeOutlines[0].focus(); 841 else
261 }, 842 this._metricsWidget.show(matchedStylePanesWrapper.element);
262 843 }
263 /**
264 * @override
265 * @return {!WebInspector.SearchableView}
266 */
267 searchableView: function()
268 {
269 return this._searchableView;
270 },
271
272 wasShown: function()
273 {
274 WebInspector.context.setFlavor(WebInspector.ElementsPanel, this);
275
276 for (var i = 0; i < this._treeOutlines.length; ++i) {
277 var treeOutline = this._treeOutlines[i];
278 // Attach heavy component lazily
279 if (treeOutline.element.parentElement !== this._contentElement)
280 this._contentElement.appendChild(treeOutline.element);
281 }
282 WebInspector.Panel.prototype.wasShown.call(this);
283 this._breadcrumbs.update();
284
285 for (var i = 0; i < this._treeOutlines.length; ++i) {
286 var treeOutline = this._treeOutlines[i];
287 treeOutline.setVisible(true);
288
289 if (!treeOutline.rootDOMNode)
290 if (treeOutline.domModel().existingDocument())
291 this._documentUpdated(treeOutline.domModel(), treeOutline.do mModel().existingDocument());
292 else
293 treeOutline.domModel().requestDocument();
294 }
295 this.focus();
296 },
297
298 willHide: function()
299 {
300 WebInspector.context.setFlavor(WebInspector.ElementsPanel, null);
301
302 WebInspector.DOMModel.hideDOMNodeHighlight();
303 for (var i = 0; i < this._treeOutlines.length; ++i) {
304 var treeOutline = this._treeOutlines[i];
305 treeOutline.setVisible(false);
306 // Detach heavy component on hide
307 this._contentElement.removeChild(treeOutline.element);
308 }
309 if (this._popoverHelper)
310 this._popoverHelper.hidePopover();
311 WebInspector.Panel.prototype.willHide.call(this);
312 },
313
314 onResize: function()
315 {
316 if (WebInspector.moduleSetting("sidebarPosition").get() === "auto")
317 this.element.window().requestAnimationFrame(this._updateSidebarPosit ion.bind(this)); // Do not force layout.
318 this._updateTreeOutlineVisibleWidth();
319 },
320 844
321 /** 845 /**
322 * @param {!WebInspector.Event} event 846 * @param {!WebInspector.Event} event
847 * @this {WebInspector.ElementsPanel}
323 */ 848 */
324 _selectedNodeChanged: function(event) 849 function tabSelected(event) {
325 { 850 var tabId = /** @type {string} */ (event.data.tabId);
326 var selectedNode = /** @type {?WebInspector.DOMNode} */ (event.data.node ); 851 if (tabId === WebInspector.UIString('Computed'))
327 var focus = /** @type {boolean} */ (event.data.focus); 852 showMetrics.call(this, true);
328 for (var i = 0; i < this._treeOutlines.length; ++i) { 853 else if (tabId === WebInspector.UIString('Styles'))
329 if (!selectedNode || selectedNode.domModel() !== this._treeOutlines[ i].domModel()) 854 showMetrics.call(this, false);
330 this._treeOutlines[i].selectDOMNode(null); 855 }
856
857 this.sidebarPaneView =
858 WebInspector.viewManager.createTabbedLocation(() => WebInspector.viewMan ager.showView('elements'));
859 var tabbedPane = this.sidebarPaneView.tabbedPane();
860 tabbedPane.element.addEventListener('contextmenu', this._sidebarContextMenuE ventFired.bind(this), false);
861 if (this._popoverHelper)
862 this._popoverHelper.hidePopover();
863 this._popoverHelper = new WebInspector.PopoverHelper(tabbedPane.element);
864 this._popoverHelper.initializeCallbacks(this._getPopoverAnchor.bind(this), t his._showPopover.bind(this));
865 this._popoverHelper.setTimeout(0);
866
867 if (horizontally) {
868 // Styles and computed are merged into a single tab.
869 this._splitWidget.installResizer(tabbedPane.headerElement());
870
871 var stylesView = new WebInspector.SimpleView(WebInspector.UIString('Styles '));
872 stylesView.element.classList.add('flex-auto');
873
874 var splitWidget = new WebInspector.SplitWidget(true, true, 'stylesPaneSpli tViewState', 215);
875 splitWidget.show(stylesView.element);
876
877 splitWidget.setMainWidget(matchedStylesContainer);
878 splitWidget.setSidebarWidget(computedStylePanesWrapper);
879
880 this.sidebarPaneView.appendView(stylesView);
881 this._stylesViewToReveal = stylesView;
882 } else {
883 // Styles and computed are in separate tabs.
884 var stylesView = new WebInspector.SimpleView(WebInspector.UIString('Styles '));
885 stylesView.element.classList.add('flex-auto', 'metrics-and-styles');
886 matchedStylesContainer.show(stylesView.element);
887
888 var computedView = new WebInspector.SimpleView(WebInspector.UIString('Comp uted'));
889 computedView.element.classList.add('composite', 'fill', 'metrics-and-compu ted');
890 computedStylePanesWrapper.show(computedView.element);
891
892 tabbedPane.addEventListener(WebInspector.TabbedPane.Events.TabSelected, ta bSelected, this);
893 this.sidebarPaneView.appendView(stylesView);
894 this.sidebarPaneView.appendView(computedView);
895 this._stylesViewToReveal = stylesView;
896 }
897
898 showMetrics.call(this, horizontally);
899
900 this.sidebarPaneView.appendApplicableItems('elements-sidebar');
901 for (var i = 0; i < extensionSidebarPanes.length; ++i)
902 this._addExtensionSidebarPane(extensionSidebarPanes[i]);
903
904 this._splitWidget.setSidebarWidget(this.sidebarPaneView.tabbedPane());
905 }
906
907 /**
908 * @param {!WebInspector.Event} event
909 */
910 _extensionSidebarPaneAdded(event) {
911 var pane = /** @type {!WebInspector.ExtensionSidebarPane} */ (event.data);
912 this._addExtensionSidebarPane(pane);
913 }
914
915 /**
916 * @param {!WebInspector.ExtensionSidebarPane} pane
917 */
918 _addExtensionSidebarPane(pane) {
919 if (pane.panelName() === this.name)
920 this.sidebarPaneView.appendView(pane);
921 }
922 };
923
924 WebInspector.ElementsPanel._elementsSidebarViewTitleSymbol = Symbol('title');
925
926 /**
927 * @implements {WebInspector.ContextMenu.Provider}
928 * @unrestricted
929 */
930 WebInspector.ElementsPanel.ContextMenuProvider = class {
931 /**
932 * @override
933 * @param {!Event} event
934 * @param {!WebInspector.ContextMenu} contextMenu
935 * @param {!Object} object
936 */
937 appendApplicableItems(event, contextMenu, object) {
938 if (!(object instanceof WebInspector.RemoteObject &&
939 (/** @type {!WebInspector.RemoteObject} */ (object)).isNode()) &&
940 !(object instanceof WebInspector.DOMNode) && !(object instanceof WebInsp ector.DeferredDOMNode)) {
941 return;
942 }
943
944 // Add debbuging-related actions
945 if (object instanceof WebInspector.DOMNode) {
946 contextMenu.appendSeparator();
947 WebInspector.domBreakpointsSidebarPane.populateNodeContextMenu(object, con textMenu, true);
948 }
949
950 // Skip adding "Reveal..." menu item for our own tree outline.
951 if (WebInspector.ElementsPanel.instance().element.isAncestor(/** @type {!Nod e} */ (event.target)))
952 return;
953 var commandCallback = WebInspector.Revealer.reveal.bind(WebInspector.Reveale r, object);
954 contextMenu.appendItem(WebInspector.UIString.capitalize('Reveal in Elements ^panel'), commandCallback);
955 }
956 };
957
958 /**
959 * @implements {WebInspector.Revealer}
960 * @unrestricted
961 */
962 WebInspector.ElementsPanel.DOMNodeRevealer = class {
963 /**
964 * @override
965 * @param {!Object} node
966 * @return {!Promise}
967 */
968 reveal(node) {
969 var panel = WebInspector.ElementsPanel.instance();
970 panel._pendingNodeReveal = true;
971
972 return new Promise(revealPromise);
973
974 /**
975 * @param {function(undefined)} resolve
976 * @param {function(!Error)} reject
977 */
978 function revealPromise(resolve, reject) {
979 if (node instanceof WebInspector.DOMNode) {
980 onNodeResolved(/** @type {!WebInspector.DOMNode} */ (node));
981 } else if (node instanceof WebInspector.DeferredDOMNode) {
982 (/** @type {!WebInspector.DeferredDOMNode} */ (node)).resolve(onNodeReso lved);
983 } else if (node instanceof WebInspector.RemoteObject) {
984 var domModel = WebInspector.DOMModel.fromTarget(/** @type {!WebInspector .RemoteObject} */ (node).target());
985 if (domModel)
986 domModel.pushObjectAsNodeToFrontend(node, onNodeResolved);
987 else
988 reject(new Error('Could not resolve a node to reveal.'));
989 } else {
990 reject(new Error('Can\'t reveal a non-node.'));
991 panel._pendingNodeReveal = false;
992 }
993
994 /**
995 * @param {?WebInspector.DOMNode} resolvedNode
996 */
997 function onNodeResolved(resolvedNode) {
998 panel._pendingNodeReveal = false;
999
1000 if (resolvedNode) {
1001 panel.revealAndSelectNode(resolvedNode).then(resolve);
1002 return;
331 } 1003 }
332 1004 reject(new Error('Could not resolve node to reveal.'));
333 this._breadcrumbs.setSelectedNode(selectedNode); 1005 }
334 1006 }
335 WebInspector.context.setFlavor(WebInspector.DOMNode, selectedNode); 1007 }
336
337 if (!selectedNode)
338 return;
339 selectedNode.setAsInspectedNode();
340 if (focus) {
341 this._selectedNodeOnReset = selectedNode;
342 this._hasNonDefaultSelectedNode = true;
343 }
344
345 var executionContexts = selectedNode.target().runtimeModel.executionCont exts();
346 var nodeFrameId = selectedNode.frameId();
347 for (var context of executionContexts) {
348 if (context.frameId === nodeFrameId) {
349 WebInspector.context.setFlavor(WebInspector.ExecutionContext, co ntext);
350 break;
351 }
352 }
353 },
354
355 _reset: function()
356 {
357 delete this.currentQuery;
358 },
359
360 /**
361 * @param {!WebInspector.Event} event
362 */
363 _documentUpdatedEvent: function(event)
364 {
365 this._documentUpdated(/** @type {!WebInspector.DOMModel} */ (event.targe t), /** @type {?WebInspector.DOMDocument} */ (event.data));
366 },
367
368 /**
369 * @param {!WebInspector.DOMModel} domModel
370 * @param {?WebInspector.DOMDocument} inspectedRootDocument
371 */
372 _documentUpdated: function(domModel, inspectedRootDocument)
373 {
374 this._reset();
375 this.searchCanceled();
376
377 var treeOutline = WebInspector.ElementsTreeOutline.forDOMModel(domModel) ;
378 treeOutline.rootDOMNode = inspectedRootDocument;
379
380 if (!inspectedRootDocument) {
381 if (this.isShowing())
382 domModel.requestDocument();
383 return;
384 }
385
386 this._hasNonDefaultSelectedNode = false;
387 WebInspector.domBreakpointsSidebarPane.restoreBreakpoints(inspectedRootD ocument);
388
389 if (this._omitDefaultSelection)
390 return;
391
392 var savedSelectedNodeOnReset = this._selectedNodeOnReset;
393 restoreNode.call(this, domModel, this._selectedNodeOnReset);
394
395 /**
396 * @param {!WebInspector.DOMModel} domModel
397 * @param {?WebInspector.DOMNode} staleNode
398 * @this {WebInspector.ElementsPanel}
399 */
400 function restoreNode(domModel, staleNode)
401 {
402 var nodePath = staleNode ? staleNode.path() : null;
403 if (!nodePath) {
404 onNodeRestored.call(this, null);
405 return;
406 }
407 domModel.pushNodeByPathToFrontend(nodePath, onNodeRestored.bind(this ));
408 }
409
410 /**
411 * @param {?DOMAgent.NodeId} restoredNodeId
412 * @this {WebInspector.ElementsPanel}
413 */
414 function onNodeRestored(restoredNodeId)
415 {
416 if (savedSelectedNodeOnReset !== this._selectedNodeOnReset)
417 return;
418 var node = restoredNodeId ? domModel.nodeForId(restoredNodeId) : nul l;
419 if (!node) {
420 var inspectedDocument = domModel.existingDocument();
421 node = inspectedDocument ? inspectedDocument.body || inspectedDo cument.documentElement : null;
422 }
423 this._setDefaultSelectedNode(node);
424 this._lastSelectedNodeSelectedForTest();
425 }
426 },
427
428 _lastSelectedNodeSelectedForTest: function() { },
429
430 /**
431 * @param {?WebInspector.DOMNode} node
432 */
433 _setDefaultSelectedNode: function(node)
434 {
435 if (!node || this._hasNonDefaultSelectedNode || this._pendingNodeReveal)
436 return;
437 var treeOutline = WebInspector.ElementsTreeOutline.forDOMModel(node.domM odel());
438 if (!treeOutline)
439 return;
440 this.selectDOMNode(node);
441 if (treeOutline.selectedTreeElement)
442 treeOutline.selectedTreeElement.expand();
443 },
444
445 /**
446 * @override
447 */
448 searchCanceled: function()
449 {
450 delete this._searchQuery;
451 this._hideSearchHighlights();
452
453 this._searchableView.updateSearchMatchesCount(0);
454
455 delete this._currentSearchResultIndex;
456 delete this._searchResults;
457
458 WebInspector.DOMModel.cancelSearch();
459 },
460
461 /**
462 * @override
463 * @param {!WebInspector.SearchableView.SearchConfig} searchConfig
464 * @param {boolean} shouldJump
465 * @param {boolean=} jumpBackwards
466 */
467 performSearch: function(searchConfig, shouldJump, jumpBackwards)
468 {
469 var query = searchConfig.query;
470 // Call searchCanceled since it will reset everything we need before doi ng a new search.
471 this.searchCanceled();
472
473 const whitespaceTrimmedQuery = query.trim();
474 if (!whitespaceTrimmedQuery.length)
475 return;
476
477 this._searchQuery = query;
478
479 var promises = [];
480 var domModels = WebInspector.DOMModel.instances();
481 for (var domModel of domModels)
482 promises.push(domModel.performSearchPromise(whitespaceTrimmedQuery, WebInspector.moduleSetting("showUAShadowDOM").get()));
483 Promise.all(promises).then(resultCountCallback.bind(this));
484
485 /**
486 * @param {!Array.<number>} resultCounts
487 * @this {WebInspector.ElementsPanel}
488 */
489 function resultCountCallback(resultCounts)
490 {
491 /**
492 * @type {!Array.<{domModel: !WebInspector.DOMModel, index: number, node: (?WebInspector.DOMNode|undefined)}>}
493 */
494 this._searchResults = [];
495 for (var i = 0; i < resultCounts.length; ++i) {
496 var resultCount = resultCounts[i];
497 for (var j = 0; j < resultCount; ++j)
498 this._searchResults.push({domModel: domModels[i], index: j, node: undefined});
499 }
500 this._searchableView.updateSearchMatchesCount(this._searchResults.le ngth);
501 if (!this._searchResults.length)
502 return;
503 this._currentSearchResultIndex = -1;
504
505 if (shouldJump)
506 this._jumpToSearchResult(jumpBackwards ? -1 : 0);
507 }
508 },
509
510 _domWordWrapSettingChanged: function(event)
511 {
512 // FIXME: crbug.com/425984
513 this._contentElement.classList.toggle("elements-wrap", event.data);
514 for (var i = 0; i < this._treeOutlines.length; ++i)
515 this._treeOutlines[i].setWordWrap(/** @type {boolean} */ (event.data ));
516 },
517
518 switchToAndFocus: function(node)
519 {
520 // Reset search restore.
521 this._searchableView.cancelSearch();
522 WebInspector.viewManager.showView("elements").then(() => this.selectDOMN ode(node, true));
523 },
524
525 /**
526 * @param {!Element} element
527 * @param {!Event} event
528 * @return {!Element|!AnchorBox|undefined}
529 */
530 _getPopoverAnchor: function(element, event)
531 {
532 var anchor = element.enclosingNodeOrSelfWithClass("webkit-html-resource- link");
533 if (!anchor || !anchor.href)
534 return;
535
536 return anchor;
537 },
538
539 /**
540 * @param {!Element} anchor
541 * @param {!WebInspector.Popover} popover
542 */
543 _showPopover: function(anchor, popover)
544 {
545 var node = this.selectedDOMNode();
546 if (node)
547 WebInspector.DOMPresentationUtils.buildImagePreviewContents(node.tar get(), anchor.href, true, showPopover);
548
549 /**
550 * @param {!Element=} contents
551 */
552 function showPopover(contents)
553 {
554 if (!contents)
555 return;
556 popover.setCanShrink(false);
557 popover.showForAnchor(contents, anchor);
558 }
559 },
560
561 _jumpToSearchResult: function(index)
562 {
563 this._hideSearchHighlights();
564 this._currentSearchResultIndex = (index + this._searchResults.length) % this._searchResults.length;
565 this._highlightCurrentSearchResult();
566 },
567
568 /**
569 * @override
570 */
571 jumpToNextSearchResult: function()
572 {
573 if (!this._searchResults)
574 return;
575 this._jumpToSearchResult(this._currentSearchResultIndex + 1);
576 },
577
578 /**
579 * @override
580 */
581 jumpToPreviousSearchResult: function()
582 {
583 if (!this._searchResults)
584 return;
585 this._jumpToSearchResult(this._currentSearchResultIndex - 1);
586 },
587
588 /**
589 * @override
590 * @return {boolean}
591 */
592 supportsCaseSensitiveSearch: function()
593 {
594 return false;
595 },
596
597 /**
598 * @override
599 * @return {boolean}
600 */
601 supportsRegexSearch: function()
602 {
603 return false;
604 },
605
606 _highlightCurrentSearchResult: function()
607 {
608 var index = this._currentSearchResultIndex;
609 var searchResults = this._searchResults;
610 var searchResult = searchResults[index];
611
612 if (searchResult.node === null) {
613 this._searchableView.updateCurrentMatchIndex(index);
614 return;
615 }
616
617 /**
618 * @param {?WebInspector.DOMNode} node
619 * @this {WebInspector.ElementsPanel}
620 */
621 function searchCallback(node)
622 {
623 searchResult.node = node;
624 this._highlightCurrentSearchResult();
625 }
626
627 if (typeof searchResult.node === "undefined") {
628 // No data for slot, request it.
629 searchResult.domModel.searchResult(searchResult.index, searchCallbac k.bind(this));
630 return;
631 }
632
633 this._searchableView.updateCurrentMatchIndex(index);
634
635 var treeElement = this._treeElementForNode(searchResult.node);
636 if (treeElement) {
637 treeElement.highlightSearchResults(this._searchQuery);
638 treeElement.reveal();
639 var matches = treeElement.listItemElement.getElementsByClassName(Web Inspector.highlightedSearchResultClassName);
640 if (matches.length)
641 matches[0].scrollIntoViewIfNeeded(false);
642 }
643 },
644
645 _hideSearchHighlights: function()
646 {
647 if (!this._searchResults || !this._searchResults.length || this._current SearchResultIndex < 0)
648 return;
649 var searchResult = this._searchResults[this._currentSearchResultIndex];
650 if (!searchResult.node)
651 return;
652 var treeOutline = WebInspector.ElementsTreeOutline.forDOMModel(searchRes ult.node.domModel());
653 var treeElement = treeOutline.findTreeElement(searchResult.node);
654 if (treeElement)
655 treeElement.hideSearchHighlights();
656 },
657
658 /**
659 * @return {?WebInspector.DOMNode}
660 */
661 selectedDOMNode: function()
662 {
663 for (var i = 0; i < this._treeOutlines.length; ++i) {
664 var treeOutline = this._treeOutlines[i];
665 if (treeOutline.selectedDOMNode())
666 return treeOutline.selectedDOMNode();
667 }
668 return null;
669 },
670
671 /**
672 * @param {!WebInspector.DOMNode} node
673 * @param {boolean=} focus
674 */
675 selectDOMNode: function(node, focus)
676 {
677 for (var i = 0; i < this._treeOutlines.length; ++i) {
678 var treeOutline = this._treeOutlines[i];
679 if (treeOutline.domModel() === node.domModel())
680 treeOutline.selectDOMNode(node, focus);
681 else
682 treeOutline.selectDOMNode(null);
683 }
684 },
685
686 /**
687 * @param {!WebInspector.Event} event
688 */
689 _updateBreadcrumbIfNeeded: function(event)
690 {
691 var nodes = /** @type {!Array.<!WebInspector.DOMNode>} */ (event.data);
692 this._breadcrumbs.updateNodes(nodes);
693 },
694
695 /**
696 * @param {!WebInspector.Event} event
697 */
698 _crumbNodeSelected: function(event)
699 {
700 var node = /** @type {!WebInspector.DOMNode} */ (event.data);
701 this.selectDOMNode(node, true);
702 },
703
704 /**
705 * @override
706 * @param {!KeyboardEvent} event
707 */
708 handleShortcut: function(event)
709 {
710 /**
711 * @param {!WebInspector.ElementsTreeOutline} treeOutline
712 */
713 function handleUndoRedo(treeOutline)
714 {
715 if (WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) && !even t.shiftKey && (event.key === "Z" || event.key === "z")) { // Z key
716 treeOutline.domModel().undo();
717 event.handled = true;
718 return;
719 }
720
721 var isRedoKey = WebInspector.isMac() ? event.metaKey && event.shiftK ey && (event.key === "Z" || event.key === "z") : // Z key
722 event.ctrlKey && (event.key = == "Y" || event.key === "y"); // Y key
723 if (isRedoKey) {
724 treeOutline.domModel().redo();
725 event.handled = true;
726 }
727 }
728
729 if (WebInspector.isEditing() && event.keyCode !== WebInspector.KeyboardS hortcut.Keys.F2.code)
730 return;
731
732 var treeOutline = null;
733 for (var i = 0; i < this._treeOutlines.length; ++i) {
734 if (this._treeOutlines[i].selectedDOMNode())
735 treeOutline = this._treeOutlines[i];
736 }
737 if (!treeOutline)
738 return;
739
740 if (!treeOutline.editing()) {
741 handleUndoRedo.call(null, treeOutline);
742 if (event.handled) {
743 this._stylesWidget.forceUpdate();
744 return;
745 }
746 }
747
748 treeOutline.handleShortcut(event);
749 if (event.handled)
750 return;
751
752 WebInspector.Panel.prototype.handleShortcut.call(this, event);
753 },
754
755 /**
756 * @param {?WebInspector.DOMNode} node
757 * @return {?WebInspector.ElementsTreeOutline}
758 */
759 _treeOutlineForNode: function(node)
760 {
761 if (!node)
762 return null;
763 return WebInspector.ElementsTreeOutline.forDOMModel(node.domModel());
764 },
765
766 /**
767 * @param {!WebInspector.DOMNode} node
768 * @return {?WebInspector.ElementsTreeElement}
769 */
770 _treeElementForNode: function(node)
771 {
772 var treeOutline = this._treeOutlineForNode(node);
773 return /** @type {?WebInspector.ElementsTreeElement} */ (treeOutline.fin dTreeElement(node));
774 },
775
776 /**
777 * @param {!WebInspector.DOMNode} node
778 * @return {!WebInspector.DOMNode}
779 */
780 _leaveUserAgentShadowDOM: function(node)
781 {
782 var userAgentShadowRoot;
783 while ((userAgentShadowRoot = node.ancestorUserAgentShadowRoot()) && use rAgentShadowRoot.parentNode)
784 node = userAgentShadowRoot.parentNode;
785 return node;
786 },
787
788 /**
789 * @param {!WebInspector.DOMNode} node
790 * @return {!Promise}
791 */
792 revealAndSelectNode: function(node)
793 {
794 if (WebInspector.inspectElementModeController && WebInspector.inspectEle mentModeController.isInInspectElementMode())
795 WebInspector.inspectElementModeController.stopInspection();
796
797 this._omitDefaultSelection = true;
798
799 node = WebInspector.moduleSetting("showUAShadowDOM").get() ? node : this ._leaveUserAgentShadowDOM(node);
800 node.highlightForTwoSeconds();
801
802 return WebInspector.viewManager.showView("elements").then(() => {
803 this.selectDOMNode(node, true);
804 delete this._omitDefaultSelection;
805
806 if (!this._notFirstInspectElement)
807 InspectorFrontendHost.inspectElementCompleted();
808 this._notFirstInspectElement = true;
809 });
810 },
811
812 _sidebarContextMenuEventFired: function(event)
813 {
814 var contextMenu = new WebInspector.ContextMenu(event);
815 contextMenu.appendApplicableItems(/** @type {!Object} */ (event.deepElem entFromPoint()));
816 contextMenu.show();
817 },
818
819 _showUAShadowDOMChanged: function()
820 {
821 for (var i = 0; i < this._treeOutlines.length; ++i)
822 this._treeOutlines[i].update();
823 },
824
825 _updateSidebarPosition: function()
826 {
827 var horizontally;
828 var position = WebInspector.moduleSetting("sidebarPosition").get();
829 if (position === "right")
830 horizontally = false;
831 else if (position === "bottom")
832 horizontally = true;
833 else
834 horizontally = WebInspector.inspectorView.element.offsetWidth < 680;
835
836 if (this.sidebarPaneView && horizontally === !this._splitWidget.isVertic al())
837 return;
838
839 if (this.sidebarPaneView && this.sidebarPaneView.tabbedPane().shouldHide OnDetach())
840 return; // We can't reparent extension iframes.
841
842 var extensionSidebarPanes = WebInspector.extensionServer.sidebarPanes();
843 if (this.sidebarPaneView) {
844 this.sidebarPaneView.tabbedPane().detach();
845 this._splitWidget.uninstallResizer(this.sidebarPaneView.tabbedPane() .headerElement());
846 }
847
848 this._splitWidget.setVertical(!horizontally);
849 this.showToolbarPane(null);
850
851 var matchedStylesContainer = new WebInspector.VBox();
852 matchedStylesContainer.element.appendChild(this._stylesSidebarToolbar);
853 var matchedStylePanesWrapper = new WebInspector.VBox();
854 matchedStylePanesWrapper.element.classList.add("style-panes-wrapper");
855 matchedStylePanesWrapper.show(matchedStylesContainer.element);
856 this._stylesWidget.show(matchedStylePanesWrapper.element);
857
858 var computedStylePanesWrapper = new WebInspector.VBox();
859 computedStylePanesWrapper.element.classList.add("style-panes-wrapper");
860 this._computedStyleWidget.show(computedStylePanesWrapper.element);
861
862 /**
863 * @param {boolean} inComputedStyle
864 * @this {WebInspector.ElementsPanel}
865 */
866 function showMetrics(inComputedStyle)
867 {
868 if (inComputedStyle)
869 this._metricsWidget.show(computedStylePanesWrapper.element, this ._computedStyleWidget.element);
870 else
871 this._metricsWidget.show(matchedStylePanesWrapper.element);
872 }
873
874 /**
875 * @param {!WebInspector.Event} event
876 * @this {WebInspector.ElementsPanel}
877 */
878 function tabSelected(event)
879 {
880 var tabId = /** @type {string} */ (event.data.tabId);
881 if (tabId === WebInspector.UIString("Computed"))
882 showMetrics.call(this, true);
883 else if (tabId === WebInspector.UIString("Styles"))
884 showMetrics.call(this, false);
885 }
886
887 this.sidebarPaneView = WebInspector.viewManager.createTabbedLocation(() => WebInspector.viewManager.showView("elements"));
888 var tabbedPane = this.sidebarPaneView.tabbedPane();
889 tabbedPane.element.addEventListener("contextmenu", this._sidebarContextM enuEventFired.bind(this), false);
890 if (this._popoverHelper)
891 this._popoverHelper.hidePopover();
892 this._popoverHelper = new WebInspector.PopoverHelper(tabbedPane.element) ;
893 this._popoverHelper.initializeCallbacks(this._getPopoverAnchor.bind(this ), this._showPopover.bind(this));
894 this._popoverHelper.setTimeout(0);
895
896 if (horizontally) {
897 // Styles and computed are merged into a single tab.
898 this._splitWidget.installResizer(tabbedPane.headerElement());
899
900 var stylesView = new WebInspector.SimpleView(WebInspector.UIString(" Styles"));
901 stylesView.element.classList.add("flex-auto");
902
903 var splitWidget = new WebInspector.SplitWidget(true, true, "stylesPa neSplitViewState", 215);
904 splitWidget.show(stylesView.element);
905
906 splitWidget.setMainWidget(matchedStylesContainer);
907 splitWidget.setSidebarWidget(computedStylePanesWrapper);
908
909 this.sidebarPaneView.appendView(stylesView);
910 this._stylesViewToReveal = stylesView;
911 } else {
912 // Styles and computed are in separate tabs.
913 var stylesView = new WebInspector.SimpleView(WebInspector.UIString(" Styles"));
914 stylesView.element.classList.add("flex-auto", "metrics-and-styles");
915 matchedStylesContainer.show(stylesView.element);
916
917 var computedView = new WebInspector.SimpleView(WebInspector.UIString ("Computed"));
918 computedView.element.classList.add("composite", "fill", "metrics-and -computed");
919 computedStylePanesWrapper.show(computedView.element);
920
921 tabbedPane.addEventListener(WebInspector.TabbedPane.Events.TabSelect ed, tabSelected, this);
922 this.sidebarPaneView.appendView(stylesView);
923 this.sidebarPaneView.appendView(computedView);
924 this._stylesViewToReveal = stylesView;
925 }
926
927 showMetrics.call(this, horizontally);
928
929 this.sidebarPaneView.appendApplicableItems("elements-sidebar");
930 for (var i = 0; i < extensionSidebarPanes.length; ++i)
931 this._addExtensionSidebarPane(extensionSidebarPanes[i]);
932
933 this._splitWidget.setSidebarWidget(this.sidebarPaneView.tabbedPane());
934 },
935
936 /**
937 * @param {!WebInspector.Event} event
938 */
939 _extensionSidebarPaneAdded: function(event)
940 {
941 var pane = /** @type {!WebInspector.ExtensionSidebarPane} */ (event.data );
942 this._addExtensionSidebarPane(pane);
943 },
944
945 /**
946 * @param {!WebInspector.ExtensionSidebarPane} pane
947 */
948 _addExtensionSidebarPane: function(pane)
949 {
950 if (pane.panelName() === this.name)
951 this.sidebarPaneView.appendView(pane);
952 },
953
954 __proto__: WebInspector.Panel.prototype
955 }; 1008 };
956 1009
957 /** 1010 /**
958 * @constructor 1011 * @implements {WebInspector.Revealer}
959 * @implements {WebInspector.ContextMenu.Provider} 1012 * @unrestricted
960 */ 1013 */
961 WebInspector.ElementsPanel.ContextMenuProvider = function() 1014 WebInspector.ElementsPanel.CSSPropertyRevealer = class {
962 { 1015 /**
1016 * @override
1017 * @param {!Object} property
1018 * @return {!Promise}
1019 */
1020 reveal(property) {
1021 var panel = WebInspector.ElementsPanel.instance();
1022 return panel._revealProperty(/** @type {!WebInspector.CSSProperty} */ (prope rty));
1023 }
963 }; 1024 };
964 1025
965 WebInspector.ElementsPanel.ContextMenuProvider.prototype = { 1026
966 /** 1027 /**
967 * @override 1028 * @implements {WebInspector.ActionDelegate}
968 * @param {!Event} event 1029 * @unrestricted
969 * @param {!WebInspector.ContextMenu} contextMenu 1030 */
970 * @param {!Object} object 1031 WebInspector.ElementsActionDelegate = class {
971 */ 1032 /**
972 appendApplicableItems: function(event, contextMenu, object) 1033 * @override
973 { 1034 * @param {!WebInspector.Context} context
974 if (!(object instanceof WebInspector.RemoteObject && (/** @type {!WebIns pector.RemoteObject} */ (object)).isNode()) 1035 * @param {string} actionId
975 && !(object instanceof WebInspector.DOMNode) 1036 * @return {boolean}
976 && !(object instanceof WebInspector.DeferredDOMNode)) { 1037 */
977 return; 1038 handleAction(context, actionId) {
978 } 1039 var node = WebInspector.context.flavor(WebInspector.DOMNode);
979 1040 if (!node)
980 // Add debbuging-related actions 1041 return true;
981 if (object instanceof WebInspector.DOMNode) { 1042 var treeOutline = WebInspector.ElementsTreeOutline.forDOMModel(node.domModel ());
982 contextMenu.appendSeparator(); 1043 if (!treeOutline)
983 WebInspector.domBreakpointsSidebarPane.populateNodeContextMenu(objec t, contextMenu, true); 1044 return true;
984 } 1045
985 1046 switch (actionId) {
986 // Skip adding "Reveal..." menu item for our own tree outline. 1047 case 'elements.hide-element':
987 if (WebInspector.ElementsPanel.instance().element.isAncestor(/** @type { !Node} */ (event.target))) 1048 treeOutline.toggleHideElement(node);
988 return; 1049 return true;
989 var commandCallback = WebInspector.Revealer.reveal.bind(WebInspector.Rev ealer, object); 1050 case 'elements.edit-as-html':
990 contextMenu.appendItem(WebInspector.UIString.capitalize("Reveal in Eleme nts ^panel"), commandCallback); 1051 treeOutline.toggleEditAsHTML(node);
991 } 1052 return true;
1053 }
1054 return false;
1055 }
992 }; 1056 };
993 1057
994 /** 1058 /**
995 * @constructor 1059 * @implements {WebInspector.DOMPresentationUtils.MarkerDecorator}
996 * @implements {WebInspector.Revealer} 1060 * @unrestricted
997 */ 1061 */
998 WebInspector.ElementsPanel.DOMNodeRevealer = function() { }; 1062 WebInspector.ElementsPanel.PseudoStateMarkerDecorator = class {
999 1063 /**
1000 WebInspector.ElementsPanel.DOMNodeRevealer.prototype = { 1064 * @override
1001 /** 1065 * @param {!WebInspector.DOMNode} node
1002 * @override 1066 * @return {?{title: string, color: string}}
1003 * @param {!Object} node 1067 */
1004 * @return {!Promise} 1068 decorate(node) {
1005 */ 1069 return {
1006 reveal: function(node) 1070 color: 'orange',
1007 { 1071 title: WebInspector.UIString(
1008 var panel = WebInspector.ElementsPanel.instance(); 1072 'Element state: %s', ':' + WebInspector.CSSModel.fromNode(node).pseudo State(node).join(', :'))
1009 panel._pendingNodeReveal = true; 1073 };
1010 1074 }
1011 return new Promise(revealPromise);
1012
1013 /**
1014 * @param {function(undefined)} resolve
1015 * @param {function(!Error)} reject
1016 */
1017 function revealPromise(resolve, reject)
1018 {
1019 if (node instanceof WebInspector.DOMNode) {
1020 onNodeResolved(/** @type {!WebInspector.DOMNode} */ (node));
1021 } else if (node instanceof WebInspector.DeferredDOMNode) {
1022 (/** @type {!WebInspector.DeferredDOMNode} */ (node)).resolve(on NodeResolved);
1023 } else if (node instanceof WebInspector.RemoteObject) {
1024 var domModel = WebInspector.DOMModel.fromTarget(/** @type {!WebI nspector.RemoteObject} */ (node).target());
1025 if (domModel)
1026 domModel.pushObjectAsNodeToFrontend(node, onNodeResolved);
1027 else
1028 reject(new Error("Could not resolve a node to reveal."));
1029 } else {
1030 reject(new Error("Can't reveal a non-node."));
1031 panel._pendingNodeReveal = false;
1032 }
1033
1034 /**
1035 * @param {?WebInspector.DOMNode} resolvedNode
1036 */
1037 function onNodeResolved(resolvedNode)
1038 {
1039 panel._pendingNodeReveal = false;
1040
1041 if (resolvedNode) {
1042 panel.revealAndSelectNode(resolvedNode).then(resolve);
1043 return;
1044 }
1045 reject(new Error("Could not resolve node to reveal."));
1046 }
1047 }
1048 }
1049 }; 1075 };
1050
1051 /**
1052 * @constructor
1053 * @implements {WebInspector.Revealer}
1054 */
1055 WebInspector.ElementsPanel.CSSPropertyRevealer = function() { };
1056
1057 WebInspector.ElementsPanel.CSSPropertyRevealer.prototype = {
1058 /**
1059 * @override
1060 * @param {!Object} property
1061 * @return {!Promise}
1062 */
1063 reveal: function(property)
1064 {
1065 var panel = WebInspector.ElementsPanel.instance();
1066 return panel._revealProperty(/** @type {!WebInspector.CSSProperty} */ (p roperty));
1067 }
1068 };
1069
1070 /**
1071 * @return {!WebInspector.ElementsPanel}
1072 */
1073 WebInspector.ElementsPanel.instance = function()
1074 {
1075 return /** @type {!WebInspector.ElementsPanel} */ (self.runtime.sharedInstan ce(WebInspector.ElementsPanel));
1076 };
1077
1078 /**
1079 * @constructor
1080 * @implements {WebInspector.ActionDelegate}
1081 */
1082 WebInspector.ElementsActionDelegate = function() { };
1083
1084 WebInspector.ElementsActionDelegate.prototype = {
1085 /**
1086 * @override
1087 * @param {!WebInspector.Context} context
1088 * @param {string} actionId
1089 * @return {boolean}
1090 */
1091 handleAction: function(context, actionId)
1092 {
1093 var node = WebInspector.context.flavor(WebInspector.DOMNode);
1094 if (!node)
1095 return true;
1096 var treeOutline = WebInspector.ElementsTreeOutline.forDOMModel(node.domM odel());
1097 if (!treeOutline)
1098 return true;
1099
1100 switch (actionId) {
1101 case "elements.hide-element":
1102 treeOutline.toggleHideElement(node);
1103 return true;
1104 case "elements.edit-as-html":
1105 treeOutline.toggleEditAsHTML(node);
1106 return true;
1107 }
1108 return false;
1109 }
1110 };
1111
1112 /**
1113 * @constructor
1114 * @implements {WebInspector.DOMPresentationUtils.MarkerDecorator}
1115 */
1116 WebInspector.ElementsPanel.PseudoStateMarkerDecorator = function()
1117 {
1118 };
1119
1120 WebInspector.ElementsPanel.PseudoStateMarkerDecorator.prototype = {
1121 /**
1122 * @override
1123 * @param {!WebInspector.DOMNode} node
1124 * @return {?{title: string, color: string}}
1125 */
1126 decorate: function(node)
1127 {
1128 return { color: "orange", title: WebInspector.UIString("Element state: % s", ":" + WebInspector.CSSModel.fromNode(node).pseudoState(node).join(", :")) };
1129 }
1130 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698