<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[203114] trunk/Source/WebInspectorUI</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/203114">203114</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2016-07-12 06:05:13 -0700 (Tue, 12 Jul 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Web Inspector: Use separate files for TreeOutline/TreeElement and DataGrid/DataGridNode
https://bugs.webkit.org/show_bug.cgi?id=159659

Patch by Joseph Pecoraro &lt;pecoraro@apple.com&gt; on 2016-07-12
Reviewed by Timothy Hatcher.

* UserInterface/Main.html:
* UserInterface/Views/DataGrid.js:
* UserInterface/Views/DataGridNode.js: Added.
* UserInterface/Views/TreeElement.js: Added.
* UserInterface/Views/TreeOutline.js:
Extra the component classes to their own file.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceMainhtml">trunk/Source/WebInspectorUI/UserInterface/Main.html</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsDataGridjs">trunk/Source/WebInspectorUI/UserInterface/Views/DataGrid.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsTreeOutlinejs">trunk/Source/WebInspectorUI/UserInterface/Views/TreeOutline.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsDataGridNodejs">trunk/Source/WebInspectorUI/UserInterface/Views/DataGridNode.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsTreeElementjs">trunk/Source/WebInspectorUI/UserInterface/Views/TreeElement.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (203113 => 203114)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2016-07-12 13:04:38 UTC (rev 203113)
+++ trunk/Source/WebInspectorUI/ChangeLog        2016-07-12 13:05:13 UTC (rev 203114)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2016-07-12  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
+
+        Web Inspector: Use separate files for TreeOutline/TreeElement and DataGrid/DataGridNode
+        https://bugs.webkit.org/show_bug.cgi?id=159659
+
+        Reviewed by Timothy Hatcher.
+
+        * UserInterface/Main.html:
+        * UserInterface/Views/DataGrid.js:
+        * UserInterface/Views/DataGridNode.js: Added.
+        * UserInterface/Views/TreeElement.js: Added.
+        * UserInterface/Views/TreeOutline.js:
+        Extra the component classes to their own file.
+
</ins><span class="cx"> 2016-07-11  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: ProfileView sometimes shows Top Functions data despite Top Functions being disabled
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceMainhtml"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (203113 => 203114)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Main.html        2016-07-12 13:04:38 UTC (rev 203113)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html        2016-07-12 13:05:13 UTC (rev 203114)
</span><span class="lines">@@ -386,13 +386,14 @@
</span><span class="cx">     &lt;script src=&quot;Proxies/HeapSnapshotWorkerProxy.js&quot;&gt;&lt;/script&gt;
</span><span class="cx"> 
</span><span class="cx">     &lt;script src=&quot;Views/View.js&quot;&gt;&lt;/script&gt;
</span><del>-    &lt;script src=&quot;Views/Dialog.js&quot;&gt;&lt;/script&gt;
</del><span class="cx"> 
</span><span class="cx">     &lt;script src=&quot;Views/ConsoleCommandView.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Views/ConsoleMessageView.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Views/ContentView.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Views/DataGrid.js&quot;&gt;&lt;/script&gt;
</span><ins>+    &lt;script src=&quot;Views/DataGridNode.js&quot;&gt;&lt;/script&gt;
</ins><span class="cx">     &lt;script src=&quot;Views/DetailsSectionRow.js&quot;&gt;&lt;/script&gt;
</span><ins>+    &lt;script src=&quot;Views/Dialog.js&quot;&gt;&lt;/script&gt;
</ins><span class="cx">     &lt;script src=&quot;Views/HierarchicalPathComponent.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Views/NavigationItem.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Views/SidebarPanel.js&quot;&gt;&lt;/script&gt;
</span><span class="lines">@@ -403,6 +404,7 @@
</span><span class="cx">     &lt;script src=&quot;Views/TextEditor.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Views/TimelineOverviewGraph.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Views/TimelineView.js&quot;&gt;&lt;/script&gt;
</span><ins>+    &lt;script src=&quot;Views/TreeElement.js&quot;&gt;&lt;/script&gt;
</ins><span class="cx">     &lt;script src=&quot;Views/TreeOutline.js&quot;&gt;&lt;/script&gt;
</span><span class="cx"> 
</span><span class="cx">     &lt;script src=&quot;Views/ButtonNavigationItem.js&quot;&gt;&lt;/script&gt;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsDataGridjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DataGrid.js (203113 => 203114)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/DataGrid.js        2016-07-12 13:04:38 UTC (rev 203113)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DataGrid.js        2016-07-12 13:05:13 UTC (rev 203114)
</span><span class="lines">@@ -1,26 +1,26 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008, 2013-2015 Apple Inc. All Rights Reserved.
</del><ins>+ * Copyright (C) 2008, 2013-2016 Apple Inc. All Rights Reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="cx">  * are met:
</span><span class="cx">  * 1. Redistributions of source code must retain the above copyright
</span><del>- *        notice, this list of conditions and the following disclaimer.
</del><ins>+ *    notice, this list of conditions and the following disclaimer.
</ins><span class="cx">  * 2. Redistributions in binary form must reproduce the above copyright
</span><del>- *        notice, this list of conditions and the following disclaimer in the
- *        documentation and/or other materials provided with the distribution.
</del><ins>+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
</ins><span class="cx">  *
</span><del>- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.         IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</del><ins>+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
</ins><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> WebInspector.DataGrid = class DataGrid extends WebInspector.View
</span><span class="lines">@@ -962,7 +962,7 @@
</span><span class="cx">                 resizer = this.resizers[i] = new WebInspector.Resizer(WebInspector.Resizer.RuleOrientation.Vertical, this);
</span><span class="cx">                 this.element.appendChild(resizer.element);
</span><span class="cx">             }
</span><del>-            
</del><ins>+
</ins><span class="cx">             left = columnWidths[i];
</span><span class="cx"> 
</span><span class="cx">             if (this._isColumnVisible(this.orderedColumns[i])) {
</span><span class="lines">@@ -1916,729 +1916,3 @@
</span><span class="cx"> WebInspector.DataGrid.SortColumnAscendingStyleClassName = &quot;sort-ascending&quot;;
</span><span class="cx"> WebInspector.DataGrid.SortColumnDescendingStyleClassName = &quot;sort-descending&quot;;
</span><span class="cx"> WebInspector.DataGrid.SortableColumnStyleClassName = &quot;sortable&quot;;
</span><del>-
-WebInspector.DataGridNode = class DataGridNode extends WebInspector.Object
-{
-    constructor(data, hasChildren)
-    {
-        super();
-
-        this._expanded = false;
-        this._hidden = false;
-        this._selected = false;
-        this._copyable = true;
-        this._shouldRefreshChildren = true;
-        this._data = data || {};
-        this.hasChildren = hasChildren || false;
-        this.children = [];
-        this.dataGrid = null;
-        this.parent = null;
-        this.previousSibling = null;
-        this.nextSibling = null;
-        this.disclosureToggleWidth = 10;
-    }
-
-    get hidden()
-    {
-        return this._hidden;
-    }
-
-    set hidden(x)
-    {
-        x = !!x;
-
-        if (this._hidden === x)
-            return;
-
-        this._hidden = x;
-        if (this._element)
-            this._element.classList.toggle(&quot;hidden&quot;, this._hidden);
-
-        if (this.dataGrid)
-            this.dataGrid._noteRowsChanged();
-    }
-
-    get selectable()
-    {
-        return this._element &amp;&amp; !this._hidden;
-    }
-
-    get copyable()
-    {
-        return this._copyable;
-    }
-
-    set copyable(x)
-    {
-        this._copyable = x;
-    }
-
-    get element()
-    {
-        if (this._element)
-            return this._element;
-
-        if (!this.dataGrid)
-            return null;
-
-        this._element = document.createElement(&quot;tr&quot;);
-        this._element._dataGridNode = this;
-
-        if (this.hasChildren)
-            this._element.classList.add(&quot;parent&quot;);
-        if (this.expanded)
-            this._element.classList.add(&quot;expanded&quot;);
-        if (this.selected)
-            this._element.classList.add(&quot;selected&quot;);
-        if (this.revealed)
-            this._element.classList.add(&quot;revealed&quot;);
-        if (this._hidden)
-            this._element.classList.add(&quot;hidden&quot;);
-
-        this.createCells();
-        return this._element;
-    }
-
-    createCells()
-    {
-        for (var columnIdentifier of this.dataGrid.orderedColumns)
-            this._element.appendChild(this.createCell(columnIdentifier));
-    }
-
-    refreshIfNeeded()
-    {
-        if (!this._needsRefresh)
-            return;
-
-        this._needsRefresh = false;
-
-        this.refresh();
-    }
-
-    needsRefresh()
-    {
-        this._needsRefresh = true;
-
-        if (!this._revealed)
-            return;
-
-        if (this._scheduledRefreshIdentifier)
-            return;
-
-        this._scheduledRefreshIdentifier = requestAnimationFrame(this.refresh.bind(this));
-    }
-
-    get data()
-    {
-        return this._data;
-    }
-
-    set data(x)
-    {
-        console.assert(typeof x === &quot;object&quot;, &quot;Data should be an object.&quot;);
-
-        x = x || {};
-
-        if (Object.shallowEqual(this._data, x))
-            return;
-
-        this._data = x;
-        this.needsRefresh();
-    }
-
-    get filterableData()
-    {
-        if (this._cachedFilterableData)
-            return this._cachedFilterableData;
-
-        this._cachedFilterableData = [];
-
-        for (let column of this.dataGrid.columns.values()) {
-            if (column.hidden)
-                continue;
-
-            let value = this.filterableDataForColumn(column.columnIdentifier);
-            if (!value)
-                continue;
-
-            if (!(value instanceof Array))
-                value = [value];
-
-            if (!value.length)
-                continue;
-
-            this._cachedFilterableData = this._cachedFilterableData.concat(value);
-        }
-
-        return this._cachedFilterableData;
-    }
-
-    get revealed()
-    {
-        if (&quot;_revealed&quot; in this)
-            return this._revealed;
-
-        var currentAncestor = this.parent;
-        while (currentAncestor &amp;&amp; !currentAncestor.root) {
-            if (!currentAncestor.expanded) {
-                this._revealed = false;
-                return false;
-            }
-
-            currentAncestor = currentAncestor.parent;
-        }
-
-        this._revealed = true;
-        return true;
-    }
-
-    set hasChildren(x)
-    {
-        if (this._hasChildren === x)
-            return;
-
-        this._hasChildren = x;
-
-        if (!this._element)
-            return;
-
-        if (this._hasChildren) {
-            this._element.classList.add(&quot;parent&quot;);
-            if (this.expanded)
-                this._element.classList.add(&quot;expanded&quot;);
-        } else
-            this._element.classList.remove(&quot;parent&quot;, &quot;expanded&quot;);
-    }
-
-    get hasChildren()
-    {
-        return this._hasChildren;
-    }
-
-    set revealed(x)
-    {
-        if (this._revealed === x)
-            return;
-
-        this._revealed = x;
-
-        if (this._element) {
-            if (this._revealed)
-                this._element.classList.add(&quot;revealed&quot;);
-            else
-                this._element.classList.remove(&quot;revealed&quot;);
-        }
-
-        this.refreshIfNeeded();
-
-        for (var i = 0; i &lt; this.children.length; ++i)
-            this.children[i].revealed = x &amp;&amp; this.expanded;
-    }
-
-    get depth()
-    {
-        if (&quot;_depth&quot; in this)
-            return this._depth;
-        if (this.parent &amp;&amp; !this.parent.root)
-            this._depth = this.parent.depth + 1;
-        else
-            this._depth = 0;
-        return this._depth;
-    }
-
-    get leftPadding()
-    {
-        if (typeof(this._leftPadding) === &quot;number&quot;)
-            return this._leftPadding;
-
-        this._leftPadding = this.depth * this.dataGrid.indentWidth;
-        return this._leftPadding;
-    }
-
-    get shouldRefreshChildren()
-    {
-        return this._shouldRefreshChildren;
-    }
-
-    set shouldRefreshChildren(x)
-    {
-        this._shouldRefreshChildren = x;
-        if (x &amp;&amp; this.expanded)
-            this.expand();
-    }
-
-    get selected()
-    {
-        return this._selected;
-    }
-
-    set selected(x)
-    {
-        if (x)
-            this.select();
-        else
-            this.deselect();
-    }
-
-    get expanded()
-    {
-        return this._expanded;
-    }
-
-    set expanded(x)
-    {
-        if (x)
-            this.expand();
-        else
-            this.collapse();
-    }
-
-    hasAncestor(ancestor)
-    {
-        if (!ancestor)
-            return false;
-
-        let currentAncestor = this.parent;
-        while (currentAncestor) {
-            if (ancestor === currentAncestor)
-                return true;
-
-            currentAncestor = currentAncestor.parent;
-        }
-
-        return false;
-    }
-
-    refresh()
-    {
-        if (!this._element || !this.dataGrid)
-            return;
-
-        if (this._scheduledRefreshIdentifier) {
-            cancelAnimationFrame(this._scheduledRefreshIdentifier);
-            this._scheduledRefreshIdentifier = undefined;
-        }
-
-        this._cachedFilterableData = null;
-        this._needsRefresh = false;
-
-        this._element.removeChildren();
-        this.createCells();
-    }
-
-    refreshRecursively()
-    {
-        this.refresh();
-        this.forEachChildInSubtree((node) =&gt; node.refresh());
-    }
-
-    updateLayout()
-    {
-        // Implemented by subclasses if needed.
-    }
-
-    createCell(columnIdentifier)
-    {
-        var cellElement = document.createElement(&quot;td&quot;);
-        cellElement.className = columnIdentifier + &quot;-column&quot;;
-        cellElement.__columnIdentifier = columnIdentifier;
-
-        var column = this.dataGrid.columns.get(columnIdentifier);
-
-        if (column[&quot;aligned&quot;])
-            cellElement.classList.add(column[&quot;aligned&quot;]);
-
-        if (column[&quot;group&quot;])
-            cellElement.classList.add(&quot;column-group-&quot; + column[&quot;group&quot;]);
-
-        var div = cellElement.createChild(&quot;div&quot;, &quot;cell-content&quot;);
-        var content = this.createCellContent(columnIdentifier, cellElement);
-        div.append(content);
-
-        if (column[&quot;icon&quot;]) {
-            let iconElement = document.createElement(&quot;div&quot;);
-            iconElement.classList.add(&quot;icon&quot;);
-            div.insertBefore(iconElement, div.firstChild);
-        }
-
-        if (columnIdentifier === this.dataGrid.disclosureColumnIdentifier) {
-            cellElement.classList.add(&quot;disclosure&quot;);
-            if (this.leftPadding)
-                cellElement.style.setProperty(&quot;padding-left&quot;, this.leftPadding + &quot;px&quot;);
-        }
-
-        return cellElement;
-    }
-
-    createCellContent(columnIdentifier)
-    {
-        return this.data[columnIdentifier] || &quot;\u200b&quot;; // Zero width space to keep the cell from collapsing.
-    }
-
-    elementWithColumnIdentifier(columnIdentifier)
-    {
-        if (!this.dataGrid)
-            return null;
-
-        let index = this.dataGrid.orderedColumns.indexOf(columnIdentifier);
-        if (index === -1)
-            return null;
-
-        return this.element.children[index];
-    }
-
-    // Share these functions with DataGrid. They are written to work with a DataGridNode this object.
-    appendChild() { return WebInspector.DataGrid.prototype.appendChild.apply(this, arguments); }
-    insertChild() { return WebInspector.DataGrid.prototype.insertChild.apply(this, arguments); }
-    removeChild() { return WebInspector.DataGrid.prototype.removeChild.apply(this, arguments); }
-    removeChildren() { return WebInspector.DataGrid.prototype.removeChildren.apply(this, arguments); }
-    removeChildrenRecursive() { return WebInspector.DataGrid.prototype.removeChildrenRecursive.apply(this, arguments); }
-
-    _recalculateSiblings(myIndex)
-    {
-        if (!this.parent)
-            return;
-
-        var previousChild = (myIndex &gt; 0 ? this.parent.children[myIndex - 1] : null);
-
-        if (previousChild) {
-            previousChild.nextSibling = this;
-            this.previousSibling = previousChild;
-        } else
-            this.previousSibling = null;
-
-        var nextChild = this.parent.children[myIndex + 1];
-
-        if (nextChild) {
-            nextChild.previousSibling = this;
-            this.nextSibling = nextChild;
-        } else
-            this.nextSibling = null;
-    }
-
-    collapse()
-    {
-        if (this._element)
-            this._element.classList.remove(&quot;expanded&quot;);
-
-        this._expanded = false;
-
-        for (var i = 0; i &lt; this.children.length; ++i)
-            this.children[i].revealed = false;
-
-        this.dispatchEventToListeners(&quot;collapsed&quot;);
-
-        if (this.dataGrid) {
-            this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Event.CollapsedNode, {dataGridNode: this});
-            this.dataGrid._noteRowsChanged();
-        }
-    }
-
-    collapseRecursively()
-    {
-        var item = this;
-        while (item) {
-            if (item.expanded)
-                item.collapse();
-            item = item.traverseNextNode(false, this, true);
-        }
-    }
-
-    expand()
-    {
-        if (!this.hasChildren || this.expanded)
-            return;
-
-        if (this.revealed &amp;&amp; !this._shouldRefreshChildren)
-            for (var i = 0; i &lt; this.children.length; ++i)
-                this.children[i].revealed = true;
-
-        if (this._shouldRefreshChildren) {
-            for (var i = 0; i &lt; this.children.length; ++i)
-                this.children[i]._detach();
-
-            this.dispatchEventToListeners(&quot;populate&quot;);
-
-            if (this._attached) {
-                for (var i = 0; i &lt; this.children.length; ++i) {
-                    var child = this.children[i];
-                    if (this.revealed)
-                        child.revealed = true;
-                    child._attach();
-                }
-            }
-
-            this._shouldRefreshChildren = false;
-        }
-
-        if (this._element)
-            this._element.classList.add(&quot;expanded&quot;);
-
-        this._expanded = true;
-
-        this.dispatchEventToListeners(&quot;expanded&quot;);
-
-        if (this.dataGrid) {
-            this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Event.ExpandedNode, {dataGridNode: this});
-            this.dataGrid._noteRowsChanged();
-        }
-    }
-
-    expandRecursively()
-    {
-        var item = this;
-        while (item) {
-            item.expand();
-            item = item.traverseNextNode(false, this);
-        }
-    }
-
-    forEachImmediateChild(callback)
-    {
-        for (let node of this.children)
-            callback(node);
-    }
-
-    forEachChildInSubtree(callback)
-    {
-        let node = this.traverseNextNode(false, this, true);
-        while (node) {
-            callback(node);
-            node = node.traverseNextNode(false, this, true);
-        }
-    }
-
-    isInSubtreeOfNode(baseNode)
-    {
-        let node = baseNode;
-        while (node) {
-            if (node === this)
-                return true;
-            node = node.traverseNextNode(false, baseNode, true);
-        }
-        return false;
-    }
-
-    reveal()
-    {
-        var currentAncestor = this.parent;
-        while (currentAncestor &amp;&amp; !currentAncestor.root) {
-            if (!currentAncestor.expanded)
-                currentAncestor.expand();
-            currentAncestor = currentAncestor.parent;
-        }
-
-        this.element.scrollIntoViewIfNeeded(false);
-
-        this.dispatchEventToListeners(&quot;revealed&quot;);
-    }
-
-    select(suppressSelectedEvent)
-    {
-        if (!this.dataGrid || !this.selectable || this.selected)
-            return;
-
-        let oldSelectedNode = this.dataGrid.selectedNode;
-        if (oldSelectedNode)
-            oldSelectedNode.deselect(true);
-
-        this._selected = true;
-        this.dataGrid.selectedNode = this;
-
-        if (this._element)
-            this._element.classList.add(&quot;selected&quot;);
-
-        if (!suppressSelectedEvent)
-            this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Event.SelectedNodeChanged, {oldSelectedNode});
-    }
-
-    revealAndSelect()
-    {
-        this.reveal();
-        this.select();
-    }
-
-    deselect(suppressDeselectedEvent)
-    {
-        if (!this.dataGrid || this.dataGrid.selectedNode !== this || !this.selected)
-            return;
-
-        this._selected = false;
-        this.dataGrid.selectedNode = null;
-
-        if (this._element)
-            this._element.classList.remove(&quot;selected&quot;);
-
-        if (!suppressDeselectedEvent)
-            this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Event.SelectedNodeChanged, {oldSelectedNode: this});
-    }
-
-    traverseNextNode(skipHidden, stayWithin, dontPopulate, info)
-    {
-        if (!dontPopulate &amp;&amp; this.hasChildren)
-            this.dispatchEventToListeners(&quot;populate&quot;);
-
-        if (info)
-            info.depthChange = 0;
-
-        var node = (!skipHidden || this.revealed) ? this.children[0] : null;
-        if (node &amp;&amp; (!skipHidden || this.expanded)) {
-            if (info)
-                info.depthChange = 1;
-            return node;
-        }
-
-        if (this === stayWithin)
-            return null;
-
-        node = (!skipHidden || this.revealed) ? this.nextSibling : null;
-        if (node)
-            return node;
-
-        node = this;
-        while (node &amp;&amp; !node.root &amp;&amp; !((!skipHidden || node.revealed) ? node.nextSibling : null) &amp;&amp; node.parent !== stayWithin) {
-            if (info)
-                info.depthChange -= 1;
-            node = node.parent;
-        }
-
-        if (!node)
-            return null;
-
-        return (!skipHidden || node.revealed) ? node.nextSibling : null;
-    }
-
-    traversePreviousNode(skipHidden, dontPopulate)
-    {
-        var node = (!skipHidden || this.revealed) ? this.previousSibling : null;
-        if (!dontPopulate &amp;&amp; node &amp;&amp; node.hasChildren)
-            node.dispatchEventToListeners(&quot;populate&quot;);
-
-        while (node &amp;&amp; ((!skipHidden || (node.revealed &amp;&amp; node.expanded)) ? node.children.lastValue : null)) {
-            if (!dontPopulate &amp;&amp; node.hasChildren)
-                node.dispatchEventToListeners(&quot;populate&quot;);
-            node = ((!skipHidden || (node.revealed &amp;&amp; node.expanded)) ? node.children.lastValue : null);
-        }
-
-        if (node)
-            return node;
-
-        if (!this.parent || this.parent.root)
-            return null;
-
-        return this.parent;
-    }
-
-    isEventWithinDisclosureTriangle(event)
-    {
-        if (!this.hasChildren)
-            return false;
-        let cell = event.target.enclosingNodeOrSelfWithNodeName(&quot;td&quot;);
-        if (!cell || !cell.classList.contains(&quot;disclosure&quot;))
-            return false;
-
-        let computedLeftPadding = window.getComputedStyle(cell).getPropertyCSSValue(&quot;padding-left&quot;).getFloatValue(CSSPrimitiveValue.CSS_PX);
-        let left = cell.totalOffsetLeft + computedLeftPadding;
-        return event.pageX &gt;= left &amp;&amp; event.pageX &lt;= left + this.disclosureToggleWidth;
-    }
-
-    _attach()
-    {
-        if (!this.dataGrid || this._attached)
-            return;
-
-        this._attached = true;
-
-        let insertionIndex = -1;
-
-        if (!this.isPlaceholderNode) {
-            var previousGridNode = this.traversePreviousNode(true, true);
-            insertionIndex = this.dataGrid._rows.indexOf(previousGridNode);
-            if (insertionIndex === -1)
-                insertionIndex = 0;
-            else
-                insertionIndex++;
-        }
-
-        if (insertionIndex === -1)
-            this.dataGrid._rows.push(this);
-        else
-            this.dataGrid._rows.insertAtIndex(this, insertionIndex);
-
-        this.dataGrid._noteRowsChanged();
-
-        if (this.expanded) {
-            for (var i = 0; i &lt; this.children.length; ++i)
-                this.children[i]._attach();
-        }
-    }
-
-    _detach()
-    {
-        if (!this._attached)
-            return;
-
-        this._attached = false;
-
-        this.dataGrid._rows.remove(this, true);
-        this.dataGrid._noteRowRemoved(this);
-
-        for (var i = 0; i &lt; this.children.length; ++i)
-            this.children[i]._detach();
-    }
-
-    savePosition()
-    {
-        if (this._savedPosition)
-            return;
-
-        console.assert(this.parent);
-        if (!this.parent)
-            return;
-
-        this._savedPosition = {
-            parent: this.parent,
-            index: this.parent.children.indexOf(this)
-        };
-    }
-
-    restorePosition()
-    {
-        if (!this._savedPosition)
-            return;
-
-        if (this.parent !== this._savedPosition.parent)
-            this._savedPosition.parent.insertChild(this, this._savedPosition.index);
-
-        this._savedPosition = null;
-    }
-
-    appendContextMenuItems(contextMenu)
-    {
-        // Subclasses may override
-        return null;
-    }
-
-    // Protected
-
-    filterableDataForColumn(columnIdentifier)
-    {
-        let value = this.data[columnIdentifier];
-        return typeof value === &quot;string&quot; ? value : null;
-    }
-};
-
-// Used to create a new table row when entering new data by editing cells.
-WebInspector.PlaceholderDataGridNode = class PlaceholderDataGridNode extends WebInspector.DataGridNode
-{
-    constructor(data)
-    {
-        super(data, false);
-        this.isPlaceholderNode = true;
-    }
-
-    makeNormal()
-    {
-        this.isPlaceholderNode = false;
-    }
-};
</del></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsDataGridNodejs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Views/DataGridNode.js (0 => 203114)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/DataGridNode.js                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DataGridNode.js        2016-07-12 13:05:13 UTC (rev 203114)
</span><span class="lines">@@ -0,0 +1,750 @@
</span><ins>+/*
+ * Copyright (C) 2008, 2013-2016 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.DataGridNode = class DataGridNode extends WebInspector.Object
+{
+    constructor(data, hasChildren)
+    {
+        super();
+
+        this._expanded = false;
+        this._hidden = false;
+        this._selected = false;
+        this._copyable = true;
+        this._shouldRefreshChildren = true;
+        this._data = data || {};
+        this.hasChildren = hasChildren || false;
+        this.children = [];
+        this.dataGrid = null;
+        this.parent = null;
+        this.previousSibling = null;
+        this.nextSibling = null;
+        this.disclosureToggleWidth = 10;
+    }
+
+    get hidden()
+    {
+        return this._hidden;
+    }
+
+    set hidden(x)
+    {
+        x = !!x;
+
+        if (this._hidden === x)
+            return;
+
+        this._hidden = x;
+        if (this._element)
+            this._element.classList.toggle(&quot;hidden&quot;, this._hidden);
+
+        if (this.dataGrid)
+            this.dataGrid._noteRowsChanged();
+    }
+
+    get selectable()
+    {
+        return this._element &amp;&amp; !this._hidden;
+    }
+
+    get copyable()
+    {
+        return this._copyable;
+    }
+
+    set copyable(x)
+    {
+        this._copyable = x;
+    }
+
+    get element()
+    {
+        if (this._element)
+            return this._element;
+
+        if (!this.dataGrid)
+            return null;
+
+        this._element = document.createElement(&quot;tr&quot;);
+        this._element._dataGridNode = this;
+
+        if (this.hasChildren)
+            this._element.classList.add(&quot;parent&quot;);
+        if (this.expanded)
+            this._element.classList.add(&quot;expanded&quot;);
+        if (this.selected)
+            this._element.classList.add(&quot;selected&quot;);
+        if (this.revealed)
+            this._element.classList.add(&quot;revealed&quot;);
+        if (this._hidden)
+            this._element.classList.add(&quot;hidden&quot;);
+
+        this.createCells();
+        return this._element;
+    }
+
+    createCells()
+    {
+        for (var columnIdentifier of this.dataGrid.orderedColumns)
+            this._element.appendChild(this.createCell(columnIdentifier));
+    }
+
+    refreshIfNeeded()
+    {
+        if (!this._needsRefresh)
+            return;
+
+        this._needsRefresh = false;
+
+        this.refresh();
+    }
+
+    needsRefresh()
+    {
+        this._needsRefresh = true;
+
+        if (!this._revealed)
+            return;
+
+        if (this._scheduledRefreshIdentifier)
+            return;
+
+        this._scheduledRefreshIdentifier = requestAnimationFrame(this.refresh.bind(this));
+    }
+
+    get data()
+    {
+        return this._data;
+    }
+
+    set data(x)
+    {
+        console.assert(typeof x === &quot;object&quot;, &quot;Data should be an object.&quot;);
+
+        x = x || {};
+
+        if (Object.shallowEqual(this._data, x))
+            return;
+
+        this._data = x;
+        this.needsRefresh();
+    }
+
+    get filterableData()
+    {
+        if (this._cachedFilterableData)
+            return this._cachedFilterableData;
+
+        this._cachedFilterableData = [];
+
+        for (let column of this.dataGrid.columns.values()) {
+            if (column.hidden)
+                continue;
+
+            let value = this.filterableDataForColumn(column.columnIdentifier);
+            if (!value)
+                continue;
+
+            if (!(value instanceof Array))
+                value = [value];
+
+            if (!value.length)
+                continue;
+
+            this._cachedFilterableData = this._cachedFilterableData.concat(value);
+        }
+
+        return this._cachedFilterableData;
+    }
+
+    get revealed()
+    {
+        if (&quot;_revealed&quot; in this)
+            return this._revealed;
+
+        var currentAncestor = this.parent;
+        while (currentAncestor &amp;&amp; !currentAncestor.root) {
+            if (!currentAncestor.expanded) {
+                this._revealed = false;
+                return false;
+            }
+
+            currentAncestor = currentAncestor.parent;
+        }
+
+        this._revealed = true;
+        return true;
+    }
+
+    set hasChildren(x)
+    {
+        if (this._hasChildren === x)
+            return;
+
+        this._hasChildren = x;
+
+        if (!this._element)
+            return;
+
+        if (this._hasChildren) {
+            this._element.classList.add(&quot;parent&quot;);
+            if (this.expanded)
+                this._element.classList.add(&quot;expanded&quot;);
+        } else
+            this._element.classList.remove(&quot;parent&quot;, &quot;expanded&quot;);
+    }
+
+    get hasChildren()
+    {
+        return this._hasChildren;
+    }
+
+    set revealed(x)
+    {
+        if (this._revealed === x)
+            return;
+
+        this._revealed = x;
+
+        if (this._element) {
+            if (this._revealed)
+                this._element.classList.add(&quot;revealed&quot;);
+            else
+                this._element.classList.remove(&quot;revealed&quot;);
+        }
+
+        this.refreshIfNeeded();
+
+        for (var i = 0; i &lt; this.children.length; ++i)
+            this.children[i].revealed = x &amp;&amp; this.expanded;
+    }
+
+    get depth()
+    {
+        if (&quot;_depth&quot; in this)
+            return this._depth;
+        if (this.parent &amp;&amp; !this.parent.root)
+            this._depth = this.parent.depth + 1;
+        else
+            this._depth = 0;
+        return this._depth;
+    }
+
+    get leftPadding()
+    {
+        if (typeof(this._leftPadding) === &quot;number&quot;)
+            return this._leftPadding;
+
+        this._leftPadding = this.depth * this.dataGrid.indentWidth;
+        return this._leftPadding;
+    }
+
+    get shouldRefreshChildren()
+    {
+        return this._shouldRefreshChildren;
+    }
+
+    set shouldRefreshChildren(x)
+    {
+        this._shouldRefreshChildren = x;
+        if (x &amp;&amp; this.expanded)
+            this.expand();
+    }
+
+    get selected()
+    {
+        return this._selected;
+    }
+
+    set selected(x)
+    {
+        if (x)
+            this.select();
+        else
+            this.deselect();
+    }
+
+    get expanded()
+    {
+        return this._expanded;
+    }
+
+    set expanded(x)
+    {
+        if (x)
+            this.expand();
+        else
+            this.collapse();
+    }
+
+    hasAncestor(ancestor)
+    {
+        if (!ancestor)
+            return false;
+
+        let currentAncestor = this.parent;
+        while (currentAncestor) {
+            if (ancestor === currentAncestor)
+                return true;
+
+            currentAncestor = currentAncestor.parent;
+        }
+
+        return false;
+    }
+
+    refresh()
+    {
+        if (!this._element || !this.dataGrid)
+            return;
+
+        if (this._scheduledRefreshIdentifier) {
+            cancelAnimationFrame(this._scheduledRefreshIdentifier);
+            this._scheduledRefreshIdentifier = undefined;
+        }
+
+        this._cachedFilterableData = null;
+        this._needsRefresh = false;
+
+        this._element.removeChildren();
+        this.createCells();
+    }
+
+    refreshRecursively()
+    {
+        this.refresh();
+        this.forEachChildInSubtree((node) =&gt; node.refresh());
+    }
+
+    updateLayout()
+    {
+        // Implemented by subclasses if needed.
+    }
+
+    createCell(columnIdentifier)
+    {
+        var cellElement = document.createElement(&quot;td&quot;);
+        cellElement.className = columnIdentifier + &quot;-column&quot;;
+        cellElement.__columnIdentifier = columnIdentifier;
+
+        var column = this.dataGrid.columns.get(columnIdentifier);
+
+        if (column[&quot;aligned&quot;])
+            cellElement.classList.add(column[&quot;aligned&quot;]);
+
+        if (column[&quot;group&quot;])
+            cellElement.classList.add(&quot;column-group-&quot; + column[&quot;group&quot;]);
+
+        var div = cellElement.createChild(&quot;div&quot;, &quot;cell-content&quot;);
+        var content = this.createCellContent(columnIdentifier, cellElement);
+        div.append(content);
+
+        if (column[&quot;icon&quot;]) {
+            let iconElement = document.createElement(&quot;div&quot;);
+            iconElement.classList.add(&quot;icon&quot;);
+            div.insertBefore(iconElement, div.firstChild);
+        }
+
+        if (columnIdentifier === this.dataGrid.disclosureColumnIdentifier) {
+            cellElement.classList.add(&quot;disclosure&quot;);
+            if (this.leftPadding)
+                cellElement.style.setProperty(&quot;padding-left&quot;, this.leftPadding + &quot;px&quot;);
+        }
+
+        return cellElement;
+    }
+
+    createCellContent(columnIdentifier)
+    {
+        return this.data[columnIdentifier] || &quot;\u200b&quot;; // Zero width space to keep the cell from collapsing.
+    }
+
+    elementWithColumnIdentifier(columnIdentifier)
+    {
+        if (!this.dataGrid)
+            return null;
+
+        let index = this.dataGrid.orderedColumns.indexOf(columnIdentifier);
+        if (index === -1)
+            return null;
+
+        return this.element.children[index];
+    }
+
+    // Share these functions with DataGrid. They are written to work with a DataGridNode this object.
+    appendChild() { return WebInspector.DataGrid.prototype.appendChild.apply(this, arguments); }
+    insertChild() { return WebInspector.DataGrid.prototype.insertChild.apply(this, arguments); }
+    removeChild() { return WebInspector.DataGrid.prototype.removeChild.apply(this, arguments); }
+    removeChildren() { return WebInspector.DataGrid.prototype.removeChildren.apply(this, arguments); }
+    removeChildrenRecursive() { return WebInspector.DataGrid.prototype.removeChildrenRecursive.apply(this, arguments); }
+
+    _recalculateSiblings(myIndex)
+    {
+        if (!this.parent)
+            return;
+
+        var previousChild = (myIndex &gt; 0 ? this.parent.children[myIndex - 1] : null);
+
+        if (previousChild) {
+            previousChild.nextSibling = this;
+            this.previousSibling = previousChild;
+        } else
+            this.previousSibling = null;
+
+        var nextChild = this.parent.children[myIndex + 1];
+
+        if (nextChild) {
+            nextChild.previousSibling = this;
+            this.nextSibling = nextChild;
+        } else
+            this.nextSibling = null;
+    }
+
+    collapse()
+    {
+        if (this._element)
+            this._element.classList.remove(&quot;expanded&quot;);
+
+        this._expanded = false;
+
+        for (var i = 0; i &lt; this.children.length; ++i)
+            this.children[i].revealed = false;
+
+        this.dispatchEventToListeners(&quot;collapsed&quot;);
+
+        if (this.dataGrid) {
+            this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Event.CollapsedNode, {dataGridNode: this});
+            this.dataGrid._noteRowsChanged();
+        }
+    }
+
+    collapseRecursively()
+    {
+        var item = this;
+        while (item) {
+            if (item.expanded)
+                item.collapse();
+            item = item.traverseNextNode(false, this, true);
+        }
+    }
+
+    expand()
+    {
+        if (!this.hasChildren || this.expanded)
+            return;
+
+        if (this.revealed &amp;&amp; !this._shouldRefreshChildren)
+            for (var i = 0; i &lt; this.children.length; ++i)
+                this.children[i].revealed = true;
+
+        if (this._shouldRefreshChildren) {
+            for (var i = 0; i &lt; this.children.length; ++i)
+                this.children[i]._detach();
+
+            this.dispatchEventToListeners(&quot;populate&quot;);
+
+            if (this._attached) {
+                for (var i = 0; i &lt; this.children.length; ++i) {
+                    var child = this.children[i];
+                    if (this.revealed)
+                        child.revealed = true;
+                    child._attach();
+                }
+            }
+
+            this._shouldRefreshChildren = false;
+        }
+
+        if (this._element)
+            this._element.classList.add(&quot;expanded&quot;);
+
+        this._expanded = true;
+
+        this.dispatchEventToListeners(&quot;expanded&quot;);
+
+        if (this.dataGrid) {
+            this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Event.ExpandedNode, {dataGridNode: this});
+            this.dataGrid._noteRowsChanged();
+        }
+    }
+
+    expandRecursively()
+    {
+        var item = this;
+        while (item) {
+            item.expand();
+            item = item.traverseNextNode(false, this);
+        }
+    }
+
+    forEachImmediateChild(callback)
+    {
+        for (let node of this.children)
+            callback(node);
+    }
+
+    forEachChildInSubtree(callback)
+    {
+        let node = this.traverseNextNode(false, this, true);
+        while (node) {
+            callback(node);
+            node = node.traverseNextNode(false, this, true);
+        }
+    }
+
+    isInSubtreeOfNode(baseNode)
+    {
+        let node = baseNode;
+        while (node) {
+            if (node === this)
+                return true;
+            node = node.traverseNextNode(false, baseNode, true);
+        }
+        return false;
+    }
+
+    reveal()
+    {
+        var currentAncestor = this.parent;
+        while (currentAncestor &amp;&amp; !currentAncestor.root) {
+            if (!currentAncestor.expanded)
+                currentAncestor.expand();
+            currentAncestor = currentAncestor.parent;
+        }
+
+        this.element.scrollIntoViewIfNeeded(false);
+
+        this.dispatchEventToListeners(&quot;revealed&quot;);
+    }
+
+    select(suppressSelectedEvent)
+    {
+        if (!this.dataGrid || !this.selectable || this.selected)
+            return;
+
+        let oldSelectedNode = this.dataGrid.selectedNode;
+        if (oldSelectedNode)
+            oldSelectedNode.deselect(true);
+
+        this._selected = true;
+        this.dataGrid.selectedNode = this;
+
+        if (this._element)
+            this._element.classList.add(&quot;selected&quot;);
+
+        if (!suppressSelectedEvent)
+            this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Event.SelectedNodeChanged, {oldSelectedNode});
+    }
+
+    revealAndSelect()
+    {
+        this.reveal();
+        this.select();
+    }
+
+    deselect(suppressDeselectedEvent)
+    {
+        if (!this.dataGrid || this.dataGrid.selectedNode !== this || !this.selected)
+            return;
+
+        this._selected = false;
+        this.dataGrid.selectedNode = null;
+
+        if (this._element)
+            this._element.classList.remove(&quot;selected&quot;);
+
+        if (!suppressDeselectedEvent)
+            this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Event.SelectedNodeChanged, {oldSelectedNode: this});
+    }
+
+    traverseNextNode(skipHidden, stayWithin, dontPopulate, info)
+    {
+        if (!dontPopulate &amp;&amp; this.hasChildren)
+            this.dispatchEventToListeners(&quot;populate&quot;);
+
+        if (info)
+            info.depthChange = 0;
+
+        var node = (!skipHidden || this.revealed) ? this.children[0] : null;
+        if (node &amp;&amp; (!skipHidden || this.expanded)) {
+            if (info)
+                info.depthChange = 1;
+            return node;
+        }
+
+        if (this === stayWithin)
+            return null;
+
+        node = (!skipHidden || this.revealed) ? this.nextSibling : null;
+        if (node)
+            return node;
+
+        node = this;
+        while (node &amp;&amp; !node.root &amp;&amp; !((!skipHidden || node.revealed) ? node.nextSibling : null) &amp;&amp; node.parent !== stayWithin) {
+            if (info)
+                info.depthChange -= 1;
+            node = node.parent;
+        }
+
+        if (!node)
+            return null;
+
+        return (!skipHidden || node.revealed) ? node.nextSibling : null;
+    }
+
+    traversePreviousNode(skipHidden, dontPopulate)
+    {
+        var node = (!skipHidden || this.revealed) ? this.previousSibling : null;
+        if (!dontPopulate &amp;&amp; node &amp;&amp; node.hasChildren)
+            node.dispatchEventToListeners(&quot;populate&quot;);
+
+        while (node &amp;&amp; ((!skipHidden || (node.revealed &amp;&amp; node.expanded)) ? node.children.lastValue : null)) {
+            if (!dontPopulate &amp;&amp; node.hasChildren)
+                node.dispatchEventToListeners(&quot;populate&quot;);
+            node = ((!skipHidden || (node.revealed &amp;&amp; node.expanded)) ? node.children.lastValue : null);
+        }
+
+        if (node)
+            return node;
+
+        if (!this.parent || this.parent.root)
+            return null;
+
+        return this.parent;
+    }
+
+    isEventWithinDisclosureTriangle(event)
+    {
+        if (!this.hasChildren)
+            return false;
+        let cell = event.target.enclosingNodeOrSelfWithNodeName(&quot;td&quot;);
+        if (!cell || !cell.classList.contains(&quot;disclosure&quot;))
+            return false;
+
+        let computedLeftPadding = window.getComputedStyle(cell).getPropertyCSSValue(&quot;padding-left&quot;).getFloatValue(CSSPrimitiveValue.CSS_PX);
+        let left = cell.totalOffsetLeft + computedLeftPadding;
+        return event.pageX &gt;= left &amp;&amp; event.pageX &lt;= left + this.disclosureToggleWidth;
+    }
+
+    _attach()
+    {
+        if (!this.dataGrid || this._attached)
+            return;
+
+        this._attached = true;
+
+        let insertionIndex = -1;
+
+        if (!this.isPlaceholderNode) {
+            var previousGridNode = this.traversePreviousNode(true, true);
+            insertionIndex = this.dataGrid._rows.indexOf(previousGridNode);
+            if (insertionIndex === -1)
+                insertionIndex = 0;
+            else
+                insertionIndex++;
+        }
+
+        if (insertionIndex === -1)
+            this.dataGrid._rows.push(this);
+        else
+            this.dataGrid._rows.insertAtIndex(this, insertionIndex);
+
+        this.dataGrid._noteRowsChanged();
+
+        if (this.expanded) {
+            for (var i = 0; i &lt; this.children.length; ++i)
+                this.children[i]._attach();
+        }
+    }
+
+    _detach()
+    {
+        if (!this._attached)
+            return;
+
+        this._attached = false;
+
+        this.dataGrid._rows.remove(this, true);
+        this.dataGrid._noteRowRemoved(this);
+
+        for (var i = 0; i &lt; this.children.length; ++i)
+            this.children[i]._detach();
+    }
+
+    savePosition()
+    {
+        if (this._savedPosition)
+            return;
+
+        console.assert(this.parent);
+        if (!this.parent)
+            return;
+
+        this._savedPosition = {
+            parent: this.parent,
+            index: this.parent.children.indexOf(this)
+        };
+    }
+
+    restorePosition()
+    {
+        if (!this._savedPosition)
+            return;
+
+        if (this.parent !== this._savedPosition.parent)
+            this._savedPosition.parent.insertChild(this, this._savedPosition.index);
+
+        this._savedPosition = null;
+    }
+
+    appendContextMenuItems(contextMenu)
+    {
+        // Subclasses may override
+        return null;
+    }
+
+    // Protected
+
+    filterableDataForColumn(columnIdentifier)
+    {
+        let value = this.data[columnIdentifier];
+        return typeof value === &quot;string&quot; ? value : null;
+    }
+};
+
+// Used to create a new table row when entering new data by editing cells.
+WebInspector.PlaceholderDataGridNode = class PlaceholderDataGridNode extends WebInspector.DataGridNode
+{
+    constructor(data)
+    {
+        super(data, false);
+        this.isPlaceholderNode = true;
+    }
+
+    makeNormal()
+    {
+        this.isPlaceholderNode = false;
+    }
+};
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsTreeElementjs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Views/TreeElement.js (0 => 203114)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/TreeElement.js                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TreeElement.js        2016-07-12 13:05:13 UTC (rev 203114)
</span><span class="lines">@@ -0,0 +1,612 @@
</span><ins>+/*
+ * Copyright (C) 2007, 2013, 2015 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Inc. (&quot;Apple&quot;) nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS &quot;AS IS&quot; AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.TreeElement = class TreeElement extends WebInspector.Object
+{
+    constructor(title, representedObject, hasChildren)
+    {
+        super();
+
+        this._title = title;
+        this.representedObject = (representedObject || {});
+
+        if (this.representedObject.__treeElementIdentifier)
+            this.identifier = this.representedObject.__treeElementIdentifier;
+        else {
+            this.identifier = WebInspector.TreeOutline._knownTreeElementNextIdentifier++;
+            this.representedObject.__treeElementIdentifier = this.identifier;
+        }
+
+        this._hidden = false;
+        this._selectable = true;
+        this.expanded = false;
+        this.selected = false;
+        this.hasChildren = hasChildren;
+        this.children = [];
+        this.treeOutline = null;
+        this.parent = null;
+        this.previousSibling = null;
+        this.nextSibling = null;
+        this._listItemNode = null;
+    }
+
+    // Methods
+
+    appendChild() { return WebInspector.TreeOutline.prototype.appendChild.apply(this, arguments); }
+    insertChild() { return WebInspector.TreeOutline.prototype.insertChild.apply(this, arguments); }
+    removeChild() { return WebInspector.TreeOutline.prototype.removeChild.apply(this, arguments); }
+    removeChildAtIndex() { return WebInspector.TreeOutline.prototype.removeChildAtIndex.apply(this, arguments); }
+    removeChildren() { return WebInspector.TreeOutline.prototype.removeChildren.apply(this, arguments); }
+    removeChildrenRecursive() { return WebInspector.TreeOutline.prototype.removeChildrenRecursive.apply(this, arguments); }
+
+    get arrowToggleWidth()
+    {
+        return 10;
+    }
+
+    get selectable()
+    {
+        if (this._hidden)
+            return false;
+        return this._selectable;
+    }
+
+    set selectable(x)
+    {
+        this._selectable = x;
+    }
+
+    get listItemElement()
+    {
+        return this._listItemNode;
+    }
+
+    get title()
+    {
+        return this._title;
+    }
+
+    set title(x)
+    {
+        this._title = x;
+        this._setListItemNodeContent();
+        this.didChange();
+    }
+
+    get titleHTML()
+    {
+        return this._titleHTML;
+    }
+
+    set titleHTML(x)
+    {
+        this._titleHTML = x;
+        this._setListItemNodeContent();
+        this.didChange();
+    }
+
+    get tooltip()
+    {
+        return this._tooltip;
+    }
+
+    set tooltip(x)
+    {
+        this._tooltip = x;
+        if (this._listItemNode)
+            this._listItemNode.title = x ? x : &quot;&quot;;
+    }
+
+    get hasChildren()
+    {
+        return this._hasChildren;
+    }
+
+    set hasChildren(x)
+    {
+        if (this._hasChildren === x)
+            return;
+
+        this._hasChildren = x;
+
+        if (!this._listItemNode)
+            return;
+
+        if (x)
+            this._listItemNode.classList.add(&quot;parent&quot;);
+        else {
+            this._listItemNode.classList.remove(&quot;parent&quot;);
+            this.collapse();
+        }
+
+        this.didChange();
+    }
+
+    get hidden()
+    {
+        return this._hidden;
+    }
+
+    set hidden(x)
+    {
+        if (this._hidden === x)
+            return;
+
+        this._hidden = x;
+
+        if (this._listItemNode)
+            this._listItemNode.hidden = this._hidden;
+        if (this._childrenListNode)
+            this._childrenListNode.hidden = this._hidden;
+
+        if (this.treeOutline)
+            this.treeOutline.dispatchEventToListeners(WebInspector.TreeOutline.Event.ElementVisibilityDidChange, {element: this});
+    }
+
+    get shouldRefreshChildren()
+    {
+        return this._shouldRefreshChildren;
+    }
+
+    set shouldRefreshChildren(x)
+    {
+        this._shouldRefreshChildren = x;
+        if (x &amp;&amp; this.expanded)
+            this.expand();
+    }
+
+    _fireDidChange()
+    {
+        if (this.treeOutline)
+            this.treeOutline._treeElementDidChange(this);
+    }
+
+    didChange()
+    {
+        if (!this.treeOutline)
+            return;
+
+        this.onNextFrame._fireDidChange();
+    }
+
+    _setListItemNodeContent()
+    {
+        if (!this._listItemNode)
+            return;
+
+        if (!this._titleHTML &amp;&amp; !this._title)
+            this._listItemNode.removeChildren();
+        else if (typeof this._titleHTML === &quot;string&quot;)
+            this._listItemNode.innerHTML = this._titleHTML;
+        else if (typeof this._title === &quot;string&quot;)
+            this._listItemNode.textContent = this._title;
+        else {
+            this._listItemNode.removeChildren();
+            if (this._title.parentNode)
+                this._title.parentNode.removeChild(this._title);
+            this._listItemNode.appendChild(this._title);
+        }
+    }
+
+    _attach()
+    {
+        if (!this._listItemNode || this.parent._shouldRefreshChildren) {
+            if (this._listItemNode &amp;&amp; this._listItemNode.parentNode)
+                this._listItemNode.parentNode.removeChild(this._listItemNode);
+
+            this._listItemNode = this.treeOutline._childrenListNode.ownerDocument.createElement(&quot;li&quot;);
+            this._listItemNode.treeElement = this;
+            this._setListItemNodeContent();
+            this._listItemNode.title = this._tooltip ? this._tooltip : &quot;&quot;;
+            this._listItemNode.hidden = this.hidden;
+
+            if (this.hasChildren)
+                this._listItemNode.classList.add(&quot;parent&quot;);
+            if (this.expanded)
+                this._listItemNode.classList.add(&quot;expanded&quot;);
+            if (this.selected)
+                this._listItemNode.classList.add(&quot;selected&quot;);
+
+            this._listItemNode.addEventListener(&quot;mousedown&quot;, WebInspector.TreeElement.treeElementMouseDown);
+            this._listItemNode.addEventListener(&quot;click&quot;, WebInspector.TreeElement.treeElementToggled);
+            this._listItemNode.addEventListener(&quot;dblclick&quot;, WebInspector.TreeElement.treeElementDoubleClicked);
+
+            if (this.onattach)
+                this.onattach(this);
+        }
+
+        var nextSibling = null;
+        if (this.nextSibling &amp;&amp; this.nextSibling._listItemNode &amp;&amp; this.nextSibling._listItemNode.parentNode === this.parent._childrenListNode)
+            nextSibling = this.nextSibling._listItemNode;
+        this.parent._childrenListNode.insertBefore(this._listItemNode, nextSibling);
+        if (this._childrenListNode)
+            this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling);
+        if (this.selected)
+            this.select();
+        if (this.expanded)
+            this.expand();
+    }
+
+    _detach()
+    {
+        if (this.ondetach)
+            this.ondetach(this);
+        if (this._listItemNode &amp;&amp; this._listItemNode.parentNode)
+            this._listItemNode.parentNode.removeChild(this._listItemNode);
+        if (this._childrenListNode &amp;&amp; this._childrenListNode.parentNode)
+            this._childrenListNode.parentNode.removeChild(this._childrenListNode);
+    }
+
+    static treeElementMouseDown(event)
+    {
+        var element = event.currentTarget;
+        if (!element || !element.treeElement || !element.treeElement.selectable)
+            return;
+
+        if (element.treeElement.isEventWithinDisclosureTriangle(event)) {
+            event.preventDefault();
+            return;
+        }
+
+        element.treeElement.selectOnMouseDown(event);
+    }
+
+    static treeElementToggled(event)
+    {
+        var element = event.currentTarget;
+        if (!element || !element.treeElement)
+            return;
+
+        var toggleOnClick = element.treeElement.toggleOnClick &amp;&amp; !element.treeElement.selectable;
+        var isInTriangle = element.treeElement.isEventWithinDisclosureTriangle(event);
+        if (!toggleOnClick &amp;&amp; !isInTriangle)
+            return;
+
+        if (element.treeElement.expanded) {
+            if (event.altKey)
+                element.treeElement.collapseRecursively();
+            else
+                element.treeElement.collapse();
+        } else {
+            if (event.altKey)
+                element.treeElement.expandRecursively();
+            else
+                element.treeElement.expand();
+        }
+        event.stopPropagation();
+    }
+
+    static treeElementDoubleClicked(event)
+    {
+        var element = event.currentTarget;
+        if (!element || !element.treeElement)
+            return;
+
+        if (element.treeElement.isEventWithinDisclosureTriangle(event))
+            return;
+
+        if (element.treeElement.ondblclick)
+            element.treeElement.ondblclick.call(element.treeElement, event);
+        else if (element.treeElement.hasChildren &amp;&amp; !element.treeElement.expanded)
+            element.treeElement.expand();
+    }
+
+    collapse()
+    {
+        if (this._listItemNode)
+            this._listItemNode.classList.remove(&quot;expanded&quot;);
+        if (this._childrenListNode)
+            this._childrenListNode.classList.remove(&quot;expanded&quot;);
+
+        this.expanded = false;
+        if (this.treeOutline)
+            this.treeOutline._treeElementsExpandedState[this.identifier] = false;
+
+        if (this.oncollapse)
+            this.oncollapse(this);
+
+        if (this.treeOutline)
+            this.treeOutline.dispatchEventToListeners(WebInspector.TreeOutline.Event.ElementDisclosureDidChanged, {element: this});
+    }
+
+    collapseRecursively()
+    {
+        var item = this;
+        while (item) {
+            if (item.expanded)
+                item.collapse();
+            item = item.traverseNextTreeElement(false, this, true);
+        }
+    }
+
+    expand()
+    {
+        if (this.expanded &amp;&amp; !this._shouldRefreshChildren &amp;&amp; this._childrenListNode)
+            return;
+
+        // Set this before onpopulate. Since onpopulate can add elements and dispatch an ElementAdded event,
+        // this makes sure the expanded flag is true before calling those functions. This prevents the
+        // possibility of an infinite loop if onpopulate or an event handler were to call expand.
+
+        this.expanded = true;
+        if (this.treeOutline)
+            this.treeOutline._treeElementsExpandedState[this.identifier] = true;
+
+        // If there are no children, return. We will be expanded once we have children.
+        if (!this.hasChildren)
+            return;
+
+        if (this.treeOutline &amp;&amp; (!this._childrenListNode || this._shouldRefreshChildren)) {
+            if (this._childrenListNode &amp;&amp; this._childrenListNode.parentNode)
+                this._childrenListNode.parentNode.removeChild(this._childrenListNode);
+
+            this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement(&quot;ol&quot;);
+            this._childrenListNode.parentTreeElement = this;
+            this._childrenListNode.classList.add(&quot;children&quot;);
+            this._childrenListNode.hidden = this.hidden;
+
+            this.onpopulate();
+
+            for (var i = 0; i &lt; this.children.length; ++i)
+                this.children[i]._attach();
+
+            this._shouldRefreshChildren = false;
+        }
+
+        if (this._listItemNode) {
+            this._listItemNode.classList.add(&quot;expanded&quot;);
+            if (this._childrenListNode &amp;&amp; this._childrenListNode.parentNode !== this._listItemNode.parentNode)
+                this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling);
+        }
+
+        if (this._childrenListNode)
+            this._childrenListNode.classList.add(&quot;expanded&quot;);
+
+        if (this.onexpand)
+            this.onexpand(this);
+
+        if (this.treeOutline)
+            this.treeOutline.dispatchEventToListeners(WebInspector.TreeOutline.Event.ElementDisclosureDidChanged, {element: this});
+    }
+
+    expandRecursively(maxDepth)
+    {
+        var item = this;
+        var info = {};
+        var depth = 0;
+
+        // The Inspector uses TreeOutlines to represents object properties, so recursive expansion
+        // in some case can be infinite, since JavaScript objects can hold circular references.
+        // So default to a recursion cap of 3 levels, since that gives fairly good results.
+        if (maxDepth === undefined)
+            maxDepth = 3;
+
+        while (item) {
+            if (depth &lt; maxDepth)
+                item.expand();
+            item = item.traverseNextTreeElement(false, this, (depth &gt;= maxDepth), info);
+            depth += info.depthChange;
+        }
+    }
+
+    hasAncestor(ancestor)
+        {
+        if (!ancestor)
+            return false;
+
+        var currentNode = this.parent;
+        while (currentNode) {
+            if (ancestor === currentNode)
+                return true;
+            currentNode = currentNode.parent;
+        }
+
+        return false;
+    }
+
+    reveal()
+    {
+        var currentAncestor = this.parent;
+        while (currentAncestor &amp;&amp; !currentAncestor.root) {
+            if (!currentAncestor.expanded)
+                currentAncestor.expand();
+            currentAncestor = currentAncestor.parent;
+        }
+
+        if (this.onreveal)
+            this.onreveal(this);
+    }
+
+    revealed(ignoreHidden)
+    {
+        if (!ignoreHidden &amp;&amp; this.hidden)
+            return false;
+
+        var currentAncestor = this.parent;
+        while (currentAncestor &amp;&amp; !currentAncestor.root) {
+            if (!currentAncestor.expanded)
+                return false;
+            if (!ignoreHidden &amp;&amp; currentAncestor.hidden)
+                return false;
+            currentAncestor = currentAncestor.parent;
+        }
+
+        return true;
+    }
+
+    selectOnMouseDown(event)
+    {
+        this.select(false, true);
+    }
+
+    select(omitFocus, selectedByUser, suppressOnSelect, suppressOnDeselect)
+    {
+        if (!this.treeOutline || !this.selectable)
+            return;
+
+        if (this.selected &amp;&amp; !this.treeOutline.allowsRepeatSelection)
+            return;
+
+        if (!omitFocus)
+            this.treeOutline._childrenListNode.focus();
+
+        // Focusing on another node may detach &quot;this&quot; from tree.
+        let treeOutline = this.treeOutline;
+        if (!treeOutline)
+            return;
+
+        treeOutline.processingSelectionChange = true;
+
+        // Prevent dispatching a SelectionDidChange event for the deselected element if
+        // it will be dispatched for the selected element. The event data includes both
+        // the selected and deselected elements, so one event is.
+        if (!suppressOnSelect)
+            suppressOnDeselect = true;
+
+        let deselectedElement = treeOutline.selectedTreeElement;
+        if (!this.selected) {
+            if (treeOutline.selectedTreeElement)
+                treeOutline.selectedTreeElement.deselect(suppressOnDeselect);
+
+            this.selected = true;
+            treeOutline.selectedTreeElement = this;
+
+            if (this._listItemNode)
+                this._listItemNode.classList.add(&quot;selected&quot;);
+        }
+
+        if (!suppressOnSelect) {
+            if (this.onselect)
+                this.onselect(this, selectedByUser);
+
+            treeOutline.dispatchEventToListeners(WebInspector.TreeOutline.Event.SelectionDidChange, {selectedElement: this, deselectedElement, selectedByUser});
+        }
+
+        treeOutline.processingSelectionChange = false;
+    }
+
+    revealAndSelect(omitFocus, selectedByUser, suppressOnSelect, suppressOnDeselect)
+    {
+        this.reveal();
+        this.select(omitFocus, selectedByUser, suppressOnSelect, suppressOnDeselect);
+    }
+
+    deselect(suppressOnDeselect)
+    {
+        if (!this.treeOutline || this.treeOutline.selectedTreeElement !== this || !this.selected)
+            return false;
+
+        this.selected = false;
+        this.treeOutline.selectedTreeElement = null;
+
+        if (this._listItemNode)
+            this._listItemNode.classList.remove(&quot;selected&quot;);
+
+        if (!suppressOnDeselect) {
+            if (this.ondeselect)
+                this.ondeselect(this);
+
+            this.treeOutline.dispatchEventToListeners(WebInspector.TreeOutline.Event.SelectionDidChange, {deselectedElement: this});
+        }
+
+        return true;
+    }
+
+    onpopulate()
+    {
+        // Overriden by subclasses.
+    }
+
+    traverseNextTreeElement(skipUnrevealed, stayWithin, dontPopulate, info)
+    {
+        function shouldSkip(element) {
+            return skipUnrevealed &amp;&amp; !element.revealed(true);
+        }
+
+        var depthChange = 0;
+        var element = this;
+
+        if (!dontPopulate)
+            element.onpopulate();
+
+        do {
+            if (element.hasChildren &amp;&amp; element.children[0] &amp;&amp; (!skipUnrevealed || element.expanded)) {
+                element = element.children[0];
+                depthChange += 1;
+            } else {
+                while (element &amp;&amp; !element.nextSibling &amp;&amp; element.parent &amp;&amp; !element.parent.root &amp;&amp; element.parent !== stayWithin) {
+                    element = element.parent;
+                    depthChange -= 1;
+                }
+
+                if (element)
+                    element = element.nextSibling;
+            }
+        } while (element &amp;&amp; shouldSkip(element));
+
+        if (info)
+            info.depthChange = depthChange;
+
+        return element;
+    }
+
+    traversePreviousTreeElement(skipUnrevealed, dontPopulate)
+    {
+        function shouldSkip(element) {
+            return skipUnrevealed &amp;&amp; !element.revealed(true);
+        }
+
+        var element = this;
+
+        do {
+            if (element.previousSibling) {
+                element = element.previousSibling;
+
+                while (element &amp;&amp; element.hasChildren &amp;&amp; element.expanded &amp;&amp; !shouldSkip(element)) {
+                    if (!dontPopulate)
+                        element.onpopulate();
+                    element = element.children.lastValue;
+                }
+            } else
+                element = element.parent &amp;&amp; element.parent.root ? null : element.parent;
+        } while (element &amp;&amp; shouldSkip(element));
+
+        return element;
+    }
+
+    isEventWithinDisclosureTriangle(event)
+    {
+        if (!document.contains(this._listItemNode))
+            return false;
+
+        // FIXME: We should not use getComputedStyle(). For that we need to get rid of using ::before for disclosure triangle. (http://webk.it/74446)
+        var computedLeftPadding = window.getComputedStyle(this._listItemNode).getPropertyCSSValue(&quot;padding-left&quot;).getFloatValue(CSSPrimitiveValue.CSS_PX);
+        var left = this._listItemNode.totalOffsetLeft + computedLeftPadding;
+        return event.pageX &gt;= left &amp;&amp; event.pageX &lt;= left + this.arrowToggleWidth &amp;&amp; this.hasChildren;
+    }
+};
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsTreeOutlinejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TreeOutline.js (203113 => 203114)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/TreeOutline.js        2016-07-12 13:04:38 UTC (rev 203113)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TreeOutline.js        2016-07-12 13:05:13 UTC (rev 203114)
</span><span class="lines">@@ -643,588 +643,3 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> WebInspector.TreeOutline._knownTreeElementNextIdentifier = 1;
</span><del>-
-WebInspector.TreeElement = class TreeElement extends WebInspector.Object
-{
-    constructor(title, representedObject, hasChildren)
-    {
-        super();
-
-        this._title = title;
-        this.representedObject = (representedObject || {});
-
-        if (this.representedObject.__treeElementIdentifier)
-            this.identifier = this.representedObject.__treeElementIdentifier;
-        else {
-            this.identifier = WebInspector.TreeOutline._knownTreeElementNextIdentifier++;
-            this.representedObject.__treeElementIdentifier = this.identifier;
-        }
-
-        this._hidden = false;
-        this._selectable = true;
-        this.expanded = false;
-        this.selected = false;
-        this.hasChildren = hasChildren;
-        this.children = [];
-        this.treeOutline = null;
-        this.parent = null;
-        this.previousSibling = null;
-        this.nextSibling = null;
-        this._listItemNode = null;
-    }
-
-    // Methods
-
-    appendChild() { return WebInspector.TreeOutline.prototype.appendChild.apply(this, arguments); }
-    insertChild() { return WebInspector.TreeOutline.prototype.insertChild.apply(this, arguments); }
-    removeChild() { return WebInspector.TreeOutline.prototype.removeChild.apply(this, arguments); }
-    removeChildAtIndex() { return WebInspector.TreeOutline.prototype.removeChildAtIndex.apply(this, arguments); }
-    removeChildren() { return WebInspector.TreeOutline.prototype.removeChildren.apply(this, arguments); }
-    removeChildrenRecursive() { return WebInspector.TreeOutline.prototype.removeChildrenRecursive.apply(this, arguments); }
-
-    get arrowToggleWidth()
-    {
-        return 10;
-    }
-
-    get selectable()
-    {
-        if (this._hidden)
-            return false;
-        return this._selectable;
-    }
-
-    set selectable(x)
-    {
-        this._selectable = x;
-    }
-
-    get listItemElement()
-    {
-        return this._listItemNode;
-    }
-
-    get title()
-    {
-        return this._title;
-    }
-
-    set title(x)
-    {
-        this._title = x;
-        this._setListItemNodeContent();
-        this.didChange();
-    }
-
-    get titleHTML()
-    {
-        return this._titleHTML;
-    }
-
-    set titleHTML(x)
-    {
-        this._titleHTML = x;
-        this._setListItemNodeContent();
-        this.didChange();
-    }
-
-    get tooltip()
-    {
-        return this._tooltip;
-    }
-
-    set tooltip(x)
-    {
-        this._tooltip = x;
-        if (this._listItemNode)
-            this._listItemNode.title = x ? x : &quot;&quot;;
-    }
-
-    get hasChildren()
-    {
-        return this._hasChildren;
-    }
-
-    set hasChildren(x)
-    {
-        if (this._hasChildren === x)
-            return;
-
-        this._hasChildren = x;
-
-        if (!this._listItemNode)
-            return;
-
-        if (x)
-            this._listItemNode.classList.add(&quot;parent&quot;);
-        else {
-            this._listItemNode.classList.remove(&quot;parent&quot;);
-            this.collapse();
-        }
-
-        this.didChange();
-    }
-
-    get hidden()
-    {
-        return this._hidden;
-    }
-
-    set hidden(x)
-    {
-        if (this._hidden === x)
-            return;
-
-        this._hidden = x;
-
-        if (this._listItemNode)
-            this._listItemNode.hidden = this._hidden;
-        if (this._childrenListNode)
-            this._childrenListNode.hidden = this._hidden;
-
-        if (this.treeOutline)
-            this.treeOutline.dispatchEventToListeners(WebInspector.TreeOutline.Event.ElementVisibilityDidChange, {element: this});
-    }
-
-    get shouldRefreshChildren()
-    {
-        return this._shouldRefreshChildren;
-    }
-
-    set shouldRefreshChildren(x)
-    {
-        this._shouldRefreshChildren = x;
-        if (x &amp;&amp; this.expanded)
-            this.expand();
-    }
-
-    _fireDidChange()
-    {
-        if (this.treeOutline)
-            this.treeOutline._treeElementDidChange(this);
-    }
-
-    didChange()
-    {
-        if (!this.treeOutline)
-            return;
-
-        this.onNextFrame._fireDidChange();
-    }
-
-    _setListItemNodeContent()
-    {
-        if (!this._listItemNode)
-            return;
-
-        if (!this._titleHTML &amp;&amp; !this._title)
-            this._listItemNode.removeChildren();
-        else if (typeof this._titleHTML === &quot;string&quot;)
-            this._listItemNode.innerHTML = this._titleHTML;
-        else if (typeof this._title === &quot;string&quot;)
-            this._listItemNode.textContent = this._title;
-        else {
-            this._listItemNode.removeChildren();
-            if (this._title.parentNode)
-                this._title.parentNode.removeChild(this._title);
-            this._listItemNode.appendChild(this._title);
-        }
-    }
-
-    _attach()
-    {
-        if (!this._listItemNode || this.parent._shouldRefreshChildren) {
-            if (this._listItemNode &amp;&amp; this._listItemNode.parentNode)
-                this._listItemNode.parentNode.removeChild(this._listItemNode);
-
-            this._listItemNode = this.treeOutline._childrenListNode.ownerDocument.createElement(&quot;li&quot;);
-            this._listItemNode.treeElement = this;
-            this._setListItemNodeContent();
-            this._listItemNode.title = this._tooltip ? this._tooltip : &quot;&quot;;
-            this._listItemNode.hidden = this.hidden;
-
-            if (this.hasChildren)
-                this._listItemNode.classList.add(&quot;parent&quot;);
-            if (this.expanded)
-                this._listItemNode.classList.add(&quot;expanded&quot;);
-            if (this.selected)
-                this._listItemNode.classList.add(&quot;selected&quot;);
-
-            this._listItemNode.addEventListener(&quot;mousedown&quot;, WebInspector.TreeElement.treeElementMouseDown);
-            this._listItemNode.addEventListener(&quot;click&quot;, WebInspector.TreeElement.treeElementToggled);
-            this._listItemNode.addEventListener(&quot;dblclick&quot;, WebInspector.TreeElement.treeElementDoubleClicked);
-
-            if (this.onattach)
-                this.onattach(this);
-        }
-
-        var nextSibling = null;
-        if (this.nextSibling &amp;&amp; this.nextSibling._listItemNode &amp;&amp; this.nextSibling._listItemNode.parentNode === this.parent._childrenListNode)
-            nextSibling = this.nextSibling._listItemNode;
-        this.parent._childrenListNode.insertBefore(this._listItemNode, nextSibling);
-        if (this._childrenListNode)
-            this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling);
-        if (this.selected)
-            this.select();
-        if (this.expanded)
-            this.expand();
-    }
-
-    _detach()
-    {
-        if (this.ondetach)
-            this.ondetach(this);
-        if (this._listItemNode &amp;&amp; this._listItemNode.parentNode)
-            this._listItemNode.parentNode.removeChild(this._listItemNode);
-        if (this._childrenListNode &amp;&amp; this._childrenListNode.parentNode)
-            this._childrenListNode.parentNode.removeChild(this._childrenListNode);
-    }
-
-    static treeElementMouseDown(event)
-    {
-        var element = event.currentTarget;
-        if (!element || !element.treeElement || !element.treeElement.selectable)
-            return;
-
-        if (element.treeElement.isEventWithinDisclosureTriangle(event)) {
-            event.preventDefault();
-            return;
-        }
-
-        element.treeElement.selectOnMouseDown(event);
-    }
-
-    static treeElementToggled(event)
-    {
-        var element = event.currentTarget;
-        if (!element || !element.treeElement)
-            return;
-
-        var toggleOnClick = element.treeElement.toggleOnClick &amp;&amp; !element.treeElement.selectable;
-        var isInTriangle = element.treeElement.isEventWithinDisclosureTriangle(event);
-        if (!toggleOnClick &amp;&amp; !isInTriangle)
-            return;
-
-        if (element.treeElement.expanded) {
-            if (event.altKey)
-                element.treeElement.collapseRecursively();
-            else
-                element.treeElement.collapse();
-        } else {
-            if (event.altKey)
-                element.treeElement.expandRecursively();
-            else
-                element.treeElement.expand();
-        }
-        event.stopPropagation();
-    }
-
-    static treeElementDoubleClicked(event)
-    {
-        var element = event.currentTarget;
-        if (!element || !element.treeElement)
-            return;
-
-        if (element.treeElement.isEventWithinDisclosureTriangle(event))
-            return;
-
-        if (element.treeElement.ondblclick)
-            element.treeElement.ondblclick.call(element.treeElement, event);
-        else if (element.treeElement.hasChildren &amp;&amp; !element.treeElement.expanded)
-            element.treeElement.expand();
-    }
-
-    collapse()
-    {
-        if (this._listItemNode)
-            this._listItemNode.classList.remove(&quot;expanded&quot;);
-        if (this._childrenListNode)
-            this._childrenListNode.classList.remove(&quot;expanded&quot;);
-
-        this.expanded = false;
-        if (this.treeOutline)
-            this.treeOutline._treeElementsExpandedState[this.identifier] = false;
-
-        if (this.oncollapse)
-            this.oncollapse(this);
-
-        if (this.treeOutline)
-            this.treeOutline.dispatchEventToListeners(WebInspector.TreeOutline.Event.ElementDisclosureDidChanged, {element: this});
-    }
-
-    collapseRecursively()
-    {
-        var item = this;
-        while (item) {
-            if (item.expanded)
-                item.collapse();
-            item = item.traverseNextTreeElement(false, this, true);
-        }
-    }
-
-    expand()
-    {
-        if (this.expanded &amp;&amp; !this._shouldRefreshChildren &amp;&amp; this._childrenListNode)
-            return;
-
-        // Set this before onpopulate. Since onpopulate can add elements and dispatch an ElementAdded event,
-        // this makes sure the expanded flag is true before calling those functions. This prevents the
-        // possibility of an infinite loop if onpopulate or an event handler were to call expand.
-
-        this.expanded = true;
-        if (this.treeOutline)
-            this.treeOutline._treeElementsExpandedState[this.identifier] = true;
-
-        // If there are no children, return. We will be expanded once we have children.
-        if (!this.hasChildren)
-            return;
-
-        if (this.treeOutline &amp;&amp; (!this._childrenListNode || this._shouldRefreshChildren)) {
-            if (this._childrenListNode &amp;&amp; this._childrenListNode.parentNode)
-                this._childrenListNode.parentNode.removeChild(this._childrenListNode);
-
-            this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement(&quot;ol&quot;);
-            this._childrenListNode.parentTreeElement = this;
-            this._childrenListNode.classList.add(&quot;children&quot;);
-            this._childrenListNode.hidden = this.hidden;
-
-            this.onpopulate();
-
-            for (var i = 0; i &lt; this.children.length; ++i)
-                this.children[i]._attach();
-
-            this._shouldRefreshChildren = false;
-        }
-
-        if (this._listItemNode) {
-            this._listItemNode.classList.add(&quot;expanded&quot;);
-            if (this._childrenListNode &amp;&amp; this._childrenListNode.parentNode !== this._listItemNode.parentNode)
-                this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling);
-        }
-
-        if (this._childrenListNode)
-            this._childrenListNode.classList.add(&quot;expanded&quot;);
-
-        if (this.onexpand)
-            this.onexpand(this);
-
-        if (this.treeOutline)
-            this.treeOutline.dispatchEventToListeners(WebInspector.TreeOutline.Event.ElementDisclosureDidChanged, {element: this});
-    }
-
-    expandRecursively(maxDepth)
-    {
-        var item = this;
-        var info = {};
-        var depth = 0;
-
-        // The Inspector uses TreeOutlines to represents object properties, so recursive expansion
-        // in some case can be infinite, since JavaScript objects can hold circular references.
-        // So default to a recursion cap of 3 levels, since that gives fairly good results.
-        if (maxDepth === undefined)
-            maxDepth = 3;
-
-        while (item) {
-            if (depth &lt; maxDepth)
-                item.expand();
-            item = item.traverseNextTreeElement(false, this, (depth &gt;= maxDepth), info);
-            depth += info.depthChange;
-        }
-    }
-
-    hasAncestor(ancestor)
-        {
-        if (!ancestor)
-            return false;
-
-        var currentNode = this.parent;
-        while (currentNode) {
-            if (ancestor === currentNode)
-                return true;
-            currentNode = currentNode.parent;
-        }
-
-        return false;
-    }
-
-    reveal()
-    {
-        var currentAncestor = this.parent;
-        while (currentAncestor &amp;&amp; !currentAncestor.root) {
-            if (!currentAncestor.expanded)
-                currentAncestor.expand();
-            currentAncestor = currentAncestor.parent;
-        }
-
-        if (this.onreveal)
-            this.onreveal(this);
-    }
-
-    revealed(ignoreHidden)
-    {
-        if (!ignoreHidden &amp;&amp; this.hidden)
-            return false;
-
-        var currentAncestor = this.parent;
-        while (currentAncestor &amp;&amp; !currentAncestor.root) {
-            if (!currentAncestor.expanded)
-                return false;
-            if (!ignoreHidden &amp;&amp; currentAncestor.hidden)
-                return false;
-            currentAncestor = currentAncestor.parent;
-        }
-
-        return true;
-    }
-
-    selectOnMouseDown(event)
-    {
-        this.select(false, true);
-    }
-
-    select(omitFocus, selectedByUser, suppressOnSelect, suppressOnDeselect)
-    {
-        if (!this.treeOutline || !this.selectable)
-            return;
-
-        if (this.selected &amp;&amp; !this.treeOutline.allowsRepeatSelection)
-            return;
-
-        if (!omitFocus)
-            this.treeOutline._childrenListNode.focus();
-
-        // Focusing on another node may detach &quot;this&quot; from tree.
-        let treeOutline = this.treeOutline;
-        if (!treeOutline)
-            return;
-
-        treeOutline.processingSelectionChange = true;
-
-        // Prevent dispatching a SelectionDidChange event for the deselected element if
-        // it will be dispatched for the selected element. The event data includes both
-        // the selected and deselected elements, so one event is.
-        if (!suppressOnSelect)
-            suppressOnDeselect = true;
-
-        let deselectedElement = treeOutline.selectedTreeElement;
-        if (!this.selected) {
-            if (treeOutline.selectedTreeElement)
-                treeOutline.selectedTreeElement.deselect(suppressOnDeselect);
-
-            this.selected = true;
-            treeOutline.selectedTreeElement = this;
-
-            if (this._listItemNode)
-                this._listItemNode.classList.add(&quot;selected&quot;);
-        }
-
-        if (!suppressOnSelect) {
-            if (this.onselect)
-                this.onselect(this, selectedByUser);
-
-            treeOutline.dispatchEventToListeners(WebInspector.TreeOutline.Event.SelectionDidChange, {selectedElement: this, deselectedElement, selectedByUser});
-        }
-
-        treeOutline.processingSelectionChange = false;
-    }
-
-    revealAndSelect(omitFocus, selectedByUser, suppressOnSelect, suppressOnDeselect)
-    {
-        this.reveal();
-        this.select(omitFocus, selectedByUser, suppressOnSelect, suppressOnDeselect);
-    }
-
-    deselect(suppressOnDeselect)
-    {
-        if (!this.treeOutline || this.treeOutline.selectedTreeElement !== this || !this.selected)
-            return false;
-
-        this.selected = false;
-        this.treeOutline.selectedTreeElement = null;
-
-        if (this._listItemNode)
-            this._listItemNode.classList.remove(&quot;selected&quot;);
-
-        if (!suppressOnDeselect) {
-            if (this.ondeselect)
-                this.ondeselect(this);
-
-            this.treeOutline.dispatchEventToListeners(WebInspector.TreeOutline.Event.SelectionDidChange, {deselectedElement: this});
-        }
-
-        return true;
-    }
-
-    onpopulate()
-    {
-        // Overriden by subclasses.
-    }
-
-    traverseNextTreeElement(skipUnrevealed, stayWithin, dontPopulate, info)
-    {
-        function shouldSkip(element) {
-            return skipUnrevealed &amp;&amp; !element.revealed(true);
-        }
-
-        var depthChange = 0;
-        var element = this;
-
-        if (!dontPopulate)
-            element.onpopulate();
-
-        do {
-            if (element.hasChildren &amp;&amp; element.children[0] &amp;&amp; (!skipUnrevealed || element.expanded)) {
-                element = element.children[0];
-                depthChange += 1;
-            } else {
-                while (element &amp;&amp; !element.nextSibling &amp;&amp; element.parent &amp;&amp; !element.parent.root &amp;&amp; element.parent !== stayWithin) {
-                    element = element.parent;
-                    depthChange -= 1;
-                }
-
-                if (element)
-                    element = element.nextSibling;
-            }
-        } while (element &amp;&amp; shouldSkip(element));
-
-        if (info)
-            info.depthChange = depthChange;
-
-        return element;
-    }
-
-    traversePreviousTreeElement(skipUnrevealed, dontPopulate)
-    {
-        function shouldSkip(element) {
-            return skipUnrevealed &amp;&amp; !element.revealed(true);
-        }
-
-        var element = this;
-
-        do {
-            if (element.previousSibling) {
-                element = element.previousSibling;
-
-                while (element &amp;&amp; element.hasChildren &amp;&amp; element.expanded &amp;&amp; !shouldSkip(element)) {
-                    if (!dontPopulate)
-                        element.onpopulate();
-                    element = element.children.lastValue;
-                }
-            } else
-                element = element.parent &amp;&amp; element.parent.root ? null : element.parent;
-        } while (element &amp;&amp; shouldSkip(element));
-
-        return element;
-    }
-
-    isEventWithinDisclosureTriangle(event)
-    {
-        if (!document.contains(this._listItemNode))
-            return false;
-
-        // FIXME: We should not use getComputedStyle(). For that we need to get rid of using ::before for disclosure triangle. (http://webk.it/74446)
-        var computedLeftPadding = window.getComputedStyle(this._listItemNode).getPropertyCSSValue(&quot;padding-left&quot;).getFloatValue(CSSPrimitiveValue.CSS_PX);
-        var left = this._listItemNode.totalOffsetLeft + computedLeftPadding;
-        return event.pageX &gt;= left &amp;&amp; event.pageX &lt;= left + this.arrowToggleWidth &amp;&amp; this.hasChildren;
-    }
-};
</del></span></pre>
</div>
</div>

</body>
</html>