Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(38)

Side by Side Diff: pkg/dartdoc/dropdown.dart

Issue 10829361: 'Find-as-you-type'-search in dartdoc/apidoc. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/dartdoc/dartdoc.dart ('k') | pkg/dartdoc/mirrors/dart2js_mirror.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 List libraryList;
6 InputElement searchInput;
7 DivElement dropdown;
8
9 /**
10 * Update the search drop down based on the current search text.
11 */
12 updateDropDown(Event event) {
13 if (libraryList == null) return;
14 if (searchInput == null) return;
15 if (dropdown == null) return;
16
17 var results = <Result>[];
18 String text = searchInput.value;
19 if (text == currentSearchText) {
20 return;
21 }
22 if (text.isEmpty()) {
23 updateResults(text, results);
24 hideDropDown();
25 return;
26 }
27 if (text.contains('.')) {
28 // Search type members.
29 String typeText = text.substring(0, text.indexOf('.'));
30 String memberText = text.substring(text.indexOf('.') + 1);
31
32 if (typeText.isEmpty() && memberText.isEmpty()) {
33 // Don't search on '.'.
34 } else if (typeText.isEmpty()) {
35 // Search text is of the form '.id' => Look up members.
36 matchAllMembers(results, memberText);
37 } else if (memberText.isEmpty()) {
38 // Search text is of the form 'Type.' => Look up members in 'Type'.
39 matchAllMembersInType(results, typeText, memberText);
40 } else {
41 // Search text is of the form 'Type.id' => Look up member 'id' in 'Type'.
42 matchMembersInType(results, text, typeText, memberText);
43 }
44 } else {
45 // Search all entities.
46 var searchText = new SearchText(text);
47 for (Map<String,Dynamic> library in libraryList) {
48 matchLibrary(results, searchText, library);
49 matchLibraryMembers(results, searchText, library);
50 matchTypes(results, searchText, library);
51 }
52 }
53 var elements = <Element>[];
54 var table = new TableElement();
55 table.classes.add('drop-down-table');
56 elements.add(table);
57
58 if (results.isEmpty()) {
59 var row = table.insertRow(0);
60 row.innerHTML = "<tr><td>No matches found for '$text'.</td></tr>";
61 } else {
62 results.sort(resultComparator);
63
64 var count = 0;
65 for (Result result in results) {
66 result.addRow(table);
67 if (++count >= 10) {
68 break;
69 }
70 }
71 if (results.length >= 10) {
72 var row = table.insertRow(table.rows.length);
73 row.innerHTML = '<tr><td>+ ${results.length-10} more.</td></tr>';
74 results = results.getRange(0, 10);
75 }
76 }
77 dropdown.elements = elements;
78 updateResults(text, results);
79 showDropDown();
80 }
81
82 void matchAllMembers(List<Result> results, String memberText) {
83 var searchText = new SearchText(memberText);
84 for (Map<String,Dynamic> library in libraryList) {
85 String libraryName = library[NAME];
86 if (library.containsKey(TYPES)) {
87 for (Map<String,Dynamic> type in library[TYPES]) {
88 String typeName = type[NAME];
89 if (type.containsKey(MEMBERS)) {
90 for (Map<String,Dynamic> member in type[MEMBERS]) {
91 StringMatch memberMatch = obtainMatch(searchText, member[NAME]);
92 if (memberMatch != null) {
93 results.add(new Result(memberMatch, member[KIND],
94 getTypeMemberUrl(libraryName, typeName, member),
95 library: libraryName, type: typeName, args: type[ARGS]));
96 }
97 }
98 }
99 }
100 }
101 }
102 }
103
104 void matchAllMembersInType(List<Result> results,
105 String typeText, String memberText) {
106 var searchText = new SearchText(typeText);
107 var emptyText = new SearchText(memberText);
108 for (Map<String,Dynamic> library in libraryList) {
109 String libraryName = library[NAME];
110 if (library.containsKey(TYPES)) {
111 for (Map<String,Dynamic> type in library[TYPES]) {
112 String typeName = type[NAME];
113 StringMatch typeMatch = obtainMatch(searchText, typeName);
114 if (typeMatch != null) {
115 if (type.containsKey(MEMBERS)) {
116 for (Map<String,Dynamic> member in type[MEMBERS]) {
117 StringMatch memberMatch = obtainMatch(emptyText,
118 member[NAME]);
119 results.add(new Result(memberMatch, member[KIND],
120 getTypeMemberUrl(libraryName, typeName, member),
121 library: libraryName, prefix: typeMatch));
122 }
123 }
124 }
125 }
126 }
127 }
128 }
129
130 void matchMembersInType(List<Result> results,
131 String text, String typeText, String memberText) {
132 var searchText = new SearchText(text);
133 var typeSearchText = new SearchText(typeText);
134 var memberSearchText = new SearchText(memberText);
135 for (Map<String,Dynamic> library in libraryList) {
136 String libraryName = library[NAME];
137 if (library.containsKey(TYPES)) {
138 for (Map<String,Dynamic> type in library[TYPES]) {
139 String typeName = type[NAME];
140 StringMatch typeMatch = obtainMatch(typeSearchText, typeName);
141 if (typeMatch != null) {
142 if (type.containsKey(MEMBERS)) {
143 for (Map<String,Dynamic> member in type[MEMBERS]) {
144 // Check for constructor match.
145 StringMatch constructorMatch = obtainMatch(searchText,
146 member[NAME]);
147 if (constructorMatch != null) {
148 results.add(new Result(constructorMatch, member[KIND],
149 getTypeMemberUrl(libraryName, typeName, member),
150 library: libraryName));
151 } else {
152 // Try member match.
153 StringMatch memberMatch = obtainMatch(memberSearchText,
154 member[NAME]);
155 if (memberMatch != null) {
156 results.add(new Result(memberMatch, member[KIND],
157 getTypeMemberUrl(libraryName, typeName, member),
158 library: libraryName, prefix: typeMatch,
159 args: type[ARGS]));
160 }
161 }
162 }
163 }
164 }
165 }
166 }
167 }
168 }
169
170 void matchLibrary(List<Result> results, SearchText searchText, Map library) {
171 String libraryName = library[NAME];
172 StringMatch libraryMatch = obtainMatch(searchText, libraryName);
173 if (libraryMatch != null) {
174 results.add(new Result(libraryMatch, LIBRARY,
175 getLibraryUrl(libraryName)));
176 }
177 }
178
179 void matchLibraryMembers(List<Result> results, SearchText searchText,
180 Map library) {
181 if (library.containsKey(MEMBERS)) {
182 String libraryName = library[NAME];
183 for (Map<String,Dynamic> member in library[MEMBERS]) {
184 StringMatch memberMatch = obtainMatch(searchText, member[NAME]);
185 if (memberMatch != null) {
186 results.add(new Result(memberMatch, member[KIND],
187 getLibraryMemberUrl(libraryName, member),
188 library: libraryName));
189 }
190 }
191 }
192 }
193
194 void matchTypes(List<Result> results, SearchText searchText,
195 Map library) {
196 if (library.containsKey(TYPES)) {
197 String libraryName = library[NAME];
198 for (Map<String,Dynamic> type in library[TYPES]) {
199 String typeName = type[NAME];
200 matchType(results, searchText, libraryName, type);
201 matchTypeMembers(results, searchText, libraryName, type);
202 }
203 }
204 }
205
206 void matchType(List<Result> results, SearchText searchText,
207 String libraryName, Map type) {
208 String typeName = type[NAME];
209 StringMatch typeMatch = obtainMatch(searchText, typeName);
210 if (typeMatch != null) {
211 results.add(new Result(typeMatch, type[KIND],
212 getTypeUrl(libraryName, type),
213 library: libraryName, args: type[ARGS]));
214 }
215 }
216
217 void matchTypeMembers(List<Result> results, SearchText searchText,
218 String libraryName, Map type) {
219 if (type.containsKey(MEMBERS)) {
220 String typeName = type[NAME];
221 for (Map<String,Dynamic> member in type[MEMBERS]) {
222 StringMatch memberMatch = obtainMatch(searchText, member[NAME]);
223 if (memberMatch != null) {
224 results.add(new Result(memberMatch, member[KIND],
225 getTypeMemberUrl(libraryName, typeName, member),
226 library: libraryName, type: typeName, args: type[ARGS]));
227 }
228 }
229 }
230 }
231
232 String currentSearchText;
233 Result _currentResult;
234 List<Result> currentResults = const <Result>[];
235
236 void updateResults(String searchText, List<Result> results) {
237 currentSearchText = searchText;
238 currentResults = results;
239 if (currentResults.isEmpty()) {
240 _currentResultIndex = -1;
241 currentResult = null;
242 } else {
243 _currentResultIndex = 0;
244 currentResult = currentResults[0];
245 }
246 }
247
248 int _currentResultIndex;
249
250 void set currentResultIndex(int index) {
251 if (index < -1) {
252 return;
253 }
254 if (index >= currentResults.length) {
255 return;
256 }
257 if (index != _currentResultIndex) {
258 _currentResultIndex = index;
259 if (index >= 0) {
260 currentResult = currentResults[_currentResultIndex];
261 } else {
262 currentResult = null;
263 }
264 }
265 }
266
267 int get currentResultIndex() => _currentResultIndex;
268
269 void set currentResult(Result result) {
270 if (_currentResult != result) {
271 if (_currentResult != null) {
272 _currentResult.row.classes.remove('drop-down-link-select');
273 }
274 _currentResult = result;
275 if (_currentResult != null) {
276 _currentResult.row.classes.add('drop-down-link-select');
277 }
278 }
279 }
280
281 Result get currentResult() => _currentResult;
282
283 /**
284 * Navigate the search drop down using up/down inside the search field. Follow
285 * the result link on enter.
286 */
287 void handleUpDown(KeyboardEvent event) {
288 if (event.keyIdentifier == KeyName.UP) {
289 currentResultIndex--;
290 event.preventDefault();
291 } else if (event.keyIdentifier == KeyName.DOWN) {
292 currentResultIndex++;
293 event.preventDefault();
294 } else if (event.keyIdentifier == KeyName.ENTER) {
295 if (currentResult != null) {
296 window.location.href = currentResult.url;
297 event.preventDefault();
298 hideDropDown();
299 }
300 }
301 }
302
303 /** Show the search drop down unless there are no current results. */
304 void showDropDown() {
305 if (currentResults.isEmpty()) {
306 hideDropDown();
307 } else {
308 dropdown.style.visibility = 'visible';
309 }
310 }
311
312 /** Used to prevent hiding the drop down when it is clicked. */
313 bool hideDropDownSuspend = false;
314
315 /** Hide the search drop down unless suspended. */
316 void hideDropDown() {
317 if (hideDropDownSuspend) return;
318
319 dropdown.style.visibility = 'hidden';
320 }
321
322 /** Activate search on Ctrl+F and F3. */
323 void shortcutHandler(KeyboardEvent event) {
324 if (event.keyCode == 0x46/*F*/ && event.ctrlKey ||
325 event.keyIdentifier == KeyName.F3) {
326 searchInput.focus();
327 event.preventDefault();
328 }
329 }
330
331 /** Setup search hooks. */
332 void setupSearch(var libraries) {
333 libraryList = libraries;
334 searchInput = query('#q');
335 dropdown = query('#drop-down');
336
337 searchInput.on.keyDown.add(handleUpDown);
338 searchInput.on.keyUp.add(updateDropDown);
339 searchInput.on.change.add(updateDropDown);
340 searchInput.on.reset.add(updateDropDown);
341 searchInput.on.focus.add((event) => showDropDown());
342 searchInput.on.blur.add((event) => hideDropDown());
343 window.on.keyDown.add(shortcutHandler);
344 }
OLDNEW
« no previous file with comments | « pkg/dartdoc/dartdoc.dart ('k') | pkg/dartdoc/mirrors/dart2js_mirror.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698