Changeset 199143 in webkit
- Timestamp:
- Apr 6, 2016 7:09:07 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 5 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r199135 r199143 1 2016-04-06 Matt Baker <mattbaker@apple.com> 2 3 Web Inspector: Improve filtering in OpenResourceDialog 4 https://bugs.webkit.org/show_bug.cgi?id=155324 5 <rdar://problem/25094504> 6 7 Reviewed by Joseph Pecoraro. 8 9 Add test coverage for ResourceQueryController. 10 11 * inspector/unit-tests/resource-query-controller-expected.txt: Added. 12 * inspector/unit-tests/resource-query-controller.html: Added. 13 1 14 2016-04-06 Saam barati <sbarati@apple.com> 2 15 -
trunk/Source/WebInspectorUI/ChangeLog
r199095 r199143 1 2016-04-06 Matt Baker <mattbaker@apple.com> 2 3 Web Inspector: Improve filtering in OpenResourceDialog 4 https://bugs.webkit.org/show_bug.cgi?id=155324 5 <rdar://problem/25094504> 6 7 Reviewed by Joseph Pecoraro and Timothy Hatcher. 8 9 * UserInterface/Base/Utilities.js: 10 (value): 11 Added String methods isLowerCase, isUpperCase, removeWhitespace. 12 13 * UserInterface/Controllers/ResourceQueryController.js: Added. 14 (WebInspector.ResourceQueryController): 15 (WebInspector.ResourceQueryController.prototype.addResource): 16 (WebInspector.ResourceQueryController.prototype.removeResource): 17 Add and remove the resources to be queried. 18 19 (WebInspector.ResourceQueryController.prototype.reset): 20 Reset controller state. Current just clears resources. 21 22 (WebInspector.ResourceQueryController.prototype.executeQuery): 23 Executes a query against the list of resources and returns a list of 24 QueryResult objects, with at most one result per resource, ordered by 25 descending rank. 26 27 The query string is stripped of whitespace characters and lowercased 28 before use. Prior to running the query, resources undergo a one-time 29 pre-processing step to locate special characters. 30 31 (WebInspector.ResourceQueryController.prototype._findQueryMatches.pushMatch): 32 (WebInspector.ResourceQueryController.prototype._findQueryMatches.matchNextSpecialCharacter): 33 (WebInspector.ResourceQueryController.prototype._findQueryMatches.backtrack): 34 (WebInspector.ResourceQueryController.prototype._findQueryMatches): 35 Returns a list of query matches for a single resource, along with metadata 36 which is used to rank the matches. The algorithm attempts to match the 37 entire query, first comparing each query character against "special" characters 38 in the resource (commonly used filename separators, the first character, 39 and camel-case word boundaries). 40 41 If there are remaining query characters after exhausting special characters, 42 regular characters are matched starting from the last matched special 43 character. Failing that, the algorithm attempts to find a match by backtracking. 44 To backtrack, the last match is discarded and the query position decremented. 45 If a special match is now the last match, matching starts again from the 46 next character in the filename after the match. If a normal match is now 47 the last match, keep discarding until a special match is found or no matches 48 remain. The query fails if no matches remain. For example, consider: 49 50 Query: "abcd" 51 Filename: "AxBcdCx" 52 53 The capital A, B, and C are all special characters, and are successfully 54 matched with the first three query characters. Having exhausted the special 55 characters the "d" at the end of the query is compared with the "x" at 56 the end of the filename, and fails to match. Backtracking then kicks in. 57 The last match, "C", is discarded and the search position in the query 58 decremented. The search resumes after the next to last match, "B", and now 59 matches the non-special characters "cd", yielding the following: "A Bcd ". 60 61 (WebInspector.ResourceQueryController.prototype._findSpecialCharacterIndices): 62 Pre-processing step for resources. Locates the positions of special 63 characters in the resource filename. Special characters are defined as: 64 65 1. The first character 66 2. Common filename separators, and the character immediately following. 67 3. A capital letter that follows a lowercase character. 68 69 * UserInterface/Models/ResourceQueryMatch.js: Added. 70 Helper class used internally by the controller and QueryResult classes. 71 (WebInspector.ResourceQueryMatch): 72 (WebInspector.ResourceQueryMatch.prototype.get type): 73 (WebInspector.ResourceQueryMatch.prototype.get index): 74 (WebInspector.ResourceQueryMatch.prototype.get queryIndex): 75 76 * UserInterface/Models/ResourceQueryResult.js: Added. 77 Holds a resource that matched the executed query. 78 (WebInspector.ResourceQueryResult): 79 (WebInspector.ResourceQueryResult.prototype.get resource): 80 (WebInspector.ResourceQueryResult.prototype.get rank): 81 Ranking relative to other results returned by the query. Used by 82 the ResourceQueryController to sort results. 83 84 (WebInspector.ResourceQueryResult.prototype.get matchingTextRanges): 85 Get TextRanges for matching substrings in the resource display name. 86 87 (WebInspector.ResourceQueryResult.prototype._calculateRank): 88 Calculate the rank of the result. Matches are scored based on the type 89 of match (Special vs. Normal), the location of the match within the filename 90 (matches closer to the beginning are scored higher), and whether the match 91 is adjacent to the previous match. 92 93 Values assigned to each ranking criteria are somewhat arbitrary, and may 94 be fine-tuned over time to produce better results. 95 96 (WebInspector.ResourceQueryResult.prototype._createMatchingTextRanges): 97 (WebInspector.ResourceQueryResult.prototype.__test_createMatchesMask): 98 Test API for visualizing matches. For a result returned from the query 99 "abce", run against a filename "abcde", the mask is "a c e". 100 101 * UserInterface/Main.html: 102 * UserInterface/Test.html: 103 New files. 104 105 * UserInterface/Views/Dialog.js: 106 (WebInspector.Dialog.prototype.dismiss): 107 (WebInspector.Dialog.prototype.didDismissDialog): 108 Add hook for subclasses to perform actions after on dialog dismissal. 109 110 * UserInterface/Views/OpenResourceDialog.js: 111 (WebInspector.OpenResourceDialog): 112 (WebInspector.OpenResourceDialog.prototype._populateResourceTreeOutline.createHighlightedTitleFragment): 113 (WebInspector.OpenResourceDialog.prototype._populateResourceTreeOutline): 114 Add tree elements for each QueryResult returned by the last query, creating 115 titles with contiguous matching query characters wrapped in highlight spans. 116 117 (WebInspector.OpenResourceDialog.prototype.didDismissDialog): 118 Clear resources from the ResourceQueryController. 119 (WebInspector.OpenResourceDialog.prototype.didPresentDialog): 120 Add resources to the ResourceQueryController. 121 (WebInspector.OpenResourceDialog.prototype._updateFilter): 122 Execute the filter text as a resource query. 123 124 * UserInterface/Views/TreeOutline.css: 125 (.tree-outline.large .item .titles): Deleted. 126 Line height too small, hid the bottom border of highlighted matches in 127 tree element title spans. Removing the style had no negative visual impact 128 on the Quick Open or Timelines tree outlines (the only "large" trees). 129 1 130 2016-04-05 Joseph Pecoraro <pecoraro@apple.com> 2 131 -
trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js
r199031 r199143 485 485 }); 486 486 487 Object.defineProperty(String.prototype, "isLowerCase", 488 { 489 value: function() 490 { 491 return String(this) === this.toLowerCase(); 492 } 493 }); 494 495 Object.defineProperty(String.prototype, "isUpperCase", 496 { 497 value: function() 498 { 499 return String(this) === this.toUpperCase(); 500 } 501 }); 502 487 503 Object.defineProperty(String.prototype, "trimMiddle", 488 504 { … … 530 546 { 531 547 return this.replace(/[\s\xA0]+/g, " "); 548 } 549 }); 550 551 Object.defineProperty(String.prototype, "removeWhitespace", 552 { 553 value: function() 554 { 555 return this.replace(/[\s\xA0]+/g, ""); 532 556 } 533 557 }); -
trunk/Source/WebInspectorUI/UserInterface/Main.html
r198537 r199143 352 352 <script src="Models/Resource.js"></script> 353 353 <script src="Models/ResourceCollection.js"></script> 354 <script src="Models/ResourceQueryMatch.js"></script> 355 <script src="Models/ResourceQueryResult.js"></script> 354 356 <script src="Models/ResourceTimelineRecord.js"></script> 355 357 <script src="Models/Revision.js"></script> … … 691 693 <script src="Controllers/ProbeManager.js"></script> 692 694 <script src="Controllers/ReplayManager.js"></script> 695 <script src="Controllers/ResourceQueryController.js"></script> 693 696 <script src="Controllers/RuntimeManager.js"></script> 694 697 <script src="Controllers/SourceMapManager.js"></script> -
trunk/Source/WebInspectorUI/UserInterface/Test.html
r198353 r199143 143 143 <script src="Models/Resource.js"></script> 144 144 <script src="Models/ResourceCollection.js"></script> 145 <script src="Models/ResourceQueryMatch.js"></script> 146 <script src="Models/ResourceQueryResult.js"></script> 145 147 <script src="Models/ResourceTimelineRecord.js"></script> 146 148 <script src="Models/Revision.js"></script> … … 181 183 <script src="Controllers/Formatter.js"></script> 182 184 <script src="Controllers/FormatterContentBuilder.js"></script> 185 <script src="Controllers/ResourceQueryController.js"></script> 183 186 <script src="Views/CodeMirrorAdditions.js"></script> 184 187 <script src="Views/CodeMirrorFormatters.js"></script> -
trunk/Source/WebInspectorUI/UserInterface/Views/Dialog.js
r197961 r199143 83 83 84 84 this._dismissing = false; 85 86 this.didDismissDialog(); 85 87 } 86 88 87 89 // Protected 90 91 didDismissDialog() 92 { 93 // Implemented by subclasses. 94 } 88 95 89 96 didPresetDialog() -
trunk/Source/WebInspectorUI/UserInterface/Views/OpenResourceDialog.js
r198690 r199143 59 59 this.element.appendChild(this._treeOutline.element); 60 60 61 this._ resources = [];62 this._filteredRes ources = [];61 this._queryController = new WebInspector.ResourceQueryController; 62 this._filteredResults = []; 63 63 } 64 64 … … 67 67 _populateResourceTreeOutline() 68 68 { 69 function createHighlightedTitleFragment(title, highlightTextRanges) 70 { 71 let titleFragment = document.createDocumentFragment(); 72 let lastIndex = 0; 73 for (let textRange of highlightTextRanges) { 74 if (textRange.startColumn > lastIndex) 75 titleFragment.append(title.substring(lastIndex, textRange.startColumn)); 76 77 let highlightSpan = document.createElement("span"); 78 highlightSpan.classList.add("highlighted"); 79 highlightSpan.append(title.substring(textRange.startColumn, textRange.endColumn)); 80 titleFragment.append(highlightSpan); 81 lastIndex = textRange.endColumn; 82 } 83 84 if (lastIndex < title.length) 85 titleFragment.append(title.substring(lastIndex, title.length)); 86 87 return titleFragment; 88 } 89 69 90 function createTreeElement(representedObject) 70 91 { … … 81 102 } 82 103 83 for (let resource of this._filteredResources) { 104 for (let result of this._filteredResults) { 105 let resource = result.resource; 106 if (this._treeOutline.findTreeElement(resource)) 107 continue; 108 84 109 let treeElement = createTreeElement(resource); 85 110 if (!treeElement) 86 111 continue; 87 112 88 if (this._treeOutline.findTreeElement(resource)) 89 continue; 90 113 treeElement.mainTitle = createHighlightedTitleFragment(resource.displayName, result.matchingTextRanges); 91 114 this._treeOutline.appendChild(treeElement); 92 115 } … … 94 117 if (this._treeOutline.children.length) 95 118 this._treeOutline.children[0].select(true, false, true, true); 119 } 120 121 didDismissDialog() 122 { 123 this._queryController.reset(); 96 124 } 97 125 … … 104 132 while (frames.length) { 105 133 let frame = frames.shift(); 106 for (let resource of frame.resources) { 134 let resources = [frame.mainResource].concat(frame.resources); 135 for (let resource of resources) { 107 136 if (!this.representedObjectIsValid(resource)) 108 137 continue; 109 138 110 this._ resources.push(resource);139 this._queryController.addResource(resource); 111 140 } 112 141 … … 194 223 _updateFilter() 195 224 { 196 this._filteredRes ources = [];225 this._filteredResults = []; 197 226 this._treeOutline.hidden = true; 198 227 this._treeOutline.removeChildren(); … … 202 231 return; 203 232 204 // FIXME: <https://webkit.org/b/155324> Web Inspector: Improve filtering in OpenResourceDialog 205 let filters = [simpleGlobStringToRegExp(filterText)]; 206 207 for (let resource of this._resources) { 208 for (let i = 0; i < filters.length; ++i) { 209 if (!filters[i].test(resource.displayName)) 210 continue; 211 212 resource.__weight = filters.length - i; 213 this._filteredResources.push(resource); 214 break; 215 } 216 } 217 218 // Sort filtered resources by weight, then alphabetically. 219 this._filteredResources.sort((a, b) => { 220 if (a.__weight === b.__weight) 221 return a.displayName.localeCompare(b.displayName); 222 223 return b.__weight - a.__weight; 224 }); 233 this._filteredResults = this._queryController.executeQuery(filterText); 225 234 226 235 this._populateResourceTreeOutline(); -
trunk/Source/WebInspectorUI/UserInterface/Views/TreeOutline.css
r197961 r199143 184 184 .tree-outline.large .item .titles { 185 185 top: 10px; 186 line-height: 11px;187 186 } 188 187
Note: See TracChangeset
for help on using the changeset viewer.