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

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

Issue 2898283002: Multiple user pods implementation for new login screen (Closed)
Patch Set: Address comments Created 3 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
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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 * @type {number} 42 * @type {number}
43 * @const 43 * @const
44 */ 44 */
45 var MAX_NUMBER_OF_ROWS_UNDER_SIGNIN_BANNER = 2; 45 var MAX_NUMBER_OF_ROWS_UNDER_SIGNIN_BANNER = 2;
46 46
47 /** 47 /**
48 * Variables used for pod placement processing. Width and height should be 48 * Variables used for pod placement processing. Width and height should be
49 * synced with computed CSS sizes of pods. 49 * synced with computed CSS sizes of pods.
50 */ 50 */
51 var CROS_POD_WIDTH = 306; 51 var CROS_POD_WIDTH = 306;
52 var CROS_SMALL_POD_WIDTH = 304;
53 var CROS_EXTRA_SMALL_POD_WIDTH = 282;
52 var DESKTOP_POD_WIDTH = 180; 54 var DESKTOP_POD_WIDTH = 180;
53 var MD_DESKTOP_POD_WIDTH = 160; 55 var MD_DESKTOP_POD_WIDTH = 160;
54 var PUBLIC_EXPANDED_BASIC_WIDTH = 500; 56 var PUBLIC_EXPANDED_BASIC_WIDTH = 500;
55 var PUBLIC_EXPANDED_ADVANCED_WIDTH = 610; 57 var PUBLIC_EXPANDED_ADVANCED_WIDTH = 610;
56 var CROS_POD_HEIGHT = 346; 58 var CROS_POD_HEIGHT = 346;
59 var CROS_SMALL_POD_HEIGHT = 74;
60 var CROS_EXTRA_SMALL_POD_HEIGHT = 60;
57 var DESKTOP_POD_HEIGHT = 226; 61 var DESKTOP_POD_HEIGHT = 226;
58 var MD_DESKTOP_POD_HEIGHT = 200; 62 var MD_DESKTOP_POD_HEIGHT = 200;
59 var POD_ROW_PADDING = 10; 63 var POD_ROW_PADDING = 10;
60 var DESKTOP_ROW_PADDING = 32; 64 var DESKTOP_ROW_PADDING = 32;
61 var CUSTOM_ICON_CONTAINER_SIZE = 40; 65 var CUSTOM_ICON_CONTAINER_SIZE = 40;
62 var CROS_PIN_POD_HEIGHT = 417; 66 var CROS_PIN_POD_HEIGHT = 417;
67 var SCROLL_MASK_HEIGHT = 112;
68
69 /**
70 * The maximum number of users that each pod placement method can handle.
71 */
72 var POD_ROW_LIMIT = 2;
73 var LANDSCAPE_MODE_LIMIT = 6;
74 var PORTRAIT_MODE_LIMIT = 9;
63 75
64 /** 76 /**
65 * Minimal padding between user pod and virtual keyboard. 77 * Minimal padding between user pod and virtual keyboard.
66 * @type {number} 78 * @type {number}
67 * @const 79 * @const
68 */ 80 */
69 var USER_POD_KEYBOARD_MIN_PADDING = 20; 81 var USER_POD_KEYBOARD_MIN_PADDING = 20;
70 82
71 /** 83 /**
72 * Maximum time for which the pod row remains hidden until all user images 84 * Maximum time for which the pod row remains hidden until all user images
73 * have been loaded. 85 * have been loaded.
74 * @type {number} 86 * @type {number}
75 * @const 87 * @const
76 */ 88 */
77 var POD_ROW_IMAGES_LOAD_TIMEOUT_MS = 3000; 89 var POD_ROW_IMAGES_LOAD_TIMEOUT_MS = 3000;
78 90
79 /** 91 /**
80 * Public session help topic identifier. 92 * Public session help topic identifier.
81 * @type {number} 93 * @type {number}
82 * @const 94 * @const
83 */ 95 */
84 var HELP_TOPIC_PUBLIC_SESSION = 3041033; 96 var HELP_TOPIC_PUBLIC_SESSION = 3041033;
85 97
86 /** 98 /**
87 * Tab order for user pods. Update these when adding new controls. 99 * Tab order for user pods. Update these when adding new controls.
88 * @enum {number} 100 * @enum {number}
89 * @const 101 * @const
90 */ 102 */
91 var UserPodTabOrder = { 103 var UserPodTabOrder = {
92 POD_INPUT: 1, // Password input field, Action box menu button and 104 POD_INPUT: 1, // Password input field and the pod itself.
93 // the pod itself. 105 PIN_KEYBOARD: 2, // Pin keyboard below the password input field.
94 PIN_KEYBOARD: 2, // Pin keyboard below the password input field. 106 POD_CUSTOM_ICON: 3, // Pod custom icon next to password input field.
95 POD_CUSTOM_ICON: 3, // Pod custom icon next to password input field. 107 HEADER_BAR: 4, // Buttons on the header bar (Shutdown, Add User).
96 HEADER_BAR: 4, // Buttons on the header bar (Shutdown, Add User). 108 ACTION_BOX_BUTTON: 5, // Action box menu button.
97 POD_MENU_ITEM: 5 // User pad menu items (User info, Remove user). 109 POD_MENU_ITEM: 6 // User pod menu items (User info, Remove user).
98 }; 110 };
99 111
100 /** 112 /**
101 * Supported authentication types. Keep in sync with the enum in 113 * Supported authentication types. Keep in sync with the enum in
102 * chrome/browser/signin/screenlock_bridge.h 114 * chrome/browser/signin/screenlock_bridge.h
103 * @enum {number} 115 * @enum {number}
104 * @const 116 * @const
105 */ 117 */
106 var AUTH_TYPE = { 118 var AUTH_TYPE = {
107 OFFLINE_PASSWORD: 0, 119 OFFLINE_PASSWORD: 0,
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 {state: FINGERPRINT_STATES.DEFAULT, class: 'default'}, 160 {state: FINGERPRINT_STATES.DEFAULT, class: 'default'},
149 {state: FINGERPRINT_STATES.SIGNIN, class: 'signin'}, 161 {state: FINGERPRINT_STATES.SIGNIN, class: 'signin'},
150 {state: FINGERPRINT_STATES.FAILED, class: 'failed'} 162 {state: FINGERPRINT_STATES.FAILED, class: 'failed'}
151 ]; 163 ];
152 164
153 // Focus and tab order are organized as follows: 165 // Focus and tab order are organized as follows:
154 // 166 //
155 // (1) all user pods have tab index 1 so they are traversed first; 167 // (1) all user pods have tab index 1 so they are traversed first;
156 // (2) when a user pod is activated, its tab index is set to -1 and its 168 // (2) when a user pod is activated, its tab index is set to -1 and its
157 // main input field gets focus and tab index 1; 169 // main input field gets focus and tab index 1;
158 // (3) if user pod custom icon is interactive, it has tab index 2 so it 170 // (3) if pin keyboard is present, it has tab index 2 so it follows the input;
159 // follows the input. 171 // (4) if user pod custom icon is interactive, it has tab index 3;
160 // (4) buttons on the header bar have tab index 3 so they follow the custom 172 // (5) buttons on the header bar have tab index 4;
161 // icon, or user pod if custom icon is not interactive; 173 // (6) Action box buttons have tab index 5 and follow the buttons on the
162 // (5) Action box buttons have tab index 4 and follow header bar buttons; 174 // header bar;
163 // (6) lastly, focus jumps to the Status Area and back to user pods. 175 // (7) User pod menu items (if present) have tab index 6;
176 // (8) lastly, focus jumps to the Status Area and back to user pods.
164 // 177 //
165 // 'Focus' event is handled by a capture handler for the whole document 178 // 'Focus' event is handled by a capture handler for the whole document
166 // and in some cases 'mousedown' event handlers are used instead of 'click' 179 // and in some cases 'mousedown' event handlers are used instead of 'click'
167 // handlers where it's necessary to prevent 'focus' event from being fired. 180 // handlers where it's necessary to prevent 'focus' event from being fired.
168 181
169 /** 182 /**
170 * Helper function to remove a class from given element. 183 * Helper function to remove a class from given element.
171 * @param {!HTMLElement} el Element whose class list to change. 184 * @param {!HTMLElement} el Element whose class list to change.
172 * @param {string} cl Class to remove. 185 * @param {string} cl Class to remove.
173 */ 186 */
174 function removeClass(el, cl) { 187 function removeClass(el, cl) {
175 el.classList.remove(cl); 188 el.classList.remove(cl);
176 } 189 }
177 190
178 /** 191 /**
179 * Creates a user pod. 192 * Creates a user pod.
180 * @constructor 193 * @constructor
181 * @extends {HTMLDivElement} 194 * @extends {HTMLDivElement}
182 */ 195 */
183 var UserPod = cr.ui.define(function() { 196 var UserPod = cr.ui.define(function() {
184 var node = $('user-pod-template').cloneNode(true); 197 var node = $('user-pod-template').cloneNode(true);
185 node.removeAttribute('id'); 198 node.removeAttribute('id');
186 return node; 199 return node;
187 }); 200 });
188 201
189 /** 202 /**
203 * The display style of user pods.
204 * @enum {number}
205 * @const
206 */
207 UserPod.Style = {
208 LARGE: 0,
209 SMALL: 1,
210 EXTRA_SMALL: 2
211 };
212
213 /**
190 * Stops event propagation from the any user pod child element. 214 * Stops event propagation from the any user pod child element.
191 * @param {Event} e Event to handle. 215 * @param {Event} e Event to handle.
192 */ 216 */
193 function stopEventPropagation(e) { 217 function stopEventPropagation(e) {
194 // Prevent default so that we don't trigger a 'focus' event. 218 // Prevent default so that we don't trigger a 'focus' event.
195 e.preventDefault(); 219 e.preventDefault();
196 e.stopPropagation(); 220 e.stopPropagation();
197 } 221 }
198 222
199 /** 223 /**
(...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after
746 /** 770 /**
747 * True iff the pod can display the pin keyboard. The pin keyboard may not 771 * True iff the pod can display the pin keyboard. The pin keyboard may not
748 * always be displayed even if this is true, ie, if the virtual keyboard is 772 * always be displayed even if this is true, ie, if the virtual keyboard is
749 * also being displayed. 773 * also being displayed.
750 */ 774 */
751 pinEnabled: false, 775 pinEnabled: false,
752 776
753 /** @override */ 777 /** @override */
754 decorate: function() { 778 decorate: function() {
755 this.tabIndex = UserPodTabOrder.POD_INPUT; 779 this.tabIndex = UserPodTabOrder.POD_INPUT;
756 this.actionBoxAreaElement.tabIndex = UserPodTabOrder.POD_INPUT; 780 this.actionBoxAreaElement.tabIndex = UserPodTabOrder.ACTION_BOX_BUTTON;
757 781
758 this.addEventListener('keydown', this.handlePodKeyDown_.bind(this)); 782 this.addEventListener('keydown', this.handlePodKeyDown_.bind(this));
759 this.addEventListener('click', this.handleClickOnPod_.bind(this)); 783 this.addEventListener('click', this.handleClickOnPod_.bind(this));
760 this.addEventListener('mousedown', this.handlePodMouseDown_.bind(this)); 784 this.addEventListener('mousedown', this.handlePodMouseDown_.bind(this));
761 785
762 if (this.pinKeyboard) { 786 if (this.pinKeyboard) {
763 this.pinKeyboard.passwordElement = this.passwordElement; 787 this.pinKeyboard.passwordElement = this.passwordElement;
764 this.pinKeyboard.addEventListener('pin-change', 788 this.pinKeyboard.addEventListener('pin-change',
765 this.handleInputChanged_.bind(this)); 789 this.handleInputChanged_.bind(this));
766 this.pinKeyboard.tabIndex = UserPodTabOrder.PIN_KEYBOARD; 790 this.pinKeyboard.tabIndex = UserPodTabOrder.PIN_KEYBOARD;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
816 this.handleInputMouseUp_.bind(this)); 840 this.handleInputMouseUp_.bind(this));
817 841
818 if (this.submitButton) { 842 if (this.submitButton) {
819 this.submitButton.addEventListener('click', 843 this.submitButton.addEventListener('click',
820 this.handleSubmitButtonClick_.bind(this)); 844 this.handleSubmitButtonClick_.bind(this));
821 } 845 }
822 846
823 this.imageElement.addEventListener('load', 847 this.imageElement.addEventListener('load',
824 this.parentNode.handlePodImageLoad.bind(this.parentNode, this)); 848 this.parentNode.handlePodImageLoad.bind(this.parentNode, this));
825 849
850 this.smallPodImageElement.addEventListener(
851 'load',
852 this.parentNode.handlePodImageLoad.bind(this.parentNode, this));
853
826 var initialAuthType = this.user.initialAuthType || 854 var initialAuthType = this.user.initialAuthType ||
827 AUTH_TYPE.OFFLINE_PASSWORD; 855 AUTH_TYPE.OFFLINE_PASSWORD;
828 this.setAuthType(initialAuthType, null); 856 this.setAuthType(initialAuthType, null);
829 857
830 if (this.user.isActiveDirectory) 858 if (this.user.isActiveDirectory)
831 this.setAttribute('is-active-directory', ''); 859 this.setAttribute('is-active-directory', '');
832 860
833 this.userClickAuthAllowed_ = false; 861 this.userClickAuthAllowed_ = false;
834 862
835 // Lazy load the assets needed for the polymer submit button. 863 // Lazy load the assets needed for the polymer submit button.
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
945 973
946 /** 974 /**
947 * Gets name element. 975 * Gets name element.
948 * @type {!HTMLDivElement} 976 * @type {!HTMLDivElement}
949 */ 977 */
950 get nameElement() { 978 get nameElement() {
951 return this.querySelector('.name'); 979 return this.querySelector('.name');
952 }, 980 },
953 981
954 /** 982 /**
983 * Gets image element of the small pod.
984 * @type {!HTMLImageElement}
985 */
986 get smallPodImageElement() {
987 return this.querySelector('.small-pod-image');
988 },
989
990 /**
991 * Gets name element of the small pod.
992 * @type {!HTMLDivElement}
993 */
994 get smallPodNameElement() {
995 return this.querySelector('.small-pod-name');
996 },
997
998 /**
955 * Gets reauth name hint element. 999 * Gets reauth name hint element.
956 * @type {!HTMLDivElement} 1000 * @type {!HTMLDivElement}
957 */ 1001 */
958 get reauthNameHintElement() { 1002 get reauthNameHintElement() {
959 return this.querySelector('.reauth-name-hint'); 1003 return this.querySelector('.reauth-name-hint');
960 }, 1004 },
961 1005
962 /** 1006 /**
963 * Gets the container holding the password field. 1007 * Gets the container holding the password field.
964 * @type {!HTMLInputElement} 1008 * @type {!HTMLInputElement}
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
1136 1180
1137 /** 1181 /**
1138 * Gets the fingerprint icon area. 1182 * Gets the fingerprint icon area.
1139 * @type {!HTMLDivElement} 1183 * @type {!HTMLDivElement}
1140 */ 1184 */
1141 get fingerprintIconElement() { 1185 get fingerprintIconElement() {
1142 return this.querySelector('.fingerprint-icon-container'); 1186 return this.querySelector('.fingerprint-icon-container');
1143 }, 1187 },
1144 1188
1145 /** 1189 /**
1190 * Sets the pod style.
1191 * @param {UserPod.Style} style Style set to the pod.
1192 */
1193 setPodStyle: function(style) {
1194 switch (style) {
1195 case UserPod.Style.LARGE:
1196 this.querySelector('.large-pod').hidden = false;
1197 this.querySelector('.small-pod').hidden = true;
1198 break;
1199 case UserPod.Style.SMALL:
1200 this.querySelector('.large-pod').hidden = true;
1201 this.querySelector('.small-pod').hidden = false;
1202 this.querySelector('.small-pod').classList.remove('extra-small');
1203 break;
1204 case UserPod.Style.EXTRA_SMALL:
1205 this.querySelector('.large-pod').hidden = true;
1206 this.querySelector('.small-pod').hidden = false;
1207 this.querySelector('.small-pod').classList.add('extra-small');
1208 break;
1209 default:
1210 console.error("Attempt to set an invalid pod style.");
1211 break;
1212 }
1213 },
1214
1215 /**
1216 * Gets the pod style.
1217 * @return {UserPod.Style} Pod style.
1218 */
1219 getPodStyle: function() {
1220 if (this.querySelector('.small-pod').hidden)
1221 return UserPod.Style.LARGE;
1222 if (this.querySelector('.small-pod').classList.contains('extra-small'))
1223 return UserPod.Style.EXTRA_SMALL;
1224 return UserPod.Style.SMALL;
1225 },
1226
1227 /**
1146 * Updates the user pod element. 1228 * Updates the user pod element.
1147 */ 1229 */
1148 update: function() { 1230 update: function() {
1149 this.imageElement.src = 'chrome://userimage/' + this.user.username + 1231 var imageSrc = 'chrome://userimage/' + this.user.username +
1150 '?id=' + UserPod.userImageSalt_[this.user.username]; 1232 '?id=' + UserPod.userImageSalt_[this.user.username];
1233 this.imageElement.src = imageSrc;
1234 this.smallPodImageElement.src = imageSrc;
1151 1235
1152 this.nameElement.textContent = this.user_.displayName; 1236 this.nameElement.textContent = this.user_.displayName;
1237 this.smallPodNameElement.textContent = this.user_.displayName;
1153 this.reauthNameHintElement.textContent = this.user_.displayName; 1238 this.reauthNameHintElement.textContent = this.user_.displayName;
1154 this.classList.toggle('signed-in', this.user_.signedIn); 1239 this.classList.toggle('signed-in', this.user_.signedIn);
1155 1240
1156 if (this.isAuthTypeUserClick) 1241 if (this.isAuthTypeUserClick)
1157 this.passwordLabelElement.textContent = this.authValue; 1242 this.passwordLabelElement.textContent = this.authValue;
1158 1243
1159 this.updateActionBoxArea(); 1244 this.updateActionBoxArea();
1160 1245
1161 this.passwordElement.setAttribute('aria-label', loadTimeData.getStringF( 1246 this.passwordElement.setAttribute('aria-label', loadTimeData.getStringF(
1162 'passwordFieldAccessibleName', this.user_.emailAddress)); 1247 'passwordFieldAccessibleName', this.user_.emailAddress));
(...skipping 632 matching lines...) Expand 10 before | Expand all | Expand 10 after
1795 } 1880 }
1796 }, 1881 },
1797 1882
1798 /** 1883 /**
1799 * Refresh the message in the remove user warning dialog. 1884 * Refresh the message in the remove user warning dialog.
1800 * @param {string} profilePath The filepath of the URL (must be verified). 1885 * @param {string} profilePath The filepath of the URL (must be verified).
1801 * @param {string} message The message to be written. 1886 * @param {string} message The message to be written.
1802 * @param {number|string=} count The number or string to replace $1 in 1887 * @param {number|string=} count The number or string to replace $1 in
1803 * |message|. Can be omitted if $1 is not present in |message|. 1888 * |message|. Can be omitted if $1 is not present in |message|.
1804 */ 1889 */
1805 updateRemoveWarningDialogSetMessage_: function(profilePath, message, 1890 updateRemoveWarningDialogSetMessage_: function(
1806 count) { 1891 profilePath, message, count) {
1807 if (profilePath !== this.user.profilePath) 1892 if (profilePath !== this.user.profilePath)
1808 return; 1893 return;
1809 // Add localized messages where $1 will be replaced with 1894 // Add localized messages where $1 will be replaced with
1810 // <span class="total-count"></span> and $2 will be replaced with 1895 // <span class="total-count"></span> and $2 will be replaced with
1811 // <span class="email"></span>. 1896 // <span class="email"></span>.
1812 var element = this.querySelector('.action-box-remove-user-warning-text'); 1897 var element = this.querySelector('.action-box-remove-user-warning-text');
1813 element.textContent = ''; 1898 element.textContent = '';
1814 1899
1815 messageParts = message.split(/(\$[12])/); 1900 messageParts = message.split(/(\$[12])/);
1816 var numParts = messageParts.length; 1901 var numParts = messageParts.length;
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
1980 this.actionBoxMenuRemoveElement.tabIndex = -1; 2065 this.actionBoxMenuRemoveElement.tabIndex = -1;
1981 }, 2066 },
1982 2067
1983 /** 2068 /**
1984 * Handles mouse down event. It sets whether the user click auth will be 2069 * Handles mouse down event. It sets whether the user click auth will be
1985 * allowed on the next mouse click event. The auth is allowed iff the pod 2070 * allowed on the next mouse click event. The auth is allowed iff the pod
1986 * was focused on the mouse down event starting the click. 2071 * was focused on the mouse down event starting the click.
1987 * @param {Event} e The mouse down event. 2072 * @param {Event} e The mouse down event.
1988 */ 2073 */
1989 handlePodMouseDown_: function(e) { 2074 handlePodMouseDown_: function(e) {
1990 this.userClickAuthAllowed_ = this.parentNode.isFocused(this); 2075 // Only large pods have mouse down event.
2076 if (this.getPodStyle() == UserPod.Style.LARGE)
2077 this.userClickAuthAllowed_ = this.parentNode.isFocused(this);
1991 }, 2078 },
1992 2079
1993 /** 2080 /**
1994 * Called when the input of the password element changes. Updates the submit 2081 * Called when the input of the password element changes. Updates the submit
1995 * button color and state and hides the error popup bubble. 2082 * button color and state and hides the error popup bubble.
1996 */ 2083 */
1997 updateInput_: function() { 2084 updateInput_: function() {
1998 var isEmpty = this.passwordElement.value.length == 0; 2085 var isEmpty = this.passwordElement.value.length == 0;
1999 if (this.submitButton) { 2086 if (this.submitButton) {
2000 this.submitButton.disabled = isEmpty; 2087 this.submitButton.disabled = isEmpty;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2037 }, 2124 },
2038 2125
2039 /** 2126 /**
2040 * Handles click event on a user pod. 2127 * Handles click event on a user pod.
2041 * @param {Event} e Click event. 2128 * @param {Event} e Click event.
2042 */ 2129 */
2043 handleClickOnPod_: function(e) { 2130 handleClickOnPod_: function(e) {
2044 if (this.parentNode.disabled) 2131 if (this.parentNode.disabled)
2045 return; 2132 return;
2046 2133
2134 if (this.getPodStyle() != UserPod.Style.LARGE) {
2135 $('pod-row').switchMainPod(this);
2136 return;
2137 }
2138
2047 if (!this.isActionBoxMenuActive) { 2139 if (!this.isActionBoxMenuActive) {
2048 if (this.isAuthTypeOnlineSignIn) { 2140 if (this.isAuthTypeOnlineSignIn) {
2049 this.showSigninUI(); 2141 this.showSigninUI();
2050 } else if (this.isAuthTypeUserClick && this.userClickAuthAllowed_) { 2142 } else if (this.isAuthTypeUserClick && this.userClickAuthAllowed_) {
2051 // Note that this.userClickAuthAllowed_ is set in mouse down event 2143 // Note that this.userClickAuthAllowed_ is set in mouse down event
2052 // handler. 2144 // handler.
2053 this.parentNode.setActivatedPod(this); 2145 this.parentNode.setActivatedPod(this);
2054 } else if (this.pinKeyboard && 2146 } else if (this.pinKeyboard &&
2055 e.target == this.pinKeyboard.submitButton) { 2147 e.target == this.pinKeyboard.submitButton) {
2056 // Sets the pod as activated if the submit button is clicked so that 2148 // Sets the pod as activated if the submit button is clicked so that
2057 // it simulates what the enter button does for the password/pin. 2149 // it simulates what the enter button does for the password/pin.
2058 this.parentNode.setActivatedPod(this); 2150 this.parentNode.setActivatedPod(this);
2059 } 2151 }
2060 2152
2061 if (this.multiProfilesPolicyApplied) 2153 if (this.multiProfilesPolicyApplied)
2062 this.userTypeBubbleElement.classList.add('bubble-shown'); 2154 this.userTypeBubbleElement.classList.add('bubble-shown');
2063 2155
2064 // Prevent default so that we don't trigger 'focus' event and 2156 // Prevent default so that we don't trigger 'focus' event and
2065 // stop propagation so that the 'click' event does not bubble 2157 // stop propagation so that the 'click' event does not bubble
2066 // up and accidentally closes the bubble tooltip. 2158 // up and accidentally closes the bubble tooltip.
2067 stopEventPropagation(e); 2159 stopEventPropagation(e);
2068 } 2160 }
2069 }, 2161 },
2070 2162
2071 /** 2163 /**
2072 * Handles keydown event for a user pod. 2164 * Handles keydown event for a user pod.
2073 * @param {Event} e Key event. 2165 * @param {Event} e Key event.
2074 */ 2166 */
2075 handlePodKeyDown_: function(e) { 2167 handlePodKeyDown_: function(e) {
2168 if (this.getPodStyle() != UserPod.Style.LARGE) {
2169 this.handleNonLargePodKeyDown_(e);
2170 return;
2171 }
2076 if (!this.isAuthTypeUserClick || this.disabled) 2172 if (!this.isAuthTypeUserClick || this.disabled)
2077 return; 2173 return;
2078 switch (e.key) { 2174 switch (e.key) {
2079 case 'Enter': 2175 case 'Enter':
2080 case ' ': 2176 case ' ':
2081 if (this.parentNode.isFocused(this)) 2177 if (this.parentNode.isFocused(this))
2082 this.parentNode.setActivatedPod(this); 2178 this.parentNode.setActivatedPod(this);
2083 break; 2179 break;
2084 } 2180 }
2181 },
2182
2183 /**
2184 * Handles keydown event for a small or extra small user pod.
2185 * @param {Event} e Key event.
2186 */
2187 handleNonLargePodKeyDown_: function(e) {
2188 switch (e.key) {
2189 case 'Enter':
2190 case ' ':
2191 if ($('pod-row').isFocused(this))
2192 $('pod-row').switchMainPod(this);
2193 break;
2194 }
2085 } 2195 }
2086 }; 2196 };
2087 2197
2088 /** 2198 /**
2089 * Creates a public account user pod. 2199 * Creates a public account user pod.
2090 * @constructor 2200 * @constructor
2091 * @extends {UserPod} 2201 * @extends {UserPod}
2092 */ 2202 */
2093 var PublicAccountUserPod = cr.ui.define(function() { 2203 var PublicAccountUserPod = cr.ui.define(function() {
2094 var node = UserPod(); 2204 var node = UserPod();
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
2286 this.focusInput(); 2396 this.focusInput();
2287 } 2397 }
2288 return true; 2398 return true;
2289 }, 2399 },
2290 2400
2291 /** @override */ 2401 /** @override */
2292 handleClickOnPod_: function(e) { 2402 handleClickOnPod_: function(e) {
2293 if (this.parentNode.disabled) 2403 if (this.parentNode.disabled)
2294 return; 2404 return;
2295 2405
2406 if (this.getPodStyle() != UserPod.Style.LARGE) {
2407 $('pod-row').switchMainPod(this);
2408 return;
2409 }
2410
2296 this.parentNode.focusPod(this); 2411 this.parentNode.focusPod(this);
2297 this.parentNode.setActivatedPod(this, e); 2412 this.parentNode.setActivatedPod(this, e);
2298 // Prevent default so that we don't trigger 'focus' event. 2413 // Prevent default so that we don't trigger 'focus' event.
2299 e.preventDefault(); 2414 e.preventDefault();
2300 }, 2415 },
2301 2416
2302 /** 2417 /**
2303 * Updates the display name shown on the pod. 2418 * Updates the display name shown on the pod.
2304 * @param {string} displayName The new display name 2419 * @param {string} displayName The new display name
2305 */ 2420 */
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
2519 get mainInput() { 2634 get mainInput() {
2520 if (this.user.needsSignin) 2635 if (this.user.needsSignin)
2521 return this.passwordElement; 2636 return this.passwordElement;
2522 else 2637 else
2523 return this.nameElement; 2638 return this.nameElement;
2524 }, 2639 },
2525 2640
2526 /** @override */ 2641 /** @override */
2527 update: function() { 2642 update: function() {
2528 this.imageElement.src = this.user.userImage; 2643 this.imageElement.src = this.user.userImage;
2644 this.smallPodImageElement.src = this.user.userImage;
2529 this.nameElement.textContent = this.user.displayName; 2645 this.nameElement.textContent = this.user.displayName;
2646 this.smallPodNameElement.textContent = this.user.displayName;
2530 this.reauthNameHintElement.textContent = this.user.displayName; 2647 this.reauthNameHintElement.textContent = this.user.displayName;
2531 2648
2532 var isLockedUser = this.user.needsSignin; 2649 var isLockedUser = this.user.needsSignin;
2533 var isLegacySupervisedUser = this.user.legacySupervisedUser; 2650 var isLegacySupervisedUser = this.user.legacySupervisedUser;
2534 var isChildUser = this.user.childUser; 2651 var isChildUser = this.user.childUser;
2535 var isSyncedUser = this.user.emailAddress !== ""; 2652 var isSyncedUser = this.user.emailAddress !== "";
2536 var isProfileLoaded = this.user.isProfileLoaded; 2653 var isProfileLoaded = this.user.isProfileLoaded;
2537 this.classList.toggle('locked', isLockedUser); 2654 this.classList.toggle('locked', isLockedUser);
2538 this.classList.toggle('legacy-supervised', isLegacySupervisedUser); 2655 this.classList.toggle('legacy-supervised', isLegacySupervisedUser);
2539 this.classList.toggle('child', isChildUser); 2656 this.classList.toggle('child', isChildUser);
(...skipping 24 matching lines...) Expand all
2564 } 2681 }
2565 this.passwordElement.value = ''; 2682 this.passwordElement.value = '';
2566 return true; 2683 return true;
2567 }, 2684 },
2568 2685
2569 /** @override */ 2686 /** @override */
2570 handleClickOnPod_: function(e) { 2687 handleClickOnPod_: function(e) {
2571 if (this.parentNode.disabled) 2688 if (this.parentNode.disabled)
2572 return; 2689 return;
2573 2690
2691 if (this.getPodStyle() != UserPod.Style.LARGE) {
2692 $('pod-row').switchMainPod(this);
2693 return;
2694 }
2695
2574 Oobe.clearErrors(); 2696 Oobe.clearErrors();
2575 this.parentNode.lastFocusedPod_ = this; 2697 this.parentNode.lastFocusedPod_ = this;
2576 2698
2577 // If this is a locked pod and there are local credentials, show the 2699 // If this is a locked pod and there are local credentials, show the
2578 // password field. Otherwise call activate() which will open up a browser 2700 // password field. Otherwise call activate() which will open up a browser
2579 // window or show the reauth dialog, as needed. 2701 // window or show the reauth dialog, as needed.
2580 if (!(this.user.needsSignin && this.user.hasLocalCreds) && 2702 if (!(this.user.needsSignin && this.user.hasLocalCreds) &&
2581 !this.isActionBoxMenuActive) { 2703 !this.isActionBoxMenuActive) {
2582 this.activate(e); 2704 this.activate(e);
2583 } 2705 }
(...skipping 21 matching lines...) Expand all
2605 UserPod.prototype.decorate.call(this); 2727 UserPod.prototype.decorate.call(this);
2606 this.launchAppButtonElement.addEventListener('click', 2728 this.launchAppButtonElement.addEventListener('click',
2607 this.activate.bind(this)); 2729 this.activate.bind(this));
2608 }, 2730 },
2609 2731
2610 /** @override */ 2732 /** @override */
2611 update: function() { 2733 update: function() {
2612 this.imageElement.src = this.user.iconUrl; 2734 this.imageElement.src = this.user.iconUrl;
2613 this.imageElement.alt = this.user.label; 2735 this.imageElement.alt = this.user.label;
2614 this.imageElement.title = this.user.label; 2736 this.imageElement.title = this.user.label;
2737 this.smallPodImageElement.src = this.user.iconUrl;
2738 this.smallPodImageElement.alt = this.user.label;
2739 this.smallPodImageElement.title = this.user.label;
2615 this.passwordEntryContainerElement.hidden = true; 2740 this.passwordEntryContainerElement.hidden = true;
2616 this.launchAppButtonContainerElement.hidden = false; 2741 this.launchAppButtonContainerElement.hidden = false;
2617 this.nameElement.textContent = this.user.label; 2742 this.nameElement.textContent = this.user.label;
2743 this.smallPodNameElement.textContent = this.user.label;
2618 this.reauthNameHintElement.textContent = this.user.label; 2744 this.reauthNameHintElement.textContent = this.user.label;
2619 2745
2620 UserPod.prototype.updateActionBoxArea.call(this); 2746 UserPod.prototype.updateActionBoxArea.call(this);
2621 UserPod.prototype.customizeUserPodPerUserType.call(this); 2747 UserPod.prototype.customizeUserPodPerUserType.call(this);
2622 }, 2748 },
2623 2749
2624 /** @override */ 2750 /** @override */
2625 get mainInput() { 2751 get mainInput() {
2626 return this.launchAppButtonElement; 2752 return this.launchAppButtonElement;
2627 }, 2753 },
(...skipping 16 matching lines...) Expand all
2644 var diagnosticMode = e && e.ctrlKey; 2770 var diagnosticMode = e && e.ctrlKey;
2645 this.launchApp_(this.user, diagnosticMode); 2771 this.launchApp_(this.user, diagnosticMode);
2646 return true; 2772 return true;
2647 }, 2773 },
2648 2774
2649 /** @override */ 2775 /** @override */
2650 handleClickOnPod_: function(e) { 2776 handleClickOnPod_: function(e) {
2651 if (this.parentNode.disabled) 2777 if (this.parentNode.disabled)
2652 return; 2778 return;
2653 2779
2780 if (this.getPodStyle() != UserPod.Style.LARGE) {
2781 $('pod-row').switchMainPod(this);
2782 return;
2783 }
2784
2654 Oobe.clearErrors(); 2785 Oobe.clearErrors();
2655 this.parentNode.lastFocusedPod_ = this; 2786 this.parentNode.lastFocusedPod_ = this;
2656 this.activate(e); 2787 this.activate(e);
2657 }, 2788 },
2658 2789
2659 /** 2790 /**
2660 * Launch the app. If |diagnosticMode| is true, ask user to confirm. 2791 * Launch the app. If |diagnosticMode| is true, ask user to confirm.
2661 * @param {Object} app App data. 2792 * @param {Object} app App data.
2662 * @param {boolean} diagnosticMode Whether to run the app in diagnostic 2793 * @param {boolean} diagnosticMode Whether to run the app in diagnostic
2663 * mode. 2794 * mode.
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
2705 2836
2706 // Focused pod. 2837 // Focused pod.
2707 focusedPod_: undefined, 2838 focusedPod_: undefined,
2708 2839
2709 // Activated pod, i.e. the pod of current login attempt. 2840 // Activated pod, i.e. the pod of current login attempt.
2710 activatedPod_: undefined, 2841 activatedPod_: undefined,
2711 2842
2712 // Pod that was most recently focused, if any. 2843 // Pod that was most recently focused, if any.
2713 lastFocusedPod_: undefined, 2844 lastFocusedPod_: undefined,
2714 2845
2846 // Pod that occupies the main spot.
2847 mainPod_: undefined,
2848
2715 // Pods whose initial images haven't been loaded yet. 2849 // Pods whose initial images haven't been loaded yet.
2716 podsWithPendingImages_: [], 2850 podsWithPendingImages_: [],
2717 2851
2718 // Whether pod placement has been postponed. 2852 // Whether pod placement has been postponed.
2719 podPlacementPostponed_: false, 2853 podPlacementPostponed_: false,
2720 2854
2721 // Standard user pod height/width. 2855 // Standard user pod height/width.
2722 userPodHeight_: 0, 2856 userPodHeight_: 0,
2723 userPodWidth_: 0, 2857 userPodWidth_: 0,
2724 2858
(...skipping 27 matching lines...) Expand all
2752 isNewDesktopUserManager ? MD_DESKTOP_POD_HEIGHT : 2886 isNewDesktopUserManager ? MD_DESKTOP_POD_HEIGHT :
2753 DESKTOP_POD_HEIGHT : 2887 DESKTOP_POD_HEIGHT :
2754 CROS_POD_HEIGHT; 2888 CROS_POD_HEIGHT;
2755 this.userPodWidth_ = isDesktopUserManager ? 2889 this.userPodWidth_ = isDesktopUserManager ?
2756 isNewDesktopUserManager ? MD_DESKTOP_POD_WIDTH : 2890 isNewDesktopUserManager ? MD_DESKTOP_POD_WIDTH :
2757 DESKTOP_POD_WIDTH : 2891 DESKTOP_POD_WIDTH :
2758 CROS_POD_WIDTH; 2892 CROS_POD_WIDTH;
2759 }, 2893 },
2760 2894
2761 /** 2895 /**
2762 * Returns all the pods in this pod row. 2896 * Returns all the pods in this pod row. Some pods may not be its direct
2897 * children, but the caller doesn't have to know this.
2763 * @type {NodeList} 2898 * @type {NodeList}
2764 */ 2899 */
2765 get pods() { 2900 get pods() {
2766 return Array.prototype.slice.call(this.children); 2901 var powRowChildren = Array.prototype.slice.call(this.children);
2902 var containerChildren =
2903 Array.prototype.slice.call(this.smallPodsContainer.children);
2904 return powRowChildren.concat(containerChildren);
2767 }, 2905 },
2768 2906
2769 /** 2907 /**
2770 * Return true if user pod row has only single user pod in it, which should 2908 * Return true if user pod row has only single user pod in it, which should
2771 * always be focused except desktop and touch view modes. 2909 * always be focused except desktop and touch view modes.
2772 * @type {boolean} 2910 * @type {boolean}
2773 */ 2911 */
2774 get alwaysFocusSinglePod() { 2912 get alwaysFocusSinglePod() {
2775 var isDesktopUserManager = Oobe.getInstance().displayType == 2913 var isDesktopUserManager = Oobe.getInstance().displayType ==
2776 DISPLAY_TYPE.DESKTOP_USER_MANAGER; 2914 DISPLAY_TYPE.DESKTOP_USER_MANAGER;
2777 2915
2778 return (isDesktopUserManager || this.touchViewEnabled_) ? 2916 return (isDesktopUserManager || this.touchViewEnabled_) ?
2779 false : this.children.length == 1; 2917 false :
2918 this.pods.length == 1;
2780 }, 2919 },
2781 2920
2782 /** 2921 /**
2783 * Returns pod with the given app id. 2922 * Returns pod with the given app id.
2784 * @param {!string} app_id Application id to be matched. 2923 * @param {!string} app_id Application id to be matched.
2785 * @return {Object} Pod with the given app id. null if pod hasn't been 2924 * @return {Object} Pod with the given app id. null if pod hasn't been
2786 * found. 2925 * found.
2787 */ 2926 */
2788 getPodWithAppId_: function(app_id) { 2927 getPodWithAppId_: function(app_id) {
2789 for (var i = 0, pod; pod = this.pods[i]; ++i) { 2928 for (var i = 0, pod; pod = this.pods[i]; ++i) {
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
2946 /** 3085 /**
2947 * Removes user pod from pod row. 3086 * Removes user pod from pod row.
2948 * @param {!user} username 3087 * @param {!user} username
2949 */ 3088 */
2950 removeUserPod: function(username) { 3089 removeUserPod: function(username) {
2951 var podToRemove = this.getPodWithUsername_(username); 3090 var podToRemove = this.getPodWithUsername_(username);
2952 if (podToRemove == null) { 3091 if (podToRemove == null) {
2953 console.warn('Attempt to remove pod that does not exist'); 3092 console.warn('Attempt to remove pod that does not exist');
2954 return; 3093 return;
2955 } 3094 }
2956 this.removeChild(podToRemove); 3095 // Its parent is not necessarily this pod row.
2957 if (this.pods.length > 0) 3096 podToRemove.parentNode.removeChild(podToRemove);
3097 this.mainPod_ = null;
3098 if (this.pods.length > 0) {
3099 // placePods_() will select a new main pod and re-append pods
3100 // to different parents if necessary.
2958 this.placePods_(); 3101 this.placePods_();
3102 this.maybePreselectPod();
3103 }
2959 }, 3104 },
2960 3105
2961 /** 3106 /**
2962 * Returns index of given pod or -1 if not found. 3107 * Returns index of given pod or -1 if not found.
2963 * @param {UserPod} pod Pod to look up. 3108 * @param {UserPod} pod Pod to look up.
2964 * @private 3109 * @private
2965 */ 3110 */
2966 indexOf_: function(pod) { 3111 indexOf_: function(pod) {
2967 for (var i = 0; i < this.pods.length; ++i) { 3112 for (var i = 0; i < this.pods.length; ++i) {
2968 if (pod == this.pods[i]) 3113 if (pod == this.pods[i])
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
3013 * updated. 3158 * updated.
3014 */ 3159 */
3015 rebuildPods: function() { 3160 rebuildPods: function() {
3016 var emptyPodRow = this.pods.length == 0; 3161 var emptyPodRow = this.pods.length == 0;
3017 3162
3018 // Clear existing pods. 3163 // Clear existing pods.
3019 this.innerHTML = ''; 3164 this.innerHTML = '';
3020 this.focusedPod_ = undefined; 3165 this.focusedPod_ = undefined;
3021 this.activatedPod_ = undefined; 3166 this.activatedPod_ = undefined;
3022 this.lastFocusedPod_ = undefined; 3167 this.lastFocusedPod_ = undefined;
3168 this.mainPod_ = undefined;
3023 3169
3024 // Switch off animation 3170 // Switch off animation
3025 Oobe.getInstance().toggleClass('flying-pods', false); 3171 Oobe.getInstance().toggleClass('flying-pods', false);
3026 3172
3027 // Populate the pod row.
3028 for (var i = 0; i < this.users_.length; ++i) 3173 for (var i = 0; i < this.users_.length; ++i)
3029 this.addUserPod(this.users_[i]); 3174 this.addUserPod(this.users_[i]);
3030 3175
3031 for (var i = 0, pod; pod = this.pods[i]; ++i) 3176 for (var i = 0, pod; pod = this.pods[i]; ++i)
3032 this.podsWithPendingImages_.push(pod); 3177 this.podsWithPendingImages_.push(pod);
3033 3178
3034 // TODO(nkostylev): Edge case handling when kiosk apps are not fitting. 3179 // TODO(nkostylev): Edge case handling when kiosk apps are not fitting.
3035 if (this.shouldShowApps_) { 3180 if (this.shouldShowApps_) {
3036 for (var i = 0; i < this.apps_.length; ++i) 3181 for (var i = 0; i < this.apps_.length; ++i)
3037 this.addUserPod(this.apps_[i]); 3182 this.addUserPod(this.apps_[i]);
(...skipping 25 matching lines...) Expand all
3063 if ($('login-header-bar').signinUIState == 3208 if ($('login-header-bar').signinUIState ==
3064 SIGNIN_UI_STATE.GAIA_SIGNIN && 3209 SIGNIN_UI_STATE.GAIA_SIGNIN &&
3065 emptyPodRow && 3210 emptyPodRow &&
3066 this.pods.length > 0) { 3211 this.pods.length > 0) {
3067 login.GaiaSigninScreen.updateControlsState(); 3212 login.GaiaSigninScreen.updateControlsState();
3068 } 3213 }
3069 } 3214 }
3070 }, 3215 },
3071 3216
3072 /** 3217 /**
3218 * Gets the container of small pods.
3219 * @type {!HTMLDivElement}
3220 */
3221 get smallPodsContainer() {
3222 return document.querySelector('.small-pod-container');
3223 },
3224
3225 /**
3073 * Adds given apps to the pod row. 3226 * Adds given apps to the pod row.
3074 * @param {array} apps Array of apps. 3227 * @param {array} apps Array of apps.
3075 */ 3228 */
3076 setApps: function(apps) { 3229 setApps: function(apps) {
3077 this.apps_ = apps; 3230 this.apps_ = apps;
3078 this.rebuildPods(); 3231 this.rebuildPods();
3079 chrome.send('kioskAppsLoaded'); 3232 chrome.send('kioskAppsLoaded');
3080 3233
3081 // Check whether there's a pending kiosk app error. 3234 // Check whether there's a pending kiosk app error.
3082 window.setTimeout(function() { 3235 window.setTimeout(function() {
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
3315 }, 3468 },
3316 3469
3317 /** 3470 /**
3318 * Updates the list of locales available for a public session. 3471 * Updates the list of locales available for a public session.
3319 * @param {string} userID The user ID of the public session 3472 * @param {string} userID The user ID of the public session
3320 * @param {!Object} locales The list of available locales 3473 * @param {!Object} locales The list of available locales
3321 * @param {string} defaultLocale The locale to select by default 3474 * @param {string} defaultLocale The locale to select by default
3322 * @param {boolean} multipleRecommendedLocales Whether |locales| contains 3475 * @param {boolean} multipleRecommendedLocales Whether |locales| contains
3323 * two or more recommended locales 3476 * two or more recommended locales
3324 */ 3477 */
3325 setPublicSessionLocales: function(userID, 3478 setPublicSessionLocales: function(
3326 locales, 3479 userID, locales, defaultLocale, multipleRecommendedLocales) {
3327 defaultLocale,
3328 multipleRecommendedLocales) {
3329 var pod = this.getPodWithUsername_(userID); 3480 var pod = this.getPodWithUsername_(userID);
3330 if (pod != null) { 3481 if (pod != null) {
3331 pod.populateLanguageSelect(locales, 3482 pod.populateLanguageSelect(locales,
3332 defaultLocale, 3483 defaultLocale,
3333 multipleRecommendedLocales); 3484 multipleRecommendedLocales);
3334 } 3485 }
3335 }, 3486 },
3336 3487
3337 /** 3488 /**
3338 * Updates the list of available keyboard layouts for a public session pod. 3489 * Updates the list of available keyboard layouts for a public session pod.
3339 * @param {string} userID The user ID of the public session 3490 * @param {string} userID The user ID of the public session
3340 * @param {string} locale The locale to which this list of keyboard layouts 3491 * @param {string} locale The locale to which this list of keyboard layouts
3341 * applies 3492 * applies
3342 * @param {!Object} list List of available keyboard layouts 3493 * @param {!Object} list List of available keyboard layouts
3343 */ 3494 */
3344 setPublicSessionKeyboardLayouts: function(userID, locale, list) { 3495 setPublicSessionKeyboardLayouts: function(userID, locale, list) {
3345 var pod = this.getPodWithUsername_(userID); 3496 var pod = this.getPodWithUsername_(userID);
3346 if (pod != null) 3497 if (pod != null)
3347 pod.populateKeyboardSelect(locale, list); 3498 pod.populateKeyboardSelect(locale, list);
3348 }, 3499 },
3349 3500
3350 /** 3501 /**
3351 * Called when window was resized. 3502 * Called when window was resized. The two common use cases are changing
3503 * screen orientation and showing the virtual keyboard.
3352 */ 3504 */
3353 onWindowResize: function() { 3505 onWindowResize: function() {
3354 var layout = this.calculateLayout_(); 3506 var screen = document.querySelector('#scroll-container');
3355 if (layout.columns != this.columns || layout.rows != this.rows) 3507 var clientArea = document.querySelector('#inner-container');
3356 this.placePods_(); 3508 if (Oobe.getInstance().virtualKeyboardShown) {
3357 3509 // Edge case: when virtual keyboard is shown, although the screen size
3358 // Wrap this in a set timeout so the function is called after the pod is 3510 // is reduced properly, the size of the outer container remains the
3359 // finished transitioning so that we work with the final pod dimensions. 3511 // same because its min-height is applied. Users can scroll the screen
3360 // If there is no focused pod that may be transitioning when this function 3512 // upward and see empty areas beyond the pod row and the scroll bar,
3361 // is called, we can call scrollFocusedPodIntoView() right away. 3513 // which should be avoided.
3362 var timeOut = 0; 3514 // This is a hacky solution: we can make the scroll container hide
3363 if (this.focusedPod_) { 3515 // the overflow area and manully position the client area.
3364 var style = getComputedStyle(this.focusedPod_); 3516 screen.style.overflowY = "hidden";
3365 timeOut = parseFloat(style.transitionDuration) * 1000; 3517 clientArea.style.position = "absolute";
3518 clientArea.style.left = cr.ui.toCssPx(0);
3519 clientArea.style.top = cr.ui.toCssPx(0);
3520 } else {
3521 // Sets the values to default when virtual keyboard is not shown.
3522 screen.style.overflowY = "auto";
3523 clientArea.style.position = "relative";
3366 } 3524 }
3367 3525 this.placePods_();
3368 setTimeout(function() {
3369 this.scrollFocusedPodIntoView();
3370 }.bind(this), timeOut);
3371 }, 3526 },
3372 3527
3373 /** 3528 /**
3374 * Returns width of podrow having |columns| number of columns. 3529 * Returns width of podrow having |columns| number of columns.
3375 * @private 3530 * @private
3376 */ 3531 */
3377 columnsToWidth_: function(columns) { 3532 columnsToWidth_: function(columns) {
3378 var isDesktopUserManager = Oobe.getInstance().displayType == 3533 var isDesktopUserManager = Oobe.getInstance().displayType ==
3379 DISPLAY_TYPE.DESKTOP_USER_MANAGER; 3534 DISPLAY_TYPE.DESKTOP_USER_MANAGER;
3380 var margin = isDesktopUserManager ? DESKTOP_MARGIN_BY_COLUMNS[columns] : 3535 var margin = isDesktopUserManager ? DESKTOP_MARGIN_BY_COLUMNS[columns] :
(...skipping 30 matching lines...) Expand all
3411 while (maxWidth < this.columnsToWidth_(columns) && columns > 1) 3566 while (maxWidth < this.columnsToWidth_(columns) && columns > 1)
3412 --columns; 3567 --columns;
3413 var rows = Math.floor((this.pods.length - 1) / columns) + 1; 3568 var rows = Math.floor((this.pods.length - 1) / columns) + 1;
3414 if (getComputedStyle( 3569 if (getComputedStyle(
3415 $('signin-banner'), null).getPropertyValue('display') != 'none') { 3570 $('signin-banner'), null).getPropertyValue('display') != 'none') {
3416 rows = Math.min(rows, MAX_NUMBER_OF_ROWS_UNDER_SIGNIN_BANNER); 3571 rows = Math.min(rows, MAX_NUMBER_OF_ROWS_UNDER_SIGNIN_BANNER);
3417 } 3572 }
3418 if (!Oobe.getInstance().newDesktopUserManager) { 3573 if (!Oobe.getInstance().newDesktopUserManager) {
3419 var maxHeigth = Oobe.getInstance().clientAreaSize.height; 3574 var maxHeigth = Oobe.getInstance().clientAreaSize.height;
3420 while (maxHeigth < this.rowsToHeight_(rows) && rows > 1) 3575 while (maxHeigth < this.rowsToHeight_(rows) && rows > 1)
3421 --rows; 3576 --rows;
3422 } 3577 }
3423 // One more iteration if it's not enough cells to place all pods. 3578 // One more iteration if it's not enough cells to place all pods.
3424 while (maxWidth >= this.columnsToWidth_(columns + 1) && 3579 while (maxWidth >= this.columnsToWidth_(columns + 1) &&
3425 columns * rows < this.pods.length && 3580 columns * rows < this.pods.length &&
3426 columns < MAX_NUMBER_OF_COLUMNS) { 3581 columns < MAX_NUMBER_OF_COLUMNS) {
3427 ++columns; 3582 ++columns;
3428 } 3583 }
3429 return {columns: columns, rows: rows}; 3584 return {columns: columns, rows: rows};
3430 }, 3585 },
3431 3586
3432 /** 3587 /**
3433 * Places pods onto their positions onto pod grid. 3588 * Places pods onto their positions in pod grid matching the new design.
3434 * @private 3589 * @private
3435 */ 3590 */
3436 placePods_: function() { 3591 placePods_: function() {
3437 var isDesktopUserManager = Oobe.getInstance().displayType == 3592 var pods = this.pods;
3438 DISPLAY_TYPE.DESKTOP_USER_MANAGER; 3593 if (pods.length == 0) {
3439 if (isDesktopUserManager && !Oobe.getInstance().userPodsPageVisible) 3594 console.error('Attempt to place pods for an empty pod list.');
3440 return; 3595 return;
3441 3596 }
3442 var layout = this.calculateLayout_(); 3597 // Append all pods to their proper parents. Small pods have parent other
3443 var columns = this.columns = layout.columns; 3598 // than the pod row. The pods were all initialized with the pow row as a
3444 var rows = this.rows = layout.rows; 3599 // temporary parent, which is intended to ensure that all event listeners
3445 var maxPodsNumber = columns * rows; 3600 // work properly. If the main pod already exists, it means we are in the
3446 var margin = isDesktopUserManager ? DESKTOP_MARGIN_BY_COLUMNS[columns] : 3601 // process of resizing the window, then there is no need to change parents
3447 MARGIN_BY_COLUMNS[columns]; 3602 // of any pod.
3448 this.parentNode.setPreferredSize( 3603 if (!this.mainPod_) {
3449 this.columnsToWidth_(columns), this.rowsToHeight_(rows)); 3604 this.mainPod_ = this.preselectedPod;
3450 var height = this.userPodHeight_; 3605 this.appendPodsToParents();
3451 var width = this.userPodWidth_; 3606 }
3452 var pinPodLocation = { column: columns + 1, row: rows + 1 }; 3607 this.restoreInitialStates_();
3453 if (this.focusedPod_ && this.focusedPod_.isPinShown()) 3608 if (Oobe.getInstance().virtualKeyboardShown) {
3454 pinPodLocation = this.findPodLocation_(this.focusedPod_, columns, rows); 3609 // When virtual keyboard is shown, the account picker should occupy
3455 3610 // all the remaining screen. Screen size was already updated to exclude
3456 this.pods.forEach(function(pod, index) { 3611 // the virtual keyboard.
3457 if (index >= maxPodsNumber) { 3612 this.parentNode.setPreferredSize(
3458 pod.hidden = true; 3613 this.screenSize.width,
3459 return; 3614 this.screenSize.height);
3460 } 3615 } else {
3461 pod.hidden = false; 3616 // Make sure not to block the header bar when virtual keyboard is absent .
3462 if (pod.offsetHeight != height && 3617 this.parentNode.setPreferredSize(
3463 pod.offsetHeight != CROS_PIN_POD_HEIGHT) { 3618 Oobe.getInstance().clientAreaSize.width,
3464 console.error('Pod offsetHeight (' + pod.offsetHeight + 3619 Oobe.getInstance().clientAreaSize.height);
3465 ') and POD_HEIGHT (' + height + ') are not equal.'); 3620 }
3466 } 3621
3467 if (pod.offsetWidth != width) { 3622 if (pods.length == 1) {
3468 console.error('Pod offsetWidth (' + pod.offsetWidth + 3623 this.placeSinglePod_();
3469 ') and POD_WIDTH (' + width + ') are not equal.'); 3624 } else if (pods.length == POD_ROW_LIMIT) {
3470 } 3625 this.placePodsOnPodRow_();
3471 var column = index % columns; 3626 } else {
3472 var row = Math.floor(index / columns); 3627 this.placePodsOnContainer_();
3473 3628 }
3474 var rowPadding = isDesktopUserManager ? DESKTOP_ROW_PADDING : 3629 Oobe.getInstance().updateScreenSize(this.parentNode);
3475 POD_ROW_PADDING; 3630 this.updatePodNameArea();
3476 pod.left = rowPadding + column * (width + margin); 3631 },
3477 3632
3478 // On desktop, we want the rows to always be equally spaced. 3633 /**
3479 pod.top = isDesktopUserManager ? row * (height + rowPadding) : 3634 * Append pods to proper parents. Called each time before pod placement.
3480 row * height + rowPadding; 3635 * @private
3636 */
3637 appendPodsToParents: function() {
3638 var pods = this.pods;
3639 // Pod count may have changed, so the placement method may change
3640 // accordingly. Therefore, always remove all pods from their current
3641 // parents first.
3642 for (var pod of pods) {
3643 pod.parentNode.removeChild(pod);
3644 }
3645 if (pods.length <= POD_ROW_LIMIT) {
3646 for (var pod of pods) {
3647 this.appendChild(pod);
3648 }
3649 } else {
3650 // When the user count exceeds the limit (currently set to 2), only the
3651 // main pod still has pow row as parent, all other pods should be
3652 // appended to the container with scroll bar.
3653 for (var pod of pods) {
3654 if (pod == this.mainPod_) {
3655 this.appendChild(pod);
3656 } else {
3657 this.smallPodsContainer.appendChild(pod);
3658 }
3659 }
3660 }
3661 },
3662
3663 /**
3664 * Called when there is one user pod.
3665 * @private
3666 */
3667 placeSinglePod_: function() {
3668 this.mainPod_.setPodStyle(UserPod.Style.LARGE);
3669 this.mainPod_.left = (this.screenSize.width - CROS_POD_WIDTH) / 2;
3670 this.mainPod_.top = (this.screenSize.height - CROS_POD_HEIGHT) / 2;
3671 },
3672
3673 /**
3674 * Called when there are two users pods.
3675 * @private
3676 */
3677 placePodsOnPodRow_: function() {
3678 // Both pods have large size and are placed adjacently.
3679 var secondPod =
3680 this.pods[0] == this.mainPod_ ? this.pods[1] : this.pods[0];
3681 this.mainPod_.setPodStyle(UserPod.Style.LARGE);
3682 secondPod.setPodStyle(UserPod.Style.LARGE);
3683
3684 var DOUBLE_PODS_PADDING = this.isPortraitMode() ? 32 : 118;
3685 var leftPadding = (this.screenSize.width - (CROS_POD_WIDTH * 2 + DOUBLE_PO DS_PADDING)) / 2;
3686 // Start actual positioning.
3687 this.mainPod_.left = leftPadding;
3688 this.mainPod_.top = (this.screenSize.height - CROS_POD_HEIGHT) / 2;
3689 secondPod.left = leftPadding + CROS_POD_WIDTH + DOUBLE_PODS_PADDING;
3690 secondPod.top = (this.screenSize.height - CROS_POD_HEIGHT) / 2;
3691 },
3692
3693 /**
3694 * Called when there are more than two user pods.
3695 * @private
3696 */
3697 placePodsOnContainer_: function() {
3698 this.smallPodsContainer.hidden = false;
3699 var pods = this.pods;
3700 if ((pods.length > LANDSCAPE_MODE_LIMIT && !this.isPortraitMode()) ||
3701 (pods.length > PORTRAIT_MODE_LIMIT && this.isPortraitMode())) {
3702 // If the pod count exceeds limits, they should be in extra small size
3703 // and the container will become scrollable.
3704 this.placePodsOnScrollableContainer_();
3705 return;
3706 }
3707 this.mainPod_.setPodStyle(UserPod.Style.LARGE);
3708 for (var pod of pods) {
3709 if (pod != this.mainPod_) {
3710 // All pods except the main one must be set to the small style.
3711 pod.setPodStyle(UserPod.Style.SMALL);
3712 }
3713 }
3714 // The size of the smallPodsContainer must be updated to avoid overflow,
3715 // otherwise unnecessary scroll bar will show up.
3716 this.smallPodsContainer.style.height =
3717 cr.ui.toCssPx(this.screenSize.height);
3718 this.smallPodsContainer.style.width = cr.ui.toCssPx(CROS_SMALL_POD_WIDTH);
3719
3720 var LEFT_PADDING = this.isPortraitMode() ? 0 : 98;
3721 var MIDDLE_PADDING = this.isPortraitMode() ? 84 : 220;
3722 var contentsWidth = LEFT_PADDING +
3723 CROS_POD_WIDTH + MIDDLE_PADDING + CROS_SMALL_POD_WIDTH;
3724 var blankWidth = this.screenSize.width - contentsWidth;
3725 var actualLeftPadding = LEFT_PADDING;
3726 actualLeftPadding += this.isPortraitMode() ? blankWidth * 2 / 3:
3727 blankWidth / 2;
3728 var SMALL_POD_PADDING = 54;
3729 var actualSmallPodPadding = SMALL_POD_PADDING;
3730 var smallPodsTotalHeight = (pods.length - 1) * CROS_SMALL_POD_HEIGHT +
3731 (pods.length - 2) * actualSmallPodPadding;
3732 if (smallPodsTotalHeight > this.screenSize.height) {
3733 // Edge case: when the virtual keyboard is present, the total height of
3734 // the smallPodsContainer may exceed the screen height. Decrease the
3735 // padding among small pods according to the design spec.
3736 actualSmallPodPadding = 32;
3737 smallPodsTotalHeight = (pods.length - 1) * CROS_SMALL_POD_HEIGHT +
3738 (pods.length - 2) * actualSmallPodPadding;
3739 }
3740
3741 // Start positioning of the main pod and the smallPodsContainer.
3742 this.mainPod_.left = actualLeftPadding;
3743 this.mainPod_.top = (this.screenSize.height - CROS_POD_HEIGHT) / 2;
3744 this.smallPodsContainer.style.left =
3745 cr.ui.toCssPx(actualLeftPadding + CROS_POD_WIDTH + MIDDLE_PADDING);
3746 this.smallPodsContainer.style.top = cr.ui.toCssPx(0);
3747 // Start positioning of the small pods inside the smallPodsContainer.
3748 var smallPodsTopPadding = (this.screenSize.height - smallPodsTotalHeight) / 2;
3749 for (var pod of pods) {
3750 if (pod == this.mainPod_) {
3751 continue;
3752 }
3753 pod.left = 0;
3754 pod.top = smallPodsTopPadding;
3755 smallPodsTopPadding += CROS_SMALL_POD_HEIGHT + actualSmallPodPadding;
3756 }
3757 },
3758
3759 /**
3760 * Called when there are more than 6 user pods in landscape mode, or more
3761 * than 10 user pods in portrait mode.
3762 * @private
3763 */
3764 placePodsOnScrollableContainer_: function() {
3765 this.smallPodsContainer.hidden = false;
3766 // Add a dark overlay.
3767 this.smallPodsContainer.classList.add('scroll');
3768 var pods = this.pods;
3769 this.mainPod_.setPodStyle(UserPod.Style.LARGE);
3770 for (var pod of pods) {
3771 if (pod != this.mainPod_) {
3772 // All pods except the main one must be set to the extra small style.
3773 pod.setPodStyle(UserPod.Style.EXTRA_SMALL);
3774 }
3775 }
3776
3777 var SCROLL_LEFT_PADDING = this.isPortraitMode() ? 46 : 72;
3778 var SCROLL_RIGHT_PADDING = this.isPortraitMode() ? 12 : 72;
3779 // The offsetWidth of the smallPodsContainer.
3780 var scrollAreaWidth = SCROLL_LEFT_PADDING + CROS_EXTRA_SMALL_POD_WIDTH +
3781 SCROLL_RIGHT_PADDING;
3782 var mainPodPadding = (this.screenSize.width -
3783 scrollAreaWidth - CROS_POD_WIDTH) / 2;
3784 var SCROLL_TOP_PADDING = this.isPortraitMode() ? 66 : 72;
3785 var EXTRA_SMALL_POD_PADDING = 32;
3786 // Start positioning of the main pod and the smallPodsContainer.
3787 this.mainPod_.left = mainPodPadding;
3788 this.mainPod_.top = (this.screenSize.height - CROS_POD_HEIGHT) / 2;
3789 this.smallPodsContainer.style.left =
3790 cr.ui.toCssPx(mainPodPadding * 2 + CROS_POD_WIDTH);
3791 this.smallPodsContainer.style.top = cr.ui.toCssPx(0);
3792
3793 // Precalculate the total height of the scrollable container and check if
3794 // it indeed exceeds the screen height.
3795 var scrollHeight = 0;
3796 for (var pod of pods) {
3797 if (pod == this.mainPod_) {
3798 continue;
3799 }
3800 scrollHeight += CROS_EXTRA_SMALL_POD_HEIGHT + EXTRA_SMALL_POD_PADDING;
3801 }
3802 scrollHeight -= EXTRA_SMALL_POD_PADDING;
3803 // The smallPodsContainer should occupy the full screen vertically.
3804 this.smallPodsContainer.style.height = cr.ui.toCssPx(this.screenSize.heigh t);
3805 this.smallPodsContainer.style.width = cr.ui.toCssPx(
3806 SCROLL_LEFT_PADDING + CROS_EXTRA_SMALL_POD_WIDTH +
3807 SCROLL_RIGHT_PADDING);
3808
3809 // SCROLL_TOP_PADDING denotes the smallest top padding we can tolerate
3810 // before allowing the container to overflow and show the scroll bar.
3811 var actualTopPadding = SCROLL_TOP_PADDING;
3812 if ((this.screenSize.height - scrollHeight) / 2 > actualTopPadding) {
3813 // Edge case: the total height of the scrollable container does not
3814 // exceed the screen height (minus the neceesary padding), so the
3815 // scroll bar will not appear.
3816 // In this case, we still want to keep the extra small pod size and
3817 // the overlay, but the top and bottom padding should be adjusted
3818 // to ensure a symmetric layout.
3819 actualTopPadding = (this.screenSize.height - scrollHeight) / 2;
3820 } else if (!Oobe.getInstance().virtualKeyboardShown) {
3821 // The scroll bar will definitely be shown if we reach here. A gradient
3822 // mask is applied to avoid blocking the header bar if the virtual
3823 // keyboard is not shown. When the keyboard is shown, there's no need
3824 // to add the mask and the original top padding value should be kept.
3825 actualTopPadding = SCROLL_MASK_HEIGHT;
3826 this.showScrollMask();
3827 }
3828
3829 // Start positioning of the small pods inside the smallPodsContainer.
3830 var topPadding = actualTopPadding;
3831 var lastPod = undefined;
3832 for (var pod of pods) {
3833 if (pod == this.mainPod_) {
3834 continue;
3835 }
3836 pod.left = SCROLL_LEFT_PADDING;
3837 pod.top = topPadding;
3838 topPadding += CROS_EXTRA_SMALL_POD_HEIGHT + EXTRA_SMALL_POD_PADDING;
3839 lastPod = pod;
3840 }
3841 // Make sure the last pod has a proper bottom padding for a symmetric
3842 // layout.
3843 lastPod.style.paddingBottom = cr.ui.toCssPx(actualTopPadding);
3844 },
3845
3846 /**
3847 * Called each time before pod placement to ensure we start with the
3848 * initial state, which is ready to place only one user pod. The styles
3849 * of elements necessary for other placement methods must be set
3850 * explicitly each time.
3851 * @private
3852 */
3853 restoreInitialStates_: function() {
3854 this.smallPodsContainer.hidden = true;
3855 document.querySelector('.small-pod-container-mask').hidden = true;
3856 document.querySelector('.small-pod-container-mask.rotate').hidden = true;
3857 this.smallPodsContainer.classList.remove('scroll');
3858 var pods = this.pods;
3859 for (var pod of pods) {
3860 // There is a chance that one of the pods has a bottom padding, so
3861 // reset all of them to be safe. This is because if the pod was at
3862 // the last position in the scrollable container, a bottom padding
3863 // was added to ensure a symmetric layout.
3864 pod.style.paddingBottom = cr.ui.toCssPx(0);
3865 }
3866 },
3867
3868 /**
3869 * Check if the screen is in portrait mode.
3870 * @return {boolean} True if in portrait mode.
3871 */
3872 isPortraitMode: function() {
3873 return this.screenSize.width <
3874 this.screenSize.height;
3875 },
3876
3877 /**
3878 * Called when scroll bar is shown and we need a mask for the header bar.
3879 * @private
3880 */
3881 showScrollMask: function() {
3882 var topMask = document.querySelector('.small-pod-container-mask');
3883 topMask.hidden = false;
3884 topMask.style.left = this.smallPodsContainer.style.left;
3885 topMask.style.width = this.smallPodsContainer.style.width;
3886 // The bottom mask is a rotation of the top mask.
3887 var bottomMask =
3888 document.querySelector('.small-pod-container-mask.rotate');
3889 bottomMask.hidden = false;
3890 bottomMask.style.left = this.smallPodsContainer.style.left;
3891 bottomMask.style.width = this.smallPodsContainer.style.width;
3892 // The bottom mask should overlap with the header bar, and its z-index
3893 // is chosen to ensure it does not block users from using the header bar.
3894 bottomMask.style.top = cr.ui.toCssPx(
3895 this.screenSize.height -
3896 SCROLL_MASK_HEIGHT);
3897 },
3898
3899 /**
3900 * Makes sure that user name on each large pod is centered and extra long
3901 * name does not exceed max width. Names on small pods do not need to be
3902 * dynamically updated.
3903 * @private
3904 */
3905 updatePodNameArea: function() {
3906 this.querySelectorAll('.name-container').forEach(function(nameArea) {
3907 var nameElement = nameArea.querySelector('.name');
3908 var leftMargin = (CROS_POD_WIDTH - nameElement.offsetWidth) / 2;
3909 if (leftMargin > 0)
3910 nameArea.style.left = cr.ui.toCssPx(leftMargin);
3911 else
3912 nameElement.style.width = cr.ui.toCssPx(CROS_POD_WIDTH);
3481 }); 3913 });
3482 Oobe.getInstance().updateScreenSize(this.parentNode); 3914 },
3483 }, 3915
3484 3916 /**
3485 /** 3917 * Called when a small or extra small pod is clicked to trigger the switch
3918 * with the main pod.
3919 */
3920 switchMainPod: function(pod) {
3921 if (this.disabled) {
3922 console.error('Cannot change main pod while sign-in UI is disabled.');
3923 return;
3924 }
3925 if (!this.mainPod_) {
3926 console.error('Attempt to switch a non-existing main pod.');
3927 return;
3928 }
3929 // Find the index of the small pod.
3930 var insert = 0;
3931 var children = pod.parentNode.children;
3932 while (insert < children.length && children[insert] != pod)
3933 insert++;
3934 if (insert >= children.length) {
3935 console.error('Attempt to switch a non-existing small pod.');
3936 return;
3937 }
3938 // Switch style of the two pods.
3939 this.mainPod_.setPodStyle(pod.getPodStyle());
3940 pod.setPodStyle(UserPod.Style.LARGE);
3941
3942 // Switch parent and position of the two pods.
3943 var left = pod.left;
3944 var top = pod.top;
3945 // Edge case: paddingBottom should be switched too because there's a
3946 // chance that the small pod was at the end of the scrollable container
3947 // and had a non-zero paddingBottom.
3948 var paddingBottom = pod.style.paddingBottom;
3949 var parent = pod.parentNode;
3950 parent.removeChild(pod);
3951 this.appendChild(pod);
3952 pod.left = this.mainPod_.left;
3953 pod.top = this.mainPod_.top;
3954 pod.style.paddingBottom = cr.ui.toCssPx(0);
3955
3956 this.removeChild(this.mainPod_);
3957 // It must have the same index with the original small pod, instead
3958 // of being appended as the last child, in order to maintain the 'Tab'
3959 // order.
3960 parent.insertBefore(this.mainPod_, children[insert]);
3961 this.mainPod_.left = left;
3962 this.mainPod_.top = top;
3963 this.mainPod_.style.paddingBottom = paddingBottom;
3964 this.mainPod_ = pod;
3965 // Focus the new main pod.
3966 this.focusPod(this.mainPod_);
3967 this.updatePodNameArea();
3968 },
3969
3970 /**
3971 * Returns dimensions of screen including the header bar.
3972 * @type {Object}
3973 */
3974 get screenSize() {
3975 var container = $('scroll-container');
3976 return {width: container.offsetWidth, height: container.offsetHeight};
3977 },
3978
3979 /**
3486 * Number of columns. 3980 * Number of columns.
3487 * @type {?number} 3981 * @type {?number}
3488 */ 3982 */
3489 set columns(columns) { 3983 set columns(columns) {
3490 // Cannot use 'columns' here. 3984 // Cannot use 'columns' here.
3491 this.setAttribute('ncolumns', columns); 3985 this.setAttribute('ncolumns', columns);
3492 }, 3986 },
3493 get columns() { 3987 get columns() {
3494 return parseInt(this.getAttribute('ncolumns')); 3988 return parseInt(this.getAttribute('ncolumns'));
3495 }, 3989 },
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
3796 if (e.target.classList.contains('focused')) { 4290 if (e.target.classList.contains('focused')) {
3797 if (!e.target.multiProfilesPolicyApplied) 4291 if (!e.target.multiProfilesPolicyApplied)
3798 e.target.focusInput(); 4292 e.target.focusInput();
3799 else 4293 else
3800 e.target.userTypeBubbleElement.classList.add('bubble-shown'); 4294 e.target.userTypeBubbleElement.classList.add('bubble-shown');
3801 } else 4295 } else
3802 this.focusPod(e.target); 4296 this.focusPod(e.target);
3803 return; 4297 return;
3804 } 4298 }
3805 4299
4300 // Small pods do not have input box.
4301 if (e.target.parentNode == this.smallPodsContainer) {
4302 this.focusPod(e.target, false, true /* opt_skipInputFocus */);
4303 return;
4304 }
4305
3806 var pod = findAncestorByClass(e.target, 'pod'); 4306 var pod = findAncestorByClass(e.target, 'pod');
3807 if (pod && pod.parentNode == this) { 4307 if (pod && pod.parentNode == this) {
3808 // Focus on a control of a pod but not on the action area button. 4308 // Focus on a control of a pod but not on the action area button.
3809 if (!pod.classList.contains('focused')) { 4309 if (!pod.classList.contains('focused')) {
3810 if (e.target.classList.contains('action-box-area') || 4310 if (e.target.classList.contains('action-box-area') ||
3811 e.target.classList.contains('remove-warning-button')) { 4311 e.target.classList.contains('remove-warning-button')) {
3812 // focusPod usually moves focus on the password input box which 4312 // focusPod usually moves focus on the password input box which
3813 // triggers virtual keyboard to show up. But the focus may move to a 4313 // triggers virtual keyboard to show up. But the focus may move to a
3814 // non text input element shortly by e.target.focus. Hence, a 4314 // non text input element shortly by e.target.focus. Hence, a
3815 // virtual keyboard flicking might be observed. We need to manually 4315 // virtual keyboard flicking might be observed. We need to manually
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
3956 return; 4456 return;
3957 } 4457 }
3958 4458
3959 this.podsWithPendingImages_.splice(index, 1); 4459 this.podsWithPendingImages_.splice(index, 1);
3960 if (this.podsWithPendingImages_.length == 0) { 4460 if (this.podsWithPendingImages_.length == 0) {
3961 this.classList.remove('images-loading'); 4461 this.classList.remove('images-loading');
3962 } 4462 }
3963 }, 4463 },
3964 4464
3965 /** 4465 /**
3966 * Makes sure user name is centered in each pod and extra long name
3967 * does not exceed max width.
3968 */
3969 updatePodNameArea: function() {
3970 this.querySelectorAll('.name-container').forEach(function(nameArea) {
3971 var nameElement = nameArea.querySelector('.name');
3972 var leftMargin = (CROS_POD_WIDTH - nameElement.offsetWidth) / 2;
3973 if (leftMargin > 0)
3974 nameArea.style.left = leftMargin + 'px';
3975 else
3976 nameElement.style.width = CROS_POD_WIDTH + 'px';
3977 });
3978 },
3979
3980 /**
3981 * Preselects pod, if needed. 4466 * Preselects pod, if needed.
3982 */ 4467 */
3983 maybePreselectPod: function() { 4468 maybePreselectPod: function() {
3984 var pod = this.preselectedPod; 4469 var pod = this.preselectedPod;
3985 this.focusPod(pod); 4470 this.focusPod(pod);
3986 4471
3987 // Hide user-type-bubble in case all user pods are disabled and we focus 4472 // Hide user-type-bubble in case all user pods are disabled and we focus
3988 // first pod. 4473 // first pod.
3989 if (pod && pod.multiProfilesPolicyApplied) { 4474 if (pod && pod.multiProfilesPolicyApplied) {
3990 pod.userTypeBubbleElement.classList.remove('bubble-shown'); 4475 pod.userTypeBubbleElement.classList.remove('bubble-shown');
3991 } 4476 }
3992 } 4477 }
3993 }; 4478 };
3994 4479
3995 return { 4480 return {
3996 PodRow: PodRow 4481 PodRow: PodRow
3997 }; 4482 };
3998 }); 4483 });
OLDNEW
« no previous file with comments | « ui/login/account_picker/md_user_pod_row.css ('k') | ui/login/account_picker/md_user_pod_template.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698