| Index: third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
|
| diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
|
| index 15b987827bd2dddb780552c5883e9bf3440c074f..8193317102866dd08dc151f4242aa964ec2a4297 100644
|
| --- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
|
| +++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
|
| @@ -27,39 +27,39 @@
|
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
| * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| */
|
| -
|
| /**
|
| - * @constructor
|
| - * @extends {TreeOutline}
|
| - * @param {!WebInspector.DOMModel} domModel
|
| - * @param {boolean=} omitRootDOMNode
|
| - * @param {boolean=} selectEnabled
|
| + * @unrestricted
|
| */
|
| -WebInspector.ElementsTreeOutline = function(domModel, omitRootDOMNode, selectEnabled)
|
| -{
|
| - TreeOutline.call(this);
|
| +WebInspector.ElementsTreeOutline = class extends TreeOutline {
|
| + /**
|
| + * @param {!WebInspector.DOMModel} domModel
|
| + * @param {boolean=} omitRootDOMNode
|
| + * @param {boolean=} selectEnabled
|
| + */
|
| + constructor(domModel, omitRootDOMNode, selectEnabled) {
|
| + super();
|
|
|
| this._domModel = domModel;
|
| - this._treeElementSymbol = Symbol("treeElement");
|
| - var shadowContainer = createElement("div");
|
| - this._shadowRoot = WebInspector.createShadowRootWithCoreStyles(shadowContainer, "elements/elementsTreeOutline.css");
|
| - var outlineDisclosureElement = this._shadowRoot.createChild("div", "elements-disclosure");
|
| + this._treeElementSymbol = Symbol('treeElement');
|
| + var shadowContainer = createElement('div');
|
| + this._shadowRoot = WebInspector.createShadowRootWithCoreStyles(shadowContainer, 'elements/elementsTreeOutline.css');
|
| + var outlineDisclosureElement = this._shadowRoot.createChild('div', 'elements-disclosure');
|
|
|
| this._element = this.element;
|
| - this._element.classList.add("elements-tree-outline", "source-code");
|
| - this._element.addEventListener("mousedown", this._onmousedown.bind(this), false);
|
| - this._element.addEventListener("mousemove", this._onmousemove.bind(this), false);
|
| - this._element.addEventListener("mouseleave", this._onmouseleave.bind(this), false);
|
| - this._element.addEventListener("dragstart", this._ondragstart.bind(this), false);
|
| - this._element.addEventListener("dragover", this._ondragover.bind(this), false);
|
| - this._element.addEventListener("dragleave", this._ondragleave.bind(this), false);
|
| - this._element.addEventListener("drop", this._ondrop.bind(this), false);
|
| - this._element.addEventListener("dragend", this._ondragend.bind(this), false);
|
| - this._element.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), false);
|
| - this._element.addEventListener("clipboard-beforecopy", this._onBeforeCopy.bind(this), false);
|
| - this._element.addEventListener("clipboard-copy", this._onCopyOrCut.bind(this, false), false);
|
| - this._element.addEventListener("clipboard-cut", this._onCopyOrCut.bind(this, true), false);
|
| - this._element.addEventListener("clipboard-paste", this._onPaste.bind(this), false);
|
| + this._element.classList.add('elements-tree-outline', 'source-code');
|
| + this._element.addEventListener('mousedown', this._onmousedown.bind(this), false);
|
| + this._element.addEventListener('mousemove', this._onmousemove.bind(this), false);
|
| + this._element.addEventListener('mouseleave', this._onmouseleave.bind(this), false);
|
| + this._element.addEventListener('dragstart', this._ondragstart.bind(this), false);
|
| + this._element.addEventListener('dragover', this._ondragover.bind(this), false);
|
| + this._element.addEventListener('dragleave', this._ondragleave.bind(this), false);
|
| + this._element.addEventListener('drop', this._ondrop.bind(this), false);
|
| + this._element.addEventListener('dragend', this._ondragend.bind(this), false);
|
| + this._element.addEventListener('contextmenu', this._contextMenuEventFired.bind(this), false);
|
| + this._element.addEventListener('clipboard-beforecopy', this._onBeforeCopy.bind(this), false);
|
| + this._element.addEventListener('clipboard-copy', this._onCopyOrCut.bind(this, false), false);
|
| + this._element.addEventListener('clipboard-cut', this._onCopyOrCut.bind(this, true), false);
|
| + this._element.addEventListener('clipboard-paste', this._onPaste.bind(this), false);
|
|
|
| outlineDisclosureElement.appendChild(this._element);
|
| this.element = shadowContainer;
|
| @@ -83,1719 +83,1625 @@ WebInspector.ElementsTreeOutline = function(domModel, omitRootDOMNode, selectEna
|
| this._treeElementsBeingUpdated = new Set();
|
|
|
| this._domModel.addEventListener(WebInspector.DOMModel.Events.MarkersChanged, this._markersChanged, this);
|
| - this._showHTMLCommentsSetting = WebInspector.moduleSetting("showHTMLComments");
|
| + this._showHTMLCommentsSetting = WebInspector.moduleSetting('showHTMLComments');
|
| this._showHTMLCommentsSetting.addChangeListener(this._onShowHTMLCommentsChange.bind(this));
|
| -};
|
| -
|
| -WebInspector.ElementsTreeOutline._treeOutlineSymbol = Symbol("treeOutline");
|
| + }
|
|
|
| -/**
|
| - * @param {!WebInspector.DOMModel} domModel
|
| - * @return {?WebInspector.ElementsTreeOutline}
|
| - */
|
| -WebInspector.ElementsTreeOutline.forDOMModel = function(domModel)
|
| -{
|
| + /**
|
| + * @param {!WebInspector.DOMModel} domModel
|
| + * @return {?WebInspector.ElementsTreeOutline}
|
| + */
|
| + static forDOMModel(domModel) {
|
| return domModel[WebInspector.ElementsTreeOutline._treeOutlineSymbol] || null;
|
| -};
|
| -
|
| -/** @typedef {{node: !WebInspector.DOMNode, isCut: boolean}} */
|
| -WebInspector.ElementsTreeOutline.ClipboardData;
|
| -
|
| -/** @enum {symbol} */
|
| -WebInspector.ElementsTreeOutline.Events = {
|
| - SelectedNodeChanged: Symbol("SelectedNodeChanged"),
|
| - ElementsTreeUpdated: Symbol("ElementsTreeUpdated")
|
| -};
|
| -
|
| -/**
|
| - * @const
|
| - * @type {!Object.<string, string>}
|
| - */
|
| -WebInspector.ElementsTreeOutline.MappedCharToEntity = {
|
| - "\u00a0": "nbsp",
|
| - "\u0093": "#147", // <control>
|
| - "\u00ad": "shy",
|
| - "\u2002": "ensp",
|
| - "\u2003": "emsp",
|
| - "\u2009": "thinsp",
|
| - "\u200a": "#8202", // Hairspace
|
| - "\u200b": "#8203", // ZWSP
|
| - "\u200c": "zwnj",
|
| - "\u200d": "zwj",
|
| - "\u200e": "lrm",
|
| - "\u200f": "rlm",
|
| - "\u202a": "#8234", // LRE
|
| - "\u202b": "#8235", // RLE
|
| - "\u202c": "#8236", // PDF
|
| - "\u202d": "#8237", // LRO
|
| - "\u202e": "#8238", // RLO
|
| - "\ufeff": "#65279" // BOM
|
| -};
|
| -
|
| -WebInspector.ElementsTreeOutline.prototype = {
|
| - _onShowHTMLCommentsChange: function()
|
| - {
|
| - var selectedNode = this.selectedDOMNode();
|
| - if (selectedNode && selectedNode.nodeType() === Node.COMMENT_NODE && !this._showHTMLCommentsSetting.get())
|
| - this.selectDOMNode(selectedNode.parentNode);
|
| - this.update();
|
| - },
|
| -
|
| - /**
|
| - * @return {symbol}
|
| - */
|
| - treeElementSymbol: function()
|
| - {
|
| - return this._treeElementSymbol;
|
| - },
|
| -
|
| - focus: function()
|
| - {
|
| - this._element.focus();
|
| - },
|
| -
|
| - /**
|
| - * @param {boolean} wrap
|
| - */
|
| - setWordWrap: function(wrap)
|
| - {
|
| - this._element.classList.toggle("elements-tree-nowrap", !wrap);
|
| - },
|
| -
|
| - /**
|
| - * @return {!WebInspector.DOMModel}
|
| - */
|
| - domModel: function()
|
| - {
|
| - return this._domModel;
|
| - },
|
| -
|
| - /**
|
| - * @param {?WebInspector.InplaceEditor.Controller} multilineEditing
|
| - */
|
| - setMultilineEditing: function(multilineEditing)
|
| - {
|
| - this._multilineEditing = multilineEditing;
|
| - },
|
| -
|
| - /**
|
| - * @return {number}
|
| - */
|
| - visibleWidth: function()
|
| - {
|
| - return this._visibleWidth;
|
| - },
|
| -
|
| - /**
|
| - * @param {number} width
|
| - */
|
| - setVisibleWidth: function(width)
|
| - {
|
| - this._visibleWidth = width;
|
| - if (this._multilineEditing)
|
| - this._multilineEditing.setWidth(this._visibleWidth);
|
| - },
|
| -
|
| - /**
|
| - * @param {?WebInspector.ElementsTreeOutline.ClipboardData} data
|
| - */
|
| - _setClipboardData: function(data)
|
| - {
|
| - if (this._clipboardNodeData) {
|
| - var treeElement = this.findTreeElement(this._clipboardNodeData.node);
|
| - if (treeElement)
|
| - treeElement.setInClipboard(false);
|
| - delete this._clipboardNodeData;
|
| - }
|
| -
|
| - if (data) {
|
| - var treeElement = this.findTreeElement(data.node);
|
| - if (treeElement)
|
| - treeElement.setInClipboard(true);
|
| - this._clipboardNodeData = data;
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.DOMNode} removedNode
|
| - */
|
| - resetClipboardIfNeeded: function(removedNode)
|
| - {
|
| - if (this._clipboardNodeData && this._clipboardNodeData.node === removedNode)
|
| - this._setClipboardData(null);
|
| - },
|
| -
|
| - /**
|
| - * @param {!Event} event
|
| - */
|
| - _onBeforeCopy: function(event)
|
| - {
|
| - event.handled = true;
|
| - },
|
| -
|
| - /**
|
| - * @param {boolean} isCut
|
| - * @param {!Event} event
|
| - */
|
| - _onCopyOrCut: function(isCut, event)
|
| - {
|
| - this._setClipboardData(null);
|
| - var originalEvent = event["original"];
|
| -
|
| - // Don't prevent the normal copy if the user has a selection.
|
| - if (!originalEvent.target.isComponentSelectionCollapsed())
|
| - return;
|
| -
|
| - // Do not interfere with text editing.
|
| - if (WebInspector.isEditing())
|
| - return;
|
| -
|
| - var targetNode = this.selectedDOMNode();
|
| - if (!targetNode)
|
| - return;
|
| -
|
| - originalEvent.clipboardData.clearData();
|
| - event.handled = true;
|
| -
|
| - this.performCopyOrCut(isCut, targetNode);
|
| - },
|
| -
|
| - /**
|
| - * @param {boolean} isCut
|
| - * @param {?WebInspector.DOMNode} node
|
| - */
|
| - performCopyOrCut: function(isCut, node)
|
| - {
|
| - if (isCut && (node.isShadowRoot() || node.ancestorUserAgentShadowRoot()))
|
| - return;
|
| -
|
| - node.copyNode();
|
| - this._setClipboardData({ node: node, isCut: isCut });
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.DOMNode} targetNode
|
| - * @return {boolean}
|
| - */
|
| - canPaste: function(targetNode)
|
| - {
|
| - if (targetNode.isShadowRoot() || targetNode.ancestorUserAgentShadowRoot())
|
| - return false;
|
| -
|
| - if (!this._clipboardNodeData)
|
| - return false;
|
| -
|
| - var node = this._clipboardNodeData.node;
|
| - if (this._clipboardNodeData.isCut && (node === targetNode || node.isAncestor(targetNode)))
|
| - return false;
|
| -
|
| - if (targetNode.target() !== node.target())
|
| - return false;
|
| - return true;
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.DOMNode} targetNode
|
| - */
|
| - pasteNode: function(targetNode)
|
| - {
|
| - if (this.canPaste(targetNode))
|
| - this._performPaste(targetNode);
|
| - },
|
| -
|
| - /**
|
| - * @param {!Event} event
|
| - */
|
| - _onPaste: function(event)
|
| - {
|
| - // Do not interfere with text editing.
|
| - if (WebInspector.isEditing())
|
| - return;
|
| -
|
| - var targetNode = this.selectedDOMNode();
|
| - if (!targetNode || !this.canPaste(targetNode))
|
| - return;
|
| -
|
| - event.handled = true;
|
| - this._performPaste(targetNode);
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.DOMNode} targetNode
|
| - */
|
| - _performPaste: function(targetNode)
|
| - {
|
| - if (this._clipboardNodeData.isCut) {
|
| - this._clipboardNodeData.node.moveTo(targetNode, null, expandCallback.bind(this));
|
| - this._setClipboardData(null);
|
| - } else {
|
| - this._clipboardNodeData.node.copyTo(targetNode, null, expandCallback.bind(this));
|
| - }
|
| -
|
| - /**
|
| - * @param {?Protocol.Error} error
|
| - * @param {!DOMAgent.NodeId} nodeId
|
| - * @this {WebInspector.ElementsTreeOutline}
|
| - */
|
| - function expandCallback(error, nodeId)
|
| - {
|
| - if (error)
|
| - return;
|
| - var pastedNode = this._domModel.nodeForId(nodeId);
|
| - if (!pastedNode)
|
| - return;
|
| - this.selectDOMNode(pastedNode);
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * @param {boolean} visible
|
| - */
|
| - setVisible: function(visible)
|
| - {
|
| - this._visible = visible;
|
| - if (!this._visible) {
|
| - this._popoverHelper.hidePopover();
|
| - if (this._multilineEditing)
|
| - this._multilineEditing.cancel();
|
| - return;
|
| - }
|
| -
|
| - this.runPendingUpdates();
|
| - if (this._selectedDOMNode)
|
| - this._revealAndSelectNode(this._selectedDOMNode, false);
|
| - },
|
| -
|
| - get rootDOMNode()
|
| - {
|
| - return this._rootDOMNode;
|
| - },
|
| -
|
| - set rootDOMNode(x)
|
| - {
|
| - if (this._rootDOMNode === x)
|
| - return;
|
| -
|
| - this._rootDOMNode = x;
|
| -
|
| - this._isXMLMimeType = x && x.isXMLNode();
|
| -
|
| - this.update();
|
| - },
|
| -
|
| - get isXMLMimeType()
|
| - {
|
| - return this._isXMLMimeType;
|
| - },
|
| -
|
| - /**
|
| - * @return {?WebInspector.DOMNode}
|
| - */
|
| - selectedDOMNode: function()
|
| - {
|
| - return this._selectedDOMNode;
|
| - },
|
| -
|
| - /**
|
| - * @param {?WebInspector.DOMNode} node
|
| - * @param {boolean=} focus
|
| - */
|
| - selectDOMNode: function(node, focus)
|
| - {
|
| - if (this._selectedDOMNode === node) {
|
| - this._revealAndSelectNode(node, !focus);
|
| - return;
|
| - }
|
| -
|
| - this._selectedDOMNode = node;
|
| - this._revealAndSelectNode(node, !focus);
|
| + }
|
| +
|
| + _onShowHTMLCommentsChange() {
|
| + var selectedNode = this.selectedDOMNode();
|
| + if (selectedNode && selectedNode.nodeType() === Node.COMMENT_NODE && !this._showHTMLCommentsSetting.get())
|
| + this.selectDOMNode(selectedNode.parentNode);
|
| + this.update();
|
| + }
|
| +
|
| + /**
|
| + * @return {symbol}
|
| + */
|
| + treeElementSymbol() {
|
| + return this._treeElementSymbol;
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + */
|
| + focus() {
|
| + this._element.focus();
|
| + }
|
| +
|
| + /**
|
| + * @param {boolean} wrap
|
| + */
|
| + setWordWrap(wrap) {
|
| + this._element.classList.toggle('elements-tree-nowrap', !wrap);
|
| + }
|
| +
|
| + /**
|
| + * @return {!WebInspector.DOMModel}
|
| + */
|
| + domModel() {
|
| + return this._domModel;
|
| + }
|
| +
|
| + /**
|
| + * @param {?WebInspector.InplaceEditor.Controller} multilineEditing
|
| + */
|
| + setMultilineEditing(multilineEditing) {
|
| + this._multilineEditing = multilineEditing;
|
| + }
|
| +
|
| + /**
|
| + * @return {number}
|
| + */
|
| + visibleWidth() {
|
| + return this._visibleWidth;
|
| + }
|
| +
|
| + /**
|
| + * @param {number} width
|
| + */
|
| + setVisibleWidth(width) {
|
| + this._visibleWidth = width;
|
| + if (this._multilineEditing)
|
| + this._multilineEditing.setWidth(this._visibleWidth);
|
| + }
|
| +
|
| + /**
|
| + * @param {?WebInspector.ElementsTreeOutline.ClipboardData} data
|
| + */
|
| + _setClipboardData(data) {
|
| + if (this._clipboardNodeData) {
|
| + var treeElement = this.findTreeElement(this._clipboardNodeData.node);
|
| + if (treeElement)
|
| + treeElement.setInClipboard(false);
|
| + delete this._clipboardNodeData;
|
| + }
|
|
|
| - // The _revealAndSelectNode() method might find a different element if there is inlined text,
|
| - // and the select() call would change the selectedDOMNode and reenter this setter. So to
|
| - // avoid calling _selectedNodeChanged() twice, first check if _selectedDOMNode is the same
|
| - // node as the one passed in.
|
| - if (this._selectedDOMNode === node)
|
| - this._selectedNodeChanged(!!focus);
|
| - },
|
| + if (data) {
|
| + var treeElement = this.findTreeElement(data.node);
|
| + if (treeElement)
|
| + treeElement.setInClipboard(true);
|
| + this._clipboardNodeData = data;
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.DOMNode} removedNode
|
| + */
|
| + resetClipboardIfNeeded(removedNode) {
|
| + if (this._clipboardNodeData && this._clipboardNodeData.node === removedNode)
|
| + this._setClipboardData(null);
|
| + }
|
| +
|
| + /**
|
| + * @param {!Event} event
|
| + */
|
| + _onBeforeCopy(event) {
|
| + event.handled = true;
|
| + }
|
| +
|
| + /**
|
| + * @param {boolean} isCut
|
| + * @param {!Event} event
|
| + */
|
| + _onCopyOrCut(isCut, event) {
|
| + this._setClipboardData(null);
|
| + var originalEvent = event['original'];
|
| +
|
| + // Don't prevent the normal copy if the user has a selection.
|
| + if (!originalEvent.target.isComponentSelectionCollapsed())
|
| + return;
|
| +
|
| + // Do not interfere with text editing.
|
| + if (WebInspector.isEditing())
|
| + return;
|
| +
|
| + var targetNode = this.selectedDOMNode();
|
| + if (!targetNode)
|
| + return;
|
| +
|
| + originalEvent.clipboardData.clearData();
|
| + event.handled = true;
|
| +
|
| + this.performCopyOrCut(isCut, targetNode);
|
| + }
|
| +
|
| + /**
|
| + * @param {boolean} isCut
|
| + * @param {?WebInspector.DOMNode} node
|
| + */
|
| + performCopyOrCut(isCut, node) {
|
| + if (isCut && (node.isShadowRoot() || node.ancestorUserAgentShadowRoot()))
|
| + return;
|
| +
|
| + node.copyNode();
|
| + this._setClipboardData({node: node, isCut: isCut});
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.DOMNode} targetNode
|
| + * @return {boolean}
|
| + */
|
| + canPaste(targetNode) {
|
| + if (targetNode.isShadowRoot() || targetNode.ancestorUserAgentShadowRoot())
|
| + return false;
|
| +
|
| + if (!this._clipboardNodeData)
|
| + return false;
|
| +
|
| + var node = this._clipboardNodeData.node;
|
| + if (this._clipboardNodeData.isCut && (node === targetNode || node.isAncestor(targetNode)))
|
| + return false;
|
| +
|
| + if (targetNode.target() !== node.target())
|
| + return false;
|
| + return true;
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.DOMNode} targetNode
|
| + */
|
| + pasteNode(targetNode) {
|
| + if (this.canPaste(targetNode))
|
| + this._performPaste(targetNode);
|
| + }
|
| +
|
| + /**
|
| + * @param {!Event} event
|
| + */
|
| + _onPaste(event) {
|
| + // Do not interfere with text editing.
|
| + if (WebInspector.isEditing())
|
| + return;
|
| +
|
| + var targetNode = this.selectedDOMNode();
|
| + if (!targetNode || !this.canPaste(targetNode))
|
| + return;
|
| +
|
| + event.handled = true;
|
| + this._performPaste(targetNode);
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.DOMNode} targetNode
|
| + */
|
| + _performPaste(targetNode) {
|
| + if (this._clipboardNodeData.isCut) {
|
| + this._clipboardNodeData.node.moveTo(targetNode, null, expandCallback.bind(this));
|
| + this._setClipboardData(null);
|
| + } else {
|
| + this._clipboardNodeData.node.copyTo(targetNode, null, expandCallback.bind(this));
|
| + }
|
|
|
| /**
|
| - * @return {boolean}
|
| - */
|
| - editing: function()
|
| - {
|
| - var node = this.selectedDOMNode();
|
| - if (!node)
|
| - return false;
|
| - var treeElement = this.findTreeElement(node);
|
| - if (!treeElement)
|
| - return false;
|
| - return treeElement.isEditing() || false;
|
| - },
|
| -
|
| - update: function()
|
| - {
|
| - var selectedNode = this.selectedDOMNode();
|
| - this.removeChildren();
|
| - if (!this.rootDOMNode)
|
| - return;
|
| -
|
| - if (this._includeRootDOMNode) {
|
| - var treeElement = this._createElementTreeElement(this.rootDOMNode);
|
| - this.appendChild(treeElement);
|
| - } else {
|
| - // FIXME: this could use findTreeElement to reuse a tree element if it already exists
|
| - var children = this._visibleChildren(this.rootDOMNode);
|
| - for (var child of children) {
|
| - var treeElement = this._createElementTreeElement(child);
|
| - this.appendChild(treeElement);
|
| - }
|
| - }
|
| + * @param {?Protocol.Error} error
|
| + * @param {!DOMAgent.NodeId} nodeId
|
| + * @this {WebInspector.ElementsTreeOutline}
|
| + */
|
| + function expandCallback(error, nodeId) {
|
| + if (error)
|
| + return;
|
| + var pastedNode = this._domModel.nodeForId(nodeId);
|
| + if (!pastedNode)
|
| + return;
|
| + this.selectDOMNode(pastedNode);
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * @param {boolean} visible
|
| + */
|
| + setVisible(visible) {
|
| + this._visible = visible;
|
| + if (!this._visible) {
|
| + this._popoverHelper.hidePopover();
|
| + if (this._multilineEditing)
|
| + this._multilineEditing.cancel();
|
| + return;
|
| + }
|
|
|
| - if (selectedNode)
|
| - this._revealAndSelectNode(selectedNode, true);
|
| - },
|
| + this.runPendingUpdates();
|
| + if (this._selectedDOMNode)
|
| + this._revealAndSelectNode(this._selectedDOMNode, false);
|
| + }
|
| +
|
| + get rootDOMNode() {
|
| + return this._rootDOMNode;
|
| + }
|
| +
|
| + set rootDOMNode(x) {
|
| + if (this._rootDOMNode === x)
|
| + return;
|
| +
|
| + this._rootDOMNode = x;
|
| +
|
| + this._isXMLMimeType = x && x.isXMLNode();
|
| +
|
| + this.update();
|
| + }
|
| +
|
| + get isXMLMimeType() {
|
| + return this._isXMLMimeType;
|
| + }
|
| +
|
| + /**
|
| + * @return {?WebInspector.DOMNode}
|
| + */
|
| + selectedDOMNode() {
|
| + return this._selectedDOMNode;
|
| + }
|
| +
|
| + /**
|
| + * @param {?WebInspector.DOMNode} node
|
| + * @param {boolean=} focus
|
| + */
|
| + selectDOMNode(node, focus) {
|
| + if (this._selectedDOMNode === node) {
|
| + this._revealAndSelectNode(node, !focus);
|
| + return;
|
| + }
|
|
|
| - /**
|
| - * @param {boolean} focus
|
| - */
|
| - _selectedNodeChanged: function(focus)
|
| - {
|
| - this.dispatchEventToListeners(WebInspector.ElementsTreeOutline.Events.SelectedNodeChanged, {node: this._selectedDOMNode, focus: focus});
|
| - },
|
| + this._selectedDOMNode = node;
|
| + this._revealAndSelectNode(node, !focus);
|
| +
|
| + // The _revealAndSelectNode() method might find a different element if there is inlined text,
|
| + // and the select() call would change the selectedDOMNode and reenter this setter. So to
|
| + // avoid calling _selectedNodeChanged() twice, first check if _selectedDOMNode is the same
|
| + // node as the one passed in.
|
| + if (this._selectedDOMNode === node)
|
| + this._selectedNodeChanged(!!focus);
|
| + }
|
| +
|
| + /**
|
| + * @return {boolean}
|
| + */
|
| + editing() {
|
| + var node = this.selectedDOMNode();
|
| + if (!node)
|
| + return false;
|
| + var treeElement = this.findTreeElement(node);
|
| + if (!treeElement)
|
| + return false;
|
| + return treeElement.isEditing() || false;
|
| + }
|
| +
|
| + update() {
|
| + var selectedNode = this.selectedDOMNode();
|
| + this.removeChildren();
|
| + if (!this.rootDOMNode)
|
| + return;
|
| +
|
| + if (this._includeRootDOMNode) {
|
| + var treeElement = this._createElementTreeElement(this.rootDOMNode);
|
| + this.appendChild(treeElement);
|
| + } else {
|
| + // FIXME: this could use findTreeElement to reuse a tree element if it already exists
|
| + var children = this._visibleChildren(this.rootDOMNode);
|
| + for (var child of children) {
|
| + var treeElement = this._createElementTreeElement(child);
|
| + this.appendChild(treeElement);
|
| + }
|
| + }
|
|
|
| - /**
|
| - * @param {!Array.<!WebInspector.DOMNode>} nodes
|
| - */
|
| - _fireElementsTreeUpdated: function(nodes)
|
| - {
|
| - this.dispatchEventToListeners(WebInspector.ElementsTreeOutline.Events.ElementsTreeUpdated, nodes);
|
| - },
|
| + if (selectedNode)
|
| + this._revealAndSelectNode(selectedNode, true);
|
| + }
|
| +
|
| + /**
|
| + * @param {boolean} focus
|
| + */
|
| + _selectedNodeChanged(focus) {
|
| + this.dispatchEventToListeners(
|
| + WebInspector.ElementsTreeOutline.Events.SelectedNodeChanged, {node: this._selectedDOMNode, focus: focus});
|
| + }
|
| +
|
| + /**
|
| + * @param {!Array.<!WebInspector.DOMNode>} nodes
|
| + */
|
| + _fireElementsTreeUpdated(nodes) {
|
| + this.dispatchEventToListeners(WebInspector.ElementsTreeOutline.Events.ElementsTreeUpdated, nodes);
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.DOMNode} node
|
| + * @return {?WebInspector.ElementsTreeElement}
|
| + */
|
| + findTreeElement(node) {
|
| + var treeElement = this._lookUpTreeElement(node);
|
| + if (!treeElement && node.nodeType() === Node.TEXT_NODE) {
|
| + // The text node might have been inlined if it was short, so try to find the parent element.
|
| + treeElement = this._lookUpTreeElement(node.parentNode);
|
| + }
|
|
|
| - /**
|
| - * @param {!WebInspector.DOMNode} node
|
| - * @return {?WebInspector.ElementsTreeElement}
|
| - */
|
| - findTreeElement: function(node)
|
| - {
|
| - var treeElement = this._lookUpTreeElement(node);
|
| - if (!treeElement && node.nodeType() === Node.TEXT_NODE) {
|
| - // The text node might have been inlined if it was short, so try to find the parent element.
|
| - treeElement = this._lookUpTreeElement(node.parentNode);
|
| - }
|
| + return /** @type {?WebInspector.ElementsTreeElement} */ (treeElement);
|
| + }
|
| +
|
| + /**
|
| + * @param {?WebInspector.DOMNode} node
|
| + * @return {?TreeElement}
|
| + */
|
| + _lookUpTreeElement(node) {
|
| + if (!node)
|
| + return null;
|
| +
|
| + var cachedElement = node[this._treeElementSymbol];
|
| + if (cachedElement)
|
| + return cachedElement;
|
| +
|
| + // Walk up the parent pointers from the desired node
|
| + var ancestors = [];
|
| + for (var currentNode = node.parentNode; currentNode; currentNode = currentNode.parentNode) {
|
| + ancestors.push(currentNode);
|
| + if (currentNode[this._treeElementSymbol]) // stop climbing as soon as we hit
|
| + break;
|
| + }
|
|
|
| - return /** @type {?WebInspector.ElementsTreeElement} */ (treeElement);
|
| - },
|
| + if (!currentNode)
|
| + return null;
|
|
|
| - /**
|
| - * @param {?WebInspector.DOMNode} node
|
| - * @return {?TreeElement}
|
| - */
|
| - _lookUpTreeElement: function(node)
|
| - {
|
| - if (!node)
|
| - return null;
|
| -
|
| - var cachedElement = node[this._treeElementSymbol];
|
| - if (cachedElement)
|
| - return cachedElement;
|
| -
|
| - // Walk up the parent pointers from the desired node
|
| - var ancestors = [];
|
| - for (var currentNode = node.parentNode; currentNode; currentNode = currentNode.parentNode) {
|
| - ancestors.push(currentNode);
|
| - if (currentNode[this._treeElementSymbol]) // stop climbing as soon as we hit
|
| - break;
|
| - }
|
| + // Walk down to populate each ancestor's children, to fill in the tree and the cache.
|
| + for (var i = ancestors.length - 1; i >= 0; --i) {
|
| + var treeElement = ancestors[i][this._treeElementSymbol];
|
| + if (treeElement)
|
| + treeElement.onpopulate(); // fill the cache with the children of treeElement
|
| + }
|
|
|
| - if (!currentNode)
|
| - return null;
|
| + return node[this._treeElementSymbol];
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.DOMNode} node
|
| + * @return {?WebInspector.ElementsTreeElement}
|
| + */
|
| + createTreeElementFor(node) {
|
| + var treeElement = this.findTreeElement(node);
|
| + if (treeElement)
|
| + return treeElement;
|
| + if (!node.parentNode)
|
| + return null;
|
| +
|
| + treeElement = this.createTreeElementFor(node.parentNode);
|
| + return treeElement ? this._showChild(treeElement, node) : null;
|
| + }
|
| +
|
| + set suppressRevealAndSelect(x) {
|
| + if (this._suppressRevealAndSelect === x)
|
| + return;
|
| + this._suppressRevealAndSelect = x;
|
| + }
|
| +
|
| + /**
|
| + * @param {?WebInspector.DOMNode} node
|
| + * @param {boolean} omitFocus
|
| + */
|
| + _revealAndSelectNode(node, omitFocus) {
|
| + if (this._suppressRevealAndSelect)
|
| + return;
|
| +
|
| + if (!this._includeRootDOMNode && node === this.rootDOMNode && this.rootDOMNode)
|
| + node = this.rootDOMNode.firstChild;
|
| + if (!node)
|
| + return;
|
| + var treeElement = this.createTreeElementFor(node);
|
| + if (!treeElement)
|
| + return;
|
| +
|
| + treeElement.revealAndSelect(omitFocus);
|
| + }
|
| +
|
| + /**
|
| + * @return {?TreeElement}
|
| + */
|
| + _treeElementFromEvent(event) {
|
| + var scrollContainer = this.element.parentElement;
|
| +
|
| + // We choose this X coordinate based on the knowledge that our list
|
| + // items extend at least to the right edge of the outer <ol> container.
|
| + // In the no-word-wrap mode the outer <ol> may be wider than the tree container
|
| + // (and partially hidden), in which case we are left to use only its right boundary.
|
| + var x = scrollContainer.totalOffsetLeft() + scrollContainer.offsetWidth - 36;
|
| +
|
| + var y = event.pageY;
|
| +
|
| + // Our list items have 1-pixel cracks between them vertically. We avoid
|
| + // the cracks by checking slightly above and slightly below the mouse
|
| + // and seeing if we hit the same element each time.
|
| + var elementUnderMouse = this.treeElementFromPoint(x, y);
|
| + var elementAboveMouse = this.treeElementFromPoint(x, y - 2);
|
| + var element;
|
| + if (elementUnderMouse === elementAboveMouse)
|
| + element = elementUnderMouse;
|
| + else
|
| + element = this.treeElementFromPoint(x, y + 2);
|
| +
|
| + return element;
|
| + }
|
| +
|
| + /**
|
| + * @param {!Element} element
|
| + * @param {!Event} event
|
| + * @return {!Element|!AnchorBox|undefined}
|
| + */
|
| + _getPopoverAnchor(element, event) {
|
| + var anchor = element.enclosingNodeOrSelfWithClass('webkit-html-resource-link');
|
| + if (!anchor || !anchor.href)
|
| + return;
|
| +
|
| + return anchor;
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.DOMNode} node
|
| + * @param {function()} callback
|
| + */
|
| + _loadDimensionsForNode(node, callback) {
|
| + if (!node.nodeName() || node.nodeName().toLowerCase() !== 'img') {
|
| + callback();
|
| + return;
|
| + }
|
|
|
| - // Walk down to populate each ancestor's children, to fill in the tree and the cache.
|
| - for (var i = ancestors.length - 1; i >= 0; --i) {
|
| - var treeElement = ancestors[i][this._treeElementSymbol];
|
| - if (treeElement)
|
| - treeElement.onpopulate(); // fill the cache with the children of treeElement
|
| - }
|
| + node.resolveToObject('', resolvedNode);
|
| +
|
| + function resolvedNode(object) {
|
| + if (!object) {
|
| + callback();
|
| + return;
|
| + }
|
| +
|
| + object.callFunctionJSON(features, undefined, callback);
|
| + object.release();
|
| +
|
| + /**
|
| + * @return {!{offsetWidth: number, offsetHeight: number, naturalWidth: number, naturalHeight: number, currentSrc: (string|undefined)}}
|
| + * @suppressReceiverCheck
|
| + * @this {!Element}
|
| + */
|
| + function features() {
|
| + return {
|
| + offsetWidth: this.offsetWidth,
|
| + offsetHeight: this.offsetHeight,
|
| + naturalWidth: this.naturalWidth,
|
| + naturalHeight: this.naturalHeight,
|
| + currentSrc: this.currentSrc
|
| + };
|
| + }
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * @param {!Element} anchor
|
| + * @param {!WebInspector.Popover} popover
|
| + */
|
| + _showPopover(anchor, popover) {
|
| + var listItem = anchor.enclosingNodeOrSelfWithNodeName('li');
|
| + var node = /** @type {!WebInspector.ElementsTreeElement} */ (listItem.treeElement).node();
|
| + this._loadDimensionsForNode(
|
| + node, WebInspector.DOMPresentationUtils.buildImagePreviewContents.bind(
|
| + WebInspector.DOMPresentationUtils, node.target(), anchor.href, true, showPopover));
|
| +
|
| + /**
|
| + * @param {!Element=} contents
|
| + */
|
| + function showPopover(contents) {
|
| + if (!contents)
|
| + return;
|
| + popover.setCanShrink(false);
|
| + popover.showForAnchor(contents, anchor);
|
| + }
|
| + }
|
|
|
| - return node[this._treeElementSymbol];
|
| - },
|
| + _onmousedown(event) {
|
| + var element = this._treeElementFromEvent(event);
|
|
|
| - /**
|
| - * @param {!WebInspector.DOMNode} node
|
| - * @return {?WebInspector.ElementsTreeElement}
|
| - */
|
| - createTreeElementFor: function(node)
|
| - {
|
| - var treeElement = this.findTreeElement(node);
|
| - if (treeElement)
|
| - return treeElement;
|
| - if (!node.parentNode)
|
| - return null;
|
| -
|
| - treeElement = this.createTreeElementFor(node.parentNode);
|
| - return treeElement ? this._showChild(treeElement, node) : null;
|
| - },
|
| -
|
| - set suppressRevealAndSelect(x)
|
| - {
|
| - if (this._suppressRevealAndSelect === x)
|
| - return;
|
| - this._suppressRevealAndSelect = x;
|
| - },
|
| + if (!element || element.isEventWithinDisclosureTriangle(event))
|
| + return;
|
|
|
| - /**
|
| - * @param {?WebInspector.DOMNode} node
|
| - * @param {boolean} omitFocus
|
| - */
|
| - _revealAndSelectNode: function(node, omitFocus)
|
| - {
|
| - if (this._suppressRevealAndSelect)
|
| - return;
|
| -
|
| - if (!this._includeRootDOMNode && node === this.rootDOMNode && this.rootDOMNode)
|
| - node = this.rootDOMNode.firstChild;
|
| - if (!node)
|
| - return;
|
| - var treeElement = this.createTreeElementFor(node);
|
| - if (!treeElement)
|
| - return;
|
| -
|
| - treeElement.revealAndSelect(omitFocus);
|
| - },
|
| + element.select();
|
| + }
|
|
|
| - /**
|
| - * @return {?TreeElement}
|
| - */
|
| - _treeElementFromEvent: function(event)
|
| - {
|
| - var scrollContainer = this.element.parentElement;
|
| -
|
| - // We choose this X coordinate based on the knowledge that our list
|
| - // items extend at least to the right edge of the outer <ol> container.
|
| - // In the no-word-wrap mode the outer <ol> may be wider than the tree container
|
| - // (and partially hidden), in which case we are left to use only its right boundary.
|
| - var x = scrollContainer.totalOffsetLeft() + scrollContainer.offsetWidth - 36;
|
| -
|
| - var y = event.pageY;
|
| -
|
| - // Our list items have 1-pixel cracks between them vertically. We avoid
|
| - // the cracks by checking slightly above and slightly below the mouse
|
| - // and seeing if we hit the same element each time.
|
| - var elementUnderMouse = this.treeElementFromPoint(x, y);
|
| - var elementAboveMouse = this.treeElementFromPoint(x, y - 2);
|
| - var element;
|
| - if (elementUnderMouse === elementAboveMouse)
|
| - element = elementUnderMouse;
|
| - else
|
| - element = this.treeElementFromPoint(x, y + 2);
|
| + /**
|
| + * @param {?TreeElement} treeElement
|
| + */
|
| + setHoverEffect(treeElement) {
|
| + if (this._previousHoveredElement === treeElement)
|
| + return;
|
|
|
| - return element;
|
| - },
|
| + if (this._previousHoveredElement) {
|
| + this._previousHoveredElement.hovered = false;
|
| + delete this._previousHoveredElement;
|
| + }
|
|
|
| - /**
|
| - * @param {!Element} element
|
| - * @param {!Event} event
|
| - * @return {!Element|!AnchorBox|undefined}
|
| - */
|
| - _getPopoverAnchor: function(element, event)
|
| - {
|
| - var anchor = element.enclosingNodeOrSelfWithClass("webkit-html-resource-link");
|
| - if (!anchor || !anchor.href)
|
| - return;
|
| + if (treeElement) {
|
| + treeElement.hovered = true;
|
| + this._previousHoveredElement = treeElement;
|
| + }
|
| + }
|
|
|
| - return anchor;
|
| - },
|
| + _onmousemove(event) {
|
| + var element = this._treeElementFromEvent(event);
|
| + if (element && this._previousHoveredElement === element)
|
| + return;
|
|
|
| - /**
|
| - * @param {!WebInspector.DOMNode} node
|
| - * @param {function()} callback
|
| - */
|
| - _loadDimensionsForNode: function(node, callback)
|
| - {
|
| - if (!node.nodeName() || node.nodeName().toLowerCase() !== "img") {
|
| - callback();
|
| - return;
|
| - }
|
| + this.setHoverEffect(element);
|
|
|
| - node.resolveToObject("", resolvedNode);
|
| -
|
| - function resolvedNode(object)
|
| - {
|
| - if (!object) {
|
| - callback();
|
| - return;
|
| - }
|
| -
|
| - object.callFunctionJSON(features, undefined, callback);
|
| - object.release();
|
| -
|
| - /**
|
| - * @return {!{offsetWidth: number, offsetHeight: number, naturalWidth: number, naturalHeight: number, currentSrc: (string|undefined)}}
|
| - * @suppressReceiverCheck
|
| - * @this {!Element}
|
| - */
|
| - function features()
|
| - {
|
| - return { offsetWidth: this.offsetWidth, offsetHeight: this.offsetHeight, naturalWidth: this.naturalWidth, naturalHeight: this.naturalHeight, currentSrc: this.currentSrc };
|
| - }
|
| - }
|
| - },
|
| + if (element instanceof WebInspector.ElementsTreeElement) {
|
| + this._domModel.highlightDOMNodeWithConfig(
|
| + element.node().id, {mode: 'all', showInfo: !WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event)});
|
| + return;
|
| + }
|
|
|
| - /**
|
| - * @param {!Element} anchor
|
| - * @param {!WebInspector.Popover} popover
|
| - */
|
| - _showPopover: function(anchor, popover)
|
| - {
|
| - var listItem = anchor.enclosingNodeOrSelfWithNodeName("li");
|
| - var node = /** @type {!WebInspector.ElementsTreeElement} */ (listItem.treeElement).node();
|
| - this._loadDimensionsForNode(node, WebInspector.DOMPresentationUtils.buildImagePreviewContents.bind(WebInspector.DOMPresentationUtils, node.target(), anchor.href, true, showPopover));
|
| -
|
| - /**
|
| - * @param {!Element=} contents
|
| - */
|
| - function showPopover(contents)
|
| - {
|
| - if (!contents)
|
| - return;
|
| - popover.setCanShrink(false);
|
| - popover.showForAnchor(contents, anchor);
|
| - }
|
| - },
|
| + if (element instanceof WebInspector.ElementsTreeOutline.ShortcutTreeElement)
|
| + this._domModel.highlightDOMNodeWithConfig(
|
| + undefined, {mode: 'all', showInfo: !WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event)},
|
| + element.backendNodeId());
|
| + }
|
|
|
| - _onmousedown: function(event)
|
| - {
|
| - var element = this._treeElementFromEvent(event);
|
| + _onmouseleave(event) {
|
| + this.setHoverEffect(null);
|
| + WebInspector.DOMModel.hideDOMNodeHighlight();
|
| + }
|
|
|
| - if (!element || element.isEventWithinDisclosureTriangle(event))
|
| - return;
|
| + _ondragstart(event) {
|
| + if (!event.target.isComponentSelectionCollapsed())
|
| + return false;
|
| + if (event.target.nodeName === 'A')
|
| + return false;
|
|
|
| - element.select();
|
| - },
|
| + var treeElement = this._treeElementFromEvent(event);
|
| + if (!this._isValidDragSourceOrTarget(treeElement))
|
| + return false;
|
|
|
| - /**
|
| - * @param {?TreeElement} treeElement
|
| - */
|
| - setHoverEffect: function(treeElement)
|
| - {
|
| - if (this._previousHoveredElement === treeElement)
|
| - return;
|
| -
|
| - if (this._previousHoveredElement) {
|
| - this._previousHoveredElement.hovered = false;
|
| - delete this._previousHoveredElement;
|
| - }
|
| + if (treeElement.node().nodeName() === 'BODY' || treeElement.node().nodeName() === 'HEAD')
|
| + return false;
|
|
|
| - if (treeElement) {
|
| - treeElement.hovered = true;
|
| - this._previousHoveredElement = treeElement;
|
| - }
|
| - },
|
| + event.dataTransfer.setData('text/plain', treeElement.listItemElement.textContent.replace(/\u200b/g, ''));
|
| + event.dataTransfer.effectAllowed = 'copyMove';
|
| + this._treeElementBeingDragged = treeElement;
|
|
|
| - _onmousemove: function(event)
|
| - {
|
| - var element = this._treeElementFromEvent(event);
|
| - if (element && this._previousHoveredElement === element)
|
| - return;
|
| + WebInspector.DOMModel.hideDOMNodeHighlight();
|
|
|
| - this.setHoverEffect(element);
|
| + return true;
|
| + }
|
|
|
| - if (element instanceof WebInspector.ElementsTreeElement) {
|
| - this._domModel.highlightDOMNodeWithConfig(element.node().id, { mode: "all", showInfo: !WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) });
|
| - return;
|
| - }
|
| + _ondragover(event) {
|
| + if (!this._treeElementBeingDragged)
|
| + return false;
|
|
|
| - if (element instanceof WebInspector.ElementsTreeOutline.ShortcutTreeElement)
|
| - this._domModel.highlightDOMNodeWithConfig(undefined, { mode: "all", showInfo: !WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) }, element.backendNodeId());
|
| - },
|
| -
|
| - _onmouseleave: function(event)
|
| - {
|
| - this.setHoverEffect(null);
|
| - WebInspector.DOMModel.hideDOMNodeHighlight();
|
| - },
|
| -
|
| - _ondragstart: function(event)
|
| - {
|
| - if (!event.target.isComponentSelectionCollapsed())
|
| - return false;
|
| - if (event.target.nodeName === "A")
|
| - return false;
|
| -
|
| - var treeElement = this._treeElementFromEvent(event);
|
| - if (!this._isValidDragSourceOrTarget(treeElement))
|
| - return false;
|
| -
|
| - if (treeElement.node().nodeName() === "BODY" || treeElement.node().nodeName() === "HEAD")
|
| - return false;
|
| -
|
| - event.dataTransfer.setData("text/plain", treeElement.listItemElement.textContent.replace(/\u200b/g, ""));
|
| - event.dataTransfer.effectAllowed = "copyMove";
|
| - this._treeElementBeingDragged = treeElement;
|
| -
|
| - WebInspector.DOMModel.hideDOMNodeHighlight();
|
| -
|
| - return true;
|
| - },
|
| -
|
| - _ondragover: function(event)
|
| - {
|
| - if (!this._treeElementBeingDragged)
|
| - return false;
|
| -
|
| - var treeElement = this._treeElementFromEvent(event);
|
| - if (!this._isValidDragSourceOrTarget(treeElement))
|
| - return false;
|
| -
|
| - var node = treeElement.node();
|
| - while (node) {
|
| - if (node === this._treeElementBeingDragged._node)
|
| - return false;
|
| - node = node.parentNode;
|
| - }
|
| -
|
| - treeElement.listItemElement.classList.add("elements-drag-over");
|
| - this._dragOverTreeElement = treeElement;
|
| - event.preventDefault();
|
| - event.dataTransfer.dropEffect = "move";
|
| - return false;
|
| - },
|
| + var treeElement = this._treeElementFromEvent(event);
|
| + if (!this._isValidDragSourceOrTarget(treeElement))
|
| + return false;
|
|
|
| - _ondragleave: function(event)
|
| - {
|
| - this._clearDragOverTreeElementMarker();
|
| - event.preventDefault();
|
| + var node = treeElement.node();
|
| + while (node) {
|
| + if (node === this._treeElementBeingDragged._node)
|
| return false;
|
| - },
|
| + node = node.parentNode;
|
| + }
|
|
|
| - /**
|
| - * @param {?TreeElement} treeElement
|
| - * @return {boolean}
|
| - */
|
| - _isValidDragSourceOrTarget: function(treeElement)
|
| - {
|
| - if (!treeElement)
|
| - return false;
|
| -
|
| - if (!(treeElement instanceof WebInspector.ElementsTreeElement))
|
| - return false;
|
| - var elementsTreeElement = /** @type {!WebInspector.ElementsTreeElement} */ (treeElement);
|
| -
|
| - var node = elementsTreeElement.node();
|
| - if (!node.parentNode || node.parentNode.nodeType() !== Node.ELEMENT_NODE)
|
| - return false;
|
| -
|
| - return true;
|
| - },
|
| -
|
| - _ondrop: function(event)
|
| - {
|
| - event.preventDefault();
|
| - var treeElement = this._treeElementFromEvent(event);
|
| - if (treeElement)
|
| - this._doMove(treeElement);
|
| - },
|
| + treeElement.listItemElement.classList.add('elements-drag-over');
|
| + this._dragOverTreeElement = treeElement;
|
| + event.preventDefault();
|
| + event.dataTransfer.dropEffect = 'move';
|
| + return false;
|
| + }
|
| +
|
| + _ondragleave(event) {
|
| + this._clearDragOverTreeElementMarker();
|
| + event.preventDefault();
|
| + return false;
|
| + }
|
| +
|
| + /**
|
| + * @param {?TreeElement} treeElement
|
| + * @return {boolean}
|
| + */
|
| + _isValidDragSourceOrTarget(treeElement) {
|
| + if (!treeElement)
|
| + return false;
|
| +
|
| + if (!(treeElement instanceof WebInspector.ElementsTreeElement))
|
| + return false;
|
| + var elementsTreeElement = /** @type {!WebInspector.ElementsTreeElement} */ (treeElement);
|
| +
|
| + var node = elementsTreeElement.node();
|
| + if (!node.parentNode || node.parentNode.nodeType() !== Node.ELEMENT_NODE)
|
| + return false;
|
| +
|
| + return true;
|
| + }
|
| +
|
| + _ondrop(event) {
|
| + event.preventDefault();
|
| + var treeElement = this._treeElementFromEvent(event);
|
| + if (treeElement)
|
| + this._doMove(treeElement);
|
| + }
|
| +
|
| + /**
|
| + * @param {!TreeElement} treeElement
|
| + */
|
| + _doMove(treeElement) {
|
| + if (!this._treeElementBeingDragged)
|
| + return;
|
| +
|
| + var parentNode;
|
| + var anchorNode;
|
| +
|
| + if (treeElement.isClosingTag()) {
|
| + // Drop onto closing tag -> insert as last child.
|
| + parentNode = treeElement.node();
|
| + } else {
|
| + var dragTargetNode = treeElement.node();
|
| + parentNode = dragTargetNode.parentNode;
|
| + anchorNode = dragTargetNode;
|
| + }
|
|
|
| - /**
|
| - * @param {!TreeElement} treeElement
|
| - */
|
| - _doMove: function(treeElement)
|
| - {
|
| - if (!this._treeElementBeingDragged)
|
| - return;
|
| -
|
| - var parentNode;
|
| - var anchorNode;
|
| -
|
| - if (treeElement.isClosingTag()) {
|
| - // Drop onto closing tag -> insert as last child.
|
| - parentNode = treeElement.node();
|
| - } else {
|
| - var dragTargetNode = treeElement.node();
|
| - parentNode = dragTargetNode.parentNode;
|
| - anchorNode = dragTargetNode;
|
| - }
|
| + var wasExpanded = this._treeElementBeingDragged.expanded;
|
| + this._treeElementBeingDragged._node.moveTo(
|
| + parentNode, anchorNode, this.selectNodeAfterEdit.bind(this, wasExpanded));
|
|
|
| - var wasExpanded = this._treeElementBeingDragged.expanded;
|
| - this._treeElementBeingDragged._node.moveTo(parentNode, anchorNode, this.selectNodeAfterEdit.bind(this, wasExpanded));
|
| + delete this._treeElementBeingDragged;
|
| + }
|
|
|
| - delete this._treeElementBeingDragged;
|
| - },
|
| + _ondragend(event) {
|
| + event.preventDefault();
|
| + this._clearDragOverTreeElementMarker();
|
| + delete this._treeElementBeingDragged;
|
| + }
|
|
|
| - _ondragend: function(event)
|
| - {
|
| - event.preventDefault();
|
| - this._clearDragOverTreeElementMarker();
|
| - delete this._treeElementBeingDragged;
|
| - },
|
| + _clearDragOverTreeElementMarker() {
|
| + if (this._dragOverTreeElement) {
|
| + this._dragOverTreeElement.listItemElement.classList.remove('elements-drag-over');
|
| + delete this._dragOverTreeElement;
|
| + }
|
| + }
|
| +
|
| + _contextMenuEventFired(event) {
|
| + var treeElement = this._treeElementFromEvent(event);
|
| + if (treeElement instanceof WebInspector.ElementsTreeElement)
|
| + this.showContextMenu(treeElement, event);
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.ElementsTreeElement} treeElement
|
| + * @param {!Event} event
|
| + */
|
| + showContextMenu(treeElement, event) {
|
| + if (WebInspector.isEditing())
|
| + return;
|
| +
|
| + var contextMenu = new WebInspector.ContextMenu(event);
|
| + var isPseudoElement = !!treeElement.node().pseudoType();
|
| + var isTag = treeElement.node().nodeType() === Node.ELEMENT_NODE && !isPseudoElement;
|
| + var textNode = event.target.enclosingNodeOrSelfWithClass('webkit-html-text-node');
|
| + if (textNode && textNode.classList.contains('bogus'))
|
| + textNode = null;
|
| + var commentNode = event.target.enclosingNodeOrSelfWithClass('webkit-html-comment');
|
| + contextMenu.appendApplicableItems(event.target);
|
| + if (textNode) {
|
| + contextMenu.appendSeparator();
|
| + treeElement.populateTextContextMenu(contextMenu, textNode);
|
| + } else if (isTag) {
|
| + contextMenu.appendSeparator();
|
| + treeElement.populateTagContextMenu(contextMenu, event);
|
| + } else if (commentNode) {
|
| + contextMenu.appendSeparator();
|
| + treeElement.populateNodeContextMenu(contextMenu);
|
| + } else if (isPseudoElement) {
|
| + treeElement.populateScrollIntoView(contextMenu);
|
| + }
|
|
|
| - _clearDragOverTreeElementMarker: function()
|
| - {
|
| - if (this._dragOverTreeElement) {
|
| - this._dragOverTreeElement.listItemElement.classList.remove("elements-drag-over");
|
| - delete this._dragOverTreeElement;
|
| - }
|
| - },
|
| + contextMenu.appendApplicableItems(treeElement.node());
|
| + contextMenu.show();
|
| + }
|
| +
|
| + runPendingUpdates() {
|
| + this._updateModifiedNodes();
|
| + }
|
| +
|
| + handleShortcut(event) {
|
| + var node = this.selectedDOMNode();
|
| + if (!node)
|
| + return;
|
| + var treeElement = node[this._treeElementSymbol];
|
| + if (!treeElement)
|
| + return;
|
| +
|
| + if (WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) && node.parentNode) {
|
| + if (event.key === 'ArrowUp' && node.previousSibling) {
|
| + node.moveTo(node.parentNode, node.previousSibling, this.selectNodeAfterEdit.bind(this, treeElement.expanded));
|
| + event.handled = true;
|
| + return;
|
| + }
|
| + if (event.key === 'ArrowDown' && node.nextSibling) {
|
| + node.moveTo(
|
| + node.parentNode, node.nextSibling.nextSibling, this.selectNodeAfterEdit.bind(this, treeElement.expanded));
|
| + event.handled = true;
|
| + return;
|
| + }
|
| + }
|
| + }
|
|
|
| - _contextMenuEventFired: function(event)
|
| - {
|
| - var treeElement = this._treeElementFromEvent(event);
|
| - if (treeElement instanceof WebInspector.ElementsTreeElement)
|
| - this.showContextMenu(treeElement, event);
|
| - },
|
| + /**
|
| + * @param {!WebInspector.DOMNode} node
|
| + * @param {boolean=} startEditing
|
| + * @param {function()=} callback
|
| + */
|
| + toggleEditAsHTML(node, startEditing, callback) {
|
| + var treeElement = node[this._treeElementSymbol];
|
| + if (!treeElement || !treeElement.hasEditableNode())
|
| + return;
|
|
|
| - /**
|
| - * @param {!WebInspector.ElementsTreeElement} treeElement
|
| - * @param {!Event} event
|
| - */
|
| - showContextMenu: function(treeElement, event)
|
| - {
|
| - if (WebInspector.isEditing())
|
| - return;
|
| -
|
| - var contextMenu = new WebInspector.ContextMenu(event);
|
| - var isPseudoElement = !!treeElement.node().pseudoType();
|
| - var isTag = treeElement.node().nodeType() === Node.ELEMENT_NODE && !isPseudoElement;
|
| - var textNode = event.target.enclosingNodeOrSelfWithClass("webkit-html-text-node");
|
| - if (textNode && textNode.classList.contains("bogus"))
|
| - textNode = null;
|
| - var commentNode = event.target.enclosingNodeOrSelfWithClass("webkit-html-comment");
|
| - contextMenu.appendApplicableItems(event.target);
|
| - if (textNode) {
|
| - contextMenu.appendSeparator();
|
| - treeElement.populateTextContextMenu(contextMenu, textNode);
|
| - } else if (isTag) {
|
| - contextMenu.appendSeparator();
|
| - treeElement.populateTagContextMenu(contextMenu, event);
|
| - } else if (commentNode) {
|
| - contextMenu.appendSeparator();
|
| - treeElement.populateNodeContextMenu(contextMenu);
|
| - } else if (isPseudoElement) {
|
| - treeElement.populateScrollIntoView(contextMenu);
|
| - }
|
| + if (node.pseudoType())
|
| + return;
|
|
|
| - contextMenu.appendApplicableItems(treeElement.node());
|
| - contextMenu.show();
|
| - },
|
| -
|
| - runPendingUpdates: function()
|
| - {
|
| - this._updateModifiedNodes();
|
| - },
|
| -
|
| - handleShortcut: function(event)
|
| - {
|
| - var node = this.selectedDOMNode();
|
| - if (!node)
|
| - return;
|
| - var treeElement = node[this._treeElementSymbol];
|
| - if (!treeElement)
|
| - return;
|
| -
|
| - if (WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) && node.parentNode) {
|
| - if (event.key === "ArrowUp" && node.previousSibling) {
|
| - node.moveTo(node.parentNode, node.previousSibling, this.selectNodeAfterEdit.bind(this, treeElement.expanded));
|
| - event.handled = true;
|
| - return;
|
| - }
|
| - if (event.key === "ArrowDown" && node.nextSibling) {
|
| - node.moveTo(node.parentNode, node.nextSibling.nextSibling, this.selectNodeAfterEdit.bind(this, treeElement.expanded));
|
| - event.handled = true;
|
| - return;
|
| - }
|
| - }
|
| - },
|
| + var parentNode = node.parentNode;
|
| + var index = node.index;
|
| + var wasExpanded = treeElement.expanded;
|
|
|
| - /**
|
| - * @param {!WebInspector.DOMNode} node
|
| - * @param {boolean=} startEditing
|
| - * @param {function()=} callback
|
| - */
|
| - toggleEditAsHTML: function(node, startEditing, callback)
|
| - {
|
| - var treeElement = node[this._treeElementSymbol];
|
| - if (!treeElement || !treeElement.hasEditableNode())
|
| - return;
|
| -
|
| - if (node.pseudoType())
|
| - return;
|
| -
|
| - var parentNode = node.parentNode;
|
| - var index = node.index;
|
| - var wasExpanded = treeElement.expanded;
|
| -
|
| - treeElement.toggleEditAsHTML(editingFinished.bind(this), startEditing);
|
| -
|
| - /**
|
| - * @this {WebInspector.ElementsTreeOutline}
|
| - * @param {boolean} success
|
| - */
|
| - function editingFinished(success)
|
| - {
|
| - if (callback)
|
| - callback();
|
| - if (!success)
|
| - return;
|
| -
|
| - // Select it and expand if necessary. We force tree update so that it processes dom events and is up to date.
|
| - this.runPendingUpdates();
|
| -
|
| - var newNode = parentNode ? parentNode.children()[index] || parentNode : null;
|
| - if (!newNode)
|
| - return;
|
| -
|
| - this.selectDOMNode(newNode, true);
|
| -
|
| - if (wasExpanded) {
|
| - var newTreeItem = this.findTreeElement(newNode);
|
| - if (newTreeItem)
|
| - newTreeItem.expand();
|
| - }
|
| - }
|
| - },
|
| + treeElement.toggleEditAsHTML(editingFinished.bind(this), startEditing);
|
|
|
| /**
|
| - * @param {boolean} wasExpanded
|
| - * @param {?Protocol.Error} error
|
| - * @param {!DOMAgent.NodeId=} nodeId
|
| - * @return {?WebInspector.ElementsTreeElement} nodeId
|
| + * @this {WebInspector.ElementsTreeOutline}
|
| + * @param {boolean} success
|
| */
|
| - selectNodeAfterEdit: function(wasExpanded, error, nodeId)
|
| - {
|
| - if (error)
|
| - return null;
|
| + function editingFinished(success) {
|
| + if (callback)
|
| + callback();
|
| + if (!success)
|
| + return;
|
|
|
| - // Select it and expand if necessary. We force tree update so that it processes dom events and is up to date.
|
| - this.runPendingUpdates();
|
| + // Select it and expand if necessary. We force tree update so that it processes dom events and is up to date.
|
| + this.runPendingUpdates();
|
|
|
| - var newNode = nodeId ? this._domModel.nodeForId(nodeId) : null;
|
| - if (!newNode)
|
| - return null;
|
| + var newNode = parentNode ? parentNode.children()[index] || parentNode : null;
|
| + if (!newNode)
|
| + return;
|
|
|
| - this.selectDOMNode(newNode, true);
|
| + this.selectDOMNode(newNode, true);
|
|
|
| + if (wasExpanded) {
|
| var newTreeItem = this.findTreeElement(newNode);
|
| - if (wasExpanded) {
|
| - if (newTreeItem)
|
| - newTreeItem.expand();
|
| - }
|
| - return newTreeItem;
|
| - },
|
| -
|
| - /**
|
| - * Runs a script on the node's remote object that toggles a class name on
|
| - * the node and injects a stylesheet into the head of the node's document
|
| - * containing a rule to set "visibility: hidden" on the class and all it's
|
| - * ancestors.
|
| - *
|
| - * @param {!WebInspector.DOMNode} node
|
| - * @param {function(?WebInspector.RemoteObject, boolean=)=} userCallback
|
| - */
|
| - toggleHideElement: function(node, userCallback)
|
| - {
|
| - var pseudoType = node.pseudoType();
|
| - var effectiveNode = pseudoType ? node.parentNode : node;
|
| - if (!effectiveNode)
|
| - return;
|
| -
|
| - var hidden = node.marker("hidden-marker");
|
| -
|
| - function resolvedNode(object)
|
| - {
|
| - if (!object)
|
| - return;
|
| -
|
| - /**
|
| - * @param {?string} pseudoType
|
| - * @param {boolean} hidden
|
| - * @suppressGlobalPropertiesCheck
|
| - * @suppressReceiverCheck
|
| - * @this {!Element}
|
| - */
|
| - function toggleClassAndInjectStyleRule(pseudoType, hidden)
|
| - {
|
| - const classNamePrefix = "__web-inspector-hide";
|
| - const classNameSuffix = "-shortcut__";
|
| - const styleTagId = "__web-inspector-hide-shortcut-style__";
|
| - var selectors = [];
|
| - selectors.push(".__web-inspector-hide-shortcut__");
|
| - selectors.push(".__web-inspector-hide-shortcut__ *");
|
| - selectors.push(".__web-inspector-hidebefore-shortcut__::before");
|
| - selectors.push(".__web-inspector-hideafter-shortcut__::after");
|
| - var selector = selectors.join(", ");
|
| - var ruleBody = " visibility: hidden !important;";
|
| - var rule = "\n" + selector + "\n{\n" + ruleBody + "\n}\n";
|
| - var className = classNamePrefix + (pseudoType || "") + classNameSuffix;
|
| - this.classList.toggle(className, hidden);
|
| -
|
| - var localRoot = this;
|
| - while (localRoot.parentNode)
|
| - localRoot = localRoot.parentNode;
|
| - if (localRoot.nodeType === Node.DOCUMENT_NODE)
|
| - localRoot = document.head;
|
| -
|
| - var style = localRoot.querySelector("style#" + styleTagId);
|
| - if (style)
|
| - return;
|
| -
|
| - style = document.createElement("style");
|
| - style.id = styleTagId;
|
| - style.type = "text/css";
|
| - style.textContent = rule;
|
| -
|
| - localRoot.appendChild(style);
|
| - }
|
| -
|
| - object.callFunction(toggleClassAndInjectStyleRule, [{ value: pseudoType }, { value: !hidden}], userCallback);
|
| - object.release();
|
| - node.setMarker("hidden-marker", hidden ? null : true);
|
| - }
|
| -
|
| - effectiveNode.resolveToObject("", resolvedNode);
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.DOMNode} node
|
| - * @return {boolean}
|
| - */
|
| - isToggledToHidden: function(node)
|
| - {
|
| - return !!node.marker("hidden-marker");
|
| - },
|
| -
|
| - _reset: function()
|
| - {
|
| - this.rootDOMNode = null;
|
| - this.selectDOMNode(null, false);
|
| - this._popoverHelper.hidePopover();
|
| - delete this._clipboardNodeData;
|
| - WebInspector.DOMModel.hideDOMNodeHighlight();
|
| - this._updateRecords.clear();
|
| - },
|
| -
|
| - wireToDOMModel: function()
|
| - {
|
| - this._domModel[WebInspector.ElementsTreeOutline._treeOutlineSymbol] = this;
|
| - this._domModel.addEventListener(WebInspector.DOMModel.Events.NodeInserted, this._nodeInserted, this);
|
| - this._domModel.addEventListener(WebInspector.DOMModel.Events.NodeRemoved, this._nodeRemoved, this);
|
| - this._domModel.addEventListener(WebInspector.DOMModel.Events.AttrModified, this._attributeModified, this);
|
| - this._domModel.addEventListener(WebInspector.DOMModel.Events.AttrRemoved, this._attributeRemoved, this);
|
| - this._domModel.addEventListener(WebInspector.DOMModel.Events.CharacterDataModified, this._characterDataModified, this);
|
| - this._domModel.addEventListener(WebInspector.DOMModel.Events.DocumentUpdated, this._documentUpdated, this);
|
| - this._domModel.addEventListener(WebInspector.DOMModel.Events.ChildNodeCountUpdated, this._childNodeCountUpdated, this);
|
| - this._domModel.addEventListener(WebInspector.DOMModel.Events.DistributedNodesChanged, this._distributedNodesChanged, this);
|
| - },
|
| -
|
| - unwireFromDOMModel: function()
|
| - {
|
| - this._domModel.removeEventListener(WebInspector.DOMModel.Events.NodeInserted, this._nodeInserted, this);
|
| - this._domModel.removeEventListener(WebInspector.DOMModel.Events.NodeRemoved, this._nodeRemoved, this);
|
| - this._domModel.removeEventListener(WebInspector.DOMModel.Events.AttrModified, this._attributeModified, this);
|
| - this._domModel.removeEventListener(WebInspector.DOMModel.Events.AttrRemoved, this._attributeRemoved, this);
|
| - this._domModel.removeEventListener(WebInspector.DOMModel.Events.CharacterDataModified, this._characterDataModified, this);
|
| - this._domModel.removeEventListener(WebInspector.DOMModel.Events.DocumentUpdated, this._documentUpdated, this);
|
| - this._domModel.removeEventListener(WebInspector.DOMModel.Events.ChildNodeCountUpdated, this._childNodeCountUpdated, this);
|
| - this._domModel.removeEventListener(WebInspector.DOMModel.Events.DistributedNodesChanged, this._distributedNodesChanged, this);
|
| - delete this._domModel[WebInspector.ElementsTreeOutline._treeOutlineSymbol];
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.DOMNode} node
|
| - * @return {!WebInspector.ElementsTreeOutline.UpdateRecord}
|
| - */
|
| - _addUpdateRecord: function(node)
|
| - {
|
| - var record = this._updateRecords.get(node);
|
| - if (!record) {
|
| - record = new WebInspector.ElementsTreeOutline.UpdateRecord();
|
| - this._updateRecords.set(node, record);
|
| - }
|
| - return record;
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.DOMNode} node
|
| - * @return {?WebInspector.ElementsTreeOutline.UpdateRecord}
|
| - */
|
| - _updateRecordForHighlight: function(node)
|
| - {
|
| - if (!this._visible)
|
| - return null;
|
| - return this._updateRecords.get(node) || null;
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.Event} event
|
| - */
|
| - _documentUpdated: function(event)
|
| - {
|
| - var inspectedRootDocument = event.data;
|
| -
|
| - this._reset();
|
| -
|
| - if (!inspectedRootDocument)
|
| - return;
|
| -
|
| - this.rootDOMNode = inspectedRootDocument;
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.Event} event
|
| - */
|
| - _attributeModified: function(event)
|
| - {
|
| - var node = /** @type {!WebInspector.DOMNode} */ (event.data.node);
|
| - this._addUpdateRecord(node).attributeModified(event.data.name);
|
| - this._updateModifiedNodesSoon();
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.Event} event
|
| - */
|
| - _attributeRemoved: function(event)
|
| - {
|
| - var node = /** @type {!WebInspector.DOMNode} */ (event.data.node);
|
| - this._addUpdateRecord(node).attributeRemoved(event.data.name);
|
| - this._updateModifiedNodesSoon();
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.Event} event
|
| - */
|
| - _characterDataModified: function(event)
|
| - {
|
| - var node = /** @type {!WebInspector.DOMNode} */ (event.data);
|
| - this._addUpdateRecord(node).charDataModified();
|
| - // Text could be large and force us to render itself as the child in the tree outline.
|
| - if (node.parentNode && node.parentNode.firstChild === node.parentNode.lastChild)
|
| - this._addUpdateRecord(node.parentNode).childrenModified();
|
| - this._updateModifiedNodesSoon();
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.Event} event
|
| - */
|
| - _nodeInserted: function(event)
|
| - {
|
| - var node = /** @type {!WebInspector.DOMNode} */ (event.data);
|
| - this._addUpdateRecord(/** @type {!WebInspector.DOMNode} */ (node.parentNode)).nodeInserted(node);
|
| - this._updateModifiedNodesSoon();
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.Event} event
|
| - */
|
| - _nodeRemoved: function(event)
|
| - {
|
| - var node = /** @type {!WebInspector.DOMNode} */ (event.data.node);
|
| - var parentNode = /** @type {!WebInspector.DOMNode} */ (event.data.parent);
|
| - this.resetClipboardIfNeeded(node);
|
| - this._addUpdateRecord(parentNode).nodeRemoved(node);
|
| - this._updateModifiedNodesSoon();
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.Event} event
|
| - */
|
| - _childNodeCountUpdated: function(event)
|
| - {
|
| - var node = /** @type {!WebInspector.DOMNode} */ (event.data);
|
| - this._addUpdateRecord(node).childrenModified();
|
| - this._updateModifiedNodesSoon();
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.Event} event
|
| - */
|
| - _distributedNodesChanged: function(event)
|
| - {
|
| - var node = /** @type {!WebInspector.DOMNode} */ (event.data);
|
| - this._addUpdateRecord(node).childrenModified();
|
| - this._updateModifiedNodesSoon();
|
| - },
|
| -
|
| - _updateModifiedNodesSoon: function()
|
| - {
|
| - if (!this._updateRecords.size)
|
| - return;
|
| - if (this._updateModifiedNodesTimeout)
|
| - return;
|
| - this._updateModifiedNodesTimeout = setTimeout(this._updateModifiedNodes.bind(this), 50);
|
| - },
|
| -
|
| - _updateModifiedNodes: function()
|
| - {
|
| - if (this._updateModifiedNodesTimeout) {
|
| - clearTimeout(this._updateModifiedNodesTimeout);
|
| - delete this._updateModifiedNodesTimeout;
|
| - }
|
| -
|
| - var updatedNodes = this._updateRecords.keysArray();
|
| - var hidePanelWhileUpdating = updatedNodes.length > 10;
|
| - if (hidePanelWhileUpdating) {
|
| - var treeOutlineContainerElement = this.element.parentNode;
|
| - var originalScrollTop = treeOutlineContainerElement ? treeOutlineContainerElement.scrollTop : 0;
|
| - this._element.classList.add("hidden");
|
| - }
|
| -
|
| - if (this._rootDOMNode && this._updateRecords.get(this._rootDOMNode) && this._updateRecords.get(this._rootDOMNode).hasChangedChildren()) {
|
| - // Document's children have changed, perform total update.
|
| - this.update();
|
| - } else {
|
| - for (var node of this._updateRecords.keys()) {
|
| - if (this._updateRecords.get(node).hasChangedChildren())
|
| - this._updateModifiedParentNode(node);
|
| - else
|
| - this._updateModifiedNode(node);
|
| - }
|
| - }
|
| -
|
| - if (hidePanelWhileUpdating) {
|
| - this._element.classList.remove("hidden");
|
| - if (originalScrollTop)
|
| - treeOutlineContainerElement.scrollTop = originalScrollTop;
|
| - }
|
| -
|
| - this._updateRecords.clear();
|
| - this._fireElementsTreeUpdated(updatedNodes);
|
| - },
|
| -
|
| - _updateModifiedNode: function(node)
|
| - {
|
| - var treeElement = this.findTreeElement(node);
|
| - if (treeElement)
|
| - treeElement.updateTitle(this._updateRecordForHighlight(node));
|
| - },
|
| -
|
| - _updateModifiedParentNode: function(node)
|
| - {
|
| - var parentTreeElement = this.findTreeElement(node);
|
| - if (parentTreeElement) {
|
| - parentTreeElement.setExpandable(this._hasVisibleChildren(node));
|
| - parentTreeElement.updateTitle(this._updateRecordForHighlight(node));
|
| - if (parentTreeElement.populated)
|
| - this._updateChildren(parentTreeElement);
|
| - }
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.ElementsTreeElement} treeElement
|
| - */
|
| - populateTreeElement: function(treeElement)
|
| - {
|
| - if (treeElement.childCount() || !treeElement.isExpandable())
|
| - return;
|
| -
|
| - this._updateModifiedParentNode(treeElement.node());
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.DOMNode} node
|
| - * @param {boolean=} closingTag
|
| - * @return {!WebInspector.ElementsTreeElement}
|
| - */
|
| - _createElementTreeElement: function(node, closingTag)
|
| - {
|
| - var treeElement = new WebInspector.ElementsTreeElement(node, closingTag);
|
| - treeElement.setExpandable(!closingTag && this._hasVisibleChildren(node));
|
| - if (node.nodeType() === Node.ELEMENT_NODE && node.parentNode && node.parentNode.nodeType() === Node.DOCUMENT_NODE && !node.parentNode.parentNode)
|
| - treeElement.setCollapsible(false);
|
| - treeElement.selectable = this._selectEnabled;
|
| - return treeElement;
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.ElementsTreeElement} treeElement
|
| - * @param {!WebInspector.DOMNode} child
|
| - * @return {?WebInspector.ElementsTreeElement}
|
| - */
|
| - _showChild: function(treeElement, child)
|
| - {
|
| - if (treeElement.isClosingTag())
|
| - return null;
|
| -
|
| - var index = this._visibleChildren(treeElement.node()).indexOf(child);
|
| - if (index === -1)
|
| - return null;
|
| -
|
| - if (index >= treeElement.expandedChildrenLimit())
|
| - this.setExpandedChildrenLimit(treeElement, index + 1);
|
| - return /** @type {!WebInspector.ElementsTreeElement} */ (treeElement.childAt(index));
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.DOMNode} node
|
| - * @return {!Array.<!WebInspector.DOMNode>} visibleChildren
|
| - */
|
| - _visibleChildren: function(node)
|
| - {
|
| - var visibleChildren = WebInspector.ElementsTreeElement.visibleShadowRoots(node);
|
| -
|
| - var importedDocument = node.importedDocument();
|
| - if (importedDocument)
|
| - visibleChildren.push(importedDocument);
|
| -
|
| - var templateContent = node.templateContent();
|
| - if (templateContent)
|
| - visibleChildren.push(templateContent);
|
| -
|
| - var beforePseudoElement = node.beforePseudoElement();
|
| - if (beforePseudoElement)
|
| - visibleChildren.push(beforePseudoElement);
|
| -
|
| - if (node.childNodeCount()) {
|
| - var children = node.children();
|
| - if (!this._showHTMLCommentsSetting.get())
|
| - children = children.filter(n => n.nodeType() !== Node.COMMENT_NODE);
|
| - visibleChildren = visibleChildren.concat(children);
|
| - }
|
| -
|
| - var afterPseudoElement = node.afterPseudoElement();
|
| - if (afterPseudoElement)
|
| - visibleChildren.push(afterPseudoElement);
|
| + if (newTreeItem)
|
| + newTreeItem.expand();
|
| + }
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * @param {boolean} wasExpanded
|
| + * @param {?Protocol.Error} error
|
| + * @param {!DOMAgent.NodeId=} nodeId
|
| + * @return {?WebInspector.ElementsTreeElement} nodeId
|
| + */
|
| + selectNodeAfterEdit(wasExpanded, error, nodeId) {
|
| + if (error)
|
| + return null;
|
| +
|
| + // Select it and expand if necessary. We force tree update so that it processes dom events and is up to date.
|
| + this.runPendingUpdates();
|
| +
|
| + var newNode = nodeId ? this._domModel.nodeForId(nodeId) : null;
|
| + if (!newNode)
|
| + return null;
|
| +
|
| + this.selectDOMNode(newNode, true);
|
| +
|
| + var newTreeItem = this.findTreeElement(newNode);
|
| + if (wasExpanded) {
|
| + if (newTreeItem)
|
| + newTreeItem.expand();
|
| + }
|
| + return newTreeItem;
|
| + }
|
| +
|
| + /**
|
| + * Runs a script on the node's remote object that toggles a class name on
|
| + * the node and injects a stylesheet into the head of the node's document
|
| + * containing a rule to set "visibility: hidden" on the class and all it's
|
| + * ancestors.
|
| + *
|
| + * @param {!WebInspector.DOMNode} node
|
| + * @param {function(?WebInspector.RemoteObject, boolean=)=} userCallback
|
| + */
|
| + toggleHideElement(node, userCallback) {
|
| + var pseudoType = node.pseudoType();
|
| + var effectiveNode = pseudoType ? node.parentNode : node;
|
| + if (!effectiveNode)
|
| + return;
|
| +
|
| + var hidden = node.marker('hidden-marker');
|
| +
|
| + function resolvedNode(object) {
|
| + if (!object)
|
| + return;
|
| +
|
| + /**
|
| + * @param {?string} pseudoType
|
| + * @param {boolean} hidden
|
| + * @suppressGlobalPropertiesCheck
|
| + * @suppressReceiverCheck
|
| + * @this {!Element}
|
| + */
|
| + function toggleClassAndInjectStyleRule(pseudoType, hidden) {
|
| + const classNamePrefix = '__web-inspector-hide';
|
| + const classNameSuffix = '-shortcut__';
|
| + const styleTagId = '__web-inspector-hide-shortcut-style__';
|
| + var selectors = [];
|
| + selectors.push('.__web-inspector-hide-shortcut__');
|
| + selectors.push('.__web-inspector-hide-shortcut__ *');
|
| + selectors.push('.__web-inspector-hidebefore-shortcut__::before');
|
| + selectors.push('.__web-inspector-hideafter-shortcut__::after');
|
| + var selector = selectors.join(', ');
|
| + var ruleBody = ' visibility: hidden !important;';
|
| + var rule = '\n' + selector + '\n{\n' + ruleBody + '\n}\n';
|
| + var className = classNamePrefix + (pseudoType || '') + classNameSuffix;
|
| + this.classList.toggle(className, hidden);
|
| +
|
| + var localRoot = this;
|
| + while (localRoot.parentNode)
|
| + localRoot = localRoot.parentNode;
|
| + if (localRoot.nodeType === Node.DOCUMENT_NODE)
|
| + localRoot = document.head;
|
| +
|
| + var style = localRoot.querySelector('style#' + styleTagId);
|
| + if (style)
|
| + return;
|
| +
|
| + style = document.createElement('style');
|
| + style.id = styleTagId;
|
| + style.type = 'text/css';
|
| + style.textContent = rule;
|
| +
|
| + localRoot.appendChild(style);
|
| + }
|
| +
|
| + object.callFunction(toggleClassAndInjectStyleRule, [{value: pseudoType}, {value: !hidden}], userCallback);
|
| + object.release();
|
| + node.setMarker('hidden-marker', hidden ? null : true);
|
| + }
|
|
|
| - return visibleChildren;
|
| - },
|
| + effectiveNode.resolveToObject('', resolvedNode);
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.DOMNode} node
|
| + * @return {boolean}
|
| + */
|
| + isToggledToHidden(node) {
|
| + return !!node.marker('hidden-marker');
|
| + }
|
| +
|
| + _reset() {
|
| + this.rootDOMNode = null;
|
| + this.selectDOMNode(null, false);
|
| + this._popoverHelper.hidePopover();
|
| + delete this._clipboardNodeData;
|
| + WebInspector.DOMModel.hideDOMNodeHighlight();
|
| + this._updateRecords.clear();
|
| + }
|
| +
|
| + wireToDOMModel() {
|
| + this._domModel[WebInspector.ElementsTreeOutline._treeOutlineSymbol] = this;
|
| + this._domModel.addEventListener(WebInspector.DOMModel.Events.NodeInserted, this._nodeInserted, this);
|
| + this._domModel.addEventListener(WebInspector.DOMModel.Events.NodeRemoved, this._nodeRemoved, this);
|
| + this._domModel.addEventListener(WebInspector.DOMModel.Events.AttrModified, this._attributeModified, this);
|
| + this._domModel.addEventListener(WebInspector.DOMModel.Events.AttrRemoved, this._attributeRemoved, this);
|
| + this._domModel.addEventListener(
|
| + WebInspector.DOMModel.Events.CharacterDataModified, this._characterDataModified, this);
|
| + this._domModel.addEventListener(WebInspector.DOMModel.Events.DocumentUpdated, this._documentUpdated, this);
|
| + this._domModel.addEventListener(
|
| + WebInspector.DOMModel.Events.ChildNodeCountUpdated, this._childNodeCountUpdated, this);
|
| + this._domModel.addEventListener(
|
| + WebInspector.DOMModel.Events.DistributedNodesChanged, this._distributedNodesChanged, this);
|
| + }
|
| +
|
| + unwireFromDOMModel() {
|
| + this._domModel.removeEventListener(WebInspector.DOMModel.Events.NodeInserted, this._nodeInserted, this);
|
| + this._domModel.removeEventListener(WebInspector.DOMModel.Events.NodeRemoved, this._nodeRemoved, this);
|
| + this._domModel.removeEventListener(WebInspector.DOMModel.Events.AttrModified, this._attributeModified, this);
|
| + this._domModel.removeEventListener(WebInspector.DOMModel.Events.AttrRemoved, this._attributeRemoved, this);
|
| + this._domModel.removeEventListener(
|
| + WebInspector.DOMModel.Events.CharacterDataModified, this._characterDataModified, this);
|
| + this._domModel.removeEventListener(WebInspector.DOMModel.Events.DocumentUpdated, this._documentUpdated, this);
|
| + this._domModel.removeEventListener(
|
| + WebInspector.DOMModel.Events.ChildNodeCountUpdated, this._childNodeCountUpdated, this);
|
| + this._domModel.removeEventListener(
|
| + WebInspector.DOMModel.Events.DistributedNodesChanged, this._distributedNodesChanged, this);
|
| + delete this._domModel[WebInspector.ElementsTreeOutline._treeOutlineSymbol];
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.DOMNode} node
|
| + * @return {!WebInspector.ElementsTreeOutline.UpdateRecord}
|
| + */
|
| + _addUpdateRecord(node) {
|
| + var record = this._updateRecords.get(node);
|
| + if (!record) {
|
| + record = new WebInspector.ElementsTreeOutline.UpdateRecord();
|
| + this._updateRecords.set(node, record);
|
| + }
|
| + return record;
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.DOMNode} node
|
| + * @return {?WebInspector.ElementsTreeOutline.UpdateRecord}
|
| + */
|
| + _updateRecordForHighlight(node) {
|
| + if (!this._visible)
|
| + return null;
|
| + return this._updateRecords.get(node) || null;
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.Event} event
|
| + */
|
| + _documentUpdated(event) {
|
| + var inspectedRootDocument = event.data;
|
| +
|
| + this._reset();
|
| +
|
| + if (!inspectedRootDocument)
|
| + return;
|
| +
|
| + this.rootDOMNode = inspectedRootDocument;
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.Event} event
|
| + */
|
| + _attributeModified(event) {
|
| + var node = /** @type {!WebInspector.DOMNode} */ (event.data.node);
|
| + this._addUpdateRecord(node).attributeModified(event.data.name);
|
| + this._updateModifiedNodesSoon();
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.Event} event
|
| + */
|
| + _attributeRemoved(event) {
|
| + var node = /** @type {!WebInspector.DOMNode} */ (event.data.node);
|
| + this._addUpdateRecord(node).attributeRemoved(event.data.name);
|
| + this._updateModifiedNodesSoon();
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.Event} event
|
| + */
|
| + _characterDataModified(event) {
|
| + var node = /** @type {!WebInspector.DOMNode} */ (event.data);
|
| + this._addUpdateRecord(node).charDataModified();
|
| + // Text could be large and force us to render itself as the child in the tree outline.
|
| + if (node.parentNode && node.parentNode.firstChild === node.parentNode.lastChild)
|
| + this._addUpdateRecord(node.parentNode).childrenModified();
|
| + this._updateModifiedNodesSoon();
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.Event} event
|
| + */
|
| + _nodeInserted(event) {
|
| + var node = /** @type {!WebInspector.DOMNode} */ (event.data);
|
| + this._addUpdateRecord(/** @type {!WebInspector.DOMNode} */ (node.parentNode)).nodeInserted(node);
|
| + this._updateModifiedNodesSoon();
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.Event} event
|
| + */
|
| + _nodeRemoved(event) {
|
| + var node = /** @type {!WebInspector.DOMNode} */ (event.data.node);
|
| + var parentNode = /** @type {!WebInspector.DOMNode} */ (event.data.parent);
|
| + this.resetClipboardIfNeeded(node);
|
| + this._addUpdateRecord(parentNode).nodeRemoved(node);
|
| + this._updateModifiedNodesSoon();
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.Event} event
|
| + */
|
| + _childNodeCountUpdated(event) {
|
| + var node = /** @type {!WebInspector.DOMNode} */ (event.data);
|
| + this._addUpdateRecord(node).childrenModified();
|
| + this._updateModifiedNodesSoon();
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.Event} event
|
| + */
|
| + _distributedNodesChanged(event) {
|
| + var node = /** @type {!WebInspector.DOMNode} */ (event.data);
|
| + this._addUpdateRecord(node).childrenModified();
|
| + this._updateModifiedNodesSoon();
|
| + }
|
| +
|
| + _updateModifiedNodesSoon() {
|
| + if (!this._updateRecords.size)
|
| + return;
|
| + if (this._updateModifiedNodesTimeout)
|
| + return;
|
| + this._updateModifiedNodesTimeout = setTimeout(this._updateModifiedNodes.bind(this), 50);
|
| + }
|
| +
|
| + _updateModifiedNodes() {
|
| + if (this._updateModifiedNodesTimeout) {
|
| + clearTimeout(this._updateModifiedNodesTimeout);
|
| + delete this._updateModifiedNodesTimeout;
|
| + }
|
|
|
| - /**
|
| - * @param {!WebInspector.DOMNode} node
|
| - * @return {boolean}
|
| - */
|
| - _hasVisibleChildren: function(node)
|
| - {
|
| - if (node.importedDocument())
|
| - return true;
|
| - if (node.templateContent())
|
| - return true;
|
| - if (WebInspector.ElementsTreeElement.visibleShadowRoots(node).length)
|
| - return true;
|
| - if (node.hasPseudoElements())
|
| - return true;
|
| - if (node.isInsertionPoint())
|
| - return true;
|
| - return !!node.childNodeCount() && !WebInspector.ElementsTreeElement.canShowInlineText(node);
|
| - },
|
| + var updatedNodes = this._updateRecords.keysArray();
|
| + var hidePanelWhileUpdating = updatedNodes.length > 10;
|
| + if (hidePanelWhileUpdating) {
|
| + var treeOutlineContainerElement = this.element.parentNode;
|
| + var originalScrollTop = treeOutlineContainerElement ? treeOutlineContainerElement.scrollTop : 0;
|
| + this._element.classList.add('hidden');
|
| + }
|
|
|
| - /**
|
| - * @param {!WebInspector.ElementsTreeElement} treeElement
|
| - */
|
| - _createExpandAllButtonTreeElement: function(treeElement)
|
| - {
|
| - var button = createTextButton("", handleLoadAllChildren.bind(this));
|
| - button.value = "";
|
| - var expandAllButtonElement = new TreeElement(button);
|
| - expandAllButtonElement.selectable = false;
|
| - expandAllButtonElement.expandAllButton = true;
|
| - expandAllButtonElement.button = button;
|
| - return expandAllButtonElement;
|
| -
|
| - /**
|
| - * @this {WebInspector.ElementsTreeOutline}
|
| - * @param {!Event} event
|
| - */
|
| - function handleLoadAllChildren(event)
|
| - {
|
| - var visibleChildCount = this._visibleChildren(treeElement.node()).length;
|
| - this.setExpandedChildrenLimit(treeElement, Math.max(visibleChildCount, treeElement.expandedChildrenLimit() + WebInspector.ElementsTreeElement.InitialChildrenLimit));
|
| - event.consume();
|
| - }
|
| - },
|
| + if (this._rootDOMNode && this._updateRecords.get(this._rootDOMNode) &&
|
| + this._updateRecords.get(this._rootDOMNode).hasChangedChildren()) {
|
| + // Document's children have changed, perform total update.
|
| + this.update();
|
| + } else {
|
| + for (var node of this._updateRecords.keys()) {
|
| + if (this._updateRecords.get(node).hasChangedChildren())
|
| + this._updateModifiedParentNode(node);
|
| + else
|
| + this._updateModifiedNode(node);
|
| + }
|
| + }
|
|
|
| - /**
|
| - * @param {!WebInspector.ElementsTreeElement} treeElement
|
| - * @param {number} expandedChildrenLimit
|
| - */
|
| - setExpandedChildrenLimit: function(treeElement, expandedChildrenLimit)
|
| - {
|
| - if (treeElement.expandedChildrenLimit() === expandedChildrenLimit)
|
| - return;
|
| + if (hidePanelWhileUpdating) {
|
| + this._element.classList.remove('hidden');
|
| + if (originalScrollTop)
|
| + treeOutlineContainerElement.scrollTop = originalScrollTop;
|
| + }
|
|
|
| - treeElement.setExpandedChildrenLimit(expandedChildrenLimit);
|
| - if (treeElement.treeOutline && !this._treeElementsBeingUpdated.has(treeElement))
|
| - this._updateModifiedParentNode(treeElement.node());
|
| - },
|
| + this._updateRecords.clear();
|
| + this._fireElementsTreeUpdated(updatedNodes);
|
| + }
|
| +
|
| + _updateModifiedNode(node) {
|
| + var treeElement = this.findTreeElement(node);
|
| + if (treeElement)
|
| + treeElement.updateTitle(this._updateRecordForHighlight(node));
|
| + }
|
| +
|
| + _updateModifiedParentNode(node) {
|
| + var parentTreeElement = this.findTreeElement(node);
|
| + if (parentTreeElement) {
|
| + parentTreeElement.setExpandable(this._hasVisibleChildren(node));
|
| + parentTreeElement.updateTitle(this._updateRecordForHighlight(node));
|
| + if (parentTreeElement.populated)
|
| + this._updateChildren(parentTreeElement);
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.ElementsTreeElement} treeElement
|
| + */
|
| + populateTreeElement(treeElement) {
|
| + if (treeElement.childCount() || !treeElement.isExpandable())
|
| + return;
|
| +
|
| + this._updateModifiedParentNode(treeElement.node());
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.DOMNode} node
|
| + * @param {boolean=} closingTag
|
| + * @return {!WebInspector.ElementsTreeElement}
|
| + */
|
| + _createElementTreeElement(node, closingTag) {
|
| + var treeElement = new WebInspector.ElementsTreeElement(node, closingTag);
|
| + treeElement.setExpandable(!closingTag && this._hasVisibleChildren(node));
|
| + if (node.nodeType() === Node.ELEMENT_NODE && node.parentNode && node.parentNode.nodeType() === Node.DOCUMENT_NODE &&
|
| + !node.parentNode.parentNode)
|
| + treeElement.setCollapsible(false);
|
| + treeElement.selectable = this._selectEnabled;
|
| + return treeElement;
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.ElementsTreeElement} treeElement
|
| + * @param {!WebInspector.DOMNode} child
|
| + * @return {?WebInspector.ElementsTreeElement}
|
| + */
|
| + _showChild(treeElement, child) {
|
| + if (treeElement.isClosingTag())
|
| + return null;
|
| +
|
| + var index = this._visibleChildren(treeElement.node()).indexOf(child);
|
| + if (index === -1)
|
| + return null;
|
| +
|
| + if (index >= treeElement.expandedChildrenLimit())
|
| + this.setExpandedChildrenLimit(treeElement, index + 1);
|
| + return /** @type {!WebInspector.ElementsTreeElement} */ (treeElement.childAt(index));
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.DOMNode} node
|
| + * @return {!Array.<!WebInspector.DOMNode>} visibleChildren
|
| + */
|
| + _visibleChildren(node) {
|
| + var visibleChildren = WebInspector.ElementsTreeElement.visibleShadowRoots(node);
|
| +
|
| + var importedDocument = node.importedDocument();
|
| + if (importedDocument)
|
| + visibleChildren.push(importedDocument);
|
| +
|
| + var templateContent = node.templateContent();
|
| + if (templateContent)
|
| + visibleChildren.push(templateContent);
|
| +
|
| + var beforePseudoElement = node.beforePseudoElement();
|
| + if (beforePseudoElement)
|
| + visibleChildren.push(beforePseudoElement);
|
| +
|
| + if (node.childNodeCount()) {
|
| + var children = node.children();
|
| + if (!this._showHTMLCommentsSetting.get())
|
| + children = children.filter(n => n.nodeType() !== Node.COMMENT_NODE);
|
| + visibleChildren = visibleChildren.concat(children);
|
| + }
|
|
|
| - /**
|
| - * @param {!WebInspector.ElementsTreeElement} treeElement
|
| + var afterPseudoElement = node.afterPseudoElement();
|
| + if (afterPseudoElement)
|
| + visibleChildren.push(afterPseudoElement);
|
| +
|
| + return visibleChildren;
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.DOMNode} node
|
| + * @return {boolean}
|
| + */
|
| + _hasVisibleChildren(node) {
|
| + if (node.importedDocument())
|
| + return true;
|
| + if (node.templateContent())
|
| + return true;
|
| + if (WebInspector.ElementsTreeElement.visibleShadowRoots(node).length)
|
| + return true;
|
| + if (node.hasPseudoElements())
|
| + return true;
|
| + if (node.isInsertionPoint())
|
| + return true;
|
| + return !!node.childNodeCount() && !WebInspector.ElementsTreeElement.canShowInlineText(node);
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.ElementsTreeElement} treeElement
|
| + */
|
| + _createExpandAllButtonTreeElement(treeElement) {
|
| + var button = createTextButton('', handleLoadAllChildren.bind(this));
|
| + button.value = '';
|
| + var expandAllButtonElement = new TreeElement(button);
|
| + expandAllButtonElement.selectable = false;
|
| + expandAllButtonElement.expandAllButton = true;
|
| + expandAllButtonElement.button = button;
|
| + return expandAllButtonElement;
|
| +
|
| + /**
|
| + * @this {WebInspector.ElementsTreeOutline}
|
| + * @param {!Event} event
|
| */
|
| - _updateChildren: function(treeElement)
|
| - {
|
| - if (!treeElement.isExpandable()) {
|
| - var selectedTreeElement = treeElement.treeOutline.selectedTreeElement;
|
| - if (selectedTreeElement && selectedTreeElement.hasAncestor(treeElement))
|
| - treeElement.select(true);
|
| - treeElement.removeChildren();
|
| - return;
|
| - }
|
| + function handleLoadAllChildren(event) {
|
| + var visibleChildCount = this._visibleChildren(treeElement.node()).length;
|
| + this.setExpandedChildrenLimit(
|
| + treeElement, Math.max(
|
| + visibleChildCount, treeElement.expandedChildrenLimit() +
|
| + WebInspector.ElementsTreeElement.InitialChildrenLimit));
|
| + event.consume();
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.ElementsTreeElement} treeElement
|
| + * @param {number} expandedChildrenLimit
|
| + */
|
| + setExpandedChildrenLimit(treeElement, expandedChildrenLimit) {
|
| + if (treeElement.expandedChildrenLimit() === expandedChildrenLimit)
|
| + return;
|
| +
|
| + treeElement.setExpandedChildrenLimit(expandedChildrenLimit);
|
| + if (treeElement.treeOutline && !this._treeElementsBeingUpdated.has(treeElement))
|
| + this._updateModifiedParentNode(treeElement.node());
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.ElementsTreeElement} treeElement
|
| + */
|
| + _updateChildren(treeElement) {
|
| + if (!treeElement.isExpandable()) {
|
| + var selectedTreeElement = treeElement.treeOutline.selectedTreeElement;
|
| + if (selectedTreeElement && selectedTreeElement.hasAncestor(treeElement))
|
| + treeElement.select(true);
|
| + treeElement.removeChildren();
|
| + return;
|
| + }
|
|
|
| - console.assert(!treeElement.isClosingTag());
|
| + console.assert(!treeElement.isClosingTag());
|
|
|
| - treeElement.node().getChildNodes(childNodesLoaded.bind(this));
|
| -
|
| - /**
|
| - * @param {?Array.<!WebInspector.DOMNode>} children
|
| - * @this {WebInspector.ElementsTreeOutline}
|
| - */
|
| - function childNodesLoaded(children)
|
| - {
|
| - // FIXME: sort this out, it should not happen.
|
| - if (!children)
|
| - return;
|
| - this._innerUpdateChildren(treeElement);
|
| - }
|
| - },
|
| + treeElement.node().getChildNodes(childNodesLoaded.bind(this));
|
|
|
| /**
|
| - * @param {!WebInspector.ElementsTreeElement} treeElement
|
| - * @param {!WebInspector.DOMNode} child
|
| - * @param {number} index
|
| - * @param {boolean=} closingTag
|
| - * @return {!WebInspector.ElementsTreeElement}
|
| + * @param {?Array.<!WebInspector.DOMNode>} children
|
| + * @this {WebInspector.ElementsTreeOutline}
|
| */
|
| - insertChildElement: function(treeElement, child, index, closingTag)
|
| - {
|
| - var newElement = this._createElementTreeElement(child, closingTag);
|
| - treeElement.insertChild(newElement, index);
|
| - return newElement;
|
| - },
|
| + function childNodesLoaded(children) {
|
| + // FIXME: sort this out, it should not happen.
|
| + if (!children)
|
| + return;
|
| + this._innerUpdateChildren(treeElement);
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.ElementsTreeElement} treeElement
|
| + * @param {!WebInspector.DOMNode} child
|
| + * @param {number} index
|
| + * @param {boolean=} closingTag
|
| + * @return {!WebInspector.ElementsTreeElement}
|
| + */
|
| + insertChildElement(treeElement, child, index, closingTag) {
|
| + var newElement = this._createElementTreeElement(child, closingTag);
|
| + treeElement.insertChild(newElement, index);
|
| + return newElement;
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.ElementsTreeElement} treeElement
|
| + * @param {!WebInspector.ElementsTreeElement} child
|
| + * @param {number} targetIndex
|
| + */
|
| + _moveChild(treeElement, child, targetIndex) {
|
| + if (treeElement.indexOfChild(child) === targetIndex)
|
| + return;
|
| + var wasSelected = child.selected;
|
| + if (child.parent)
|
| + child.parent.removeChild(child);
|
| + treeElement.insertChild(child, targetIndex);
|
| + if (wasSelected)
|
| + child.select();
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.ElementsTreeElement} treeElement
|
| + */
|
| + _innerUpdateChildren(treeElement) {
|
| + if (this._treeElementsBeingUpdated.has(treeElement))
|
| + return;
|
| +
|
| + this._treeElementsBeingUpdated.add(treeElement);
|
| +
|
| + var node = treeElement.node();
|
| + var visibleChildren = this._visibleChildren(node);
|
| + var visibleChildrenSet = new Set(visibleChildren);
|
| +
|
| + // Remove any tree elements that no longer have this node as their parent and save
|
| + // all existing elements that could be reused. This also removes closing tag element.
|
| + var existingTreeElements = new Map();
|
| + for (var i = treeElement.childCount() - 1; i >= 0; --i) {
|
| + var existingTreeElement = treeElement.childAt(i);
|
| + if (!(existingTreeElement instanceof WebInspector.ElementsTreeElement)) {
|
| + // Remove expand all button and shadow host toolbar.
|
| + treeElement.removeChildAtIndex(i);
|
| + continue;
|
| + }
|
| + var elementsTreeElement = /** @type {!WebInspector.ElementsTreeElement} */ (existingTreeElement);
|
| + var existingNode = elementsTreeElement.node();
|
| +
|
| + if (visibleChildrenSet.has(existingNode)) {
|
| + existingTreeElements.set(existingNode, existingTreeElement);
|
| + continue;
|
| + }
|
| +
|
| + treeElement.removeChildAtIndex(i);
|
| + }
|
|
|
| - /**
|
| - * @param {!WebInspector.ElementsTreeElement} treeElement
|
| - * @param {!WebInspector.ElementsTreeElement} child
|
| - * @param {number} targetIndex
|
| - */
|
| - _moveChild: function(treeElement, child, targetIndex)
|
| - {
|
| - if (treeElement.indexOfChild(child) === targetIndex)
|
| - return;
|
| - var wasSelected = child.selected;
|
| - if (child.parent)
|
| - child.parent.removeChild(child);
|
| - treeElement.insertChild(child, targetIndex);
|
| - if (wasSelected)
|
| - child.select();
|
| - },
|
| + for (var i = 0; i < visibleChildren.length && i < treeElement.expandedChildrenLimit(); ++i) {
|
| + var child = visibleChildren[i];
|
| + var existingTreeElement = existingTreeElements.get(child) || this.findTreeElement(child);
|
| + if (existingTreeElement && existingTreeElement !== treeElement) {
|
| + // If an existing element was found, just move it.
|
| + this._moveChild(treeElement, existingTreeElement, i);
|
| + } else {
|
| + // No existing element found, insert a new element.
|
| + var newElement = this.insertChildElement(treeElement, child, i);
|
| + if (this._updateRecordForHighlight(node) && treeElement.expanded)
|
| + WebInspector.ElementsTreeElement.animateOnDOMUpdate(newElement);
|
| + // If a node was inserted in the middle of existing list dynamically we might need to increase the limit.
|
| + if (treeElement.childCount() > treeElement.expandedChildrenLimit())
|
| + this.setExpandedChildrenLimit(treeElement, treeElement.expandedChildrenLimit() + 1);
|
| + }
|
| + }
|
|
|
| - /**
|
| - * @param {!WebInspector.ElementsTreeElement} treeElement
|
| - */
|
| - _innerUpdateChildren: function(treeElement)
|
| - {
|
| - if (this._treeElementsBeingUpdated.has(treeElement))
|
| - return;
|
| -
|
| - this._treeElementsBeingUpdated.add(treeElement);
|
| -
|
| - var node = treeElement.node();
|
| - var visibleChildren = this._visibleChildren(node);
|
| - var visibleChildrenSet = new Set(visibleChildren);
|
| -
|
| - // Remove any tree elements that no longer have this node as their parent and save
|
| - // all existing elements that could be reused. This also removes closing tag element.
|
| - var existingTreeElements = new Map();
|
| - for (var i = treeElement.childCount() - 1; i >= 0; --i) {
|
| - var existingTreeElement = treeElement.childAt(i);
|
| - if (!(existingTreeElement instanceof WebInspector.ElementsTreeElement)) {
|
| - // Remove expand all button and shadow host toolbar.
|
| - treeElement.removeChildAtIndex(i);
|
| - continue;
|
| - }
|
| - var elementsTreeElement = /** @type {!WebInspector.ElementsTreeElement} */ (existingTreeElement);
|
| - var existingNode = elementsTreeElement.node();
|
| -
|
| - if (visibleChildrenSet.has(existingNode)) {
|
| - existingTreeElements.set(existingNode, existingTreeElement);
|
| - continue;
|
| - }
|
| -
|
| - treeElement.removeChildAtIndex(i);
|
| - }
|
| + // Update expand all button.
|
| + var expandedChildCount = treeElement.childCount();
|
| + if (visibleChildren.length > expandedChildCount) {
|
| + var targetButtonIndex = expandedChildCount;
|
| + if (!treeElement.expandAllButtonElement)
|
| + treeElement.expandAllButtonElement = this._createExpandAllButtonTreeElement(treeElement);
|
| + treeElement.insertChild(treeElement.expandAllButtonElement, targetButtonIndex);
|
| + treeElement.expandAllButtonElement.button.textContent =
|
| + WebInspector.UIString('Show All Nodes (%d More)', visibleChildren.length - expandedChildCount);
|
| + } else if (treeElement.expandAllButtonElement) {
|
| + delete treeElement.expandAllButtonElement;
|
| + }
|
|
|
| - for (var i = 0; i < visibleChildren.length && i < treeElement.expandedChildrenLimit(); ++i) {
|
| - var child = visibleChildren[i];
|
| - var existingTreeElement = existingTreeElements.get(child) || this.findTreeElement(child);
|
| - if (existingTreeElement && existingTreeElement !== treeElement) {
|
| - // If an existing element was found, just move it.
|
| - this._moveChild(treeElement, existingTreeElement, i);
|
| - } else {
|
| - // No existing element found, insert a new element.
|
| - var newElement = this.insertChildElement(treeElement, child, i);
|
| - if (this._updateRecordForHighlight(node) && treeElement.expanded)
|
| - WebInspector.ElementsTreeElement.animateOnDOMUpdate(newElement);
|
| - // If a node was inserted in the middle of existing list dynamically we might need to increase the limit.
|
| - if (treeElement.childCount() > treeElement.expandedChildrenLimit())
|
| - this.setExpandedChildrenLimit(treeElement, treeElement.expandedChildrenLimit() + 1);
|
| - }
|
| - }
|
| + // Insert shortcuts to distrubuted children.
|
| + if (node.isInsertionPoint()) {
|
| + for (var distributedNode of node.distributedNodes())
|
| + treeElement.appendChild(new WebInspector.ElementsTreeOutline.ShortcutTreeElement(distributedNode));
|
| + }
|
|
|
| - // Update expand all button.
|
| - var expandedChildCount = treeElement.childCount();
|
| - if (visibleChildren.length > expandedChildCount) {
|
| - var targetButtonIndex = expandedChildCount;
|
| - if (!treeElement.expandAllButtonElement)
|
| - treeElement.expandAllButtonElement = this._createExpandAllButtonTreeElement(treeElement);
|
| - treeElement.insertChild(treeElement.expandAllButtonElement, targetButtonIndex);
|
| - treeElement.expandAllButtonElement.button.textContent = WebInspector.UIString("Show All Nodes (%d More)", visibleChildren.length - expandedChildCount);
|
| - } else if (treeElement.expandAllButtonElement) {
|
| - delete treeElement.expandAllButtonElement;
|
| - }
|
| + // Insert close tag.
|
| + if (node.nodeType() === Node.ELEMENT_NODE && treeElement.isExpandable())
|
| + this.insertChildElement(treeElement, node, treeElement.childCount(), true);
|
| +
|
| + this._treeElementsBeingUpdated.delete(treeElement);
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.Event} event
|
| + */
|
| + _markersChanged(event) {
|
| + var node = /** @type {!WebInspector.DOMNode} */ (event.data);
|
| + var treeElement = node[this._treeElementSymbol];
|
| + if (treeElement)
|
| + treeElement.updateDecorations();
|
| + }
|
| +};
|
|
|
| - // Insert shortcuts to distrubuted children.
|
| - if (node.isInsertionPoint()) {
|
| - for (var distributedNode of node.distributedNodes())
|
| - treeElement.appendChild(new WebInspector.ElementsTreeOutline.ShortcutTreeElement(distributedNode));
|
| - }
|
| +WebInspector.ElementsTreeOutline._treeOutlineSymbol = Symbol('treeOutline');
|
|
|
| - // Insert close tag.
|
| - if (node.nodeType() === Node.ELEMENT_NODE && treeElement.isExpandable())
|
| - this.insertChildElement(treeElement, node, treeElement.childCount(), true);
|
|
|
| - this._treeElementsBeingUpdated.delete(treeElement);
|
| - },
|
| +/** @typedef {{node: !WebInspector.DOMNode, isCut: boolean}} */
|
| +WebInspector.ElementsTreeOutline.ClipboardData;
|
|
|
| - /**
|
| - * @param {!WebInspector.Event} event
|
| - */
|
| - _markersChanged: function(event)
|
| - {
|
| - var node = /** @type {!WebInspector.DOMNode} */ (event.data);
|
| - var treeElement = node[this._treeElementSymbol];
|
| - if (treeElement)
|
| - treeElement.updateDecorations();
|
| - },
|
| -
|
| - __proto__: TreeOutline.prototype
|
| +/** @enum {symbol} */
|
| +WebInspector.ElementsTreeOutline.Events = {
|
| + SelectedNodeChanged: Symbol('SelectedNodeChanged'),
|
| + ElementsTreeUpdated: Symbol('ElementsTreeUpdated')
|
| };
|
|
|
| /**
|
| - * @constructor
|
| + * @const
|
| + * @type {!Object.<string, string>}
|
| */
|
| -WebInspector.ElementsTreeOutline.UpdateRecord = function()
|
| -{
|
| +WebInspector.ElementsTreeOutline.MappedCharToEntity = {
|
| + '\u00a0': 'nbsp',
|
| + '\u0093': '#147', // <control>
|
| + '\u00ad': 'shy',
|
| + '\u2002': 'ensp',
|
| + '\u2003': 'emsp',
|
| + '\u2009': 'thinsp',
|
| + '\u200a': '#8202', // Hairspace
|
| + '\u200b': '#8203', // ZWSP
|
| + '\u200c': 'zwnj',
|
| + '\u200d': 'zwj',
|
| + '\u200e': 'lrm',
|
| + '\u200f': 'rlm',
|
| + '\u202a': '#8234', // LRE
|
| + '\u202b': '#8235', // RLE
|
| + '\u202c': '#8236', // PDF
|
| + '\u202d': '#8237', // LRO
|
| + '\u202e': '#8238', // RLO
|
| + '\ufeff': '#65279' // BOM
|
| };
|
|
|
| -WebInspector.ElementsTreeOutline.UpdateRecord.prototype = {
|
| - /**
|
| - * @param {string} attrName
|
| - */
|
| - attributeModified: function(attrName)
|
| - {
|
| - if (this._removedAttributes && this._removedAttributes.has(attrName))
|
| - this._removedAttributes.delete(attrName);
|
| - if (!this._modifiedAttributes)
|
| - this._modifiedAttributes = /** @type {!Set.<string>} */ (new Set());
|
| - this._modifiedAttributes.add(attrName);
|
| - },
|
| -
|
| - /**
|
| - * @param {string} attrName
|
| - */
|
| - attributeRemoved: function(attrName)
|
| - {
|
| - if (this._modifiedAttributes && this._modifiedAttributes.has(attrName))
|
| - this._modifiedAttributes.delete(attrName);
|
| - if (!this._removedAttributes)
|
| - this._removedAttributes = /** @type {!Set.<string>} */ (new Set());
|
| - this._removedAttributes.add(attrName);
|
| - },
|
| -
|
| - /**
|
| - * @param {!WebInspector.DOMNode} node
|
| - */
|
| - nodeInserted: function(node)
|
| - {
|
| - this._hasChangedChildren = true;
|
| - },
|
| -
|
| - nodeRemoved: function(node)
|
| - {
|
| - this._hasChangedChildren = true;
|
| - this._hasRemovedChildren = true;
|
| - },
|
| -
|
| - charDataModified: function()
|
| - {
|
| - this._charDataModified = true;
|
| - },
|
| -
|
| - childrenModified: function()
|
| - {
|
| - this._hasChangedChildren = true;
|
| - },
|
| -
|
| - /**
|
| - * @param {string} attributeName
|
| - * @return {boolean}
|
| - */
|
| - isAttributeModified: function(attributeName)
|
| - {
|
| - return this._modifiedAttributes && this._modifiedAttributes.has(attributeName);
|
| - },
|
| -
|
| - /**
|
| - * @return {boolean}
|
| - */
|
| - hasRemovedAttributes: function()
|
| - {
|
| - return !!this._removedAttributes && !!this._removedAttributes.size;
|
| - },
|
| -
|
| - /**
|
| - * @return {boolean}
|
| - */
|
| - isCharDataModified: function()
|
| - {
|
| - return !!this._charDataModified;
|
| - },
|
| -
|
| - /**
|
| - * @return {boolean}
|
| - */
|
| - hasChangedChildren: function()
|
| - {
|
| - return !!this._hasChangedChildren;
|
| - },
|
| -
|
| - /**
|
| - * @return {boolean}
|
| - */
|
| - hasRemovedChildren: function()
|
| - {
|
| - return !!this._hasRemovedChildren;
|
| - }
|
| +/**
|
| + * @unrestricted
|
| + */
|
| +WebInspector.ElementsTreeOutline.UpdateRecord = class {
|
| + /**
|
| + * @param {string} attrName
|
| + */
|
| + attributeModified(attrName) {
|
| + if (this._removedAttributes && this._removedAttributes.has(attrName))
|
| + this._removedAttributes.delete(attrName);
|
| + if (!this._modifiedAttributes)
|
| + this._modifiedAttributes = /** @type {!Set.<string>} */ (new Set());
|
| + this._modifiedAttributes.add(attrName);
|
| + }
|
| +
|
| + /**
|
| + * @param {string} attrName
|
| + */
|
| + attributeRemoved(attrName) {
|
| + if (this._modifiedAttributes && this._modifiedAttributes.has(attrName))
|
| + this._modifiedAttributes.delete(attrName);
|
| + if (!this._removedAttributes)
|
| + this._removedAttributes = /** @type {!Set.<string>} */ (new Set());
|
| + this._removedAttributes.add(attrName);
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.DOMNode} node
|
| + */
|
| + nodeInserted(node) {
|
| + this._hasChangedChildren = true;
|
| + }
|
| +
|
| + nodeRemoved(node) {
|
| + this._hasChangedChildren = true;
|
| + this._hasRemovedChildren = true;
|
| + }
|
| +
|
| + charDataModified() {
|
| + this._charDataModified = true;
|
| + }
|
| +
|
| + childrenModified() {
|
| + this._hasChangedChildren = true;
|
| + }
|
| +
|
| + /**
|
| + * @param {string} attributeName
|
| + * @return {boolean}
|
| + */
|
| + isAttributeModified(attributeName) {
|
| + return this._modifiedAttributes && this._modifiedAttributes.has(attributeName);
|
| + }
|
| +
|
| + /**
|
| + * @return {boolean}
|
| + */
|
| + hasRemovedAttributes() {
|
| + return !!this._removedAttributes && !!this._removedAttributes.size;
|
| + }
|
| +
|
| + /**
|
| + * @return {boolean}
|
| + */
|
| + isCharDataModified() {
|
| + return !!this._charDataModified;
|
| + }
|
| +
|
| + /**
|
| + * @return {boolean}
|
| + */
|
| + hasChangedChildren() {
|
| + return !!this._hasChangedChildren;
|
| + }
|
| +
|
| + /**
|
| + * @return {boolean}
|
| + */
|
| + hasRemovedChildren() {
|
| + return !!this._hasRemovedChildren;
|
| + }
|
| };
|
|
|
| /**
|
| - * @constructor
|
| * @implements {WebInspector.Renderer}
|
| + * @unrestricted
|
| */
|
| -WebInspector.ElementsTreeOutline.Renderer = function()
|
| -{
|
| -};
|
| -
|
| -WebInspector.ElementsTreeOutline.Renderer.prototype = {
|
| - /**
|
| - * @override
|
| - * @param {!Object} object
|
| - * @return {!Promise.<!Element>}
|
| - */
|
| - render: function(object)
|
| - {
|
| - return new Promise(renderPromise);
|
| -
|
| - /**
|
| - * @param {function(!Element)} resolve
|
| - * @param {function(!Error)} reject
|
| - */
|
| - function renderPromise(resolve, reject)
|
| - {
|
| - if (object instanceof WebInspector.DOMNode) {
|
| - onNodeResolved(/** @type {!WebInspector.DOMNode} */ (object));
|
| - } else if (object instanceof WebInspector.DeferredDOMNode) {
|
| - (/** @type {!WebInspector.DeferredDOMNode} */ (object)).resolve(onNodeResolved);
|
| - } else if (object instanceof WebInspector.RemoteObject) {
|
| - var domModel = WebInspector.DOMModel.fromTarget((/** @type {!WebInspector.RemoteObject} */ (object)).target());
|
| - if (domModel)
|
| - domModel.pushObjectAsNodeToFrontend(object, onNodeResolved);
|
| - else
|
| - reject(new Error("No dom model for given JS object target found."));
|
| - } else {
|
| - reject(new Error("Can't reveal not a node."));
|
| - }
|
| -
|
| - /**
|
| - * @param {?WebInspector.DOMNode} node
|
| - */
|
| - function onNodeResolved(node)
|
| - {
|
| - if (!node) {
|
| - reject(new Error("Could not resolve node."));
|
| - return;
|
| - }
|
| - var treeOutline = new WebInspector.ElementsTreeOutline(node.domModel(), false, false);
|
| - treeOutline.rootDOMNode = node;
|
| - if (!treeOutline.firstChild().isExpandable())
|
| - treeOutline._element.classList.add("single-node");
|
| - treeOutline.setVisible(true);
|
| - treeOutline.element.treeElementForTest = treeOutline.firstChild();
|
| - resolve(treeOutline.element);
|
| - }
|
| +WebInspector.ElementsTreeOutline.Renderer = class {
|
| + /**
|
| + * @override
|
| + * @param {!Object} object
|
| + * @return {!Promise.<!Element>}
|
| + */
|
| + render(object) {
|
| + return new Promise(renderPromise);
|
| +
|
| + /**
|
| + * @param {function(!Element)} resolve
|
| + * @param {function(!Error)} reject
|
| + */
|
| + function renderPromise(resolve, reject) {
|
| + if (object instanceof WebInspector.DOMNode) {
|
| + onNodeResolved(/** @type {!WebInspector.DOMNode} */ (object));
|
| + } else if (object instanceof WebInspector.DeferredDOMNode) {
|
| + (/** @type {!WebInspector.DeferredDOMNode} */ (object)).resolve(onNodeResolved);
|
| + } else if (object instanceof WebInspector.RemoteObject) {
|
| + var domModel = WebInspector.DOMModel.fromTarget((/** @type {!WebInspector.RemoteObject} */ (object)).target());
|
| + if (domModel)
|
| + domModel.pushObjectAsNodeToFrontend(object, onNodeResolved);
|
| + else
|
| + reject(new Error('No dom model for given JS object target found.'));
|
| + } else {
|
| + reject(new Error('Can\'t reveal not a node.'));
|
| + }
|
| +
|
| + /**
|
| + * @param {?WebInspector.DOMNode} node
|
| + */
|
| + function onNodeResolved(node) {
|
| + if (!node) {
|
| + reject(new Error('Could not resolve node.'));
|
| + return;
|
| }
|
| + var treeOutline = new WebInspector.ElementsTreeOutline(node.domModel(), false, false);
|
| + treeOutline.rootDOMNode = node;
|
| + if (!treeOutline.firstChild().isExpandable())
|
| + treeOutline._element.classList.add('single-node');
|
| + treeOutline.setVisible(true);
|
| + treeOutline.element.treeElementForTest = treeOutline.firstChild();
|
| + resolve(treeOutline.element);
|
| + }
|
| }
|
| + }
|
| };
|
|
|
| /**
|
| - * @constructor
|
| - * @extends {TreeElement}
|
| - * @param {!WebInspector.DOMNodeShortcut} nodeShortcut
|
| + * @unrestricted
|
| */
|
| -WebInspector.ElementsTreeOutline.ShortcutTreeElement = function(nodeShortcut)
|
| -{
|
| - TreeElement.call(this, "");
|
| - this.listItemElement.createChild("div", "selection fill");
|
| - var title = this.listItemElement.createChild("span", "elements-tree-shortcut-title");
|
| +WebInspector.ElementsTreeOutline.ShortcutTreeElement = class extends TreeElement {
|
| + /**
|
| + * @param {!WebInspector.DOMNodeShortcut} nodeShortcut
|
| + */
|
| + constructor(nodeShortcut) {
|
| + super('');
|
| + this.listItemElement.createChild('div', 'selection fill');
|
| + var title = this.listItemElement.createChild('span', 'elements-tree-shortcut-title');
|
| var text = nodeShortcut.nodeName.toLowerCase();
|
| if (nodeShortcut.nodeType === Node.ELEMENT_NODE)
|
| - text = "<" + text + ">";
|
| - title.textContent = "\u21AA " + text;
|
| + text = '<' + text + '>';
|
| + title.textContent = '\u21AA ' + text;
|
|
|
| var link = WebInspector.DOMPresentationUtils.linkifyDeferredNodeReference(nodeShortcut.deferredNode);
|
| - this.listItemElement.createTextChild(" ");
|
| - link.classList.add("elements-tree-shortcut-link");
|
| - link.textContent = WebInspector.UIString("reveal");
|
| + this.listItemElement.createTextChild(' ');
|
| + link.classList.add('elements-tree-shortcut-link');
|
| + link.textContent = WebInspector.UIString('reveal');
|
| this.listItemElement.appendChild(link);
|
| this._nodeShortcut = nodeShortcut;
|
| -};
|
| -
|
| -WebInspector.ElementsTreeOutline.ShortcutTreeElement.prototype = {
|
| + }
|
| +
|
| + /**
|
| + * @return {boolean}
|
| + */
|
| + get hovered() {
|
| + return this._hovered;
|
| + }
|
| +
|
| + /**
|
| + * @param {boolean} x
|
| + */
|
| + set hovered(x) {
|
| + if (this._hovered === x)
|
| + return;
|
| + this._hovered = x;
|
| + this.listItemElement.classList.toggle('hovered', x);
|
| + }
|
| +
|
| + /**
|
| + * @return {number}
|
| + */
|
| + backendNodeId() {
|
| + return this._nodeShortcut.deferredNode.backendNodeId();
|
| + }
|
| +
|
| + /**
|
| + * @override
|
| + * @param {boolean=} selectedByUser
|
| + * @return {boolean}
|
| + */
|
| + onselect(selectedByUser) {
|
| + if (!selectedByUser)
|
| + return true;
|
| + this._nodeShortcut.deferredNode.highlight();
|
| + this._nodeShortcut.deferredNode.resolve(resolved.bind(this));
|
| /**
|
| - * @return {boolean}
|
| - */
|
| - get hovered()
|
| - {
|
| - return this._hovered;
|
| - },
|
| -
|
| - set hovered(x)
|
| - {
|
| - if (this._hovered === x)
|
| - return;
|
| - this._hovered = x;
|
| - this.listItemElement.classList.toggle("hovered", x);
|
| - },
|
| -
|
| - /**
|
| - * @return {number}
|
| - */
|
| - backendNodeId: function()
|
| - {
|
| - return this._nodeShortcut.deferredNode.backendNodeId();
|
| - },
|
| -
|
| - /**
|
| - * @override
|
| - * @param {boolean=} selectedByUser
|
| - * @return {boolean}
|
| + * @param {?WebInspector.DOMNode} node
|
| + * @this {WebInspector.ElementsTreeOutline.ShortcutTreeElement}
|
| */
|
| - onselect: function(selectedByUser)
|
| - {
|
| - if (!selectedByUser)
|
| - return true;
|
| - this._nodeShortcut.deferredNode.highlight();
|
| - this._nodeShortcut.deferredNode.resolve(resolved.bind(this));
|
| - /**
|
| - * @param {?WebInspector.DOMNode} node
|
| - * @this {WebInspector.ElementsTreeOutline.ShortcutTreeElement}
|
| - */
|
| - function resolved(node)
|
| - {
|
| - if (node) {
|
| - this.treeOutline._selectedDOMNode = node;
|
| - this.treeOutline._selectedNodeChanged();
|
| - }
|
| - }
|
| - return true;
|
| - },
|
| -
|
| - __proto__: TreeElement.prototype
|
| + function resolved(node) {
|
| + if (node) {
|
| + this.treeOutline._selectedDOMNode = node;
|
| + this.treeOutline._selectedNodeChanged();
|
| + }
|
| + }
|
| + return true;
|
| + }
|
| };
|
|
|