Changeset 223065 in webkit


Ignore:
Timestamp:
Oct 9, 2017 1:38:09 PM (7 years ago)
Author:
Joseph Pecoraro
Message:

Web Inspector: Network Tab - Filter resources based on URL / Text Content
https://bugs.webkit.org/show_bug.cgi?id=178071
<rdar://problem/34071562>

Reviewed by Brian Burg.

  • Localizations/en.lproj/localizedStrings.js:

New strings.

  • UserInterface/Views/FilterBar.css:

(.filter-bar.active > input[type="search"]::-webkit-search-decoration):
(.filter-bar.indicating-progress > input[type="search"]::-webkit-search-decoration):
New icon for progress / active states.

  • UserInterface/Views/FilterBar.js:

(WI.FilterBar.prototype.get inputField):
(WI.FilterBar.prototype.get placeholder):
(WI.FilterBar.prototype.set placeholder):
(WI.FilterBar.prototype.get incremental):
(WI.FilterBar.prototype.set incremental):
(WI.FilterBar.prototype.get indicatingProgress):
(WI.FilterBar.prototype.set indicatingProgress):
(WI.FilterBar.prototype.get indicatingActive):
(WI.FilterBar.prototype.set indicatingActive):
(WI.FilterBar.prototype._handleFilterInputEvent):
When incremental is set to false on the FilterBar still dispatch an
event when the textfield clears.

  • UserInterface/Images/FilterFieldActiveGlyph.svg: Added.
  • UserInterface/Images/gtk/FilterFieldActiveGlyph.svg: Added.

New blue icon for active state.

  • UserInterface/Controllers/FrameResourceManager.js:

(WI.FrameResourceManager.prototype.resourceForIdentifier):
Accessor for arbitrary resource.

  • UserInterface/Views/NetworkTableContentView.css:

(.content-view.network .navigation-bar .filter-bar):
(.content-view.network .warning-banner):
(body[dir=ltr] .content-view.network .warning-banner):
(body[dir=rtl] .content-view.network .warning-banner):
(.content-view.network .warning-banner > a):
Warning banner when the filter produces no results. This matches the
warning in the Debugger tab when breakpoints are disabled.

  • UserInterface/Views/ScopeBar.js:

(WI.ScopeBar.prototype.resetToDefault):
Provide a way to easily reset a scope bar to the default item.

  • UserInterface/Views/RadioButtonNavigationItem.css:

(.navigation-bar .item.radio.button.text-only:active):

  • UserInterface/Views/ScopeBar.css:

(.scope-bar > li:active):
Cleanup some styles that should be using a variable.

  • UserInterface/Views/NetworkTableContentView.js:

(WI.NetworkTableContentView):
(WI.NetworkTableContentView.prototype.get filterNavigationItems):
(WI.NetworkTableContentView.prototype.layout):
(WI.NetworkTableContentView.prototype._processPendingEntries):
(WI.NetworkTableContentView.prototype._checkTextFilterAgainstFinishedResource):
(WI.NetworkTableContentView.prototype._checkTextFilterAgainstFailedResource):
(WI.NetworkTableContentView.prototype._updateTextFilterActiveIndicator):
(WI.NetworkTableContentView.prototype._updateEmptyFilterResultsWarning):
(WI.NetworkTableContentView.prototype._showEmptyFilterResultsWarning):
(WI.NetworkTableContentView.prototype._hideEmptyFilterResultsWarning):
(WI.NetworkTableContentView.prototype._positionEmptyFilterMessage):
(WI.NetworkTableContentView.prototype._resourceLoadingDidFinish):
(WI.NetworkTableContentView.prototype._resourceLoadingDidFail):
(WI.NetworkTableContentView.prototype._networkTimelineRecordAdded):
(WI.NetworkTableContentView.prototype._insertResourceAndReloadTable):
(WI.NetworkTableContentView.prototype._hasTypeFilter):
(WI.NetworkTableContentView.prototype._hasTextFilter):
(WI.NetworkTableContentView.prototype._hasActiveFilter):
(WI.NetworkTableContentView.prototype._passTypeFilter):
(WI.NetworkTableContentView.prototype._passTextFilter):
(WI.NetworkTableContentView.prototype._passFilter):
(WI.NetworkTableContentView.prototype._updateFilteredEntries):
(WI.NetworkTableContentView.prototype._resetFilters):
(WI.NetworkTableContentView.prototype._textFilterDidChange):
(WI.NetworkTableContentView.prototype._tableNameColumnDidChangeWidth):
There are now two filters.

  • FilterBar - Filters URL and Full Text Content
  • ScopeBar - Filters Resource Type

The text content filter is asynchronous. We reuse the existing Search
functionality when filtering on text. We need to defer text content
filtering until the resource finishes loading.

Location:
trunk/Source/WebInspectorUI
Files:
2 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebInspectorUI/ChangeLog

    r223059 r223065  
     12017-10-09  Joseph Pecoraro  <pecoraro@apple.com>
     2
     3        Web Inspector: Network Tab - Filter resources based on URL / Text Content
     4        https://bugs.webkit.org/show_bug.cgi?id=178071
     5        <rdar://problem/34071562>
     6
     7        Reviewed by Brian Burg.
     8
     9        * Localizations/en.lproj/localizedStrings.js:
     10        New strings.
     11
     12        * UserInterface/Views/FilterBar.css:
     13        (.filter-bar.active > input[type="search"]::-webkit-search-decoration):
     14        (.filter-bar.indicating-progress > input[type="search"]::-webkit-search-decoration):
     15        New icon for progress / active states.
     16
     17        * UserInterface/Views/FilterBar.js:
     18        (WI.FilterBar.prototype.get inputField):
     19        (WI.FilterBar.prototype.get placeholder):
     20        (WI.FilterBar.prototype.set placeholder):
     21        (WI.FilterBar.prototype.get incremental):
     22        (WI.FilterBar.prototype.set incremental):
     23        (WI.FilterBar.prototype.get indicatingProgress):
     24        (WI.FilterBar.prototype.set indicatingProgress):
     25        (WI.FilterBar.prototype.get indicatingActive):
     26        (WI.FilterBar.prototype.set indicatingActive):
     27        (WI.FilterBar.prototype._handleFilterInputEvent):
     28        When incremental is set to false on the FilterBar still dispatch an
     29        event when the textfield clears.
     30
     31        * UserInterface/Images/FilterFieldActiveGlyph.svg: Added.
     32        * UserInterface/Images/gtk/FilterFieldActiveGlyph.svg: Added.
     33        New blue icon for active state.
     34
     35        * UserInterface/Controllers/FrameResourceManager.js:
     36        (WI.FrameResourceManager.prototype.resourceForIdentifier):
     37        Accessor for arbitrary resource.
     38
     39        * UserInterface/Views/NetworkTableContentView.css:
     40        (.content-view.network .navigation-bar .filter-bar):
     41        (.content-view.network .warning-banner):
     42        (body[dir=ltr] .content-view.network .warning-banner):
     43        (body[dir=rtl] .content-view.network .warning-banner):
     44        (.content-view.network .warning-banner > a):
     45        Warning banner when the filter produces no results. This matches the
     46        warning in the Debugger tab when breakpoints are disabled.
     47
     48        * UserInterface/Views/ScopeBar.js:
     49        (WI.ScopeBar.prototype.resetToDefault):
     50        Provide a way to easily reset a scope bar to the default item.
     51
     52        * UserInterface/Views/RadioButtonNavigationItem.css:
     53        (.navigation-bar .item.radio.button.text-only:active):
     54        * UserInterface/Views/ScopeBar.css:
     55        (.scope-bar > li:active):
     56        Cleanup some styles that should be using a variable.
     57
     58        * UserInterface/Views/NetworkTableContentView.js:
     59        (WI.NetworkTableContentView):
     60        (WI.NetworkTableContentView.prototype.get filterNavigationItems):
     61        (WI.NetworkTableContentView.prototype.layout):
     62        (WI.NetworkTableContentView.prototype._processPendingEntries):
     63        (WI.NetworkTableContentView.prototype._checkTextFilterAgainstFinishedResource):
     64        (WI.NetworkTableContentView.prototype._checkTextFilterAgainstFailedResource):
     65        (WI.NetworkTableContentView.prototype._updateTextFilterActiveIndicator):
     66        (WI.NetworkTableContentView.prototype._updateEmptyFilterResultsWarning):
     67        (WI.NetworkTableContentView.prototype._showEmptyFilterResultsWarning):
     68        (WI.NetworkTableContentView.prototype._hideEmptyFilterResultsWarning):
     69        (WI.NetworkTableContentView.prototype._positionEmptyFilterMessage):
     70        (WI.NetworkTableContentView.prototype._resourceLoadingDidFinish):
     71        (WI.NetworkTableContentView.prototype._resourceLoadingDidFail):
     72        (WI.NetworkTableContentView.prototype._networkTimelineRecordAdded):
     73        (WI.NetworkTableContentView.prototype._insertResourceAndReloadTable):
     74        (WI.NetworkTableContentView.prototype._hasTypeFilter):
     75        (WI.NetworkTableContentView.prototype._hasTextFilter):
     76        (WI.NetworkTableContentView.prototype._hasActiveFilter):
     77        (WI.NetworkTableContentView.prototype._passTypeFilter):
     78        (WI.NetworkTableContentView.prototype._passTextFilter):
     79        (WI.NetworkTableContentView.prototype._passFilter):
     80        (WI.NetworkTableContentView.prototype._updateFilteredEntries):
     81        (WI.NetworkTableContentView.prototype._resetFilters):
     82        (WI.NetworkTableContentView.prototype._textFilterDidChange):
     83        (WI.NetworkTableContentView.prototype._tableNameColumnDidChangeWidth):
     84        There are now two filters.
     85
     86          - FilterBar - Filters URL and Full Text Content
     87          - ScopeBar  - Filters Resource Type
     88
     89        The text content filter is asynchronous. We reuse the existing Search
     90        functionality when filtering on text. We need to defer text content
     91        filtering until the resource finishes loading.
     92
    1932017-10-09  Joseph Pecoraro  <pecoraro@apple.com>
    294
  • trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js

    r223058 r223065  
    182182localizedStrings["Clear Network Items (%s)"] = "Clear Network Items (%s)";
    183183localizedStrings["Clear Timeline (%s)"] = "Clear Timeline (%s)";
     184localizedStrings["Clear filters"] = "Clear filters";
    184185localizedStrings["Clear focus"] = "Clear focus";
    185186localizedStrings["Clear log (%s or %s)"] = "Clear log (%s or %s)";
     
    404405localizedStrings["Fill Mode"] = "Fill Mode";
    405406localizedStrings["Filter"] = "Filter";
     407localizedStrings["Filter Full URL and Text"] = "Filter Full URL and Text";
    406408localizedStrings["Flexbox"] = "Flexbox";
    407409localizedStrings["Float"] = "Float";
  • trunk/Source/WebInspectorUI/UserInterface/Controllers/FrameResourceManager.js

    r222739 r223065  
    6666    }
    6767
     68    resourceForRequestIdentifier(requestIdentifier)
     69    {
     70        return this._resourceRequestIdentifierMap.get(requestIdentifier) || null;
     71    }
     72
    6873    frameDidNavigate(framePayload)
    6974    {
  • trunk/Source/WebInspectorUI/UserInterface/Views/FilterBar.css

    r220609 r223065  
    9191    -webkit-appearance: none;
    9292}
     93
     94.filter-bar.active > input[type="search"]::-webkit-search-decoration {
     95    background-image: url(../Images/FilterFieldActiveGlyph.svg);
     96}
     97
     98.filter-bar.indicating-progress > input[type="search"]::-webkit-search-decoration {
     99    background-image: url(../Images/IndeterminateProgressSpinner1.svg);
     100    background-repeat: no-repeat;
     101    background-size: 100% 100%;
     102
     103    animation-name: discrete-spinner;
     104    animation-duration: 1s;
     105    animation-iteration-count: infinite;
     106    animation-timing-function: step-start;
     107}
  • trunk/Source/WebInspectorUI/UserInterface/Views/FilterBar.js

    r220609 r223065  
    4343        this._inputField.spellcheck = false;
    4444        this._inputField.incremental = true;
    45         this._inputField.addEventListener("search", this._handleFilterChanged.bind(this), false);
     45        this._inputField.addEventListener("search", this._handleFilterChanged.bind(this));
     46        this._inputField.addEventListener("input", this._handleFilterInputEvent.bind(this));
    4647        this._element.appendChild(this._inputField);
    4748
     
    5657    }
    5758
     59    get inputField()
     60    {
     61        return this._inputField;
     62    }
     63
    5864    get placeholder()
    5965    {
    60         return this._inputField.getAttribute("placeholder");
     66        return this._inputField.placeholder;
    6167    }
    6268
    6369    set placeholder(text)
    6470    {
    65         this._inputField.setAttribute("placeholder", text);
     71        this._inputField.placeholder = text;
    6672    }
    6773
    68     get inputField()
     74    get incremental()
    6975    {
    70         return this._inputField;
     76        return this._inputField.incremental;
     77    }
     78
     79    set incremental(incremental)
     80    {
     81        this._inputField.incremental = incremental;
    7182    }
    7283
     
    8495        if (oldTextValue !== this._inputField.value)
    8596            this._handleFilterChanged();
     97    }
     98
     99    get indicatingProgress()
     100    {
     101        return this._element.classList.contains("indicating-progress");
     102    }
     103
     104    set indicatingProgress(progress)
     105    {
     106        this._element.classList.toggle("indicating-progress", !!progress);
     107    }
     108
     109    get indicatingActive()
     110    {
     111        return this._element.classList.contains("active");
     112    }
     113
     114    set indicatingActive(active)
     115    {
     116        this._element.classList.toggle("active", !!active);
     117    }
     118
     119    clear()
     120    {
     121        this._inputField.value = "";
     122        this._inputField.value = null; // Get the placeholder to show again.
     123        this._lastFilterValue = this.filters;
    86124    }
    87125
     
    143181        }
    144182    }
     183
     184    _handleFilterInputEvent(event)
     185    {
     186        // When not incremental we still want to detect if the field becomes empty.
     187
     188        if (this.incremental)
     189            return;
     190
     191        if (!this._inputField.value)
     192            this._handleFilterChanged();
     193    }
    145194};
    146195
  • trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.css

    r223058 r223065  
    2323 * THE POSSIBILITY OF SUCH DAMAGE.
    2424 */
     25
     26.content-view.network .navigation-bar .filter-bar {
     27    background: none;
     28}
    2529
    2630.content-view.network .network-table .icon {
     
    7276    background: rgba(0, 0, 0, 0.07);
    7377}
     78
     79.content-view.network .empty-content-placeholder {
     80    position: absolute;
     81    top: var(--navigation-bar-height);
     82    bottom: 0;
     83    padding: 0;
     84    padding-top: 15px;
     85    padding-bottom: 15px;
     86    display: flex;
     87    justify-content: center;
     88    align-items: center;
     89    overflow: hidden;
     90    background: var(--odd-zebra-stripe-row-background-color);
     91    --empty-content-placeholder-start: 0;
     92}
     93
     94body[dir=ltr] .content-view.network .empty-content-placeholder {
     95    left: var(--empty-content-placeholder-start);
     96}
     97
     98body[dir=rtl] .content-view.network .empty-content-placeholder {
     99    right: var(--empty-content-placeholder-start);
     100}
     101
     102.content-view.network .empty-content-placeholder > .message {
     103    display: inline-block;
     104    white-space: nowrap;
     105
     106    font-size: var(--sidebar-no-results-message-font-size);
     107    color: var(--text-color-gray-medium);
     108
     109    padding: 5px 15px 6px;
     110    line-height: 25px;
     111    text-align: center;
     112}
  • trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js

    r223006 r223065  
    3535        this._pendingInsertions = [];
    3636        this._pendingUpdates = [];
     37        this._pendingFilter = false;
    3738
    3839        this._table = null;
     
    4445
    4546        // FIXME: Network Timeline.
    46         // FIXME: Filter text field.
    4747        // FIXME: Throttling.
    4848        // FIXME: HAR Export.
     
    7171        this._typeFilterScopeBar.addEventListener(WI.ScopeBar.Event.SelectionChanged, this._typeFilterScopeBarSelectionChanged, this);
    7272
     73        this._textFilterSearchId = 0;
     74        this._textFilterSearchText = null;
     75        this._textFilterIsActive = false;
     76
     77        this._textFilterNavigationItem = new WI.FilterBarNavigationItem;
     78        this._textFilterNavigationItem.filterBar.incremental = false;
     79        this._textFilterNavigationItem.filterBar.addEventListener(WI.FilterBar.Event.FilterDidChange, this._textFilterDidChange, this);
     80        this._textFilterNavigationItem.filterBar.placeholder = WI.UIString("Filter Full URL and Text");
     81
    7382        this._activeTypeFilters = this._generateTypeFilter();
     83        this._activeTextFilterResources = new Set;
     84
     85        this._emptyFilterResultsMessageElement = null;
    7486
    7587        // COMPATIBILITY (iOS 10.3): Network.setDisableResourceCaching did not exist.
     
    143155    get filterNavigationItems()
    144156    {
    145         return [this._typeFilterScopeBar];
     157        let items = [];
     158        if (window.PageAgent)
     159            items.push(this._textFilterNavigationItem);
     160        items.push(this._typeFilterScopeBar);
     161        return items;
    146162    }
    147163
     
    582598        this._processPendingEntries();
    583599        this._positionDetailView();
     600        this._positionEmptyFilterMessage();
    584601    }
    585602
     
    594611    {
    595612        let needsSort = this._pendingUpdates.length > 0;
    596 
    597         // No global sort is needed, so just insert new records into their sorted position.
    598         if (!needsSort) {
     613        let needsFilter = this._pendingFilter;
     614
     615        // No global sort or filter is needed, so just insert new records into their sorted position.
     616        if (!needsSort && !needsFilter) {
    599617            let originalLength = this._pendingInsertions.length;
    600618            for (let resource of this._pendingInsertions)
     
    613631        this._pendingUpdates = [];
    614632
     633        this._pendingFilter = false;
     634
    615635        this._updateSortAndFilteredEntries();
    616636        this._table.reloadData();
     637    }
     638
     639    _checkTextFilterAgainstFinishedResource(resource)
     640    {
     641        let frame = resource.parentFrame;
     642        if (!frame)
     643            return;
     644
     645        let searchQuery = this._textFilterSearchText;
     646        if (resource.url.includes(searchQuery)) {
     647            this._activeTextFilterResources.add(resource);
     648            return;
     649        }
     650
     651        let searchId = this._textFilterSearchId;
     652
     653        const isCaseSensitive = true;
     654        const isRegex = false;
     655        PageAgent.searchInResource(frame.id, resource.url, searchQuery, isCaseSensitive, isRegex, resource.requestIdentifier, (error, searchResults) => {
     656            if (searchId !== this._textFilterSearchId)
     657                return;
     658
     659            if (error || !searchResults || !searchResults.length)
     660                return;
     661
     662            this._activeTextFilterResources.add(resource);
     663
     664            this._pendingFilter = true;
     665            this.needsLayout();
     666        });
     667    }
     668
     669    _checkTextFilterAgainstFailedResource(resource)
     670    {
     671        let searchQuery = this._textFilterSearchText;
     672        if (resource.url.includes(searchQuery))
     673            this._activeTextFilterResources.add(resource);
    617674    }
    618675
     
    690747    }
    691748
     749    _updateTextFilterActiveIndicator()
     750    {
     751        this._textFilterNavigationItem.filterBar.indicatingActive = this._hasTextFilter();
     752    }
     753
     754    _updateEmptyFilterResultsMessage()
     755    {
     756        if (this._hasActiveFilter() && !this._filteredEntries.length)
     757            this._showEmptyFilterResultsMessage();
     758        else
     759            this._hideEmptyFilterResultsMessage();
     760    }
     761
     762    _showEmptyFilterResultsMessage()
     763    {
     764        if (!this._emptyFilterResultsMessageElement) {
     765            let message = WI.UIString("No Filter Results");
     766            let buttonElement = document.createElement("button");
     767            buttonElement.textContent = WI.UIString("Clear filters");
     768            buttonElement.addEventListener("click", () => { this._resetFilters(); });
     769
     770            this._emptyFilterResultsMessageElement = document.createElement("div");
     771            this._emptyFilterResultsMessageElement.className = "empty-content-placeholder";
     772
     773            let messageElement = this._emptyFilterResultsMessageElement.appendChild(document.createElement("div"));
     774            messageElement.className = "message";
     775            messageElement.append(message, document.createElement("br"), buttonElement);
     776        }
     777
     778        this.element.appendChild(this._emptyFilterResultsMessageElement);
     779        this._positionEmptyFilterMessage();
     780    }
     781
     782    _hideEmptyFilterResultsMessage()
     783    {
     784        if (!this._emptyFilterResultsMessageElement)
     785            return;
     786
     787        this._emptyFilterResultsMessageElement.remove();
     788    }
     789
     790    _positionEmptyFilterMessage()
     791    {
     792        if (!this._emptyFilterResultsMessageElement)
     793            return;
     794
     795        let width = this._nameColumn.width - 1; // For the 1px border.
     796        this._emptyFilterResultsMessageElement.style.width = width + "px";
     797    }
     798
    692799    _resourceCachingDisabledSettingChanged()
    693800    {
     
    715822        let resource = event.target;
    716823        this._pendingUpdates.push(resource);
     824
     825        if (this._hasTextFilter())
     826            this._checkTextFilterAgainstFinishedResource(resource);
     827
    717828        this.needsLayout();
    718829    }
     
    722833        let resource = event.target;
    723834        this._pendingUpdates.push(resource);
     835
     836        if (this._hasTextFilter())
     837            this._checkTextFilterAgainstFailedResource(resource);
     838
    724839        this.needsLayout();
    725840    }
     
    759874
    760875        let resource = resourceTimelineRecord.resource;
    761         this._insertResourceAndReloadTable(resource)
     876        this._insertResourceAndReloadTable(resource);
    762877    }
    763878
     
    771886        if (!(WI.tabBrowser.selectedTabContentView instanceof WI.NetworkTabContentView)) {
    772887            this._pendingInsertions.push(resource);
     888            this.needsLayout();
    773889            return;
    774890        }
     
    846962    }
    847963
     964    _hasTypeFilter()
     965    {
     966        return !!this._activeTypeFilters;
     967    }
     968
     969    _hasTextFilter()
     970    {
     971        return this._textFilterIsActive;
     972    }
     973
     974    _hasActiveFilter()
     975    {
     976        return this._hasTypeFilter()
     977            || this._hasTextFilter();
     978    }
     979
     980    _passTypeFilter(entry)
     981    {
     982        if (!this._hasTypeFilter())
     983            return true;
     984        return this._activeTypeFilters.some((checker) => checker(entry.resource.type));
     985    }
     986
     987    _passTextFilter(entry)
     988    {
     989        if (!this._hasTextFilter())
     990            return true;
     991        return this._activeTextFilterResources.has(entry.resource);
     992    }
     993
    848994    _passFilter(entry)
    849995    {
    850         if (!this._activeTypeFilters)
    851             return true;
    852 
    853         return this._activeTypeFilters.some((checker) => checker(entry.resource.type));
     996        return this._passTypeFilter(entry)
     997            && this._passTextFilter(entry);
    854998    }
    855999
     
    8621006    _updateFilteredEntries()
    8631007    {
    864         if (this._activeTypeFilters)
     1008        if (this._hasActiveFilter())
    8651009            this._filteredEntries = this._entries.filter(this._passFilter, this);
    8661010        else
     
    8681012
    8691013        this._restoreSelectedRow();
     1014
     1015        this._updateTextFilterActiveIndicator();
     1016        this._updateEmptyFilterResultsMessage();
    8701017    }
    8711018
     
    8771024
    8781025        return selectedItems.map((item) => item.__checker);
     1026    }
     1027
     1028    _resetFilters()
     1029    {
     1030        console.assert(this._hasActiveFilter());
     1031
     1032        // Clear text filter.
     1033        this._textFilterSearchId++;
     1034        this._textFilterNavigationItem.filterBar.indicatingProgress = false;
     1035        this._textFilterSearchText = null;
     1036        this._textFilterIsActive = false;
     1037        this._activeTextFilterResources.clear();
     1038        this._textFilterNavigationItem.filterBar.clear();
     1039        console.assert(!this._hasTextFilter());
     1040
     1041        // Clear type filter.
     1042        this._typeFilterScopeBar.resetToDefault();
     1043        console.assert(!this._hasTypeFilter());
     1044
     1045        console.assert(!this._hasActiveFilter());
     1046
     1047        this._updateFilteredEntries();
     1048        this._table.reloadData();
    8791049    }
    8801050
     
    9131083    }
    9141084
     1085    _textFilterDidChange(event)
     1086    {
     1087        let searchQuery = this._textFilterNavigationItem.filterBar.filters.text;
     1088        if (searchQuery === this._textFilterSearchText)
     1089            return;
     1090
     1091        // Even if the selected resource would still be visible, lets close the detail view if a filter changes.
     1092        this._hideResourceDetailView();
     1093
     1094        let searchId = ++this._textFilterSearchId;
     1095
     1096        // Search cleared.
     1097        if (!searchQuery) {
     1098            this._textFilterNavigationItem.filterBar.indicatingProgress = false;
     1099            this._textFilterSearchText = null;
     1100            this._textFilterIsActive = false;
     1101            this._activeTextFilterResources.clear();
     1102
     1103            this._updateFilteredEntries();
     1104            this._table.reloadData();
     1105            return;
     1106        }
     1107
     1108        this._textFilterSearchText = searchQuery;
     1109        this._textFilterNavigationItem.filterBar.indicatingProgress = true;
     1110
     1111        // NetworkTable text filter currently searches:
     1112        //   - Resource URL
     1113        //   - Resource Text Content
     1114        // It does not search all the content in the table (like mimeType, headers, etc).
     1115        // For those we should provide more custom filters.
     1116
     1117        const isCaseSensitive = true;
     1118        const isRegex = false;
     1119        PageAgent.searchInResources(searchQuery, isCaseSensitive, isRegex, (error, searchResults) => {
     1120            if (searchId !== this._textFilterSearchId)
     1121                return;
     1122
     1123            this._textFilterIsActive = true;
     1124            this._activeTextFilterResources.clear();
     1125            this._textFilterNavigationItem.filterBar.indicatingProgress = false;
     1126
     1127            // Add resources based on URL.
     1128            for (let entry of this._entries) {
     1129                let resource = entry.resource;
     1130                if (resource.url.includes(searchQuery))
     1131                    this._activeTextFilterResources.add(resource);
     1132            }
     1133
     1134            // Add resources based on content.
     1135            if (!error) {
     1136                for (let {url, frameId, requestId} of searchResults) {
     1137                    if (requestId) {
     1138                        let resource = WI.frameResourceManager.resourceForRequestIdentifier(requestId);
     1139                        if (resource) {
     1140                            this._activeTextFilterResources.add(resource);
     1141                            continue;
     1142                        }
     1143                    }
     1144
     1145                    if (frameId && url) {
     1146                        let frame = WI.frameResourceManager.frameForIdentifier(frameId);
     1147                        if (frame) {
     1148                            if (frame.mainResource.url === url) {
     1149                                this._activeTextFilterResources.add(frame.mainResource);
     1150                                continue;
     1151                            }
     1152                            let resource = frame.resourceForURL(url);
     1153                            if (resource) {
     1154                                this._activeTextFilterResources.add(resource);
     1155                                continue;
     1156                            }
     1157                        }
     1158                    }
     1159                }
     1160            }
     1161
     1162            // Apply.
     1163            this._updateFilteredEntries();
     1164            this._table.reloadData();
     1165        });
     1166    }
     1167
    9151168    _restoreSelectedRow()
    9161169    {
     
    9331186
    9341187        this._positionDetailView();
     1188        this._positionEmptyFilterMessage();
    9351189    }
    9361190};
  • trunk/Source/WebInspectorUI/UserInterface/Views/RadioButtonNavigationItem.css

    r197029 r223065  
    4444.navigation-bar .item.radio.button.text-only:active {
    4545    color: var(--selected-foreground-color);
    46     background-color: hsla(212, 92%, 54%, 0.55);
     46    background-color: var(--selected-background-color-active);
    4747}
    4848
  • trunk/Source/WebInspectorUI/UserInterface/Views/ScopeBar.css

    r212662 r223065  
    110110.scope-bar > li:active {
    111111    color: var(--selected-foreground-color);
    112     background-color: hsla(212, 92%, 54%, 0.55);
     112    background-color: var(--selected-background-color-active);
    113113}
    114114
  • trunk/Source/WebInspectorUI/UserInterface/Views/ScopeBar.js

    r220119 r223065  
    9090    }
    9191
     92    resetToDefault()
     93    {
     94        let selectedItems = this.selectedItems;
     95        if (selectedItems.length === 1 && selectedItems[0] === this._defaultItem)
     96            return;
     97
     98        for (let item of this._items)
     99            item.selected = false;
     100        this._defaultItem.selected = true;
     101
     102        this.dispatchEventToListeners(WI.ScopeBar.Event.SelectionChanged);
     103    }
     104
    92105    // Private
    93106
Note: See TracChangeset for help on using the changeset viewer.