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.VBox}
9 WebInspector.AdvancedSearchView = function()
11 WebInspector.VBox.call(this);
15 this.element.classList.add("search-view");
17 this._searchPanelElement = this.element.createChild("div", "search-drawer-header");
18 this._searchPanelElement.addEventListener("keydown", this._onKeyDown.bind(this), false);
20 this._searchResultsElement = this.element.createChild("div");
21 this._searchResultsElement.className = "search-results";
23 this._search = this._searchPanelElement.createChild("input");
24 this._search.placeholder = WebInspector.UIString("Search sources");
25 this._search.setAttribute("type", "text");
26 this._search.classList.add("search-config-search");
27 this._search.setAttribute("results", "0");
28 this._search.setAttribute("size", 30);
30 this._ignoreCaseLabel = this._searchPanelElement.createChild("label");
31 this._ignoreCaseLabel.classList.add("search-config-label");
32 this._ignoreCaseCheckbox = this._ignoreCaseLabel.createChild("input");
33 this._ignoreCaseCheckbox.setAttribute("type", "checkbox");
34 this._ignoreCaseCheckbox.classList.add("search-config-checkbox");
35 this._ignoreCaseLabel.createTextChild(WebInspector.UIString("Ignore case"));
37 this._regexLabel = this._searchPanelElement.createChild("label");
38 this._regexLabel.classList.add("search-config-label");
39 this._regexCheckbox = this._regexLabel.createChild("input");
40 this._regexCheckbox.setAttribute("type", "checkbox");
41 this._regexCheckbox.classList.add("search-config-checkbox");
42 this._regexLabel.createTextChild(WebInspector.UIString("Regular expression"));
44 this._searchStatusBarElement = this.element.createChild("div", "search-status-bar-summary");
45 this._searchMessageElement = this._searchStatusBarElement.createChild("div", "search-message");
46 this._searchProgressPlaceholderElement = this._searchStatusBarElement.createChild("div");
47 this._searchStatusBarElement.createChild("div", "search-message-spacer");
48 this._searchResultsMessageElement = this._searchStatusBarElement.createChild("div", "search-message");
50 WebInspector.settings.advancedSearchConfig = WebInspector.settings.createSetting("advancedSearchConfig", new WebInspector.SearchConfig("", true, false).toPlainObject());
52 WebInspector.AdvancedSearchView._instance = this;
53 /** @type {!WebInspector.SearchScope} */
54 this._searchScope = new WebInspector.SourcesSearchScope();
55 if (WebInspector.AdvancedSearchView._pendingQuery) {
56 this._toggle(WebInspector.AdvancedSearchView._pendingQuery);
57 delete WebInspector.AdvancedSearchView._pendingQuery;
61 WebInspector.AdvancedSearchView.prototype = {
63 * @return {!WebInspector.SearchConfig}
65 _buildSearchConfig: function()
67 return new WebInspector.SearchConfig(this._search.value, this._ignoreCaseCheckbox.checked, this._regexCheckbox.checked);
71 * @param {string} queryCandidate
73 _toggle: function(queryCandidate)
76 this._search.value = queryCandidate;
79 this._startIndexing();
83 * @param {boolean} finished
85 _onIndexingFinished: function(finished)
87 delete this._isIndexing;
88 this._indexingFinished(finished);
90 delete this._pendingSearchConfig;
91 if (!this._pendingSearchConfig)
93 var searchConfig = this._pendingSearchConfig;
94 delete this._pendingSearchConfig;
95 this._innerStartSearch(searchConfig);
98 _startIndexing: function()
100 this._isIndexing = true;
101 if (this._progressIndicator)
102 this._progressIndicator.done();
103 this._progressIndicator = new WebInspector.ProgressIndicator();
104 this._indexingStarted(this._progressIndicator);
105 this._searchScope.performIndexing(this._progressIndicator, this._onIndexingFinished.bind(this));
109 * @param {number} searchId
110 * @param {!WebInspector.FileBasedSearchResult} searchResult
112 _onSearchResult: function(searchId, searchResult)
114 if (searchId !== this._searchId)
116 this._addSearchResult(searchResult);
117 if (!searchResult.searchMatches.length)
119 if (!this._searchResultsPane)
120 this._searchResultsPane = this._searchScope.createSearchResultsPane(this._searchConfig);
121 this._resetResults();
122 this._searchResultsElement.appendChild(this._searchResultsPane.element);
123 this._searchResultsPane.addSearchResult(searchResult);
127 * @param {number} searchId
128 * @param {boolean} finished
130 _onSearchFinished: function(searchId, finished)
132 if (searchId !== this._searchId)
134 if (!this._searchResultsPane)
135 this._nothingFound();
136 this._searchFinished(finished);
137 delete this._searchConfig;
141 * @param {!WebInspector.SearchConfig} searchConfig
143 _startSearch: function(searchConfig)
147 if (!this._isIndexing)
148 this._startIndexing();
149 this._pendingSearchConfig = searchConfig;
153 * @param {!WebInspector.SearchConfig} searchConfig
155 _innerStartSearch: function(searchConfig)
157 this._searchConfig = searchConfig;
158 if (this._progressIndicator)
159 this._progressIndicator.done();
160 this._progressIndicator = new WebInspector.ProgressIndicator();
161 this._searchStarted(this._progressIndicator);
162 this._searchScope.performSearch(searchConfig, this._progressIndicator, this._onSearchResult.bind(this, this._searchId), this._onSearchFinished.bind(this, this._searchId));
165 _resetSearch: function()
169 if (this._searchResultsPane) {
170 this._resetResults();
171 delete this._searchResultsPane;
175 _stopSearch: function()
177 if (this._progressIndicator)
178 this._progressIndicator.cancel();
179 if (this._searchScope)
180 this._searchScope.stopSearch();
181 delete this._searchConfig;
185 * @param {!WebInspector.ProgressIndicator} progressIndicator
187 _searchStarted: function(progressIndicator)
189 this._resetResults();
190 this._resetCounters();
192 this._searchMessageElement.textContent = WebInspector.UIString("Searching\u2026");
193 progressIndicator.show(this._searchProgressPlaceholderElement);
194 this._updateSearchResultsMessage();
196 if (!this._searchingView)
197 this._searchingView = new WebInspector.EmptyView(WebInspector.UIString("Searching\u2026"));
198 this._searchingView.show(this._searchResultsElement);
202 * @param {!WebInspector.ProgressIndicator} progressIndicator
204 _indexingStarted: function(progressIndicator)
206 this._searchMessageElement.textContent = WebInspector.UIString("Indexing\u2026");
207 progressIndicator.show(this._searchProgressPlaceholderElement);
211 * @param {boolean} finished
213 _indexingFinished: function(finished)
215 this._searchMessageElement.textContent = finished ? "" : WebInspector.UIString("Indexing interrupted.");
218 _updateSearchResultsMessage: function()
220 if (this._searchMatchesCount && this._searchResultsCount)
221 this._searchResultsMessageElement.textContent = WebInspector.UIString("Found %d matches in %d files.", this._searchMatchesCount, this._nonEmptySearchResultsCount);
223 this._searchResultsMessageElement.textContent = "";
226 _resetResults: function()
228 if (this._searchingView)
229 this._searchingView.detach();
230 if (this._notFoundView)
231 this._notFoundView.detach();
232 this._searchResultsElement.removeChildren();
235 _resetCounters: function()
237 this._searchMatchesCount = 0;
238 this._searchResultsCount = 0;
239 this._nonEmptySearchResultsCount = 0;
242 _nothingFound: function()
244 this._resetResults();
246 if (!this._notFoundView)
247 this._notFoundView = new WebInspector.EmptyView(WebInspector.UIString("No matches found."));
248 this._notFoundView.show(this._searchResultsElement);
249 this._searchResultsMessageElement.textContent = WebInspector.UIString("No matches found.");
253 * @param {!WebInspector.FileBasedSearchResult} searchResult
255 _addSearchResult: function(searchResult)
257 this._searchMatchesCount += searchResult.searchMatches.length;
258 this._searchResultsCount++;
259 if (searchResult.searchMatches.length)
260 this._nonEmptySearchResultsCount++;
261 this._updateSearchResultsMessage();
265 * @param {boolean} finished
267 _searchFinished: function(finished)
269 this._searchMessageElement.textContent = finished ? WebInspector.UIString("Search finished.") : WebInspector.UIString("Search interrupted.");
274 WebInspector.setCurrentFocusElement(this._search);
275 this._search.select();
284 * @param {!Event} event
286 _onKeyDown: function(event)
288 switch (event.keyCode) {
289 case WebInspector.KeyboardShortcut.Keys.Enter.code:
297 WebInspector.settings.advancedSearchConfig.set(this._buildSearchConfig().toPlainObject());
302 var searchConfig = WebInspector.SearchConfig.fromPlainObject(WebInspector.settings.advancedSearchConfig.get());
303 this._search.value = searchConfig.query();
304 this._ignoreCaseCheckbox.checked = searchConfig.ignoreCase();
305 this._regexCheckbox.checked = searchConfig.isRegex();
308 _onAction: function()
310 var searchConfig = this._buildSearchConfig();
311 if (!searchConfig.query() || !searchConfig.query().length)
315 this._startSearch(searchConfig);
318 __proto__: WebInspector.VBox.prototype
323 * @param {!WebInspector.ProjectSearchConfig} searchConfig
325 WebInspector.SearchResultsPane = function(searchConfig)
327 this._searchConfig = searchConfig;
328 this.element = createElement("div");
331 WebInspector.SearchResultsPane.prototype = {
333 * @return {!WebInspector.ProjectSearchConfig}
337 return this._searchConfig;
341 * @param {!WebInspector.FileBasedSearchResult} searchResult
343 addSearchResult: function(searchResult) { }
348 * @implements {WebInspector.ActionDelegate}
350 WebInspector.AdvancedSearchView.ToggleDrawerViewActionDelegate = function()
354 WebInspector.AdvancedSearchView.ToggleDrawerViewActionDelegate.prototype = {
357 * // FIXME: remove this suppression.
358 * @suppressGlobalPropertiesCheck
360 handleAction: function()
362 var searchView = WebInspector.AdvancedSearchView._instance;
363 if (!searchView || !searchView.isShowing() || searchView._search !== document.activeElement) {
364 var selection = window.getSelection();
365 var queryCandidate = "";
366 if (selection.rangeCount)
367 queryCandidate = selection.toString().replace(/\r?\n.*/, "");
369 WebInspector.inspectorView.setCurrentPanel(WebInspector.SourcesPanel.instance());
370 WebInspector.inspectorView.showViewInDrawer("sources.search");
371 if (WebInspector.AdvancedSearchView._instance)
372 WebInspector.AdvancedSearchView._instance._toggle(queryCandidate);
374 WebInspector.AdvancedSearchView._pendingQuery = queryCandidate;
376 WebInspector.inspectorView.closeDrawer();
384 * @param {!WebInspector.UISourceCode} uiSourceCode
385 * @param {!Array.<!Object>} searchMatches
387 WebInspector.FileBasedSearchResult = function(uiSourceCode, searchMatches) {
388 this.uiSourceCode = uiSourceCode;
389 this.searchMatches = searchMatches;
395 WebInspector.SearchScope = function()
399 WebInspector.SearchScope.prototype = {
401 * @param {!WebInspector.SearchConfig} searchConfig
402 * @param {!WebInspector.Progress} progress
403 * @param {function(!WebInspector.FileBasedSearchResult)} searchResultCallback
404 * @param {function(boolean)} searchFinishedCallback
406 performSearch: function(searchConfig, progress, searchResultCallback, searchFinishedCallback) { },
409 * @param {!WebInspector.Progress} progress
410 * @param {function(boolean)} callback
412 performIndexing: function(progress, callback) { },
414 stopSearch: function() { },
417 * @param {!WebInspector.ProjectSearchConfig} searchConfig
418 * @return {!WebInspector.SearchResultsPane}
420 createSearchResultsPane: function(searchConfig) { }