Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / devtools / front_end / sources / AdvancedSearchView.js
blobe2edd3946f1f2ac3cedbd2276df912241e3ff3cf
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.
5 /**
6 * @constructor
7 * @extends {WebInspector.VBox}
8 */
9 WebInspector.AdvancedSearchView = function()
11 WebInspector.VBox.call(this, true);
12 this.setMinimumSize(0, 40);
13 this.registerRequiredCSS("sources/sourcesSearch.css");
15 this._searchId = 0;
17 this.contentElement.classList.add("search-view");
19 this._searchPanelElement = this.contentElement.createChild("div", "search-drawer-header");
20 this._searchPanelElement.addEventListener("keydown", this._onKeyDown.bind(this), false);
22 this._searchResultsElement = this.contentElement.createChild("div");
23 this._searchResultsElement.className = "search-results";
25 this._search = WebInspector.HistoryInput.create();
26 this._searchPanelElement.appendChild(this._search);
27 this._search.placeholder = WebInspector.UIString("Enter query, use `file:` to filter by path");
28 this._search.setAttribute("type", "text");
29 this._search.classList.add("search-config-search");
30 this._search.setAttribute("results", "0");
31 this._search.setAttribute("size", 30);
33 this._ignoreCaseLabel = createCheckboxLabel(WebInspector.UIString("Ignore case"));
34 this._ignoreCaseLabel.classList.add("search-config-label");
35 this._searchPanelElement.appendChild(this._ignoreCaseLabel);
36 this._ignoreCaseCheckbox = this._ignoreCaseLabel.checkboxElement;
37 this._ignoreCaseCheckbox.classList.add("search-config-checkbox");
39 this._regexLabel = createCheckboxLabel(WebInspector.UIString("Regular expression"));
40 this._regexLabel.classList.add("search-config-label");
41 this._searchPanelElement.appendChild(this._regexLabel);
42 this._regexCheckbox = this._regexLabel.checkboxElement;
43 this._regexCheckbox.classList.add("search-config-checkbox");
45 this._searchToolbarElement = this.contentElement.createChild("div", "search-toolbar-summary");
46 this._searchMessageElement = this._searchToolbarElement.createChild("div", "search-message");
47 this._searchProgressPlaceholderElement = this._searchToolbarElement.createChild("div", "flex-centered");
48 this._searchToolbarElement.createChild("div", "search-message-spacer");
49 this._searchResultsMessageElement = this._searchToolbarElement.createChild("div", "search-message");
51 this._advancedSearchConfig = WebInspector.settings.createLocalSetting("advancedSearchConfig", new WebInspector.SearchConfig("", true, false).toPlainObject());
52 this._load();
53 /** @type {!WebInspector.SearchScope} */
54 this._searchScope = new WebInspector.SourcesSearchScope();
57 WebInspector.AdvancedSearchView.prototype = {
58 /**
59 * @return {!WebInspector.SearchConfig}
61 _buildSearchConfig: function()
63 return new WebInspector.SearchConfig(this._search.value, this._ignoreCaseCheckbox.checked, this._regexCheckbox.checked);
66 /**
67 * @param {string} queryCandidate
69 _toggle: function(queryCandidate)
71 if (queryCandidate)
72 this._search.value = queryCandidate;
73 this.focus();
75 this._startIndexing();
78 _onIndexingFinished: function()
80 var finished = !this._progressIndicator.isCanceled();
81 this._progressIndicator.done();
82 delete this._progressIndicator;
83 delete this._isIndexing;
84 this._indexingFinished(finished);
85 if (!finished)
86 delete this._pendingSearchConfig;
87 if (!this._pendingSearchConfig)
88 return;
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._searchMessageElement.textContent = WebInspector.UIString("Indexing\u2026");
101 this._progressIndicator.show(this._searchProgressPlaceholderElement);
102 this._searchScope.performIndexing(new WebInspector.ProgressProxy(this._progressIndicator, this._onIndexingFinished.bind(this)));
106 * @param {number} searchId
107 * @param {!WebInspector.FileBasedSearchResult} searchResult
109 _onSearchResult: function(searchId, searchResult)
111 if (searchId !== this._searchId || !this._progressIndicator)
112 return;
113 if (this._progressIndicator && this._progressIndicator.isCanceled()) {
114 this._onIndexingFinished();
115 return;
117 this._addSearchResult(searchResult);
118 if (!searchResult.searchMatches.length)
119 return;
120 if (!this._searchResultsPane)
121 this._searchResultsPane = this._searchScope.createSearchResultsPane(this._searchConfig);
122 this._resetResults();
123 this._searchResultsElement.appendChild(this._searchResultsPane.element);
124 this._searchResultsPane.addSearchResult(searchResult);
128 * @param {number} searchId
129 * @param {boolean} finished
131 _onSearchFinished: function(searchId, finished)
133 if (searchId !== this._searchId || !this._progressIndicator)
134 return;
135 if (!this._searchResultsPane)
136 this._nothingFound();
137 this._searchFinished(finished);
138 delete this._searchConfig;
142 * @param {!WebInspector.SearchConfig} searchConfig
144 _startSearch: function(searchConfig)
146 this._resetSearch();
147 ++this._searchId;
148 if (!this._isIndexing)
149 this._startIndexing();
150 this._pendingSearchConfig = searchConfig;
154 * @param {!WebInspector.SearchConfig} searchConfig
156 _innerStartSearch: function(searchConfig)
158 this._searchConfig = searchConfig;
159 if (this._progressIndicator)
160 this._progressIndicator.done();
161 this._progressIndicator = new WebInspector.ProgressIndicator();
162 this._searchStarted(this._progressIndicator);
163 this._searchScope.performSearch(searchConfig, this._progressIndicator, this._onSearchResult.bind(this, this._searchId), this._onSearchFinished.bind(this, this._searchId));
166 _resetSearch: function()
168 this._stopSearch();
170 if (this._searchResultsPane) {
171 this._resetResults();
172 delete this._searchResultsPane;
176 _stopSearch: function()
178 if (this._progressIndicator && !this._isIndexing)
179 this._progressIndicator.cancel();
180 if (this._searchScope)
181 this._searchScope.stopSearch();
182 delete this._searchConfig;
186 * @param {!WebInspector.ProgressIndicator} progressIndicator
188 _searchStarted: function(progressIndicator)
190 this._resetResults();
191 this._resetCounters();
193 this._searchMessageElement.textContent = WebInspector.UIString("Searching\u2026");
194 progressIndicator.show(this._searchProgressPlaceholderElement);
195 this._updateSearchResultsMessage();
197 if (!this._searchingView)
198 this._searchingView = new WebInspector.EmptyWidget(WebInspector.UIString("Searching\u2026"));
199 this._searchingView.show(this._searchResultsElement);
203 * @param {boolean} finished
205 _indexingFinished: function(finished)
207 this._searchMessageElement.textContent = finished ? "" : WebInspector.UIString("Indexing interrupted.");
210 _updateSearchResultsMessage: function()
212 if (this._searchMatchesCount && this._searchResultsCount)
213 this._searchResultsMessageElement.textContent = WebInspector.UIString("Found %d matches in %d files.", this._searchMatchesCount, this._nonEmptySearchResultsCount);
214 else
215 this._searchResultsMessageElement.textContent = "";
218 _resetResults: function()
220 if (this._searchingView)
221 this._searchingView.detach();
222 if (this._notFoundView)
223 this._notFoundView.detach();
224 this._searchResultsElement.removeChildren();
227 _resetCounters: function()
229 this._searchMatchesCount = 0;
230 this._searchResultsCount = 0;
231 this._nonEmptySearchResultsCount = 0;
234 _nothingFound: function()
236 this._resetResults();
238 if (!this._notFoundView)
239 this._notFoundView = new WebInspector.EmptyWidget(WebInspector.UIString("No matches found."));
240 this._notFoundView.show(this._searchResultsElement);
241 this._searchResultsMessageElement.textContent = WebInspector.UIString("No matches found.");
245 * @param {!WebInspector.FileBasedSearchResult} searchResult
247 _addSearchResult: function(searchResult)
249 this._searchMatchesCount += searchResult.searchMatches.length;
250 this._searchResultsCount++;
251 if (searchResult.searchMatches.length)
252 this._nonEmptySearchResultsCount++;
253 this._updateSearchResultsMessage();
257 * @param {boolean} finished
259 _searchFinished: function(finished)
261 this._searchMessageElement.textContent = finished ? WebInspector.UIString("Search finished.") : WebInspector.UIString("Search interrupted.");
264 focus: function()
266 WebInspector.setCurrentFocusElement(this._search);
267 this._search.select();
270 willHide: function()
272 this._stopSearch();
276 * @param {!Event} event
278 _onKeyDown: function(event)
280 switch (event.keyCode) {
281 case WebInspector.KeyboardShortcut.Keys.Enter.code:
282 this._onAction();
283 break;
287 _save: function()
289 this._advancedSearchConfig.set(this._buildSearchConfig().toPlainObject());
292 _load: function()
294 var searchConfig = WebInspector.SearchConfig.fromPlainObject(this._advancedSearchConfig.get());
295 this._search.value = searchConfig.query();
296 this._ignoreCaseCheckbox.checked = searchConfig.ignoreCase();
297 this._regexCheckbox.checked = searchConfig.isRegex();
300 _onAction: function()
302 var searchConfig = this._buildSearchConfig();
303 if (!searchConfig.query() || !searchConfig.query().length)
304 return;
306 this._save();
307 this._startSearch(searchConfig);
310 __proto__: WebInspector.VBox.prototype
314 * @constructor
315 * @param {!WebInspector.ProjectSearchConfig} searchConfig
317 WebInspector.SearchResultsPane = function(searchConfig)
319 this._searchConfig = searchConfig;
320 this.element = createElement("div");
323 WebInspector.SearchResultsPane.prototype = {
325 * @return {!WebInspector.ProjectSearchConfig}
327 get searchConfig()
329 return this._searchConfig;
333 * @param {!WebInspector.FileBasedSearchResult} searchResult
335 addSearchResult: function(searchResult) { }
339 * @constructor
340 * @implements {WebInspector.ActionDelegate}
342 WebInspector.AdvancedSearchView.ActionDelegate = function()
344 this._searchView = new WebInspector.AdvancedSearchView();
347 WebInspector.AdvancedSearchView.ActionDelegate.prototype = {
349 * @override
350 * @param {!WebInspector.Context} context
351 * @param {string} actionId
353 handleAction: function(context, actionId)
355 if (!this._searchView.isShowing() || this._searchView._search !== this._searchView.element.window().document.activeElement) {
356 var selection = WebInspector.inspectorView.element.getDeepSelection();
357 var queryCandidate = "";
358 if (selection.rangeCount)
359 queryCandidate = selection.toString().replace(/\r?\n.*/, "");
361 WebInspector.inspectorView.setCurrentPanel(WebInspector.SourcesPanel.instance());
362 this._searchView._toggle(queryCandidate);
363 WebInspector.inspectorView.showCloseableViewInDrawer("sources.search", WebInspector.UIString("Search"), this._searchView);
364 this._searchView.focus();
370 * @constructor
371 * @param {!WebInspector.UISourceCode} uiSourceCode
372 * @param {!Array.<!Object>} searchMatches
374 WebInspector.FileBasedSearchResult = function(uiSourceCode, searchMatches) {
375 this.uiSourceCode = uiSourceCode;
376 this.searchMatches = searchMatches;
380 * @interface
382 WebInspector.SearchScope = function()
386 WebInspector.SearchScope.prototype = {
388 * @param {!WebInspector.SearchConfig} searchConfig
389 * @param {!WebInspector.Progress} progress
390 * @param {function(!WebInspector.FileBasedSearchResult)} searchResultCallback
391 * @param {function(boolean)} searchFinishedCallback
393 performSearch: function(searchConfig, progress, searchResultCallback, searchFinishedCallback) { },
396 * @param {!WebInspector.Progress} progress
398 performIndexing: function(progress) { },
400 stopSearch: function() { },
403 * @param {!WebInspector.ProjectSearchConfig} searchConfig
404 * @return {!WebInspector.SearchResultsPane}
406 createSearchResultsPane: function(searchConfig) { }