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.appendChild(document.createTextNode(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.appendChild(document.createTextNode(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();
57 WebInspector.AdvancedSearchView.prototype = {
59 * @return {!WebInspector.SearchConfig}
61 _buildSearchConfig: function()
63 return new WebInspector.SearchConfig(this._search.value, this._ignoreCaseCheckbox.checked, this._regexCheckbox.checked);
67 * @param {string} queryCandidate
69 _toggle: function(queryCandidate)
72 this._search.value = queryCandidate;
75 this._startIndexing();
79 * @param {boolean} finished
81 _onIndexingFinished: function(finished)
83 delete this._isIndexing;
84 this._indexingFinished(finished);
86 delete this._pendingSearchConfig;
87 if (!this._pendingSearchConfig)
89 var searchConfig = this._pendingSearchConfig;
90 delete this._pendingSearchConfig;
91 this._innerStartSearch(searchConfig);
94 _startIndexing: function()
96 this._isIndexing = true;
97 if (this._progressIndicator)
98 this._progressIndicator.done();
99 this._progressIndicator = new WebInspector.ProgressIndicator();
100 this._indexingStarted(this._progressIndicator);
101 this._searchScope.performIndexing(this._progressIndicator, this._onIndexingFinished.bind(this));
105 * @param {number} searchId
106 * @param {!WebInspector.FileBasedSearchResult} searchResult
108 _onSearchResult: function(searchId, searchResult)
110 if (searchId !== this._searchId)
112 this._addSearchResult(searchResult);
113 if (!searchResult.searchMatches.length)
115 if (!this._searchResultsPane)
116 this._searchResultsPane = this._searchScope.createSearchResultsPane(this._searchConfig);
117 this._resetResults();
118 this._searchResultsElement.appendChild(this._searchResultsPane.element);
119 this._searchResultsPane.addSearchResult(searchResult);
123 * @param {number} searchId
124 * @param {boolean} finished
126 _onSearchFinished: function(searchId, finished)
128 if (searchId !== this._searchId)
130 if (!this._searchResultsPane)
131 this._nothingFound();
132 this._searchFinished(finished);
133 delete this._searchConfig;
137 * @param {!WebInspector.SearchConfig} searchConfig
139 _startSearch: function(searchConfig)
143 if (!this._isIndexing)
144 this._startIndexing();
145 this._pendingSearchConfig = searchConfig;
149 * @param {!WebInspector.SearchConfig} searchConfig
151 _innerStartSearch: function(searchConfig)
153 this._searchConfig = searchConfig;
154 if (this._progressIndicator)
155 this._progressIndicator.done();
156 this._progressIndicator = new WebInspector.ProgressIndicator();
157 this._searchStarted(this._progressIndicator);
158 this._searchScope.performSearch(searchConfig, this._progressIndicator, this._onSearchResult.bind(this, this._searchId), this._onSearchFinished.bind(this, this._searchId));
161 _resetSearch: function()
165 if (this._searchResultsPane) {
166 this._resetResults();
167 delete this._searchResultsPane;
171 _stopSearch: function()
173 if (this._progressIndicator)
174 this._progressIndicator.cancel();
175 if (this._searchScope)
176 this._searchScope.stopSearch();
177 delete this._searchConfig;
181 * @param {!WebInspector.ProgressIndicator} progressIndicator
183 _searchStarted: function(progressIndicator)
185 this._resetResults();
186 this._resetCounters();
188 this._searchMessageElement.textContent = WebInspector.UIString("Searching\u2026");
189 progressIndicator.show(this._searchProgressPlaceholderElement);
190 this._updateSearchResultsMessage();
192 if (!this._searchingView)
193 this._searchingView = new WebInspector.EmptyView(WebInspector.UIString("Searching\u2026"));
194 this._searchingView.show(this._searchResultsElement);
198 * @param {!WebInspector.ProgressIndicator} progressIndicator
200 _indexingStarted: function(progressIndicator)
202 this._searchMessageElement.textContent = WebInspector.UIString("Indexing\u2026");
203 progressIndicator.show(this._searchProgressPlaceholderElement);
207 * @param {boolean} finished
209 _indexingFinished: function(finished)
211 this._searchMessageElement.textContent = finished ? "" : WebInspector.UIString("Indexing interrupted.");
214 _updateSearchResultsMessage: function()
216 if (this._searchMatchesCount && this._searchResultsCount)
217 this._searchResultsMessageElement.textContent = WebInspector.UIString("Found %d matches in %d files.", this._searchMatchesCount, this._nonEmptySearchResultsCount);
219 this._searchResultsMessageElement.textContent = "";
222 _resetResults: function()
224 if (this._searchingView)
225 this._searchingView.detach();
226 if (this._notFoundView)
227 this._notFoundView.detach();
228 this._searchResultsElement.removeChildren();
231 _resetCounters: function()
233 this._searchMatchesCount = 0;
234 this._searchResultsCount = 0;
235 this._nonEmptySearchResultsCount = 0;
238 _nothingFound: function()
240 this._resetResults();
242 if (!this._notFoundView)
243 this._notFoundView = new WebInspector.EmptyView(WebInspector.UIString("No matches found."));
244 this._notFoundView.show(this._searchResultsElement);
245 this._searchResultsMessageElement.textContent = WebInspector.UIString("No matches found.");
249 * @param {!WebInspector.FileBasedSearchResult} searchResult
251 _addSearchResult: function(searchResult)
253 this._searchMatchesCount += searchResult.searchMatches.length;
254 this._searchResultsCount++;
255 if (searchResult.searchMatches.length)
256 this._nonEmptySearchResultsCount++;
257 this._updateSearchResultsMessage();
261 * @param {boolean} finished
263 _searchFinished: function(finished)
265 this._searchMessageElement.textContent = finished ? WebInspector.UIString("Search finished.") : WebInspector.UIString("Search interrupted.");
270 WebInspector.setCurrentFocusElement(this._search);
271 this._search.select();
280 * @param {!Event} event
282 _onKeyDown: function(event)
284 switch (event.keyCode) {
285 case WebInspector.KeyboardShortcut.Keys.Enter.code:
293 WebInspector.settings.advancedSearchConfig.set(this._buildSearchConfig().toPlainObject());
298 var searchConfig = WebInspector.SearchConfig.fromPlainObject(WebInspector.settings.advancedSearchConfig.get());
299 this._search.value = searchConfig.query();
300 this._ignoreCaseCheckbox.checked = searchConfig.ignoreCase();
301 this._regexCheckbox.checked = searchConfig.isRegex();
304 _onAction: function()
306 var searchConfig = this._buildSearchConfig();
307 if (!searchConfig.query() || !searchConfig.query().length)
311 this._startSearch(searchConfig);
314 __proto__: WebInspector.VBox.prototype
319 * @param {!WebInspector.ProjectSearchConfig} searchConfig
321 WebInspector.SearchResultsPane = function(searchConfig)
323 this._searchConfig = searchConfig;
324 this.element = document.createElement("div");
327 WebInspector.SearchResultsPane.prototype = {
329 * @return {!WebInspector.ProjectSearchConfig}
333 return this._searchConfig;
337 * @param {!WebInspector.FileBasedSearchResult} searchResult
339 addSearchResult: function(searchResult) { }
344 * @implements {WebInspector.ActionDelegate}
346 WebInspector.AdvancedSearchView.ToggleDrawerViewActionDelegate = function()
350 WebInspector.AdvancedSearchView.ToggleDrawerViewActionDelegate.prototype = {
354 handleAction: function()
356 var searchView = WebInspector.AdvancedSearchView._instance;
357 if (!searchView || !searchView.isShowing() || searchView._search !== document.activeElement) {
358 var selection = window.getSelection();
359 var queryCandidate = "";
360 if (selection.rangeCount)
361 queryCandidate = selection.toString().replace(/\r?\n.*/, "");
363 WebInspector.inspectorView.showPanel("sources");
364 WebInspector.inspectorView.showViewInDrawer("sources.search");
365 WebInspector.AdvancedSearchView._instance._toggle(queryCandidate);
367 WebInspector.inspectorView.closeDrawer();
375 * @param {!WebInspector.UISourceCode} uiSourceCode
376 * @param {!Array.<!Object>} searchMatches
378 WebInspector.FileBasedSearchResult = function(uiSourceCode, searchMatches) {
379 this.uiSourceCode = uiSourceCode;
380 this.searchMatches = searchMatches;
386 WebInspector.SearchScope = function()
390 WebInspector.SearchScope.prototype = {
392 * @param {!WebInspector.SearchConfig} searchConfig
393 * @param {!WebInspector.Progress} progress
394 * @param {function(!WebInspector.FileBasedSearchResult)} searchResultCallback
395 * @param {function(boolean)} searchFinishedCallback
397 performSearch: function(searchConfig, progress, searchResultCallback, searchFinishedCallback) { },
400 * @param {!WebInspector.Progress} progress
401 * @param {function(boolean)} callback
403 performIndexing: function(progress, callback) { },
405 stopSearch: function() { },
408 * @param {!WebInspector.ProjectSearchConfig} searchConfig
409 * @return {!WebInspector.SearchResultsPane}
411 createSearchResultsPane: function(searchConfig) { }