Title: [185723] trunk/Source/WebInspectorUI
Revision
185723
Author
[email protected]
Date
2015-06-18 15:24:37 -0700 (Thu, 18 Jun 2015)

Log Message

Web Inspector: Add a filter for CSS properties in the Styles sidebar
https://bugs.webkit.org/show_bug.cgi?id=145536

Patch by Devin Rousso <[email protected]> on 2015-06-18
Reviewed by Timothy Hatcher.

* UserInterface/Base/Utilities.js: Added function to Strings that returns an array of all matching indexes of a given string.
(.value):
* UserInterface/Views/CSSStyleDeclarationSection.js:
(WebInspector.CSSStyleDeclarationSection):
(WebInspector.CSSStyleDeclarationSection.prototype.refresh.appendSelector):
(WebInspector.CSSStyleDeclarationSection.prototype.findMatchingPropertiesAndSelectors): Loops through the property list and selectors of each section to find matches to the filtered text.
* UserInterface/Views/CSSStyleDeclarationTextEditor.js:
(WebInspector.CSSStyleDeclarationTextEditor.prototype.findMatchingProperties): Searches through the properties list to find and highlight all matching properties.
(WebInspector.CSSStyleDeclarationTextEditor.prototype.removeNonMatchingProperties): Removes all properties that do not match and highlights the specific matched text in matching properties.
(WebInspector.CSSStyleDeclarationTextEditor.prototype.resetFilteredProperties): Restores all properties to full visibility and removes any highlighting.
(WebInspector.CSSStyleDeclarationTextEditor.prototype._createTextMarkerForPropertyIfNeeded): Classes are added to selections of the text editor of that partiular selection contains text which matches the filter (see CSSStyleDetailsSidebarPanel.css for different classes).
(WebInspector.CSSStyleDeclarationTextEditor.prototype._iterateOverProperties): If a filter is active, find properties matching the filter instead of all properties.
* UserInterface/Views/CSSStyleDetailsSidebarPanel.css:
(.sidebar > .panel.details.css-style > .content.has-filter-bar + .filter-bar):
(.sidebar > .panel.details.css-style > .content:not(.has-filter-bar) + .filter-bar):
* UserInterface/Views/CSSStyleDetailsSidebarPanel.js:
(WebInspector.CSSStyleDetailsSidebarPanel): Added a filter bar to the CSS sidebar.
(WebInspector.CSSStyleDetailsSidebarPanel.prototype._switchPanels): Switching panels preserves and applies filter bar text.
(WebInspector.CSSStyleDetailsSidebarPanel.prototype._filterDidChange): Function called when the filter bar text changes that calls the current panel's filterDidChange function if it exists.
* UserInterface/Views/FilterBar.js: Added function and variable to check if the text in the filter bar had changed.
* UserInterface/Views/MetricsStyleDetailsPanel.js:
(WebInspector.MetricsStyleDetailsPanel.prototype.refresh): Now calls superclass refresh.
(WebInspector.MetricsStyleDetailsPanel): Added delegate variable to constructor.
* UserInterface/Views/RulesStyleDetailsPanel.css:
(.sidebar > .panel.details.css-style > .content.filter-in-progress .label):
(.sidebar > .panel.details.css-style > .content.filter-in-progress .label ~ .label):
(.sidebar > .panel.details.css-style > .content.filter-in-progress .label.filter-matching-label):
(.sidebar > .panel.details.css-style > .content.filter-in-progress .new-rule):
(.sidebar > .panel.details.css-style > .content.filter-in-progress .style-declaration-section:not(.filter-section-non-matching) ~ .label:not(.filter-section-non-matching)):
(.sidebar > .panel.details.css-style > .content:not(.filter-in-progress) > .rules > .new-rule + .style-declaration-section):
(.sidebar > .panel.details.css-style > .content > .rules:not(.filter-non-matching) > .no-filter-results):
(.sidebar > .panel.details.css-style > .content.filter-in-progress > .rules.filter-non-matching > .no-filter-results):
(.sidebar > .panel.details.css-style > .content.filter-in-progress > .rules.filter-non-matching > .no-filter-results > .no-filter-results-message):
* UserInterface/Views/RulesStyleDetailsPanel.js:
(WebInspector.RulesStyleDetailsPanel): Added delegate variable to constructor.
(WebInspector.RulesStyleDetailsPanel.prototype.refresh): Now calls superclass refresh.
(WebInspector.RulesStyleDetailsPanel.prototype.filterDidChange): Function to search through the computed styles list and highlight all matched properties and selectors of the filter bar text, turning all non matching properties slightly opaque (unless a selector for that property is a match).
(WebInspector.StyleDetailsPanel): Added delegate variable to constructor.
(WebInspector.StyleDetailsPanel.prototype.refresh): Added event dispatch for panel refresh.

Modified Paths

Diff

Modified: trunk/Source/WebInspectorUI/ChangeLog (185722 => 185723)


--- trunk/Source/WebInspectorUI/ChangeLog	2015-06-18 22:07:15 UTC (rev 185722)
+++ trunk/Source/WebInspectorUI/ChangeLog	2015-06-18 22:24:37 UTC (rev 185723)
@@ -1,5 +1,52 @@
 2015-06-18  Devin Rousso  <[email protected]>
 
+        Web Inspector: Add a filter for CSS properties in the Styles sidebar
+        https://bugs.webkit.org/show_bug.cgi?id=145536
+
+        Reviewed by Timothy Hatcher.
+
+        * UserInterface/Base/Utilities.js: Added function to Strings that returns an array of all matching indexes of a given string.
+        (.value):
+        * UserInterface/Views/CSSStyleDeclarationSection.js:
+        (WebInspector.CSSStyleDeclarationSection):
+        (WebInspector.CSSStyleDeclarationSection.prototype.refresh.appendSelector):
+        (WebInspector.CSSStyleDeclarationSection.prototype.findMatchingPropertiesAndSelectors): Loops through the property list and selectors of each section to find matches to the filtered text.
+        * UserInterface/Views/CSSStyleDeclarationTextEditor.js:
+        (WebInspector.CSSStyleDeclarationTextEditor.prototype.findMatchingProperties): Searches through the properties list to find and highlight all matching properties.
+        (WebInspector.CSSStyleDeclarationTextEditor.prototype.removeNonMatchingProperties): Removes all properties that do not match and highlights the specific matched text in matching properties.
+        (WebInspector.CSSStyleDeclarationTextEditor.prototype.resetFilteredProperties): Restores all properties to full visibility and removes any highlighting.
+        (WebInspector.CSSStyleDeclarationTextEditor.prototype._createTextMarkerForPropertyIfNeeded): Classes are added to selections of the text editor of that partiular selection contains text which matches the filter (see CSSStyleDetailsSidebarPanel.css for different classes).
+        (WebInspector.CSSStyleDeclarationTextEditor.prototype._iterateOverProperties): If a filter is active, find properties matching the filter instead of all properties.
+        * UserInterface/Views/CSSStyleDetailsSidebarPanel.css:
+        (.sidebar > .panel.details.css-style > .content.has-filter-bar + .filter-bar):
+        (.sidebar > .panel.details.css-style > .content:not(.has-filter-bar) + .filter-bar):
+        * UserInterface/Views/CSSStyleDetailsSidebarPanel.js:
+        (WebInspector.CSSStyleDetailsSidebarPanel): Added a filter bar to the CSS sidebar.
+        (WebInspector.CSSStyleDetailsSidebarPanel.prototype._switchPanels): Switching panels preserves and applies filter bar text.
+        (WebInspector.CSSStyleDetailsSidebarPanel.prototype._filterDidChange): Function called when the filter bar text changes that calls the current panel's filterDidChange function if it exists.
+        * UserInterface/Views/FilterBar.js: Added function and variable to check if the text in the filter bar had changed.
+        * UserInterface/Views/MetricsStyleDetailsPanel.js:
+        (WebInspector.MetricsStyleDetailsPanel.prototype.refresh): Now calls superclass refresh.
+        (WebInspector.MetricsStyleDetailsPanel): Added delegate variable to constructor.
+        * UserInterface/Views/RulesStyleDetailsPanel.css:
+        (.sidebar > .panel.details.css-style > .content.filter-in-progress .label):
+        (.sidebar > .panel.details.css-style > .content.filter-in-progress .label ~ .label):
+        (.sidebar > .panel.details.css-style > .content.filter-in-progress .label.filter-matching-label):
+        (.sidebar > .panel.details.css-style > .content.filter-in-progress .new-rule):
+        (.sidebar > .panel.details.css-style > .content.filter-in-progress .style-declaration-section:not(.filter-section-non-matching) ~ .label:not(.filter-section-non-matching)):
+        (.sidebar > .panel.details.css-style > .content:not(.filter-in-progress) > .rules > .new-rule + .style-declaration-section):
+        (.sidebar > .panel.details.css-style > .content > .rules:not(.filter-non-matching) > .no-filter-results):
+        (.sidebar > .panel.details.css-style > .content.filter-in-progress > .rules.filter-non-matching > .no-filter-results):
+        (.sidebar > .panel.details.css-style > .content.filter-in-progress > .rules.filter-non-matching > .no-filter-results > .no-filter-results-message):
+        * UserInterface/Views/RulesStyleDetailsPanel.js:
+        (WebInspector.RulesStyleDetailsPanel): Added delegate variable to constructor.
+        (WebInspector.RulesStyleDetailsPanel.prototype.refresh): Now calls superclass refresh.
+        (WebInspector.RulesStyleDetailsPanel.prototype.filterDidChange): Function to search through the computed styles list and highlight all matched properties and selectors of the filter bar text, turning all non matching properties slightly opaque (unless a selector for that property is a match).
+        (WebInspector.StyleDetailsPanel): Added delegate variable to constructor.
+        (WebInspector.StyleDetailsPanel.prototype.refresh): Added event dispatch for panel refresh.
+
+2015-06-18  Devin Rousso  <[email protected]>
+
         Web Inspector: Ability to Copy entire CSS Rule from Styles Sidebar
         https://bugs.webkit.org/show_bug.cgi?id=138812
 

Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (185722 => 185723)


--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js	2015-06-18 22:07:15 UTC (rev 185722)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js	2015-06-18 22:24:37 UTC (rev 185723)
@@ -127,8 +127,8 @@
 localizedStrings["Cookies"] = "Cookies";
 localizedStrings["Copy Path to Property"] = "Copy Path to Property";
 localizedStrings["Copy Row"] = "Copy Row";
-localizedStrings["Copy gs["New TaCopy = "New Tab";
-localizedStrCopy as HTML"] = "Copy as HTML";
+localizedStrings["Copy Rule"] = "Copy Rule";
+localizedStrings["Copy as HTML"] = "Copy as HTML";
 localizedStrings["Could not fetch properties. Object may no longer exist."] = "Could not fetch properties. Object may no longer exist.";
 localizedStrings["Create a new tab"] = "Create a new tab";
 localizedStrings["Data"] = "Data";
@@ -225,6 +225,7 @@
 localizedStrings["Filter Resource List"] = "Filter Resource List";
 localizedStrings["Filter Search Results"] = "Filter Search Results";
 localizedStrings["Filter Storage List"] = "Filter Storage List";
+localizedStrings["Filter Styles"] = "Filter Styles";
 localizedStrings["Flows"] = "Flows";
 localizedStrings["Focused"] = "Focused";
 localizedStrings["Font"] = "Font";
@@ -337,6 +338,7 @@
 localizedStrings["No Query Parameters"] = "No Query Parameters";
 localizedStrings["No Request Headers"] = "No Request Headers";
 localizedStrings["No Response Headers"] = "No Response Headers";
+localizedStrings["No Results Found"] = "No Results Found";
 localizedStrings["No Search Results"] = "No Search Results";
 localizedStrings["No exact ARIA role match."] = "No exact ARIA role match.";
 localizedStrings["No message"] = "No message";

Modified: trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js (185722 => 185723)


--- trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js	2015-06-18 22:07:15 UTC (rev 185722)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js	2015-06-18 22:24:37 UTC (rev 185723)
@@ -748,6 +748,22 @@
     }
 });
 
+Object.defineProperty(String.prototype, "getMatchingIndexes",
+{
+    value: function(needle)
+    {
+        var indexesOfNeedle = [];
+        var index = this.indexOf(needle);
+
+        while (index >= 0) {
+            indexesOfNeedle.push(index);
+            index = this.indexOf(needle, index + 1);
+        }
+
+        return indexesOfNeedle;
+    }
+});
+
 Object.defineProperty(Number, "constrain",
 {
     value: function(num, min, max)

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDeclarationSection.js (185722 => 185723)


--- trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDeclarationSection.js	2015-06-18 22:07:15 UTC (rev 185722)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDeclarationSection.js	2015-06-18 22:24:37 UTC (rev 185723)
@@ -32,6 +32,7 @@
 
     console.assert(style);
     this._style = style || null;
+    this._selectorElements = [];
 
     this._element = document.createElement("div");
     this._element.className = "style-declaration-section";
@@ -164,6 +165,7 @@
     {
         this._selectorElement.removeChildren();
         this._originElement.removeChildren();
+        this._selectorElements = [];
 
         this._originElement.appendChild(document.createTextNode(" \u2014 "));
 
@@ -196,6 +198,7 @@
             }
 
             this._selectorElement.appendChild(selectorElement);
+            this._selectorElements.push(selectorElement);
         }
 
         function appendSelectorTextKnownToMatch(selectorText)
@@ -274,6 +277,36 @@
         return false;
     },
 
+    findMatchingPropertiesAndSelectors: function(needle)
+    {
+        this._element.classList.remove(WebInspector.CSSStyleDetailsSidebarPanel.NoFilterMatchInSectionClassName, WebInspector.CSSStyleDetailsSidebarPanel.FilterMatchingSectionHasLabelClassName);
+
+        var hasMatchingSelector = false;
+
+        for (var selectorElement of this._selectorElements) {
+            selectorElement.classList.remove(WebInspector.CSSStyleDetailsSidebarPanel.FilterMatchSectionClassName);
+
+            if (needle && selectorElement.textContent.includes(needle)) {
+                selectorElement.classList.add(WebInspector.CSSStyleDetailsSidebarPanel.FilterMatchSectionClassName);
+                hasMatchingSelector = true;
+            }
+        }
+
+        if (!needle) {
+            this._propertiesTextEditor.resetFilteredProperties();
+            return false;
+        }
+
+        var hasMatchingProperty = this._propertiesTextEditor.findMatchingProperties(needle);
+
+        if (!hasMatchingProperty && !hasMatchingSelector) {
+            this._element.classList.add(WebInspector.CSSStyleDetailsSidebarPanel.NoFilterMatchInSectionClassName);
+            return false;
+        }
+
+        return true;
+    },
+
     updateLayout: function()
     {
         this._propertiesTextEditor.updateLayout();

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDeclarationTextEditor.js (185722 => 185723)


--- trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDeclarationTextEditor.js	2015-06-18 22:07:15 UTC (rev 185722)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDeclarationTextEditor.js	2015-06-18 22:24:37 UTC (rev 185723)
@@ -36,6 +36,7 @@
 
         this._showsImplicitProperties = true;
         this._alwaysShowPropertyNames = {};
+        this._filterResultPropertyNames = null;
         this._sortProperties = false;
 
         this._prefixWhitespace = "";
@@ -229,6 +230,78 @@
         this._codeMirror.setCursor({line: 0, ch: 0});
     }
 
+    findMatchingProperties(needle)
+    {
+        if (!needle) {
+            this.resetFilteredProperties();
+            return false;
+        }
+
+        var propertiesList = this._style.visibleProperties.length ? this._style.visibleProperties : this._style.properties;
+        var matchingProperties = [];
+
+        for (var property of propertiesList)
+            matchingProperties.push(property.text.includes(needle));
+
+        if (!matchingProperties.includes(true)) {
+            this.resetFilteredProperties();
+            return false;
+        }
+
+        for (var i = 0; i < matchingProperties.length; ++i) {
+            var property = propertiesList[i];
+
+            if (matchingProperties[i])
+                property.__filterResultClassName = WebInspector.CSSStyleDetailsSidebarPanel.FilterMatchSectionClassName;
+            else
+                property.__filterResultClassName = WebInspector.CSSStyleDetailsSidebarPanel.NoFilterMatchInPropertyClassName;
+
+            this._updateTextMarkerForPropertyIfNeeded(property);
+        }
+
+        return true;
+    }
+
+    resetFilteredProperties()
+    {
+        var propertiesList = this._style.visibleProperties.length ? this._style.visibleProperties : this._style.properties;
+
+        for (var property of propertiesList) {
+            if (property.__filterResultClassName) {
+                property.__filterResultClassName = null;
+                this._updateTextMarkerForPropertyIfNeeded(property)
+            }
+        }
+    }
+
+    removeNonMatchingProperties(needle)
+    {
+        this._filterResultPropertyNames = null;
+
+        if (!needle) {
+            this._resetContent();
+            return false;
+        }
+
+        var matchingPropertyNames = [];
+
+        for (var property of this._style.properties) {
+            var indexesOfNeedle = property.text.getMatchingIndexes(needle);
+
+            if (indexesOfNeedle.length) {
+                matchingPropertyNames.push(property.name);
+                property.__filterResultClassName = WebInspector.CSSStyleDetailsSidebarPanel.FilterMatchSectionClassName;
+                property.__filterResultNeedlePosition = {start: indexesOfNeedle, length: needle.length};
+            }
+        }
+
+        this._filterResultPropertyNames = matchingPropertyNames.length ? matchingPropertyNames.keySet() : {};
+
+        this._resetContent();
+
+        return matchingPropertyNames.length > 0;
+    }
+
     // Protected
 
     didDismissPopover(popover)
@@ -527,6 +600,9 @@
         if (!property.enabled)
             classNames.push("disabled");
 
+        if (property.__filterResultClassName && !property.__filterResultNeedlePosition)
+            classNames.push(property.__filterResultClassName);
+
         var classNamesString = classNames.join(" ");
 
         // If there is already a text marker and it's in the same document, then try to avoid recreating it.
@@ -558,6 +634,15 @@
 
             this._codeMirror.markText(start, end, {className: "invalid"});
         }
+
+        if (property.__filterResultClassName && property.__filterResultNeedlePosition) {
+            for (var needlePosition of property.__filterResultNeedlePosition.start) {
+                var start = {line: from.line, ch: needlePosition};
+                var end = {line: to.line, ch: start.ch + property.__filterResultNeedlePosition.length};
+
+                this._codeMirror.markText(start, end, {className: property.__filterResultClassName});
+            }
+        }
     }
 
     _clearTextMarkers(nonatomic, all)
@@ -597,7 +682,14 @@
     {
         var properties = onlyVisibleProperties ? this._style.visibleProperties : this._style.properties;
 
-        if (!onlyVisibleProperties) {
+        if (this._filterResultPropertyNames) {
+            properties = properties.filter(function(property) {
+                return (!property.implicit || this._showsImplicitProperties) && property.name in this._filterResultPropertyNames;
+            }, this);
+
+            if (this._sortProperties)
+                properties.sort(function(a, b) { return a.name.localeCompare(b.name); });
+        } else if (!onlyVisibleProperties) {
             // Filter based on options only when all properties are used.
             properties = properties.filter(function(property) {
                 return !property.implicit || this._showsImplicitProperties || property.canonicalName in this._alwaysShowPropertyNames;

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDetailsSidebarPanel.css (185722 => 185723)


--- trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDetailsSidebarPanel.css	2015-06-18 22:07:15 UTC (rev 185722)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDetailsSidebarPanel.css	2015-06-18 22:24:37 UTC (rev 185723)
@@ -42,6 +42,10 @@
     overflow-x: hidden;
 }
 
+.sidebar > .panel.details.css-style > .content.has-filter-bar {
+    bottom: 28px;
+}
+
 .sidebar > .panel.details.css-style > .content > .pseudo-classes {
     padding: 10px;
     border-bottom: 1px solid rgb(179, 179, 179);
@@ -68,3 +72,49 @@
     display: inline-block;
     white-space: nowrap;
 }
+
+.sidebar > .panel.details.css-style > .content.has-filter-bar + .filter-bar {
+    position: absolute;
+    bottom: 0;
+    width: 100%;
+    background-color: white;
+    border-top: 1px solid rgb(179, 179, 179);
+}
+
+.sidebar > .panel.details.css-style > .content:not(.has-filter-bar) + .filter-bar {
+    display: none;
+}
+
+.sidebar > .panel.details.css-style > .content.filter-in-progress .filter-matching {
+    display: inline;
+    background-color: rgba(235, 215, 38, 0.5);
+    border-bottom: 1px solid rgb(237, 202, 71);
+    opacity: 1;
+}
+
+.sidebar > .panel.details.css-style > .content.filter-in-progress .style-declaration-section {
+    margin-bottom: 0;
+}
+
+.sidebar > .panel.details.css-style > .content.filter-in-progress .style-declaration-section.last-in-group.filter-section-non-matching + .style-declaration-section.filter-section-has-label {
+    margin-top: 0;
+    border-top: none;
+}
+
+.sidebar > .panel.details.css-style > .content.filter-in-progress .style-declaration-section:not(.filter-section-has-label) {
+    margin-top: 0;
+    border-top: none;
+    border-bottom: 1px solid rgb(179, 179, 179);
+}
+
+.sidebar > .panel.details.css-style > .content.filter-in-progress .style-declaration-section > .header > .selector > .filter-matching {
+    color: black;
+}
+
+.sidebar > .panel.details.css-style > .content.filter-in-progress .filter-section-non-matching {
+    display: none;
+}
+
+.sidebar > .panel.details.css-style > .content.filter-in-progress .filter-property-non-matching {
+    opacity: 0.5;
+}

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDetailsSidebarPanel.js (185722 => 185723)


--- trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDetailsSidebarPanel.js	2015-06-18 22:07:15 UTC (rev 185722)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDetailsSidebarPanel.js	2015-06-18 22:24:37 UTC (rev 185723)
@@ -71,9 +71,12 @@
         }
 
         this._computedStyleDetailsPanel = new WebInspector.ComputedStyleDetailsPanel(this);
-        this._rulesStyleDetailsPanel = new WebInspector.RulesStyleDetailsPanel;
-        this._metricsStyleDetailsPanel = new WebInspector.MetricsStyleDetailsPanel;
+        this._rulesStyleDetailsPanel = new WebInspector.RulesStyleDetailsPanel(this);
+        this._metricsStyleDetailsPanel = new WebInspector.MetricsStyleDetailsPanel(this);
 
+        this._computedStyleDetailsPanel.addEventListener(WebInspector.StyleDetailsPanel.Event.Refreshed, this._filterDidChange, this);
+        this._rulesStyleDetailsPanel.addEventListener(WebInspector.StyleDetailsPanel.Event.Refreshed, this._filterDidChange, this);
+
         this._panels = [this._computedStyleDetailsPanel, this._rulesStyleDetailsPanel, this._metricsStyleDetailsPanel];
 
         this._navigationBar.addNavigationItem(this._computedStyleDetailsPanel.navigationItem);
@@ -84,6 +87,11 @@
 
         // This will cause the selected panel to be set in _navigationItemSelected.
         this._navigationBar.selectedNavigationItem = this._lastSelectedSectionSetting.value;
+
+        this._filterBar = new WebInspector.FilterBar;
+        this._filterBar.placeholder = WebInspector.UIString("Filter Styles");
+        this._filterBar.addEventListener(WebInspector.FilterBar.Event.FilterDidChange, this._filterDidChange, this);
+        this.element.appendChild(this._filterBar.element);
     }
 
     // Public
@@ -211,6 +219,11 @@
             else
                 this.contentElement.scrollTop = this._initialScrollOffset;
 
+            var hasFilter = typeof this._selectedPanel.filterDidChange === "function";
+            this.contentElement.classList.toggle("has-filter-bar", hasFilter);
+            if (this._filterBar)
+                this.contentElement.classList.toggle(WebInspector.CSSStyleDetailsSidebarPanel.FilterInProgressClassName, hasFilter && this._filterBar.hasActiveFilters());
+
             this._selectedPanel.shown();
         }
 
@@ -237,6 +250,19 @@
             checkboxElement.checked = enabledPseudoClasses.includes(pseudoClass);
         }
     }
+
+    _filterDidChange()
+    {
+        this.contentElement.classList.toggle(WebInspector.CSSStyleDetailsSidebarPanel.FilterInProgressClassName, this._filterBar.hasActiveFilters());
+
+        this._selectedPanel.filterDidChange(this._filterBar);
+    }
 };
 
 WebInspector.CSSStyleDetailsSidebarPanel.NoForcedPseudoClassesScrollOffset = 38; // Default height of the forced pseudo classes container. Updated in widthDidChange.
+WebInspector.CSSStyleDetailsSidebarPanel.FilterInProgressClassName = "filter-in-progress";
+WebInspector.CSSStyleDetailsSidebarPanel.FilterMatchingSectionHasLabelClassName = "filter-section-has-label";
+WebInspector.CSSStyleDetailsSidebarPanel.FilterMatchSectionClassName = "filter-matching";
+WebInspector.CSSStyleDetailsSidebarPanel.NoFilterMatchInSectionClassName = "filter-section-non-matching";
+WebInspector.CSSStyleDetailsSidebarPanel.NoFilterMatchInPropertyClassName = "filter-property-non-matching";
+

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ComputedStyleDetailsPanel.js (185722 => 185723)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ComputedStyleDetailsPanel.js	2015-06-18 22:07:15 UTC (rev 185722)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ComputedStyleDetailsPanel.js	2015-06-18 22:24:37 UTC (rev 185723)
@@ -27,10 +27,8 @@
 {
     constructor(delegate)
     {
-        super(WebInspector.ComputedStyleDetailsPanel.StyleClassName, "computed", WebInspector.UIString("Computed"));
+        super(delegate, WebInspector.ComputedStyleDetailsPanel.StyleClassName, "computed", WebInspector.UIString("Computed"));
 
-        this._delegate = delegate || null;
-
         this._computedStyleShowAllSetting = new WebInspector.Setting("computed-style-show-all", false);
 
         var computedStyleShowAllLabel = document.createElement("label");
@@ -153,8 +151,15 @@
     {
         this._propertiesTextEditor.style = this.nodeStyles.computedStyle;
         this._refreshFlowDetails(this.nodeStyles.node);
+
+        super.refresh();
     }
 
+    filterDidChange(filterBar)
+    {
+        this._propertiesTextEditor.removeNonMatchingProperties(filterBar.filters.text);
+    }
+
     // Protected
 
     shown()

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/FilterBar.js (185722 => 185723)


--- trunk/Source/WebInspectorUI/UserInterface/Views/FilterBar.js	2015-06-18 22:07:15 UTC (rev 185722)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/FilterBar.js	2015-06-18 22:24:37 UTC (rev 185723)
@@ -43,6 +43,8 @@
         this._inputField.incremental = true;
         this._inputField.addEventListener("search", this._handleFilterChanged.bind(this), false);
         this._element.appendChild(this._inputField);
+
+        this._lastFilterValue = this.filters;
     }
 
     // Public
@@ -99,6 +101,21 @@
         return !!this._inputField.value || !!this._filterFunctionsMap.size;
     }
 
+    hasFilterChanged()
+    {
+        var currentFunctions = this.filters.functions;
+
+        if (this._lastFilterValue.text !== this._inputField.value || this._lastFilterValue.functions.length !== currentFunctions.length)
+            return true;
+
+        for (var i = 0; i < currentFunctions.length; ++i) {
+            if (this._lastFilterValue.functions[i] !== currentFunctions[i])
+                return true;
+        }
+
+        return false;
+    }
+
     // Private
 
     _handleFilterBarButtonClicked(event)
@@ -119,7 +136,10 @@
 
     _handleFilterChanged()
     {
-        this.dispatchEventToListeners(WebInspector.FilterBar.Event.FilterDidChange);
+        if (this.hasFilterChanged()) {
+            this._lastFilterValue = this.filters;
+            this.dispatchEventToListeners(WebInspector.FilterBar.Event.FilterDidChange);
+        }
     }
 };
 

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/MetricsStyleDetailsPanel.js (185722 => 185723)


--- trunk/Source/WebInspectorUI/UserInterface/Views/MetricsStyleDetailsPanel.js	2015-06-18 22:07:15 UTC (rev 185722)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/MetricsStyleDetailsPanel.js	2015-06-18 22:24:37 UTC (rev 185723)
@@ -25,9 +25,9 @@
 
 WebInspector.MetricsStyleDetailsPanel = class MetricsStyleDetailsPanel extends WebInspector.StyleDetailsPanel
 {
-    constructor()
+    constructor(delegate)
     {
-        super("metrics", "metrics", WebInspector.UIString("Metrics"));
+        super(delegate, "metrics", "metrics", WebInspector.UIString("Metrics"));
 
         this._boxModelDiagramRow = new WebInspector.BoxModelDetailsSectionRow;
 
@@ -42,5 +42,7 @@
     refresh()
     {
         this._boxModelDiagramRow.nodeStyles = this.nodeStyles;
+
+        super.refresh();
     }
 };

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.css (185722 => 185723)


--- trunk/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.css	2015-06-18 22:07:15 UTC (rev 185722)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.css	2015-06-18 22:24:37 UTC (rev 185723)
@@ -52,10 +52,36 @@
     opacity: 0.5;
 }
 
-.sidebar > .panel.details.css-style .rules .new-rule + .style-declaration-section {
+.sidebar > .panel.details.css-style > .content.filter-in-progress .label {
+    padding-top: 15px;
+}
+
+.sidebar > .panel.details.css-style > .content.filter-in-progress .label ~ .label {
+    padding-top: 0;
+}
+
+.sidebar > .panel.details.css-style > .content.filter-in-progress .label.filter-matching-label {
+    padding-bottom: 5px;
+    border-bottom: 1px solid rgb(179, 179, 179);
+}
+
+.sidebar > .panel.details.css-style > .content.filter-in-progress .new-rule {
+    display: none;
+}
+
+.sidebar > .panel.details.css-style > .content.filter-in-progress .style-declaration-section:not(.filter-section-non-matching) ~ .label:not(.filter-section-non-matching) {
+    padding-top: 15px;
+}
+
+.sidebar > .panel.details.css-style > .content:not(.filter-in-progress) > .rules > .new-rule + .style-declaration-section {
     border-top: 1px solid rgb(179, 179, 179);
 }
 
+.sidebar > .panel.details.css-style > .content:not(.filter-in-progress) > .rules > .new-rule + .label {
+    padding-top: 10px;
+    border-top: 1px solid rgb(179, 179, 179);
+}
+
 .sidebar > .panel.details.css-style .rules .new-rule img {
     content: url(../Images/Plus.svg);
 
@@ -74,3 +100,28 @@
 .sidebar > .panel.details.css-style .rules .new-rule:active {
     opacity: 0.7;
 }
+
+.sidebar > .panel.details.css-style > .content > .rules:not(.filter-non-matching) > .no-filter-results {
+    display: none;
+}
+
+.sidebar > .panel.details.css-style > .content.filter-in-progress > .rules.filter-non-matching > .no-filter-results {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+
+.sidebar > .panel.details.css-style > .content.filter-in-progress > .rules.filter-non-matching > .no-filter-results > .no-filter-results-message {
+    font-size: 13px;
+    color: white;
+    background-color: rgba(0, 0, 0, 0.15);
+    text-shadow: rgba(0, 0, 0, 0.2) 0 1px 0;
+    box-shadow: inset rgba(0, 0, 0, 0.2) 0 1px 0, rgba(255, 255, 255, 0.4) 0 1px 0;
+    border-radius: 6px;
+    padding: 5px 15px 6px;
+}

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.js (185722 => 185723)


--- trunk/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.js	2015-06-18 22:07:15 UTC (rev 185722)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.js	2015-06-18 22:24:37 UTC (rev 185723)
@@ -25,13 +25,22 @@
 
 WebInspector.RulesStyleDetailsPanel = class RulesStyleDetailsPanel extends WebInspector.StyleDetailsPanel
 {
-    constructor()
+    constructor(delegate)
     {
-        super("rules", "rules", WebInspector.UIString("Rules"));
+        super(delegate, "rules", "rules", WebInspector.UIString("Rules"));
 
         this._sections = [];
         this._previousFocusedSection = null;
+        this._ruleMediaAndInherticanceList = [];
         this._propertyToSelectAndHighlight = null;
+
+        this._emptyFilterResultsElement = document.createElement("div");
+        this._emptyFilterResultsElement.classList.add("no-filter-results");
+
+        this._emptyFilterResultsMessage = document.createElement("div");
+        this._emptyFilterResultsMessage.classList.add("no-filter-results-message");
+        this._emptyFilterResultsMessage.textContent = WebInspector.UIString("No Results Found");
+        this._emptyFilterResultsElement.appendChild(this._emptyFilterResultsMessage);
     }
 
     // Public
@@ -40,8 +49,10 @@
     {
         // We only need to do a rebuild on significant changes. Other changes are handled
         // by the sections and text editors themselves.
-        if (!significantChange)
+        if (!significantChange) {
+            super.refresh();
             return;
+        }
 
         var newSections = [];
         var newDOMFragment = document.createDocumentFragment();
@@ -170,11 +181,14 @@
         }
 
         var addedNewRuleButton = false;
+        this._ruleMediaAndInherticanceList = [];
 
         var orderedStyles = uniqueOrderedStyles(this.nodeStyles.orderedStyles);
         for (var i = 0; i < orderedStyles.length; ++i) {
             var style = orderedStyles[i];
 
+            var hasMediaOrInherited = [];
+
             if (style.type === WebInspector.CSSStyleDeclaration.Type.Rule && !addedNewRuleButton)
                 addNewRuleButton.call(this);
 
@@ -189,6 +203,8 @@
                 inheritedLabel.appendChild(prefixElement);
                 inheritedLabel.appendChild(WebInspector.linkifyNodeReference(style.node));
                 newDOMFragment.appendChild(inheritedLabel);
+
+                hasMediaOrInherited.push(inheritedLabel);
             }
 
             // Only include the media list if it is different from the previous media list shown.
@@ -218,9 +234,16 @@
                     }
 
                     newDOMFragment.appendChild(mediaLabel);
+
+                    hasMediaOrInherited.push(mediaLabel);
                 }
             }
 
+            if (!hasMediaOrInherited.length && previousSection && !previousSection.lastInGroup)
+                hasMediaOrInherited = this._ruleMediaAndInherticanceList.lastValue;
+
+            this._ruleMediaAndInherticanceList.push(hasMediaOrInherited);
+
             appendStyleSection.call(this, style);
         }
 
@@ -232,11 +255,14 @@
 
         this.element.removeChildren();
         this.element.appendChild(newDOMFragment);
+        this.element.appendChild(this._emptyFilterResultsElement);
 
         this._sections = newSections;
 
         for (var i = 0; i < this._sections.length; ++i)
             this._sections[i].updateLayout();
+
+        super.refresh();
     }
 
     scrollToSectionAndHighlightProperty(property)
@@ -262,6 +288,35 @@
         }
     }
 
+    filterDidChange(filterBar)
+    {
+        for (var labels of this._ruleMediaAndInherticanceList) {
+            for (var i = 0; i < labels.length; ++i) {
+                labels[i].classList.toggle(WebInspector.CSSStyleDetailsSidebarPanel.NoFilterMatchInSectionClassName, filterBar.hasActiveFilters());
+
+                if (i === labels.length - 1)
+                    labels[i].classList.toggle("filter-matching-label", filterBar.hasActiveFilters());
+            }
+        }
+
+        var matchFound = !filterBar.hasActiveFilters();
+        for (var i = 0; i < this._sections.length; ++i) {
+            var section = this._sections[i];
+
+            if (section.findMatchingPropertiesAndSelectors(filterBar.filters.text) && filterBar.hasActiveFilters()) {
+                if (this._ruleMediaAndInherticanceList[i].length) {
+                    for (var label of this._ruleMediaAndInherticanceList[i])
+                        label.classList.remove(WebInspector.CSSStyleDetailsSidebarPanel.NoFilterMatchInSectionClassName);
+                } else
+                    section.element.classList.add(WebInspector.CSSStyleDetailsSidebarPanel.FilterMatchingSectionHasLabelClassName);
+                
+                matchFound = true;
+            }
+        }
+
+        this.element.classList.toggle("filter-non-matching", !matchFound);
+    }
+
     // Protected
 
     shown()

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/StyleDetailsPanel.js (185722 => 185723)


--- trunk/Source/WebInspectorUI/UserInterface/Views/StyleDetailsPanel.js	2015-06-18 22:07:15 UTC (rev 185722)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/StyleDetailsPanel.js	2015-06-18 22:24:37 UTC (rev 185723)
@@ -25,10 +25,12 @@
 
 WebInspector.StyleDetailsPanel = class StyleDetailsPanel extends WebInspector.Object
 {
-    constructor(className, identifier, label)
+    constructor(delegate, className, identifier, label)
     {
         super();
 
+        this._delegate = delegate || null;
+
         this._element = document.createElement("div");
         this._element.className = className;
 
@@ -109,6 +111,7 @@
     refresh(significantChange)
     {
         // Implemented by subclasses.
+        this.dispatchEventToListeners(WebInspector.StyleDetailsPanel.Event.Refreshed);
     }
 
     // Protected
@@ -160,3 +163,7 @@
             this._refreshNodeStyles();
     }
 };
+
+WebInspector.StyleDetailsPanel.Event = {
+    Refreshed: "style-details-panel-refreshed"
+};
\ No newline at end of file
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to