18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
40bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * Copyright (C) 2009 Joseph Pecoraro
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1.  Redistributions of source code must retain the above copyright
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     notice, this list of conditions and the following disclaimer.
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2.  Redistributions in binary form must reproduce the above copyright
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     notice, this list of conditions and the following disclaimer in the
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     documentation and/or other materials provided with the distribution.
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     its contributors may be used to endorse or promote products derived
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *     from this software without specific prior written permission.
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectWebInspector.ElementsTreeOutline = function() {
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    this.element = document.createElement("ol");
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    this.element.addEventListener("mousedown", this._onmousedown.bind(this), false);
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    this.element.addEventListener("mousemove", this._onmousemove.bind(this), false);
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    this.element.addEventListener("mouseout", this._onmouseout.bind(this), false);
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    TreeOutline.call(this, this.element);
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    this.includeRootDOMNode = true;
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    this.selectEnabled = false;
41cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    this.showInElementsPanelEnabled = false;
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    this.rootDOMNode = null;
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    this.focusedDOMNode = null;
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectWebInspector.ElementsTreeOutline.prototype = {
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    get rootDOMNode()
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return this._rootDOMNode;
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    set rootDOMNode(x)
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
54231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (this._rootDOMNode === x)
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        this._rootDOMNode = x;
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
59692e5dbf12901edacf14812a6fae25462920af42Steve Block        this._isXMLMimeType = !!(WebInspector.mainResource && WebInspector.mainResource.mimeType && WebInspector.mainResource.mimeType.match(/x(?:ht)?ml/i));
60692e5dbf12901edacf14812a6fae25462920af42Steve Block
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        this.update();
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
64692e5dbf12901edacf14812a6fae25462920af42Steve Block    get isXMLMimeType()
65692e5dbf12901edacf14812a6fae25462920af42Steve Block    {
66692e5dbf12901edacf14812a6fae25462920af42Steve Block        return this._isXMLMimeType;
67692e5dbf12901edacf14812a6fae25462920af42Steve Block    },
68692e5dbf12901edacf14812a6fae25462920af42Steve Block
69dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    nodeNameToCorrectCase: function(nodeName)
70dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    {
71dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return this.isXMLMimeType ? nodeName : nodeName.toLowerCase();
72dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    },
73dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    get focusedDOMNode()
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return this._focusedDOMNode;
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    set focusedDOMNode(x)
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
81231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (this._focusedDOMNode === x) {
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            this.revealAndSelectNode(x);
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        this._focusedDOMNode = x;
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        this.revealAndSelectNode(x);
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // The revealAndSelectNode() method might find a different element if there is inlined text,
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // and the select() call would change the focusedDOMNode and reenter this setter. So to
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // avoid calling focusedNodeChanged() twice, first check if _focusedDOMNode is the same
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // node as the one passed in.
9468513a70bcd92384395513322f1b801e7bf9c729Steve Block        if (this._focusedDOMNode === x)
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            this.focusedNodeChanged();
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
985af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    get editing()
995af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    {
1005af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        return this._editing;
1015af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    },
1025af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    update: function()
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
105643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        var selectedNode = this.selectedTreeElement ? this.selectedTreeElement.representedObject : null;
106643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        this.removeChildren();
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!this.rootDOMNode)
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        var treeElement;
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (this.includeRootDOMNode) {
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            treeElement = new WebInspector.ElementsTreeElement(this.rootDOMNode);
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            treeElement.selectable = this.selectEnabled;
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            this.appendChild(treeElement);
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else {
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // FIXME: this could use findTreeElement to reuse a tree element if it already exists
119231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            var node = this.rootDOMNode.firstChild;
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            while (node) {
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                treeElement = new WebInspector.ElementsTreeElement(node);
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                treeElement.selectable = this.selectEnabled;
1238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                this.appendChild(treeElement);
124231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                node = node.nextSibling;
1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
128643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if (selectedNode)
129643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            this.revealAndSelectNode(selectedNode);
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    updateSelection: function()
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!this.selectedTreeElement)
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        var element = this.treeOutline.selectedTreeElement;
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        element.updateSelection();
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    focusedNodeChanged: function(forceUpdate) {},
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
142231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    findTreeElement: function(node)
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
144231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        var treeElement = TreeOutline.prototype.findTreeElement.call(this, node, isAncestorNode, parentNode);
1452bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (!treeElement && node.nodeType() === Node.TEXT_NODE) {
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // The text node might have been inlined if it was short, so try to find the parent element.
147231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            treeElement = TreeOutline.prototype.findTreeElement.call(this, node.parentNode, isAncestorNode, parentNode);
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return treeElement;
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
153692e5dbf12901edacf14812a6fae25462920af42Steve Block    createTreeElementFor: function(node)
154692e5dbf12901edacf14812a6fae25462920af42Steve Block    {
155692e5dbf12901edacf14812a6fae25462920af42Steve Block        var treeElement = this.findTreeElement(node);
156692e5dbf12901edacf14812a6fae25462920af42Steve Block        if (treeElement)
157692e5dbf12901edacf14812a6fae25462920af42Steve Block            return treeElement;
158692e5dbf12901edacf14812a6fae25462920af42Steve Block        if (!node.parentNode)
159692e5dbf12901edacf14812a6fae25462920af42Steve Block            return null;
160692e5dbf12901edacf14812a6fae25462920af42Steve Block
161692e5dbf12901edacf14812a6fae25462920af42Steve Block        var treeElement = this.createTreeElementFor(node.parentNode);
162692e5dbf12901edacf14812a6fae25462920af42Steve Block        if (treeElement && treeElement.showChild(node.index))
163692e5dbf12901edacf14812a6fae25462920af42Steve Block            return treeElement.children[node.index];
164692e5dbf12901edacf14812a6fae25462920af42Steve Block
165692e5dbf12901edacf14812a6fae25462920af42Steve Block        return null;
166692e5dbf12901edacf14812a6fae25462920af42Steve Block    },
167692e5dbf12901edacf14812a6fae25462920af42Steve Block
168dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    set suppressRevealAndSelect(x)
169dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    {
170dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (this._suppressRevealAndSelect === x)
171dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            return;
172dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        this._suppressRevealAndSelect = x;
173dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    },
174dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    revealAndSelectNode: function(node)
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
177dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (!node || this._suppressRevealAndSelect)
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
180692e5dbf12901edacf14812a6fae25462920af42Steve Block        var treeElement = this.createTreeElementFor(node);
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!treeElement)
1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        treeElement.reveal();
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        treeElement.select();
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    _treeElementFromEvent: function(event)
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
1902bde8e466a4451c7319e3a072d118917957d6554Steve Block        var scrollContainer = this.element.parentElement;
1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // We choose this X coordinate based on the knowledge that our list
1932bde8e466a4451c7319e3a072d118917957d6554Steve Block        // items extend at least to the right edge of the outer <ol> container.
1942bde8e466a4451c7319e3a072d118917957d6554Steve Block        // In the no-word-wrap mode the outer <ol> may be wider than the tree container
1952bde8e466a4451c7319e3a072d118917957d6554Steve Block        // (and partially hidden), in which case we are left to use only its right boundary.
1962bde8e466a4451c7319e3a072d118917957d6554Steve Block        var x = scrollContainer.totalOffsetLeft + scrollContainer.offsetWidth - 36;
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        var y = event.pageY;
1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Our list items have 1-pixel cracks between them vertically. We avoid
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // the cracks by checking slightly above and slightly below the mouse
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // and seeing if we hit the same element each time.
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        var elementUnderMouse = this.treeElementFromPoint(x, y);
2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        var elementAboveMouse = this.treeElementFromPoint(x, y - 2);
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        var element;
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (elementUnderMouse === elementAboveMouse)
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            element = elementUnderMouse;
2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            element = this.treeElementFromPoint(x, y + 2);
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return element;
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
213dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    _onmousedown: function(event)
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        var element = this._treeElementFromEvent(event);
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!element || element.isEventWithinDisclosureTriangle(event))
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        element.select();
2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    _onmousemove: function(event)
2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
226cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        var element = this._treeElementFromEvent(event);
227cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        if (element && this._previousHoveredElement === element)
228cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            return;
229cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (this._previousHoveredElement) {
2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            this._previousHoveredElement.hovered = false;
2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            delete this._previousHoveredElement;
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
235dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (element) {
2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            element.hovered = true;
2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            this._previousHoveredElement = element;
23821939df44de1705786c545cd1bf519d47250322dBen Murdoch
23921939df44de1705786c545cd1bf519d47250322dBen Murdoch            // Lazily compute tag-specific tooltips.
24021939df44de1705786c545cd1bf519d47250322dBen Murdoch            if (element.representedObject && !element.tooltip)
24121939df44de1705786c545cd1bf519d47250322dBen Murdoch                element._createTooltipForNode();
2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
24468513a70bcd92384395513322f1b801e7bf9c729Steve Block        WebInspector.highlightDOMNode(element ? element.representedObject.id : 0);
2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    _onmouseout: function(event)
2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY);
250231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (nodeUnderMouse && nodeUnderMouse.isDescendant(this.element))
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (this._previousHoveredElement) {
2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            this._previousHoveredElement.hovered = false;
2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            delete this._previousHoveredElement;
2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
25868513a70bcd92384395513322f1b801e7bf9c729Steve Block        WebInspector.highlightDOMNode(0);
259643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    },
260643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
2612bde8e466a4451c7319e3a072d118917957d6554Steve Block    populateContextMenu: function(contextMenu, event)
262643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    {
263643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        var listItem = event.target.enclosingNodeOrSelfWithNodeName("LI");
264643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if (!listItem || !listItem.treeElement)
2652bde8e466a4451c7319e3a072d118917957d6554Steve Block            return false;
266643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
2672bde8e466a4451c7319e3a072d118917957d6554Steve Block        var populated;
2686b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        if (this.showInElementsPanelEnabled) {
2696b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            function focusElement()
2706b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            {
2712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                WebInspector.panels.elements.switchToAndFocus(listItem.treeElement.representedObject);
2726b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            }
2736b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            contextMenu.appendItem(WebInspector.UIString("Reveal in Elements Panel"), focusElement.bind(this));
2742bde8e466a4451c7319e3a072d118917957d6554Steve Block            populated = true;
2756b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        } else {
2766b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            var href = event.target.enclosingNodeOrSelfWithClass("webkit-html-resource-link") || event.target.enclosingNodeOrSelfWithClass("webkit-html-external-link");
2776b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            var tag = event.target.enclosingNodeOrSelfWithClass("webkit-html-tag");
2786b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            var textNode = event.target.enclosingNodeOrSelfWithClass("webkit-html-text-node");
2796b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            if (href)
2802bde8e466a4451c7319e3a072d118917957d6554Steve Block                populated = WebInspector.panels.elements.populateHrefContextMenu(contextMenu, event, href);
2816b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            if (tag && listItem.treeElement._populateTagContextMenu) {
2822bde8e466a4451c7319e3a072d118917957d6554Steve Block                if (populated)
2836b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                    contextMenu.appendSeparator();
2846b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                listItem.treeElement._populateTagContextMenu(contextMenu, event);
2852bde8e466a4451c7319e3a072d118917957d6554Steve Block                populated = true;
2866b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            } else if (textNode && listItem.treeElement._populateTextContextMenu) {
2872bde8e466a4451c7319e3a072d118917957d6554Steve Block                if (populated)
2886b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                    contextMenu.appendSeparator();
2896b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                listItem.treeElement._populateTextContextMenu(contextMenu, textNode);
2902bde8e466a4451c7319e3a072d118917957d6554Steve Block                populated = true;
2916b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            }
29268513a70bcd92384395513322f1b801e7bf9c729Steve Block        }
2932bde8e466a4451c7319e3a072d118917957d6554Steve Block
2942bde8e466a4451c7319e3a072d118917957d6554Steve Block        return populated;
2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectWebInspector.ElementsTreeOutline.prototype.__proto__ = TreeOutline.prototype;
2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
300dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockWebInspector.ElementsTreeElement = function(node, elementCloseTag)
3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
302dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    this._elementCloseTag = elementCloseTag;
303dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    var hasChildrenOverride = !elementCloseTag && node.hasChildNodes() && !this._showInlineText(node);
3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // The title will be updated in onattach.
306231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    TreeElement.call(this, "", node, hasChildrenOverride);
3070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3082bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (this.representedObject.nodeType() == Node.ELEMENT_NODE && !elementCloseTag)
3090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        this._canAddAttributes = true;
310692e5dbf12901edacf14812a6fae25462920af42Steve Block    this._searchQuery = null;
311692e5dbf12901edacf14812a6fae25462920af42Steve Block    this._expandedChildrenLimit = WebInspector.ElementsTreeElement.InitialChildrenLimit;
3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
314692e5dbf12901edacf14812a6fae25462920af42Steve BlockWebInspector.ElementsTreeElement.InitialChildrenLimit = 500;
315692e5dbf12901edacf14812a6fae25462920af42Steve Block
316692e5dbf12901edacf14812a6fae25462920af42Steve Block// A union of HTML4 and HTML5-Draft elements that explicitly
317692e5dbf12901edacf14812a6fae25462920af42Steve Block// or implicitly (for HTML5) forbid the closing tag.
318692e5dbf12901edacf14812a6fae25462920af42Steve Block// FIXME: Revise once HTML5 Final is published.
319692e5dbf12901edacf14812a6fae25462920af42Steve BlockWebInspector.ElementsTreeElement.ForbiddenClosingTagElements = [
320692e5dbf12901edacf14812a6fae25462920af42Steve Block    "area", "base", "basefont", "br", "canvas", "col", "command", "embed", "frame",
321692e5dbf12901edacf14812a6fae25462920af42Steve Block    "hr", "img", "input", "isindex", "keygen", "link", "meta", "param", "source"
322692e5dbf12901edacf14812a6fae25462920af42Steve Block].keySet();
3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
324dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block// These tags we do not allow editing their tag name.
325dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockWebInspector.ElementsTreeElement.EditTagBlacklist = [
326dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    "html", "head", "body"
327dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block].keySet();
328dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
329692e5dbf12901edacf14812a6fae25462920af42Steve BlockWebInspector.ElementsTreeElement.prototype = {
330692e5dbf12901edacf14812a6fae25462920af42Steve Block    highlightSearchResults: function(searchQuery)
3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
332692e5dbf12901edacf14812a6fae25462920af42Steve Block        if (this._searchQuery === searchQuery)
3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
33581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (searchQuery)
33681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            delete this._searchHighlightedHTML; // A new search query (not clear-the-current-highlighting).
33781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
338692e5dbf12901edacf14812a6fae25462920af42Steve Block        this._searchQuery = searchQuery;
33981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        this.updateTitle(true);
3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    get hovered()
3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return this._hovered;
3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    set hovered(x)
3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (this._hovered === x)
3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        this._hovered = x;
3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (this.listItemElement) {
3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (x) {
3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                this.updateSelection();
3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                this.listItemElement.addStyleClass("hovered");
358cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            } else {
3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                this.listItemElement.removeStyleClass("hovered");
360cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            }
3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
364692e5dbf12901edacf14812a6fae25462920af42Steve Block    get expandedChildrenLimit()
365692e5dbf12901edacf14812a6fae25462920af42Steve Block    {
366692e5dbf12901edacf14812a6fae25462920af42Steve Block        return this._expandedChildrenLimit;
367692e5dbf12901edacf14812a6fae25462920af42Steve Block    },
368692e5dbf12901edacf14812a6fae25462920af42Steve Block
369692e5dbf12901edacf14812a6fae25462920af42Steve Block    set expandedChildrenLimit(x)
370692e5dbf12901edacf14812a6fae25462920af42Steve Block    {
371692e5dbf12901edacf14812a6fae25462920af42Steve Block        if (this._expandedChildrenLimit === x)
372692e5dbf12901edacf14812a6fae25462920af42Steve Block            return;
373692e5dbf12901edacf14812a6fae25462920af42Steve Block
374692e5dbf12901edacf14812a6fae25462920af42Steve Block        this._expandedChildrenLimit = x;
375692e5dbf12901edacf14812a6fae25462920af42Steve Block        if (this.treeOutline && !this._updateChildrenInProgress)
376692e5dbf12901edacf14812a6fae25462920af42Steve Block            this._updateChildren(true);
377692e5dbf12901edacf14812a6fae25462920af42Steve Block    },
378692e5dbf12901edacf14812a6fae25462920af42Steve Block
379692e5dbf12901edacf14812a6fae25462920af42Steve Block    get expandedChildCount()
380692e5dbf12901edacf14812a6fae25462920af42Steve Block    {
381692e5dbf12901edacf14812a6fae25462920af42Steve Block        var count = this.children.length;
382dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (count && this.children[count - 1]._elementCloseTag)
383692e5dbf12901edacf14812a6fae25462920af42Steve Block            count--;
384692e5dbf12901edacf14812a6fae25462920af42Steve Block        if (count && this.children[count - 1].expandAllButton)
385692e5dbf12901edacf14812a6fae25462920af42Steve Block            count--;
386692e5dbf12901edacf14812a6fae25462920af42Steve Block        return count;
387692e5dbf12901edacf14812a6fae25462920af42Steve Block    },
388692e5dbf12901edacf14812a6fae25462920af42Steve Block
389692e5dbf12901edacf14812a6fae25462920af42Steve Block    showChild: function(index)
390692e5dbf12901edacf14812a6fae25462920af42Steve Block    {
391dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (this._elementCloseTag)
392dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            return;
393dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
394692e5dbf12901edacf14812a6fae25462920af42Steve Block        if (index >= this.expandedChildrenLimit) {
395692e5dbf12901edacf14812a6fae25462920af42Steve Block            this._expandedChildrenLimit = index + 1;
396692e5dbf12901edacf14812a6fae25462920af42Steve Block            this._updateChildren(true);
397692e5dbf12901edacf14812a6fae25462920af42Steve Block        }
398692e5dbf12901edacf14812a6fae25462920af42Steve Block
399692e5dbf12901edacf14812a6fae25462920af42Steve Block        // Whether index-th child is visible in the children tree
400692e5dbf12901edacf14812a6fae25462920af42Steve Block        return this.expandedChildCount > index;
401692e5dbf12901edacf14812a6fae25462920af42Steve Block    },
402692e5dbf12901edacf14812a6fae25462920af42Steve Block
40321939df44de1705786c545cd1bf519d47250322dBen Murdoch    _createTooltipForNode: function()
404643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    {
40521939df44de1705786c545cd1bf519d47250322dBen Murdoch        var node = this.representedObject;
4062bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (!node.nodeName() || node.nodeName().toLowerCase() !== "img")
407dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            return;
408e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
4092bde8e466a4451c7319e3a072d118917957d6554Steve Block        function setTooltip(error, result)
410643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        {
4112bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (error || !result || result.type !== "string")
412643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                return;
413643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
41481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            try {
41581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                var properties = JSON.parse(result.description);
41681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                var offsetWidth = properties[0];
41781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                var offsetHeight = properties[1];
41881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                var naturalWidth = properties[2];
41981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                var naturalHeight = properties[3];
42081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                if (offsetHeight === naturalHeight && offsetWidth === naturalWidth)
42181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                    this.tooltip = WebInspector.UIString("%d \xd7 %d pixels", offsetWidth, offsetHeight);
42281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                else
42381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                    this.tooltip = WebInspector.UIString("%d \xd7 %d pixels (Natural: %d \xd7 %d pixels)", offsetWidth, offsetHeight, naturalWidth, naturalHeight);
42481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            } catch (e) {
42581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                console.error(e);
42681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            }
42781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        }
42881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
4292bde8e466a4451c7319e3a072d118917957d6554Steve Block        function resolvedNode(object)
43081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        {
4312bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (!object)
43281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                return;
43381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
43481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            object.evaluate("return '[' + this.offsetWidth + ',' + this.offsetHeight + ',' + this.naturalWidth + ',' + this.naturalHeight + ']'", setTooltip.bind(this));
4352bde8e466a4451c7319e3a072d118917957d6554Steve Block            object.release();
436643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        }
4372bde8e466a4451c7319e3a072d118917957d6554Steve Block        WebInspector.RemoteObject.resolveNode(node, resolvedNode.bind(this));
438643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    },
439643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    updateSelection: function()
4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        var listItemElement = this.listItemElement;
4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!listItemElement)
4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (document.body.offsetWidth <= 0) {
4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // The stylesheet hasn't loaded yet or the window is closed,
4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // so we can't calculate what is need. Return early.
4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
4518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!this.selectionElement) {
4538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            this.selectionElement = document.createElement("div");
4548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            this.selectionElement.className = "selection selected";
4558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            listItemElement.insertBefore(this.selectionElement, listItemElement.firstChild);
4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
4578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        this.selectionElement.style.height = listItemElement.offsetHeight + "px";
4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
4608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    onattach: function()
4628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
4638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (this._hovered) {
4648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            this.updateSelection();
4658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            this.listItemElement.addStyleClass("hovered");
4668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
4678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
468d0825bca7fe65beaee391d30da42e937db621564Steve Block        this.updateTitle();
4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        this._preventFollowingLinksOnDoubleClick();
4718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    _preventFollowingLinksOnDoubleClick: function()
4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
4758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        var links = this.listItemElement.querySelectorAll("li > .webkit-html-tag > .webkit-html-attribute > .webkit-html-external-link, li > .webkit-html-tag > .webkit-html-attribute > .webkit-html-resource-link");
4768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!links)
4778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
4788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        for (var i = 0; i < links.length; ++i)
4808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            links[i].preventFollowOnDoubleClick = true;
4818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
4828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    onpopulate: function()
4848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
485dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (this.children.length || this._showInlineText(this.representedObject) || this._elementCloseTag)
4868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
4878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        this.updateChildren();
4898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
490dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
491058ccc7ba0a4d59b9f6e92808332aa9895425fc7Andrei Popescu    updateChildren: function(fullRefresh)
492d227fc870c7a697500a3c900c31baf05fb9a8524Ben Murdoch    {
493dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (this._elementCloseTag)
494dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            return;
4952bde8e466a4451c7319e3a072d118917957d6554Steve Block        this.representedObject.getChildNodes(this._updateChildren.bind(this, fullRefresh));
496231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    },
497231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
498dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    insertChildElement: function(child, index, closingTag)
499692e5dbf12901edacf14812a6fae25462920af42Steve Block    {
500dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        var newElement = new WebInspector.ElementsTreeElement(child, closingTag);
501692e5dbf12901edacf14812a6fae25462920af42Steve Block        newElement.selectable = this.treeOutline.selectEnabled;
502692e5dbf12901edacf14812a6fae25462920af42Steve Block        this.insertChild(newElement, index);
503692e5dbf12901edacf14812a6fae25462920af42Steve Block        return newElement;
504692e5dbf12901edacf14812a6fae25462920af42Steve Block    },
505692e5dbf12901edacf14812a6fae25462920af42Steve Block
506692e5dbf12901edacf14812a6fae25462920af42Steve Block    moveChild: function(child, targetIndex)
507692e5dbf12901edacf14812a6fae25462920af42Steve Block    {
508692e5dbf12901edacf14812a6fae25462920af42Steve Block        var wasSelected = child.selected;
509dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        this.removeChild(child);
510dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        this.insertChild(child, targetIndex);
511692e5dbf12901edacf14812a6fae25462920af42Steve Block        if (wasSelected)
512dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            child.select();
513692e5dbf12901edacf14812a6fae25462920af42Steve Block    },
514692e5dbf12901edacf14812a6fae25462920af42Steve Block
515231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    _updateChildren: function(fullRefresh)
516231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    {
517692e5dbf12901edacf14812a6fae25462920af42Steve Block        if (this._updateChildrenInProgress)
518692e5dbf12901edacf14812a6fae25462920af42Steve Block            return;
519692e5dbf12901edacf14812a6fae25462920af42Steve Block
520692e5dbf12901edacf14812a6fae25462920af42Steve Block        this._updateChildrenInProgress = true;
521692e5dbf12901edacf14812a6fae25462920af42Steve Block        var focusedNode = this.treeOutline.focusedDOMNode;
522692e5dbf12901edacf14812a6fae25462920af42Steve Block        var originalScrollTop;
5238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (fullRefresh) {
524692e5dbf12901edacf14812a6fae25462920af42Steve Block            var treeOutlineContainerElement = this.treeOutline.element.parentNode;
525692e5dbf12901edacf14812a6fae25462920af42Steve Block            originalScrollTop = treeOutlineContainerElement.scrollTop;
5268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            var selectedTreeElement = this.treeOutline.selectedTreeElement;
5278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (selectedTreeElement && selectedTreeElement.hasAncestor(this))
5288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                this.select();
5298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            this.removeChildren();
5308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
5318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        var treeElement = this;
5338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        var treeChildIndex = 0;
534692e5dbf12901edacf14812a6fae25462920af42Steve Block        var elementToSelect;
5358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        function updateChildrenOfNode(node)
5378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        {
5388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            var treeOutline = treeElement.treeOutline;
539231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            var child = node.firstChild;
5408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            while (child) {
5418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                var currentTreeElement = treeElement.children[treeChildIndex];
542231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                if (!currentTreeElement || currentTreeElement.representedObject !== child) {
5438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    // Find any existing element that is later in the children list.
5448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    var existingTreeElement = null;
545692e5dbf12901edacf14812a6fae25462920af42Steve Block                    for (var i = (treeChildIndex + 1), size = treeElement.expandedChildCount; i < size; ++i) {
546231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                        if (treeElement.children[i].representedObject === child) {
5478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            existingTreeElement = treeElement.children[i];
5488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                            break;
5498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        }
5508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
5518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    if (existingTreeElement && existingTreeElement.parent === treeElement) {
5538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        // If an existing element was found and it has the same parent, just move it.
554692e5dbf12901edacf14812a6fae25462920af42Steve Block                        treeElement.moveChild(existingTreeElement, treeChildIndex);
5558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    } else {
5568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                        // No existing element found, insert a new element.
557692e5dbf12901edacf14812a6fae25462920af42Steve Block                        if (treeChildIndex < treeElement.expandedChildrenLimit) {
558692e5dbf12901edacf14812a6fae25462920af42Steve Block                            var newElement = treeElement.insertChildElement(child, treeChildIndex);
559692e5dbf12901edacf14812a6fae25462920af42Steve Block                            if (child === focusedNode)
560692e5dbf12901edacf14812a6fae25462920af42Steve Block                                elementToSelect = newElement;
561692e5dbf12901edacf14812a6fae25462920af42Steve Block                            if (treeElement.expandedChildCount > treeElement.expandedChildrenLimit)
562692e5dbf12901edacf14812a6fae25462920af42Steve Block                                treeElement.expandedChildrenLimit++;
563692e5dbf12901edacf14812a6fae25462920af42Steve Block                        }
5648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    }
5658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
5668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
567231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                child = child.nextSibling;
5688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                ++treeChildIndex;
5698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
5708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
5718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Remove any tree elements that no longer have this node (or this node's contentDocument) as their parent.
5738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        for (var i = (this.children.length - 1); i >= 0; --i) {
5748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            var currentChild = this.children[i];
5758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            var currentNode = currentChild.representedObject;
5768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            var currentParentNode = currentNode.parentNode;
5778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
578231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (currentParentNode === this.representedObject)
5798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                continue;
5808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            var selectedTreeElement = this.treeOutline.selectedTreeElement;
5828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (selectedTreeElement && (selectedTreeElement === currentChild || selectedTreeElement.hasAncestor(currentChild)))
5838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                this.select();
5848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            this.removeChildAtIndex(i);
5868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
5878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        updateChildrenOfNode(this.representedObject);
589692e5dbf12901edacf14812a6fae25462920af42Steve Block        this.adjustCollapsedRange(false);
5908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        var lastChild = this.children[this.children.length - 1];
5922bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (this.representedObject.nodeType() == Node.ELEMENT_NODE && (!lastChild || !lastChild._elementCloseTag))
593dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            this.insertChildElement(this.representedObject, this.children.length, true);
594692e5dbf12901edacf14812a6fae25462920af42Steve Block
595692e5dbf12901edacf14812a6fae25462920af42Steve Block        // We want to restore the original selection and tree scroll position after a full refresh, if possible.
596692e5dbf12901edacf14812a6fae25462920af42Steve Block        if (fullRefresh && elementToSelect) {
597692e5dbf12901edacf14812a6fae25462920af42Steve Block            elementToSelect.select();
598692e5dbf12901edacf14812a6fae25462920af42Steve Block            if (treeOutlineContainerElement && originalScrollTop <= treeOutlineContainerElement.scrollHeight)
599692e5dbf12901edacf14812a6fae25462920af42Steve Block                treeOutlineContainerElement.scrollTop = originalScrollTop;
600692e5dbf12901edacf14812a6fae25462920af42Steve Block        }
601692e5dbf12901edacf14812a6fae25462920af42Steve Block
602692e5dbf12901edacf14812a6fae25462920af42Steve Block        delete this._updateChildrenInProgress;
603692e5dbf12901edacf14812a6fae25462920af42Steve Block    },
604692e5dbf12901edacf14812a6fae25462920af42Steve Block
605692e5dbf12901edacf14812a6fae25462920af42Steve Block    adjustCollapsedRange: function()
606692e5dbf12901edacf14812a6fae25462920af42Steve Block    {
607692e5dbf12901edacf14812a6fae25462920af42Steve Block        // Ensure precondition: only the tree elements for node children are found in the tree
608692e5dbf12901edacf14812a6fae25462920af42Steve Block        // (not the Expand All button or the closing tag).
609692e5dbf12901edacf14812a6fae25462920af42Steve Block        if (this.expandAllButtonElement && this.expandAllButtonElement.__treeElement.parent)
610692e5dbf12901edacf14812a6fae25462920af42Steve Block            this.removeChild(this.expandAllButtonElement.__treeElement);
611692e5dbf12901edacf14812a6fae25462920af42Steve Block
612692e5dbf12901edacf14812a6fae25462920af42Steve Block        const node = this.representedObject;
613692e5dbf12901edacf14812a6fae25462920af42Steve Block        if (!node.children)
614692e5dbf12901edacf14812a6fae25462920af42Steve Block            return;
615692e5dbf12901edacf14812a6fae25462920af42Steve Block        const childNodeCount = node.children.length;
616692e5dbf12901edacf14812a6fae25462920af42Steve Block
617692e5dbf12901edacf14812a6fae25462920af42Steve Block        // In case some nodes from the expanded range were removed, pull some nodes from the collapsed range into the expanded range at the bottom.
618692e5dbf12901edacf14812a6fae25462920af42Steve Block        for (var i = this.expandedChildCount, limit = Math.min(this.expandedChildrenLimit, childNodeCount); i < limit; ++i)
619692e5dbf12901edacf14812a6fae25462920af42Steve Block            this.insertChildElement(node.children[i], i);
620692e5dbf12901edacf14812a6fae25462920af42Steve Block
621692e5dbf12901edacf14812a6fae25462920af42Steve Block        const expandedChildCount = this.expandedChildCount;
622692e5dbf12901edacf14812a6fae25462920af42Steve Block        if (childNodeCount > this.expandedChildCount) {
623692e5dbf12901edacf14812a6fae25462920af42Steve Block            var targetButtonIndex = expandedChildCount;
624692e5dbf12901edacf14812a6fae25462920af42Steve Block            if (!this.expandAllButtonElement) {
6256b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                var item = new TreeElement(null, null, false);
6266b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                item.titleHTML = "<button class=\"show-all-nodes\" value=\"\" />";
627692e5dbf12901edacf14812a6fae25462920af42Steve Block                item.selectable = false;
628692e5dbf12901edacf14812a6fae25462920af42Steve Block                item.expandAllButton = true;
629692e5dbf12901edacf14812a6fae25462920af42Steve Block                this.insertChild(item, targetButtonIndex);
630692e5dbf12901edacf14812a6fae25462920af42Steve Block                this.expandAllButtonElement = item.listItemElement.firstChild;
631692e5dbf12901edacf14812a6fae25462920af42Steve Block                this.expandAllButtonElement.__treeElement = item;
632692e5dbf12901edacf14812a6fae25462920af42Steve Block                this.expandAllButtonElement.addEventListener("click", this.handleLoadAllChildren.bind(this), false);
633692e5dbf12901edacf14812a6fae25462920af42Steve Block            } else if (!this.expandAllButtonElement.__treeElement.parent)
634692e5dbf12901edacf14812a6fae25462920af42Steve Block                this.insertChild(this.expandAllButtonElement.__treeElement, targetButtonIndex);
635692e5dbf12901edacf14812a6fae25462920af42Steve Block            this.expandAllButtonElement.textContent = WebInspector.UIString("Show All Nodes (%d More)", childNodeCount - expandedChildCount);
636692e5dbf12901edacf14812a6fae25462920af42Steve Block        } else if (this.expandAllButtonElement)
637692e5dbf12901edacf14812a6fae25462920af42Steve Block            delete this.expandAllButtonElement;
638692e5dbf12901edacf14812a6fae25462920af42Steve Block    },
639692e5dbf12901edacf14812a6fae25462920af42Steve Block
640692e5dbf12901edacf14812a6fae25462920af42Steve Block    handleLoadAllChildren: function()
641692e5dbf12901edacf14812a6fae25462920af42Steve Block    {
642692e5dbf12901edacf14812a6fae25462920af42Steve Block        this.expandedChildrenLimit = Math.max(this.representedObject._childNodeCount, this.expandedChildrenLimit + WebInspector.ElementsTreeElement.InitialChildrenLimit);
6438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
6448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    onexpand: function()
6468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
647dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (this._elementCloseTag)
648dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            return;
649dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
650692e5dbf12901edacf14812a6fae25462920af42Steve Block        this.updateTitle();
6518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        this.treeOutline.updateSelection();
6528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
6538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    oncollapse: function()
6558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
656dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (this._elementCloseTag)
657dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            return;
658dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
659692e5dbf12901edacf14812a6fae25462920af42Steve Block        this.updateTitle();
6608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        this.treeOutline.updateSelection();
6618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
6628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    onreveal: function()
6648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
6652bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (this.listItemElement) {
6662bde8e466a4451c7319e3a072d118917957d6554Steve Block            var tagSpans = this.listItemElement.getElementsByClassName("webkit-html-tag-name");
6672bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (tagSpans.length)
6682bde8e466a4451c7319e3a072d118917957d6554Steve Block                tagSpans[0].scrollIntoViewIfNeeded(false);
6692bde8e466a4451c7319e3a072d118917957d6554Steve Block            else
6702bde8e466a4451c7319e3a072d118917957d6554Steve Block                this.listItemElement.scrollIntoViewIfNeeded(false);
6712bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
6728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
6738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
674bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    onselect: function(treeElement, selectedByUser)
6758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
676dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        this.treeOutline.suppressRevealAndSelect = true;
6778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        this.treeOutline.focusedDOMNode = this.representedObject;
678bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        if (selectedByUser)
679bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen            WebInspector.highlightDOMNode(this.representedObject.id);
6808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        this.updateSelection();
681dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        this.treeOutline.suppressRevealAndSelect = false;
6828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
6838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6845af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    ondelete: function()
6855af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    {
6865af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        var startTagTreeElement = this.treeOutline.findTreeElement(this.representedObject);
6875af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        startTagTreeElement ? startTagTreeElement.remove() : this.remove();
6885af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        return true;
6895af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    },
6905af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
6915af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    onenter: function()
6925af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    {
6935af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        // On Enter or Return start editing the first attribute
6945af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        // or create a new attribute on the selected element.
6955af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        if (this.treeOutline.editing)
6965af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke            return false;
6975af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
6985af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        this._startEditing();
6995af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
7005af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        // prevent a newline from being immediately inserted
7015af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        return true;
7025af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    },
7035af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke
704dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    selectOnMouseDown: function(event)
7058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
706dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        TreeElement.prototype.selectOnMouseDown.call(this, event);
7078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
708dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (this._editing)
709cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            return;
710cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
711dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (this.treeOutline.showInElementsPanelEnabled) {
712dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch            WebInspector.showPanel("elements");
713cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            WebInspector.panels.elements.focusedDOMNode = this.representedObject;
714cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        }
715cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
7168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Prevent selecting the nearest word on double click.
7178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (event.detail >= 2)
7188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            event.preventDefault();
7198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
7208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
721643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    ondblclick: function(event)
7228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
723dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (this._editing || this._elementCloseTag)
7248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
7258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
726dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (this._startEditingTarget(event.target))
7278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
7288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (this.hasChildren && !this.expanded)
7308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            this.expand();
7318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
7328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    _insertInLastAttributePosition: function(tag, node)
7340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    {
7350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (tag.getElementsByClassName("webkit-html-attribute").length > 0)
7360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            tag.insertBefore(node, tag.lastChild);
7370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        else {
7380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            var nodeName = tag.textContent.match(/^<(.*?)>$/)[1];
7390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            tag.textContent = '';
7400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            tag.appendChild(document.createTextNode('<'+nodeName));
7410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            tag.appendChild(node);
7420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            tag.appendChild(document.createTextNode('>'));
7430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
744cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
745cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        this.updateSelection();
7460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    },
7470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
748dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    _startEditingTarget: function(eventTarget)
7498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
7508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (this.treeOutline.focusedDOMNode != this.representedObject)
7518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
7528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7532bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (this.representedObject.nodeType() != Node.ELEMENT_NODE && this.representedObject.nodeType() != Node.TEXT_NODE)
7548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
7558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
756dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        var textNode = eventTarget.enclosingNodeOrSelfWithClass("webkit-html-text-node");
7578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (textNode)
7588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return this._startEditingTextNode(textNode);
7598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
760dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        var attribute = eventTarget.enclosingNodeOrSelfWithClass("webkit-html-attribute");
7618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (attribute)
762dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            return this._startEditingAttribute(attribute, eventTarget);
7630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
764dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        var tagName = eventTarget.enclosingNodeOrSelfWithClass("webkit-html-tag-name");
765dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (tagName)
766dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            return this._startEditingTagName(tagName);
767dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
768dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        var newAttribute = eventTarget.enclosingNodeOrSelfWithClass("add-attribute");
7690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (newAttribute)
770643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            return this._addNewAttribute();
7718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
7738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
7748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
775643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    _populateTagContextMenu: function(contextMenu, event)
776643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    {
777643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        var attribute = event.target.enclosingNodeOrSelfWithClass("webkit-html-attribute");
778643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        var newAttribute = event.target.enclosingNodeOrSelfWithClass("add-attribute");
779643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
780643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        // Add attribute-related actions.
781643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        contextMenu.appendItem(WebInspector.UIString("Add Attribute"), this._addNewAttribute.bind(this));
782643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if (attribute && !newAttribute)
783643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            contextMenu.appendItem(WebInspector.UIString("Edit Attribute"), this._startEditingAttribute.bind(this, attribute, event.target));
784643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        contextMenu.appendSeparator();
785643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
786dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // Add free-form node-related actions.
787d0825bca7fe65beaee391d30da42e937db621564Steve Block        contextMenu.appendItem(WebInspector.UIString("Edit as HTML"), this._editAsHTML.bind(this));
788d0825bca7fe65beaee391d30da42e937db621564Steve Block        contextMenu.appendItem(WebInspector.UIString("Copy as HTML"), this._copyHTML.bind(this));
789643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        contextMenu.appendItem(WebInspector.UIString("Delete Node"), this.remove.bind(this));
790e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
791bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        if (Preferences.nativeInstrumentationEnabled) {
792e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block            // Add debbuging-related actions
793e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block            contextMenu.appendSeparator();
7942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            var pane = WebInspector.panels.elements.sidebarPanes.domBreakpoints;
7952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            pane.populateNodeContextMenu(this.representedObject, contextMenu);
796e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        }
797643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    },
798643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
799643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    _populateTextContextMenu: function(contextMenu, textNode)
800643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    {
801643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        contextMenu.appendItem(WebInspector.UIString("Edit Text"), this._startEditingTextNode.bind(this, textNode));
802643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    },
803643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
804cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    _startEditing: function()
805cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    {
806cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        if (this.treeOutline.focusedDOMNode !== this.representedObject)
807cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            return;
808cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
809cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        var listItem = this._listItemNode;
810cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
811cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        if (this._canAddAttributes) {
812cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            var attribute = listItem.getElementsByClassName("webkit-html-attribute")[0];
813cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            if (attribute)
814cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                return this._startEditingAttribute(attribute, attribute.getElementsByClassName("webkit-html-attribute-value")[0]);
815cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
816643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            return this._addNewAttribute();
817cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        }
818cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
8192bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (this.representedObject.nodeType() === Node.TEXT_NODE) {
820cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            var textNode = listItem.getElementsByClassName("webkit-html-text-node")[0];
821cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            if (textNode)
822cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                return this._startEditingTextNode(textNode);
823cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            return;
824cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        }
825cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    },
826cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
827643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    _addNewAttribute: function()
8280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    {
829dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // Cannot just convert the textual html into an element without
830dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // a parent node. Use a temporary span container for the HTML.
831dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        var container = document.createElement("span");
832dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        container.innerHTML = this._attributeHTML(" ", "");
833dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        var attr = container.firstChild;
8340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        attr.style.marginLeft = "2px"; // overrides the .editing margin rule
8350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        attr.style.marginRight = "2px"; // overrides the .editing margin rule
8360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
837643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        var tag = this.listItemElement.getElementsByClassName("webkit-html-tag")[0];
8380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        this._insertInLastAttributePosition(tag, attr);
8390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return this._startEditingAttribute(attr, attr);
8400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    },
8410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
8420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    _triggerEditAttribute: function(attributeName)
8430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    {
8440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        var attributeElements = this.listItemElement.getElementsByClassName("webkit-html-attribute-name");
8450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        for (var i = 0, len = attributeElements.length; i < len; ++i) {
8460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            if (attributeElements[i].textContent === attributeName) {
8470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                for (var elem = attributeElements[i].nextSibling; elem; elem = elem.nextSibling) {
8480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                    if (elem.nodeType !== Node.ELEMENT_NODE)
8490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                        continue;
8500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
8510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                    if (elem.hasStyleClass("webkit-html-attribute-value"))
852dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                        return this._startEditingAttribute(elem.parentNode, elem);
8530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                }
8540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            }
8550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
8560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    },
8570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
8580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    _startEditingAttribute: function(attribute, elementForSelection)
8598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
8608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (WebInspector.isBeingEdited(attribute))
8618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return true;
8628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        var attributeNameElement = attribute.getElementsByClassName("webkit-html-attribute-name")[0];
8648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!attributeNameElement)
8658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
8668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8672bde8e466a4451c7319e3a072d118917957d6554Steve Block        var attributeName = attributeNameElement.textContent;
8688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        function removeZeroWidthSpaceRecursive(node)
8708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        {
8718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (node.nodeType === Node.TEXT_NODE) {
8728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                node.nodeValue = node.nodeValue.replace(/\u200B/g, "");
8738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return;
8748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
8758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (node.nodeType !== Node.ELEMENT_NODE)
8778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return;
8788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            for (var child = node.firstChild; child; child = child.nextSibling)
8808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                removeZeroWidthSpaceRecursive(child);
8818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
8828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Remove zero-width spaces that were added by nodeTitleInfo.
8848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        removeZeroWidthSpaceRecursive(attribute);
8858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
886f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        this._editing = WebInspector.startEditing(attribute, {
887f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            context: attributeName,
888f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            commitHandler: this._attributeEditingCommitted.bind(this),
889f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            cancelHandler: this._editingCancelled.bind(this)
890f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        });
8910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        window.getSelection().setBaseAndExtent(elementForSelection, 0, elementForSelection, 1);
8928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
8948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
8958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    _startEditingTextNode: function(textNode)
8978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
8988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (WebInspector.isBeingEdited(textNode))
8998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return true;
9008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
901f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        this._editing = WebInspector.startEditing(textNode, {
902f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            context: null,
903f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            commitHandler: this._textNodeEditingCommitted.bind(this),
904f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            cancelHandler: this._editingCancelled.bind(this)
905f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        });
9068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        window.getSelection().setBaseAndExtent(textNode, 0, textNode, 1);
9078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
9098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
9108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
911dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    _startEditingTagName: function(tagNameElement)
912dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    {
913dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (!tagNameElement) {
914dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            tagNameElement = this.listItemElement.getElementsByClassName("webkit-html-tag-name")[0];
915dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (!tagNameElement)
916dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                return false;
917dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
918dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
919dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        var tagName = tagNameElement.textContent;
920dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (WebInspector.ElementsTreeElement.EditTagBlacklist[tagName.toLowerCase()])
921dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            return false;
922dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
923dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (WebInspector.isBeingEdited(tagNameElement))
924dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            return true;
925dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
926dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        var closingTagElement = this._distinctClosingTagElement();
927dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
928dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        function keyupListener(event)
929dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        {
930dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (closingTagElement)
931dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                closingTagElement.textContent = "</" + tagNameElement.textContent + ">";
932dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
933dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
934dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        function editingComitted(element, newTagName)
935dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        {
936dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            tagNameElement.removeEventListener('keyup', keyupListener, false);
937dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            this._tagNameEditingCommitted.apply(this, arguments);
938dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
939dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
940dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        function editingCancelled()
941dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        {
942dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            tagNameElement.removeEventListener('keyup', keyupListener, false);
943dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            this._editingCancelled.apply(this, arguments);
944dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
945dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
946dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        tagNameElement.addEventListener('keyup', keyupListener, false);
947dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
948f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        this._editing = WebInspector.startEditing(tagNameElement, {
949f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            context: tagName,
950f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            commitHandler: editingComitted.bind(this),
951f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            cancelHandler: editingCancelled.bind(this)
952f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        });
953dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        window.getSelection().setBaseAndExtent(tagNameElement, 0, tagNameElement, 1);
954dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return true;
955dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    },
956dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
9572bde8e466a4451c7319e3a072d118917957d6554Steve Block    _startEditingAsHTML: function(commitCallback, error, initialValue)
958d0825bca7fe65beaee391d30da42e937db621564Steve Block    {
9592bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (error)
9602bde8e466a4451c7319e3a072d118917957d6554Steve Block            return;
961d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (this._htmlEditElement && WebInspector.isBeingEdited(this._htmlEditElement))
9622bde8e466a4451c7319e3a072d118917957d6554Steve Block            return;
963d0825bca7fe65beaee391d30da42e937db621564Steve Block
964d0825bca7fe65beaee391d30da42e937db621564Steve Block        this._htmlEditElement = document.createElement("div");
965d0825bca7fe65beaee391d30da42e937db621564Steve Block        this._htmlEditElement.className = "source-code elements-tree-editor";
966d0825bca7fe65beaee391d30da42e937db621564Steve Block        this._htmlEditElement.textContent = initialValue;
967d0825bca7fe65beaee391d30da42e937db621564Steve Block
968d0825bca7fe65beaee391d30da42e937db621564Steve Block        // Hide header items.
969d0825bca7fe65beaee391d30da42e937db621564Steve Block        var child = this.listItemElement.firstChild;
970d0825bca7fe65beaee391d30da42e937db621564Steve Block        while (child) {
971d0825bca7fe65beaee391d30da42e937db621564Steve Block            child.style.display = "none";
972d0825bca7fe65beaee391d30da42e937db621564Steve Block            child = child.nextSibling;
973d0825bca7fe65beaee391d30da42e937db621564Steve Block        }
974d0825bca7fe65beaee391d30da42e937db621564Steve Block        // Hide children item.
975d0825bca7fe65beaee391d30da42e937db621564Steve Block        if (this._childrenListNode)
976d0825bca7fe65beaee391d30da42e937db621564Steve Block            this._childrenListNode.style.display = "none";
977d0825bca7fe65beaee391d30da42e937db621564Steve Block        // Append editor.
978d0825bca7fe65beaee391d30da42e937db621564Steve Block        this.listItemElement.appendChild(this._htmlEditElement);
979d0825bca7fe65beaee391d30da42e937db621564Steve Block
980d0825bca7fe65beaee391d30da42e937db621564Steve Block        this.updateSelection();
981d0825bca7fe65beaee391d30da42e937db621564Steve Block
982d0825bca7fe65beaee391d30da42e937db621564Steve Block        function commit()
983d0825bca7fe65beaee391d30da42e937db621564Steve Block        {
984d0825bca7fe65beaee391d30da42e937db621564Steve Block            commitCallback(this._htmlEditElement.textContent);
985d0825bca7fe65beaee391d30da42e937db621564Steve Block            dispose.call(this);
986d0825bca7fe65beaee391d30da42e937db621564Steve Block        }
987d0825bca7fe65beaee391d30da42e937db621564Steve Block
988d0825bca7fe65beaee391d30da42e937db621564Steve Block        function dispose()
989d0825bca7fe65beaee391d30da42e937db621564Steve Block        {
990d0825bca7fe65beaee391d30da42e937db621564Steve Block            delete this._editing;
991d0825bca7fe65beaee391d30da42e937db621564Steve Block
992d0825bca7fe65beaee391d30da42e937db621564Steve Block            // Remove editor.
993d0825bca7fe65beaee391d30da42e937db621564Steve Block            this.listItemElement.removeChild(this._htmlEditElement);
994d0825bca7fe65beaee391d30da42e937db621564Steve Block            delete this._htmlEditElement;
995d0825bca7fe65beaee391d30da42e937db621564Steve Block            // Unhide children item.
996d0825bca7fe65beaee391d30da42e937db621564Steve Block            if (this._childrenListNode)
997d0825bca7fe65beaee391d30da42e937db621564Steve Block                this._childrenListNode.style.removeProperty("display");
998d0825bca7fe65beaee391d30da42e937db621564Steve Block            // Unhide header items.
999d0825bca7fe65beaee391d30da42e937db621564Steve Block            var child = this.listItemElement.firstChild;
1000d0825bca7fe65beaee391d30da42e937db621564Steve Block            while (child) {
1001d0825bca7fe65beaee391d30da42e937db621564Steve Block                child.style.removeProperty("display");
1002d0825bca7fe65beaee391d30da42e937db621564Steve Block                child = child.nextSibling;
1003d0825bca7fe65beaee391d30da42e937db621564Steve Block            }
1004d0825bca7fe65beaee391d30da42e937db621564Steve Block
1005d0825bca7fe65beaee391d30da42e937db621564Steve Block            this.updateSelection();
1006d0825bca7fe65beaee391d30da42e937db621564Steve Block        }
1007d0825bca7fe65beaee391d30da42e937db621564Steve Block
1008f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        this._editing = WebInspector.startEditing(this._htmlEditElement, {
1009f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            context: null,
1010f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            commitHandler: commit.bind(this),
1011f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            cancelHandler: dispose.bind(this),
1012f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            multiline: true
1013f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        });
1014d0825bca7fe65beaee391d30da42e937db621564Steve Block    },
1015d0825bca7fe65beaee391d30da42e937db621564Steve Block
10160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    _attributeEditingCommitted: function(element, newText, oldText, attributeName, moveDirection)
10178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
10188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        delete this._editing;
10198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // Before we do anything, determine where we should move
10210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // next based on the current element's settings
1022dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        var moveToAttribute, moveToTagName, moveToNewAttribute;
10230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (moveDirection) {
10240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            var found = false;
1025dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1026dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            // Search for the attribute's position, and then decide where to move to.
10272bde8e466a4451c7319e3a072d118917957d6554Steve Block            var attributes = this.representedObject.attributes();
1028dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            for (var i = 0; i < attributes.length; ++i) {
10290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                if (attributes[i].name === attributeName) {
10300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                    found = true;
1031dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    if (moveDirection === "backward") {
1032dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                        if (i === 0)
1033dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                            moveToTagName = true;
1034dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                        else
1035dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                            moveToAttribute = attributes[i - 1].name;
1036dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    } else if (moveDirection === "forward") {
1037dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                        if (i === attributes.length - 1)
1038dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                            moveToNewAttribute = true;
1039dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                        else
1040dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                            moveToAttribute = attributes[i + 1].name;
1041dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    }
10420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                }
10430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            }
10440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1045dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            // Moving From the "New Attribute" position.
1046dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (!found) {
1047dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                if (moveDirection === "backward" && attributes.length > 0)
1048dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    moveToAttribute = attributes[attributes.length - 1].name;
1049f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch                else if (moveDirection === "forward") {
1050f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch                    if (!/^\s*$/.test(newText))
1051f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch                        moveToNewAttribute = true;
1052f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch                    else
1053f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch                        moveToTagName = true;
1054f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch                }
1055dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
10560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
10570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1058dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        function moveToNextAttributeIfNeeded()
1059dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        {
1060dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            // Cleanup empty new attribute sections.
1061dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (element.textContent.trim().length === 0)
1062dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                element.parentNode.removeChild(element);
1063dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1064dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            // Make the move.
10650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            if (moveToAttribute)
10660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                this._triggerEditAttribute(moveToAttribute);
1067dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            else if (moveToNewAttribute)
1068dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                this._addNewAttribute();
1069dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            else if (moveToTagName)
1070dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                this._startEditingTagName();
1071dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1072dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1073dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        function regenerateStyledAttribute(name, value)
1074dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        {
1075dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            var previous = element.previousSibling;
1076dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (!previous || previous.nodeType !== Node.TEXT_NODE)
1077dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                element.parentNode.insertBefore(document.createTextNode(" "), element);
1078dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            element.outerHTML = this._attributeHTML(name, value);
10790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
10800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
10818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        var parseContainerElement = document.createElement("span");
10828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        parseContainerElement.innerHTML = "<span " + newText + "></span>";
10838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        var parseElement = parseContainerElement.firstChild;
10840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
10850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (!parseElement) {
10860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            this._editingCancelled(element, attributeName);
10870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            moveToNextAttributeIfNeeded.call(this);
10880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            return;
10890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
10900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
10910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (!parseElement.hasAttributes()) {
10922bde8e466a4451c7319e3a072d118917957d6554Steve Block            this.representedObject.removeAttribute(attributeName, this.updateTitle.bind(this));
1093cad810f21b803229eb11403f9209855525a25d57Steve Block            this.treeOutline.focusedNodeChanged(true);
10940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            moveToNextAttributeIfNeeded.call(this);
10958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
10968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
10978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        var foundOriginalAttribute = false;
10998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        for (var i = 0; i < parseElement.attributes.length; ++i) {
11008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            var attr = parseElement.attributes[i];
11018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            foundOriginalAttribute = foundOriginalAttribute || attr.name === attributeName;
11020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            try {
11032bde8e466a4451c7319e3a072d118917957d6554Steve Block                this.representedObject.setAttribute(attr.name, attr.value, this.updateTitle.bind(this));
1104dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                regenerateStyledAttribute.call(this, attr.name, attr.value);
11050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            } catch(e) {} // ignore invalid attribute (innerHTML doesn't throw errors, but this can)
11068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
11078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!foundOriginalAttribute)
11092bde8e466a4451c7319e3a072d118917957d6554Steve Block            this.representedObject.removeAttribute(attributeName, this.updateTitle.bind(this));
11108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        this.treeOutline.focusedNodeChanged(true);
11120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
11130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        moveToNextAttributeIfNeeded.call(this);
11148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
11158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1116dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    _tagNameEditingCommitted: function(element, newText, oldText, tagName, moveDirection)
1117dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    {
1118dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        delete this._editing;
1119dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        var self = this;
1120dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1121dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        function cancel()
1122dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        {
1123dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            var closingTagElement = self._distinctClosingTagElement();
1124dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (closingTagElement)
1125dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                closingTagElement.textContent = "</" + tagName + ">";
1126dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1127dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            self._editingCancelled(element, tagName);
1128dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            moveToNextAttributeIfNeeded.call(self);
1129dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1130dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1131dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        function moveToNextAttributeIfNeeded()
1132dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        {
1133f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            if (moveDirection !== "forward") {
1134f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch                this._addNewAttribute();
1135dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                return;
1136f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            }
1137dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
11382bde8e466a4451c7319e3a072d118917957d6554Steve Block            var attributes = this.representedObject.attributes();
1139dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (attributes.length > 0)
1140dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                this._triggerEditAttribute(attributes[0].name);
1141dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            else
1142dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                this._addNewAttribute();
1143dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1144dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1145dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        newText = newText.trim();
1146dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (newText === oldText) {
1147dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            cancel();
1148dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            return;
1149dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1150dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1151dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        var treeOutline = this.treeOutline;
1152dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        var wasExpanded = this.expanded;
1153dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
11542bde8e466a4451c7319e3a072d118917957d6554Steve Block        function changeTagNameCallback(error, nodeId)
1155dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        {
11562bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (error || !nodeId) {
1157dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                cancel();
1158dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                return;
1159dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
1160dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1161dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            // Select it and expand if necessary. We force tree update so that it processes dom events and is up to date.
1162dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            WebInspector.panels.elements.updateModifiedNodes();
1163dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1164dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            WebInspector.updateFocusedNode(nodeId);
1165dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            var newTreeItem = treeOutline.findTreeElement(WebInspector.domAgent.nodeForId(nodeId));
1166dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (wasExpanded)
1167dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                newTreeItem.expand();
1168dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1169dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            moveToNextAttributeIfNeeded.call(newTreeItem);
1170dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1171dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
11722bde8e466a4451c7319e3a072d118917957d6554Steve Block        this.representedObject.setNodeName(newText, changeTagNameCallback);
1173dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    },
1174dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
11758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    _textNodeEditingCommitted: function(element, newText)
11768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
11778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        delete this._editing;
11788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        var textNode;
11802bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (this.representedObject.nodeType() === Node.ELEMENT_NODE) {
11818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // We only show text nodes inline in elements if the element only
11828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // has a single child, and that child is a text node.
11838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            textNode = this.representedObject.firstChild;
11842bde8e466a4451c7319e3a072d118917957d6554Steve Block        } else if (this.representedObject.nodeType() == Node.TEXT_NODE)
11858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            textNode = this.representedObject;
11868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11872bde8e466a4451c7319e3a072d118917957d6554Steve Block        textNode.setNodeValue(newText, this.updateTitle.bind(this));
11888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
11898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    _editingCancelled: function(element, context)
11918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
11928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        delete this._editing;
11938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1194d0825bca7fe65beaee391d30da42e937db621564Steve Block        // Need to restore attributes structure.
1195d0825bca7fe65beaee391d30da42e937db621564Steve Block        this.updateTitle();
11968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
11978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1198dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    _distinctClosingTagElement: function()
1199dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    {
1200dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // FIXME: Improve the Tree Element / Outline Abstraction to prevent crawling the DOM
1201dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1202dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // For an expanded element, it will be the last element with class "close"
1203dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // in the child element list.
1204dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (this.expanded) {
1205dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            var closers = this._childrenListNode.querySelectorAll(".close");
1206dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            return closers[closers.length-1];
1207dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1208dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1209dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // Remaining cases are single line non-expanded elements with a closing
1210dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // tag, or HTML elements without a closing tag (such as <br>). Return
1211dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // null in the case where there isn't a closing tag.
1212dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        var tags = this.listItemElement.getElementsByClassName("webkit-html-tag");
1213dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return (tags.length === 1 ? null : tags[tags.length-1]);
1214dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    },
1215dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
121681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    updateTitle: function(onlySearchQueryChanged)
12178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    {
1218643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        // If we are editing, return early to prevent canceling the edit.
1219d0825bca7fe65beaee391d30da42e937db621564Steve Block        // After editing is committed updateTitle will be called.
1220643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        if (this._editing)
1221643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            return;
1222643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
122381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (onlySearchQueryChanged && this._normalHTML)
122481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            this.titleHTML = this._normalHTML;
122581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        else {
122681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            delete this._normalHTML;
122781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            this.titleHTML = "<span class=\"highlight\">" + this._nodeTitleInfo(WebInspector.linkifyURL).titleHTML + "</span>";
122881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        }
122981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
123021939df44de1705786c545cd1bf519d47250322dBen Murdoch        delete this.selectionElement;
123121939df44de1705786c545cd1bf519d47250322dBen Murdoch        this.updateSelection();
123221939df44de1705786c545cd1bf519d47250322dBen Murdoch        this._preventFollowingLinksOnDoubleClick();
123321939df44de1705786c545cd1bf519d47250322dBen Murdoch        this._highlightSearchResults();
12348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    },
1235231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
123621939df44de1705786c545cd1bf519d47250322dBen Murdoch    _attributeHTML: function(name, value, node, linkify)
1237dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    {
1238dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        var hasText = (value.length > 0);
1239dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        var html = "<span class=\"webkit-html-attribute\"><span class=\"webkit-html-attribute-name\">" + name.escapeHTML() + "</span>";
1240dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1241dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (hasText)
1242dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            html += "=&#8203;\"";
1243dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1244dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (linkify && (name === "src" || name === "href")) {
124568513a70bcd92384395513322f1b801e7bf9c729Steve Block            var rewrittenHref = WebInspector.resourceURLForRelatedNode(node, value);
1246dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            value = value.replace(/([\/;:\)\]\}])/g, "$1\u200B");
12472bde8e466a4451c7319e3a072d118917957d6554Steve Block            html += linkify(rewrittenHref, value, "webkit-html-attribute-value", node.nodeName().toLowerCase() === "a");
1248dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } else {
1249dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            value = value.escapeHTML().replace(/([\/;:\)\]\}])/g, "$1&#8203;");
1250dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            html += "<span class=\"webkit-html-attribute-value\">" + value + "</span>";
1251dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1252dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1253dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (hasText)
1254dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            html += "\"";
1255dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1256dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        html += "</span>";
1257dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return html;
1258dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    },
1259dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
126021939df44de1705786c545cd1bf519d47250322dBen Murdoch    _tagHTML: function(tagName, isClosingTag, isDistinctTreeElement, linkify)
1261dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    {
1262dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        var node = this.representedObject;
1263dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        var result = "<span class=\"webkit-html-tag" + (isClosingTag && isDistinctTreeElement ? " close" : "")  + "\">&lt;";
1264dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        result += "<span " + (isClosingTag ? "" : "class=\"webkit-html-tag-name\"") + ">" + (isClosingTag ? "/" : "") + tagName + "</span>";
1265dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (!isClosingTag && node.hasAttributes()) {
12662bde8e466a4451c7319e3a072d118917957d6554Steve Block            var attributes = node.attributes();
12672bde8e466a4451c7319e3a072d118917957d6554Steve Block            for (var i = 0; i < attributes.length; ++i) {
12682bde8e466a4451c7319e3a072d118917957d6554Steve Block                var attr = attributes[i];
126921939df44de1705786c545cd1bf519d47250322dBen Murdoch                result += " " + this._attributeHTML(attr.name, attr.value, node, linkify);
1270dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
1271dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1272dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        result += "&gt;</span>&#8203;";
1273dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1274dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return result;
1275dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    },
1276dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
127721939df44de1705786c545cd1bf519d47250322dBen Murdoch    _nodeTitleInfo: function(linkify)
1278231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    {
1279692e5dbf12901edacf14812a6fae25462920af42Steve Block        var node = this.representedObject;
12806b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        var info = {titleHTML: "", hasChildren: this.hasChildren};
1281dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
12822bde8e466a4451c7319e3a072d118917957d6554Steve Block        switch (node.nodeType()) {
1283231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            case Node.DOCUMENT_NODE:
12846b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                info.titleHTML = "Document";
1285231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                break;
1286dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
12878a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block            case Node.DOCUMENT_FRAGMENT_NODE:
12886b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                info.titleHTML = "Document Fragment";
12898a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block                break;
12908a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
12915ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            case Node.ATTRIBUTE_NODE:
12925ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                var value = node.value || "\u200B"; // Zero width space to force showing an empty value.
12936b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                info.titleHTML = this._attributeHTML(node.name, value);
12945ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                break;
12955ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1296231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            case Node.ELEMENT_NODE:
12972bde8e466a4451c7319e3a072d118917957d6554Steve Block                var tagName = this.treeOutline.nodeNameToCorrectCase(node.nodeName()).escapeHTML();
1298dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                if (this._elementCloseTag) {
12996b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                    info.titleHTML = this._tagHTML(tagName, true, true);
1300dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    info.hasChildren = false;
1301dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    break;
1302231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                }
1303dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
13046b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                var titleHTML = this._tagHTML(tagName, false, false, linkify);
1305dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
13062bde8e466a4451c7319e3a072d118917957d6554Steve Block                var textChild = this._singleTextChild(node);
13072bde8e466a4451c7319e3a072d118917957d6554Steve Block                var showInlineText = textChild && textChild.nodeValue().length < Preferences.maxInlineTextChildLength;
1308692e5dbf12901edacf14812a6fae25462920af42Steve Block
1309692e5dbf12901edacf14812a6fae25462920af42Steve Block                if (!this.expanded && (!showInlineText && (this.treeOutline.isXMLMimeType || !WebInspector.ElementsTreeElement.ForbiddenClosingTagElements[tagName]))) {
1310692e5dbf12901edacf14812a6fae25462920af42Steve Block                    if (this.hasChildren)
13116b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                        titleHTML += "<span class=\"webkit-html-text-node\">&#8230;</span>&#8203;";
13126b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                    titleHTML += this._tagHTML(tagName, true, false);
1313692e5dbf12901edacf14812a6fae25462920af42Steve Block                }
1314692e5dbf12901edacf14812a6fae25462920af42Steve Block
1315231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                // If this element only has a single child that is a text node,
1316231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                // just show that text and the closing tag inline rather than
1317231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                // create a subtree for them
1318231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                if (showInlineText) {
13192bde8e466a4451c7319e3a072d118917957d6554Steve Block                    titleHTML += "<span class=\"webkit-html-text-node\">" + textChild.nodeValue().escapeHTML() + "</span>&#8203;" + this._tagHTML(tagName, true, false);
1320231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                    info.hasChildren = false;
1321231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                }
13226b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                info.titleHTML = titleHTML;
1323231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                break;
1324dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1325231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            case Node.TEXT_NODE:
1326231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                if (isNodeWhitespace.call(node))
13276b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                    info.titleHTML = "(whitespace)";
1328231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                else {
13292bde8e466a4451c7319e3a072d118917957d6554Steve Block                    if (node.parentNode && node.parentNode.nodeName().toLowerCase() === "script") {
1330231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                        var newNode = document.createElement("span");
13312bde8e466a4451c7319e3a072d118917957d6554Steve Block                        newNode.textContent = node.nodeValue();
1332cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
1333d0825bca7fe65beaee391d30da42e937db621564Steve Block                        var javascriptSyntaxHighlighter = new WebInspector.DOMSyntaxHighlighter("text/javascript");
1334cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                        javascriptSyntaxHighlighter.syntaxHighlightNode(newNode);
1335dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
13366b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                        info.titleHTML = "<span class=\"webkit-html-text-node webkit-html-js-node\">" + newNode.innerHTML.replace(/^[\n\r]*/, "").replace(/\s*$/, "") + "</span>";
13372bde8e466a4451c7319e3a072d118917957d6554Steve Block                    } else if (node.parentNode && node.parentNode.nodeName().toLowerCase() === "style") {
1338231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                        var newNode = document.createElement("span");
13392bde8e466a4451c7319e3a072d118917957d6554Steve Block                        newNode.textContent = node.nodeValue();
1340dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1341d0825bca7fe65beaee391d30da42e937db621564Steve Block                        var cssSyntaxHighlighter = new WebInspector.DOMSyntaxHighlighter("text/css");
1342643ca7872b450ea4efacab6188849e5aac2ba161Steve Block                        cssSyntaxHighlighter.syntaxHighlightNode(newNode);
1343dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
13446b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                        info.titleHTML = "<span class=\"webkit-html-text-node webkit-html-css-node\">" + newNode.innerHTML.replace(/^[\n\r]*/, "").replace(/\s*$/, "") + "</span>";
13456b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                    } else
13462bde8e466a4451c7319e3a072d118917957d6554Steve Block                        info.titleHTML = "\"<span class=\"webkit-html-text-node\">" + node.nodeValue().escapeHTML() + "</span>\"";
1347dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                }
1348231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                break;
1349dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1350231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            case Node.COMMENT_NODE:
13512bde8e466a4451c7319e3a072d118917957d6554Steve Block                info.titleHTML = "<span class=\"webkit-html-comment\">&lt;!--" + node.nodeValue().escapeHTML() + "--&gt;</span>";
1352231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                break;
1353dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1354231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            case Node.DOCUMENT_TYPE_NODE:
13552bde8e466a4451c7319e3a072d118917957d6554Steve Block                var titleHTML = "<span class=\"webkit-html-doctype\">&lt;!DOCTYPE " + node.nodeName();
1356231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                if (node.publicId) {
13576b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                    titleHTML += " PUBLIC \"" + node.publicId + "\"";
1358231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                    if (node.systemId)
13596b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                        titleHTML += " \"" + node.systemId + "\"";
1360231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                } else if (node.systemId)
13616b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                    titleHTML += " SYSTEM \"" + node.systemId + "\"";
1362231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                if (node.internalSubset)
13636b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                    titleHTML += " [" + node.internalSubset + "]";
13646b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                titleHTML += "&gt;</span>";
13656b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                info.titleHTML = titleHTML;
1366231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                break;
1367db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
1368db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            case Node.CDATA_SECTION_NODE:
13692bde8e466a4451c7319e3a072d118917957d6554Steve Block                info.titleHTML = "<span class=\"webkit-html-text-node\">&lt;![CDATA[" + node.nodeValue().escapeHTML() + "]]&gt;</span>";
1370db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block                break;
1371231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            default:
13722bde8e466a4451c7319e3a072d118917957d6554Steve Block                info.titleHTML = this.treeOutline.nodeNameToCorrectCase(node.nodeName()).collapseWhitespace().escapeHTML();
1373231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
1374dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1375231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return info;
1376231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    },
1377231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
13782bde8e466a4451c7319e3a072d118917957d6554Steve Block    _singleTextChild: function(node)
13792bde8e466a4451c7319e3a072d118917957d6554Steve Block    {
13802bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (!node)
13812bde8e466a4451c7319e3a072d118917957d6554Steve Block            return null;
13822bde8e466a4451c7319e3a072d118917957d6554Steve Block
13832bde8e466a4451c7319e3a072d118917957d6554Steve Block        var firstChild = node.firstChild;
13842bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (!firstChild || firstChild.nodeType() !== Node.TEXT_NODE)
13852bde8e466a4451c7319e3a072d118917957d6554Steve Block            return null;
13862bde8e466a4451c7319e3a072d118917957d6554Steve Block
13872bde8e466a4451c7319e3a072d118917957d6554Steve Block        var sibling = firstChild.nextSibling;
13882bde8e466a4451c7319e3a072d118917957d6554Steve Block        return sibling ? null : firstChild;
13892bde8e466a4451c7319e3a072d118917957d6554Steve Block    },
13902bde8e466a4451c7319e3a072d118917957d6554Steve Block
1391231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    _showInlineText: function(node)
1392231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    {
13932bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (node.nodeType() === Node.ELEMENT_NODE) {
13942bde8e466a4451c7319e3a072d118917957d6554Steve Block            var textChild = this._singleTextChild(node);
13952bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (textChild && textChild.nodeValue().length < Preferences.maxInlineTextChildLength)
1396231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                return true;
1397231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
1398231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return false;
1399cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    },
1400dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1401cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    remove: function()
1402cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    {
1403cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        var parentElement = this.parent;
1404cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        if (!parentElement)
1405cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            return;
1406cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
1407cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        var self = this;
14082bde8e466a4451c7319e3a072d118917957d6554Steve Block        function removeNodeCallback(error, removedNodeId)
1409cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        {
14102bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (error)
1411cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                return;
1412cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
1413cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            parentElement.removeChild(self);
1414692e5dbf12901edacf14812a6fae25462920af42Steve Block            parentElement.adjustCollapsedRange(true);
1415cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        }
1416cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
14172bde8e466a4451c7319e3a072d118917957d6554Steve Block        this.representedObject.removeNode(removeNodeCallback);
1418d0825bca7fe65beaee391d30da42e937db621564Steve Block    },
1419d0825bca7fe65beaee391d30da42e937db621564Steve Block
1420d0825bca7fe65beaee391d30da42e937db621564Steve Block    _editAsHTML: function()
1421d0825bca7fe65beaee391d30da42e937db621564Steve Block    {
1422d0825bca7fe65beaee391d30da42e937db621564Steve Block        var treeOutline = this.treeOutline;
1423d0825bca7fe65beaee391d30da42e937db621564Steve Block        var node = this.representedObject;
1424d0825bca7fe65beaee391d30da42e937db621564Steve Block        var wasExpanded = this.expanded;
1425d0825bca7fe65beaee391d30da42e937db621564Steve Block
14262bde8e466a4451c7319e3a072d118917957d6554Steve Block        function selectNode(error, nodeId)
1427d0825bca7fe65beaee391d30da42e937db621564Steve Block        {
14282bde8e466a4451c7319e3a072d118917957d6554Steve Block            if (error || !nodeId)
1429d0825bca7fe65beaee391d30da42e937db621564Steve Block                return;
1430d0825bca7fe65beaee391d30da42e937db621564Steve Block
1431d0825bca7fe65beaee391d30da42e937db621564Steve Block            // Select it and expand if necessary. We force tree update so that it processes dom events and is up to date.
1432d0825bca7fe65beaee391d30da42e937db621564Steve Block            WebInspector.panels.elements.updateModifiedNodes();
1433d0825bca7fe65beaee391d30da42e937db621564Steve Block
1434d0825bca7fe65beaee391d30da42e937db621564Steve Block            WebInspector.updateFocusedNode(nodeId);
1435d0825bca7fe65beaee391d30da42e937db621564Steve Block            if (wasExpanded) {
1436d0825bca7fe65beaee391d30da42e937db621564Steve Block                var newTreeItem = treeOutline.findTreeElement(WebInspector.domAgent.nodeForId(nodeId));
1437d0825bca7fe65beaee391d30da42e937db621564Steve Block                if (newTreeItem)
1438d0825bca7fe65beaee391d30da42e937db621564Steve Block                    newTreeItem.expand();
1439d0825bca7fe65beaee391d30da42e937db621564Steve Block            }
1440d0825bca7fe65beaee391d30da42e937db621564Steve Block        }
1441d0825bca7fe65beaee391d30da42e937db621564Steve Block
1442d0825bca7fe65beaee391d30da42e937db621564Steve Block        function commitChange(value)
1443d0825bca7fe65beaee391d30da42e937db621564Steve Block        {
14442bde8e466a4451c7319e3a072d118917957d6554Steve Block            node.setOuterHTML(value, selectNode);
1445d0825bca7fe65beaee391d30da42e937db621564Steve Block        }
1446d0825bca7fe65beaee391d30da42e937db621564Steve Block
14472bde8e466a4451c7319e3a072d118917957d6554Steve Block        node.getOuterHTML(this._startEditingAsHTML.bind(this, commitChange));
1448d0825bca7fe65beaee391d30da42e937db621564Steve Block    },
1449d0825bca7fe65beaee391d30da42e937db621564Steve Block
1450d0825bca7fe65beaee391d30da42e937db621564Steve Block    _copyHTML: function()
1451d0825bca7fe65beaee391d30da42e937db621564Steve Block    {
14522bde8e466a4451c7319e3a072d118917957d6554Steve Block        this.representedObject.copyNode();
1453692e5dbf12901edacf14812a6fae25462920af42Steve Block    },
1454692e5dbf12901edacf14812a6fae25462920af42Steve Block
1455692e5dbf12901edacf14812a6fae25462920af42Steve Block    _highlightSearchResults: function()
1456692e5dbf12901edacf14812a6fae25462920af42Steve Block    {
1457692e5dbf12901edacf14812a6fae25462920af42Steve Block        if (!this._searchQuery)
1458692e5dbf12901edacf14812a6fae25462920af42Steve Block            return;
145981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (this._searchHighlightedHTML) {
146081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            this.listItemElement.innerHTML = this._searchHighlightedHTML;
146181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            return;
146281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        }
146381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
146481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (!this._normalHTML)
146581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            this._normalHTML = this.titleHTML;
146681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
1467692e5dbf12901edacf14812a6fae25462920af42Steve Block        var text = this.listItemElement.textContent;
146881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        var regexObject = createSearchRegex(this._searchQuery, "g");
1469692e5dbf12901edacf14812a6fae25462920af42Steve Block
1470692e5dbf12901edacf14812a6fae25462920af42Steve Block        var offset = 0;
1471692e5dbf12901edacf14812a6fae25462920af42Steve Block        var match = regexObject.exec(text);
147281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        var matchRanges = [];
1473692e5dbf12901edacf14812a6fae25462920af42Steve Block        while (match) {
147481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            matchRanges.push({ offset: match.index, length: match[0].length });
1475692e5dbf12901edacf14812a6fae25462920af42Steve Block            match = regexObject.exec(text);
1476692e5dbf12901edacf14812a6fae25462920af42Steve Block        }
14772bde8e466a4451c7319e3a072d118917957d6554Steve Block
14782bde8e466a4451c7319e3a072d118917957d6554Steve Block        // Fall back for XPath, etc. matches.
14792bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (!matchRanges.length)
14802bde8e466a4451c7319e3a072d118917957d6554Steve Block            matchRanges.push({ offset: 0, length: text.length });
14812bde8e466a4451c7319e3a072d118917957d6554Steve Block
148281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        highlightSearchResults(this.listItemElement, matchRanges);
148381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        this._searchHighlightedHTML = this.listItemElement.innerHTML;
1484231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
14858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
14868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
14878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectWebInspector.ElementsTreeElement.prototype.__proto__ = TreeElement.prototype;
1488