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

Changeset 185723 in webkit


Ignore:
Timestamp:
Jun 18, 2015, 3:24:37 PM (11 years ago)
Author:
commit-queue@webkit.org
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 <Devin Rousso> 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.

Location:
trunk/Source/WebInspectorUI
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebInspectorUI/ChangeLog

    r185720 r185723  
     12015-06-18  Devin Rousso  <drousso@apple.com>
     2
     3        Web Inspector: Add a filter for CSS properties in the Styles sidebar
     4        https://bugs.webkit.org/show_bug.cgi?id=145536
     5
     6        Reviewed by Timothy Hatcher.
     7
     8        * UserInterface/Base/Utilities.js: Added function to Strings that returns an array of all matching indexes of a given string.
     9        (.value):
     10        * UserInterface/Views/CSSStyleDeclarationSection.js:
     11        (WebInspector.CSSStyleDeclarationSection):
     12        (WebInspector.CSSStyleDeclarationSection.prototype.refresh.appendSelector):
     13        (WebInspector.CSSStyleDeclarationSection.prototype.findMatchingPropertiesAndSelectors): Loops through the property list and selectors of each section to find matches to the filtered text.
     14        * UserInterface/Views/CSSStyleDeclarationTextEditor.js:
     15        (WebInspector.CSSStyleDeclarationTextEditor.prototype.findMatchingProperties): Searches through the properties list to find and highlight all matching properties.
     16        (WebInspector.CSSStyleDeclarationTextEditor.prototype.removeNonMatchingProperties): Removes all properties that do not match and highlights the specific matched text in matching properties.
     17        (WebInspector.CSSStyleDeclarationTextEditor.prototype.resetFilteredProperties): Restores all properties to full visibility and removes any highlighting.
     18        (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).
     19        (WebInspector.CSSStyleDeclarationTextEditor.prototype._iterateOverProperties): If a filter is active, find properties matching the filter instead of all properties.
     20        * UserInterface/Views/CSSStyleDetailsSidebarPanel.css:
     21        (.sidebar > .panel.details.css-style > .content.has-filter-bar + .filter-bar):
     22        (.sidebar > .panel.details.css-style > .content:not(.has-filter-bar) + .filter-bar):
     23        * UserInterface/Views/CSSStyleDetailsSidebarPanel.js:
     24        (WebInspector.CSSStyleDetailsSidebarPanel): Added a filter bar to the CSS sidebar.
     25        (WebInspector.CSSStyleDetailsSidebarPanel.prototype._switchPanels): Switching panels preserves and applies filter bar text.
     26        (WebInspector.CSSStyleDetailsSidebarPanel.prototype._filterDidChange): Function called when the filter bar text changes that calls the current panel's filterDidChange function if it exists.
     27        * UserInterface/Views/FilterBar.js: Added function and variable to check if the text in the filter bar had changed.
     28        * UserInterface/Views/MetricsStyleDetailsPanel.js:
     29        (WebInspector.MetricsStyleDetailsPanel.prototype.refresh): Now calls superclass refresh.
     30        (WebInspector.MetricsStyleDetailsPanel): Added delegate variable to constructor.
     31        * UserInterface/Views/RulesStyleDetailsPanel.css:
     32        (.sidebar > .panel.details.css-style > .content.filter-in-progress .label):
     33        (.sidebar > .panel.details.css-style > .content.filter-in-progress .label ~ .label):
     34        (.sidebar > .panel.details.css-style > .content.filter-in-progress .label.filter-matching-label):
     35        (.sidebar > .panel.details.css-style > .content.filter-in-progress .new-rule):
     36        (.sidebar > .panel.details.css-style > .content.filter-in-progress .style-declaration-section:not(.filter-section-non-matching) ~ .label:not(.filter-section-non-matching)):
     37        (.sidebar > .panel.details.css-style > .content:not(.filter-in-progress) > .rules > .new-rule + .style-declaration-section):
     38        (.sidebar > .panel.details.css-style > .content > .rules:not(.filter-non-matching) > .no-filter-results):
     39        (.sidebar > .panel.details.css-style > .content.filter-in-progress > .rules.filter-non-matching > .no-filter-results):
     40        (.sidebar > .panel.details.css-style > .content.filter-in-progress > .rules.filter-non-matching > .no-filter-results > .no-filter-results-message):
     41        * UserInterface/Views/RulesStyleDetailsPanel.js:
     42        (WebInspector.RulesStyleDetailsPanel): Added delegate variable to constructor.
     43        (WebInspector.RulesStyleDetailsPanel.prototype.refresh): Now calls superclass refresh.
     44        (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).
     45        (WebInspector.StyleDetailsPanel): Added delegate variable to constructor.
     46        (WebInspector.StyleDetailsPanel.prototype.refresh): Added event dispatch for panel refresh.
     47
    1482015-06-18  Devin Rousso  <drousso@apple.com>
    249
  • trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js

    r185720 r185723  
    128128localizedStrings["Copy Path to Property"] = "Copy Path to Property";
    129129localizedStrings["Copy Row"] = "Copy Row";
    130 localizedStrings["Copy gs["New TaCopy = "New Tab";
    131 localizedStrCopy as HTML"] = "Copy as HTML";
     130localizedStrings["Copy Rule"] = "Copy Rule";
     131localizedStrings["Copy as HTML"] = "Copy as HTML";
    132132localizedStrings["Could not fetch properties. Object may no longer exist."] = "Could not fetch properties. Object may no longer exist.";
    133133localizedStrings["Create a new tab"] = "Create a new tab";
     
    226226localizedStrings["Filter Search Results"] = "Filter Search Results";
    227227localizedStrings["Filter Storage List"] = "Filter Storage List";
     228localizedStrings["Filter Styles"] = "Filter Styles";
    228229localizedStrings["Flows"] = "Flows";
    229230localizedStrings["Focused"] = "Focused";
     
    338339localizedStrings["No Request Headers"] = "No Request Headers";
    339340localizedStrings["No Response Headers"] = "No Response Headers";
     341localizedStrings["No Results Found"] = "No Results Found";
    340342localizedStrings["No Search Results"] = "No Search Results";
    341343localizedStrings["No exact ARIA role match."] = "No exact ARIA role match.";
  • trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js

    r185638 r185723  
    749749});
    750750
     751Object.defineProperty(String.prototype, "getMatchingIndexes",
     752{
     753    value: function(needle)
     754    {
     755        var indexesOfNeedle = [];
     756        var index = this.indexOf(needle);
     757
     758        while (index >= 0) {
     759            indexesOfNeedle.push(index);
     760            index = this.indexOf(needle, index + 1);
     761        }
     762
     763        return indexesOfNeedle;
     764    }
     765});
     766
    751767Object.defineProperty(Number, "constrain",
    752768{
  • trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDeclarationSection.js

    r185720 r185723  
    3333    console.assert(style);
    3434    this._style = style || null;
     35    this._selectorElements = [];
    3536
    3637    this._element = document.createElement("div");
     
    165166        this._selectorElement.removeChildren();
    166167        this._originElement.removeChildren();
     168        this._selectorElements = [];
    167169
    168170        this._originElement.appendChild(document.createTextNode(" \u2014 "));
     
    197199
    198200            this._selectorElement.appendChild(selectorElement);
     201            this._selectorElements.push(selectorElement);
    199202        }
    200203
     
    275278    },
    276279
     280    findMatchingPropertiesAndSelectors: function(needle)
     281    {
     282        this._element.classList.remove(WebInspector.CSSStyleDetailsSidebarPanel.NoFilterMatchInSectionClassName, WebInspector.CSSStyleDetailsSidebarPanel.FilterMatchingSectionHasLabelClassName);
     283
     284        var hasMatchingSelector = false;
     285
     286        for (var selectorElement of this._selectorElements) {
     287            selectorElement.classList.remove(WebInspector.CSSStyleDetailsSidebarPanel.FilterMatchSectionClassName);
     288
     289            if (needle && selectorElement.textContent.includes(needle)) {
     290                selectorElement.classList.add(WebInspector.CSSStyleDetailsSidebarPanel.FilterMatchSectionClassName);
     291                hasMatchingSelector = true;
     292            }
     293        }
     294
     295        if (!needle) {
     296            this._propertiesTextEditor.resetFilteredProperties();
     297            return false;
     298        }
     299
     300        var hasMatchingProperty = this._propertiesTextEditor.findMatchingProperties(needle);
     301
     302        if (!hasMatchingProperty && !hasMatchingSelector) {
     303            this._element.classList.add(WebInspector.CSSStyleDetailsSidebarPanel.NoFilterMatchInSectionClassName);
     304            return false;
     305        }
     306
     307        return true;
     308    },
     309
    277310    updateLayout: function()
    278311    {
  • trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDeclarationTextEditor.js

    r185282 r185723  
    3737        this._showsImplicitProperties = true;
    3838        this._alwaysShowPropertyNames = {};
     39        this._filterResultPropertyNames = null;
    3940        this._sortProperties = false;
    4041
     
    230231    }
    231232
     233    findMatchingProperties(needle)
     234    {
     235        if (!needle) {
     236            this.resetFilteredProperties();
     237            return false;
     238        }
     239
     240        var propertiesList = this._style.visibleProperties.length ? this._style.visibleProperties : this._style.properties;
     241        var matchingProperties = [];
     242
     243        for (var property of propertiesList)
     244            matchingProperties.push(property.text.includes(needle));
     245
     246        if (!matchingProperties.includes(true)) {
     247            this.resetFilteredProperties();
     248            return false;
     249        }
     250
     251        for (var i = 0; i < matchingProperties.length; ++i) {
     252            var property = propertiesList[i];
     253
     254            if (matchingProperties[i])
     255                property.__filterResultClassName = WebInspector.CSSStyleDetailsSidebarPanel.FilterMatchSectionClassName;
     256            else
     257                property.__filterResultClassName = WebInspector.CSSStyleDetailsSidebarPanel.NoFilterMatchInPropertyClassName;
     258
     259            this._updateTextMarkerForPropertyIfNeeded(property);
     260        }
     261
     262        return true;
     263    }
     264
     265    resetFilteredProperties()
     266    {
     267        var propertiesList = this._style.visibleProperties.length ? this._style.visibleProperties : this._style.properties;
     268
     269        for (var property of propertiesList) {
     270            if (property.__filterResultClassName) {
     271                property.__filterResultClassName = null;
     272                this._updateTextMarkerForPropertyIfNeeded(property)
     273            }
     274        }
     275    }
     276
     277    removeNonMatchingProperties(needle)
     278    {
     279        this._filterResultPropertyNames = null;
     280
     281        if (!needle) {
     282            this._resetContent();
     283            return false;
     284        }
     285
     286        var matchingPropertyNames = [];
     287
     288        for (var property of this._style.properties) {
     289            var indexesOfNeedle = property.text.getMatchingIndexes(needle);
     290
     291            if (indexesOfNeedle.length) {
     292                matchingPropertyNames.push(property.name);
     293                property.__filterResultClassName = WebInspector.CSSStyleDetailsSidebarPanel.FilterMatchSectionClassName;
     294                property.__filterResultNeedlePosition = {start: indexesOfNeedle, length: needle.length};
     295            }
     296        }
     297
     298        this._filterResultPropertyNames = matchingPropertyNames.length ? matchingPropertyNames.keySet() : {};
     299
     300        this._resetContent();
     301
     302        return matchingPropertyNames.length > 0;
     303    }
     304
    232305    // Protected
    233306
     
    528601            classNames.push("disabled");
    529602
     603        if (property.__filterResultClassName && !property.__filterResultNeedlePosition)
     604            classNames.push(property.__filterResultClassName);
     605
    530606        var classNamesString = classNames.join(" ");
    531607
     
    559635            this._codeMirror.markText(start, end, {className: "invalid"});
    560636        }
     637
     638        if (property.__filterResultClassName && property.__filterResultNeedlePosition) {
     639            for (var needlePosition of property.__filterResultNeedlePosition.start) {
     640                var start = {line: from.line, ch: needlePosition};
     641                var end = {line: to.line, ch: start.ch + property.__filterResultNeedlePosition.length};
     642
     643                this._codeMirror.markText(start, end, {className: property.__filterResultClassName});
     644            }
     645        }
    561646    }
    562647
     
    598683        var properties = onlyVisibleProperties ? this._style.visibleProperties : this._style.properties;
    599684
    600         if (!onlyVisibleProperties) {
     685        if (this._filterResultPropertyNames) {
     686            properties = properties.filter(function(property) {
     687                return (!property.implicit || this._showsImplicitProperties) && property.name in this._filterResultPropertyNames;
     688            }, this);
     689
     690            if (this._sortProperties)
     691                properties.sort(function(a, b) { return a.name.localeCompare(b.name); });
     692        } else if (!onlyVisibleProperties) {
    601693            // Filter based on options only when all properties are used.
    602694            properties = properties.filter(function(property) {
  • trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDetailsSidebarPanel.css

    r183579 r185723  
    4343}
    4444
     45.sidebar > .panel.details.css-style > .content.has-filter-bar {
     46    bottom: 28px;
     47}
     48
    4549.sidebar > .panel.details.css-style > .content > .pseudo-classes {
    4650    padding: 10px;
     
    6973    white-space: nowrap;
    7074}
     75
     76.sidebar > .panel.details.css-style > .content.has-filter-bar + .filter-bar {
     77    position: absolute;
     78    bottom: 0;
     79    width: 100%;
     80    background-color: white;
     81    border-top: 1px solid rgb(179, 179, 179);
     82}
     83
     84.sidebar > .panel.details.css-style > .content:not(.has-filter-bar) + .filter-bar {
     85    display: none;
     86}
     87
     88.sidebar > .panel.details.css-style > .content.filter-in-progress .filter-matching {
     89    display: inline;
     90    background-color: rgba(235, 215, 38, 0.5);
     91    border-bottom: 1px solid rgb(237, 202, 71);
     92    opacity: 1;
     93}
     94
     95.sidebar > .panel.details.css-style > .content.filter-in-progress .style-declaration-section {
     96    margin-bottom: 0;
     97}
     98
     99.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 {
     100    margin-top: 0;
     101    border-top: none;
     102}
     103
     104.sidebar > .panel.details.css-style > .content.filter-in-progress .style-declaration-section:not(.filter-section-has-label) {
     105    margin-top: 0;
     106    border-top: none;
     107    border-bottom: 1px solid rgb(179, 179, 179);
     108}
     109
     110.sidebar > .panel.details.css-style > .content.filter-in-progress .style-declaration-section > .header > .selector > .filter-matching {
     111    color: black;
     112}
     113
     114.sidebar > .panel.details.css-style > .content.filter-in-progress .filter-section-non-matching {
     115    display: none;
     116}
     117
     118.sidebar > .panel.details.css-style > .content.filter-in-progress .filter-property-non-matching {
     119    opacity: 0.5;
     120}
  • trunk/Source/WebInspectorUI/UserInterface/Views/CSSStyleDetailsSidebarPanel.js

    r185142 r185723  
    7272
    7373        this._computedStyleDetailsPanel = new WebInspector.ComputedStyleDetailsPanel(this);
    74         this._rulesStyleDetailsPanel = new WebInspector.RulesStyleDetailsPanel;
    75         this._metricsStyleDetailsPanel = new WebInspector.MetricsStyleDetailsPanel;
     74        this._rulesStyleDetailsPanel = new WebInspector.RulesStyleDetailsPanel(this);
     75        this._metricsStyleDetailsPanel = new WebInspector.MetricsStyleDetailsPanel(this);
     76
     77        this._computedStyleDetailsPanel.addEventListener(WebInspector.StyleDetailsPanel.Event.Refreshed, this._filterDidChange, this);
     78        this._rulesStyleDetailsPanel.addEventListener(WebInspector.StyleDetailsPanel.Event.Refreshed, this._filterDidChange, this);
    7679
    7780        this._panels = [this._computedStyleDetailsPanel, this._rulesStyleDetailsPanel, this._metricsStyleDetailsPanel];
     
    8588        // This will cause the selected panel to be set in _navigationItemSelected.
    8689        this._navigationBar.selectedNavigationItem = this._lastSelectedSectionSetting.value;
     90
     91        this._filterBar = new WebInspector.FilterBar;
     92        this._filterBar.placeholder = WebInspector.UIString("Filter Styles");
     93        this._filterBar.addEventListener(WebInspector.FilterBar.Event.FilterDidChange, this._filterDidChange, this);
     94        this.element.appendChild(this._filterBar.element);
    8795    }
    8896
     
    212220                this.contentElement.scrollTop = this._initialScrollOffset;
    213221
     222            var hasFilter = typeof this._selectedPanel.filterDidChange === "function";
     223            this.contentElement.classList.toggle("has-filter-bar", hasFilter);
     224            if (this._filterBar)
     225                this.contentElement.classList.toggle(WebInspector.CSSStyleDetailsSidebarPanel.FilterInProgressClassName, hasFilter && this._filterBar.hasActiveFilters());
     226
    214227            this._selectedPanel.shown();
    215228        }
     
    238251        }
    239252    }
     253
     254    _filterDidChange()
     255    {
     256        this.contentElement.classList.toggle(WebInspector.CSSStyleDetailsSidebarPanel.FilterInProgressClassName, this._filterBar.hasActiveFilters());
     257
     258        this._selectedPanel.filterDidChange(this._filterBar);
     259    }
    240260};
    241261
    242262WebInspector.CSSStyleDetailsSidebarPanel.NoForcedPseudoClassesScrollOffset = 38; // Default height of the forced pseudo classes container. Updated in widthDidChange.
     263WebInspector.CSSStyleDetailsSidebarPanel.FilterInProgressClassName = "filter-in-progress";
     264WebInspector.CSSStyleDetailsSidebarPanel.FilterMatchingSectionHasLabelClassName = "filter-section-has-label";
     265WebInspector.CSSStyleDetailsSidebarPanel.FilterMatchSectionClassName = "filter-matching";
     266WebInspector.CSSStyleDetailsSidebarPanel.NoFilterMatchInSectionClassName = "filter-section-non-matching";
     267WebInspector.CSSStyleDetailsSidebarPanel.NoFilterMatchInPropertyClassName = "filter-property-non-matching";
     268
  • trunk/Source/WebInspectorUI/UserInterface/Views/ComputedStyleDetailsPanel.js

    r185141 r185723  
    2828    constructor(delegate)
    2929    {
    30         super(WebInspector.ComputedStyleDetailsPanel.StyleClassName, "computed", WebInspector.UIString("Computed"));
    31 
    32         this._delegate = delegate || null;
     30        super(delegate, WebInspector.ComputedStyleDetailsPanel.StyleClassName, "computed", WebInspector.UIString("Computed"));
    3331
    3432        this._computedStyleShowAllSetting = new WebInspector.Setting("computed-style-show-all", false);
     
    154152        this._propertiesTextEditor.style = this.nodeStyles.computedStyle;
    155153        this._refreshFlowDetails(this.nodeStyles.node);
     154
     155        super.refresh();
     156    }
     157
     158    filterDidChange(filterBar)
     159    {
     160        this._propertiesTextEditor.removeNonMatchingProperties(filterBar.filters.text);
    156161    }
    157162
  • trunk/Source/WebInspectorUI/UserInterface/Views/FilterBar.js

    r182040 r185723  
    4444        this._inputField.addEventListener("search", this._handleFilterChanged.bind(this), false);
    4545        this._element.appendChild(this._inputField);
     46
     47        this._lastFilterValue = this.filters;
    4648    }
    4749
     
    100102    }
    101103
     104    hasFilterChanged()
     105    {
     106        var currentFunctions = this.filters.functions;
     107
     108        if (this._lastFilterValue.text !== this._inputField.value || this._lastFilterValue.functions.length !== currentFunctions.length)
     109            return true;
     110
     111        for (var i = 0; i < currentFunctions.length; ++i) {
     112            if (this._lastFilterValue.functions[i] !== currentFunctions[i])
     113                return true;
     114        }
     115
     116        return false;
     117    }
     118
    102119    // Private
    103120
     
    120137    _handleFilterChanged()
    121138    {
    122         this.dispatchEventToListeners(WebInspector.FilterBar.Event.FilterDidChange);
     139        if (this.hasFilterChanged()) {
     140            this._lastFilterValue = this.filters;
     141            this.dispatchEventToListeners(WebInspector.FilterBar.Event.FilterDidChange);
     142        }
    123143    }
    124144};
  • trunk/Source/WebInspectorUI/UserInterface/Views/MetricsStyleDetailsPanel.js

    r182055 r185723  
    2626WebInspector.MetricsStyleDetailsPanel = class MetricsStyleDetailsPanel extends WebInspector.StyleDetailsPanel
    2727{
    28     constructor()
     28    constructor(delegate)
    2929    {
    30         super("metrics", "metrics", WebInspector.UIString("Metrics"));
     30        super(delegate, "metrics", "metrics", WebInspector.UIString("Metrics"));
    3131
    3232        this._boxModelDiagramRow = new WebInspector.BoxModelDetailsSectionRow;
     
    4343    {
    4444        this._boxModelDiagramRow.nodeStyles = this.nodeStyles;
     45
     46        super.refresh();
    4547    }
    4648};
  • trunk/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.css

    r183579 r185723  
    5353}
    5454
    55 .sidebar > .panel.details.css-style .rules .new-rule + .style-declaration-section {
     55.sidebar > .panel.details.css-style > .content.filter-in-progress .label {
     56    padding-top: 15px;
     57}
     58
     59.sidebar > .panel.details.css-style > .content.filter-in-progress .label ~ .label {
     60    padding-top: 0;
     61}
     62
     63.sidebar > .panel.details.css-style > .content.filter-in-progress .label.filter-matching-label {
     64    padding-bottom: 5px;
     65    border-bottom: 1px solid rgb(179, 179, 179);
     66}
     67
     68.sidebar > .panel.details.css-style > .content.filter-in-progress .new-rule {
     69    display: none;
     70}
     71
     72.sidebar > .panel.details.css-style > .content.filter-in-progress .style-declaration-section:not(.filter-section-non-matching) ~ .label:not(.filter-section-non-matching) {
     73    padding-top: 15px;
     74}
     75
     76.sidebar > .panel.details.css-style > .content:not(.filter-in-progress) > .rules > .new-rule + .style-declaration-section {
     77    border-top: 1px solid rgb(179, 179, 179);
     78}
     79
     80.sidebar > .panel.details.css-style > .content:not(.filter-in-progress) > .rules > .new-rule + .label {
     81    padding-top: 10px;
    5682    border-top: 1px solid rgb(179, 179, 179);
    5783}
     
    75101    opacity: 0.7;
    76102}
     103
     104.sidebar > .panel.details.css-style > .content > .rules:not(.filter-non-matching) > .no-filter-results {
     105    display: none;
     106}
     107
     108.sidebar > .panel.details.css-style > .content.filter-in-progress > .rules.filter-non-matching > .no-filter-results {
     109    position: absolute;
     110    top: 0;
     111    left: 0;
     112    right: 0;
     113    bottom: 0;
     114    display: flex;
     115    justify-content: center;
     116    align-items: center;
     117}
     118
     119.sidebar > .panel.details.css-style > .content.filter-in-progress > .rules.filter-non-matching > .no-filter-results > .no-filter-results-message {
     120    font-size: 13px;
     121    color: white;
     122    background-color: rgba(0, 0, 0, 0.15);
     123    text-shadow: rgba(0, 0, 0, 0.2) 0 1px 0;
     124    box-shadow: inset rgba(0, 0, 0, 0.2) 0 1px 0, rgba(255, 255, 255, 0.4) 0 1px 0;
     125    border-radius: 6px;
     126    padding: 5px 15px 6px;
     127}
  • trunk/Source/WebInspectorUI/UserInterface/Views/RulesStyleDetailsPanel.js

    r185709 r185723  
    2626WebInspector.RulesStyleDetailsPanel = class RulesStyleDetailsPanel extends WebInspector.StyleDetailsPanel
    2727{
    28     constructor()
    29     {
    30         super("rules", "rules", WebInspector.UIString("Rules"));
     28    constructor(delegate)
     29    {
     30        super(delegate, "rules", "rules", WebInspector.UIString("Rules"));
    3131
    3232        this._sections = [];
    3333        this._previousFocusedSection = null;
     34        this._ruleMediaAndInherticanceList = [];
    3435        this._propertyToSelectAndHighlight = null;
     36
     37        this._emptyFilterResultsElement = document.createElement("div");
     38        this._emptyFilterResultsElement.classList.add("no-filter-results");
     39
     40        this._emptyFilterResultsMessage = document.createElement("div");
     41        this._emptyFilterResultsMessage.classList.add("no-filter-results-message");
     42        this._emptyFilterResultsMessage.textContent = WebInspector.UIString("No Results Found");
     43        this._emptyFilterResultsElement.appendChild(this._emptyFilterResultsMessage);
    3544    }
    3645
     
    4150        // We only need to do a rebuild on significant changes. Other changes are handled
    4251        // by the sections and text editors themselves.
    43         if (!significantChange)
     52        if (!significantChange) {
     53            super.refresh();
    4454            return;
     55        }
    4556
    4657        var newSections = [];
     
    171182
    172183        var addedNewRuleButton = false;
     184        this._ruleMediaAndInherticanceList = [];
    173185
    174186        var orderedStyles = uniqueOrderedStyles(this.nodeStyles.orderedStyles);
    175187        for (var i = 0; i < orderedStyles.length; ++i) {
    176188            var style = orderedStyles[i];
     189
     190            var hasMediaOrInherited = [];
    177191
    178192            if (style.type === WebInspector.CSSStyleDeclaration.Type.Rule && !addedNewRuleButton)
     
    190204                inheritedLabel.appendChild(WebInspector.linkifyNodeReference(style.node));
    191205                newDOMFragment.appendChild(inheritedLabel);
     206
     207                hasMediaOrInherited.push(inheritedLabel);
    192208            }
    193209
     
    219235
    220236                    newDOMFragment.appendChild(mediaLabel);
     237
     238                    hasMediaOrInherited.push(mediaLabel);
    221239                }
    222240            }
     241
     242            if (!hasMediaOrInherited.length && previousSection && !previousSection.lastInGroup)
     243                hasMediaOrInherited = this._ruleMediaAndInherticanceList.lastValue;
     244
     245            this._ruleMediaAndInherticanceList.push(hasMediaOrInherited);
    223246
    224247            appendStyleSection.call(this, style);
     
    233256        this.element.removeChildren();
    234257        this.element.appendChild(newDOMFragment);
     258        this.element.appendChild(this._emptyFilterResultsElement);
    235259
    236260        this._sections = newSections;
     
    238262        for (var i = 0; i < this._sections.length; ++i)
    239263            this._sections[i].updateLayout();
     264
     265        super.refresh();
    240266    }
    241267
     
    261287                section.clearSelection();
    262288        }
     289    }
     290
     291    filterDidChange(filterBar)
     292    {
     293        for (var labels of this._ruleMediaAndInherticanceList) {
     294            for (var i = 0; i < labels.length; ++i) {
     295                labels[i].classList.toggle(WebInspector.CSSStyleDetailsSidebarPanel.NoFilterMatchInSectionClassName, filterBar.hasActiveFilters());
     296
     297                if (i === labels.length - 1)
     298                    labels[i].classList.toggle("filter-matching-label", filterBar.hasActiveFilters());
     299            }
     300        }
     301
     302        var matchFound = !filterBar.hasActiveFilters();
     303        for (var i = 0; i < this._sections.length; ++i) {
     304            var section = this._sections[i];
     305
     306            if (section.findMatchingPropertiesAndSelectors(filterBar.filters.text) && filterBar.hasActiveFilters()) {
     307                if (this._ruleMediaAndInherticanceList[i].length) {
     308                    for (var label of this._ruleMediaAndInherticanceList[i])
     309                        label.classList.remove(WebInspector.CSSStyleDetailsSidebarPanel.NoFilterMatchInSectionClassName);
     310                } else
     311                    section.element.classList.add(WebInspector.CSSStyleDetailsSidebarPanel.FilterMatchingSectionHasLabelClassName);
     312               
     313                matchFound = true;
     314            }
     315        }
     316
     317        this.element.classList.toggle("filter-non-matching", !matchFound);
    263318    }
    264319
  • trunk/Source/WebInspectorUI/UserInterface/Views/StyleDetailsPanel.js

    r184977 r185723  
    2626WebInspector.StyleDetailsPanel = class StyleDetailsPanel extends WebInspector.Object
    2727{
    28     constructor(className, identifier, label)
     28    constructor(delegate, className, identifier, label)
    2929    {
    3030        super();
     31
     32        this._delegate = delegate || null;
    3133
    3234        this._element = document.createElement("div");
     
    110112    {
    111113        // Implemented by subclasses.
     114        this.dispatchEventToListeners(WebInspector.StyleDetailsPanel.Event.Refreshed);
    112115    }
    113116
     
    161164    }
    162165};
     166
     167WebInspector.StyleDetailsPanel.Event = {
     168    Refreshed: "style-details-panel-refreshed"
     169};
Note: See TracChangeset for help on using the changeset viewer.