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

Side by Side Diff: chrome/browser/resources/access_chromevox/chromevox/injected/user_commands.js

Issue 6254007: Adding ChromeVox as a component extensions (enabled only for ChromeOS, for no... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 11 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
Property Changes:
Added: svn:executable
+ *
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 goog.provide('cvox.ChromeVoxUserCommands');
6
7 goog.require('cvox.AbstractEarcons');
8 goog.require('cvox.ChromeVox');
9 goog.require('cvox.ChromeVoxSearch');
10 goog.require('cvox.ExtensionBridge');
11 goog.require('cvox.SelectionUtil');
12
13 /**
14 * @fileoverview High level commands that the user can invoke using hotkeys.
15 */
16 cvox.ChromeVoxUserCommands = function() { };
17
18 /**
19 * @type {number}
20 */
21 cvox.ChromeVoxUserCommands.silenceLevel = 0;
22
23 /**
24 * @type {Object}
25 */
26 cvox.ChromeVoxUserCommands.commands = {};
27
28 /**
29 * Stops speech.
30 *
31 * @return {boolean} Always return false since we want to prevent the default
32 * action.
33 */
34 cvox.ChromeVoxUserCommands.commands['stopSpeech'] = function() {
35 cvox.ChromeVox.tts.stop();
36 return false;
37 };
38
39 /**
40 * Moves forward and speaks the result.
41 *
42 * @return {boolean} Always return false since we want to prevent the default
43 * action.
44 */
45 cvox.ChromeVoxUserCommands.commands['forward'] = function() {
46 cvox.ChromeVoxUserCommands.silenceEventWatchers_();
47 cvox.ChromeVox.navigationManager.next();
48 cvox.ChromeVoxUserCommands.finishNavCommand('');
49 return false;
50 };
51
52 /**
53 * Moves backward and speaks the result.
54 *
55 * @return {boolean} Always return false since we want to prevent the default
56 * action.
57 */
58 cvox.ChromeVoxUserCommands.commands['backward'] = function() {
59 cvox.ChromeVoxUserCommands.silenceEventWatchers_();
60 cvox.ChromeVox.navigationManager.previous();
61 cvox.ChromeVoxUserCommands.finishNavCommand('');
62 return false;
63 };
64
65 /**
66 * Moves up to a different navigation strategy and speaks a summary of the
67 * current position.
68 *
69 * @return {boolean} Always return false since we want to prevent the default
70 * action.
71 */
72 cvox.ChromeVoxUserCommands.commands['previousGranularity'] = function() {
73 cvox.ChromeVox.navigationManager.up();
74 var strategy = cvox.ChromeVox.navigationManager.getStrategy();
75 if (strategy == 'SELECTION') {
76 strategy = cvox.ChromeVox.navigationManager.getGranularity();
77 }
78 cvox.ChromeVoxUserCommands.finishNavCommand(strategy + ' ');
79 return false;
80 };
81
82 /**
83 * Moves down to a different navigation strategy and speaks a summary of the
84 * current position.
85 *
86 * @return {boolean} Always return false since we want to prevent the default
87 * action.
88 */
89 cvox.ChromeVoxUserCommands.commands['nextGranularity'] = function() {
90 cvox.ChromeVox.navigationManager.down();
91 var strategy = cvox.ChromeVox.navigationManager.getStrategy();
92 if (strategy == 'SELECTION') {
93 strategy = cvox.ChromeVox.navigationManager.getGranularity();
94 }
95 cvox.ChromeVoxUserCommands.finishNavCommand(strategy + ' ');
96 return false;
97 };
98
99 /**
100 * This is a NOP command. It is needed in case we would like
101 * to swallow certain keys via mapping them to a NOP operation.
102 *
103 * @return {boolean} Always return false since we want to prevent the default
104 * action.
105 */
106 cvox.ChromeVoxUserCommands.commands['nop'] = function() {
107 /* do nothing */
108 return false;
109 };
110
111 /**
112 * Perform all of the actions that should happen at the end of any
113 * navigation operation: update the lens, play earcons, and speak the
114 * description of the object that was navigated to.
115 *
116 * @param {string} messagePrefixStr The string to be prepended to what
117 * is spoken to the user.
118 */
119 cvox.ChromeVoxUserCommands.finishNavCommand = function(messagePrefixStr) {
120 cvox.ChromeVox.lens.updateText();
121 var message = cvox.ChromeVox.navigationManager.getCurrentDescription();
122 // Remove all whitespace from the beginning and end, and collapse all
123 // inner strings of whitespace to a single space.
124 message = message.replace(/\s+/g, ' ').replace(/^\s+|\s+$/g, '');
125 setTimeout(function() {
126 cvox.ChromeVox.navigationManager.setFocus();
127 }, 0);
128 cvox.SelectionUtil.scrollToSelection(window.getSelection());
129 cvox.ChromeVox.tts.speak(messagePrefixStr + message, 0, null);
130 cvox.ChromeVoxUserCommands.playEarcons();
131 };
132
133 /**
134 * Play earcons for the object that was most recently navigated to.
135 */
136 cvox.ChromeVoxUserCommands.playEarcons = function() {
137 var ancestors = cvox.ChromeVox.navigationManager.getChangedAncestors();
138 var earcons = [];
139 for (var i = 0; i < ancestors.length; i++) {
140 var node = ancestors[i];
141 switch (node.tagName) {
142 case 'BUTTON':
143 earcons.push(cvox.AbstractEarcons.BUTTON);
144 break;
145 case 'A':
146 earcons.push(cvox.AbstractEarcons.LINK);
147 break;
148 case 'LI':
149 earcons.push(cvox.AbstractEarcons.LIST_ITEM);
150 break;
151 case 'SELECT':
152 earcons.push(cvox.AbstractEarcons.LISTBOX);
153 break;
154 case 'TEXTAREA':
155 earcons.push(cvox.AbstractEarcons.EDITABLE_TEXT);
156 break;
157 case 'INPUT':
158 switch (node.type) {
159 case 'submit':
160 case 'reset':
161 earcons.push(cvox.AbstractEarcons.BUTTON);
162 break;
163 case 'checkbox':
164 case 'radio':
165 if (node.value) {
166 earcons.push(cvox.AbstractEarcons.CHECK_ON);
167 } else {
168 earcons.push(cvox.AbstractEarcons.CHECK_OFF);
169 }
170 break;
171 default:
172 if (cvox.DomUtil.isInputTypeText(node)) {
173 // 'text', 'password', etc.
174 earcons.push(cvox.AbstractEarcons.EDITABLE_TEXT);
175 }
176 break;
177 }
178 }
179 }
180
181 for (var j = 0; j < earcons.length; j++) {
182 cvox.ChromeVox.earcons.playEarcon(earcons[j]);
183 }
184 };
185
186 /**
187 * Find the next occurrence of an item defined by the given predicate.
188 * @param {function(Array.<Node>)} predicate A function taking a node as a
189 * parameter and returning true if it's what to search for.
190 * @param {string} errorStr A string to speak if the item couldn't be found.
191 * @private
192 */
193 cvox.ChromeVoxUserCommands.findNextAndSpeak_ = function(predicate,
194 errorStr) {
195 cvox.ChromeVoxUserCommands.silenceEventWatchers_();
196 if (!cvox.ChromeVox.navigationManager.findNext(predicate)) {
197 cvox.ChromeVox.tts.speak(errorStr, 0, null);
198 return;
199 }
200 cvox.ChromeVoxUserCommands.finishNavCommand('');
201 };
202
203 /**
204 * Find the next occurrence of an item defined by the given predicate.
205 * @param {function(Array.<Node>)} predicate A function taking a node as a
206 * parameter and returning true if it's what to search for.
207 * @param {string} errorStr A string to speak if the item couldn't be found.
208 * @private
209 */
210 cvox.ChromeVoxUserCommands.findPreviousAndSpeak_ = function(predicate,
211 errorStr) {
212 cvox.ChromeVoxUserCommands.silenceEventWatchers_();
213 if (!cvox.ChromeVox.navigationManager.findPrevious(predicate)) {
214 cvox.ChromeVox.tts.speak(errorStr, 0, null);
215 return;
216 }
217 cvox.ChromeVoxUserCommands.finishNavCommand('');
218 };
219
220 /**
221 * @param {Array} arr Array of nodes.
222 * @param {string} tagName The name of the tag.
223 * @return {boolean} True if obj is in the array.
224 * @private
225 */
226 cvox.ChromeVoxUserCommands.containsTagName_ = function(arr, tagName) {
227 var i = arr.length;
228 while (i--) {
229 if (arr[i].tagName == tagName) {
230 return true;
231 }
232 }
233 return false;
234 };
235
236 /**
237 * Temporarily silence event watchers, then automatically un-silence them
238 * after a short delay. This prevents us from speaking that something has
239 * focused when the focusing was a result of a ChromeVox action.
240 * @private
241 */
242 cvox.ChromeVoxUserCommands.silenceEventWatchers_ = function() {
243 cvox.ChromeVoxUserCommands.silenceLevel += 1;
244 setTimeout(function() {
245 cvox.ChromeVoxUserCommands.silenceLevel -= 1;
246 }, 100);
247 };
248
249 /**
250 * Handles TAB navigation by putting focus at the user's position.
251 * This function will create dummy nodes if there is nothing that
252 * is focusable at the current position.
253 *
254 * @return {boolean} Always return true since we rely on the default action.
255 */
256 cvox.ChromeVoxUserCommands.commands['handleTab'] = function() {
257 // Clean up after any previous runs
258 var previousDummySpan = document.getElementById('ChromeVoxTabDummySpan');
259 if (previousDummySpan) {
260 previousDummySpan.parentNode.removeChild(previousDummySpan);
261 }
262
263 // Hide the search widget if it is shown.
264 cvox.ChromeVoxSearch.hide();
265
266 var tagName = 'A';
267 // If the user is already focused on a link or control,
268 // nothing more needs to be done.
269 if ((document.activeElement.tagName == tagName) ||
270 cvox.DomUtil.isControl(document.activeElement)) {
271 return true;
272 }
273
274 // Try to find something reasonable to focus on in the current selection.
275 var sel = window.getSelection();
276 if (sel == null || sel.anchorNode == null || sel.focusNode == null) {
277 return true;
278 }
279 if (sel.anchorNode.tagName &&
280 ((sel.anchorNode.tagName == tagName) ||
281 cvox.DomUtil.isControl(sel.anchorNode))) {
282 sel.anchorNode.focus();
283 return true;
284 }
285 if (sel.focusNode.tagName &&
286 ((sel.focusNode.tagName == tagName) ||
287 cvox.DomUtil.isControl(sel.focusNode))) {
288 sel.focusNode.focus();
289 return true;
290 }
291 if (sel.anchorNode.parentNode.tagName &&
292 ((sel.anchorNode.parentNode.tagName == tagName) ||
293 cvox.DomUtil.isControl(sel.anchorNode.parentNode))) {
294 sel.anchorNode.parentNode.focus();
295 return true;
296 }
297 if (sel.focusNode.parentNode.tagName &&
298 ((sel.focusNode.parentNode.tagName == tagName) ||
299 cvox.DomUtil.isControl(sel.focusNode))) {
300 sel.focusNode.parentNode.focus();
301 return true;
302 }
303
304 // Create a dummy span immediately before the current position and focus
305 // on it so that the default tab action will start off as close to the
306 // user's current position as possible.
307 var span = document.createElement('span');
308 span.id = 'ChromeVoxTabDummySpan';
309 sel.anchorNode.parentNode.insertBefore(span, sel.anchorNode);
310 span.tabIndex = -1;
311 span.focus();
312 return true;
313 };
314
315 /**
316 * Toggles between searching and browsing.
317 *
318 * @return {boolean} Always return false since we want to prevent the default
319 * action.
320 */
321 cvox.ChromeVoxUserCommands.commands['toggleSearchWidget'] = function() {
322 if (cvox.ChromeVoxSearch.isActive()) {
323 cvox.ChromeVoxSearch.hide();
324 cvox.ChromeVox.tts.speak('Browse', 0, null);
325 } else {
326 cvox.ChromeVoxSearch.show();
327 cvox.ChromeVox.tts.speak('Search', 0, null);
328 }
329 return false;
330 };
331
332 /**
333 * Cycles through the Text-To-Speech Engines.
334 *
335 * @return {boolean} Always return false since we want to prevent the default
336 * action.
337 */
338 cvox.ChromeVoxUserCommands.commands['nextTtsEngine'] = function() {
339 cvox.ChromeVox.tts.nextEngine();
340 return false;
341 };
342
343 /**
344 * Decreases the tts rate.
345 *
346 * @return {boolean} Always return false since we want to prevent the default
347 * action.
348 */
349 cvox.ChromeVoxUserCommands.commands['decreaseTtsRate'] = function() {
350 cvox.ChromeVox.tts.decreaseProperty('Rate');
351 return false;
352 };
353
354 /**
355 * Increases the tts rate.
356 *
357 * @return {boolean} Always return false since we want to prevent the default
358 * action.
359 */
360 cvox.ChromeVoxUserCommands.commands['increaseTtsRate'] = function() {
361 cvox.ChromeVox.tts.increaseProperty('Rate');
362 return false;
363 };
364
365 /**
366 * Decreases the tts pitch.
367 *
368 * @return {boolean} Always return false since we want to prevent the default
369 * action.
370 */
371 cvox.ChromeVoxUserCommands.commands['decreaseTtsPitch'] = function() {
372 cvox.ChromeVox.tts.decreaseProperty('Pitch');
373 return false;
374 };
375
376 /**
377 * Increases the tts pitch.
378 *
379 * @return {boolean} Always return false since we want to prevent the default
380 * action.
381 */
382 cvox.ChromeVoxUserCommands.commands['increaseTtsPitch'] = function() {
383 cvox.ChromeVox.tts.increaseProperty('Pitch');
384 return false;
385 };
386
387 /**
388 * Decreases the tts volume.
389 *
390 * @return {boolean} Always return false since we want to prevent the default
391 * action.
392 */
393 cvox.ChromeVoxUserCommands.commands['decreaseTtsVolume'] = function() {
394 cvox.ChromeVox.tts.decreaseProperty('Volume');
395 return false;
396 };
397
398 /**
399 * Increases the tts volume.
400 *
401 * @return {boolean} Always return false since we want to prevent the default
402 * action.
403 */
404 cvox.ChromeVoxUserCommands.commands['increaseTtsVolume'] = function() {
405 cvox.ChromeVox.tts.increaseProperty('Volume');
406 return false;
407 };
408
409 /**
410 * Shows the bookmark manager
411 *
412 * @return {boolean} Always return false since we want to prevent the default
413 * action.
414 */
415 cvox.ChromeVoxUserCommands.commands['showBookmarkManager'] = function() {
416 cvox.ExtensionBridge.send({
417 'target': 'BookmarkManager',
418 'action': 'open'});
419 return false;
420 };
421
422 /**
423 * Debug function - useful for quickly trying out some behavior
424 *
425 * @return {boolean} Always return false since we want to prevent the default
426 * action.
427 */
428 cvox.ChromeVoxUserCommands.commands['debug'] = function() {
429 alert('ok');
430 return false;
431 };
432
433 //
434 // Jump commands - jump to the next / previous node of a certain category
435 //
436
437 /**
438 * Next checkbox.
439 *
440 * @return {boolean} Always return false since we want to prevent the default
441 * action.
442 */
443 cvox.ChromeVoxUserCommands.commands['nextCheckbox'] = function() {
444 cvox.ChromeVoxUserCommands.findNextAndSpeak_(
445 cvox.ChromeVoxUserCommands.checkboxPredicate_,
446 'No next checkbox.');
447 return false;
448 };
449
450 /**
451 * Previous checkbox.
452 *
453 * @return {boolean} Always return false since we want to prevent the default
454 * action.
455 */
456 cvox.ChromeVoxUserCommands.commands['previousCheckbox'] = function() {
457 cvox.ChromeVoxUserCommands.findPreviousAndSpeak_(
458 cvox.ChromeVoxUserCommands.checkboxPredicate_,
459 'No previous checkbox.');
460 return false;
461 };
462
463 /**
464 * Next radio button.
465 *
466 * @return {boolean} Always return false since we want to prevent the default
467 * action.
468 */
469 cvox.ChromeVoxUserCommands.commands['nextRadio'] = function() {
470 cvox.ChromeVoxUserCommands.findNextAndSpeak_(
471 cvox.ChromeVoxUserCommands.radioPredicate_,
472 'No next radio button.');
473 return false;
474 };
475
476 /**
477 * Previous radio button.
478 *
479 * @return {boolean} Always return false since we want to prevent the default
480 * action.
481 */
482 cvox.ChromeVoxUserCommands.commands['previousRadio'] = function() {
483 cvox.ChromeVoxUserCommands.findPreviousAndSpeak_(
484 cvox.ChromeVoxUserCommands.radioPredicate_,
485 'No previous radio button.');
486 return false;
487 };
488
489 /**
490 * Next slider.
491 *
492 * @return {boolean} Always return false since we want to prevent the default
493 * action.
494 */
495 cvox.ChromeVoxUserCommands.commands['nextSlider'] = function() {
496 cvox.ChromeVoxUserCommands.findNextAndSpeak_(
497 cvox.ChromeVoxUserCommands.sliderPredicate_,
498 'No next slider.');
499 return false;
500 };
501
502 /**
503 * Previous slider.
504 *
505 * @return {boolean} Always return false since we want to prevent the default
506 * action.
507 */
508 cvox.ChromeVoxUserCommands.commands['previousSlider'] = function() {
509 cvox.ChromeVoxUserCommands.findPreviousAndSpeak_(
510 cvox.ChromeVoxUserCommands.sliderPredicate_,
511 'No previous slider.');
512 return false;
513 };
514
515 /**
516 * Next graphic.
517 *
518 * @return {boolean} Always return false since we want to prevent the default
519 * action.
520 */
521 cvox.ChromeVoxUserCommands.commands['nextGraphic'] = function() {
522 cvox.ChromeVoxUserCommands.findNextAndSpeak_(
523 cvox.ChromeVoxUserCommands.graphicPredicate_,
524 'No next graphic.');
525 return false;
526 };
527
528 /**
529 * Previous graphic.
530 *
531 * @return {boolean} Always return false since we want to prevent the default
532 * action.
533 */
534 cvox.ChromeVoxUserCommands.commands['previousGraphic'] = function() {
535 cvox.ChromeVoxUserCommands.findPreviousAndSpeak_(
536 cvox.ChromeVoxUserCommands.graphicPredicate_,
537 'No previous graphic.');
538 return false;
539 };
540
541 /**
542 * Next button.
543 *
544 * @return {boolean} Always return false since we want to prevent the default
545 * action.
546 */
547 cvox.ChromeVoxUserCommands.commands['nextButton'] = function() {
548 cvox.ChromeVoxUserCommands.findNextAndSpeak_(
549 cvox.ChromeVoxUserCommands.buttonPredicate_,
550 'No next button.');
551 return false;
552 };
553
554 /**
555 * Previous button.
556 *
557 * @return {boolean} Always return false since we want to prevent the default
558 * action.
559 */
560 cvox.ChromeVoxUserCommands.commands['previousButton'] = function() {
561 cvox.ChromeVoxUserCommands.findPreviousAndSpeak_(
562 cvox.ChromeVoxUserCommands.buttonPredicate_,
563 'No previous button.');
564 return false;
565 };
566
567 /**
568 * Next combo box.
569 *
570 * @return {boolean} Always return false since we want to prevent the default
571 * action.
572 */
573 cvox.ChromeVoxUserCommands.commands['nextComboBox'] = function() {
574 cvox.ChromeVoxUserCommands.findNextAndSpeak_(
575 cvox.ChromeVoxUserCommands.comboBoxPredicate_,
576 'No next combo box.');
577 return false;
578 };
579
580 /**
581 * Previous combo box.
582 *
583 * @return {boolean} Always return false since we want to prevent the default
584 * action.
585 */
586 cvox.ChromeVoxUserCommands.commands['previousComboBox'] = function() {
587 cvox.ChromeVoxUserCommands.findPreviousAndSpeak_(
588 cvox.ChromeVoxUserCommands.comboBoxPredicate_,
589 'No previous combo box.');
590 return false;
591 };
592
593 /**
594 * Next editable text field.
595 *
596 * @return {boolean} Always return false since we want to prevent the default
597 * action.
598 */
599 cvox.ChromeVoxUserCommands.commands['nextEditText'] = function() {
600 cvox.ChromeVoxUserCommands.findNextAndSpeak_(
601 cvox.ChromeVoxUserCommands.editTextPredicate_,
602 'No next editable text field.');
603 return false;
604 };
605
606 /**
607 * Previous editable text field.
608 *
609 * @return {boolean} Always return false since we want to prevent the default
610 * action.
611 */
612 cvox.ChromeVoxUserCommands.commands['previousEditText'] = function() {
613 cvox.ChromeVoxUserCommands.findPreviousAndSpeak_(
614 cvox.ChromeVoxUserCommands.editTextPredicate_,
615 'No previous editable text field.');
616 return false;
617 };
618
619 /**
620 * Next heading.
621 *
622 * @return {boolean} Always return false since we want to prevent the default
623 * action.
624 */
625 cvox.ChromeVoxUserCommands.commands['nextHeading'] = function() {
626 cvox.ChromeVoxUserCommands.findNextAndSpeak_(
627 cvox.ChromeVoxUserCommands.headingPredicate_,
628 'No next heading.');
629 return false;
630 };
631
632 /**
633 * Previous heading.
634 *
635 * @return {boolean} Always return false since we want to prevent the default
636 * action.
637 */
638 cvox.ChromeVoxUserCommands.commands['previousHeading'] = function() {
639 cvox.ChromeVoxUserCommands.findPreviousAndSpeak_(
640 cvox.ChromeVoxUserCommands.headingPredicate_,
641 'No previous heading.');
642 return false;
643 };
644
645 /**
646 * Next heading level 1.
647 *
648 * @return {boolean} Always return false since we want to prevent the default
649 * action.
650 */
651 cvox.ChromeVoxUserCommands.commands['nextHeading1'] = function() {
652 cvox.ChromeVoxUserCommands.findNextAndSpeak_(
653 cvox.ChromeVoxUserCommands.heading1Predicate_,
654 'No next level 1 heading.');
655 return false;
656 };
657
658 /**
659 * Previous heading level 1.
660 *
661 * @return {boolean} Always return false since we want to prevent the default
662 * action.
663 */
664 cvox.ChromeVoxUserCommands.commands['previousHeading1'] = function() {
665 cvox.ChromeVoxUserCommands.findPreviousAndSpeak_(
666 cvox.ChromeVoxUserCommands.heading1Predicate_,
667 'No previous level 1 heading.');
668 return false;
669 };
670
671 /**
672 * Next heading level 2.
673 *
674 * @return {boolean} Always return false since we want to prevent the default
675 * action.
676 */
677 cvox.ChromeVoxUserCommands.commands['nextHeading2'] = function() {
678 cvox.ChromeVoxUserCommands.findNextAndSpeak_(
679 cvox.ChromeVoxUserCommands.heading2Predicate_,
680 'No next level 2 heading.');
681 return false;
682 };
683
684 /**
685 * Previous heading level 2.
686 *
687 * @return {boolean} Always return false since we want to prevent the default
688 * action.
689 */
690 cvox.ChromeVoxUserCommands.commands['previousHeading2'] = function() {
691 cvox.ChromeVoxUserCommands.findPreviousAndSpeak_(
692 cvox.ChromeVoxUserCommands.heading2Predicate_,
693 'No previous level 2 heading.');
694 return false;
695 };
696
697 /**
698 * Next heading level 3.
699 *
700 * @return {boolean} Always return false since we want to prevent the default
701 * action.
702 */
703 cvox.ChromeVoxUserCommands.commands['nextHeading3'] = function() {
704 cvox.ChromeVoxUserCommands.findNextAndSpeak_(
705 cvox.ChromeVoxUserCommands.heading3Predicate_,
706 'No next level 3 heading.');
707 return false;
708 };
709
710 /**
711 * Previous heading level 3.
712 *
713 * @return {boolean} Always return false since we want to prevent the default
714 * action.
715 */
716 cvox.ChromeVoxUserCommands.commands['previousHeading3'] = function() {
717 cvox.ChromeVoxUserCommands.findPreviousAndSpeak_(
718 cvox.ChromeVoxUserCommands.heading3Predicate_,
719 'No previous level 3 heading.');
720 return false;
721 };
722
723 /**
724 * Next heading level 4.
725 *
726 * @return {boolean} Always return false since we want to prevent the default
727 * action.
728 */
729 cvox.ChromeVoxUserCommands.commands['nextHeading4'] = function() {
730 cvox.ChromeVoxUserCommands.findNextAndSpeak_(
731 cvox.ChromeVoxUserCommands.heading4Predicate_,
732 'No next level 4 heading.');
733 return false;
734 };
735
736 /**
737 * Previous heading level 4.
738 *
739 * @return {boolean} Always return false since we want to prevent the default
740 * action.
741 */
742 cvox.ChromeVoxUserCommands.commands['previousHeading4'] = function() {
743 cvox.ChromeVoxUserCommands.findPreviousAndSpeak_(
744 cvox.ChromeVoxUserCommands.heading4Predicate_,
745 'No previous level 4 heading.');
746 return false;
747 };
748
749 /**
750 * Next heading level 5.
751 *
752 * @return {boolean} Always return false since we want to prevent the default
753 * action.
754 */
755 cvox.ChromeVoxUserCommands.commands['nextHeading5'] = function() {
756 cvox.ChromeVoxUserCommands.findNextAndSpeak_(
757 cvox.ChromeVoxUserCommands.heading5Predicate_,
758 'No next level 5 heading.');
759 return false;
760 };
761
762 /**
763 * Previous heading level 5.
764 *
765 * @return {boolean} Always return false since we want to prevent the default
766 * action.
767 */
768 cvox.ChromeVoxUserCommands.commands['previousHeading5'] = function() {
769 cvox.ChromeVoxUserCommands.findPreviousAndSpeak_(
770 cvox.ChromeVoxUserCommands.heading5Predicate_,
771 'No previous level 5 heading.');
772 return false;
773 };
774
775 /**
776 * Next heading level 6.
777 *
778 * @return {boolean} Always return false since we want to prevent the default
779 * action.
780 */
781 cvox.ChromeVoxUserCommands.commands['nextHeading6'] = function() {
782 cvox.ChromeVoxUserCommands.findNextAndSpeak_(
783 cvox.ChromeVoxUserCommands.heading6Predicate_,
784 'No next level 6 heading.');
785 return false;
786 };
787
788 /**
789 * Previous heading level 6.
790 *
791 * @return {boolean} Always return false since we want to prevent the default
792 * action.
793 */
794 cvox.ChromeVoxUserCommands.commands['previousHeading6'] = function() {
795 cvox.ChromeVoxUserCommands.findPreviousAndSpeak_(
796 cvox.ChromeVoxUserCommands.heading6Predicate_,
797 'No previous level 6 heading.');
798 return false;
799 };
800
801 /**
802 * Next not-link.
803 *
804 * @return {boolean} Always return false since we want to prevent the default
805 * action.
806 */
807 cvox.ChromeVoxUserCommands.commands['nextNotLink'] = function() {
808 cvox.ChromeVoxUserCommands.findNextAndSpeak_(
809 cvox.ChromeVoxUserCommands.notLinkPredicate_,
810 'No next item that isn\'t a link.');
811 return false;
812 };
813
814 /**
815 * Previous not-link.
816 *
817 * @return {boolean} Always return false since we want to prevent the default
818 * action.
819 */
820 cvox.ChromeVoxUserCommands.commands['previousNotLink'] = function() {
821 cvox.ChromeVoxUserCommands.findPreviousAndSpeak_(
822 cvox.ChromeVoxUserCommands.notLinkPredicate_,
823 'No previous item that isn\'t a link.');
824 return false;
825 };
826
827 /**
828 * Next link.
829 *
830 * @return {boolean} Always return false since we want to prevent the default
831 * action.
832 */
833 cvox.ChromeVoxUserCommands.commands['nextLink'] = function() {
834 cvox.ChromeVoxUserCommands.findNextAndSpeak_(
835 cvox.ChromeVoxUserCommands.linkPredicate_,
836 'No next link.');
837 return false;
838 };
839
840 /**
841 * Previous link.
842 *
843 * @return {boolean} Always return false since we want to prevent the default
844 * action.
845 */
846 cvox.ChromeVoxUserCommands.commands['previousLink'] = function() {
847 cvox.ChromeVoxUserCommands.findPreviousAndSpeak_(
848 cvox.ChromeVoxUserCommands.linkPredicate_,
849 'No previous link.');
850 return false;
851 };
852
853 /**
854 * Next table.
855 *
856 * @return {boolean} Always return false since we want to prevent the default
857 * action.
858 */
859 cvox.ChromeVoxUserCommands.commands['nextTable'] = function() {
860 cvox.ChromeVoxUserCommands.findNextAndSpeak_(
861 cvox.ChromeVoxUserCommands.tablePredicate_,
862 'No next table.');
863 return false;
864 };
865
866 /**
867 * Previous table.
868 *
869 * @return {boolean} Always return false since we want to prevent the default
870 * action.
871 */
872 cvox.ChromeVoxUserCommands.commands['previousTable'] = function() {
873 cvox.ChromeVoxUserCommands.findPreviousAndSpeak_(
874 cvox.ChromeVoxUserCommands.tablePredicate_,
875 'No previous table.');
876 return false;
877 };
878
879 /**
880 * Next list.
881 *
882 * @return {boolean} Always return false since we want to prevent the default
883 * action.
884 */
885 cvox.ChromeVoxUserCommands.commands['nextList'] = function() {
886 cvox.ChromeVoxUserCommands.findNextAndSpeak_(
887 cvox.ChromeVoxUserCommands.listPredicate_,
888 'No next list.');
889 return false;
890 };
891
892 /**
893 * Previous list.
894 *
895 * @return {boolean} Always return false since we want to prevent the default
896 * action.
897 */
898 cvox.ChromeVoxUserCommands.commands['previousList'] = function() {
899 cvox.ChromeVoxUserCommands.findPreviousAndSpeak_(
900 cvox.ChromeVoxUserCommands.listPredicate_,
901 'No previous list.');
902 return false;
903 };
904
905 /**
906 * Next list item.
907 *
908 * @return {boolean} Always return false since we want to prevent the default
909 * action.
910 */
911 cvox.ChromeVoxUserCommands.commands['nextListItem'] = function() {
912 cvox.ChromeVoxUserCommands.findNextAndSpeak_(
913 cvox.ChromeVoxUserCommands.listItemPredicate_,
914 'No next list item.');
915 return false;
916 };
917
918 /**
919 * Previous list item.
920 *
921 * @return {boolean} Always return false since we want to prevent the default
922 * action.
923 */
924 cvox.ChromeVoxUserCommands.commands['previousListItem'] = function() {
925 cvox.ChromeVoxUserCommands.findPreviousAndSpeak_(
926 cvox.ChromeVoxUserCommands.listItemPredicate_,
927 'No previous list item.');
928 return false;
929 };
930
931 /**
932 * Next blockquote.
933 *
934 * @return {boolean} Always return false since we want to prevent the default
935 * action.
936 */
937 cvox.ChromeVoxUserCommands.commands['nextBlockquote'] = function() {
938 cvox.ChromeVoxUserCommands.findNextAndSpeak_(
939 cvox.ChromeVoxUserCommands.blockquotePredicate_,
940 'No next blockquote.');
941 return false;
942 };
943
944 /**
945 * Previous blockquote.
946 *
947 * @return {boolean} Always return false since we want to prevent the default
948 * action.
949 */
950 cvox.ChromeVoxUserCommands.commands['previousBlockquote'] = function() {
951 cvox.ChromeVoxUserCommands.findPreviousAndSpeak_(
952 cvox.ChromeVoxUserCommands.blockquotePredicate_,
953 'No previous blockquote.');
954 return false;
955 };
956
957 /**
958 * Next form field.
959 *
960 * @return {boolean} Always return false since we want to prevent the default
961 * action.
962 */
963 cvox.ChromeVoxUserCommands.commands['nextFormField'] = function() {
964 cvox.ChromeVoxUserCommands.findNextAndSpeak_(
965 cvox.ChromeVoxUserCommands.formFieldPredicate_,
966 'No next form field.');
967 return false;
968 };
969
970 /**
971 * Previous form field.
972 *
973 * @return {boolean} Always return false since we want to prevent the default
974 * action.
975 */
976 cvox.ChromeVoxUserCommands.commands['previousFormField'] = function() {
977 cvox.ChromeVoxUserCommands.findPreviousAndSpeak_(
978 cvox.ChromeVoxUserCommands.formFieldPredicate_,
979 'No previous form field.');
980 return false;
981 };
982
983 /**
984 * Attempts to do something reasonable given the current item that the user is
985 * on.
986 * For example, if the user is on a chunk of text that contains a link, navigate
987 * to that link. If there are multiple links in that chunk, bring up a menu to
988 * let the user choose which link they meant to click on.
989 *
990 * @return {boolean} Always return false since we want to prevent the default
991 * action.
992 */
993 cvox.ChromeVoxUserCommands.commands['actOnCurrentItem'] = function() {
994 var actionTaken = cvox.ChromeVox.navigationManager.actOnCurrentItem();
995 if (!actionTaken) {
996 cvox.ChromeVox.tts.speak('No actions available.', 0, null);
997 }
998 return false;
999 };
1000
1001
1002 //
1003 // Predicates - functions that take an array of ancestor nodes that have
1004 // changed and returns true if a certain category has been found. Used for
1005 // implementing functions like nextCheckbox / prevCheckbox, and so on.
1006 //
1007
1008 /**
1009 * Checkbox.
1010 * @param {Array.<Node>} nodes An array of nodes to check.
1011 * @return {boolean} True if the array contains a checkbox.
1012 * @private
1013 */
1014 cvox.ChromeVoxUserCommands.checkboxPredicate_ = function(nodes) {
1015 for (var i = 0; i < nodes.length; i++) {
1016 if (nodes[i].role == 'checkbox') {
1017 return true;
1018 }
1019 if (nodes[i].tagName == 'INPUT' && nodes[i].type == 'checkbox') {
1020 return true;
1021 }
1022 }
1023 return false;
1024 };
1025
1026 /**
1027 * Radio button.
1028 * @param {Array.<Node>} nodes An array of nodes to check.
1029 * @return {boolean} True if the array contains a radio button.
1030 * @private
1031 */
1032 cvox.ChromeVoxUserCommands.radioPredicate_ = function(nodes) {
1033 for (var i = 0; i < nodes.length; i++) {
1034 if (nodes[i].role == 'radio') {
1035 return true;
1036 }
1037 if (nodes[i].tagName == 'INPUT' && nodes[i].type == 'radio') {
1038 return true;
1039 }
1040 }
1041 return false;
1042 };
1043
1044 /**
1045 * Slider.
1046 * @param {Array.<Node>} nodes An array of nodes to check.
1047 * @return {boolean} True if the array contains a slider.
1048 * @private
1049 */
1050 cvox.ChromeVoxUserCommands.sliderPredicate_ = function(nodes) {
1051 for (var i = 0; i < nodes.length; i++) {
1052 if (nodes[i].role == 'slider') {
1053 return true;
1054 }
1055 if (nodes[i].tagName == 'INPUT' && nodes[i].type == 'range') {
1056 return true;
1057 }
1058 }
1059 return false;
1060 };
1061
1062 /**
1063 * Graphic.
1064 * @param {Array.<Node>} nodes An array of nodes to check.
1065 * @return {boolean} True if the array contains a graphic.
1066 * @private
1067 */
1068 cvox.ChromeVoxUserCommands.graphicPredicate_ = function(nodes) {
1069 for (var i = 0; i < nodes.length; i++) {
1070 if (nodes[i].tagName == 'IMG') {
1071 return true;
1072 }
1073 if (nodes[i].tagName == 'INPUT' && nodes[i].type == 'img') {
1074 return true;
1075 }
1076 }
1077 return false;
1078 };
1079
1080 /**
1081 * Button.
1082 * @param {Array.<Node>} nodes An array of nodes to check.
1083 * @return {boolean} True if the array contains a button.
1084 * @private
1085 */
1086 cvox.ChromeVoxUserCommands.buttonPredicate_ = function(nodes) {
1087 for (var i = 0; i < nodes.length; i++) {
1088 if (nodes[i].role == 'button') {
1089 return true;
1090 }
1091 if (nodes[i].tagName == 'BUTTON') {
1092 return true;
1093 }
1094 if (nodes[i].tagName == 'INPUT' && nodes[i].type == 'submit') {
1095 return true;
1096 }
1097 if (nodes[i].tagName == 'INPUT' && nodes[i].type == 'reset') {
1098 return true;
1099 }
1100 }
1101 };
1102
1103 /**
1104 * Combo box.
1105 * @param {Array.<Node>} nodes An array of nodes to check.
1106 * @return {boolean} True if the array contains a combo box.
1107 * @private
1108 */
1109 cvox.ChromeVoxUserCommands.comboBoxPredicate_ = function(nodes) {
1110 for (var i = 0; i < nodes.length; i++) {
1111 if (nodes[i].role == 'combobox') {
1112 return true;
1113 }
1114 if (nodes[i].tagName == 'SELECT') {
1115 return true;
1116 }
1117 }
1118 return false;
1119 };
1120
1121 /**
1122 * Editable text field.
1123 * @param {Array.<Node>} nodes An array of nodes to check.
1124 * @return {boolean} True if the array contains an editable text field.
1125 * @private
1126 */
1127 cvox.ChromeVoxUserCommands.editTextPredicate_ = function(nodes) {
1128 for (var i = 0; i < nodes.length; i++) {
1129 if (nodes[i].role == 'textbox') {
1130 return true;
1131 }
1132 if (nodes[i].tagName == 'TEXTAREA') {
1133 return true;
1134 }
1135 if (nodes[i].tagName == 'INPUT') {
1136 return cvox.DomUtil.isInputTypeText(nodes[i]);
1137 }
1138 }
1139 return false;
1140 };
1141
1142 /**
1143 * Heading.
1144 * @param {Array.<Node>} nodes An array of nodes to check.
1145 * @return {boolean} True if the array contains a heading.
1146 * @private
1147 */
1148 cvox.ChromeVoxUserCommands.headingPredicate_ = function(nodes) {
1149 for (var i = 0; i < nodes.length; i++) {
1150 if (nodes[i].role == 'heading') {
1151 return true;
1152 }
1153 switch (nodes[i].tagName) {
1154 case 'H1':
1155 case 'H2':
1156 case 'H3':
1157 case 'H4':
1158 case 'H5':
1159 case 'H6':
1160 return true;
1161 }
1162 }
1163 return false;
1164 };
1165
1166 /**
1167 * Heading level 1.
1168 * @param {Array.<Node>} nodes An array of nodes to check.
1169 * @return {boolean} True if the array contains a heading level 1.
1170 * TODO: handle ARIA headings with ARIA heading levels?
1171 * @private
1172 */
1173 cvox.ChromeVoxUserCommands.heading1Predicate_ = function(nodes) {
1174 return cvox.ChromeVoxUserCommands.containsTagName_(nodes, 'H1');
1175 };
1176
1177 /**
1178 * Heading level 2.
1179 * @param {Array.<Node>} nodes An array of nodes to check.
1180 * @return {boolean} True if the array contains a heading level 2.
1181 * @private
1182 */
1183 cvox.ChromeVoxUserCommands.heading2Predicate_ = function(nodes) {
1184 return cvox.ChromeVoxUserCommands.containsTagName_(nodes, 'H2');
1185 };
1186
1187 /**
1188 * Heading level 3.
1189 * @param {Array.<Node>} nodes An array of nodes to check.
1190 * @return {boolean} True if the array contains a heading level 3.
1191 * @private
1192 */
1193 cvox.ChromeVoxUserCommands.heading3Predicate_ = function(nodes) {
1194 return cvox.ChromeVoxUserCommands.containsTagName_(nodes, 'H3');
1195 };
1196
1197 /**
1198 * Heading level 4.
1199 * @param {Array.<Node>} nodes An array of nodes to check.
1200 * @return {boolean} True if the array contains a heading level 4.
1201 * @private
1202 */
1203 cvox.ChromeVoxUserCommands.heading4Predicate_ = function(nodes) {
1204 return cvox.ChromeVoxUserCommands.containsTagName_(nodes, 'H4');
1205 };
1206
1207 /**
1208 * Heading level 5.
1209 * @param {Array.<Node>} nodes An array of nodes to check.
1210 * @return {boolean} True if the array contains a heading level 5.
1211 * @private
1212 */
1213 cvox.ChromeVoxUserCommands.heading5Predicate_ = function(nodes) {
1214 return cvox.ChromeVoxUserCommands.containsTagName_(nodes, 'H5');
1215 };
1216
1217 /**
1218 * Heading level 6.
1219 * @param {Array.<Node>} nodes An array of nodes to check.
1220 * @return {boolean} True if the array contains a heading level 6.
1221 * @private
1222 */
1223 cvox.ChromeVoxUserCommands.heading6Predicate_ = function(nodes) {
1224 return cvox.ChromeVoxUserCommands.containsTagName_(nodes, 'H6');
1225 };
1226
1227 /**
1228 * Not-link.
1229 * @param {Array.<Node>} nodes An array of nodes to check.
1230 * @return {boolean} True if none of the items in the array is a link.
1231 * @private
1232 */
1233 cvox.ChromeVoxUserCommands.notLinkPredicate_ = function(nodes) {
1234 return !cvox.ChromeVoxUserCommands.linkPredicate_(nodes);
1235 };
1236
1237 /**
1238 * Link.
1239 * @param {Array.<Node>} nodes An array of nodes to check.
1240 * @return {boolean} True if the array contains a link.
1241 * @private
1242 */
1243 cvox.ChromeVoxUserCommands.linkPredicate_ = function(nodes) {
1244 for (var i = 0; i < nodes.length; i++) {
1245 if (nodes[i].role == 'link') {
1246 return true;
1247 }
1248 if (nodes[i].tagName == 'A') {
1249 return true;
1250 }
1251 }
1252 return false;
1253 };
1254
1255 /**
1256 * Table.
1257 * @param {Array.<Node>} nodes An array of nodes to check.
1258 * @return {boolean} True if the array contains a table.
1259 * @private
1260 */
1261 cvox.ChromeVoxUserCommands.tablePredicate_ = function(nodes) {
1262 return cvox.ChromeVoxUserCommands.containsTagName_(nodes, 'TABLE');
1263 };
1264
1265 /**
1266 * List.
1267 * @param {Array.<Node>} nodes An array of nodes to check.
1268 * @return {boolean} True if the array contains a list.
1269 * @private
1270 */
1271 cvox.ChromeVoxUserCommands.listPredicate_ = function(nodes) {
1272 for (var i = 0; i < nodes.length; i++) {
1273 if (nodes[i].tagName == 'UL') {
1274 return true;
1275 }
1276 if (nodes[i].tagName == 'OL') {
1277 return true;
1278 }
1279 }
1280 return false;
1281 };
1282
1283 /**
1284 * List item.
1285 * @param {Array.<Node>} nodes An array of nodes to check.
1286 * @return {boolean} True if the array contains a list item.
1287 * @private
1288 */
1289 cvox.ChromeVoxUserCommands.listItemPredicate_ = function(nodes) {
1290 return cvox.ChromeVoxUserCommands.containsTagName_(nodes, 'TABLE');
1291 };
1292
1293 /**
1294 * Blockquote.
1295 * @param {Array.<Node>} nodes An array of nodes to check.
1296 * @return {boolean} True if the array contains a blockquote.
1297 * @private
1298 */
1299 cvox.ChromeVoxUserCommands.blockquotePredicate_ = function(nodes) {
1300 return cvox.ChromeVoxUserCommands.containsTagName_(nodes, 'BLOCKQUOTE');
1301 };
1302
1303 /**
1304 * Form field.
1305 * @param {Array.<Node>} nodes An array of nodes to check.
1306 * @return {boolean} True if the array contains any type of form field.
1307 * @private
1308 */
1309 cvox.ChromeVoxUserCommands.formFieldPredicate_ = function(nodes) {
1310 for (var i = 0; i < nodes.length; i++) {
1311 if (nodes[i].role == 'button') {
1312 return true;
1313 }
1314 if (nodes[i].role == 'checkbox') {
1315 return true;
1316 }
1317 if (nodes[i].role == 'combobox') {
1318 return true;
1319 }
1320 if (nodes[i].role == 'radio') {
1321 return true;
1322 }
1323 if (nodes[i].role == 'slider') {
1324 return true;
1325 }
1326 if (nodes[i].role == 'spinbutton') {
1327 return true;
1328 }
1329 if (nodes[i].role == 'textbox') {
1330 return true;
1331 }
1332 if (nodes[i].tagName == 'INPUT') {
1333 return true;
1334 }
1335 if (nodes[i].tagName == 'SELECT') {
1336 return true;
1337 }
1338 if (nodes[i].tagName == 'BUTTON') {
1339 return true;
1340 }
1341 }
1342 return false;
1343 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698