⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 201840 in webkit


Ignore:
Timestamp:
Jun 8, 2016, 4:04:11 PM (10 years ago)
Author:
BJ Burg
Message:

Web Inspector: DOMTreeOutline selection areas should be created and updated lazily
https://bugs.webkit.org/show_bug.cgi?id=158513
<rdar://problem/26689646>

Reviewed by Timothy Hatcher.

Selection areas for DOMTreeElements are used for several things: drag markers,
element hover styles, element selection styles, and showing forced pseudo states
for an element. Fortunately it's easy to tell when any of these things is necessary.

Change DOMTreeOutline and DOMTreeElement so they don't create selection areas
unless they are needed for one of these tasks. This significantly reduces
forced layouts that are required to update the selection area height in case the
element has new attributes that cause the tag to become more or less wrapped.

  • UserInterface/Views/DOMTreeElement.js:

(WebInspector.DOMTreeElement.prototype.set hovered):
Modernize this method a bit.

(WebInspector.DOMTreeElement.prototype.updateSelectionArea):
If a selection area is not necessary, don't create one.
If one exists and it's not needed, then remove it.

(WebInspector.DOMTreeElement.prototype.onattach):
Remove redundant calls to updateSelection(). This is already called in
updateTitle().

(WebInspector.DOMTreeElement.prototype.onselect):
Ask the DOMTreeOutline to update the selection rather than forcing the
element to do it. This is consistent with other updates to user selection.

(WebInspector.DOMTreeElement.prototype._insertInLastAttributePosition):
(WebInspector.DOMTreeElement.prototype._startEditingAsHTML.dispose):
(WebInspector.DOMTreeElement.prototype._startEditingAsHTML):
Use renamed method.

(WebInspector.DOMTreeElement.prototype.updateTitle):
Add a comment to explain why the selection area is nulled out here.

(WebInspector.DOMTreeElement.prototype.get pseudoClassesEnabled):
(WebInspector.DOMTreeElement.prototype._nodePseudoClassesDidChange):
Update the selection area in case one does not exist for this tree element.
The indicator for forced pseudo classes is a pseudo element of the selection area.

(WebInspector.DOMTreeElement.prototype.updateSelection): Renamed.
(WebInspector.DOMTreeElement.prototype.onexpand):
(WebInspector.DOMTreeElement.prototype.oncollapse):
Remove redundant calls to updateSelection(). This is already called in
updateTitle().

  • UserInterface/Views/DOMTreeOutline.css:

(.tree-outline.dom):
(.tree-outline.dom li.hovered:not(.selected) .selection-area):
(.tree-outline.dom li .selection-area):
(.tree-outline.dom li.selected .selection-area):
(.tree-outline.dom li.elements-drag-over .selection-area):
(.tree-outline.dom:focus li.selected .selection-area):
(.tree-outline.dom li.pseudo-class-enabled > .selection-area::before):
(.tree-outline.dom:focus li.selected.pseudo-class-enabled > .selection-area::before):
(.tree-outline.dom li.hovered:not(.selected) .selection): Deleted.
(.tree-outline.dom li .selection): Deleted.
(.tree-outline.dom li.selected .selection): Deleted.
(.tree-outline.dom li.elements-drag-over .selection): Deleted.
(.tree-outline.dom:focus li.selected .selection): Deleted.
(.tree-outline.dom li.pseudo-class-enabled > .selection::before): Deleted.
(.tree-outline.dom:focus li.selected.pseudo-class-enabled > .selection::before): Deleted.
Rename the selector to be less ambiguous.

  • UserInterface/Views/DOMTreeOutline.js:

(WebInspector.DOMTreeOutline.prototype.updateSelection): Simplify. The call
to update the selection area will bail out if there is nothing to be done.

(WebInspector.DOMTreeOutline.prototype.findTreeElement):
(WebInspector.DOMTreeOutline.prototype._onmousemove):
(WebInspector.DOMTreeOutline.prototype._onmouseout):
Clean up and use let and arrow functions.

(WebInspector.DOMTreeOutline.prototype._ondragover):
(WebInspector.DOMTreeOutline.prototype._clearDragOverTreeElementMarker):
Clear the dragging element before updating the selection area since it looks at
the dragging element to determine whether anything needs to be done.

  • UserInterface/Views/FormattedValue.css:

(.formatted-node > .tree-outline.dom li.hovered:not(.selected) .selection-area):
(.formatted-node > .tree-outline.dom li.hovered:not(.selected) .selection): Deleted.
Rename the selector to be less ambiguous.

Location:
trunk/Source/WebInspectorUI
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebInspectorUI/ChangeLog

    r201839 r201840  
     12016-06-08  Brian Burg  <bburg@apple.com>
     2
     3        Web Inspector: DOMTreeOutline selection areas should be created and updated lazily
     4        https://bugs.webkit.org/show_bug.cgi?id=158513
     5        <rdar://problem/26689646>
     6
     7        Reviewed by Timothy Hatcher.
     8
     9        Selection areas for DOMTreeElements are used for several things: drag markers,
     10        element hover styles, element selection styles, and showing forced pseudo states
     11        for an element. Fortunately it's easy to tell when any of these things is necessary.
     12
     13        Change DOMTreeOutline and DOMTreeElement so they don't create selection areas
     14        unless they are needed for one of these tasks. This significantly reduces
     15        forced layouts that are required to update the selection area height in case the
     16        element has new attributes that cause the tag to become more or less wrapped.
     17
     18        * UserInterface/Views/DOMTreeElement.js:
     19        (WebInspector.DOMTreeElement.prototype.set hovered):
     20        Modernize this method a bit.
     21
     22        (WebInspector.DOMTreeElement.prototype.updateSelectionArea):
     23        If a selection area is not necessary, don't create one.
     24        If one exists and it's not needed, then remove it.
     25
     26        (WebInspector.DOMTreeElement.prototype.onattach):
     27        Remove redundant calls to updateSelection(). This is already called in
     28        updateTitle().
     29
     30        (WebInspector.DOMTreeElement.prototype.onselect):
     31        Ask the DOMTreeOutline to update the selection rather than forcing the
     32        element to do it. This is consistent with other updates to user selection.
     33
     34        (WebInspector.DOMTreeElement.prototype._insertInLastAttributePosition):
     35        (WebInspector.DOMTreeElement.prototype._startEditingAsHTML.dispose):
     36        (WebInspector.DOMTreeElement.prototype._startEditingAsHTML):
     37        Use renamed method.
     38
     39        (WebInspector.DOMTreeElement.prototype.updateTitle):
     40        Add a comment to explain why the selection area is nulled out here.
     41
     42        (WebInspector.DOMTreeElement.prototype.get pseudoClassesEnabled):
     43        (WebInspector.DOMTreeElement.prototype._nodePseudoClassesDidChange):
     44        Update the selection area in case one does not exist for this tree element.
     45        The indicator for forced pseudo classes is a pseudo element of the selection area.
     46
     47        (WebInspector.DOMTreeElement.prototype.updateSelection): Renamed.
     48        (WebInspector.DOMTreeElement.prototype.onexpand):
     49        (WebInspector.DOMTreeElement.prototype.oncollapse):
     50        Remove redundant calls to updateSelection(). This is already called in
     51        updateTitle().
     52
     53        * UserInterface/Views/DOMTreeOutline.css:
     54        (.tree-outline.dom):
     55        (.tree-outline.dom li.hovered:not(.selected) .selection-area):
     56        (.tree-outline.dom li .selection-area):
     57        (.tree-outline.dom li.selected .selection-area):
     58        (.tree-outline.dom li.elements-drag-over .selection-area):
     59        (.tree-outline.dom:focus li.selected .selection-area):
     60        (.tree-outline.dom li.pseudo-class-enabled > .selection-area::before):
     61        (.tree-outline.dom:focus li.selected.pseudo-class-enabled > .selection-area::before):
     62        (.tree-outline.dom li.hovered:not(.selected) .selection): Deleted.
     63        (.tree-outline.dom li .selection): Deleted.
     64        (.tree-outline.dom li.selected .selection): Deleted.
     65        (.tree-outline.dom li.elements-drag-over .selection): Deleted.
     66        (.tree-outline.dom:focus li.selected .selection): Deleted.
     67        (.tree-outline.dom li.pseudo-class-enabled > .selection::before): Deleted.
     68        (.tree-outline.dom:focus li.selected.pseudo-class-enabled > .selection::before): Deleted.
     69        Rename the selector to be less ambiguous.
     70
     71        * UserInterface/Views/DOMTreeOutline.js:
     72        (WebInspector.DOMTreeOutline.prototype.updateSelection): Simplify. The call
     73        to update the selection area will bail out if there is nothing to be done.
     74
     75        (WebInspector.DOMTreeOutline.prototype.findTreeElement):
     76        (WebInspector.DOMTreeOutline.prototype._onmousemove):
     77        (WebInspector.DOMTreeOutline.prototype._onmouseout):
     78        Clean up and use let and arrow functions.
     79
     80        (WebInspector.DOMTreeOutline.prototype._ondragover):
     81        (WebInspector.DOMTreeOutline.prototype._clearDragOverTreeElementMarker):
     82        Clear the dragging element before updating the selection area since it looks at
     83        the dragging element to determine whether anything needs to be done.
     84
     85        * UserInterface/Views/FormattedValue.css:
     86        (.formatted-node > .tree-outline.dom li.hovered:not(.selected) .selection-area):
     87        (.formatted-node > .tree-outline.dom li.hovered:not(.selected) .selection): Deleted.
     88        Rename the selector to be less ambiguous.
     89
    1902016-06-08  Brian Burg  <bburg@apple.com>
    291
  • trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeElement.js

    r201833 r201840  
    145145    }
    146146
    147     set hovered(x)
    148     {
    149         if (this._hovered === x)
    150             return;
    151 
    152         this._hovered = x;
     147    set hovered(value)
     148    {
     149        if (this._hovered === value)
     150            return;
     151
     152        this._hovered = value;
    153153
    154154        if (this.listItemElement) {
    155             if (x) {
    156                 this.updateSelection();
    157                 this.listItemElement.classList.add("hovered");
    158             } else {
    159                 this.listItemElement.classList.remove("hovered");
    160             }
     155            this.listItemElement.classList.toggle("hovered", this._hovered);
     156            this.updateSelectionArea();
    161157        }
    162158    }
     
    263259    }
    264260
    265     updateSelection()
    266     {
    267         var listItemElement = this.listItemElement;
     261    updateSelectionArea()
     262    {
     263        let listItemElement = this.listItemElement;
    268264        if (!listItemElement)
    269265            return;
    270266
    271         if (!this.selectionElement) {
    272             this.selectionElement = document.createElement("div");
    273             this.selectionElement.className = "selection selected";
    274             listItemElement.insertBefore(this.selectionElement, listItemElement.firstChild);
    275         }
    276 
    277         this.selectionElement.style.height = listItemElement.offsetHeight + "px";
     267        // If there's no reason to have a selection area, remove the DOM element.
     268        let indicatesTreeOutlineState = this.treeOutline && (this.treeOutline.dragOverTreeElement === this || this.treeOutline.selectedTreeElement === this);
     269        if (!this.hovered && !this.pseudoClassesEnabled && !indicatesTreeOutlineState) {
     270            if (this._selectionElement) {
     271                this._selectionElement.remove();
     272                this._selectionElement = null;
     273            }
     274
     275            return;
     276        }
     277
     278        if (!this._selectionElement) {
     279            this._selectionElement = document.createElement("div");
     280            this._selectionElement.className = "selection-area";
     281            listItemElement.insertBefore(this._selectionElement, listItemElement.firstChild);
     282        }
     283
     284        this._selectionElement.style.height = listItemElement.offsetHeight + "px";
    278285    }
    279286
    280287    onattach()
    281288    {
    282         if (this._hovered) {
    283             this.updateSelection();
     289        if (this.hovered)
    284290            this.listItemElement.classList.add("hovered");
    285         }
    286291
    287292        this.updateTitle();
     
    485490
    486491        this.updateTitle();
    487         this.treeOutline.updateSelection();
    488492    }
    489493
     
    494498
    495499        this.updateTitle();
    496         this.treeOutline.updateSelection();
    497500    }
    498501
     
    514517        if (selectedByUser)
    515518            WebInspector.domTreeManager.highlightDOMNode(this.representedObject.id);
    516         this.updateSelection();
     519        this.treeOutline.updateSelection();
    517520        this.treeOutline.suppressRevealAndSelect = false;
    518521    }
     
    589592        }
    590593
    591         this.updateSelection();
     594        this.updateSelectionArea();
    592595    }
    593596
     
    855858        this.listItemElement.appendChild(this._htmlEditElement);
    856859
    857         this.updateSelection();
     860        this.updateSelectionArea();
    858861
    859862        function commit()
     
    880883            }
    881884
    882             this.updateSelection();
     885            this.updateSelectionArea();
    883886        }
    884887
     
    10741077        }
    10751078
    1076         this.selectionElement = null;
    1077         this.updateSelection();
     1079        // Setting this.title will implicitly remove all children. Clear the
     1080        // selection element so that we properly recreate it if necessary.
     1081        this._selectionElement = null;
     1082        this.updateSelectionArea();
    10781083        this._highlightSearchResults();
    10791084    }
     
    15191524    }
    15201525
     1526    get pseudoClassesEnabled()
     1527    {
     1528        return !!this.representedObject.enabledPseudoClasses.length;
     1529    }
     1530
    15211531    _nodePseudoClassesDidChange(event)
    15221532    {
     
    15241534            return;
    15251535
     1536        this.updateSelectionArea();
    15261537        this._listItemNode.classList.toggle("pseudo-class-enabled", !!this.representedObject.enabledPseudoClasses.length);
    15271538    }
  • trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.css

    r201454 r201840  
    3535    list-style-type: none;
    3636
    37  /* Needed to make the negative z-index on .selection works. Otherwise the background-color from .syntax-highlighted hides the selection. */
     37 /* Needed to make the negative z-index on .selection-area works. Otherwise the background-color from .syntax-highlighted hides the selection. */
    3838    background-color: transparent !important;
    3939    color: black;
    4040}
    4141
    42 .tree-outline.dom li.hovered:not(.selected) .selection {
     42.tree-outline.dom li.hovered:not(.selected) .selection-area {
    4343    background-color: hsla(209, 100%, 49%, 0.1);
    4444}
    4545
    46 .tree-outline.dom li .selection {
     46.tree-outline.dom li .selection-area {
    4747    position: absolute;
    4848    left: 0;
     
    5252}
    5353
    54 .tree-outline.dom li.selected .selection {
     54.tree-outline.dom li.selected .selection-area {
    5555    background-color: hsl(0, 0%, 83%);
    5656}
    5757
    58 .tree-outline.dom li.elements-drag-over .selection {
     58.tree-outline.dom li.elements-drag-over .selection-area {
    5959    margin-top: -2px;
    6060    border-top: 2px solid hsl(209, 100%, 49%);
    6161}
    6262
    63 .tree-outline.dom:focus li.selected .selection {
     63.tree-outline.dom:focus li.selected .selection-area {
    6464    background-color: hsl(209, 100%, 49%);
    6565}
     
    110110}
    111111
    112 .tree-outline.dom li.pseudo-class-enabled > .selection::before {
     112.tree-outline.dom li.pseudo-class-enabled > .selection-area::before {
    113113    display: inline-block;
    114114    position: absolute;
     
    130130}
    131131
    132 .tree-outline.dom:focus li.selected.pseudo-class-enabled > .selection::before {
     132.tree-outline.dom:focus li.selected.pseudo-class-enabled > .selection-area::before {
    133133    background-color: hsl(0, 100%, 100%);
    134134}
  • trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.js

    r200539 r201840  
    190190    updateSelection()
    191191    {
    192         if (!this.selectedTreeElement)
    193             return;
    194         var element = this.treeOutline.selectedTreeElement;
    195         element.updateSelection();
     192        // This will miss updating selection areas used for the hovered tree element and
     193        // and those used to show forced pseudo class indicators, but this should be okay.
     194        // The hovered element will update when user moves the mouse, and indicators don't need the
     195        // selection area height to be accurate since they use ::before to place the indicator.
     196        if (this.selectedTreeElement)
     197            this.selectedTreeElement.updateSelectionArea();
    196198    }
    197199
     
    203205    findTreeElement(node)
    204206    {
    205         function isAncestorNode(ancestor, node)
    206         {
    207             return ancestor.isAncestor(node);
    208         }
    209 
    210         function parentNode(node)
    211         {
    212             return node.parentNode;
    213         }
    214 
    215         var treeElement = super.findTreeElement(node, isAncestorNode, parentNode);
     207        let isAncestorNode = (ancestor, node) => ancestor.isAncestor(node);
     208        let parentNode = (node) => node.parentNode;
     209        let treeElement = super.findTreeElement(node, isAncestorNode, parentNode);
    216210        if (!treeElement && node.nodeType() === Node.TEXT_NODE) {
    217211            // The text node might have been inlined if it was short, so try to find the parent element.
     
    342336        if (this._previousHoveredElement) {
    343337            this._previousHoveredElement.hovered = false;
    344             delete this._previousHoveredElement;
     338            this._previousHoveredElement = null;
    345339        }
    346340
     
    365359        if (this._previousHoveredElement) {
    366360            this._previousHoveredElement.hovered = false;
    367             delete this._previousHoveredElement;
     361            this._previousHoveredElement = null;
    368362        }
    369363
     
    408402        }
    409403
    410         treeElement.updateSelection();
     404        this.dragOverTreeElement = treeElement;
    411405        treeElement.listItemElement.classList.add("elements-drag-over");
    412         this._dragOverTreeElement = treeElement;
     406        treeElement.updateSelectionArea();
     407
    413408        event.preventDefault();
    414409        event.dataTransfer.dropEffect = "move";
     
    482477    _clearDragOverTreeElementMarker()
    483478    {
    484         if (this._dragOverTreeElement) {
    485             this._dragOverTreeElement.updateSelection();
    486             this._dragOverTreeElement.listItemElement.classList.remove("elements-drag-over");
    487             delete this._dragOverTreeElement;
     479        if (this.dragOverTreeElement) {
     480            let element = this.dragOverTreeElement;
     481            this.dragOverTreeElement = null;
     482
     483            element.listItemElement.classList.remove("elements-drag-over");
     484            element.updateSelectionArea();
    488485        }
    489486    }
  • trunk/Source/WebInspectorUI/UserInterface/Views/FormattedValue.css

    r195303 r201840  
    7777}
    7878
    79 .formatted-node > .tree-outline.dom li.hovered:not(.selected) .selection {
     79.formatted-node > .tree-outline.dom li.hovered:not(.selected) .selection-area {
    8080    display: block;
    8181    left: -1px;
Note: See TracChangeset for help on using the changeset viewer.