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

Side by Side Diff: chrome/browser/resources/chromeos/chromevox/cvox2/background/panel.js

Issue 2454213002: Use modes to switch cvox panel between collapsed, menus, focused, and tutorial (Closed)
Patch Set: Created 4 years, 1 month 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
« no previous file with comments | « chrome/browser/resources/chromeos/chromevox/cvox2/background/panel.html ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 * @fileoverview The ChromeVox panel and menus. 6 * @fileoverview The ChromeVox panel and menus.
7 */ 7 */
8 8
9 goog.provide('Panel'); 9 goog.provide('Panel');
10 10
11 goog.require('ISearchUI'); 11 goog.require('ISearchUI');
12 goog.require('Msgs'); 12 goog.require('Msgs');
13 goog.require('PanelCommand'); 13 goog.require('PanelCommand');
14 goog.require('PanelMenu'); 14 goog.require('PanelMenu');
15 goog.require('PanelMenuItem'); 15 goog.require('PanelMenuItem');
16 goog.require('Tutorial'); 16 goog.require('Tutorial');
17 goog.require('cvox.ChromeVoxKbHandler'); 17 goog.require('cvox.ChromeVoxKbHandler');
18 goog.require('cvox.CommandStore'); 18 goog.require('cvox.CommandStore');
19 19
20 /** 20 /**
21 * Class to manage the panel. 21 * Class to manage the panel.
22 * @constructor 22 * @constructor
23 */ 23 */
24 Panel = function() { 24 Panel = function() {
25 }; 25 };
26 26
27 /** 27 /**
28 * @enum {string}
29 */
30 Panel.Mode = {
31 COLLAPSED: 'collapsed',
32 FOCUSED: 'focused',
33 FULLSCREEN_MENUS: 'menus',
34 FULLSCREEN_TUTORIAL: 'tutorial'
David Tseng 2016/10/28 21:24:35 Is there a non full screen tutorial (and menu)?
dmazzoni 2016/10/28 21:29:13 Nope, the idea was just to make it clear what the
David Tseng 2016/10/28 23:02:13 Not really an issue besides the enum values being
35 };
36
37 /**
28 * Initialize the panel. 38 * Initialize the panel.
29 */ 39 */
30 Panel.init = function() { 40 Panel.init = function() {
31 /** @type {Element} @private */ 41 /** @type {Element} @private */
32 this.speechContainer_ = $('speech-container'); 42 this.speechContainer_ = $('speech-container');
33 43
34 /** @type {Element} @private */ 44 /** @type {Element} @private */
35 this.speechElement_ = $('speech'); 45 this.speechElement_ = $('speech');
36 46
37 /** @type {Element} @private */ 47 /** @type {Element} @private */
38 this.brailleContainer_ = $('braille-container'); 48 this.brailleContainer_ = $('braille-container');
39 49
40 /** @type {Element} @private */ 50 /** @type {Element} @private */
41 this.searchContainer_ = $('search-container'); 51 this.searchContainer_ = $('search-container');
42 52
43 /** @type {Element} @private */ 53 /** @type {Element} @private */
44 this.searchInput_ = $('search'); 54 this.searchInput_ = $('search');
45 55
46 /** @type {Element} @private */ 56 /** @type {Element} @private */
47 this.brailleTableElement_ = $('braille-table'); 57 this.brailleTableElement_ = $('braille-table');
48 58
59 /** @type {Panel.Mode} @private */
60 this.mode_ = Panel.Mode.COLLAPSED;
61
49 /** 62 /**
50 * The array of top-level menus. 63 * The array of top-level menus.
51 * @type {!Array<PanelMenu>} 64 * @type {!Array<PanelMenu>}
52 * @private 65 * @private
53 */ 66 */
54 this.menus_ = []; 67 this.menus_ = [];
55 68
56 /** 69 /**
57 * The currently active menu, if any. 70 * The currently active menu, if any.
58 * @type {PanelMenu} 71 * @type {PanelMenu}
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 document.addEventListener('mouseup', Panel.onMouseUp, false); 131 document.addEventListener('mouseup', Panel.onMouseUp, false);
119 132
120 Panel.searchInput_.addEventListener('blur', Panel.onSearchInputBlur, false); 133 Panel.searchInput_.addEventListener('blur', Panel.onSearchInputBlur, false);
121 }; 134 };
122 135
123 /** 136 /**
124 * Update the display based on prefs. 137 * Update the display based on prefs.
125 */ 138 */
126 Panel.updateFromPrefs = function() { 139 Panel.updateFromPrefs = function() {
127 if (Panel.searching_) { 140 if (Panel.searching_) {
128 this.speechContainer_.style.display = 'none'; 141 this.speechContainer_.hidden = true;
129 this.brailleContainer_.style.display = 'none'; 142 this.brailleContainer_.hidden = true;
130 this.searchContainer_.style.display = 'block'; 143 this.searchContainer_.hidden = false;
131 return; 144 return;
132 } 145 }
133 146
134 this.speechContainer_.style.display = 'block'; 147 this.speechContainer_.hidden = false;
135 this.brailleContainer_.style.display = 'block'; 148 this.brailleContainer_.hidden = false;
136 this.searchContainer_.style.display = 'none'; 149 this.searchContainer_.hidden = true;
137 150
138 if (localStorage['brailleCaptions'] === String(true)) { 151 if (localStorage['brailleCaptions'] === String(true)) {
139 this.speechContainer_.style.visibility = 'hidden'; 152 this.speechContainer_.style.visibility = 'hidden';
140 this.brailleContainer_.style.visibility = 'visible'; 153 this.brailleContainer_.style.visibility = 'visible';
141 } else { 154 } else {
142 this.speechContainer_.style.visibility = 'visible'; 155 this.speechContainer_.style.visibility = 'visible';
143 this.brailleContainer_.style.visibility = 'hidden'; 156 this.brailleContainer_.style.visibility = 'hidden';
144 } 157 }
145 }; 158 };
146 159
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 break; 228 break;
216 } 229 }
217 }; 230 };
218 231
219 /** 232 /**
220 * Enable the ChromeVox Menus. 233 * Enable the ChromeVox Menus.
221 */ 234 */
222 Panel.onEnableMenus = function() { 235 Panel.onEnableMenus = function() {
223 Panel.menusEnabled_ = true; 236 Panel.menusEnabled_ = true;
224 $('menus_button').disabled = false; 237 $('menus_button').disabled = false;
225 $('triangle').style.display = ''; 238 $('triangle').hidden = false;
226 }; 239 };
227 240
228 /** 241 /**
229 * Disable the ChromeVox Menus. 242 * Disable the ChromeVox Menus.
230 */ 243 */
231 Panel.onDisableMenus = function() { 244 Panel.onDisableMenus = function() {
232 Panel.menusEnabled_ = false; 245 Panel.menusEnabled_ = false;
233 $('menus_button').disabled = true; 246 $('menus_button').disabled = true;
234 $('triangle').style.display = 'none'; 247 $('triangle').hidden = true;
235 }; 248 };
236 249
237 /** 250 /**
251 * Sets the mode, which determines the size of the panel and what objects
252 * are shown or hidden.
253 * @param {Panel.Mode} mode The new mode.
254 */
255 Panel.setMode = function(mode) {
256 if (this.mode_ == mode)
257 return;
258
259 this.mode_ = mode;
David Tseng 2016/10/28 23:02:13 This is also perhaps a good opportunity to ensure
dmazzoni 2016/11/01 22:31:22 I think I need to figure out how to support the me
260
261 if (this.mode_ == Panel.Mode.FULLSCREEN_MENUS ||
262 this.mode_ == Panel.Mode.FULLSCREEN_TUTORIAL) {
263 // Change the url fragment to 'fullscreen', which signals the native
264 // host code to make the window fullscreen and give it focus.
265 window.location = '#fullscreen';
266 } else if (this.mode_ == Panel.Mode.FOCUSED) {
267 // // Change the url fragment to 'focus', which signals the native
268 // host code to give the window focus.
269 window.location = '#focus';
270 } else {
271 // Remove the url fragment, which signals the native host code to
272 // collapse the panel to its normal size and cause it to lose focus.
273 window.location = '#';
274 }
275
276 $('main').hidden = (this.mode_ == Panel.Mode.FULLSCREEN_TUTORIAL);
277 $('menus_background').hidden = (this.mode_ != Panel.Mode.FULLSCREEN_MENUS);
278 $('tutorial').hidden = (this.mode_ != Panel.Mode.FULLSCREEN_TUTORIAL);
279 };
280
281 /**
238 * Open / show the ChromeVox Menus. 282 * Open / show the ChromeVox Menus.
239 * @param {Event=} opt_event An optional event that triggered this. 283 * @param {Event=} opt_event An optional event that triggered this.
240 * @param {*=} opt_activateMenuTitle Title msg id of menu to open. 284 * @param {*=} opt_activateMenuTitle Title msg id of menu to open.
241 */ 285 */
242 Panel.onOpenMenus = function(opt_event, opt_activateMenuTitle) { 286 Panel.onOpenMenus = function(opt_event, opt_activateMenuTitle) {
243 // Don't open the menu if it's not enabled, such as when ChromeVox Next 287 // Don't open the menu if it's not enabled, such as when ChromeVox Next
244 // is not active. 288 // is not active.
245 if (!Panel.menusEnabled_) 289 if (!Panel.menusEnabled_)
246 return; 290 return;
247 291
248 // Eat the event so that a mousedown isn't turned into a drag, allowing 292 // Eat the event so that a mousedown isn't turned into a drag, allowing
249 // users to click-drag-release to select a menu item. 293 // users to click-drag-release to select a menu item.
250 if (opt_event) { 294 if (opt_event) {
251 opt_event.stopPropagation(); 295 opt_event.stopPropagation();
252 opt_event.preventDefault(); 296 opt_event.preventDefault();
253 } 297 }
254 298
255 // Change the url fragment to 'fullscreen', which signals the native 299 Panel.setMode(Panel.Mode.FULLSCREEN_MENUS);
256 // host code to make the window fullscreen, revealing the menus.
257 window.location = '#fullscreen';
258 300
259 // Clear any existing menus and clear the callback. 301 // Clear any existing menus and clear the callback.
260 Panel.clearMenus(); 302 Panel.clearMenus();
261 Panel.pendingCallback_ = null; 303 Panel.pendingCallback_ = null;
262 304
263 // Build the top-level menus. 305 // Build the top-level menus.
264 var jumpMenu = Panel.addMenu('panel_menu_jump'); 306 var jumpMenu = Panel.addMenu('panel_menu_jump');
265 var speechMenu = Panel.addMenu('panel_menu_speech'); 307 var speechMenu = Panel.addMenu('panel_menu_speech');
266 var tabsMenu = Panel.addMenu('panel_menu_tabs'); 308 var tabsMenu = Panel.addMenu('panel_menu_tabs');
267 var chromevoxMenu = Panel.addMenu('panel_menu_chromevox'); 309 var chromevoxMenu = Panel.addMenu('panel_menu_chromevox');
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 } 413 }
372 Panel.activateMenu(selectedMenu); 414 Panel.activateMenu(selectedMenu);
373 }; 415 };
374 416
375 /** Open incremental search. */ 417 /** Open incremental search. */
376 Panel.onSearch = function() { 418 Panel.onSearch = function() {
377 Panel.clearMenus(); 419 Panel.clearMenus();
378 Panel.pendingCallback_ = null; 420 Panel.pendingCallback_ = null;
379 Panel.searching_ = true; 421 Panel.searching_ = true;
380 Panel.updateFromPrefs(); 422 Panel.updateFromPrefs();
381 423 Panel.setMode(Panel.Mode.FOCUSED);
382 window.location = '#focus';
383 424
384 ISearchUI.get(Panel.searchInput_); 425 ISearchUI.get(Panel.searchInput_);
385 }; 426 };
386 427
387 /** 428 /**
388 * Clear any previous menus. The menus are all regenerated each time the 429 * Clear any previous menus. The menus are all regenerated each time the
389 * menus are opened. 430 * menus are opened.
390 */ 431 */
391 Panel.clearMenus = function() { 432 Panel.clearMenus = function() {
392 while (this.menus_.length) { 433 while (this.menus_.length) {
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
528 Panel.pendingCallback_ = Panel.activeMenu_.getCallbackForElement(target); 569 Panel.pendingCallback_ = Panel.activeMenu_.getCallbackForElement(target);
529 Panel.closeMenusAndRestoreFocus(); 570 Panel.closeMenusAndRestoreFocus();
530 }; 571 };
531 572
532 /** 573 /**
533 * Called when a key is pressed. Handle arrow keys to navigate the menus, 574 * Called when a key is pressed. Handle arrow keys to navigate the menus,
534 * Esc to close, and Enter/Space to activate an item. 575 * Esc to close, and Enter/Space to activate an item.
535 * @param {Event} event The key event. 576 * @param {Event} event The key event.
536 */ 577 */
537 Panel.onKeyDown = function(event) { 578 Panel.onKeyDown = function(event) {
579 if (event.key == 'Escape' && Panel.mode_ == Panel.Mode.FULLSCREEN_TUTORIAL) {
580 Panel.setMode(Panel.Mode.COLLAPSED);
581 return;
582 }
583
538 if (!Panel.activeMenu_) 584 if (!Panel.activeMenu_)
539 return; 585 return;
540 586
541 if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) 587 if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey)
542 return; 588 return;
543 589
544 switch (event.key) { 590 switch (event.key) {
545 case 'ArrowLeft': 591 case 'ArrowLeft':
546 Panel.advanceActiveMenuBy(-1); 592 Panel.advanceActiveMenuBy(-1);
547 break; 593 break;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
583 event.stopPropagation(); 629 event.stopPropagation();
584 }; 630 };
585 631
586 /** 632 /**
587 * Called when focus leaves the search input. 633 * Called when focus leaves the search input.
588 */ 634 */
589 Panel.onSearchInputBlur = function() { 635 Panel.onSearchInputBlur = function() {
590 if (Panel.searching_) { 636 if (Panel.searching_) {
591 if (document.activeElement != Panel.searchInput_ || !document.hasFocus()) { 637 if (document.activeElement != Panel.searchInput_ || !document.hasFocus()) {
592 Panel.searching_ = false; 638 Panel.searching_ = false;
593 if (window.location == '#focus') 639 Panel.setMode(Panel.Mode.COLLAPSED);
David Tseng 2016/10/28 21:24:35 Not equivalent to the removed code.
dmazzoni 2016/10/28 21:31:29 What does setMode do that it shouldn't?
David Tseng 2016/10/28 23:02:13 Previously, we only collapsed if we were focused.
594 window.location = '#';
595 Panel.updateFromPrefs(); 640 Panel.updateFromPrefs();
596 Panel.searchInput_.value = ''; 641 Panel.searchInput_.value = '';
597 } 642 }
598 } 643 }
599 }; 644 };
600 645
601 /** 646 /**
602 * Open the ChromeVox Options. 647 * Open the ChromeVox Options.
603 */ 648 */
604 Panel.onOptions = function() { 649 Panel.onOptions = function() {
605 var bkgnd = 650 var bkgnd =
606 chrome.extension.getBackgroundPage()['ChromeVoxState']['instance']; 651 chrome.extension.getBackgroundPage()['ChromeVoxState']['instance'];
607 bkgnd['showOptionsPage'](); 652 bkgnd['showOptionsPage']();
608 window.location = '#'; 653 Panel.setMode(Panel.Mode.COLLAPSED);
609 }; 654 };
610 655
611 /** 656 /**
612 * Exit ChromeVox. 657 * Exit ChromeVox.
613 */ 658 */
614 Panel.onClose = function() { 659 Panel.onClose = function() {
660 // Change the url fragment to 'close', which signals the native code
661 // to exit ChromeVox.
615 window.location = '#close'; 662 window.location = '#close';
616 }; 663 };
617 664
618 /** 665 /**
619 * Get the callback for whatever item is currently selected. 666 * Get the callback for whatever item is currently selected.
620 * @return {Function} The callback for the current item. 667 * @return {Function} The callback for the current item.
621 */ 668 */
622 Panel.getCallbackForCurrentItem = function() { 669 Panel.getCallbackForCurrentItem = function() {
623 if (this.activeMenu_) 670 if (this.activeMenu_)
624 return this.activeMenu_.getCallbackForCurrentItem(); 671 return this.activeMenu_.getCallbackForCurrentItem();
625 return null; 672 return null;
626 }; 673 };
627 674
628 /** 675 /**
629 * Close the menus and restore focus to the page. If a menu item's callback 676 * Close the menus and restore focus to the page. If a menu item's callback
630 * was queued, execute it once focus is restored. 677 * was queued, execute it once focus is restored.
631 */ 678 */
632 Panel.closeMenusAndRestoreFocus = function() { 679 Panel.closeMenusAndRestoreFocus = function() {
633 // Watch for the next focus event. 680 // Watch for the next focus event.
634 var onFocus = function(desktop, evt) { 681 var onFocus = function(desktop, evt) {
635 desktop.removeEventListener(chrome.automation.EventType.focus, onFocus); 682 desktop.removeEventListener(chrome.automation.EventType.focus, onFocus);
636 Panel.pendingCallback_ && Panel.pendingCallback_(); 683 if (Panel.pendingCallback_) {
684 // Clear it before calling it, in case the callback itself triggers
685 // another pending callback.
686 var pendingCallback = Panel.pendingCallback_;
687 Panel.pendingCallback_ = null;
688 pendingCallback();
689 }
637 }.bind(this); 690 }.bind(this);
638 691
639 chrome.automation.getDesktop(function(desktop) { 692 chrome.automation.getDesktop(function(desktop) {
640 onFocus = /** @type {function(chrome.automation.AutomationEvent)} */( 693 onFocus = /** @type {function(chrome.automation.AutomationEvent)} */(
641 onFocus.bind(this, desktop)); 694 onFocus.bind(this, desktop));
642 desktop.addEventListener(chrome.automation.EventType.focus, 695 desktop.addEventListener(chrome.automation.EventType.focus,
643 onFocus, 696 onFocus,
644 true); 697 true);
645 698
646 // Make sure all menus are cleared to avoid bogous output when we re-open. 699 // Make sure all menus are cleared to avoid bogous output when we re-open.
647 Panel.clearMenus(); 700 Panel.clearMenus();
648 701
649 // Make sure we're not in full-screen mode. 702 // Make sure we're not in full-screen mode.
650 window.location = '#'; 703 Panel.setMode(Panel.Mode.COLLAPSED);
651 704
652 this.activeMenu_ = null; 705 this.activeMenu_ = null;
653 }); 706 });
654 }; 707 };
655 708
656 /** 709 /**
657 * Open the tutorial. 710 * Open the tutorial.
658 */ 711 */
659 Panel.onTutorial = function() { 712 Panel.onTutorial = function() {
660 // Change the url fragment to 'fullscreen', which signals the native 713 // Change the url fragment to 'fullscreen', which signals the native
661 // host code to make the window fullscreen, revealing the menus. 714 // host code to make the window fullscreen, revealing the menus.
662 window.location = '#fullscreen'; 715 Panel.setMode(Panel.Mode.FULLSCREEN_TUTORIAL);
663
664 $('main').style.display = 'none';
665 $('menus_background').style.display = 'none';
666 $('tutorial').style.display = 'block';
667 716
668 Panel.tutorial_.firstPage(); 717 Panel.tutorial_.firstPage();
669 }; 718 };
670 719
671 /** 720 /**
672 * Move to the next page in the tutorial. 721 * Move to the next page in the tutorial.
673 */ 722 */
674 Panel.onTutorialNext = function() { 723 Panel.onTutorialNext = function() {
675 Panel.tutorial_.nextPage(); 724 Panel.tutorial_.nextPage();
676 }; 725 };
677 726
678 /** 727 /**
679 * Move to the previous page in the tutorial. 728 * Move to the previous page in the tutorial.
680 */ 729 */
681 Panel.onTutorialPrevious = function() { 730 Panel.onTutorialPrevious = function() {
682 Panel.tutorial_.previousPage(); 731 Panel.tutorial_.previousPage();
683 }; 732 };
684 733
685 /** 734 /**
686 * Close the tutorial. 735 * Close the tutorial.
687 */ 736 */
688 Panel.onCloseTutorial = function() { 737 Panel.onCloseTutorial = function() {
689 $('main').style.display = 'block'; 738 Panel.setMode(Panel.Mode.COLLAPSED);
690 $('tutorial').style.display = 'none';
691 Panel.closeMenusAndRestoreFocus();
692 }; 739 };
693 740
694 window.addEventListener('load', function() { 741 window.addEventListener('load', function() {
695 Panel.init(); 742 Panel.init();
696 743
697 switch (location.search.slice(1)) { 744 switch (location.search.slice(1)) {
698 case 'tutorial': 745 case 'tutorial':
699 Panel.onTutorial(); 746 Panel.onTutorial();
700 } 747 }
701 }, false); 748 }, false);
702 749
703 window.addEventListener('hashchange', function() { 750 window.addEventListener('hashchange', function() {
704 if (location.hash == '#fullscreen' || location.hash == '#focus') { 751 if (location.hash == '#fullscreen' || location.hash == '#focus') {
705 this.originalStickyState_ = cvox.ChromeVox.isStickyPrefOn; 752 this.originalStickyState_ = cvox.ChromeVox.isStickyPrefOn;
706 cvox.ChromeVox.isStickyPrefOn = false; 753 cvox.ChromeVox.isStickyPrefOn = false;
707 } else { 754 } else {
708 cvox.ChromeVox.isStickyPrefOn = this.originalStickyState_; 755 cvox.ChromeVox.isStickyPrefOn = this.originalStickyState_;
709 } 756 }
710 }, false); 757 }, false);
OLDNEW
« no previous file with comments | « chrome/browser/resources/chromeos/chromevox/cvox2/background/panel.html ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698