OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 | 5 |
6 /** | 6 /** |
7 * @fileoverview Uses ChromeVox API to enhance the search experience. | 7 * @fileoverview Uses ChromeVox API to enhance the search experience. |
8 */ | 8 */ |
9 | 9 |
10 goog.provide('cvox.Search'); | 10 goog.provide('cvox.Search'); |
11 | 11 |
12 goog.require('cvox.ChromeVox'); | 12 goog.require('cvox.ChromeVox'); |
13 goog.require('cvox.SearchConstants'); | 13 goog.require('cvox.SearchConstants'); |
14 goog.require('cvox.SearchResults'); | 14 goog.require('cvox.SearchResults'); |
15 goog.require('cvox.SearchUtil'); | 15 goog.require('cvox.SearchUtil'); |
16 goog.require('cvox.UnknownResult'); | 16 goog.require('cvox.UnknownResult'); |
17 | 17 |
18 /** | 18 /** |
19 * @constructor | 19 * @constructor |
20 */ | 20 */ |
21 cvox.Search = function() { | 21 cvox.Search = function() {}; |
22 }; | |
23 | 22 |
24 /** | 23 /** |
25 * Selectors to match results. | 24 * Selectors to match results. |
26 * @type {Object<string>} | 25 * @type {Object<string>} |
27 */ | 26 */ |
28 cvox.Search.selectors = {}; | 27 cvox.Search.selectors = {}; |
29 | 28 |
30 /** | 29 /** |
31 * Selectors for web results. | 30 * Selectors for web results. |
32 */ | 31 */ |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 var isSpoken = resultType.speak(result); | 92 var isSpoken = resultType.speak(result); |
94 cvox.ChromeVox.syncToNode(resultType.getSyncNode(result), !isSpoken); | 93 cvox.ChromeVox.syncToNode(resultType.getSyncNode(result), !isSpoken); |
95 cvox.Search.isPane = false; | 94 cvox.Search.isPane = false; |
96 }; | 95 }; |
97 | 96 |
98 /** | 97 /** |
99 * Sync the search result index to ChromeVox. | 98 * Sync the search result index to ChromeVox. |
100 */ | 99 */ |
101 cvox.Search.syncToIndex = function() { | 100 cvox.Search.syncToIndex = function() { |
102 cvox.ChromeVox.tts.stop(); | 101 cvox.ChromeVox.tts.stop(); |
103 var prop = { endCallback: cvox.Search.speakSync_ }; | 102 var prop = {endCallback: cvox.Search.speakSync_}; |
104 if (cvox.Search.index === 0) { | 103 if (cvox.Search.index === 0) { |
105 cvox.ChromeVox.tts.speak('First result', cvox.QueueMode.QUEUE, prop); | 104 cvox.ChromeVox.tts.speak('First result', cvox.QueueMode.QUEUE, prop); |
106 } else if (cvox.Search.index === cvox.Search.results.length - 1) { | 105 } else if (cvox.Search.index === cvox.Search.results.length - 1) { |
107 cvox.ChromeVox.tts.speak('Last result', cvox.QueueMode.QUEUE, prop); | 106 cvox.ChromeVox.tts.speak('Last result', cvox.QueueMode.QUEUE, prop); |
108 } else { | 107 } else { |
109 cvox.Search.speakSync_(); | 108 cvox.Search.speakSync_(); |
110 } | 109 } |
111 }; | 110 }; |
112 | 111 |
113 /** | 112 /** |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 */ | 161 */ |
163 cvox.Search.navigatePage = function(next) { | 162 cvox.Search.navigatePage = function(next) { |
164 /* NavEnd contains previous / next page links. */ | 163 /* NavEnd contains previous / next page links. */ |
165 var NAV_END_CLASS = 'navend'; | 164 var NAV_END_CLASS = 'navend'; |
166 var navEnds = document.getElementsByClassName(NAV_END_CLASS); | 165 var navEnds = document.getElementsByClassName(NAV_END_CLASS); |
167 var navEnd = next ? navEnds[1] : navEnds[0]; | 166 var navEnd = next ? navEnds[1] : navEnds[0]; |
168 var url = cvox.SearchUtil.extractURL(navEnd); | 167 var url = cvox.SearchUtil.extractURL(navEnd); |
169 var navToUrl = function() { | 168 var navToUrl = function() { |
170 window.location = url; | 169 window.location = url; |
171 }; | 170 }; |
172 var prop = { endCallback: navToUrl }; | 171 var prop = {endCallback: navToUrl}; |
173 if (url) { | 172 if (url) { |
174 var pageNumber = cvox.Search.getPageNumber(url); | 173 var pageNumber = cvox.Search.getPageNumber(url); |
175 if (!isNaN(pageNumber)) { | 174 if (!isNaN(pageNumber)) { |
176 cvox.ChromeVox.tts.speak('Page ' + pageNumber, cvox.QueueMode.FLUSH, | 175 cvox.ChromeVox.tts.speak( |
177 prop); | 176 'Page ' + pageNumber, cvox.QueueMode.FLUSH, prop); |
178 } else { | 177 } else { |
179 cvox.ChromeVox.tts.speak('Unknown page.', cvox.QueueMode.FLUSH, prop); | 178 cvox.ChromeVox.tts.speak('Unknown page.', cvox.QueueMode.FLUSH, prop); |
180 } | 179 } |
181 } | 180 } |
182 }; | 181 }; |
183 | 182 |
184 /** | 183 /** |
185 * Navigates to the currently synced pane. | 184 * Navigates to the currently synced pane. |
186 */ | 185 */ |
187 cvox.Search.goToPane = function() { | 186 cvox.Search.goToPane = function() { |
188 var pane = cvox.Search.panes[cvox.Search.paneIndex]; | 187 var pane = cvox.Search.panes[cvox.Search.paneIndex]; |
189 if (pane.className === cvox.Search.SELECTED_PANE_CLASS) { | 188 if (pane.className === cvox.Search.SELECTED_PANE_CLASS) { |
190 cvox.ChromeVox.tts.speak('You are already on that page.', | 189 cvox.ChromeVox.tts.speak( |
191 cvox.QueueMode.QUEUE); | 190 'You are already on that page.', cvox.QueueMode.QUEUE); |
192 return; | 191 return; |
193 } | 192 } |
194 var anchor = pane.querySelector('a'); | 193 var anchor = pane.querySelector('a'); |
195 cvox.ChromeVox.tts.speak(anchor.textContent, cvox.QueueMode.QUEUE); | 194 cvox.ChromeVox.tts.speak(anchor.textContent, cvox.QueueMode.QUEUE); |
196 var url = cvox.SearchUtil.extractURL(pane); | 195 var url = cvox.SearchUtil.extractURL(pane); |
197 if (url) { | 196 if (url) { |
198 window.location = url; | 197 window.location = url; |
199 } | 198 } |
200 }; | 199 }; |
201 | 200 |
(...skipping 24 matching lines...) Expand all Loading... |
226 if (evt.shiftKey || evt.altKey || evt.ctrlKey) { | 225 if (evt.shiftKey || evt.altKey || evt.ctrlKey) { |
227 return false; | 226 return false; |
228 } | 227 } |
229 | 228 |
230 /* Do not handle if search input has focus, or if the search widget | 229 /* Do not handle if search input has focus, or if the search widget |
231 * has focus. | 230 * has focus. |
232 */ | 231 */ |
233 if (document.activeElement !== searchInput && | 232 if (document.activeElement !== searchInput && |
234 !cvox.SearchUtil.isSearchWidgetActive()) { | 233 !cvox.SearchUtil.isSearchWidgetActive()) { |
235 switch (evt.keyCode) { | 234 switch (evt.keyCode) { |
236 case cvox.SearchConstants.KeyCode.UP: | 235 case cvox.SearchConstants.KeyCode.UP: |
237 /* Add results.length because JS Modulo is silly. */ | 236 /* Add results.length because JS Modulo is silly. */ |
238 cvox.Search.index = cvox.SearchUtil.subOneWrap(cvox.Search.index, | 237 cvox.Search.index = cvox.SearchUtil.subOneWrap( |
239 cvox.Search.results.length); | 238 cvox.Search.index, cvox.Search.results.length); |
240 if (cvox.Search.index === cvox.Search.results.length - 1) { | 239 if (cvox.Search.index === cvox.Search.results.length - 1) { |
241 cvox.ChromeVox.earcons.playEarcon(cvox.Earcon.WRAP); | 240 cvox.ChromeVox.earcons.playEarcon(cvox.Earcon.WRAP); |
242 } | 241 } |
243 cvox.Search.syncToIndex(); | 242 cvox.Search.syncToIndex(); |
244 break; | 243 break; |
245 | 244 |
246 case cvox.SearchConstants.KeyCode.DOWN: | 245 case cvox.SearchConstants.KeyCode.DOWN: |
247 cvox.Search.index = cvox.SearchUtil.addOneWrap(cvox.Search.index, | 246 cvox.Search.index = cvox.SearchUtil.addOneWrap( |
248 cvox.Search.results.length); | 247 cvox.Search.index, cvox.Search.results.length); |
249 if (cvox.Search.index === 0) { | 248 if (cvox.Search.index === 0) { |
250 cvox.ChromeVox.earcons.playEarcon(cvox.Earcon.WRAP); | 249 cvox.ChromeVox.earcons.playEarcon(cvox.Earcon.WRAP); |
251 } | 250 } |
252 cvox.Search.syncToIndex(); | 251 cvox.Search.syncToIndex(); |
253 break; | 252 break; |
254 | 253 |
255 case cvox.SearchConstants.KeyCode.PAGE_UP: | 254 case cvox.SearchConstants.KeyCode.PAGE_UP: |
256 cvox.Search.navigatePage(false); | 255 cvox.Search.navigatePage(false); |
257 break; | 256 break; |
258 | 257 |
259 case cvox.SearchConstants.KeyCode.PAGE_DOWN: | 258 case cvox.SearchConstants.KeyCode.PAGE_DOWN: |
260 cvox.Search.navigatePage(true); | 259 cvox.Search.navigatePage(true); |
261 break; | 260 break; |
262 | 261 |
263 case cvox.SearchConstants.KeyCode.LEFT: | 262 case cvox.SearchConstants.KeyCode.LEFT: |
264 cvox.Search.paneIndex = cvox.SearchUtil.subOneWrap(cvox.Search.paneIndex, | 263 cvox.Search.paneIndex = cvox.SearchUtil.subOneWrap( |
265 cvox.Search.panes.length); | 264 cvox.Search.paneIndex, cvox.Search.panes.length); |
266 cvox.Search.syncPaneToIndex(); | 265 cvox.Search.syncPaneToIndex(); |
267 break; | 266 break; |
268 | 267 |
269 case cvox.SearchConstants.KeyCode.RIGHT: | 268 case cvox.SearchConstants.KeyCode.RIGHT: |
270 cvox.Search.paneIndex = cvox.SearchUtil.addOneWrap(cvox.Search.paneIndex, | 269 cvox.Search.paneIndex = cvox.SearchUtil.addOneWrap( |
271 cvox.Search.panes.length); | 270 cvox.Search.paneIndex, cvox.Search.panes.length); |
272 cvox.Search.syncPaneToIndex(); | 271 cvox.Search.syncPaneToIndex(); |
273 break; | 272 break; |
274 | 273 |
275 case cvox.SearchConstants.KeyCode.ENTER: | 274 case cvox.SearchConstants.KeyCode.ENTER: |
276 if (cvox.Search.isPane) { | 275 if (cvox.Search.isPane) { |
277 cvox.Search.goToPane(); | 276 cvox.Search.goToPane(); |
278 } else { | 277 } else { |
279 cvox.Search.goToResult(); | 278 cvox.Search.goToResult(); |
280 } | 279 } |
281 break; | 280 break; |
282 | 281 |
283 default: | 282 default: |
284 return false; | 283 return false; |
285 } | 284 } |
286 evt.preventDefault(); | 285 evt.preventDefault(); |
287 evt.stopPropagation(); | 286 evt.stopPropagation(); |
288 return true; | 287 return true; |
289 } | 288 } |
290 return false; | 289 return false; |
291 }; | 290 }; |
292 | 291 |
293 /** | 292 /** |
294 * Adds the elements that match the selector to results. | 293 * Adds the elements that match the selector to results. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 var SEARCH_AREA_SELECT = '#rg_s'; | 341 var SEARCH_AREA_SELECT = '#rg_s'; |
343 var target = document.querySelector(SEARCH_AREA_SELECT); | 342 var target = document.querySelector(SEARCH_AREA_SELECT); |
344 | 343 |
345 var observer = new MutationObserver(function(mutations) { | 344 var observer = new MutationObserver(function(mutations) { |
346 cvox.Search.results = []; | 345 cvox.Search.results = []; |
347 cvox.Search.populateResults(); | 346 cvox.Search.populateResults(); |
348 }); | 347 }); |
349 | 348 |
350 var config = | 349 var config = |
351 /** @type MutationObserverInit */ | 350 /** @type MutationObserverInit */ |
352 ({ attributes: true, childList: true, characterData: true }); | 351 ({attributes: true, childList: true, characterData: true}); |
353 observer.observe(target, config); | 352 observer.observe(target, config); |
354 }; | 353 }; |
355 | 354 |
356 /** | 355 /** |
357 * Get the current selected pane's index. | 356 * Get the current selected pane's index. |
358 * @return {number} Index of selected pane. | 357 * @return {number} Index of selected pane. |
359 */ | 358 */ |
360 cvox.Search.getSelectedPaneIndex = function() { | 359 cvox.Search.getSelectedPaneIndex = function() { |
361 var panes = cvox.Search.panes; | 360 var panes = cvox.Search.panes; |
362 for (var i = 0; i < panes.length; i++) { | 361 for (var i = 0; i < panes.length; i++) { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
413 | 412 |
414 /* Determine the type of search. */ | 413 /* Determine the type of search. */ |
415 var SELECTED_CLASS = 'hdtb-msel'; | 414 var SELECTED_CLASS = 'hdtb-msel'; |
416 var selected = document.getElementsByClassName(SELECTED_CLASS)[0]; | 415 var selected = document.getElementsByClassName(SELECTED_CLASS)[0]; |
417 if (!selected) { | 416 if (!selected) { |
418 return; | 417 return; |
419 } | 418 } |
420 | 419 |
421 var selectedHTML = selected.innerHTML; | 420 var selectedHTML = selected.innerHTML; |
422 switch (selectedHTML) { | 421 switch (selectedHTML) { |
423 case 'Web': | 422 case 'Web': |
424 case 'News': | 423 case 'News': |
425 cvox.Search.selectors = cvox.Search.webSelectors; | 424 cvox.Search.selectors = cvox.Search.webSelectors; |
426 break; | 425 break; |
427 case 'Images': | 426 case 'Images': |
428 cvox.Search.selectors = cvox.Search.imageSelectors; | 427 cvox.Search.selectors = cvox.Search.imageSelectors; |
429 cvox.Search.observeMutation(); | 428 cvox.Search.observeMutation(); |
430 break; | 429 break; |
431 default: | 430 default: |
432 return; | 431 return; |
433 } | 432 } |
434 | 433 |
435 cvox.Search.populateResults(); | 434 cvox.Search.populateResults(); |
436 cvox.Search.populatePanes(); | 435 cvox.Search.populatePanes(); |
437 cvox.Search.paneIndex = cvox.Search.getSelectedPaneIndex(); | 436 cvox.Search.paneIndex = cvox.Search.getSelectedPaneIndex(); |
438 | 437 |
439 cvox.Search.initialSync(); | 438 cvox.Search.initialSync(); |
440 | 439 |
441 }; | 440 }; |
OLD | NEW |