/*
 * Copyright (C) 2007, 2008, 2013, 2015, 2016 Apple Inc.  All rights reserved.
 * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
 * Copyright (C) 2009 Joseph Pecoraro
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

WI.DOMTreeElement = class DOMTreeElement extends WI.TreeElement
{
    constructor(node, elementCloseTag)
    {
        super("", node);

        this._elementCloseTag = elementCloseTag;
        this.hasChildren = !elementCloseTag && this._hasVisibleChildren();

        if (this.representedObject.nodeType() === Node.ELEMENT_NODE && !elementCloseTag)
            this._canAddAttributes = true;
        this._searchQuery = null;
        this._expandedChildrenLimit = WI.DOMTreeElement.InitialChildrenLimit;
        this._breakpointStatus = WI.DOMTreeElement.BreakpointStatus.None;
        this._animatingHighlight = false;
        this._shouldHighlightAfterReveal = false;
        this._boundHighlightAnimationEnd = this._highlightAnimationEnd.bind(this);
        this._subtreeBreakpointTreeElements = null;

        this._showGoToArrow = false;
        this._highlightedAttributes = new Set;
        this._recentlyModifiedAttributes = new Map;
        this._closeTagTreeElement = null;

        node.addEventListener(WI.DOMNode.Event.EnabledPseudoClassesChanged, this._updatePseudoClassIndicator, this);

        this._ignoreSingleTextChild = false;
        this._forceUpdateTitle = false;
    }

    // Static

    static shadowRootTypeDisplayName(type)
    {
        switch (type) {
        case WI.DOMNode.ShadowRootType.UserAgent:
            return WI.UIString("User Agent");
        case WI.DOMNode.ShadowRootType.Open:
            return WI.UIString("Open");
        case WI.DOMNode.ShadowRootType.Closed:
            return WI.UIString("Closed");
        }
    }

    // Public

    get hasBreakpoint()
    {
        return this._breakpointStatus !== WI.DOMTreeElement.BreakpointStatus.None || (this._subtreeBreakpointTreeElements && this._subtreeBreakpointTreeElements.size);
    }

    get breakpointStatus()
    {
        return this._breakpointStatus;
    }

    set breakpointStatus(status)
    {
        if (this._breakpointStatus === status)
            return;

        let increment;
        if (this._breakpointStatus === WI.DOMTreeElement.BreakpointStatus.None)
            increment = 1;
        else if (status === WI.DOMTreeElement.BreakpointStatus.None)
            increment = -1;

        this._breakpointStatus = status;
        this._updateBreakpointStatus();

        if (!increment)
            return;

        let parentElement = this.parent;
        while (parentElement && !parentElement.root) {
            parentElement._subtreeBreakpointChanged(this);
            parentElement = parentElement.parent;
        }
    }

    bindRevealDescendantBreakpointsMenuItemHandler()
    {
        if (!this._subtreeBreakpointTreeElements || !this._subtreeBreakpointTreeElements.size)
            return null;

        let subtreeBreakpointTreeElements = Array.from(this._subtreeBreakpointTreeElements);
        return () => {
            for (let subtreeBreakpointTreeElement of subtreeBreakpointTreeElements)
                subtreeBreakpointTreeElement.reveal();
        };
    }

    get closeTagTreeElement() { return this._closeTagTreeElement; }

    revealAndHighlight()
    {
        if (this._animatingHighlight)
            return;

        this._shouldHighlightAfterReveal = true;
        this.reveal();
    }

    isCloseTag()
    {
        return this._elementCloseTag;
    }

    highlightSearchResults(searchQuery)
    {
        if (this._searchQuery !== searchQuery) {
            this._updateSearchHighlight(false);
            this._highlightResult = undefined; // A new search query.
        }

        this._searchQuery = searchQuery;
        this._searchHighlightsVisible = true;
        this.updateTitle(true);
    }

    hideSearchHighlights()
    {
        this._searchHighlightsVisible = false;
        this._updateSearchHighlight(false);
    }

    emphasizeSearchHighlight()
    {
        var highlightElement = this.title.querySelector("." + WI.DOMTreeElement.SearchHighlightStyleClassName);
        console.assert(highlightElement);
        if (!highlightElement)
            return;

        if (this._bouncyHighlightElement)
            this._bouncyHighlightElement.remove();

        this._bouncyHighlightElement = document.createElement("div");
        this._bouncyHighlightElement.className = WI.DOMTreeElement.BouncyHighlightStyleClassName;
        this._bouncyHighlightElement.textContent = highlightElement.textContent;

        // Position and show the bouncy highlight adjusting the coordinates to be inside the TreeOutline's space.
        var highlightElementRect = highlightElement.getBoundingClientRect();
        var treeOutlineRect = this.treeOutline.element.getBoundingClientRect();
        this._bouncyHighlightElement.style.top = (highlightElementRect.top - treeOutlineRect.top) + "px";
        this._bouncyHighlightElement.style.left = (highlightElementRect.left - treeOutlineRect.left) + "px";
        this.title.appendChild(this._bouncyHighlightElement);

        function animationEnded()
        {
            if (!this._bouncyHighlightElement)
                return;

            this._bouncyHighlightElement.remove();
            this._bouncyHighlightElement = null;
        }

        this._bouncyHighlightElement.addEventListener("animationend", animationEnded.bind(this));
    }

    _updateSearchHighlight(show)
    {
        if (!this._highlightResult)
            return;

        function updateEntryShow(entry)
        {
            switch (entry.type) {
                case "added":
                    entry.parent.insertBefore(entry.node, entry.nextSibling);
                    break;
                case "changed":
                    entry.node.textContent = entry.newText;
                    break;
            }
        }

        function updateEntryHide(entry)
        {
            switch (entry.type) {
                case "added":
                    entry.node.remove();
                    break;
                case "changed":
                    entry.node.textContent = entry.oldText;
                    break;
            }
        }

        var updater = show ? updateEntryShow : updateEntryHide;

        for (var i = 0, size = this._highlightResult.length; i < size; ++i)
            updater(this._highlightResult[i]);
    }

    get hovered()
    {
        return this._hovered;
    }

    set hovered(value)
    {
        if (this._hovered === value)
            return;

        this._hovered = value;

        if (this.listItemElement) {
            this.listItemElement.classList.toggle("hovered", this._hovered);
            this.updateSelectionArea();
        }
    }

    get editable()
    {
        let node = this.representedObject;

        if (node.destroyed)
            return false;

        if (node.isShadowRoot())
            return false;

        if (node.isInUserAgentShadowTree() && !WI.DOMManager.supportsEditingUserAgentShadowTrees())
            return false;

        if (node.isPseudoElement())
            return false;

        return this.treeOutline.editable;
    }

    get expandedChildrenLimit()
    {
        return this._expandedChildrenLimit;
    }

    set expandedChildrenLimit(x)
    {
        if (this._expandedChildrenLimit === x)
            return;

        this._expandedChildrenLimit = x;
        if (this.treeOutline && !this._updateChildrenInProgress)
            this._updateChildren(true);
    }

    get expandedChildCount()
    {
        var count = this.children.length;
        if (count && this.children[count - 1]._elementCloseTag)
            count--;
        if (count && this.children[count - 1].expandAllButton)
            count--;
        return count;
    }

    set showGoToArrow(x)
    {
        if (this._showGoToArrow === x)
            return;

        this._showGoToArrow = x;

        this.updateTitle();
    }

    attributeDidChange(name)
    {
        if (this._recentlyModifiedAttributes.has(name))
            return;

        this._recentlyModifiedAttributes.set(name, {
            value: null,
            timestamp: NaN,
            element: null,
            listener: null,
        });
    }

    highlightAttribute(name)
    {
        this._highlightedAttributes.add(name);
    }

    showChildNode(node)
    {
        console.assert(!this._elementCloseTag);
        if (this._elementCloseTag)
            return null;

        var index = this._visibleChildren().indexOf(node);
        if (index === -1)
            return null;

        if (index >= this.expandedChildrenLimit) {
            this._expandedChildrenLimit = index + 1;
            this._updateChildren(true);
        }

        return this.children[index];
    }

    toggleElementVisibility(forceHidden)
    {
        let effectiveNode = this.representedObject;
        if (effectiveNode.isPseudoElement()) {
            effectiveNode = effectiveNode.parentNode;
            console.assert(effectiveNode);
            if (!effectiveNode)
                return;
        }

        if (effectiveNode.nodeType() !== Node.ELEMENT_NODE)
            return;

        function inspectedPage_node_injectStyleAndToggleClass(hiddenClassName, force) {
            let root = this.getRootNode() || document;

            let styleElement = root.getElementById(hiddenClassName);
            if (!styleElement) {
                styleElement = document.createElement("style");
                styleElement.id = hiddenClassName;
                styleElement.textContent = `.${hiddenClassName} { visibility: hidden !important; }`;

                if (root instanceof HTMLDocument)
                    root.head.appendChild(styleElement);
                else // Inside Shadow DOM.
                    root.insertBefore(styleElement, root.firstChild);
            }

            this.classList.toggle(hiddenClassName, force);
        }

        WI.RemoteObject.resolveNode(effectiveNode).then((object) => {
            object.callFunction(inspectedPage_node_injectStyleAndToggleClass, [WI.DOMTreeElement.HideElementStyleSheetIdOrClassName, forceHidden], false);
            object.release();
        });
    }

    _createTooltipForNode()
    {
        var node = this.representedObject;
        if (!node.nodeName() || node.nodeName().toLowerCase() !== "img")
            return;

        function setTooltip(error, result, wasThrown)
        {
            if (error || wasThrown || !result || result.type !== "string")
                return;

            try {
                var properties = JSON.parse(result.description);
                var offsetWidth = properties[0];
                var offsetHeight = properties[1];
                var naturalWidth = properties[2];
                var naturalHeight = properties[3];
                if (offsetHeight === naturalHeight && offsetWidth === naturalWidth)
                    this.tooltip = WI.UIString("%d \xd7 %d pixels").format(offsetWidth, offsetHeight);
                else
                    this.tooltip = WI.UIString("%d \xd7 %d pixels (Natural: %d \xd7 %d pixels)").format(offsetWidth, offsetHeight, naturalWidth, naturalHeight);
            } catch (e) {
                console.error(e);
            }
        }

        WI.RemoteObject.resolveNode(node).then((object) => {
            function inspectedPage_node_dimensions() {
                return "[" + this.offsetWidth + "," + this.offsetHeight + "," + this.naturalWidth + "," + this.naturalHeight + "]";
            }

            object.callFunction(inspectedPage_node_dimensions, undefined, false, setTooltip.bind(this));
            object.release();
        });
    }

    updateSelectionArea()
    {
        let listItemElement = this.listItemElement;
        if (!listItemElement)
            return;

        // If there's no reason to have a selection area, remove the DOM element.
        let indicatesTreeOutlineState = this.treeOutline && (this.treeOutline.dragOverTreeElement === this || this.selected || this._animatingHighlight);
        if (!this.hovered && !indicatesTreeOutlineState) {
            if (this._selectionElement) {
                this._selectionElement.remove();
                this._selectionElement = null;
            }

            return;
        }

        if (!this._selectionElement) {
            this._selectionElement = document.createElement("div");
            this._selectionElement.className = "selection-area";
            listItemElement.insertBefore(this._selectionElement, listItemElement.firstChild);
        }

        this._selectionElement.style.height = listItemElement.offsetHeight + "px";
    }

    onattach()
    {
        if (this.hovered)
            this.listItemElement.classList.add("hovered");

        this.updateTitle();

        if (this.editable) {
            this.listItemElement.draggable = true;
            this.listItemElement.addEventListener("dragstart", this);
        }
    }

    onpopulate()
    {
        if (this.children.length || !this._hasVisibleChildren() || this._elementCloseTag)
            return;

        this.updateChildren();
    }

    expandRecursively()
    {
        this.representedObject.getSubtree(-1, super.expandRecursively.bind(this, Number.MAX_VALUE));
    }

    updateChildren(fullRefresh)
    {
        if (this._elementCloseTag)
            return;

        this.representedObject.getChildNodes(this._updateChildren.bind(this, fullRefresh));
    }

    insertChildElement(child, index, closingTag)
    {
        var newElement = new WI.DOMTreeElement(child, closingTag);
        newElement.selectable = this.treeOutline.selectable;
        this.insertChild(newElement, index);
        return newElement;
    }

    moveChild(child, targetIndex)
    {
        // No move needed if the child is already in the right place.
        if (this.children[targetIndex] === child)
            return;

        var originalSelectedChild = this.treeOutline.selectedTreeElement;

        this.removeChild(child);
        this.insertChild(child, targetIndex);

        if (originalSelectedChild !== this.treeOutline.selectedTreeElement)
            originalSelectedChild.select();
    }

    _updateChildren(fullRefresh)
    {
        if (this._updateChildrenInProgress || !this.treeOutline._visible)
            return;

        this._closeTagTreeElement = null;
        this._updateChildrenInProgress = true;

        var node = this.representedObject;
        var selectedNode = this.treeOutline.selectedDOMNode();
        var originalScrollTop = 0;

        var hasVisibleChildren = this._hasVisibleChildren();

        if (fullRefresh || !hasVisibleChildren) {
            var treeOutlineContainerElement = this.treeOutline.element.parentNode;
            originalScrollTop = treeOutlineContainerElement.scrollTop;
            var selectedTreeElement = this.treeOutline.selectedTreeElement;
            if (selectedTreeElement && selectedTreeElement.hasAncestor(this))
                this.select();
            this.removeChildren();

            // No longer have children.
            if (!hasVisibleChildren) {
                this.hasChildren = false;
                this.updateTitle();
                this._updateChildrenInProgress = false;
                return;
            }
        }

        // We now have children.
        if (!this.hasChildren) {
            this.hasChildren = true;
            this.updateTitle();
        }

        // Remove any tree elements that no longer have this node (or this node's contentDocument) as their parent.
        // Keep a list of existing tree elements for nodes that we can use later.
        var existingChildTreeElements = new Map;
        for (var i = this.children.length - 1; i >= 0; --i) {
            var currentChildTreeElement = this.children[i];
            var currentNode = currentChildTreeElement.representedObject;
            var currentParentNode = currentNode.parentNode;
            if (currentParentNode === node) {
                existingChildTreeElements.set(currentNode, currentChildTreeElement);
                continue;
            }

            this.removeChildAtIndex(i);
        }

        // Move / create TreeElements for our visible children.
        var elementToSelect = null;
        var visibleChildren = this._visibleChildren();
        for (var i = 0; i < visibleChildren.length && i < this.expandedChildrenLimit; ++i) {
            var childNode = visibleChildren[i];

            // Already have a tree element for this child, just move it.
            var existingChildTreeElement = existingChildTreeElements.get(childNode);
            if (existingChildTreeElement) {
                this.moveChild(existingChildTreeElement, i);
                continue;
            }

            // No existing tree element for this child. Insert a new element.
            var newChildTreeElement = this.insertChildElement(childNode, i);

            // Update state.
            if (childNode === selectedNode)
                elementToSelect = newChildTreeElement;
            if (this.expandedChildCount > this.expandedChildrenLimit)
                this.expandedChildrenLimit++;
        }

        // Update expand all children button.
        this.adjustCollapsedRange();

        // Insert closing tag tree element.
        var lastChild = this.children.lastValue;
        if (node.nodeType() === Node.ELEMENT_NODE && (!lastChild || !lastChild._elementCloseTag))
            this._closeTagTreeElement = this.insertChildElement(this.representedObject, this.children.length, true);

        // We want to restore the original selection and tree scroll position after a full refresh, if possible.
        if (fullRefresh && elementToSelect) {
            elementToSelect.select();
            if (treeOutlineContainerElement && originalScrollTop <= treeOutlineContainerElement.scrollHeight)
                treeOutlineContainerElement.scrollTop = originalScrollTop;
        }

        this._updateChildrenInProgress = false;
    }

    adjustCollapsedRange()
    {
        // Ensure precondition: only the tree elements for node children are found in the tree
        // (not the Expand All button or the closing tag).
        if (this.expandAllButtonElement && this.expandAllButtonElement.__treeElement.parent)
            this.removeChild(this.expandAllButtonElement.__treeElement);

        if (!this._hasVisibleChildren())
            return;

        var visibleChildren = this._visibleChildren();
        var totalChildrenCount = visibleChildren.length;

        // In case some nodes from the expanded range were removed, pull some nodes from the collapsed range into the expanded range at the bottom.
        for (var i = this.expandedChildCount, limit = Math.min(this.expandedChildrenLimit, totalChildrenCount); i < limit; ++i)
            this.insertChildElement(visibleChildren[i], i);

        var expandedChildCount = this.expandedChildCount;
        if (totalChildrenCount > this.expandedChildCount) {
            var targetButtonIndex = expandedChildCount;
            if (!this.expandAllButtonElement) {
                var button = document.createElement("button");
                button.className = "show-all-nodes";
                button.value = "";

                var item = new WI.TreeElement(button, null, false);
                item.selectable = false;
                item.expandAllButton = true;

                this.insertChild(item, targetButtonIndex);
                this.expandAllButtonElement = button;
                this.expandAllButtonElement.__treeElement = item;
                this.expandAllButtonElement.addEventListener("click", this.handleLoadAllChildren.bind(this), false);
            } else if (!this.expandAllButtonElement.__treeElement.parent)
                this.insertChild(this.expandAllButtonElement.__treeElement, targetButtonIndex);

            this.expandAllButtonElement.textContent = WI.UIString("Show All Nodes (%d More)").format(totalChildrenCount - expandedChildCount);
        } else if (this.expandAllButtonElement)
            this.expandAllButtonElement = null;
    }

    handleLoadAllChildren()
    {
        var visibleChildren = this._visibleChildren();
        this.expandedChildrenLimit = Math.max(visibleChildren.length, this.expandedChildrenLimit + WI.DOMTreeElement.InitialChildrenLimit);
    }

    onexpand()
    {
        if (this._elementCloseTag)
            return;

        if (!this.listItemElement)
            return;

        this.updateTitle();

        for (let treeElement of this.children)
            treeElement.updateSelectionArea();
    }

    oncollapse()
    {
        if (this._elementCloseTag)
            return;

        this.updateTitle();
    }

    onreveal()
    {
        let listItemElement = this.listItemElement;
        if (!listItemElement)
            return;

        let tagSpans = listItemElement.getElementsByClassName("html-tag-name");
        if (tagSpans.length)
            tagSpans[0].scrollIntoViewIfNeeded(false);
        else
            listItemElement.scrollIntoViewIfNeeded(false);

        if (!this._shouldHighlightAfterReveal)
            return;

        this._shouldHighlightAfterReveal = false;
        this._animatingHighlight = true;

        this.updateSelectionArea();

        listItemElement.addEventListener("animationend", this._boundHighlightAnimationEnd);
        listItemElement.classList.add(WI.DOMTreeElement.HighlightStyleClassName);
    }

    onenter()
    {
        if (!this.editable)
            return false;

        // On Enter or Return start editing the first attribute
        // or create a new attribute on the selected element.
        if (this.treeOutline.editing)
            return false;

        this._startEditing();

        // prevent a newline from being immediately inserted
        return true;
    }

    canSelectOnMouseDown(event)
    {
        if (this._editing)
            return false;

        // Prevent selecting the nearest word on double click.
        if (event.detail >= 2) {
            event.preventDefault();
            return false;
        }

        return true;
    }

    ondblclick(event)
    {
        if (!this.editable)
            return false;

        if (this._editing || this._elementCloseTag)
            return;

        if (this._startEditingTarget(event.target))
            return;

        if (this.hasChildren && !this.expanded)
            this.expand();
    }

    _insertInLastAttributePosition(tag, node)
    {
        if (tag.getElementsByClassName("html-attribute").length > 0)
            tag.insertBefore(node, tag.lastChild);
        else {
            var nodeName = tag.textContent.match(/^<(.*?)>$/)[1];
            tag.textContent = "";
            tag.append("<" + nodeName, node, ">");
        }

        this.updateSelectionArea();
    }

    _startEditingTarget(eventTarget)
    {
        if (this.treeOutline.selectedDOMNode() !== this.representedObject)
            return false;

        if (this.representedObject.isShadowRoot())
            return false;

        if (this.representedObject.isInUserAgentShadowTree() && !WI.DOMManager.supportsEditingUserAgentShadowTrees())
            return false;

        if (this.representedObject.isPseudoElement())
            return false;

        if (this.representedObject.nodeType() !== Node.ELEMENT_NODE && this.representedObject.nodeType() !== Node.TEXT_NODE)
            return false;

        var textNode = eventTarget.closest(".html-text-node");
        if (textNode)
            return this._startEditingTextNode(textNode);

        var attribute = eventTarget.closest(".html-attribute");
        if (attribute)
            return this._startEditingAttribute(attribute, eventTarget);

        var tagName = eventTarget.closest(".html-tag-name");
        if (tagName)
            return this._startEditingTagName(tagName);

        return false;
    }

    populateDOMNodeContextMenu(contextMenu, subMenus, event)
    {
        let attributeNode = event.target.closest(".html-attribute");
        let textNode = event.target.closest(".html-text-node");

        let attributeName = null;
        if (attributeNode) {
            let attributeNameElement = attributeNode.getElementsByClassName("html-attribute-name")[0];
            if (attributeNameElement)
                attributeName = attributeNameElement.textContent.trim();
        }

        if (event.target && event.target.tagName === "A")
            WI.appendContextMenuItemsForURL(contextMenu, event.target.href, {frame: this.representedObject.frame});

        contextMenu.appendSeparator();

        let isEditableNode = this.representedObject.nodeType() === Node.ELEMENT_NODE && this.editable;
        let isNonShadowEditable = isEditableNode && (!this.representedObject.isInUserAgentShadowTree() || WI.DOMManager.supportsEditingUserAgentShadowTrees());
        let alreadyEditingHTML = this._htmlEditElement && WI.isBeingEdited(this._htmlEditElement);

        if (isEditableNode) {
            if (!DOMTreeElement.ForbiddenClosingTagElements.has(this.representedObject.nodeNameInCorrectCase())) {
                subMenus.add.appendItem(WI.UIString("Child", "A submenu item of 'Add' to append DOM nodes to the selected DOM node"), () => {
                    this._addHTML();
                }, alreadyEditingHTML);
            }

            subMenus.add.appendItem(WI.UIString("Previous Sibling", "A submenu item of 'Add' to add DOM nodes before the selected DOM node"), () => {
                this._addPreviousSibling();
            }, alreadyEditingHTML);

            subMenus.add.appendItem(WI.UIString("Next Sibling", "A submenu item of 'Add' to add DOM nodes after the selected DOM node"), () => {
                this._addNextSibling();
            }, alreadyEditingHTML);
        }

        if (isNonShadowEditable) {
            subMenus.add.appendItem(WI.UIString("Attribute"), () => {
                this._addNewAttribute();
            });
        }

        if (this.editable) {
            subMenus.edit.appendItem(WI.UIString("HTML"), () => {
                this._editAsHTML();
            }, alreadyEditingHTML);
        }

        if (isNonShadowEditable) {
            if (attributeName) {
                subMenus.edit.appendItem(WI.UIString("Attribute"), () => {
                    this._startEditingAttribute(attributeNode, event.target);
                }, WI.isBeingEdited(attributeNode));
            }

            if (!DOMTreeElement.EditTagBlacklist.has(this.representedObject.nodeNameInCorrectCase())) {
                let tagNameNode = event.target.closest(".html-tag-name");

                subMenus.edit.appendItem(WI.UIString("Tag", "A submenu item of 'Edit' to change DOM element's tag name"), () => {
                    this._startEditingTagName(tagNameNode);
                }, WI.isBeingEdited(tagNameNode));
            }
        }

        if (textNode && this.editable) {
            subMenus.edit.appendItem(WI.UIString("Text"), () => {
                this._startEditingTextNode(textNode);
            }, WI.isBeingEdited(textNode));
        }

        if (!this.representedObject.destroyed && !this.representedObject.isPseudoElement()) {
            subMenus.copy.appendItem(WI.UIString("HTML"), () => {
                this.representedObject.getOuterHTML()
                .then((outerHTML) => {
                    InspectorFrontendHost.copyText(outerHTML);
                });
            });
        }

        if (attributeName) {
            subMenus.copy.appendItem(WI.UIString("Attribute"), () => {
                let text = attributeName;
                let attributeValue = this.representedObject.getAttribute(attributeName);
                if (attributeValue)
                    text += "=\"" + attributeValue.replace(/"/g, "\\\"") + "\"";
                InspectorFrontendHost.copyText(text);
            });
        }

        if (textNode && textNode.textContent.length) {
            subMenus.copy.appendItem(WI.UIString("Text"), () => {
                InspectorFrontendHost.copyText(textNode.textContent);
            });
        }

        if (this.editable && (!this.selected || this.treeOutline.selectedTreeElements.length === 1)) {
            subMenus.delete.appendItem(WI.UIString("Node"), () => {
                this.remove();
            });
        }

        if (attributeName && isNonShadowEditable) {
            subMenus.delete.appendItem(WI.UIString("Attribute"), () => {
                this.representedObject.removeAttribute(attributeName);
            });
        }

        for (let subMenu of Object.values(subMenus))
            contextMenu.pushItem(subMenu);

        if (this.treeOutline.editable) {
            if (this.selected && this.treeOutline && this.treeOutline.selectedTreeElements.length > 1) {
                let forceHidden = !this.treeOutline.selectedTreeElements.every((treeElement) => treeElement.isNodeHidden);
                let label = forceHidden ? WI.UIString("Hide Elements") : WI.UIString("Show Elements");
                contextMenu.appendItem(label, () => {
                    this.treeOutline.toggleSelectedElementsVisibility(forceHidden);
                });
            } else if (isEditableNode) {
                contextMenu.appendItem(WI.UIString("Toggle Visibility"), () => {
                    this.toggleElementVisibility();
                });
            }
        }
    }

    _startEditing()
    {
        if (this.treeOutline.selectedDOMNode() !== this.representedObject)
            return false;

        if (!this.editable)
            return false;

        var listItem = this.listItemElement;

        if (this._canAddAttributes) {
            var attribute = listItem.getElementsByClassName("html-attribute")[0];
            if (attribute)
                return this._startEditingAttribute(attribute, attribute.getElementsByClassName("html-attribute-value")[0]);

            return this._addNewAttribute();
        }

        if (this.representedObject.nodeType() === Node.TEXT_NODE) {
            var textNode = listItem.getElementsByClassName("html-text-node")[0];
            if (textNode)
                return this._startEditingTextNode(textNode);
            return false;
        }
    }

    _addNewAttribute()
    {
        // Cannot just convert the textual html into an element without
        // a parent node. Use a temporary span container for the HTML.
        var container = document.createElement("span");
        this._buildAttributeDOM(container, " ", "");
        var attr = container.firstChild;
        attr.style.marginLeft = "2px"; // overrides the .editing margin rule
        attr.style.marginRight = "2px"; // overrides the .editing margin rule

        var tag = this.listItemElement.getElementsByClassName("html-tag")[0];
        this._insertInLastAttributePosition(tag, attr);
        return this._startEditingAttribute(attr, attr);
    }

    _triggerEditAttribute(attributeName)
    {
        var attributeElements = this.listItemElement.getElementsByClassName("html-attribute-name");
        for (var i = 0, len = attributeElements.length; i < len; ++i) {
            if (attributeElements[i].textContent === attributeName) {
                for (var elem = attributeElements[i].nextSibling; elem; elem = elem.nextSibling) {
                    if (elem.nodeType !== Node.ELEMENT_NODE)
                        continue;

                    if (elem.classList.contains("html-attribute-value"))
                        return this._startEditingAttribute(elem.parentNode, elem);
                }
            }
        }
    }

    _startEditingAttribute(attribute, elementForSelection)
    {
        if (WI.isBeingEdited(attribute))
            return true;

        var attributeNameElement = attribute.getElementsByClassName("html-attribute-name")[0];
        if (!attributeNameElement)
            return false;

        var attributeName = attributeNameElement.textContent;

        function removeZeroWidthSpaceRecursive(node)
        {
            if (node.nodeType === Node.TEXT_NODE) {
                node.nodeValue = node.nodeValue.replace(/\u200B/g, "");
                return;
            }

            if (node.nodeType !== Node.ELEMENT_NODE)
                return;

            for (var child = node.firstChild; child; child = child.nextSibling)
                removeZeroWidthSpaceRecursive(child);
        }

        // Remove zero-width spaces that were added by nodeTitleInfo.
        removeZeroWidthSpaceRecursive(attribute);

        var config = new WI.EditingConfig(this._attributeEditingCommitted.bind(this), this._editingCancelled.bind(this), attributeName);
        config.setNumberCommitHandler(this._attributeNumberEditingCommitted.bind(this));
        this._editing = WI.startEditing(attribute, config);

        window.getSelection().setBaseAndExtent(elementForSelection, 0, elementForSelection, 1);

        return true;
    }

    _startEditingTextNode(textNode)
    {
        if (WI.isBeingEdited(textNode))
            return true;

        var config = new WI.EditingConfig(this._textNodeEditingCommitted.bind(this), this._editingCancelled.bind(this));
        config.spellcheck = true;
        this._editing = WI.startEditing(textNode, config);
        window.getSelection().setBaseAndExtent(textNode, 0, textNode, 1);

        return true;
    }

    _startEditingTagName(tagNameElement)
    {
        if (!tagNameElement) {
            tagNameElement = this.listItemElement.getElementsByClassName("html-tag-name")[0];
            if (!tagNameElement)
                return false;
        }

        var tagName = tagNameElement.textContent;
        if (WI.DOMTreeElement.EditTagBlacklist.has(tagName.toLowerCase()))
            return false;

        if (WI.isBeingEdited(tagNameElement))
            return true;

        let closingTagElement = this._distinctClosingTagElement();
        let originalClosingTagTextContent = closingTagElement ? closingTagElement.textContent : "";

        function keyupListener(event)
        {
            if (closingTagElement)
                closingTagElement.textContent = "</" + tagNameElement.textContent + ">";
        }

        function editingComitted(element, newTagName)
        {
            tagNameElement.removeEventListener("keyup", keyupListener, false);
            this._tagNameEditingCommitted.apply(this, arguments);
        }

        function editingCancelled()
        {
            if (closingTagElement)
                closingTagElement.textContent = originalClosingTagTextContent;

            tagNameElement.removeEventListener("keyup", keyupListener, false);
            this._editingCancelled.apply(this, arguments);
        }

        tagNameElement.addEventListener("keyup", keyupListener, false);

        var config = new WI.EditingConfig(editingComitted.bind(this), editingCancelled.bind(this), tagName);
        this._editing = WI.startEditing(tagNameElement, config);
        window.getSelection().setBaseAndExtent(tagNameElement, 0, tagNameElement, 1);
        return true;
    }

    _startEditingAsHTML(commitCallback, options = {})
    {
        if (this._htmlEditElement && WI.isBeingEdited(this._htmlEditElement))
            return;

        if (options.hideExistingElements) {
            let child = this.listItemElement.firstChild;
            while (child) {
                child.style.display = "none";
                child = child.nextSibling;
            }
            if (this._childrenListNode)
                this._childrenListNode.style.display = "none";
        }

        let positionInside = options.position === "afterbegin" || options.position === "beforeend";
        if (positionInside && this._childrenListNode) {
            this._htmlEditElement = document.createElement("li");

            let referenceNode = options.position === "afterbegin" ? this._childrenListNode.firstElementChild : this._childrenListNode.lastElementChild;
            this._childrenListNode.insertBefore(this._htmlEditElement, referenceNode);
        } else if (options.position && !positionInside) {
            this._htmlEditElement = document.createElement("li");

            let targetNode = (options.position === "afterend" && this._childrenListNode) ? this._childrenListNode : this.listItemElement;
            targetNode.insertAdjacentElement(options.position, this._htmlEditElement);
        } else {
            this._htmlEditElement = document.createElement("div");
            this.listItemElement.appendChild(this._htmlEditElement);
        }

        if (options.initialValue)
            this._htmlEditElement.textContent = options.initialValue;

        this.updateSelectionArea();

        function commit()
        {
            commitCallback(this._htmlEditElement.textContent);
            dispose.call(this);
        }

        function dispose()
        {
            this._editing = false;

            // Remove editor.
            this._htmlEditElement.remove();
            this._htmlEditElement = null;

            if (options.hideExistingElements) {
                if (this._childrenListNode)
                    this._childrenListNode.style.removeProperty("display");
                let child = this.listItemElement.firstChild;
                while (child) {
                    child.style.removeProperty("display");
                    child = child.nextSibling;
                }
            }

            this.updateSelectionArea();
        }

        var config = new WI.EditingConfig(commit.bind(this), dispose.bind(this));
        config.setMultiline(true);
        this._editing = WI.startEditing(this._htmlEditElement, config);

        if (options.initialValue && !isNaN(options.startPosition)) {
            let range = document.createRange();
            range.setStart(this._htmlEditElement.firstChild, options.startPosition);
            range.collapse(true);

            let selection = window.getSelection();
            selection.removeAllRanges();
            selection.addRange(range);
        }
    }

    _attributeEditingCommitted(element, newText, oldText, attributeName, moveDirection)
    {
        this._editing = false;

        if (!newText.trim())
            element.remove();

        if (!moveDirection && newText === oldText)
            return;

        // FIXME: Workaround for <https://webkit.org/b/123163> &nbsp; is forced on SPACE between text nodes.
        const nbspRegex = /\xA0/g;
        newText = newText.replace(nbspRegex, " ");

        var treeOutline = this.treeOutline;
        function moveToNextAttributeIfNeeded(error)
        {
            if (error)
                this._editingCancelled(element, attributeName);

            if (!moveDirection)
                return;

            treeOutline._updateModifiedNodes();

            // Search for the attribute's position, and then decide where to move to.
            var attributes = this.representedObject.attributes();
            for (var i = 0; i < attributes.length; ++i) {
                if (attributes[i].name !== attributeName)
                    continue;

                if (moveDirection === "backward") {
                    if (i === 0)
                        this._startEditingTagName();
                    else
                        this._triggerEditAttribute(attributes[i - 1].name);
                } else {
                    if (i === attributes.length - 1)
                        this._addNewAttribute();
                    else
                        this._triggerEditAttribute(attributes[i + 1].name);
                }
                return;
            }

            // Moving From the "New Attribute" position.
            if (moveDirection === "backward") {
                if (newText === " ") {
                    // Moving from "New Attribute" that was not edited
                    if (attributes.length)
                        this._triggerEditAttribute(attributes.lastValue.name);
                } else {
                    // Moving from "New Attribute" that holds new value
                    if (attributes.length > 1)
                        this._triggerEditAttribute(attributes[attributes.length - 2].name);
                }
            } else if (moveDirection === "forward") {
                if (!/^\s*$/.test(newText))
                    this._addNewAttribute();
                else
                    this._startEditingTagName();
            }
        }

        this.representedObject.setAttribute(attributeName, newText, moveToNextAttributeIfNeeded.bind(this));
    }

    _attributeNumberEditingCommitted(element, newText, oldText, attributeName, moveDirection)
    {
        if (newText === oldText)
            return;

        this.representedObject.setAttribute(attributeName, newText);
    }

    _tagNameEditingCommitted(element, newText, oldText, tagName, moveDirection)
    {
        this._editing = false;
        var self = this;

        function cancel()
        {
            var closingTagElement = self._distinctClosingTagElement();
            if (closingTagElement)
                closingTagElement.textContent = "</" + tagName + ">";

            self._editingCancelled(element, tagName);
            moveToNextAttributeIfNeeded.call(self);
        }

        function moveToNextAttributeIfNeeded()
        {
            if (moveDirection !== "forward") {
                this._addNewAttribute();
                return;
            }

            var attributes = this.representedObject.attributes();
            if (attributes.length > 0)
                this._triggerEditAttribute(attributes[0].name);
            else
                this._addNewAttribute();
        }

        newText = newText.trim();
        if (newText === oldText) {
            cancel();
            return;
        }

        var treeOutline = this.treeOutline;
        var wasExpanded = this.expanded;

        function changeTagNameCallback(error, nodeId)
        {
            if (error || !nodeId) {
                cancel();
                return;
            }

            var node = WI.domManager.nodeForId(nodeId);

            // Select it and expand if necessary. We force tree update so that it processes dom events and is up to date.
            treeOutline._updateModifiedNodes();
            treeOutline.selectDOMNode(node, true);

            var newTreeItem = treeOutline.findTreeElement(node);
            if (wasExpanded)
                newTreeItem.expand();

            moveToNextAttributeIfNeeded.call(newTreeItem);
        }

        this.representedObject.setNodeName(newText, changeTagNameCallback);
    }

    _textNodeEditingCommitted(element, newText)
    {
        this._editing = false;

        var textNode;
        if (this.representedObject.nodeType() === Node.ELEMENT_NODE) {
            // We only show text nodes inline in elements if the element only
            // has a single child, and that child is a text node.
            textNode = this.representedObject.firstChild;
        } else if (this.representedObject.nodeType() === Node.TEXT_NODE)
            textNode = this.representedObject;

        textNode.setNodeValue(newText, this.updateTitle.bind(this));
    }

    _editingCancelled(element, context)
    {
        this._editing = false;

        // Need to restore attributes structure.
        this.updateTitle();
    }

    _distinctClosingTagElement()
    {
        // FIXME: Improve the Tree Element / Outline Abstraction to prevent crawling the DOM

        // For an expanded element, it will be the last element with class "close"
        // in the child element list.
        if (this.expanded) {
            var closers = this._childrenListNode.querySelectorAll(".close");
            return closers[closers.length - 1];
        }

        // Remaining cases are single line non-expanded elements with a closing
        // tag, or HTML elements without a closing tag (such as <br>). Return
        // null in the case where there isn't a closing tag.
        var tags = this.listItemElement.getElementsByClassName("html-tag");
        return tags.length === 1 ? null : tags[tags.length - 1];
    }

    updateTitle(onlySearchQueryChanged)
    {
        // If we are editing, return early to prevent canceling the edit.
        // After editing is committed updateTitle will be called.
        if (this._editing && !this._forceUpdateTitle)
            return;

        if (onlySearchQueryChanged) {
            if (this._highlightResult)
                this._updateSearchHighlight(false);
        } else {
            this.title = document.createElement("span");
            this.title.appendChild(this._nodeTitleInfo().titleDOM);
            this._highlightResult = undefined;
        }

        // Setting this.title will implicitly remove all children. Clear the
        // selection element so that we properly recreate it if necessary.
        this._selectionElement = null;
        this.updateSelectionArea();
        this._highlightSearchResults();
        this._updatePseudoClassIndicator();
        this._updateBreakpointStatus();
    }

    _buildAttributeDOM(parentElement, name, value, node)
    {
        let hasText = value.length > 0;
        let attrSpanElement = parentElement.createChild("span", "html-attribute");
        let attrNameElement = attrSpanElement.createChild("span", "html-attribute-name");
        attrNameElement.textContent = name;
        let attrValueElement = null;
        if (hasText)
            attrSpanElement.append("=\u200B\"");

        if (name === "src" || /\bhref\b/.test(name)) {
            let baseURL = node.frame ? node.frame.url : null;
            let rewrittenURL = absoluteURL(value, baseURL);
            value = value.insertWordBreakCharacters();
            if (!rewrittenURL) {
                attrValueElement = attrSpanElement.createChild("span", "html-attribute-value");
                attrValueElement.textContent = value;
            } else {
                if (value.startsWith("data:"))
                    value = value.truncateMiddle(60);

                attrValueElement = document.createElement("a");
                attrValueElement.href = rewrittenURL;
                attrValueElement.textContent = value;
                attrSpanElement.appendChild(attrValueElement);
            }
        } else if (name === "srcset") {
            let baseURL = node.frame ? node.frame.url : null;
            attrValueElement = attrSpanElement.createChild("span", "html-attribute-value");

            // Leading whitespace.
            let groups = value.split(/\s*,\s*/);
            for (let i = 0; i < groups.length; ++i) {
                let string = groups[i].trim();
                let spaceIndex = string.search(/\s/);

                if (spaceIndex === -1) {
                    let linkText = string;
                    let rewrittenURL = absoluteURL(string, baseURL);
                    let linkElement = attrValueElement.appendChild(document.createElement("a"));
                    linkElement.href = rewrittenURL;
                    linkElement.textContent = linkText.insertWordBreakCharacters();
                } else {
                    let linkText = string.substring(0, spaceIndex);
                    let descriptorText = string.substring(spaceIndex).insertWordBreakCharacters();
                    let rewrittenURL = absoluteURL(linkText, baseURL);
                    let linkElement = attrValueElement.appendChild(document.createElement("a"));
                    linkElement.href = rewrittenURL;
                    linkElement.textContent = linkText.insertWordBreakCharacters();
                    let descriptorElement = attrValueElement.appendChild(document.createElement("span"));
                    descriptorElement.textContent = descriptorText;
                }

                if (i < groups.length - 1) {
                    let commaElement = attrValueElement.appendChild(document.createElement("span"));
                    commaElement.textContent = ", ";
                }
            }
        } else {
            value = value.insertWordBreakCharacters();
            attrValueElement = attrSpanElement.createChild("span", "html-attribute-value");
            attrValueElement.textContent = value;
        }

        if (hasText)
            attrSpanElement.append("\"");

        this._createModifiedAnimation(name, value, hasText ? attrValueElement : attrNameElement);

        if (this._highlightedAttributes.has(name))
            attrSpanElement.classList.add("highlight");
    }

    _buildTagDOM({parentElement, tagName, isClosingTag, isDistinctTreeElement, willRenderCloseTagInline})
    {
        var node = this.representedObject;
        var classes = ["html-tag"];
        if (isClosingTag && isDistinctTreeElement)
            classes.push("close");
        var tagElement = parentElement.createChild("span", classes.join(" "));
        tagElement.append("<");
        var tagNameElement = tagElement.createChild("span", isClosingTag ? "" : "html-tag-name");
        tagNameElement.textContent = (isClosingTag ? "/" : "") + tagName;
        if (!isClosingTag && node.hasAttributes()) {
            var attributes = node.attributes();
            for (var i = 0; i < attributes.length; ++i) {
                var attr = attributes[i];
                tagElement.append(" ");
                this._buildAttributeDOM(tagElement, attr.name, attr.value, node);
            }
        }
        tagElement.append(">");
        parentElement.append("\u200B");

        if (this._showGoToArrow && node.nodeType() === Node.ELEMENT_NODE && willRenderCloseTagInline === isClosingTag) {
            let goToArrowElement = parentElement.appendChild(WI.createGoToArrowButton());
            goToArrowElement.title = WI.UIString("Reveal in Elements Tab");
            goToArrowElement.addEventListener("click", (event) => {
                WI.domManager.inspectElement(this.representedObject.id, {
                    initiatorHint: WI.TabBrowser.TabNavigationInitiator.LinkClick,
                });
            });
        }
    }

    _nodeTitleInfo()
    {
        var node = this.representedObject;
        var info = {titleDOM: document.createDocumentFragment(), hasChildren: this.hasChildren};

        function trimedNodeValue()
        {
            // Trim empty lines from the beginning and extra space at the end since most style and script tags begin with a newline
            // and end with a newline and indentation for the end tag.
            return node.nodeValue().replace(/^[\n\r]*/, "").replace(/\s*$/, "");
        }

        switch (node.nodeType()) {
            case Node.DOCUMENT_FRAGMENT_NODE:
                var fragmentElement = info.titleDOM.createChild("span", "html-fragment");
                if (node.shadowRootType()) {
                    fragmentElement.textContent = WI.UIString("Shadow Content (%s)").format(WI.DOMTreeElement.shadowRootTypeDisplayName(node.shadowRootType()));
                    this.listItemElement.classList.add("shadow");
                } else if (node.parentNode && node.parentNode.templateContent() === node) {
                    fragmentElement.textContent = WI.UIString("Template Content");
                    this.listItemElement.classList.add("template");
                } else {
                    fragmentElement.textContent = WI.UIString("Document Fragment");
                    this.listItemElement.classList.add("fragment");
                }
                break;

            case Node.ATTRIBUTE_NODE:
                var value = node.value || "\u200B"; // Zero width space to force showing an empty value.
                this._buildAttributeDOM(info.titleDOM, node.name, value);
                break;

            case Node.ELEMENT_NODE:
                if (node.isPseudoElement()) {
                    var pseudoElement = info.titleDOM.createChild("span", "html-pseudo-element");
                    pseudoElement.textContent = "::" + node.pseudoType();
                    info.titleDOM.appendChild(document.createTextNode("\u200B"));
                    info.hasChildren = false;
                    break;
                }

                var tagName = node.nodeNameInCorrectCase();
                if (this._elementCloseTag) {
                    this._buildTagDOM({
                        parentElement: info.titleDOM,
                        tagName,
                        isClosingTag: true,
                        isDistinctTreeElement: true,
                        willRenderCloseTagInline: false,
                    });
                    info.hasChildren = false;
                    break;
                }

                var textChild = this._singleTextChild(node);
                var showInlineText = textChild && textChild.nodeValue().length < WI.DOMTreeElement.MaximumInlineTextChildLength;
                var showInlineEllipsis = !this.expanded && !showInlineText && (this.treeOutline.isXMLMimeType || !WI.DOMTreeElement.ForbiddenClosingTagElements.has(tagName));

                this._buildTagDOM({
                    parentElement: info.titleDOM,
                    tagName,
                    isClosingTag: false,
                    isDistinctTreeElement: false,
                    willRenderCloseTagInline: showInlineText || showInlineEllipsis,
                });

                if (showInlineEllipsis) {
                    if (this.hasChildren) {
                        var textNodeElement = info.titleDOM.createChild("span", "html-text-node");
                        textNodeElement.textContent = ellipsis;
                        info.titleDOM.append("\u200B");
                    }
                    this._buildTagDOM({
                        parentElement: info.titleDOM,
                        tagName,
                        isClosingTag: true,
                        isDistinctTreeElement: false,
                        willRenderCloseTagInline: true,
                    });
                }

                // If this element only has a single child that is a text node,
                // just show that text and the closing tag inline rather than
                // create a subtree for them
                if (showInlineText) {
                    var textNodeElement = info.titleDOM.createChild("span", "html-text-node");
                    var nodeNameLowerCase = node.nodeName().toLowerCase();

                    if (nodeNameLowerCase === "script")
                        textNodeElement.appendChild(WI.syntaxHighlightStringAsDocumentFragment(textChild.nodeValue().trim(), "text/javascript"));
                    else if (nodeNameLowerCase === "style")
                        textNodeElement.appendChild(WI.syntaxHighlightStringAsDocumentFragment(textChild.nodeValue().trim(), "text/css"));
                    else
                        textNodeElement.textContent = textChild.nodeValue();

                    info.titleDOM.append("\u200B");

                    this._buildTagDOM({
                        parentElement: info.titleDOM,
                        tagName,
                        isClosingTag: true,
                        isDistinctTreeElement: false,
                        willRenderCloseTagInline: true,
                    });
                    info.hasChildren = false;
                }
                break;

            case Node.TEXT_NODE:
                if (node.parentNode && node.parentNode.nodeName().toLowerCase() === "script") {
                    var newNode = info.titleDOM.createChild("span", "html-text-node large");
                    newNode.appendChild(WI.syntaxHighlightStringAsDocumentFragment(trimedNodeValue(), "text/javascript"));
                } else if (node.parentNode && node.parentNode.nodeName().toLowerCase() === "style") {
                    var newNode = info.titleDOM.createChild("span", "html-text-node large");
                    newNode.appendChild(WI.syntaxHighlightStringAsDocumentFragment(trimedNodeValue(), "text/css"));
                } else {
                    info.titleDOM.append("\"");
                    var textNodeElement = info.titleDOM.createChild("span", "html-text-node");
                    textNodeElement.textContent = node.nodeValue();
                    info.titleDOM.append("\"");
                }
                break;

            case Node.COMMENT_NODE:
                var commentElement = info.titleDOM.createChild("span", "html-comment");
                commentElement.append("<!--" + node.nodeValue() + "-->");
                break;

            case Node.DOCUMENT_TYPE_NODE:
                var docTypeElement = info.titleDOM.createChild("span", "html-doctype");
                docTypeElement.append("<!DOCTYPE " + node.nodeName());
                if (node.publicId) {
                    docTypeElement.append(" PUBLIC \"" + node.publicId + "\"");
                    if (node.systemId)
                        docTypeElement.append(" \"" + node.systemId + "\"");
                } else if (node.systemId)
                    docTypeElement.append(" SYSTEM \"" + node.systemId + "\"");

                docTypeElement.append(">");
                break;

            case Node.CDATA_SECTION_NODE:
                var cdataElement = info.titleDOM.createChild("span", "html-text-node");
                cdataElement.append("<![CDATA[" + node.nodeValue() + "]]>");
                break;

            case Node.PROCESSING_INSTRUCTION_NODE:
                var processingInstructionElement = info.titleDOM.createChild("span", "html-processing-instruction");
                var data = node.nodeValue();
                var dataString = data.length ? " " + data : "";
                var title = "<?" + node.nodeNameInCorrectCase() + dataString + "?>";
                processingInstructionElement.append(title);
                break;

            default:
                info.titleDOM.append(node.nodeNameInCorrectCase().collapseWhitespace());
        }

        return info;
    }

    _singleTextChild(node)
    {
        if (!node || this._ignoreSingleTextChild)
            return null;

        var firstChild = node.firstChild;
        if (!firstChild || firstChild.nodeType() !== Node.TEXT_NODE)
            return null;

        if (node.hasShadowRoots())
            return null;
        if (node.templateContent())
            return null;
        if (node.hasPseudoElements())
            return null;

        var sibling = firstChild.nextSibling;
        return sibling ? null : firstChild;
    }

    _showInlineText(node)
    {
        if (node.nodeType() === Node.ELEMENT_NODE) {
            var textChild = this._singleTextChild(node);
            if (textChild && textChild.nodeValue().length < WI.DOMTreeElement.MaximumInlineTextChildLength)
                return true;
        }
        return false;
    }

    _hasVisibleChildren()
    {
        var node = this.representedObject;

        if (this._showInlineText(node))
            return false;

        if (node.hasChildNodes())
            return true;
        if (node.templateContent())
            return true;
        if (node.hasPseudoElements())
            return true;

        return false;
    }

    _visibleChildren()
    {
        var node = this.representedObject;

        var visibleChildren = [];

        var templateContent = node.templateContent();
        if (templateContent)
            visibleChildren.push(templateContent);

        var beforePseudoElement = node.beforePseudoElement();
        if (beforePseudoElement)
            visibleChildren.push(beforePseudoElement);

        if (node.childNodeCount && node.children)
            visibleChildren.pushAll(node.children);

        var afterPseudoElement = node.afterPseudoElement();
        if (afterPseudoElement)
            visibleChildren.push(afterPseudoElement);

        return visibleChildren;
    }

    remove()
    {
        var parentElement = this.parent;
        if (!parentElement)
            return;

        var self = this;
        function removeNodeCallback(error, removedNodeId)
        {
            if (error)
                return;

            if (!self.parent)
                return;

            parentElement.removeChild(self);
            parentElement.adjustCollapsedRange();
        }

        this.representedObject.removeNode(removeNodeCallback);
    }

    _insertAdjacentHTML(position, options = {})
    {
        let hasChildren = this.hasChildren;

        let commitCallback = (value) => {
            this._ignoreSingleTextChild = false;

            if (!value.length) {
                if (!hasChildren) {
                    this._forceUpdateTitle = true;
                    this.hasChildren = false;
                    this._forceUpdateTitle = false;
                }
                return;
            }

            this.representedObject.insertAdjacentHTML(position, value);
        };

        if (position === "afterbegin" || position === "beforeend") {
            this._ignoreSingleTextChild = true;
            this.hasChildren = true;
            this.expand();
        }

        this._startEditingAsHTML(commitCallback, {...options, position});
    }

    _addHTML(event)
    {
        let options = {};
        switch (this.representedObject.nodeNameInCorrectCase()) {
        case "ul":
        case "ol":
            options.initialValue = "<li></li>";
            options.startPosition = 4;
            break;
        case "table":
        case "thead":
        case "tbody":
        case "tfoot":
            options.initialValue = "<tr></tr>";
            options.startPosition = 4;
            break;
        case "tr":
            options.initializing = "<td></td>";
            options.startPosition = 4;
            break;
        }
        this._insertAdjacentHTML("beforeend", options);
    }

    _addPreviousSibling(event)
    {
        let options = {};
        let nodeName = this.representedObject.nodeNameInCorrectCase();
        if (nodeName === "li" || nodeName === "tr" || nodeName === "th" || nodeName === "td") {
            options.initialValue = `<${nodeName}></${nodeName}>`;
            options.startPosition = nodeName.length + 2;
        }
        this._insertAdjacentHTML("beforebegin", options);
    }

    _addNextSibling(event)
    {
        let options = {};
        let nodeName = this.representedObject.nodeNameInCorrectCase();
        if (nodeName === "li" || nodeName === "tr" || nodeName === "th" || nodeName === "td") {
            options.initialValue = `<${nodeName}></${nodeName}>`;
            options.startPosition = nodeName.length + 2;
        }
        this._insertAdjacentHTML("afterend", options);
    }

    _editAsHTML()
    {
        var treeOutline = this.treeOutline;
        var node = this.representedObject;
        var parentNode = node.parentNode;
        var index = node.index;
        var wasExpanded = this.expanded;

        function selectNode(error, nodeId)
        {
            if (error)
                return;

            // Select it and expand if necessary. We force tree update so that it processes dom events and is up to date.
            treeOutline._updateModifiedNodes();

            var newNode = parentNode ? parentNode.children[index] || parentNode : null;
            if (!newNode)
                return;

            treeOutline.selectDOMNode(newNode, true);

            if (wasExpanded) {
                var newTreeItem = treeOutline.findTreeElement(newNode);
                if (newTreeItem)
                    newTreeItem.expand();
            }
        }

        function commitChange(value)
        {
            node.setOuterHTML(value, selectNode);
        }

        node.getOuterHTML((error, initialValue) => {
            if (error)
                return;

            this._startEditingAsHTML(commitChange, {
                initialValue,
                hideExistingElements: true,
            });
        });
    }

    _highlightSearchResults()
    {
        if (!this.title || !this._searchQuery || !this._searchHighlightsVisible)
            return;

        if (this._highlightResult) {
            this._updateSearchHighlight(true);
            return;
        }

        var text = this.title.textContent;
        let searchRegex = WI.SearchUtilities.regExpForString(this._searchQuery, WI.SearchUtilities.defaultSettings);

        var match = searchRegex.exec(text);
        var matchRanges = [];
        while (match) {
            matchRanges.push({offset: match.index, length: match[0].length});
            match = searchRegex.exec(text);
        }

        // Fall back for XPath, etc. matches.
        if (!matchRanges.length)
            matchRanges.push({offset: 0, length: text.length});

        this._highlightResult = [];
        WI.highlightRangesWithStyleClass(this.title, matchRanges, WI.DOMTreeElement.SearchHighlightStyleClassName, this._highlightResult);
    }

    _createModifiedAnimation(key, value, element)
    {
        let existing = this._recentlyModifiedAttributes.get(key);
        if (!existing)
            return;

        if (existing.element) {
            if (existing.listener)
                existing.element.removeEventListener("animationend", existing.listener);

            existing.element.classList.remove("node-state-changed");
            existing.element.style.removeProperty("animation-delay");
        }

        existing.listener = (event) => {
            element.classList.remove("node-state-changed");
            element.style.removeProperty("animation-delay");

            this._recentlyModifiedAttributes.delete(key);
        };

        element.classList.remove("node-state-changed");
        element.style.removeProperty("animation-delay");

        if (existing.value === value)
            element.style.setProperty("animation-delay", "-" + (performance.now() - existing.timestamp) + "ms");
        else
            existing.timestamp = performance.now();

        existing.value = value;
        existing.element = element;

        element.addEventListener("animationend", existing.listener, {once: true});
        element.classList.add("node-state-changed");
    }

    get isNodeHidden()
    {
        let classes = this.representedObject.getAttribute("class");
        return classes && classes.includes(WI.DOMTreeElement.HideElementStyleSheetIdOrClassName);
    }

    _updatePseudoClassIndicator()
    {
        if (!this.listItemElement || this._elementCloseTag)
            return;

        if (this.representedObject.enabledPseudoClasses.length) {
            if (!this._pseudoClassIndicatorElement) {
                this._pseudoClassIndicatorElement = document.createElement("div");
                this._pseudoClassIndicatorElement.classList.add("pseudo-class-indicator");
            }
            this.listItemElement.insertBefore(this._pseudoClassIndicatorElement, this.listItemElement.firstChild);
        } else {
            if (this._pseudoClassIndicatorElement) {
                this._pseudoClassIndicatorElement.remove();
                this._pseudoClassIndicatorElement = null;
            }
        }
    }

    handleEvent(event)
    {
        if (event.type === "dragstart" && this._editing)
            event.preventDefault();
    }

    _subtreeBreakpointChanged(treeElement)
    {
        if (treeElement.hasBreakpoint) {
            if (!this._subtreeBreakpointTreeElements)
                this._subtreeBreakpointTreeElements = new Set;
            this._subtreeBreakpointTreeElements.add(treeElement);
        } else {
            this._subtreeBreakpointTreeElements.delete(treeElement);
            if (!this._subtreeBreakpointTreeElements.size)
                this._subtreeBreakpointTreeElements = null;
        }

        this._updateBreakpointStatus();
    }

    _updateBreakpointStatus()
    {
        let listItemElement = this.listItemElement;
        if (!listItemElement)
            return;

        let hasBreakpoint = this._breakpointStatus !== WI.DOMTreeElement.BreakpointStatus.None;
        let hasSubtreeBreakpoints = this._subtreeBreakpointTreeElements && this._subtreeBreakpointTreeElements.size;

        if (!hasBreakpoint && !hasSubtreeBreakpoints) {
            if (this._statusImageElement)
                this._statusImageElement.remove();
            return;
        }

        if (!this._statusImageElement) {
            this._statusImageElement = WI.ImageUtilities.useSVGSymbol("Images/DOMBreakpoint.svg", "status-image");
            this._statusImageElement.classList.add("breakpoint");
            this._statusImageElement.addEventListener("click", this._statusImageClicked.bind(this));
            this._statusImageElement.addEventListener("contextmenu", this._statusImageContextmenu.bind(this));
            this._statusImageElement.addEventListener("mousedown", (event) => { event.stopPropagation(); });
        }

        this._statusImageElement.classList.toggle("subtree", !hasBreakpoint && hasSubtreeBreakpoints);

        this.listItemElement.insertBefore(this._statusImageElement, this.listItemElement.firstChild);

        let disabled = this._breakpointStatus === WI.DOMTreeElement.BreakpointStatus.DisabledBreakpoint;
        this._statusImageElement.classList.toggle("disabled", disabled);
    }

    _statusImageClicked(event)
    {
        if (this._breakpointStatus === WI.DOMTreeElement.BreakpointStatus.None)
            return;

        if (event.button !== 0 || event.ctrlKey)
            return;

        let breakpoints = WI.domDebuggerManager.domBreakpointsForNode(this.representedObject);
        if (!breakpoints || !breakpoints.length)
            return;

        let shouldEnable = breakpoints.some((breakpoint) => breakpoint.disabled);
        breakpoints.forEach((breakpoint) => { breakpoint.disabled = !shouldEnable });
    }

    _statusImageContextmenu(event)
    {
        if (!this.hasBreakpoint)
            return;

        let contextMenu = WI.ContextMenu.createFromEvent(event);

        WI.appendContextMenuItemsForDOMNodeBreakpoints(contextMenu, this.representedObject, {
            revealDescendantBreakpointsMenuItemHandler: this.bindRevealDescendantBreakpointsMenuItemHandler(),
        });
    }

    _highlightAnimationEnd()
    {
        let listItemElement = this.listItemElement;
        if (!listItemElement)
            return;

        listItemElement.removeEventListener("animationend", this._boundHighlightAnimationEnd);
        listItemElement.classList.remove(WI.DOMTreeElement.HighlightStyleClassName);

        this._animatingHighlight = false;
    }
};

WI.DOMTreeElement.InitialChildrenLimit = 500;
WI.DOMTreeElement.MaximumInlineTextChildLength = 80;

// A union of HTML4 and HTML5-Draft elements that explicitly
// or implicitly (for HTML5) forbid the closing tag.
WI.DOMTreeElement.ForbiddenClosingTagElements = new Set([
    "area", "base", "basefont", "br", "canvas", "col", "command", "embed", "frame",
    "hr", "img", "input", "keygen", "link", "meta", "param", "source",
    "wbr", "track", "menuitem"
]);

// These tags we do not allow editing their tag name.
WI.DOMTreeElement.EditTagBlacklist = new Set([
    "html", "head", "body"
]);

WI.DOMTreeElement.BreakpointStatus = {
    None: Symbol("none"),
    Breakpoint: Symbol("breakpoint"),
    DisabledBreakpoint: Symbol("disabled-breakpoint"),
};

WI.DOMTreeElement.HighlightStyleClassName = "highlight";
WI.DOMTreeElement.SearchHighlightStyleClassName = "search-highlight";
WI.DOMTreeElement.BouncyHighlightStyleClassName = "bouncy-highlight";
WI.DOMTreeElement.HideElementStyleSheetIdOrClassName = "__WebInspectorHideElement__";
