| Index: ui/login/account_picker/user_pod_row.js
|
| diff --git a/ui/login/account_picker/user_pod_row.js b/ui/login/account_picker/user_pod_row.js
|
| index 194a3c6062713726f9f56ab612491d344b8756a4..39b5c7deb584276ab1a5769e32490ec3bf3abc69 100644
|
| --- a/ui/login/account_picker/user_pod_row.js
|
| +++ b/ui/login/account_picker/user_pod_row.js
|
| @@ -55,6 +55,7 @@ cr.define('login', function() {
|
| var DESKTOP_POD_HEIGHT = 226;
|
| var POD_ROW_PADDING = 10;
|
| var DESKTOP_ROW_PADDING = 15;
|
| + var CUSTOM_ICON_CONTAINER_SIZE = 40;
|
|
|
| /**
|
| * Minimal padding between user pod and virtual keyboard.
|
| @@ -159,6 +160,330 @@ cr.define('login', function() {
|
| }
|
|
|
| /**
|
| + * Creates an element for custom icon shown in a user pod next to the input
|
| + * field.
|
| + * @constructor
|
| + * @extends {HTMLDivElement}
|
| + */
|
| + var UserPodCustomIcon = cr.ui.define(function() {
|
| + var node = document.createElement('div');
|
| + node.classList.add('custom-icon-container');
|
| + node.hidden = true;
|
| +
|
| + // Create the actual icon element and add it as a child to the container.
|
| + var iconNode = document.createElement('div');
|
| + iconNode.classList.add('custom-icon');
|
| + node.appendChild(iconNode);
|
| + return node;
|
| + });
|
| +
|
| + UserPodCustomIcon.prototype = {
|
| + __proto__: HTMLDivElement.prototype,
|
| +
|
| + /**
|
| + * The icon height.
|
| + * @type {number}
|
| + * @private
|
| + */
|
| + height_: 0,
|
| +
|
| + /**
|
| + * The icon width.
|
| + * @type {number}
|
| + * @private
|
| + */
|
| + width_: 0,
|
| +
|
| + /**
|
| + * Tooltip to be shown when the user hovers over the icon. The icon
|
| + * properties may be set so the tooltip is shown automatically when the icon
|
| + * is updated. The tooltip is shown in a bubble attached to the icon
|
| + * element.
|
| + * @type {string}
|
| + * @private
|
| + */
|
| + tooltip_: '',
|
| +
|
| + /**
|
| + * Whether the tooltip is shown and the user is hovering over the icon.
|
| + * @type {boolean}
|
| + * @private
|
| + */
|
| + tooltipActive_: false,
|
| +
|
| + /**
|
| + * Whether the icon has been shown as a result of |autoshow| parameter begin
|
| + * set rather than user hovering over the icon.
|
| + * If this is set, the tooltip will not be removed when the mouse leaves the
|
| + * icon.
|
| + * @type {boolean}
|
| + * @private
|
| + */
|
| + tooltipAutoshown_: false,
|
| +
|
| + /**
|
| + * A reference to the timeout for showing tooltip after mouse enters the
|
| + * icon.
|
| + * @type {?number}
|
| + * @private
|
| + */
|
| + showTooltipTimeout_: null,
|
| +
|
| + /**
|
| + * If animation is set, the current horizontal background offset for the
|
| + * icon resource.
|
| + * @type {number}
|
| + * @private
|
| + */
|
| + lastAnimationOffset_: 0,
|
| +
|
| + /**
|
| + * The reference to interval for progressing the animation.
|
| + * @type {?number}
|
| + * @private
|
| + */
|
| + animationInterval_: null,
|
| +
|
| + /**
|
| + * The width of the resource that contains representations for different
|
| + * animation stages.
|
| + * @type {number}
|
| + * @private
|
| + */
|
| + animationResourceSize_: 0,
|
| +
|
| + /** @override */
|
| + decorate: function() {
|
| + this.iconElement.addEventListener('mouseover',
|
| + this.showTooltipSoon_.bind(this));
|
| + this.iconElement.addEventListener('mouseout',
|
| + this.hideTooltip_.bind(this, false));
|
| + this.iconElement.addEventListener('mousedown',
|
| + this.hideTooltip_.bind(this, false));
|
| + },
|
| +
|
| + /**
|
| + * Getter for the icon element's div.
|
| + * @return {HTMLDivElement}
|
| + */
|
| + get iconElement() {
|
| + return this.querySelector('.custom-icon');
|
| + },
|
| +
|
| + /**
|
| + * Set the icon's background image as image set with different
|
| + * representations for available screen scale factors.
|
| + * @param {!{scale1x: string, scale2x: string}} icon The icon
|
| + * representations.
|
| + */
|
| + setIconAsImageSet: function(icon) {
|
| + this.iconElement.style.backgroundImage =
|
| + '-webkit-image-set(' +
|
| + 'url(' + icon.scale1x + ') 1x,' +
|
| + 'url(' + icon.scale2x + ') 2x)';
|
| + },
|
| +
|
| + /**
|
| + * Sets the icon background image to a chrome://theme URL.
|
| + * @param {!string} iconUrl The icon's background image URL.
|
| + */
|
| + setIconAsResourceUrl: function(iconUrl) {
|
| + this.iconElement.style.backgroundImage =
|
| + '-webkit-image-set(' +
|
| + 'url(' + iconUrl + '@1x) 1x,' +
|
| + 'url(' + iconUrl + '@2x) 2x)';
|
| + },
|
| +
|
| + /**
|
| + * Shows the icon.
|
| + */
|
| + show: function() {
|
| + this.hidden = false;
|
| + },
|
| +
|
| + /**
|
| + * Hides the icon. Makes sure the tooltip is hidden and animation reset.
|
| + */
|
| + hide: function() {
|
| + this.hideTooltip_(true);
|
| + this.setAnimation(null);
|
| + this.hidden = true;
|
| + },
|
| +
|
| + /**
|
| + * Sets the icon size element size.
|
| + * @param {!{width: number, height: number}} size The icon size.
|
| + */
|
| + setSize: function(size) {
|
| + this.height_ = size.height < CUSTOM_ICON_CONTAINER_SIZE ?
|
| + size.height : CUSTOM_ICON_COTAINER_SIZE;
|
| + this.iconElement.style.height = this.height_ + 'px';
|
| +
|
| + this.width_ = size.width < CUSTOM_ICON_CONTAINER_SIZE ?
|
| + size.width : CUSTOM_ICON_COTAINER_SIZE;
|
| + this.iconElement.style.width = this.width_ + 'px';
|
| + this.style.width = this.width_ + 'px';
|
| + },
|
| +
|
| + /**
|
| + * Sets the icon opacity.
|
| + * @param {number} opacity The icon opacity in [0-100] scale.
|
| + */
|
| + setOpacity: function(opacity) {
|
| + if (opacity > 100) {
|
| + this.style.opacity = 1;
|
| + } else if (opacity < 0) {
|
| + this.style.opacity = 0;
|
| + } else {
|
| + this.style.opacity = opacity / 100;
|
| + }
|
| + },
|
| +
|
| + /**
|
| + * Updates the icon tooltip. If {@code autoshow} parameter is set the
|
| + * tooltip is immediatelly shown. If tooltip text is not set, the method
|
| + * ensures the tooltip gets hidden. If tooltip is shown prior to this call,
|
| + * it remains shown, but the tooltip text is updated.
|
| + * @param {!{text: string, autoshow: boolean}} tooltip The tooltip
|
| + * parameters.
|
| + */
|
| + setTooltip: function(tooltip) {
|
| + if (this.tooltip_ == tooltip.text && !tooltip.autoshow)
|
| + return;
|
| + this.tooltip_ = tooltip.text;
|
| +
|
| + // If tooltip is already shown, just update the text.
|
| + if (tooltip.text && this.tooltipActive_ && !$('bubble').hidden) {
|
| + // If both previous and the new tooltip are supposed to be shown
|
| + // automatically, keep the autoshown flag.
|
| + var markAutoshown = this.tooltipAutoshown_ && tooltip.autoshow;
|
| + this.hideTooltip_(true);
|
| + this.showTooltip_();
|
| + this.tooltipAutoshown_ = markAutoshown;
|
| + return;
|
| + }
|
| +
|
| + // If autoshow flag is set, make sure the tooltip gets shown.
|
| + if (tooltip.text && tooltip.autoshow) {
|
| + this.hideTooltip_(true);
|
| + this.showTooltip_();
|
| + this.tooltipAutoshown_ = true;
|
| + // Reset the tooltip active flag, which gets set in |showTooltip_|.
|
| + this.tooltipActive_ = false;
|
| + return;
|
| + }
|
| +
|
| + this.hideTooltip_(true);
|
| +
|
| + if (this.tooltip_)
|
| + this.iconElement.setAttribute('aria-lablel', this.tooltip_);
|
| + },
|
| +
|
| + /**
|
| + * Sets the icon animation parameter and starts the animation.
|
| + * The animation is set using the resource containing all animation frames
|
| + * concatenated horizontally. The animator offsets the background image in
|
| + * regural intervals.
|
| + * @param {?{resourceWidth: number, frameLengthMs: number}} animation
|
| + * |resourceWidth|: Total width for the resource containing the
|
| + * animation frames.
|
| + * |frameLengthMs|: Time interval for which a single animation frame is
|
| + * shown.
|
| + */
|
| + setAnimation: function(animation) {
|
| + if (this.animationInterval_)
|
| + clearInterval(this.animationInterval_);
|
| + this.iconElement.style.backgroundPosition = 'center';
|
| + if (!animation)
|
| + return;
|
| + this.lastAnimationOffset_ = 0;
|
| + this.animationResourceSize_ = animation.resourceWidth;
|
| + this.animationInterval_ = setInterval(this.progressAnimation_.bind(this),
|
| + animation.frameLengthMs);
|
| + },
|
| +
|
| + /**
|
| + * Called when mouse enters the icon. It sets timeout for showing the
|
| + * tooltip.
|
| + * @private
|
| + */
|
| + showTooltipSoon_: function() {
|
| + if (this.showTooltipTimeout_ || this.tooltipActive_)
|
| + return;
|
| + this.showTooltipTimeout_ =
|
| + setTimeout(this.showTooltip_.bind(this), 1000);
|
| + },
|
| +
|
| + /**
|
| + * Shows the current tooltip, if one is set.
|
| + * @private
|
| + */
|
| + showTooltip_: function() {
|
| + if (this.hidden || !this.tooltip_ || this.tooltipActive_)
|
| + return;
|
| +
|
| + // If autoshown bubble got hidden, clear the autoshown flag.
|
| + if ($('bubble').hidden && this.tooltipAutoshown_)
|
| + this.tooltipAutoshown_ = false;
|
| +
|
| + // Show the tooltip bubble.
|
| + var bubbleContent = document.createElement('div');
|
| + bubbleContent.textContent = this.tooltip_;
|
| +
|
| + /** @const */ var BUBBLE_OFFSET = CUSTOM_ICON_CONTAINER_SIZE / 2;
|
| + /** @const */ var BUBBLE_PADDING = 8;
|
| + $('bubble').showContentForElement(this,
|
| + cr.ui.Bubble.Attachment.RIGHT,
|
| + bubbleContent,
|
| + BUBBLE_OFFSET,
|
| + BUBBLE_PADDING);
|
| + this.ensureTooltipTimeoutCleared_();
|
| + this.tooltipActive_ = true;
|
| + },
|
| +
|
| + /**
|
| + * Hides the tooltip. If the current tooltip was automatically shown, it
|
| + * will be hidden only if |force| is set.
|
| + * @param {boolean} Whether the tooltip should be hidden if it got shown
|
| + * because autoshow flag was set.
|
| + * @private
|
| + */
|
| + hideTooltip_: function(force) {
|
| + this.tooltipActive_ = false;
|
| + this.ensureTooltipTimeoutCleared_();
|
| + if (!force && this.tooltipAutoshown_)
|
| + return;
|
| + $('bubble').hideForElement(this);
|
| + this.tooltipAutoshown_ = false;
|
| + this.iconElement.removeAttribute('aria-label');
|
| + },
|
| +
|
| + /**
|
| + * Clears timaout for showing the tooltip if it's set.
|
| + * @private
|
| + */
|
| + ensureTooltipTimeoutCleared_: function() {
|
| + if (this.showTooltipTimeout_) {
|
| + clearTimeout(this.showTooltipTimeout_);
|
| + this.showTooltipTimeout_ = null;
|
| + }
|
| + },
|
| +
|
| + /**
|
| + * Horizontally offsets the animated icon's background for a single icon
|
| + * size width.
|
| + * @private
|
| + */
|
| + progressAnimation_: function() {
|
| + this.lastAnimationOffset_ += this.width_;
|
| + if (this.lastAnimationOffset_ >= this.animationResourceSize_)
|
| + this.lastAnimationOffset_ = 0;
|
| + this.iconElement.style.backgroundPosition =
|
| + '-' + this.lastAnimationOffset_ + 'px center';
|
| + }
|
| + };
|
| +
|
| + /**
|
| * Unique salt added to user image URLs to prevent caching. Dictionary with
|
| * user names as keys.
|
| * @type {Object}
|
| @@ -198,6 +523,9 @@ cr.define('login', function() {
|
| this.actionBoxRemoveUserWarningButtonElement.addEventListener(
|
| 'keydown',
|
| this.handleRemoveUserConfirmationKeyDown_.bind(this));
|
| +
|
| + var customIcon = this.customIconElement;
|
| + customIcon.parentNode.replaceChild(new UserPodCustomIcon(), customIcon);
|
| },
|
|
|
| /**
|
| @@ -445,7 +773,7 @@ cr.define('login', function() {
|
| * @type {!HTMLDivElement}
|
| */
|
| get customIconElement() {
|
| - return this.querySelector('.custom-icon');
|
| + return this.querySelector('.custom-icon-container');
|
| },
|
|
|
| /**
|
| @@ -1843,8 +2171,14 @@ cr.define('login', function() {
|
| /**
|
| * Shows a custom icon on a user pod besides the input field.
|
| * @param {string} username Username of pod to add button
|
| - * @param {{scale1x: string, scale2x: string}} icon Dictionary of URLs of
|
| - * the custom icon's representations for 1x and 2x scale factors.
|
| + * @param {!{resourceUrl: (string | undefined),
|
| + * data: ({scale1x: string, scale2x: string} | undefined),
|
| + * size: ({width: number, height: number} | undefined),
|
| + * animation: ({resourceWidth: number, frameLength: number} |
|
| + * undefined),
|
| + * opacity: (number | undefined),
|
| + * tooltip: ({text: string, autoshow: boolean} | undefined)}} icon
|
| + * The icon parameters.
|
| */
|
| showUserPodCustomIcon: function(username, icon) {
|
| var pod = this.getPodWithUsername_(username);
|
| @@ -1854,11 +2188,22 @@ cr.define('login', function() {
|
| return;
|
| }
|
|
|
| - pod.customIconElement.hidden = false;
|
| - pod.customIconElement.style.backgroundImage =
|
| - '-webkit-image-set(' +
|
| - 'url(' + icon.scale1x + ') 1x,' +
|
| - 'url(' + icon.scale2x + ') 2x)';
|
| + if (icon.resourceUrl) {
|
| + pod.customIconElement.setIconAsResourceUrl(icon.resourceUrl);
|
| + } else if (icon.data) {
|
| + pod.customIconElement.setIconAsImageSet(icon.data);
|
| + } else {
|
| + return;
|
| + }
|
| +
|
| + pod.customIconElement.setSize(icon.size || {width: 0, height: 0});
|
| + pod.customIconElement.setAnimation(icon.animation || null);
|
| + pod.customIconElement.setOpacity(icon.opacity || 100);
|
| + pod.customIconElement.show();
|
| + // This has to be called after |show| in case the tooltip should be shown
|
| + // immediatelly.
|
| + pod.customIconElement.setTooltip(
|
| + icon.tooltip || {text: '', autoshow: false});
|
| },
|
|
|
| /**
|
| @@ -1873,7 +2218,7 @@ cr.define('login', function() {
|
| return;
|
| }
|
|
|
| - pod.customIconElement.hidden = true;
|
| + pod.customIconElement.hide();
|
| },
|
|
|
| /**
|
| @@ -1894,29 +2239,6 @@ cr.define('login', function() {
|
| },
|
|
|
| /**
|
| - * Shows a tooltip bubble explaining Easy Unlock for the focused pod.
|
| - */
|
| - showEasyUnlockBubble: function() {
|
| - if (!this.focusedPod_) {
|
| - console.error('No focused pod to show Easy Unlock bubble.');
|
| - return;
|
| - }
|
| -
|
| - var bubbleContent = document.createElement('div');
|
| - bubbleContent.classList.add('easy-unlock-button-content');
|
| - bubbleContent.textContent = loadTimeData.getString('easyUnlockTooltip');
|
| -
|
| - var attachElement = this.focusedPod_.customIconElement;
|
| - /** @const */ var BUBBLE_OFFSET = 20;
|
| - /** @const */ var BUBBLE_PADDING = 8;
|
| - $('bubble').showContentForElement(attachElement,
|
| - cr.ui.Bubble.Attachment.RIGHT,
|
| - bubbleContent,
|
| - BUBBLE_OFFSET,
|
| - BUBBLE_PADDING);
|
| - },
|
| -
|
| - /**
|
| * Updates the display name shown on a public session pod.
|
| * @param {string} userID The user ID of the public session
|
| * @param {string} displayName The new display name
|
|
|