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

Side by Side Diff: ui/login/account_picker/user_pod_row.js

Issue 2054783002: ChromeVox access to login user pod menus (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 6 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
« no previous file with comments | « ui/login/account_picker/user_pod_row.css ('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 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 * @fileoverview User pod row implementation. 6 * @fileoverview User pod row implementation.
7 */ 7 */
8 8
9 cr.define('login', function() { 9 cr.define('login', function() {
10 /** 10 /**
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 /** 85 /**
86 * Tab order for user pods. Update these when adding new controls. 86 * Tab order for user pods. Update these when adding new controls.
87 * @enum {number} 87 * @enum {number}
88 * @const 88 * @const
89 */ 89 */
90 var UserPodTabOrder = { 90 var UserPodTabOrder = {
91 POD_INPUT: 1, // Password input field, Action box menu button, and 91 POD_INPUT: 1, // Password input field, Action box menu button, and
92 // the pod itself. 92 // the pod itself.
93 POD_CUSTOM_ICON: 2, // Pod custom icon next to password input field. 93 POD_CUSTOM_ICON: 2, // Pod custom icon next to password input field.
94 HEADER_BAR: 3, // Buttons on the header bar (Shutdown, Add User). 94 HEADER_BAR: 3, // Buttons on the header bar (Shutdown, Add User).
95 PAD_MENU_ITEM: 4 // User pad menu items (Remove this user). 95 POD_MENU_ITEM: 4 // User pad menu items (User info, Remove user).
96 }; 96 };
97 97
98 /** 98 /**
99 * Supported authentication types. Keep in sync with the enum in 99 * Supported authentication types. Keep in sync with the enum in
100 * chrome/browser/signin/screenlock_bridge.h 100 * chrome/browser/signin/screenlock_bridge.h
101 * @enum {number} 101 * @enum {number}
102 * @const 102 * @const
103 */ 103 */
104 var AUTH_TYPE = { 104 var AUTH_TYPE = {
105 OFFLINE_PASSWORD: 0, 105 OFFLINE_PASSWORD: 0,
(...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after
712 this.addEventListener('click', this.handleClickOnPod_.bind(this)); 712 this.addEventListener('click', this.handleClickOnPod_.bind(this));
713 this.addEventListener('mousedown', this.handlePodMouseDown_.bind(this)); 713 this.addEventListener('mousedown', this.handlePodMouseDown_.bind(this));
714 714
715 this.actionBoxAreaElement.addEventListener('mousedown', 715 this.actionBoxAreaElement.addEventListener('mousedown',
716 stopEventPropagation); 716 stopEventPropagation);
717 this.actionBoxAreaElement.addEventListener('click', 717 this.actionBoxAreaElement.addEventListener('click',
718 this.handleActionAreaButtonClick_.bind(this)); 718 this.handleActionAreaButtonClick_.bind(this));
719 this.actionBoxAreaElement.addEventListener('keydown', 719 this.actionBoxAreaElement.addEventListener('keydown',
720 this.handleActionAreaButtonKeyDown_.bind(this)); 720 this.handleActionAreaButtonKeyDown_.bind(this));
721 721
722 this.actionBoxMenuTitleElement.addEventListener('keydown',
723 this.handleMenuTitleElementKeyDown_.bind(this));
724 this.actionBoxMenuTitleElement.addEventListener('blur',
725 this.handleMenuTitleElementBlur_.bind(this));
726
722 this.actionBoxMenuRemoveElement.addEventListener('click', 727 this.actionBoxMenuRemoveElement.addEventListener('click',
723 this.handleRemoveCommandClick_.bind(this)); 728 this.handleRemoveCommandClick_.bind(this));
724 this.actionBoxMenuRemoveElement.addEventListener('keydown', 729 this.actionBoxMenuRemoveElement.addEventListener('keydown',
725 this.handleRemoveCommandKeyDown_.bind(this)); 730 this.handleRemoveCommandKeyDown_.bind(this));
726 this.actionBoxMenuRemoveElement.addEventListener('blur', 731 this.actionBoxMenuRemoveElement.addEventListener('blur',
727 this.handleRemoveCommandBlur_.bind(this)); 732 this.handleRemoveCommandBlur_.bind(this));
728 this.actionBoxRemoveUserWarningButtonElement.addEventListener( 733 this.actionBoxRemoveUserWarningButtonElement.addEventListener('click',
729 'click',
730 this.handleRemoveUserConfirmationClick_.bind(this)); 734 this.handleRemoveUserConfirmationClick_.bind(this));
731 this.actionBoxRemoveUserWarningButtonElement.addEventListener( 735 this.actionBoxRemoveUserWarningButtonElement.addEventListener('keydown',
732 'keydown', 736 this.handleRemoveUserConfirmationKeyDown_.bind(this));
733 this.handleRemoveUserConfirmationKeyDown_.bind(this));
734 737
735 var pinKeyboard = $('pin-keyboard'); 738 var pinKeyboard = $('pin-keyboard');
736 // The pin keyboard is not present on the md user manager. 739 // The pin keyboard is not present on the md user manager.
737 if (pinKeyboard) { 740 if (pinKeyboard) {
738 pinKeyboard.addEventListener('submit', 741 pinKeyboard.addEventListener('submit',
739 this.handlePinSubmitted_.bind(this)); 742 this.handlePinSubmitted_.bind(this));
740 } 743 }
741 744
742 var customIcon = this.customIconElement; 745 var customIcon = this.customIconElement;
743 customIcon.parentNode.replaceChild(new UserPodCustomIcon(), customIcon); 746 customIcon.parentNode.replaceChild(new UserPodCustomIcon(), customIcon);
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
925 /** 928 /**
926 * Gets user type bubble like multi-profiles policy restriction message. 929 * Gets user type bubble like multi-profiles policy restriction message.
927 * @type {!HTMLDivElement} 930 * @type {!HTMLDivElement}
928 */ 931 */
929 get userTypeBubbleElement() { 932 get userTypeBubbleElement() {
930 return this.querySelector('.user-type-bubble'); 933 return this.querySelector('.user-type-bubble');
931 }, 934 },
932 935
933 /** 936 /**
934 * Gets action box menu. 937 * Gets action box menu.
935 * @type {!HTMLInputElement} 938 * @type {!HTMLDivElement}
Greg Levin 2016/06/09 13:44:45 No idea if these comment tags should be fixed like
936 */ 939 */
937 get actionBoxMenu() { 940 get actionBoxMenu() {
938 return this.querySelector('.action-box-menu'); 941 return this.querySelector('.action-box-menu');
939 }, 942 },
940 943
941 /** 944 /**
945 * Gets action box menu title (user name and email).
946 * @type {!HTMLDivElement}
947 */
948 get actionBoxMenuTitleElement() {
949 return this.querySelector('.action-box-menu-title');
950 },
951
952 /**
942 * Gets action box menu title, user name item. 953 * Gets action box menu title, user name item.
943 * @type {!HTMLInputElement} 954 * @type {!HTMLSpanElement}
944 */ 955 */
945 get actionBoxMenuTitleNameElement() { 956 get actionBoxMenuTitleNameElement() {
946 return this.querySelector('.action-box-menu-title-name'); 957 return this.querySelector('.action-box-menu-title-name');
947 }, 958 },
948 959
949 /** 960 /**
950 * Gets action box menu title, user email item. 961 * Gets action box menu title, user email item.
951 * @type {!HTMLInputElement} 962 * @type {!HTMLSpanElement}
952 */ 963 */
953 get actionBoxMenuTitleEmailElement() { 964 get actionBoxMenuTitleEmailElement() {
954 return this.querySelector('.action-box-menu-title-email'); 965 return this.querySelector('.action-box-menu-title-email');
955 }, 966 },
956 967
957 /** 968 /**
958 * Gets action box menu, remove user command item. 969 * Gets action box menu, remove user command item.
959 * @type {!HTMLInputElement} 970 * @type {!HTMLInputElement}
960 */ 971 */
961 get actionBoxMenuCommandElement() { 972 get actionBoxMenuCommandElement() {
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
1145 if (!this.parentNode.isFocused(this)) { 1156 if (!this.parentNode.isFocused(this)) {
1146 this.parentNode.focusPod(undefined, true); 1157 this.parentNode.focusPod(undefined, true);
1147 this.actionBoxAreaElement.focus(); 1158 this.actionBoxAreaElement.focus();
1148 } 1159 }
1149 1160
1150 // Hide user-type-bubble. 1161 // Hide user-type-bubble.
1151 this.userTypeBubbleElement.classList.remove('bubble-shown'); 1162 this.userTypeBubbleElement.classList.remove('bubble-shown');
1152 1163
1153 this.actionBoxAreaElement.classList.add('active'); 1164 this.actionBoxAreaElement.classList.add('active');
1154 1165
1166 // Invisible focus causes ChromeVox to read user name and email.
1167 this.actionBoxMenuTitleElement.tabIndex = UserPodTabOrder.POD_MENU_ITEM;
1168 this.actionBoxMenuTitleElement.focus();
Greg Levin 2016/06/09 13:44:45 I tried using aria-activedescendant to get CV to r
1169
1155 // If the user pod is on either edge of the screen, then the menu 1170 // If the user pod is on either edge of the screen, then the menu
1156 // could be displayed partially ofscreen. 1171 // could be displayed partially ofscreen.
1157 this.actionBoxMenu.classList.remove('left-edge-offset'); 1172 this.actionBoxMenu.classList.remove('left-edge-offset');
1158 this.actionBoxMenu.classList.remove('right-edge-offset'); 1173 this.actionBoxMenu.classList.remove('right-edge-offset');
1159 1174
1160 var offsetLeft = 1175 var offsetLeft =
1161 cr.ui.login.DisplayManager.getOffset(this.actionBoxMenu).left; 1176 cr.ui.login.DisplayManager.getOffset(this.actionBoxMenu).left;
1162 var menuWidth = this.actionBoxMenu.offsetWidth; 1177 var menuWidth = this.actionBoxMenu.offsetWidth;
1163 if (offsetLeft < 0) 1178 if (offsetLeft < 0)
1164 this.actionBoxMenu.classList.add('left-edge-offset'); 1179 this.actionBoxMenu.classList.add('left-edge-offset');
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
1386 case 'Enter': 1401 case 'Enter':
1387 case 'U+0020': // Space 1402 case 'U+0020': // Space
1388 if (this.parentNode.focusedPod_ && !this.isActionBoxMenuActive) 1403 if (this.parentNode.focusedPod_ && !this.isActionBoxMenuActive)
1389 this.isActionBoxMenuActive = true; 1404 this.isActionBoxMenuActive = true;
1390 e.stopPropagation(); 1405 e.stopPropagation();
1391 break; 1406 break;
1392 case 'Up': 1407 case 'Up':
1393 case 'Down': 1408 case 'Down':
1394 if (this.isActionBoxMenuActive) { 1409 if (this.isActionBoxMenuActive) {
1395 this.actionBoxMenuRemoveElement.tabIndex = 1410 this.actionBoxMenuRemoveElement.tabIndex =
1396 UserPodTabOrder.PAD_MENU_ITEM; 1411 UserPodTabOrder.POD_MENU_ITEM;
1397 this.actionBoxMenuRemoveElement.focus(); 1412 this.actionBoxMenuRemoveElement.focus();
1398 } 1413 }
1399 e.stopPropagation(); 1414 e.stopPropagation();
1400 break; 1415 break;
1416 // Ignore these two, so ChromeVox hotkeys don't close the menu before
1417 // they can navigate through it.
1418 case 'Shift':
1419 case 'Win':
1420 break;
1401 case 'U+001B': // Esc 1421 case 'U+001B': // Esc
1402 this.isActionBoxMenuActive = false; 1422 this.isActionBoxMenuActive = false;
1403 e.stopPropagation(); 1423 e.stopPropagation();
1404 break; 1424 break;
1405 case 'U+0009': // Tab 1425 case 'U+0009': // Tab
1406 if (!this.parentNode.alwaysFocusSinglePod) 1426 if (!this.parentNode.alwaysFocusSinglePod)
1407 this.parentNode.focusPod(); 1427 this.parentNode.focusPod();
1408 default: 1428 default:
1409 this.isActionBoxMenuActive = false; 1429 this.isActionBoxMenuActive = false;
1410 break; 1430 break;
1411 } 1431 }
1412 }, 1432 },
1413 1433
1414 /** 1434 /**
1435 * Handles a keydown event on menu title.
1436 * @param {Event} e KeyDown event.
1437 */
1438 handleMenuTitleElementKeyDown_: function(e) {
1439 if (this.disabled)
1440 return;
1441
1442 if (e.keyIdentifier != 'U+0009' /* TAB */) {
1443 this.handleActionAreaButtonKeyDown_(e);
1444 return;
1445 }
1446
1447 if (e.shiftKey == false) {
1448 if (this.actionBoxMenuRemoveElement.hidden) {
1449 this.isActionBoxMenuActive = false;
1450 } else {
1451 this.actionBoxMenuRemoveElement.tabIndex =
1452 UserPodTabOrder.POD_MENU_ITEM;
1453 this.actionBoxMenuRemoveElement.focus();
1454 e.preventDefault();
1455 }
1456 } else {
1457 this.isActionBoxMenuActive = false;
1458 this.focusInput();
1459 e.preventDefault();
1460 }
1461 },
1462
1463 /**
1464 * Handles a blur event on menu title.
1465 * @param {Event} e Blur event.
1466 */
1467 handleMenuTitleElementBlur_: function(e) {
1468 if (this.disabled)
1469 return;
1470 this.actionBoxMenuTitleElement.tabIndex = -1;
1471 },
1472
1473 /**
1415 * Handles a click event on remove user command. 1474 * Handles a click event on remove user command.
1416 * @param {Event} e Click event. 1475 * @param {Event} e Click event.
1417 */ 1476 */
1418 handleRemoveCommandClick_: function(e) { 1477 handleRemoveCommandClick_: function(e) {
1419 if (this.user.legacySupervisedUser || this.user.isDesktopUser) { 1478 if (this.user.legacySupervisedUser || this.user.isDesktopUser) {
1420 this.showRemoveWarning_(); 1479 this.showRemoveWarning_();
1421 return; 1480 return;
1422 } 1481 }
1423 if (this.isActionBoxMenuActive) 1482 if (this.isActionBoxMenuActive)
1424 chrome.send('removeUser', [this.user.username]); 1483 chrome.send('removeUser', [this.user.username]);
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
1640 this.showRemoveWarning_(); 1699 this.showRemoveWarning_();
1641 } else { 1700 } else {
1642 this.removeUser(this.user); 1701 this.removeUser(this.user);
1643 } 1702 }
1644 e.stopPropagation(); 1703 e.stopPropagation();
1645 break; 1704 break;
1646 case 'Up': 1705 case 'Up':
1647 case 'Down': 1706 case 'Down':
1648 e.stopPropagation(); 1707 e.stopPropagation();
1649 break; 1708 break;
1709 // Ignore these two, so ChromeVox hotkeys don't close the menu before
1710 // they can navigate through it.
1711 case 'Shift':
1712 case 'Win':
1713 break;
1650 case 'U+001B': // Esc 1714 case 'U+001B': // Esc
1651 this.actionBoxAreaElement.focus(); 1715 this.actionBoxAreaElement.focus();
1652 this.isActionBoxMenuActive = false; 1716 this.isActionBoxMenuActive = false;
1653 e.stopPropagation(); 1717 e.stopPropagation();
1654 break; 1718 break;
1655 default: 1719 default:
1656 this.actionBoxAreaElement.focus(); 1720 this.actionBoxAreaElement.focus();
1657 this.isActionBoxMenuActive = false; 1721 this.isActionBoxMenuActive = false;
1658 break; 1722 break;
1659 } 1723 }
(...skipping 1700 matching lines...) Expand 10 before | Expand all | Expand 10 after
3360 if (pod && pod.multiProfilesPolicyApplied) { 3424 if (pod && pod.multiProfilesPolicyApplied) {
3361 pod.userTypeBubbleElement.classList.remove('bubble-shown'); 3425 pod.userTypeBubbleElement.classList.remove('bubble-shown');
3362 } 3426 }
3363 } 3427 }
3364 }; 3428 };
3365 3429
3366 return { 3430 return {
3367 PodRow: PodRow 3431 PodRow: PodRow
3368 }; 3432 };
3369 }); 3433 });
OLDNEW
« no previous file with comments | « ui/login/account_picker/user_pod_row.css ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698