| OLD | NEW |
| 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 }; | |
| OLD | NEW |