Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / devtools / front_end / sources / AdvancedSearchView.js
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.
4
5 /**
6  * @constructor
7  * @extends {WebInspector.VBox}
8  */
9 WebInspector.AdvancedSearchView = function()
10 {
11     WebInspector.VBox.call(this);
12
13     this._searchId = 0;
14
15     this.element.classList.add("search-view");
16
17     this._searchPanelElement = this.element.createChild("div", "search-drawer-header");
18     this._searchPanelElement.addEventListener("keydown", this._onKeyDown.bind(this), false);
19
20     this._searchResultsElement = this.element.createChild("div");
21     this._searchResultsElement.className = "search-results";
22
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);
29
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")));
36
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")));
43
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");
49
50     WebInspector.settings.advancedSearchConfig = WebInspector.settings.createSetting("advancedSearchConfig", new WebInspector.SearchConfig("", true, false).toPlainObject());
51     this._load();
52     WebInspector.AdvancedSearchView._instance = this;
53     /** @type {!WebInspector.SearchScope} */
54     this._searchScope = new WebInspector.SourcesSearchScope();
55 }
56
57 WebInspector.AdvancedSearchView.prototype = {
58     /**
59      * @return {!WebInspector.SearchConfig}
60      */
61     _buildSearchConfig: function()
62     {
63         return new WebInspector.SearchConfig(this._search.value, this._ignoreCaseCheckbox.checked, this._regexCheckbox.checked);
64     },
65
66     /**
67      * @param {string} queryCandidate
68      */
69     _toggle: function(queryCandidate)
70     {
71         if (queryCandidate)
72             this._search.value = queryCandidate;
73         this.focus();
74
75         this._startIndexing();
76     },
77
78     /**
79      * @param {boolean} finished
80      */
81     _onIndexingFinished: function(finished)
82     {
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);
92     },
93
94     _startIndexing: function()
95     {
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));
102     },
103
104     /**
105      * @param {number} searchId
106      * @param {!WebInspector.FileBasedSearchResult} searchResult
107      */
108     _onSearchResult: function(searchId, searchResult)
109     {
110         if (searchId !== this._searchId)
111             return;
112         this._addSearchResult(searchResult);
113         if (!searchResult.searchMatches.length)
114             return;
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);
120     },
121
122     /**
123      * @param {number} searchId
124      * @param {boolean} finished
125      */
126     _onSearchFinished: function(searchId, finished)
127     {
128         if (searchId !== this._searchId)
129             return;
130         if (!this._searchResultsPane)
131             this._nothingFound();
132         this._searchFinished(finished);
133         delete this._searchConfig;
134     },
135
136     /**
137      * @param {!WebInspector.SearchConfig} searchConfig
138      */
139     _startSearch: function(searchConfig)
140     {
141         this._resetSearch();
142         ++this._searchId;
143         if (!this._isIndexing)
144             this._startIndexing();
145         this._pendingSearchConfig = searchConfig;
146     },
147
148     /**
149      * @param {!WebInspector.SearchConfig} searchConfig
150      */
151     _innerStartSearch: function(searchConfig)
152     {
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));
159     },
160
161     _resetSearch: function()
162     {
163         this._stopSearch();
164
165         if (this._searchResultsPane) {
166             this._resetResults();
167             delete this._searchResultsPane;
168         }
169     },
170
171     _stopSearch: function()
172     {
173         if (this._progressIndicator)
174             this._progressIndicator.cancel();
175         if (this._searchScope)
176             this._searchScope.stopSearch();
177         delete this._searchConfig;
178     },
179
180     /**
181      * @param {!WebInspector.ProgressIndicator} progressIndicator
182      */
183     _searchStarted: function(progressIndicator)
184     {
185         this._resetResults();
186         this._resetCounters();
187
188         this._searchMessageElement.textContent = WebInspector.UIString("Searching\u2026");
189         progressIndicator.show(this._searchProgressPlaceholderElement);
190         this._updateSearchResultsMessage();
191
192         if (!this._searchingView)
193             this._searchingView = new WebInspector.EmptyView(WebInspector.UIString("Searching\u2026"));
194         this._searchingView.show(this._searchResultsElement);
195     },
196
197     /**
198      * @param {!WebInspector.ProgressIndicator} progressIndicator
199      */
200     _indexingStarted: function(progressIndicator)
201     {
202         this._searchMessageElement.textContent = WebInspector.UIString("Indexing\u2026");
203         progressIndicator.show(this._searchProgressPlaceholderElement);
204     },
205
206     /**
207      * @param {boolean} finished
208      */
209     _indexingFinished: function(finished)
210     {
211         this._searchMessageElement.textContent = finished ? "" : WebInspector.UIString("Indexing interrupted.");
212     },
213
214     _updateSearchResultsMessage: function()
215     {
216         if (this._searchMatchesCount && this._searchResultsCount)
217             this._searchResultsMessageElement.textContent = WebInspector.UIString("Found %d matches in %d files.", this._searchMatchesCount, this._nonEmptySearchResultsCount);
218         else
219             this._searchResultsMessageElement.textContent = "";
220     },
221
222     _resetResults: function()
223     {
224         if (this._searchingView)
225             this._searchingView.detach();
226         if (this._notFoundView)
227             this._notFoundView.detach();
228         this._searchResultsElement.removeChildren();
229     },
230
231     _resetCounters: function()
232     {
233         this._searchMatchesCount = 0;
234         this._searchResultsCount = 0;
235         this._nonEmptySearchResultsCount = 0;
236     },
237
238     _nothingFound: function()
239     {
240         this._resetResults();
241
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.");
246     },
247
248     /**
249      * @param {!WebInspector.FileBasedSearchResult} searchResult
250      */
251     _addSearchResult: function(searchResult)
252     {
253         this._searchMatchesCount += searchResult.searchMatches.length;
254         this._searchResultsCount++;
255         if (searchResult.searchMatches.length)
256             this._nonEmptySearchResultsCount++;
257         this._updateSearchResultsMessage();
258     },
259
260     /**
261      * @param {boolean} finished
262      */
263     _searchFinished: function(finished)
264     {
265         this._searchMessageElement.textContent = finished ? WebInspector.UIString("Search finished.") : WebInspector.UIString("Search interrupted.");
266     },
267
268     focus: function()
269     {
270         WebInspector.setCurrentFocusElement(this._search);
271         this._search.select();
272     },
273
274     willHide: function()
275     {
276         this._stopSearch();
277     },
278
279     /**
280      * @param {!Event} event
281      */
282     _onKeyDown: function(event)
283     {
284         switch (event.keyCode) {
285         case WebInspector.KeyboardShortcut.Keys.Enter.code:
286             this._onAction();
287             break;
288         }
289     },
290
291     _save: function()
292     {
293         WebInspector.settings.advancedSearchConfig.set(this._buildSearchConfig().toPlainObject());
294     },
295
296     _load: function()
297     {
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();
302     },
303
304     _onAction: function()
305     {
306         var searchConfig = this._buildSearchConfig();
307         if (!searchConfig.query() || !searchConfig.query().length)
308             return;
309
310         this._save();
311         this._startSearch(searchConfig);
312     },
313
314     __proto__: WebInspector.VBox.prototype
315 }
316
317 /**
318  * @constructor
319  * @param {!WebInspector.ProjectSearchConfig} searchConfig
320  */
321 WebInspector.SearchResultsPane = function(searchConfig)
322 {
323     this._searchConfig = searchConfig;
324     this.element = document.createElement("div");
325 }
326
327 WebInspector.SearchResultsPane.prototype = {
328     /**
329      * @return {!WebInspector.ProjectSearchConfig}
330      */
331     get searchConfig()
332     {
333         return this._searchConfig;
334     },
335
336     /**
337      * @param {!WebInspector.FileBasedSearchResult} searchResult
338      */
339     addSearchResult: function(searchResult) { }
340 }
341
342 /**
343  * @constructor
344  * @implements {WebInspector.ActionDelegate}
345  */
346 WebInspector.AdvancedSearchView.ToggleDrawerViewActionDelegate = function()
347 {
348 }
349
350 WebInspector.AdvancedSearchView.ToggleDrawerViewActionDelegate.prototype = {
351     /**
352      * @return {boolean}
353      */
354     handleAction: function()
355     {
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.*/, "");
362
363             WebInspector.inspectorView.showPanel("sources");
364             WebInspector.inspectorView.showViewInDrawer("sources.search");
365             WebInspector.AdvancedSearchView._instance._toggle(queryCandidate);
366         } else {
367             WebInspector.inspectorView.closeDrawer();
368         }
369         return true;
370     }
371 }
372
373 /**
374  * @constructor
375  * @param {!WebInspector.UISourceCode} uiSourceCode
376  * @param {!Array.<!Object>} searchMatches
377  */
378 WebInspector.FileBasedSearchResult = function(uiSourceCode, searchMatches) {
379     this.uiSourceCode = uiSourceCode;
380     this.searchMatches = searchMatches;
381 }
382
383 /**
384  * @interface
385  */
386 WebInspector.SearchScope = function()
387 {
388 }
389
390 WebInspector.SearchScope.prototype = {
391     /**
392      * @param {!WebInspector.SearchConfig} searchConfig
393      * @param {!WebInspector.Progress} progress
394      * @param {function(!WebInspector.FileBasedSearchResult)} searchResultCallback
395      * @param {function(boolean)} searchFinishedCallback
396      */
397     performSearch: function(searchConfig, progress, searchResultCallback, searchFinishedCallback) { },
398
399     /**
400      * @param {!WebInspector.Progress} progress
401      * @param {function(boolean)} callback
402      */
403     performIndexing: function(progress, callback) { },
404
405     stopSearch: function() { },
406
407     /**
408      * @param {!WebInspector.ProjectSearchConfig} searchConfig
409      * @return {!WebInspector.SearchResultsPane}
410      */
411     createSearchResultsPane: function(searchConfig) { }
412 }