Index: ui/login/account_picker/md_user_pod_row.js |
diff --git a/ui/login/account_picker/md_user_pod_row.js b/ui/login/account_picker/md_user_pod_row.js |
index 8a03bd902f31700709697ef4635569db27ceb41e..5ba328648f4bae1226037de08777696ba2f37e2e 100644 |
--- a/ui/login/account_picker/md_user_pod_row.js |
+++ b/ui/login/account_picker/md_user_pod_row.js |
@@ -8,43 +8,6 @@ |
cr.define('login', function() { |
/** |
- * Number of displayed columns depending on user pod count. |
- * @type {Array<number>} |
- * @const |
- */ |
- var COLUMNS = [0, 1, 2, 3, 4, 5, 4, 4, 4, 5, 5, 6, 6, 5, 5, 6, 6, 6, 6]; |
- |
- /** |
- * Mapping between number of columns in pod-row and margin between user pods |
- * for such layout. |
- * @type {Array<number>} |
- * @const |
- */ |
- var MARGIN_BY_COLUMNS = [undefined, 40, 40, 40, 40, 40, 12]; |
- |
- /** |
- * Mapping between number of columns in the desktop pod-row and margin |
- * between user pods for such layout. |
- * @type {Array<number>} |
- * @const |
- */ |
- var DESKTOP_MARGIN_BY_COLUMNS = [undefined, 32, 32, 32, 32, 32, 32]; |
- |
- /** |
- * Maximal number of columns currently supported by pod-row. |
- * @type {number} |
- * @const |
- */ |
- var MAX_NUMBER_OF_COLUMNS = 6; |
- |
- /** |
- * Maximal number of rows if sign-in banner is displayed alonside. |
- * @type {number} |
- * @const |
- */ |
- var MAX_NUMBER_OF_ROWS_UNDER_SIGNIN_BANNER = 2; |
- |
- /** |
* Variables used for pod placement processing. Width and height should be |
* synced with computed CSS sizes of pods. |
*/ |
@@ -65,6 +28,7 @@ cr.define('login', function() { |
var CUSTOM_ICON_CONTAINER_SIZE = 40; |
var CROS_PIN_POD_HEIGHT = 417; |
var SCROLL_MASK_HEIGHT = 112; |
+ var BANNER_MESSAGE_WIDTH = 520; |
/** |
* The maximum number of users that each pod placement method can handle. |
@@ -984,7 +948,7 @@ cr.define('login', function() { |
* @type {!HTMLImageElement} |
*/ |
get smallPodImageElement() { |
- return this.querySelector('.small-pod-image'); |
+ return this.querySelector('.user-image.small-pod-image'); |
}, |
/** |
@@ -1221,7 +1185,7 @@ cr.define('login', function() { |
return UserPod.Style.LARGE; |
if (this.querySelector('.small-pod').classList.contains('extra-small')) |
return UserPod.Style.EXTRA_SMALL; |
- return UserPod.Style.SMALL; |
+ return UserPod.Style.SMALL; |
}, |
/** |
@@ -1416,19 +1380,6 @@ cr.define('login', function() { |
// Invisible focus causes ChromeVox to read user name and email. |
this.actionBoxMenuTitleElement.tabIndex = UserPodTabOrder.POD_MENU_ITEM; |
this.actionBoxMenuTitleElement.focus(); |
- |
- // If the user pod is on either edge of the screen, then the menu |
- // could be displayed partially ofscreen. |
- this.actionBoxMenu.classList.remove('left-edge-offset'); |
- this.actionBoxMenu.classList.remove('right-edge-offset'); |
- |
- var offsetLeft = |
- cr.ui.login.DisplayManager.getOffset(this.actionBoxMenu).left; |
- var menuWidth = this.actionBoxMenu.offsetWidth; |
- if (offsetLeft < 0) |
- this.actionBoxMenu.classList.add('left-edge-offset'); |
- else if (offsetLeft + menuWidth > window.innerWidth) |
- this.actionBoxMenu.classList.add('right-edge-offset'); |
} else { |
this.actionBoxAreaElement.classList.remove('active'); |
this.actionBoxAreaElement.classList.remove('menu-moved-up'); |
@@ -2135,6 +2086,7 @@ cr.define('login', function() { |
$('pod-row').switchMainPod(this); |
return; |
} |
+ Oobe.clearErrors(); |
if (!this.isActionBoxMenuActive) { |
if (this.isAuthTypeOnlineSignIn) { |
@@ -2407,6 +2359,7 @@ cr.define('login', function() { |
$('pod-row').switchMainPod(this); |
return; |
} |
+ Oobe.clearErrors(); |
this.parentNode.focusPod(this); |
this.parentNode.setActivatedPod(this, e); |
@@ -2868,6 +2821,9 @@ cr.define('login', function() { |
// If we're in Touch View mode. |
touchViewEnabled_: false, |
+ // If testing mode is enabled. |
+ testingModeEnabled_: false, |
+ |
/** @override */ |
decorate: function() { |
// Event listeners that are installed for the time period during which |
@@ -3503,88 +3459,10 @@ cr.define('login', function() { |
* screen orientation and showing the virtual keyboard. |
*/ |
onWindowResize: function() { |
- var screen = document.querySelector('#scroll-container'); |
- var clientArea = document.querySelector('#inner-container'); |
- if (Oobe.getInstance().virtualKeyboardShown) { |
- // Edge case: when virtual keyboard is shown, although the screen size |
- // is reduced properly, the size of the outer container remains the |
- // same because its min-height is applied. Users can scroll the screen |
- // upward and see empty areas beyond the pod row and the scroll bar, |
- // which should be avoided. |
- // This is a hacky solution: we can make the scroll container hide |
- // the overflow area and manully position the client area. |
- screen.style.overflowY = "hidden"; |
- clientArea.style.position = "absolute"; |
- clientArea.style.left = cr.ui.toCssPx(0); |
- clientArea.style.top = cr.ui.toCssPx(0); |
- } else { |
- // Sets the values to default when virtual keyboard is not shown. |
- screen.style.overflowY = "auto"; |
- clientArea.style.position = "relative"; |
- } |
this.placePods_(); |
}, |
/** |
- * Returns width of podrow having |columns| number of columns. |
- * @private |
- */ |
- columnsToWidth_: function(columns) { |
- var isDesktopUserManager = Oobe.getInstance().displayType == |
- DISPLAY_TYPE.DESKTOP_USER_MANAGER; |
- var margin = isDesktopUserManager ? DESKTOP_MARGIN_BY_COLUMNS[columns] : |
- MARGIN_BY_COLUMNS[columns]; |
- var rowPadding = isDesktopUserManager ? DESKTOP_ROW_PADDING : |
- POD_ROW_PADDING; |
- return 2 * rowPadding + columns * this.userPodWidth_ + |
- (columns - 1) * margin; |
- }, |
- |
- /** |
- * Returns height of podrow having |rows| number of rows. |
- * @private |
- */ |
- rowsToHeight_: function(rows) { |
- var isDesktopUserManager = Oobe.getInstance().displayType == |
- DISPLAY_TYPE.DESKTOP_USER_MANAGER; |
- var rowPadding = isDesktopUserManager ? DESKTOP_ROW_PADDING : |
- POD_ROW_PADDING; |
- return 2 * rowPadding + rows * this.userPodHeight_; |
- }, |
- |
- /** |
- * Calculates number of columns and rows that podrow should have in order to |
- * hold as much its pods as possible for current screen size. Also it tries |
- * to choose layout that looks good. |
- * @return {{columns: number, rows: number}} |
- */ |
- calculateLayout_: function() { |
- var preferredColumns = this.pods.length < COLUMNS.length ? |
- COLUMNS[this.pods.length] : COLUMNS[COLUMNS.length - 1]; |
- var maxWidth = Oobe.getInstance().clientAreaSize.width; |
- var columns = preferredColumns; |
- while (maxWidth < this.columnsToWidth_(columns) && columns > 1) |
- --columns; |
- var rows = Math.floor((this.pods.length - 1) / columns) + 1; |
- if (getComputedStyle( |
- $('signin-banner'), null).getPropertyValue('display') != 'none') { |
- rows = Math.min(rows, MAX_NUMBER_OF_ROWS_UNDER_SIGNIN_BANNER); |
- } |
- if (!Oobe.getInstance().newDesktopUserManager) { |
- var maxHeigth = Oobe.getInstance().clientAreaSize.height; |
- while (maxHeigth < this.rowsToHeight_(rows) && rows > 1) |
- --rows; |
- } |
- // One more iteration if it's not enough cells to place all pods. |
- while (maxWidth >= this.columnsToWidth_(columns + 1) && |
- columns * rows < this.pods.length && |
- columns < MAX_NUMBER_OF_COLUMNS) { |
- ++columns; |
- } |
- return {columns: columns, rows: rows}; |
- }, |
- |
- /** |
* Places pods onto their positions in pod grid matching the new design. |
* @private |
*/ |
@@ -3594,7 +3472,7 @@ cr.define('login', function() { |
console.error('Attempt to place pods for an empty pod list.'); |
return; |
} |
- // Append all pods to their proper parents. Small pods have parent other |
+ // Appends all pods to their proper parents. Small pods have parent other |
// than the pod row. The pods were all initialized with the pow row as a |
// temporary parent, which is intended to ensure that all event listeners |
// work properly. If the main pod already exists, it means we are in the |
@@ -3602,16 +3480,21 @@ cr.define('login', function() { |
// of any pod. |
if (!this.mainPod_) { |
this.mainPod_ = this.preselectedPod; |
- this.appendPodsToParents(); |
+ this.appendPodsToParents_(); |
} |
this.restoreInitialStates_(); |
- if (Oobe.getInstance().virtualKeyboardShown) { |
+ this.hideEmptyArea_(); |
+ // Clear error bubbles whenever pod placement is happening, i.e., after |
+ // orientation change, showing or hiding virtual keyboard, and user |
+ // removal. |
+ Oobe.clearErrors(); |
+ |
+ if (this.isScreenShrinked_()) { |
// When virtual keyboard is shown, the account picker should occupy |
// all the remaining screen. Screen size was already updated to exclude |
// the virtual keyboard. |
this.parentNode.setPreferredSize( |
- this.screenSize.width, |
- this.screenSize.height); |
+ this.screenSize.width, this.screenSize.height); |
} else { |
// Make sure not to block the header bar when virtual keyboard is absent. |
this.parentNode.setPreferredSize( |
@@ -3627,14 +3510,14 @@ cr.define('login', function() { |
this.placePodsOnContainer_(); |
} |
Oobe.getInstance().updateScreenSize(this.parentNode); |
- this.updatePodNameArea(); |
+ this.updatePodNameArea_(); |
}, |
/** |
- * Append pods to proper parents. Called each time before pod placement. |
+ * Appends pods to proper parents. Called each time before pod placement. |
* @private |
*/ |
- appendPodsToParents: function() { |
+ appendPodsToParents_: function() { |
var pods = this.pods; |
// Pod count may have changed, so the placement method may change |
// accordingly. Therefore, always remove all pods from their current |
@@ -3651,16 +3534,42 @@ cr.define('login', function() { |
// main pod still has pow row as parent, all other pods should be |
// appended to the container with scroll bar. |
for (var pod of pods) { |
- if (pod == this.mainPod_) { |
+ if (pod == this.mainPod_) |
this.appendChild(pod); |
- } else { |
+ else |
this.smallPodsContainer.appendChild(pod); |
- } |
} |
} |
}, |
/** |
+ * Makes inner container unscrollable and hides the bottom empty area |
+ * when virtual keyboard is shown. |
+ * @private |
+ */ |
+ hideEmptyArea_: function() { |
+ var screen = document.querySelector('#scroll-container'); |
+ var clientArea = document.querySelector('#inner-container'); |
+ if (this.isScreenShrinked_()) { |
+ // When virtual keyboard is shown, although the screen size |
+ // is reduced properly, the size of the outer container remains the |
+ // same because its min-height is applied. Users can scroll the screen |
+ // upward and see empty areas beyond the pod row and the scroll bar, |
+ // which should be avoided. |
+ // This is a hacky solution: we can make the scroll container hide |
+ // the overflow area and manully position the client area. |
+ screen.style.overflowY = 'hidden'; |
+ clientArea.style.position = 'absolute'; |
+ clientArea.style.left = cr.ui.toCssPx(0); |
+ clientArea.style.top = cr.ui.toCssPx(0); |
+ } else { |
+ // Sets the values to default when virtual keyboard is not shown. |
+ screen.style.overflowY = 'auto'; |
+ clientArea.style.position = 'relative'; |
+ } |
+ }, |
+ |
+ /** |
* Called when there is one user pod. |
* @private |
*/ |
@@ -3681,8 +3590,10 @@ cr.define('login', function() { |
this.mainPod_.setPodStyle(UserPod.Style.LARGE); |
secondPod.setPodStyle(UserPod.Style.LARGE); |
- var DOUBLE_PODS_PADDING = this.isPortraitMode() ? 32 : 118; |
- var leftPadding = (this.screenSize.width - (CROS_POD_WIDTH * 2 + DOUBLE_PODS_PADDING)) / 2; |
+ var DOUBLE_PODS_PADDING = this.isPortraitMode_() ? 32 : 118; |
+ var leftPadding = |
+ (this.screenSize.width - (CROS_POD_WIDTH * 2 + DOUBLE_PODS_PADDING)) / |
+ 2; |
// Start actual positioning. |
this.mainPod_.left = leftPadding; |
this.mainPod_.top = (this.screenSize.height - CROS_POD_HEIGHT) / 2; |
@@ -3697,8 +3608,8 @@ cr.define('login', function() { |
placePodsOnContainer_: function() { |
this.smallPodsContainer.hidden = false; |
var pods = this.pods; |
- if ((pods.length > LANDSCAPE_MODE_LIMIT && !this.isPortraitMode()) || |
- (pods.length > PORTRAIT_MODE_LIMIT && this.isPortraitMode())) { |
+ if ((pods.length > LANDSCAPE_MODE_LIMIT && !this.isPortraitMode_()) || |
+ (pods.length > PORTRAIT_MODE_LIMIT && this.isPortraitMode_())) { |
// If the pod count exceeds limits, they should be in extra small size |
// and the container will become scrollable. |
this.placePodsOnScrollableContainer_(); |
@@ -3711,31 +3622,46 @@ cr.define('login', function() { |
pod.setPodStyle(UserPod.Style.SMALL); |
} |
} |
- // The size of the smallPodsContainer must be updated to avoid overflow, |
- // otherwise unnecessary scroll bar will show up. |
+ // The size of the smallPodsContainer must be updated to avoid overflow. |
this.smallPodsContainer.style.height = |
cr.ui.toCssPx(this.screenSize.height); |
this.smallPodsContainer.style.width = cr.ui.toCssPx(CROS_SMALL_POD_WIDTH); |
- var LEFT_PADDING = this.isPortraitMode() ? 0 : 98; |
- var MIDDLE_PADDING = this.isPortraitMode() ? 84 : 220; |
+ var LEFT_PADDING = this.isPortraitMode_() ? 0 : 98; |
+ var MIDDLE_PADDING = this.isPortraitMode_() ? 84 : 220; |
var contentsWidth = LEFT_PADDING + |
CROS_POD_WIDTH + MIDDLE_PADDING + CROS_SMALL_POD_WIDTH; |
var blankWidth = this.screenSize.width - contentsWidth; |
var actualLeftPadding = LEFT_PADDING; |
- actualLeftPadding += this.isPortraitMode() ? blankWidth * 2 / 3: |
- blankWidth / 2; |
+ actualLeftPadding += |
+ this.isPortraitMode_() ? blankWidth * 2 / 3 : blankWidth / 2; |
var SMALL_POD_PADDING = 54; |
var actualSmallPodPadding = SMALL_POD_PADDING; |
var smallPodsTotalHeight = (pods.length - 1) * CROS_SMALL_POD_HEIGHT + |
(pods.length - 2) * actualSmallPodPadding; |
- if (smallPodsTotalHeight > this.screenSize.height) { |
- // Edge case: when the virtual keyboard is present, the total height of |
- // the smallPodsContainer may exceed the screen height. Decrease the |
- // padding among small pods according to the design spec. |
- actualSmallPodPadding = 32; |
- smallPodsTotalHeight = (pods.length - 1) * CROS_SMALL_POD_HEIGHT + |
- (pods.length - 2) * actualSmallPodPadding; |
+ |
+ var SCROLL_TOP_PADDING = this.isPortraitMode_() ? 66 : 72; |
+ if (smallPodsTotalHeight + SCROLL_TOP_PADDING * 2 > |
+ this.screenSize.height) { |
+ // Edge case: the design spec assumes that the screen height is large |
+ // enough if the pod count limits set above are not exceeded, but for |
+ // smaller screens the contents may still overflow. |
+ // SCROLL_TOP_PADDING denotes the smallest top padding we can tolerate |
+ // before allowing the container to overflow and show the scroll bar. |
+ // If virtual keyboard is shown, we will first try a smaller padding |
+ // and recalculate the total height. |
+ if (this.isScreenShrinked_()) { |
+ actualSmallPodPadding = 32; |
+ smallPodsTotalHeight = (pods.length - 1) * CROS_SMALL_POD_HEIGHT + |
+ (pods.length - 2) * actualSmallPodPadding; |
+ } |
+ // If virtual keyboard is not shown, or the updated total height still |
+ // exceeds screen height, fall to the scrollable container case. |
+ if (smallPodsTotalHeight + SCROLL_TOP_PADDING * 2 > |
+ this.screenSize.height) { |
+ this.placePodsOnScrollableContainer_(); |
+ return; |
+ } |
} |
// Start positioning of the main pod and the smallPodsContainer. |
@@ -3745,7 +3671,8 @@ cr.define('login', function() { |
cr.ui.toCssPx(actualLeftPadding + CROS_POD_WIDTH + MIDDLE_PADDING); |
this.smallPodsContainer.style.top = cr.ui.toCssPx(0); |
// Start positioning of the small pods inside the smallPodsContainer. |
- var smallPodsTopPadding = (this.screenSize.height - smallPodsTotalHeight) / 2; |
+ var smallPodsTopPadding = |
+ (this.screenSize.height - smallPodsTotalHeight) / 2; |
for (var pod of pods) { |
if (pod == this.mainPod_) { |
continue; |
@@ -3774,14 +3701,14 @@ cr.define('login', function() { |
} |
} |
- var SCROLL_LEFT_PADDING = this.isPortraitMode() ? 46 : 72; |
- var SCROLL_RIGHT_PADDING = this.isPortraitMode() ? 12 : 72; |
+ var SCROLL_LEFT_PADDING = this.isPortraitMode_() ? 46 : 72; |
+ var SCROLL_RIGHT_PADDING = this.isPortraitMode_() ? 12 : 72; |
// The offsetWidth of the smallPodsContainer. |
var scrollAreaWidth = SCROLL_LEFT_PADDING + CROS_EXTRA_SMALL_POD_WIDTH + |
SCROLL_RIGHT_PADDING; |
var mainPodPadding = (this.screenSize.width - |
scrollAreaWidth - CROS_POD_WIDTH) / 2; |
- var SCROLL_TOP_PADDING = this.isPortraitMode() ? 66 : 72; |
+ var SCROLL_TOP_PADDING = this.isPortraitMode_() ? 66 : 72; |
var EXTRA_SMALL_POD_PADDING = 32; |
// Start positioning of the main pod and the smallPodsContainer. |
this.mainPod_.left = mainPodPadding; |
@@ -3801,7 +3728,8 @@ cr.define('login', function() { |
} |
scrollHeight -= EXTRA_SMALL_POD_PADDING; |
// The smallPodsContainer should occupy the full screen vertically. |
- this.smallPodsContainer.style.height = cr.ui.toCssPx(this.screenSize.height); |
+ this.smallPodsContainer.style.height = |
+ cr.ui.toCssPx(this.screenSize.height); |
this.smallPodsContainer.style.width = cr.ui.toCssPx( |
SCROLL_LEFT_PADDING + CROS_EXTRA_SMALL_POD_WIDTH + |
SCROLL_RIGHT_PADDING); |
@@ -3817,13 +3745,13 @@ cr.define('login', function() { |
// the overlay, but the top and bottom padding should be adjusted |
// to ensure a symmetric layout. |
actualTopPadding = (this.screenSize.height - scrollHeight) / 2; |
- } else if (!Oobe.getInstance().virtualKeyboardShown) { |
+ } else if (!this.isScreenShrinked_()) { |
// The scroll bar will definitely be shown if we reach here. A gradient |
// mask is applied to avoid blocking the header bar if the virtual |
// keyboard is not shown. When the keyboard is shown, there's no need |
// to add the mask and the original top padding value should be kept. |
actualTopPadding = SCROLL_MASK_HEIGHT; |
- this.showScrollMask(); |
+ this.showScrollMask_(); |
} |
// Start positioning of the small pods inside the smallPodsContainer. |
@@ -3862,23 +3790,36 @@ cr.define('login', function() { |
// the last position in the scrollable container, a bottom padding |
// was added to ensure a symmetric layout. |
pod.style.paddingBottom = cr.ui.toCssPx(0); |
+ // Remove the switch animation that might be added earlier. |
+ pod.imageElement.classList.remove('switch-image-animation'); |
+ pod.smallPodImageElement.classList.remove('switch-image-animation'); |
} |
}, |
/** |
- * Check if the screen is in portrait mode. |
+ * Checks if the screen is in portrait mode. |
* @return {boolean} True if in portrait mode. |
*/ |
- isPortraitMode: function() { |
- return this.screenSize.width < |
- this.screenSize.height; |
+ isPortraitMode_: function() { |
+ return this.screenSize.width < this.screenSize.height; |
+ }, |
+ |
+ /** |
+ * Checks if the screen is shrinked, i.e., when showing virtual keyboard. |
+ * We used to check Oobe.getInstance().virtualKeyboardShown directly |
+ * but there were occasional bugs because that value may not be updated yet |
+ * during pod placement. |
+ * @return {boolean} True if the screen is shrinked. |
+ */ |
+ isScreenShrinked_: function() { |
+ return this.screenSize.height <= Oobe.getInstance().clientAreaSize.height; |
}, |
/** |
* Called when scroll bar is shown and we need a mask for the header bar. |
* @private |
*/ |
- showScrollMask: function() { |
+ showScrollMask_: function() { |
var topMask = document.querySelector('.small-pod-container-mask'); |
topMask.hidden = false; |
topMask.style.left = this.smallPodsContainer.style.left; |
@@ -3891,26 +3832,55 @@ cr.define('login', function() { |
bottomMask.style.width = this.smallPodsContainer.style.width; |
// The bottom mask should overlap with the header bar, and its z-index |
// is chosen to ensure it does not block users from using the header bar. |
- bottomMask.style.top = cr.ui.toCssPx( |
- this.screenSize.height - |
- SCROLL_MASK_HEIGHT); |
+ bottomMask.style.top = |
+ cr.ui.toCssPx(this.screenSize.height - SCROLL_MASK_HEIGHT); |
}, |
/** |
- * Makes sure that user name on each large pod is centered and extra long |
- * name does not exceed max width. Names on small pods do not need to be |
- * dynamically updated. |
+ * Makes sure that: |
+ * 1) User name on each large pod is centered. |
+ * 2) Extra long names don't exceed maximum pod width. |
+ * 3) Action box menus are either left-aligned or right-aligned with |
+ * the drop down button. |
* @private |
*/ |
- updatePodNameArea: function() { |
- this.querySelectorAll('.name-container').forEach(function(nameArea) { |
- var nameElement = nameArea.querySelector('.name'); |
- var leftMargin = (CROS_POD_WIDTH - nameElement.offsetWidth) / 2; |
+ updatePodNameArea_: function() { |
+ var pods = this.pods; |
+ for (var pod of pods) { |
+ if (pods.length > POD_ROW_LIMIT && pod != this.mainPod_) |
+ continue; |
+ var nameArea = pod.querySelector('.name-container'); |
+ var leftMargin = (CROS_POD_WIDTH - pod.nameElement.offsetWidth) / 2; |
if (leftMargin > 0) |
nameArea.style.left = cr.ui.toCssPx(leftMargin); |
- else |
- nameElement.style.width = cr.ui.toCssPx(CROS_POD_WIDTH); |
- }); |
+ else { |
+ pod.nameElement.style.width = cr.ui.toCssPx(CROS_POD_WIDTH); |
+ nameArea.style.left = cr.ui.toCssPx(0); |
+ } |
+ // Update action box menu position to ensure it doesn't overlap with |
+ // elements outside the pod. |
+ var actionBoxMenu = pod.querySelector('.action-box-menu'); |
+ var actionBoxButton = pod.querySelector('.action-box-button'); |
+ var MENU_TOP_PADDING = 7; |
+ actionBoxMenu.style.top = |
+ cr.ui.toCssPx(actionBoxButton.offsetHeight + MENU_TOP_PADDING); |
+ if (this.isPortraitMode_() && pods.length > 1) { |
+ // Confine the menu inside the pod when it may overlap with outside |
+ // elements. |
+ actionBoxMenu.style.left = 'auto'; |
+ actionBoxMenu.style.right = cr.ui.toCssPx(0); |
+ } else { |
+ actionBoxMenu.style.left = cr.ui.toCssPx( |
+ pod.nameElement.offsetWidth + actionBoxButton.style.marginLeft); |
+ actionBoxMenu.style.right = 'auto'; |
+ } |
+ // Add ripple animation. |
+ var actionBoxRippleEffect = |
+ pod.querySelector('.action-box-button.ripple-circle'); |
+ actionBoxRippleEffect.style.left = actionBoxMenu.style.left; |
+ actionBoxRippleEffect.style.top = |
+ cr.ui.toCssPx(actionBoxButton.style.marginTop); |
+ } |
}, |
/** |
@@ -3938,6 +3908,10 @@ cr.define('login', function() { |
// Switch style of the two pods. |
this.mainPod_.setPodStyle(pod.getPodStyle()); |
pod.setPodStyle(UserPod.Style.LARGE); |
+ // Add switch animation. |
+ this.mainPod_.smallPodImageElement.classList.add( |
+ 'switch-image-animation'); |
+ pod.imageElement.classList.add('switch-image-animation'); |
// Switch parent and position of the two pods. |
var left = pod.left; |
@@ -3962,9 +3936,10 @@ cr.define('login', function() { |
this.mainPod_.top = top; |
this.mainPod_.style.paddingBottom = paddingBottom; |
this.mainPod_ = pod; |
- // Focus the new main pod. |
- this.focusPod(this.mainPod_); |
- this.updatePodNameArea(); |
+ // The new main pod should already be focused but we need a focus update |
+ // in order to focus on the input box. |
+ this.focusPod(this.mainPod_, true /* force */); |
+ this.updatePodNameArea_(); |
}, |
/** |
@@ -3977,27 +3952,26 @@ cr.define('login', function() { |
}, |
/** |
- * Number of columns. |
- * @type {?number} |
- */ |
- set columns(columns) { |
- // Cannot use 'columns' here. |
- this.setAttribute('ncolumns', columns); |
- }, |
- get columns() { |
- return parseInt(this.getAttribute('ncolumns')); |
- }, |
- |
- /** |
- * Number of rows. |
- * @type {?number} |
+ * Displays a banner containing |message|. If the banner is already present |
+ * this function updates the message in the banner. |
+ * @param {string} message Text to be displayed or empty to hide the banner. |
*/ |
- set rows(rows) { |
- // Cannot use 'rows' here. |
- this.setAttribute('nrows', rows); |
- }, |
- get rows() { |
- return parseInt(this.getAttribute('nrows')); |
+ showBannerMessage: function(message) { |
+ var banner = $('signin-banner'); |
+ banner.textContent = message; |
+ banner.classList.toggle('message-set', !!message); |
+ var bannerContainer = $('signin-banner-container1'); |
+ var BANNER_TOP_PADDING = this.isScreenShrinked_() ? 0 : 38; |
+ bannerContainer.style.top = cr.ui.toCssPx( |
+ this.mainPod_.top + CROS_POD_HEIGHT + BANNER_TOP_PADDING); |
+ if (this.pods.length <= POD_ROW_LIMIT) |
+ bannerContainer.style.left = |
+ cr.ui.toCssPx((this.screenSize.width - BANNER_MESSAGE_WIDTH) / 2); |
+ else { |
+ var leftPadding = |
+ this.mainPod_.left - (BANNER_MESSAGE_WIDTH - CROS_POD_WIDTH) / 2; |
+ bannerContainer.style.left = cr.ui.toCssPx(Math.max(leftPadding, 0)); |
+ } |
}, |
/** |
@@ -4079,7 +4053,6 @@ cr.define('login', function() { |
chrome.send('focusPod', [podToFocus.user.username]); |
this.firstShown_ = false; |
this.lastFocusedPod_ = podToFocus; |
- this.scrollFocusedPodIntoView(); |
this.setUserPodFingerprintIcon( |
podToFocus.user.username, FINGERPRINT_STATES.DEFAULT); |
} else { |
@@ -4114,11 +4087,42 @@ cr.define('login', function() { |
console.error('Cannot activate pod while sign-in UI is disabled.'); |
return; |
} |
+ // If testing mode is enabled and a positive integer was entered, abort |
+ // the activation process and start testing mode. |
+ if (pod && this.testingModeEnabled_) { |
+ var userCount = pod.passwordElement.value; |
+ if (parseInt(userCount) == userCount && userCount > 0) { |
+ this.showDummyUsersForTesting(userCount); |
+ return; |
+ } |
+ } |
if (pod && pod.activate(e)) |
this.activatedPod_ = pod; |
}, |
/** |
+ * Used for testing only. Create the specified number of dummy users and |
+ * conveniently test the behaviors under different number of pods. |
+ * @param {number} count The number of users we want to test for. |
+ */ |
+ showDummyUsersForTesting: function(count) { |
+ if (!this.testingModeEnabled_) { |
+ console.error( |
+ 'Attempt to create dummy users when testing mode is disabled.'); |
+ return; |
+ } |
+ var pods = this.pods; |
+ for (var pod of pods) |
+ pod.parentNode.removeChild(pod); |
+ var sampleUser = this.users_[0]; |
+ var users = []; |
+ for (var i = 0; i < count; i++) |
+ users.push(sampleUser); |
+ |
+ this.loadPods(users); |
+ }, |
+ |
+ /** |
* The pod of the signed-in user, if any; null otherwise. |
* @type {?UserPod} |
*/ |
@@ -4235,14 +4239,18 @@ cr.define('login', function() { |
this.focusPod(); |
} |
- if (pod) |
+ if (pod && pod.getPodStyle() == UserPod.Style.LARGE) |
pod.isActionBoxMenuHovered = true; |
// Return focus back to single pod. |
if (this.alwaysFocusSinglePod && !pod) { |
if ($('login-header-bar').contains(e.target)) |
return; |
- this.focusPod(this.focusedPod_, true /* force */); |
+ // If the click is outside the single pod, still focus on that pod |
+ // but do not focus on input box any more. This makes virtual keyboard |
+ // (if present) disappear. |
+ this.focusPod( |
+ this.focusedPod_, true /* force */, true /* opt_skipInputFocus */); |
this.focusedPod_.userTypeBubbleElement.classList.remove('bubble-shown'); |
this.focusedPod_.isActionBoxMenuHovered = false; |
} |
@@ -4286,8 +4294,12 @@ cr.define('login', function() { |
if (this.disabled) |
return; |
if (e.target.parentNode == this) { |
- // Focus on a pod |
+ // Handles focus event on a large pod. |
if (e.target.classList.contains('focused')) { |
+ // Edge case: prevent input box from receiving unncessary focus |
+ // (thus hiding virtual keyboard) when remove user is clicked. |
+ if (e.target.isActionBoxMenuActive) |
+ return; |
if (!e.target.multiProfilesPolicyApplied) |
e.target.focusInput(); |
else |
@@ -4433,7 +4445,7 @@ cr.define('login', function() { |
this.maybePreselectPod(); |
} |
- this.updatePodNameArea(); |
+ this.updatePodNameArea_(); |
}, |
/** |