2011-07-07 Ilya Tikhonovsky <loislo@chromium.org>
authorloislo@chromium.org <loislo@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 7 Jul 2011 12:06:29 +0000 (12:06 +0000)
committerloislo@chromium.org <loislo@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 7 Jul 2011 12:06:29 +0000 (12:06 +0000)
        Web Inspector: Searching on the Network panel doesn't do anything?
        https://bugs.webkit.org/show_bug.cgi?id=55489

        This is initial implementation of search in Network panel.
        It is pretty simple search only for names and paths.

        Reviewed by Pavel Feldman.

        * inspector/front-end/NetworkPanel.js:
        (WebInspector.NetworkPanel.prototype.refresh):
        (WebInspector.NetworkPanel.prototype._reset):
        (WebInspector.NetworkPanel.prototype._updateOffscreenRows):
        (WebInspector.NetworkPanel.prototype._matchResource):
        (WebInspector.NetworkPanel.prototype._clearSearchMatchedList):
        (WebInspector.NetworkPanel.prototype._highlightNthMatchedResource):
        (WebInspector.NetworkPanel.prototype.performSearch):
        (WebInspector.NetworkDataGridNode.prototype.createCells):
        * inspector/front-end/utilities.js:
        (String.prototype.escapeHTML):
        ():

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@90556 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/inspector/front-end/NetworkPanel.js
Source/WebCore/inspector/front-end/utilities.js

index 232ca62a6ab67daa2754beb7934b486e93a21564..4ce5419eea83856c7afa193e5d6817a5d15b6a4e 100644 (file)
@@ -1,3 +1,26 @@
+2011-07-07  Ilya Tikhonovsky  <loislo@chromium.org>
+
+        Web Inspector: Searching on the Network panel doesn't do anything?
+        https://bugs.webkit.org/show_bug.cgi?id=55489
+
+        This is initial implementation of search in Network panel.
+        It is pretty simple search only for names and paths.
+
+        Reviewed by Pavel Feldman.
+
+        * inspector/front-end/NetworkPanel.js:
+        (WebInspector.NetworkPanel.prototype.refresh):
+        (WebInspector.NetworkPanel.prototype._reset):
+        (WebInspector.NetworkPanel.prototype._updateOffscreenRows):
+        (WebInspector.NetworkPanel.prototype._matchResource):
+        (WebInspector.NetworkPanel.prototype._clearSearchMatchedList):
+        (WebInspector.NetworkPanel.prototype._highlightNthMatchedResource):
+        (WebInspector.NetworkPanel.prototype.performSearch):
+        (WebInspector.NetworkDataGridNode.prototype.createCells):
+        * inspector/front-end/utilities.js:
+        (String.prototype.escapeHTML):
+        ():
+
 2011-07-07  Vsevolod Vlasov  <vsevik@chromium.org>
 
         Web Inspector: Resources panel shows only one resource when multiple resources have the same url.
index fca5bfa0504b8585d91b2deec87a57b371cfddda..90f8583386ed3e898555e213f4bebc97e50820c6 100644 (file)
@@ -49,6 +49,9 @@ WebInspector.NetworkPanel = function()
     this._mainResourceLoadTime = -1;
     this._mainResourceDOMContentTime = -1;
     this._hiddenCategories = {};
+    this._matchedResources = [];
+    this._matchedResourcesMap = {};
+    this._currentMatchedResourceIndex = -1;
 
     this._categories = WebInspector.resourceCategories;
 
@@ -291,6 +294,8 @@ WebInspector.NetworkPanel.prototype = {
         this._dataGrid.sortNodes(sortingFunction, this._dataGrid.sortOrder === "descending");
         this._timelineSortSelector.selectedIndex = 0;
         this._updateOffscreenRows();
+
+        this.performSearch(null, true);
     },
 
     _sortByTimeline: function()
@@ -416,6 +421,7 @@ WebInspector.NetworkPanel.prototype = {
             selectMultiple = true;
 
         this._filter(e.target, selectMultiple);
+        this.performSearch(null, true);
     },
 
     _filter: function(target, selectMultiple)
@@ -667,6 +673,9 @@ WebInspector.NetworkPanel.prototype = {
 
             if (this.calculator.updateBoundaries(resource))
                 boundariesChanged = true;
+
+            if (!node.isFilteredOut())
+                this._updateHighlightIfMatched(resource);
         }
 
         if (boundariesChanged) {
@@ -697,6 +706,7 @@ WebInspector.NetworkPanel.prototype = {
     {
         this._popoverHelper.hidePopup();
         this._closeVisibleResource();
+        this._clearSearchMatchedList();
 
         this._toggleGridMode();
 
@@ -1100,6 +1110,124 @@ WebInspector.NetworkPanel.prototype = {
             }
             unfilteredRowIndex++;
         }
+    },
+
+    _matchResource: function(resource)
+    {
+        if (!this._searchRegExp)
+            return -1;
+
+        if ((!resource.displayName || !resource.displayName.match(this._searchRegExp)) && (!resource.path || !resource.path.match(this._searchRegExp)))
+            return -1;
+
+        if (resource.identifier in this._matchedResourcesMap)
+            return this._matchedResourcesMap[resource.identifier];
+
+        var matchedResourceIndex = this._matchedResources.length;
+        this._matchedResourcesMap[resource.identifier] = matchedResourceIndex;
+        this._matchedResources.push(resource.identifier);
+
+        return matchedResourceIndex;
+    },
+
+    _clearSearchMatchedList: function()
+    {
+        this._matchedResources = [];
+        this._matchedResourcesMap = {};
+        this._highlightNthMatchedResource(-1, false);
+    },
+
+    _updateHighlightIfMatched: function(resource)
+    {
+        var matchedResourceIndex = this._matchResource(resource);
+        if (matchedResourceIndex === -1)
+            return;
+
+        WebInspector.searchController.updateSearchMatchesCount(this._matchedResources.length, this);
+
+        if (this._currentMatchedResourceIndex !== -1 && this._currentMatchedResourceIndex !== matchedResourceIndex)
+            return;
+
+        this._highlightNthMatchedResource(matchedResourceIndex, false);
+    },
+
+    _highlightNthMatchedResource: function(matchedResourceIndex, reveal)
+    {
+        if (this._highlightedSubstringChanges) {
+            revertDomChanges(this._highlightedSubstringChanges);
+            this._highlightedSubstringChanges = null;
+        }
+
+        if (matchedResourceIndex === -1) {
+            this._currentMatchedResourceIndex = matchedResourceIndex;
+            return;
+        }
+
+        var resource = this._resourcesById[this._matchedResources[matchedResourceIndex]];
+        if (!resource)
+            return;
+
+        var nameMatched = resource.displayName && resource.displayName.match(this._searchRegExp);
+        var pathMatched = resource.path && resource.path.match(this._searchRegExp);
+        if (!nameMatched && pathMatched && !this._largerResourcesButton.toggled)
+            this._toggleLargerResources();
+
+        var node = this._resourceGridNode(resource);
+        if (node) {
+            this._highlightedSubstringChanges = node._highlightMatchedSubstring(this._searchRegExp);
+            if (reveal)
+                node.reveal();
+            this._currentMatchedResourceIndex = matchedResourceIndex;
+        }
+    },
+
+    performSearch: function(searchQuery, sortOrFilterApplied)
+    {
+        var newMatchedResourceIndex = 0;
+        var currentMatchedResourceId;
+        if (this._currentMatchedResourceIndex !== -1)
+            currentMatchedResourceId = this._matchedResources[this._currentMatchedResourceIndex];
+
+        if (!sortOrFilterApplied)
+            this._searchRegExp = createSearchRegex(searchQuery);
+
+        this._clearSearchMatchedList();
+
+        var childNodes = this._dataGrid.dataTableBody.childNodes;
+        var resourceNodes = Array.prototype.slice.call(childNodes, 0, childNodes.length - 1); // drop the filler row.
+
+        for (var i = 0; i < resourceNodes.length; ++i) {
+            var dataGridNode = this._dataGrid.dataGridNodeFromNode(resourceNodes[i]);
+            if (dataGridNode.isFilteredOut())
+                continue;
+
+            if (this._matchResource(dataGridNode._resource) !== -1 && dataGridNode._resource.identifier === currentMatchedResourceId)
+                newMatchedResourceIndex = this._matchedResources.length - 1;
+        }
+
+        this._highlightNthMatchedResource(newMatchedResourceIndex, !sortOrFilterApplied);
+
+        WebInspector.searchController.updateSearchMatchesCount(this._matchedResources.length, this);
+    },
+
+    jumpToPreviousSearchResult: function()
+    {
+        if (!this._matchedResources.length)
+            return;
+        this._highlightNthMatchedResource((this._currentMatchedResourceIndex + this._matchedResources.length - 1) % this._matchedResources.length, true);
+    },
+
+    jumpToNextSearchResult: function()
+    {
+        if (!this._matchedResources.length)
+            return;
+        this._highlightNthMatchedResource((this._currentMatchedResourceIndex + 1) % this._matchedResources.length, true);
+    },
+
+    searchCanceled: function()
+    {
+        this._clearSearchMatchedList();
+        WebInspector.searchController.updateSearchMatchesCount(0, this);
     }
 }
 
@@ -1421,6 +1549,14 @@ WebInspector.NetworkDataGridNode.prototype = {
         WebInspector.DataGridNode.prototype.select.apply(this, arguments);
     },
 
+    _highlightMatchedSubstring: function(regexp)
+    {
+        var domChanges = [];
+        var matchInfo = this._nameCell.textContent.match(regexp);
+        highlightSearchResult(this._nameCell, matchInfo.index, matchInfo[0].length, domChanges);
+        return domChanges;
+    },
+
     _openInNewTab: function()
     {
         PageAgent.open(this._resource.url, true);
index b4b21a692d995223455eea3446197663364c926a..eff55e96fe18d8ca14d268ef13878f8ab3b3ec92 100644 (file)
@@ -443,7 +443,7 @@ String.prototype.escapeForRegExp = function()
 
 String.prototype.escapeHTML = function()
 {
-    return this.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
+    return this.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"); //" doublequotes just for editor
 }
 
 String.prototype.collapseWhitespace = function()
@@ -956,9 +956,9 @@ function isEnterKey(event) {
     return event.keyCode !== 229 && event.keyIdentifier === "Enter";
 }
 
-function highlightSearchResult(element, offset, length)
+function highlightSearchResult(element, offset, length, domChanges)
 {
-    var result = highlightSearchResults(element, [{offset: offset, length: length }]);
+    var result = highlightSearchResults(element, [{offset: offset, length: length }], domChanges);
     return result.length ? result[0] : null;
 }
 
@@ -1049,6 +1049,37 @@ function highlightSearchResults(element, resultRanges, changes)
     return highlightNodes;
 }
 
+function applyDomChanges(domChanges)
+{
+    for (var i = 0, size = domChanges.length; i < size; ++i) {
+        var entry = domChanges[i];
+        switch (entry.type) {
+        case "added":
+            entry.parent.insertBefore(entry.node, entry.nextSibling);
+            break;
+        case "changed":
+            entry.node.textContent = entry.newText;
+            break;
+        }
+    }
+}
+
+function revertDomChanges(domChanges)
+{
+    for (var i = 0, size = domChanges.length; i < size; ++i) {
+        var entry = domChanges[i];
+        switch (entry.type) {
+        case "added":
+            if (entry.node.parentElement)
+                entry.node.parentElement.removeChild(entry.node);
+            break;
+        case "changed":
+            entry.node.textContent = entry.oldText;
+            break;
+        }
+    }
+}
+
 function createSearchRegex(query, extraFlags)
 {
     // This should be kept the same as the one in InspectorPageAgent.cpp.