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

Unified Diff: ui/login/account_picker/user_pod_row.js

Issue 446743003: Hook up new API for easy unlock to update lock screen (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 6 years, 4 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/login/account_picker/user_pod_row.css ('k') | ui/login/account_picker/user_pod_template.html » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « ui/login/account_picker/user_pod_row.css ('k') | ui/login/account_picker/user_pod_template.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698