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

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 and add corner case handling for virtual keyboard Created 3 years, 7 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 */
1192 set podStyle(style) {
1193 this.setPodStyle_(style);
1194 },
1195
1196 /**
1197 * Gets the pod style.
1198 * @type {UserPod.Style}
1199 */
1200 get podStyle() {
1201 return this.getPodStyle_();
1202 },
1203
1204 /**
1205 * Helper function to set the pod style.
1206 * @private
1207 */
1208 setPodStyle_: function(style) {
1209 switch (style) {
1210 case UserPod.Style.LARGE:
1211 this.querySelector('.large-pod').hidden = false;
1212 this.querySelector('.small-pod').hidden = true;
1213 break;
1214 case UserPod.Style.SMALL:
1215 this.querySelector('.large-pod').hidden = true;
1216 this.querySelector('.small-pod').hidden = false;
1217 this.querySelector('.small-pod').classList.remove('extra-small');
1218 break;
1219 case UserPod.Style.EXTRA_SMALL:
1220 this.querySelector('.large-pod').hidden = true;
1221 this.querySelector('.small-pod').hidden = false;
1222 this.querySelector('.small-pod').classList.add('extra-small');
1223 break;
1224 default:
1225 console.error("Attempt to set an invalid pod style.");
1226 break;
1227 }
1228 },
1229
1230 /**
1231 * Helper function to get the pod style.
1232 * @type {UserPod.Style}
1233 * @private
1234 */
1235 getPodStyle_: function() {
1236 if (this.querySelector('.small-pod').hidden)
1237 return UserPod.Style.LARGE;
1238 if (this.querySelector('.small-pod').classList.contains('extra-small'))
1239 return UserPod.Style.EXTRA_SMALL;
1240 return UserPod.Style.SMALL;
1241 },
1242
1243 /**
1146 * Updates the user pod element. 1244 * Updates the user pod element.
1147 */ 1245 */
1148 update: function() { 1246 update: function() {
1149 this.imageElement.src = 'chrome://userimage/' + this.user.username + 1247 var imageSrc = 'chrome://userimage/' + this.user.username +
1150 '?id=' + UserPod.userImageSalt_[this.user.username]; 1248 '?id=' + UserPod.userImageSalt_[this.user.username];
1249 this.imageElement.src = imageSrc;
1250 this.smallPodImageElement.src = imageSrc;
1151 1251
1152 this.nameElement.textContent = this.user_.displayName; 1252 this.nameElement.textContent = this.user_.displayName;
1253 this.smallPodNameElement.textContent = this.user_.displayName;
1153 this.reauthNameHintElement.textContent = this.user_.displayName; 1254 this.reauthNameHintElement.textContent = this.user_.displayName;
1154 this.classList.toggle('signed-in', this.user_.signedIn); 1255 this.classList.toggle('signed-in', this.user_.signedIn);
1155 1256
1156 if (this.isAuthTypeUserClick) 1257 if (this.isAuthTypeUserClick)
1157 this.passwordLabelElement.textContent = this.authValue; 1258 this.passwordLabelElement.textContent = this.authValue;
1158 1259
1159 this.updateActionBoxArea(); 1260 this.updateActionBoxArea();
1160 1261
1161 this.passwordElement.setAttribute('aria-label', loadTimeData.getStringF( 1262 this.passwordElement.setAttribute('aria-label', loadTimeData.getStringF(
1162 'passwordFieldAccessibleName', this.user_.emailAddress)); 1263 'passwordFieldAccessibleName', this.user_.emailAddress));
(...skipping 632 matching lines...) Expand 10 before | Expand all | Expand 10 after
1795 } 1896 }
1796 }, 1897 },
1797 1898
1798 /** 1899 /**
1799 * Refresh the message in the remove user warning dialog. 1900 * Refresh the message in the remove user warning dialog.
1800 * @param {string} profilePath The filepath of the URL (must be verified). 1901 * @param {string} profilePath The filepath of the URL (must be verified).
1801 * @param {string} message The message to be written. 1902 * @param {string} message The message to be written.
1802 * @param {number|string=} count The number or string to replace $1 in 1903 * @param {number|string=} count The number or string to replace $1 in
1803 * |message|. Can be omitted if $1 is not present in |message|. 1904 * |message|. Can be omitted if $1 is not present in |message|.
1804 */ 1905 */
1805 updateRemoveWarningDialogSetMessage_: function(profilePath, message, 1906 updateRemoveWarningDialogSetMessage_: function(
1806 count) { 1907 profilePath, message, count) {
1807 if (profilePath !== this.user.profilePath) 1908 if (profilePath !== this.user.profilePath)
1808 return; 1909 return;
1809 // Add localized messages where $1 will be replaced with 1910 // Add localized messages where $1 will be replaced with
1810 // <span class="total-count"></span> and $2 will be replaced with 1911 // <span class="total-count"></span> and $2 will be replaced with
1811 // <span class="email"></span>. 1912 // <span class="email"></span>.
1812 var element = this.querySelector('.action-box-remove-user-warning-text'); 1913 var element = this.querySelector('.action-box-remove-user-warning-text');
1813 element.textContent = ''; 1914 element.textContent = '';
1814 1915
1815 messageParts = message.split(/(\$[12])/); 1916 messageParts = message.split(/(\$[12])/);
1816 var numParts = messageParts.length; 1917 var numParts = messageParts.length;
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
1980 this.actionBoxMenuRemoveElement.tabIndex = -1; 2081 this.actionBoxMenuRemoveElement.tabIndex = -1;
1981 }, 2082 },
1982 2083
1983 /** 2084 /**
1984 * Handles mouse down event. It sets whether the user click auth will be 2085 * 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 2086 * 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. 2087 * was focused on the mouse down event starting the click.
1987 * @param {Event} e The mouse down event. 2088 * @param {Event} e The mouse down event.
1988 */ 2089 */
1989 handlePodMouseDown_: function(e) { 2090 handlePodMouseDown_: function(e) {
1990 this.userClickAuthAllowed_ = this.parentNode.isFocused(this); 2091 // Small pods do not have mouse down event.
2092 if (this.podStyle == UserPod.Style.LARGE)
2093 this.userClickAuthAllowed_ = this.parentNode.isFocused(this);
1991 }, 2094 },
1992 2095
1993 /** 2096 /**
1994 * Called when the input of the password element changes. Updates the submit 2097 * Called when the input of the password element changes. Updates the submit
1995 * button color and state and hides the error popup bubble. 2098 * button color and state and hides the error popup bubble.
1996 */ 2099 */
1997 updateInput_: function() { 2100 updateInput_: function() {
1998 var isEmpty = this.passwordElement.value.length == 0; 2101 var isEmpty = this.passwordElement.value.length == 0;
1999 if (this.submitButton) { 2102 if (this.submitButton) {
2000 this.submitButton.disabled = isEmpty; 2103 this.submitButton.disabled = isEmpty;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2037 }, 2140 },
2038 2141
2039 /** 2142 /**
2040 * Handles click event on a user pod. 2143 * Handles click event on a user pod.
2041 * @param {Event} e Click event. 2144 * @param {Event} e Click event.
2042 */ 2145 */
2043 handleClickOnPod_: function(e) { 2146 handleClickOnPod_: function(e) {
2044 if (this.parentNode.disabled) 2147 if (this.parentNode.disabled)
2045 return; 2148 return;
2046 2149
2150 if (this.podStyle != UserPod.Style.LARGE) {
2151 // It should trigger the switch between the small pod and the main pod.
2152 $('pod-row').switchMainPod(this);
2153 return;
2154 }
2155
2047 if (!this.isActionBoxMenuActive) { 2156 if (!this.isActionBoxMenuActive) {
2048 if (this.isAuthTypeOnlineSignIn) { 2157 if (this.isAuthTypeOnlineSignIn) {
2049 this.showSigninUI(); 2158 this.showSigninUI();
2050 } else if (this.isAuthTypeUserClick && this.userClickAuthAllowed_) { 2159 } else if (this.isAuthTypeUserClick && this.userClickAuthAllowed_) {
2051 // Note that this.userClickAuthAllowed_ is set in mouse down event 2160 // Note that this.userClickAuthAllowed_ is set in mouse down event
2052 // handler. 2161 // handler.
2053 this.parentNode.setActivatedPod(this); 2162 this.parentNode.setActivatedPod(this);
2054 } else if (this.pinKeyboard && 2163 } else if (this.pinKeyboard &&
2055 e.target == this.pinKeyboard.submitButton) { 2164 e.target == this.pinKeyboard.submitButton) {
2056 // Sets the pod as activated if the submit button is clicked so that 2165 // 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. 2166 // it simulates what the enter button does for the password/pin.
2058 this.parentNode.setActivatedPod(this); 2167 this.parentNode.setActivatedPod(this);
2059 } 2168 }
2060 2169
2061 if (this.multiProfilesPolicyApplied) 2170 if (this.multiProfilesPolicyApplied)
2062 this.userTypeBubbleElement.classList.add('bubble-shown'); 2171 this.userTypeBubbleElement.classList.add('bubble-shown');
2063 2172
2064 // Prevent default so that we don't trigger 'focus' event and 2173 // Prevent default so that we don't trigger 'focus' event and
2065 // stop propagation so that the 'click' event does not bubble 2174 // stop propagation so that the 'click' event does not bubble
2066 // up and accidentally closes the bubble tooltip. 2175 // up and accidentally closes the bubble tooltip.
2067 stopEventPropagation(e); 2176 stopEventPropagation(e);
2068 } 2177 }
2069 }, 2178 },
2070 2179
2071 /** 2180 /**
2072 * Handles keydown event for a user pod. 2181 * Handles keydown event for a user pod.
2073 * @param {Event} e Key event. 2182 * @param {Event} e Key event.
2074 */ 2183 */
2075 handlePodKeyDown_: function(e) { 2184 handlePodKeyDown_: function(e) {
2185 if (this.podStyle != UserPod.Style.LARGE) {
2186 this.handleNonLargePodKeyDown_(e);
2187 return;
2188 }
2076 if (!this.isAuthTypeUserClick || this.disabled) 2189 if (!this.isAuthTypeUserClick || this.disabled)
2077 return; 2190 return;
2078 switch (e.key) { 2191 switch (e.key) {
2079 case 'Enter': 2192 case 'Enter':
2080 case ' ': 2193 case ' ':
2081 if (this.parentNode.isFocused(this)) 2194 if (this.parentNode.isFocused(this))
2082 this.parentNode.setActivatedPod(this); 2195 this.parentNode.setActivatedPod(this);
2083 break; 2196 break;
2084 } 2197 }
2198 },
2199
2200 /**
2201 * Handles keydown event for a small or extra small user pod.
2202 * @param {Event} e Key event.
2203 */
2204 handleNonLargePodKeyDown_: function(e) {
2205 switch (e.key) {
2206 case 'Enter':
2207 case ' ':
2208 if ($('pod-row').isFocused(this))
2209 $('pod-row').switchMainPod(this);
2210 break;
2211 }
2085 } 2212 }
2086 }; 2213 };
2087 2214
2088 /** 2215 /**
2089 * Creates a public account user pod. 2216 * Creates a public account user pod.
2090 * @constructor 2217 * @constructor
2091 * @extends {UserPod} 2218 * @extends {UserPod}
2092 */ 2219 */
2093 var PublicAccountUserPod = cr.ui.define(function() { 2220 var PublicAccountUserPod = cr.ui.define(function() {
2094 var node = UserPod(); 2221 var node = UserPod();
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
2286 this.focusInput(); 2413 this.focusInput();
2287 } 2414 }
2288 return true; 2415 return true;
2289 }, 2416 },
2290 2417
2291 /** @override */ 2418 /** @override */
2292 handleClickOnPod_: function(e) { 2419 handleClickOnPod_: function(e) {
2293 if (this.parentNode.disabled) 2420 if (this.parentNode.disabled)
2294 return; 2421 return;
2295 2422
2423 if (this.podStyle != UserPod.Style.LARGE) {
2424 // It should trigger the switch between the small pod and the main pod.
2425 $('pod-row').switchMainPod(this);
2426 return;
2427 }
2428
2296 this.parentNode.focusPod(this); 2429 this.parentNode.focusPod(this);
2297 this.parentNode.setActivatedPod(this, e); 2430 this.parentNode.setActivatedPod(this, e);
2298 // Prevent default so that we don't trigger 'focus' event. 2431 // Prevent default so that we don't trigger 'focus' event.
2299 e.preventDefault(); 2432 e.preventDefault();
2300 }, 2433 },
2301 2434
2302 /** 2435 /**
2303 * Updates the display name shown on the pod. 2436 * Updates the display name shown on the pod.
2304 * @param {string} displayName The new display name 2437 * @param {string} displayName The new display name
2305 */ 2438 */
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
2519 get mainInput() { 2652 get mainInput() {
2520 if (this.user.needsSignin) 2653 if (this.user.needsSignin)
2521 return this.passwordElement; 2654 return this.passwordElement;
2522 else 2655 else
2523 return this.nameElement; 2656 return this.nameElement;
2524 }, 2657 },
2525 2658
2526 /** @override */ 2659 /** @override */
2527 update: function() { 2660 update: function() {
2528 this.imageElement.src = this.user.userImage; 2661 this.imageElement.src = this.user.userImage;
2662 this.smallPodImageElement.src = this.user.userImage;
2529 this.nameElement.textContent = this.user.displayName; 2663 this.nameElement.textContent = this.user.displayName;
2664 this.smallPodNameElement.textContent = this.user.displayName;
2530 this.reauthNameHintElement.textContent = this.user.displayName; 2665 this.reauthNameHintElement.textContent = this.user.displayName;
2531 2666
2532 var isLockedUser = this.user.needsSignin; 2667 var isLockedUser = this.user.needsSignin;
2533 var isLegacySupervisedUser = this.user.legacySupervisedUser; 2668 var isLegacySupervisedUser = this.user.legacySupervisedUser;
2534 var isChildUser = this.user.childUser; 2669 var isChildUser = this.user.childUser;
2535 var isSyncedUser = this.user.emailAddress !== ""; 2670 var isSyncedUser = this.user.emailAddress !== "";
2536 var isProfileLoaded = this.user.isProfileLoaded; 2671 var isProfileLoaded = this.user.isProfileLoaded;
2537 this.classList.toggle('locked', isLockedUser); 2672 this.classList.toggle('locked', isLockedUser);
2538 this.classList.toggle('legacy-supervised', isLegacySupervisedUser); 2673 this.classList.toggle('legacy-supervised', isLegacySupervisedUser);
2539 this.classList.toggle('child', isChildUser); 2674 this.classList.toggle('child', isChildUser);
(...skipping 24 matching lines...) Expand all
2564 } 2699 }
2565 this.passwordElement.value = ''; 2700 this.passwordElement.value = '';
2566 return true; 2701 return true;
2567 }, 2702 },
2568 2703
2569 /** @override */ 2704 /** @override */
2570 handleClickOnPod_: function(e) { 2705 handleClickOnPod_: function(e) {
2571 if (this.parentNode.disabled) 2706 if (this.parentNode.disabled)
2572 return; 2707 return;
2573 2708
2709 if (this.podStyle != UserPod.Style.LARGE) {
2710 // It should trigger the switch between the small pod and the main pod.
2711 $('pod-row').switchMainPod(this);
2712 return;
2713 }
2714
2574 Oobe.clearErrors(); 2715 Oobe.clearErrors();
2575 this.parentNode.lastFocusedPod_ = this; 2716 this.parentNode.lastFocusedPod_ = this;
2576 2717
2577 // If this is a locked pod and there are local credentials, show the 2718 // 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 2719 // password field. Otherwise call activate() which will open up a browser
2579 // window or show the reauth dialog, as needed. 2720 // window or show the reauth dialog, as needed.
2580 if (!(this.user.needsSignin && this.user.hasLocalCreds) && 2721 if (!(this.user.needsSignin && this.user.hasLocalCreds) &&
2581 !this.isActionBoxMenuActive) { 2722 !this.isActionBoxMenuActive) {
2582 this.activate(e); 2723 this.activate(e);
2583 } 2724 }
(...skipping 21 matching lines...) Expand all
2605 UserPod.prototype.decorate.call(this); 2746 UserPod.prototype.decorate.call(this);
2606 this.launchAppButtonElement.addEventListener('click', 2747 this.launchAppButtonElement.addEventListener('click',
2607 this.activate.bind(this)); 2748 this.activate.bind(this));
2608 }, 2749 },
2609 2750
2610 /** @override */ 2751 /** @override */
2611 update: function() { 2752 update: function() {
2612 this.imageElement.src = this.user.iconUrl; 2753 this.imageElement.src = this.user.iconUrl;
2613 this.imageElement.alt = this.user.label; 2754 this.imageElement.alt = this.user.label;
2614 this.imageElement.title = this.user.label; 2755 this.imageElement.title = this.user.label;
2756 this.smallPodImageElement.src = this.user.iconUrl;
2757 this.smallPodImageElement.alt = this.user.label;
2758 this.smallPodImageElement.title = this.user.label;
2615 this.passwordEntryContainerElement.hidden = true; 2759 this.passwordEntryContainerElement.hidden = true;
2616 this.launchAppButtonContainerElement.hidden = false; 2760 this.launchAppButtonContainerElement.hidden = false;
2617 this.nameElement.textContent = this.user.label; 2761 this.nameElement.textContent = this.user.label;
2762 this.smallPodNameElement.textContent = this.user.label;
2618 this.reauthNameHintElement.textContent = this.user.label; 2763 this.reauthNameHintElement.textContent = this.user.label;
2619 2764
2620 UserPod.prototype.updateActionBoxArea.call(this); 2765 UserPod.prototype.updateActionBoxArea.call(this);
2621 UserPod.prototype.customizeUserPodPerUserType.call(this); 2766 UserPod.prototype.customizeUserPodPerUserType.call(this);
2622 }, 2767 },
2623 2768
2624 /** @override */ 2769 /** @override */
2625 get mainInput() { 2770 get mainInput() {
2626 return this.launchAppButtonElement; 2771 return this.launchAppButtonElement;
2627 }, 2772 },
(...skipping 16 matching lines...) Expand all
2644 var diagnosticMode = e && e.ctrlKey; 2789 var diagnosticMode = e && e.ctrlKey;
2645 this.launchApp_(this.user, diagnosticMode); 2790 this.launchApp_(this.user, diagnosticMode);
2646 return true; 2791 return true;
2647 }, 2792 },
2648 2793
2649 /** @override */ 2794 /** @override */
2650 handleClickOnPod_: function(e) { 2795 handleClickOnPod_: function(e) {
2651 if (this.parentNode.disabled) 2796 if (this.parentNode.disabled)
2652 return; 2797 return;
2653 2798
2799 if (this.podStyle != UserPod.Style.LARGE) {
2800 // It should trigger the switch between the small pod and the main pod.
2801 $('pod-row').switchMainPod(this);
2802 return;
2803 }
2804
2654 Oobe.clearErrors(); 2805 Oobe.clearErrors();
2655 this.parentNode.lastFocusedPod_ = this; 2806 this.parentNode.lastFocusedPod_ = this;
2656 this.activate(e); 2807 this.activate(e);
2657 }, 2808 },
2658 2809
2659 /** 2810 /**
2660 * Launch the app. If |diagnosticMode| is true, ask user to confirm. 2811 * Launch the app. If |diagnosticMode| is true, ask user to confirm.
2661 * @param {Object} app App data. 2812 * @param {Object} app App data.
2662 * @param {boolean} diagnosticMode Whether to run the app in diagnostic 2813 * @param {boolean} diagnosticMode Whether to run the app in diagnostic
2663 * mode. 2814 * mode.
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
2705 2856
2706 // Focused pod. 2857 // Focused pod.
2707 focusedPod_: undefined, 2858 focusedPod_: undefined,
2708 2859
2709 // Activated pod, i.e. the pod of current login attempt. 2860 // Activated pod, i.e. the pod of current login attempt.
2710 activatedPod_: undefined, 2861 activatedPod_: undefined,
2711 2862
2712 // Pod that was most recently focused, if any. 2863 // Pod that was most recently focused, if any.
2713 lastFocusedPod_: undefined, 2864 lastFocusedPod_: undefined,
2714 2865
2866 // Pod that occupies the main spot.
2867 mainPod_: undefined,
2868
2715 // Pods whose initial images haven't been loaded yet. 2869 // Pods whose initial images haven't been loaded yet.
2716 podsWithPendingImages_: [], 2870 podsWithPendingImages_: [],
2717 2871
2718 // Whether pod placement has been postponed. 2872 // Whether pod placement has been postponed.
2719 podPlacementPostponed_: false, 2873 podPlacementPostponed_: false,
2720 2874
2721 // Standard user pod height/width. 2875 // Standard user pod height/width.
2722 userPodHeight_: 0, 2876 userPodHeight_: 0,
2723 userPodWidth_: 0, 2877 userPodWidth_: 0,
2724 2878
(...skipping 27 matching lines...) Expand all
2752 isNewDesktopUserManager ? MD_DESKTOP_POD_HEIGHT : 2906 isNewDesktopUserManager ? MD_DESKTOP_POD_HEIGHT :
2753 DESKTOP_POD_HEIGHT : 2907 DESKTOP_POD_HEIGHT :
2754 CROS_POD_HEIGHT; 2908 CROS_POD_HEIGHT;
2755 this.userPodWidth_ = isDesktopUserManager ? 2909 this.userPodWidth_ = isDesktopUserManager ?
2756 isNewDesktopUserManager ? MD_DESKTOP_POD_WIDTH : 2910 isNewDesktopUserManager ? MD_DESKTOP_POD_WIDTH :
2757 DESKTOP_POD_WIDTH : 2911 DESKTOP_POD_WIDTH :
2758 CROS_POD_WIDTH; 2912 CROS_POD_WIDTH;
2759 }, 2913 },
2760 2914
2761 /** 2915 /**
2762 * Returns all the pods in this pod row. 2916 * Returns all the pods in this pod row. Some pods may not be its direct
2917 * children, but the caller doesn't have to know this.
2763 * @type {NodeList} 2918 * @type {NodeList}
2764 */ 2919 */
2765 get pods() { 2920 get pods() {
2766 return Array.prototype.slice.call(this.children); 2921 var powRowChildren = Array.prototype.slice.call(this.children);
2922 var containerChildren =
2923 Array.prototype.slice.call(this.smallPodsContainer.children);
2924 return powRowChildren.concat(containerChildren);
2767 }, 2925 },
2768 2926
2769 /** 2927 /**
2770 * Return true if user pod row has only single user pod in it, which should 2928 * 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. 2929 * always be focused except desktop and touch view modes.
2772 * @type {boolean} 2930 * @type {boolean}
2773 */ 2931 */
2774 get alwaysFocusSinglePod() { 2932 get alwaysFocusSinglePod() {
2775 var isDesktopUserManager = Oobe.getInstance().displayType == 2933 var isDesktopUserManager = Oobe.getInstance().displayType ==
2776 DISPLAY_TYPE.DESKTOP_USER_MANAGER; 2934 DISPLAY_TYPE.DESKTOP_USER_MANAGER;
2777 2935
2778 return (isDesktopUserManager || this.touchViewEnabled_) ? 2936 return (isDesktopUserManager || this.touchViewEnabled_) ?
2779 false : this.children.length == 1; 2937 false :
2938 this.pods.length == 1;
2780 }, 2939 },
2781 2940
2782 /** 2941 /**
2783 * Returns pod with the given app id. 2942 * Returns pod with the given app id.
2784 * @param {!string} app_id Application id to be matched. 2943 * @param {!string} app_id Application id to be matched.
2785 * @return {Object} Pod with the given app id. null if pod hasn't been 2944 * @return {Object} Pod with the given app id. null if pod hasn't been
2786 * found. 2945 * found.
2787 */ 2946 */
2788 getPodWithAppId_: function(app_id) { 2947 getPodWithAppId_: function(app_id) {
2789 for (var i = 0, pod; pod = this.pods[i]; ++i) { 2948 for (var i = 0, pod; pod = this.pods[i]; ++i) {
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
2946 /** 3105 /**
2947 * Removes user pod from pod row. 3106 * Removes user pod from pod row.
2948 * @param {!user} username 3107 * @param {!user} username
2949 */ 3108 */
2950 removeUserPod: function(username) { 3109 removeUserPod: function(username) {
2951 var podToRemove = this.getPodWithUsername_(username); 3110 var podToRemove = this.getPodWithUsername_(username);
2952 if (podToRemove == null) { 3111 if (podToRemove == null) {
2953 console.warn('Attempt to remove pod that does not exist'); 3112 console.warn('Attempt to remove pod that does not exist');
2954 return; 3113 return;
2955 } 3114 }
2956 this.removeChild(podToRemove); 3115 // Its parent is not necessarily this pod row.
2957 if (this.pods.length > 0) 3116 podToRemove.parentNode.removeChild(podToRemove);
3117 this.mainPod_ = null;
3118 if (this.pods.length > 0) {
3119 // placePods_() will select a new main pod and re-append pods
3120 // to different parents if necessary.
2958 this.placePods_(); 3121 this.placePods_();
3122 this.maybePreselectPod();
3123 }
2959 }, 3124 },
2960 3125
2961 /** 3126 /**
2962 * Returns index of given pod or -1 if not found. 3127 * Returns index of given pod or -1 if not found.
2963 * @param {UserPod} pod Pod to look up. 3128 * @param {UserPod} pod Pod to look up.
2964 * @private 3129 * @private
2965 */ 3130 */
2966 indexOf_: function(pod) { 3131 indexOf_: function(pod) {
2967 for (var i = 0; i < this.pods.length; ++i) { 3132 for (var i = 0; i < this.pods.length; ++i) {
2968 if (pod == this.pods[i]) 3133 if (pod == this.pods[i])
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
3013 * updated. 3178 * updated.
3014 */ 3179 */
3015 rebuildPods: function() { 3180 rebuildPods: function() {
3016 var emptyPodRow = this.pods.length == 0; 3181 var emptyPodRow = this.pods.length == 0;
3017 3182
3018 // Clear existing pods. 3183 // Clear existing pods.
3019 this.innerHTML = ''; 3184 this.innerHTML = '';
3020 this.focusedPod_ = undefined; 3185 this.focusedPod_ = undefined;
3021 this.activatedPod_ = undefined; 3186 this.activatedPod_ = undefined;
3022 this.lastFocusedPod_ = undefined; 3187 this.lastFocusedPod_ = undefined;
3188 this.mainPod_ = undefined;
3023 3189
3024 // Switch off animation 3190 // Switch off animation
3025 Oobe.getInstance().toggleClass('flying-pods', false); 3191 Oobe.getInstance().toggleClass('flying-pods', false);
3026 3192
3027 // Populate the pod row.
3028 for (var i = 0; i < this.users_.length; ++i) 3193 for (var i = 0; i < this.users_.length; ++i)
3029 this.addUserPod(this.users_[i]); 3194 this.addUserPod(this.users_[i]);
3030 3195
3031 for (var i = 0, pod; pod = this.pods[i]; ++i) 3196 for (var i = 0, pod; pod = this.pods[i]; ++i)
3032 this.podsWithPendingImages_.push(pod); 3197 this.podsWithPendingImages_.push(pod);
3033 3198
3034 // TODO(nkostylev): Edge case handling when kiosk apps are not fitting. 3199 // TODO(nkostylev): Edge case handling when kiosk apps are not fitting.
3035 if (this.shouldShowApps_) { 3200 if (this.shouldShowApps_) {
3036 for (var i = 0; i < this.apps_.length; ++i) 3201 for (var i = 0; i < this.apps_.length; ++i)
3037 this.addUserPod(this.apps_[i]); 3202 this.addUserPod(this.apps_[i]);
(...skipping 25 matching lines...) Expand all
3063 if ($('login-header-bar').signinUIState == 3228 if ($('login-header-bar').signinUIState ==
3064 SIGNIN_UI_STATE.GAIA_SIGNIN && 3229 SIGNIN_UI_STATE.GAIA_SIGNIN &&
3065 emptyPodRow && 3230 emptyPodRow &&
3066 this.pods.length > 0) { 3231 this.pods.length > 0) {
3067 login.GaiaSigninScreen.updateControlsState(); 3232 login.GaiaSigninScreen.updateControlsState();
3068 } 3233 }
3069 } 3234 }
3070 }, 3235 },
3071 3236
3072 /** 3237 /**
3238 * Gets the container of small pods.
3239 * @type {!HTMLDivElement}
3240 */
3241 get smallPodsContainer() {
3242 return document.querySelector('.small-pod-container');
3243 },
3244
3245 /**
3073 * Adds given apps to the pod row. 3246 * Adds given apps to the pod row.
3074 * @param {array} apps Array of apps. 3247 * @param {array} apps Array of apps.
3075 */ 3248 */
3076 setApps: function(apps) { 3249 setApps: function(apps) {
3077 this.apps_ = apps; 3250 this.apps_ = apps;
3078 this.rebuildPods(); 3251 this.rebuildPods();
3079 chrome.send('kioskAppsLoaded'); 3252 chrome.send('kioskAppsLoaded');
3080 3253
3081 // Check whether there's a pending kiosk app error. 3254 // Check whether there's a pending kiosk app error.
3082 window.setTimeout(function() { 3255 window.setTimeout(function() {
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
3315 }, 3488 },
3316 3489
3317 /** 3490 /**
3318 * Updates the list of locales available for a public session. 3491 * Updates the list of locales available for a public session.
3319 * @param {string} userID The user ID of the public session 3492 * @param {string} userID The user ID of the public session
3320 * @param {!Object} locales The list of available locales 3493 * @param {!Object} locales The list of available locales
3321 * @param {string} defaultLocale The locale to select by default 3494 * @param {string} defaultLocale The locale to select by default
3322 * @param {boolean} multipleRecommendedLocales Whether |locales| contains 3495 * @param {boolean} multipleRecommendedLocales Whether |locales| contains
3323 * two or more recommended locales 3496 * two or more recommended locales
3324 */ 3497 */
3325 setPublicSessionLocales: function(userID, 3498 setPublicSessionLocales: function(
3326 locales, 3499 userID, locales, defaultLocale, multipleRecommendedLocales) {
3327 defaultLocale,
3328 multipleRecommendedLocales) {
3329 var pod = this.getPodWithUsername_(userID); 3500 var pod = this.getPodWithUsername_(userID);
3330 if (pod != null) { 3501 if (pod != null) {
3331 pod.populateLanguageSelect(locales, 3502 pod.populateLanguageSelect(locales,
3332 defaultLocale, 3503 defaultLocale,
3333 multipleRecommendedLocales); 3504 multipleRecommendedLocales);
3334 } 3505 }
3335 }, 3506 },
3336 3507
3337 /** 3508 /**
3338 * Updates the list of available keyboard layouts for a public session pod. 3509 * Updates the list of available keyboard layouts for a public session pod.
3339 * @param {string} userID The user ID of the public session 3510 * @param {string} userID The user ID of the public session
3340 * @param {string} locale The locale to which this list of keyboard layouts 3511 * @param {string} locale The locale to which this list of keyboard layouts
3341 * applies 3512 * applies
3342 * @param {!Object} list List of available keyboard layouts 3513 * @param {!Object} list List of available keyboard layouts
3343 */ 3514 */
3344 setPublicSessionKeyboardLayouts: function(userID, locale, list) { 3515 setPublicSessionKeyboardLayouts: function(userID, locale, list) {
3345 var pod = this.getPodWithUsername_(userID); 3516 var pod = this.getPodWithUsername_(userID);
3346 if (pod != null) 3517 if (pod != null)
3347 pod.populateKeyboardSelect(locale, list); 3518 pod.populateKeyboardSelect(locale, list);
3348 }, 3519 },
3349 3520
3350 /** 3521 /**
3351 * Called when window was resized. 3522 * Called when window was resized. The two common use cases are changing
3523 * screen orientation and showing the virtual keyboard.
3352 */ 3524 */
3353 onWindowResize: function() { 3525 onWindowResize: function() {
3354 var layout = this.calculateLayout_(); 3526 var screen = document.querySelector('#scroll-container');
3355 if (layout.columns != this.columns || layout.rows != this.rows) 3527 var clientArea = document.querySelector('#inner-container');
3356 this.placePods_(); 3528 if (Oobe.getInstance().virtualKeyboardShown) {
3357 3529 // 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 3530 // is reduced properly, the size of the outer container remains the
jdufault 2017/05/24 20:44:52 Nice comment
Wenzhao (Colin) Zang 2017/05/24 21:36:37 :)
3359 // finished transitioning so that we work with the final pod dimensions. 3531 // 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 3532 // upward and see empty areas beyond the pod row and the scroll bar,
3361 // is called, we can call scrollFocusedPodIntoView() right away. 3533 // which should be avoided.
3362 var timeOut = 0; 3534 // This is a hacky solution: we can make the scroll container hide
3363 if (this.focusedPod_) { 3535 // the overflow area and manully position the client area.
3364 var style = getComputedStyle(this.focusedPod_); 3536 screen.style.overflowY = "hidden";
3365 timeOut = parseFloat(style.transitionDuration) * 1000; 3537 clientArea.style.position = "absolute";
3538 clientArea.style.left = cr.ui.toCssPx(0);
3539 clientArea.style.top = cr.ui.toCssPx(0);
3540 } else {
3541 // Sets the values to default when virtual keyboard is not shown.
3542 screen.style.overflowY = "auto";
3543 clientArea.style.position = "relative";
3366 } 3544 }
3367 3545 this.placePods_();
3368 setTimeout(function() {
3369 this.scrollFocusedPodIntoView();
3370 }.bind(this), timeOut);
3371 }, 3546 },
3372 3547
3373 /** 3548 /**
3374 * Returns width of podrow having |columns| number of columns. 3549 * Returns width of podrow having |columns| number of columns.
3375 * @private 3550 * @private
3376 */ 3551 */
3377 columnsToWidth_: function(columns) { 3552 columnsToWidth_: function(columns) {
3378 var isDesktopUserManager = Oobe.getInstance().displayType == 3553 var isDesktopUserManager = Oobe.getInstance().displayType ==
3379 DISPLAY_TYPE.DESKTOP_USER_MANAGER; 3554 DISPLAY_TYPE.DESKTOP_USER_MANAGER;
3380 var margin = isDesktopUserManager ? DESKTOP_MARGIN_BY_COLUMNS[columns] : 3555 var margin = isDesktopUserManager ? DESKTOP_MARGIN_BY_COLUMNS[columns] :
(...skipping 30 matching lines...) Expand all
3411 while (maxWidth < this.columnsToWidth_(columns) && columns > 1) 3586 while (maxWidth < this.columnsToWidth_(columns) && columns > 1)
3412 --columns; 3587 --columns;
3413 var rows = Math.floor((this.pods.length - 1) / columns) + 1; 3588 var rows = Math.floor((this.pods.length - 1) / columns) + 1;
3414 if (getComputedStyle( 3589 if (getComputedStyle(
3415 $('signin-banner'), null).getPropertyValue('display') != 'none') { 3590 $('signin-banner'), null).getPropertyValue('display') != 'none') {
3416 rows = Math.min(rows, MAX_NUMBER_OF_ROWS_UNDER_SIGNIN_BANNER); 3591 rows = Math.min(rows, MAX_NUMBER_OF_ROWS_UNDER_SIGNIN_BANNER);
3417 } 3592 }
3418 if (!Oobe.getInstance().newDesktopUserManager) { 3593 if (!Oobe.getInstance().newDesktopUserManager) {
3419 var maxHeigth = Oobe.getInstance().clientAreaSize.height; 3594 var maxHeigth = Oobe.getInstance().clientAreaSize.height;
3420 while (maxHeigth < this.rowsToHeight_(rows) && rows > 1) 3595 while (maxHeigth < this.rowsToHeight_(rows) && rows > 1)
3421 --rows; 3596 --rows;
3422 } 3597 }
3423 // One more iteration if it's not enough cells to place all pods. 3598 // One more iteration if it's not enough cells to place all pods.
3424 while (maxWidth >= this.columnsToWidth_(columns + 1) && 3599 while (maxWidth >= this.columnsToWidth_(columns + 1) &&
3425 columns * rows < this.pods.length && 3600 columns * rows < this.pods.length &&
3426 columns < MAX_NUMBER_OF_COLUMNS) { 3601 columns < MAX_NUMBER_OF_COLUMNS) {
3427 ++columns; 3602 ++columns;
3428 } 3603 }
3429 return {columns: columns, rows: rows}; 3604 return {columns: columns, rows: rows};
3430 }, 3605 },
3431 3606
3432 /** 3607 /**
3433 * Places pods onto their positions onto pod grid. 3608 * Places pods onto their positions in pod grid matching the new design.
3434 * @private 3609 * @private
3435 */ 3610 */
3436 placePods_: function() { 3611 placePods_: function() {
3437 var isDesktopUserManager = Oobe.getInstance().displayType == 3612 var pods = this.pods;
3438 DISPLAY_TYPE.DESKTOP_USER_MANAGER; 3613 if (pods.length == 0) {
3439 if (isDesktopUserManager && !Oobe.getInstance().userPodsPageVisible) 3614 console.error('Attempt to place pods for an empty pod list.');
3440 return; 3615 return;
3441 3616 }
3442 var layout = this.calculateLayout_(); 3617 // Append all pods to their proper parents. Small pods have parent other
3443 var columns = this.columns = layout.columns; 3618 // than the pod row. The pods were all initialized with the pow row as a
3444 var rows = this.rows = layout.rows; 3619 // temporary parent, which is intended to ensure that all event listeners
3445 var maxPodsNumber = columns * rows; 3620 // work properly. If the main pod already exists, it means we are in the
3446 var margin = isDesktopUserManager ? DESKTOP_MARGIN_BY_COLUMNS[columns] : 3621 // process of resizing the window, then there is no need to change parents
3447 MARGIN_BY_COLUMNS[columns]; 3622 // of any pod.
3448 this.parentNode.setPreferredSize( 3623 if (!this.mainPod_) {
3449 this.columnsToWidth_(columns), this.rowsToHeight_(rows)); 3624 this.mainPod_ = this.preselectedPod;
3450 var height = this.userPodHeight_; 3625 this.appendPodsToParents();
3451 var width = this.userPodWidth_; 3626 }
3452 var pinPodLocation = { column: columns + 1, row: rows + 1 }; 3627 this.restoreInitialStates_();
3453 if (this.focusedPod_ && this.focusedPod_.isPinShown()) 3628 if (Oobe.getInstance().virtualKeyboardShown) {
3454 pinPodLocation = this.findPodLocation_(this.focusedPod_, columns, rows); 3629 // When virtual keyboard is shown, the account picker should occupy
3455 3630 // all the remaining screen. Screen size was already updated to exclude
3456 this.pods.forEach(function(pod, index) { 3631 // the virtual keyboard.
3457 if (index >= maxPodsNumber) { 3632 this.parentNode.setPreferredSize(
3458 pod.hidden = true; 3633 this.screenSize.width,
3459 return; 3634 this.screenSize.height);
3460 } 3635 } else {
3461 pod.hidden = false; 3636 // Make sure not to block the header bar when virtual keyboard is absent .
3462 if (pod.offsetHeight != height && 3637 this.parentNode.setPreferredSize(
3463 pod.offsetHeight != CROS_PIN_POD_HEIGHT) { 3638 Oobe.getInstance().clientAreaSize.width,
3464 console.error('Pod offsetHeight (' + pod.offsetHeight + 3639 Oobe.getInstance().clientAreaSize.height);
3465 ') and POD_HEIGHT (' + height + ') are not equal.'); 3640 }
3466 } 3641
3467 if (pod.offsetWidth != width) { 3642 if (pods.length == 1) {
3468 console.error('Pod offsetWidth (' + pod.offsetWidth + 3643 this.placeSinglePod_();
3469 ') and POD_WIDTH (' + width + ') are not equal.'); 3644 } else if (pods.length == POD_ROW_LIMIT) {
3470 } 3645 this.placePodsOnPodRow_();
3471 var column = index % columns; 3646 } else {
3472 var row = Math.floor(index / columns); 3647 this.placePodsOnContainer_();
3473 3648 }
3474 var rowPadding = isDesktopUserManager ? DESKTOP_ROW_PADDING : 3649 Oobe.getInstance().updateScreenSize(this.parentNode);
3475 POD_ROW_PADDING; 3650 this.updatePodNameArea();
3476 pod.left = rowPadding + column * (width + margin); 3651 },
3477 3652
3478 // On desktop, we want the rows to always be equally spaced. 3653 /**
3479 pod.top = isDesktopUserManager ? row * (height + rowPadding) : 3654 * Append pods to proper parents. Called each time before pod placement.
3480 row * height + rowPadding; 3655 * @private
3656 */
3657 appendPodsToParents: function() {
3658 var pods = this.pods;
3659 // Pod count may have changed, so the placement method may change
3660 // accordingly. Therefore, always remove all pods from their current
3661 // parents first.
3662 for (var pod of pods) {
3663 pod.parentNode.removeChild(pod);
3664 }
3665 if (pods.length <= POD_ROW_LIMIT) {
3666 for (var pod of pods) {
3667 this.appendChild(pod);
3668 }
3669 } else {
3670 // When the user count exceeds the limit (currently set to 2), only the
3671 // main pod still has pow row as parent, all other pods should be
3672 // appended to the container with scroll bar.
3673 for (var pod of pods) {
3674 if (pod == this.mainPod_) {
3675 this.appendChild(pod);
3676 } else {
3677 this.smallPodsContainer.appendChild(pod);
3678 }
3679 }
3680 }
3681 },
3682
3683 /**
3684 * Called when there is one user pod.
3685 * @private
3686 */
3687 placeSinglePod_: function() {
3688 this.mainPod_.podStyle = UserPod.Style.LARGE;
3689 this.mainPod_.left = (this.screenSize.width - CROS_POD_WIDTH) / 2;
3690 this.mainPod_.top = (this.screenSize.height - CROS_POD_HEIGHT) / 2;
3691 },
3692
3693 /**
3694 * Called when there are two users pods.
3695 * @private
3696 */
3697 placePodsOnPodRow_: function() {
3698 // Both pods have large size and are placed adjacently.
3699 var secondPod =
3700 this.pods[0] == this.mainPod_ ? this.pods[1] : this.pods[0];
3701 this.mainPod_.podStyle = UserPod.Style.LARGE;
3702 secondPod.podStyle = UserPod.Style.LARGE;
3703
3704 var DOUBLE_PODS_PADDING = this.isPortraitMode() ? 32 : 118;
3705 var leftPadding = (this.screenSize.width - (CROS_POD_WIDTH * 2 + DOUBLE_PO DS_PADDING)) / 2;
3706 // Start actual positioning.
3707 this.mainPod_.left = leftPadding;
3708 this.mainPod_.top = (this.screenSize.height - CROS_POD_HEIGHT) / 2;
3709 secondPod.left = leftPadding + CROS_POD_WIDTH + DOUBLE_PODS_PADDING;
3710 secondPod.top = (this.screenSize.height - CROS_POD_HEIGHT) / 2;
3711 },
3712
3713 /**
3714 * Called when there are more than two user pods.
3715 * @private
3716 */
3717 placePodsOnContainer_: function() {
3718 this.smallPodsContainer.hidden = false;
3719 var pods = this.pods;
3720 if ((pods.length > LANDSCAPE_MODE_LIMIT && !this.isPortraitMode()) ||
3721 (pods.length > PORTRAIT_MODE_LIMIT && this.isPortraitMode())) {
3722 // If the pod count exceeds limits, they should be in extra small size
3723 // and the container will become scrollable.
3724 this.placePodsOnScrollableContainer_();
3725 return;
3726 }
3727 this.mainPod_.podStyle = UserPod.Style.LARGE;
3728 for (var pod of pods) {
3729 if (pod != this.mainPod_) {
3730 // All pods except the main one must be set to the small style.
3731 pod.podStyle = UserPod.Style.SMALL;
3732 }
3733 }
3734 // The size of the smallPodsContainer must be updated to avoid overflow,
3735 // otherwise unnecessary scroll bar will show up.
3736 this.smallPodsContainer.style.height =
3737 cr.ui.toCssPx(this.screenSize.height);
3738 this.smallPodsContainer.style.width = cr.ui.toCssPx(CROS_SMALL_POD_WIDTH);
3739
3740 var LEFT_PADDING = this.isPortraitMode() ? 0 : 98;
3741 var MIDDLE_PADDING = this.isPortraitMode() ? 84 : 220;
3742 var contentsWidth = LEFT_PADDING +
3743 CROS_POD_WIDTH + MIDDLE_PADDING + CROS_SMALL_POD_WIDTH;
3744 var blankWidth = this.screenSize.width - contentsWidth;
3745 var actualLeftPadding = LEFT_PADDING;
3746 actualLeftPadding += this.isPortraitMode() ? blankWidth * 2 / 3:
3747 blankWidth / 2;
3748 var SMALL_POD_PADDING = 54;
3749 var actualSmallPodPadding = SMALL_POD_PADDING;
3750 var smallPodsTotalHeight = (pods.length - 1) * CROS_SMALL_POD_HEIGHT +
3751 (pods.length - 2) * actualSmallPodPadding;
3752 if (smallPodsTotalHeight > this.screenSize.height) {
3753 // Edge case: when the virtual keyboard is present, the total height of
3754 // the smallPodsContainer may exceed the screen height. Decrease the
3755 // padding among small pods according to the design spec.
3756 actualSmallPodPadding = 32;
3757 smallPodsTotalHeight = (pods.length - 1) * CROS_SMALL_POD_HEIGHT +
3758 (pods.length - 2) * actualSmallPodPadding;
3759 }
3760
3761 // Start positioning of the main pod and the smallPodsContainer.
3762 this.mainPod_.left = actualLeftPadding;
3763 this.mainPod_.top = (this.screenSize.height - CROS_POD_HEIGHT) / 2;
3764 this.smallPodsContainer.style.left =
3765 cr.ui.toCssPx(actualLeftPadding + CROS_POD_WIDTH + MIDDLE_PADDING);
3766 this.smallPodsContainer.style.top = cr.ui.toCssPx(0);
3767 // Start positioning of the small pods inside the smallPodsContainer.
3768 var smallPodsTopPadding = (this.screenSize.height - smallPodsTotalHeight) / 2;
3769 for (var pod of pods) {
3770 if (pod == this.mainPod_) {
3771 continue;
3772 }
3773 pod.left = 0;
3774 pod.top = smallPodsTopPadding;
3775 smallPodsTopPadding += CROS_SMALL_POD_HEIGHT + actualSmallPodPadding;
3776 }
3777 },
3778
3779 /**
3780 * Called when there are more than 6 user pods in landscape mode, or more
3781 * than 10 user pods in portrait mode.
3782 * @private
3783 */
3784 placePodsOnScrollableContainer_: function() {
3785 this.smallPodsContainer.hidden = false;
3786 // Add a dark overlay.
3787 this.smallPodsContainer.classList.add('scroll');
3788 var pods = this.pods;
3789 this.mainPod_.podStyle = UserPod.Style.LARGE;
3790 for (var pod of pods) {
3791 if (pod != this.mainPod_) {
3792 // All pods except the main one must be set to the extra small style.
3793 pod.podStyle = UserPod.Style.EXTRA_SMALL;
3794 }
3795 }
3796
3797 var SCROLL_LEFT_PADDING = this.isPortraitMode() ? 46 : 72;
3798 var SCROLL_RIGHT_PADDING = this.isPortraitMode() ? 12 : 72;
3799 // The offsetWidth of the smallPodsContainer.
3800 var scrollAreaWidth = SCROLL_LEFT_PADDING + CROS_EXTRA_SMALL_POD_WIDTH +
3801 SCROLL_RIGHT_PADDING;
3802 var mainPodPadding = (this.screenSize.width -
3803 scrollAreaWidth - CROS_POD_WIDTH) / 2;
3804 var SCROLL_TOP_PADDING = this.isPortraitMode() ? 66 : 72;
3805 var EXTRA_SMALL_POD_PADDING = 32;
3806 // Start positioning of the main pod and the smallPodsContainer.
3807 this.mainPod_.left = mainPodPadding;
3808 this.mainPod_.top = (this.screenSize.height - CROS_POD_HEIGHT) / 2;
3809 this.smallPodsContainer.style.left =
3810 cr.ui.toCssPx(mainPodPadding * 2 + CROS_POD_WIDTH);
3811 this.smallPodsContainer.style.top = cr.ui.toCssPx(0);
3812
3813 // Precalculate the total height of the scrollable container and check if
3814 // it indeed exceeds the screen height.
3815 var scrollHeight = 0;
3816 for (var pod of pods) {
3817 if (pod == this.mainPod_) {
3818 continue;
3819 }
3820 scrollHeight += CROS_EXTRA_SMALL_POD_HEIGHT + EXTRA_SMALL_POD_PADDING;
3821 }
3822 scrollHeight -= EXTRA_SMALL_POD_PADDING;
3823 // The smallPodsContainer should occupy the full screen vertically.
3824 this.smallPodsContainer.style.height = cr.ui.toCssPx(this.screenSize.heigh t);
3825 this.smallPodsContainer.style.width = cr.ui.toCssPx(
3826 SCROLL_LEFT_PADDING + CROS_EXTRA_SMALL_POD_WIDTH +
3827 SCROLL_RIGHT_PADDING);
3828
3829 // SCROLL_TOP_PADDING denotes the smallest top padding we can tolerate
3830 // before allowing the container to overflow and show the scroll bar.
3831 var actualTopPadding = SCROLL_TOP_PADDING;
3832 if ((this.screenSize.height - scrollHeight) / 2 > actualTopPadding) {
3833 // Edge case: the total height of the scrollable container does not
3834 // exceed the screen height (minus the neceesary padding), so the
3835 // scroll bar will not appear.
3836 // In this case, we still want to keep the extra small pod size and
3837 // the overlay, but the top and bottom padding should be adjusted
3838 // to ensure a symmetric layout.
3839 actualTopPadding = (this.screenSize.height - scrollHeight) / 2;
3840 } else if (!Oobe.getInstance().virtualKeyboardShown) {
3841 // The scroll bar will definitely be shown if we reach here. A gradient
3842 // mask is applied to avoid blocking the header bar if the virtual
3843 // keyboard is not shown. When the keyboard is shown, there's no need
3844 // to add the mask and the original top padding value should be kept.
3845 actualTopPadding = SCROLL_MASK_HEIGHT;
3846 this.showScrollMask();
3847 }
3848
3849 // Start positioning of the small pods inside the smallPodsContainer.
3850 var topPadding = actualTopPadding;
3851 var lastPod = undefined;
3852 for (var pod of pods) {
3853 if (pod == this.mainPod_) {
3854 continue;
3855 }
3856 pod.left = SCROLL_LEFT_PADDING;
3857 pod.top = topPadding;
3858 topPadding += CROS_EXTRA_SMALL_POD_HEIGHT + EXTRA_SMALL_POD_PADDING;
3859 lastPod = pod;
3860 }
3861 // Make sure the last pod has a proper bottom padding for a symmetric
3862 // layout.
3863 lastPod.style.paddingBottom = cr.ui.toCssPx(actualTopPadding);
3864 },
3865
3866 /**
3867 * Called each time before pod placement to ensure we start with the
3868 * initial state, which is ready to place only one user pod. The styles
3869 * of elements necessary for other placement methods must be set
3870 * explicitly each time.
3871 * @private
3872 */
3873 restoreInitialStates_: function() {
3874 this.smallPodsContainer.hidden = true;
3875 document.querySelector('.small-pod-container-mask').hidden = true;
3876 document.querySelector('.small-pod-container-mask.rotate').hidden = true;
3877 this.smallPodsContainer.classList.remove('scroll');
3878 var pods = this.pods;
3879 for (var pod of pods) {
3880 // There is a chance that one of the pods has a bottom padding, so
3881 // reset all of them to be safe. This is because if the pod was at
3882 // the last position in the scrollable container, a bottom padding
3883 // was added to ensure a symmetric layout.
3884 pod.style.paddingBottom = cr.ui.toCssPx(0);
3885 }
3886 },
3887
3888 /**
3889 * Check if the screen is in portrait mode.
3890 * @return {boolean} True if in portrait mode.
3891 */
3892 isPortraitMode: function() {
3893 return this.screenSize.width <
3894 this.screenSize.height;
3895 },
3896
3897 /**
3898 * Called when scroll bar is shown and we need a mask for the header bar.
3899 * @private
3900 */
3901 showScrollMask: function() {
3902 var topMask = document.querySelector('.small-pod-container-mask');
3903 topMask.hidden = false;
3904 topMask.style.left = this.smallPodsContainer.style.left;
3905 topMask.style.width = this.smallPodsContainer.style.width;
3906 // The bottom mask is a rotation of the top mask.
3907 var bottomMask =
3908 document.querySelector('.small-pod-container-mask.rotate');
3909 bottomMask.hidden = false;
3910 bottomMask.style.left = this.smallPodsContainer.style.left;
3911 bottomMask.style.width = this.smallPodsContainer.style.width;
3912 // The bottom mask should overlap with the header bar, and its z-index
3913 // is chosen to ensure it does not block users from using the header bar.
3914 bottomMask.style.top = cr.ui.toCssPx(
3915 this.screenSize.height -
3916 SCROLL_MASK_HEIGHT);
3917 },
3918
3919 /**
3920 * Makes sure that user name on each large pod is centered and extra long
3921 * name does not exceed max width. Names on small pods do not need to be
3922 * dynamically updated.
3923 * @private
3924 */
3925 updatePodNameArea: function() {
3926 this.querySelectorAll('.name-container').forEach(function(nameArea) {
3927 var nameElement = nameArea.querySelector('.name');
3928 var leftMargin = (CROS_POD_WIDTH - nameElement.offsetWidth) / 2;
3929 if (leftMargin > 0)
3930 nameArea.style.left = cr.ui.toCssPx(leftMargin);
3931 else
3932 nameElement.style.width = cr.ui.toCssPx(CROS_POD_WIDTH);
3481 }); 3933 });
3482 Oobe.getInstance().updateScreenSize(this.parentNode); 3934 },
3483 }, 3935
3484 3936 /**
3485 /** 3937 * Called when a small pod is clicked to trigger the switch between the
3938 * small pod and the main pod.
3939 */
3940 switchMainPod: function(pod) {
3941 if (this.disabled) {
3942 console.error('Cannot change main pod while sign-in UI is disabled.');
jdufault 2017/05/24 20:44:52 I wonder if the entire sign-in screen is disabled,
Wenzhao (Colin) Zang 2017/05/24 21:36:37 This is for the pow row. Please see lines 2950 - 2
3943 return;
3944 }
3945 if (!this.mainPod_) {
3946 console.error('Attempt to switch a non-existing main pod.');
3947 return;
3948 }
3949 // Find the index of the small pod.
3950 var insert = 0;
3951 var children = pod.parentNode.children;
3952 while (insert < children.length && children[insert] != pod)
3953 insert++;
3954 if (insert >= children.length) {
3955 console.error('Attempt to switch a non-existing small pod.');
3956 return;
3957 }
3958 // Switch style of the two pods.
3959 this.mainPod_.podStyle = pod.podStyle;
3960 pod.podStyle = UserPod.Style.LARGE;
3961
3962 // Switch parent and position of the two pods.
3963 var left = pod.left;
3964 var top = pod.top;
3965 // Edge case: paddingBottom should be switched too because there's a
3966 // chance that the small pod was at the end of the scrollable container
3967 // and had a non-zero paddingBottom.
3968 var paddingBottom = pod.style.paddingBottom;
3969 var parent = pod.parentNode;
3970 parent.removeChild(pod);
3971 this.appendChild(pod);
3972 pod.left = this.mainPod_.left;
3973 pod.top = this.mainPod_.top;
3974 pod.style.paddingBottom = cr.ui.toCssPx(0);
3975
3976 this.removeChild(this.mainPod_);
3977 // It must have the same index with the original small pod, instead
3978 // of being appended as the last child, in order to maintain the 'Tab'
3979 // order.
3980 parent.insertBefore(this.mainPod_, children[insert]);
3981 this.mainPod_.left = left;
3982 this.mainPod_.top = top;
3983 this.mainPod_.style.paddingBottom = paddingBottom;
3984 this.mainPod_ = pod;
3985 // Focus the new main pod.
3986 this.focusPod(this.mainPod_);
3987 this.updatePodNameArea();
3988 },
3989
3990 /**
3991 * Returns dimensions of screen including the header bar.
3992 * @type {Object}
3993 */
3994 get screenSize() {
3995 var container = $('scroll-container');
3996 return {width: container.offsetWidth, height: container.offsetHeight};
3997 },
3998
3999 /**
3486 * Number of columns. 4000 * Number of columns.
3487 * @type {?number} 4001 * @type {?number}
3488 */ 4002 */
3489 set columns(columns) { 4003 set columns(columns) {
3490 // Cannot use 'columns' here. 4004 // Cannot use 'columns' here.
3491 this.setAttribute('ncolumns', columns); 4005 this.setAttribute('ncolumns', columns);
3492 }, 4006 },
3493 get columns() { 4007 get columns() {
3494 return parseInt(this.getAttribute('ncolumns')); 4008 return parseInt(this.getAttribute('ncolumns'));
3495 }, 4009 },
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
3796 if (e.target.classList.contains('focused')) { 4310 if (e.target.classList.contains('focused')) {
3797 if (!e.target.multiProfilesPolicyApplied) 4311 if (!e.target.multiProfilesPolicyApplied)
3798 e.target.focusInput(); 4312 e.target.focusInput();
3799 else 4313 else
3800 e.target.userTypeBubbleElement.classList.add('bubble-shown'); 4314 e.target.userTypeBubbleElement.classList.add('bubble-shown');
3801 } else 4315 } else
3802 this.focusPod(e.target); 4316 this.focusPod(e.target);
3803 return; 4317 return;
3804 } 4318 }
3805 4319
4320 // Small pods do not have input box.
4321 if (e.target.parentNode == this.smallPodsContainer) {
4322 this.focusPod(e.target, false, true /* opt_skipInputFocus */);
4323 return;
4324 }
4325
3806 var pod = findAncestorByClass(e.target, 'pod'); 4326 var pod = findAncestorByClass(e.target, 'pod');
3807 if (pod && pod.parentNode == this) { 4327 if (pod && pod.parentNode == this) {
3808 // Focus on a control of a pod but not on the action area button. 4328 // Focus on a control of a pod but not on the action area button.
3809 if (!pod.classList.contains('focused')) { 4329 if (!pod.classList.contains('focused')) {
3810 if (e.target.classList.contains('action-box-area') || 4330 if (e.target.classList.contains('action-box-area') ||
3811 e.target.classList.contains('remove-warning-button')) { 4331 e.target.classList.contains('remove-warning-button')) {
3812 // focusPod usually moves focus on the password input box which 4332 // focusPod usually moves focus on the password input box which
3813 // triggers virtual keyboard to show up. But the focus may move to a 4333 // 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 4334 // non text input element shortly by e.target.focus. Hence, a
3815 // virtual keyboard flicking might be observed. We need to manually 4335 // virtual keyboard flicking might be observed. We need to manually
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
3956 return; 4476 return;
3957 } 4477 }
3958 4478
3959 this.podsWithPendingImages_.splice(index, 1); 4479 this.podsWithPendingImages_.splice(index, 1);
3960 if (this.podsWithPendingImages_.length == 0) { 4480 if (this.podsWithPendingImages_.length == 0) {
3961 this.classList.remove('images-loading'); 4481 this.classList.remove('images-loading');
3962 } 4482 }
3963 }, 4483 },
3964 4484
3965 /** 4485 /**
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. 4486 * Preselects pod, if needed.
3982 */ 4487 */
3983 maybePreselectPod: function() { 4488 maybePreselectPod: function() {
3984 var pod = this.preselectedPod; 4489 var pod = this.preselectedPod;
3985 this.focusPod(pod); 4490 this.focusPod(pod);
3986 4491
3987 // Hide user-type-bubble in case all user pods are disabled and we focus 4492 // Hide user-type-bubble in case all user pods are disabled and we focus
3988 // first pod. 4493 // first pod.
3989 if (pod && pod.multiProfilesPolicyApplied) { 4494 if (pod && pod.multiProfilesPolicyApplied) {
3990 pod.userTypeBubbleElement.classList.remove('bubble-shown'); 4495 pod.userTypeBubbleElement.classList.remove('bubble-shown');
3991 } 4496 }
3992 } 4497 }
3993 }; 4498 };
3994 4499
3995 return { 4500 return {
3996 PodRow: PodRow 4501 PodRow: PodRow
3997 }; 4502 };
3998 }); 4503 });
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