1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 * @extends {WebInspector.SearchResultsPane}
8 * @param {!WebInspector.ProjectSearchConfig} searchConfig
10 WebInspector.FileBasedSearchResultsPane = function(searchConfig)
12 WebInspector.SearchResultsPane.call(this, searchConfig);
14 this._searchResults = [];
16 this.element.id = "search-results-pane-file-based";
18 this._treeOutlineElement = document.createElement("ol");
19 this._treeOutlineElement.className = "search-results-outline-disclosure";
20 this.element.appendChild(this._treeOutlineElement);
21 this._treeOutline = new TreeOutline(this._treeOutlineElement);
23 this._matchesExpandedCount = 0;
26 WebInspector.FileBasedSearchResultsPane.matchesExpandedByDefaultCount = 20;
27 WebInspector.FileBasedSearchResultsPane.fileMatchesShownAtOnce = 20;
29 WebInspector.FileBasedSearchResultsPane.prototype = {
31 * @param {!WebInspector.FileBasedSearchResult} searchResult
33 addSearchResult: function(searchResult)
35 this._searchResults.push(searchResult);
36 var uiSourceCode = searchResult.uiSourceCode;
39 this._addFileTreeElement(searchResult);
43 * @param {!WebInspector.FileBasedSearchResult} searchResult
45 _addFileTreeElement: function(searchResult)
47 var fileTreeElement = new WebInspector.FileBasedSearchResultsPane.FileTreeElement(this._searchConfig, searchResult);
48 this._treeOutline.appendChild(fileTreeElement);
49 // Expand until at least a certain number of matches is expanded.
50 if (this._matchesExpandedCount < WebInspector.FileBasedSearchResultsPane.matchesExpandedByDefaultCount)
51 fileTreeElement.expand();
52 this._matchesExpandedCount += searchResult.searchMatches.length;
55 __proto__: WebInspector.SearchResultsPane.prototype
60 * @extends {TreeElement}
61 * @param {!WebInspector.ProjectSearchConfig} searchConfig
62 * @param {!WebInspector.FileBasedSearchResult} searchResult
64 WebInspector.FileBasedSearchResultsPane.FileTreeElement = function(searchConfig, searchResult)
66 TreeElement.call(this, "", null, true);
67 this._searchConfig = searchConfig;
68 this._searchResult = searchResult;
70 this.toggleOnClick = true;
71 this.selectable = false;
74 WebInspector.FileBasedSearchResultsPane.FileTreeElement.prototype = {
77 if (this._initialized)
80 this._updateMatchesUI();
81 this._initialized = true;
84 _updateMatchesUI: function()
86 this.removeChildren();
87 var toIndex = Math.min(this._searchResult.searchMatches.length, WebInspector.FileBasedSearchResultsPane.fileMatchesShownAtOnce);
88 if (toIndex < this._searchResult.searchMatches.length) {
89 this._appendSearchMatches(0, toIndex - 1);
90 this._appendShowMoreMatchesElement(toIndex - 1);
92 this._appendSearchMatches(0, toIndex);
98 this._updateSearchMatches();
101 _updateSearchMatches: function()
103 this.listItemElement.classList.add("search-result");
105 var fileNameSpan = document.createElement("span");
106 fileNameSpan.className = "search-result-file-name";
107 fileNameSpan.textContent = this._searchResult.uiSourceCode.fullDisplayName();
108 this.listItemElement.appendChild(fileNameSpan);
110 var matchesCountSpan = document.createElement("span");
111 matchesCountSpan.className = "search-result-matches-count";
113 var searchMatchesCount = this._searchResult.searchMatches.length;
114 if (searchMatchesCount === 1)
115 matchesCountSpan.textContent = WebInspector.UIString("(%d match)", searchMatchesCount);
117 matchesCountSpan.textContent = WebInspector.UIString("(%d matches)", searchMatchesCount);
119 this.listItemElement.appendChild(matchesCountSpan);
121 this._updateMatchesUI();
125 * @param {number} fromIndex
126 * @param {number} toIndex
128 _appendSearchMatches: function(fromIndex, toIndex)
130 var searchResult = this._searchResult;
131 var uiSourceCode = searchResult.uiSourceCode;
132 var searchMatches = searchResult.searchMatches;
134 var queries = this._searchConfig.queries();
136 for (var i = 0; i < queries.length; ++i)
137 regexes.push(createSearchRegex(queries[i], !this._searchConfig.ignoreCase(), this._searchConfig.isRegex()));
139 for (var i = fromIndex; i < toIndex; ++i) {
140 var lineNumber = searchMatches[i].lineNumber;
141 var lineContent = searchMatches[i].lineContent;
142 var matchRanges = [];
143 for (var j = 0; j < regexes.length; ++j)
144 matchRanges = matchRanges.concat(this._regexMatchRanges(lineContent, regexes[j]));
146 var anchor = this._createAnchor(uiSourceCode, lineNumber, matchRanges[0].offset);
148 var numberString = numberToStringWithSpacesPadding(lineNumber + 1, 4);
149 var lineNumberSpan = document.createElement("span");
150 lineNumberSpan.classList.add("search-match-line-number");
151 lineNumberSpan.textContent = numberString;
152 anchor.appendChild(lineNumberSpan);
154 var contentSpan = this._createContentSpan(lineContent, matchRanges);
155 anchor.appendChild(contentSpan);
157 var searchMatchElement = new TreeElement("");
158 searchMatchElement.selectable = false;
159 this.appendChild(searchMatchElement);
160 searchMatchElement.listItemElement.className = "search-match source-code";
161 searchMatchElement.listItemElement.appendChild(anchor);
166 * @param {number} startMatchIndex
168 _appendShowMoreMatchesElement: function(startMatchIndex)
170 var matchesLeftCount = this._searchResult.searchMatches.length - startMatchIndex;
171 var showMoreMatchesText = WebInspector.UIString("Show all matches (%d more).", matchesLeftCount);
172 this._showMoreMatchesTreeElement = new TreeElement(showMoreMatchesText);
173 this.appendChild(this._showMoreMatchesTreeElement);
174 this._showMoreMatchesTreeElement.listItemElement.classList.add("show-more-matches");
175 this._showMoreMatchesTreeElement.onselect = this._showMoreMatchesElementSelected.bind(this, startMatchIndex);
179 * @param {!WebInspector.UISourceCode} uiSourceCode
180 * @param {number} lineNumber
181 * @param {number} columnNumber
184 _createAnchor: function(uiSourceCode, lineNumber, columnNumber)
186 return WebInspector.Linkifier.linkifyUsingRevealer(uiSourceCode.uiLocation(lineNumber, columnNumber), "", uiSourceCode.url, lineNumber);
190 * @param {string} lineContent
191 * @param {!Array.<!WebInspector.SourceRange>} matchRanges
193 _createContentSpan: function(lineContent, matchRanges)
195 var contentSpan = document.createElement("span");
196 contentSpan.className = "search-match-content";
197 contentSpan.textContent = lineContent;
198 WebInspector.highlightRangesWithStyleClass(contentSpan, matchRanges, "highlighted-match");
203 * @param {string} lineContent
204 * @param {!RegExp} regex
205 * @return {!Array.<!WebInspector.SourceRange>}
207 _regexMatchRanges: function(lineContent, regex)
212 var matchRanges = [];
213 while ((regex.lastIndex < lineContent.length) && (match = regex.exec(lineContent)))
214 matchRanges.push(new WebInspector.SourceRange(match.index, match[0].length));
220 * @param {number} startMatchIndex
223 _showMoreMatchesElementSelected: function(startMatchIndex)
225 this.removeChild(this._showMoreMatchesTreeElement);
226 this._appendSearchMatches(startMatchIndex, this._searchResult.searchMatches.length);
230 __proto__: TreeElement.prototype