@openui5/sap.m
Version:
OpenUI5 UI Library sap.m
1,106 lines (942 loc) • 33.3 kB
JavaScript
/*!
* OpenUI5
* (c) Copyright 2026 SAP SE or an SAP affiliate company.
* Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
*/
// Provides control sap.m.Avatar.
sap.ui.define([
"sap/ui/core/Control",
"sap/ui/core/IconPool",
"./AvatarRenderer",
"sap/ui/core/Lib",
"sap/ui/events/KeyCodes",
"sap/base/Log",
"sap/ui/core/Icon",
"./library",
"sap/ui/core/library",
'sap/ui/core/InvisibleText',
'sap/m/imageUtils/getCacheBustedUrl'
], function(Control, IconPool, AvatarRenderer, Library, KeyCodes, Log, Icon, library, coreLibrary, InvisibleText, getCacheBustedUrl) {
"use strict";
// shortcut for sap.m.AvatarType
var AvatarType = library.AvatarType;
// shortcut for sap.m.AvatarImageFitType
var AvatarImageFitType = library.AvatarImageFitType;
// shortcut for sap.m.AvatarColor
var AvatarColor = library.AvatarColor;
// shortcut for sap.m.AvatarBadgeColor
var AvatarBadgeColor = library.AvatarBadgeColor;
// shortcut for sap.m.AvatarSize
var AvatarSize = library.AvatarSize;
// shortcut for sap.m.AvatarShape
var AvatarShape = library.AvatarShape;
// shortcut for sap.ui.core.aria.HasPopup
var AriaHasPopup = coreLibrary.aria.HasPopup;
// shortcut for sap.ui.core.ValueState
var ValueState = coreLibrary.ValueState;
// shortcut for Accent colors keys only (from AvatarColor enum)
var AccentColors = Object.keys(AvatarColor).filter(function (sCurrColor) {
return sCurrColor.indexOf("Accent") !== -1;
});
// constant for Avatar badge icon with no icon display
var AVATAR_ICON_NONE = "sap-icon://avatar-icon-none";
/**
* Constructor for a new <code>Avatar</code>.
*
* @param {string} [sId] ID for the new control, generated automatically if no ID is given
* @param {object} [mSettings] Initial settings for the new control
*
* @class
* An image-like control that has different display options for representing images, initials,
* and icons.
*
* <h3>Overview</h3>
*
* The <code>Avatar</code> control allows the usage of different content, shapes, and sizes
* depending on the use case.
*
* The content types that can be displayed are either images, icons, or initials. The shape
* can be circular or square. There are several predefined sizes, as well as an option to
* set a custom size.
*
* <h3>Usage</h3>
*
* Up to three Latin letters can be displayed as initials in an <code>Avatar</code>. If there
* are more than three letters, or if there's a non-Latin character present, a default image
* placeholder will be created.
*
* There are two options for how the displayed image can fit inside the
* available area:
* <ul>
* <li>Cover - the image is scaled to cover all of the available area</li>
* <li>Contain - the image is scaled as large as possible while both
* its height and width fit inside the avalable area</li>
* </ul>
* <b>Note:</b> To set a custom size for the <code>Avatar</code>, you have to choose the <code>Custom</code>
* value for the <code>displaySize</code> property. Then, you have to set both the
* <code>customDisplaySize</code> and <code>customFontSize</code> properties.
*
* @extends sap.ui.core.Control
*
* @author SAP SE
* @version 1.146.0
*
* @constructor
* @public
* @since 1.73
* @see {@link fiori:https://experience.sap.com/fiori-design-web/avatar/ Avatar}
* @alias sap.m.Avatar
*/
var Avatar = Control.extend("sap.m.Avatar", {
metadata: {
library: "sap.m",
properties: {
/**
* Determines the path to the desired image or icon.
*/
src: {type: "sap.ui.core.URI", group: "Data", defaultValue: null},
/**
* Defines the displayed initials. They should consist of only 1,2 or 3 latin letters.
*/
initials: {type: "string", group: "Data", defaultValue: null},
/**
* Defines the shape of the <code>Avatar</code>.
*/
displayShape: {type: "sap.m.AvatarShape", group: "Appearance", defaultValue: AvatarShape.Circle},
/**
* Sets a predefined display size of the <code>Avatar</code>.
*/
displaySize: {type: "sap.m.AvatarSize", group: "Appearance", defaultValue: AvatarSize.S},
/**
* Specifies custom display size of the <code>Avatar</code>.
*
*<b>Note:</b> It takes effect if the <code>displaySize</code> property is set to <code>Custom</code>.
*/
customDisplaySize: {type: "sap.ui.core.CSSSize", group: "Appearance", defaultValue: "3rem"},
/**
* Specifies custom font size of the <code>Avatar</code>.
*
*<b>Note:</b> It takes effect if the <code>displaySize</code> property is set to <code>Custom</code>.
*/
customFontSize: {type: "sap.ui.core.CSSSize", group: "Appearance", defaultValue: "1.125rem"},
/**
* Specifies how an image would fit in the <code>Avatar</code>.
*/
imageFitType: {type: "sap.m.AvatarImageFitType", group: "Appearance", defaultValue: AvatarImageFitType.Cover},
/**
* Defines the fallback icon displayed in case of wrong image src and no initials set.
*
* <b>Notes:</b>
* <ul>
* <li>If not set, a default fallback icon is displayed depending on the set <code>displayShape</code> property.</li>
* <li>Accepted values are only icons from the SAP icon font.</li>
* </ul>
*/
fallbackIcon: {type: "string", group: "Data", defaultValue: null},
/**
* Determines the background color of the control.
*/
backgroundColor: {type: "sap.m.AvatarColor", group: "Appearance", defaultValue: AvatarColor.Accent6},
/**
* Determines whether the control is displayed with border.
*/
showBorder: {type: "boolean", group: "Appearance", defaultValue: false},
/**
* Defines what type of icon is displayed as visual affordance. It can be predefined or custom.
*
* The predefined icons are recommended for:
* <ul>
* <li>Suggesting a zooming action: <code>sap-icon://zoom-in</code></li>
* <li>Suggesting an image change: <code>sap-icon://camera</code></li>
* <li>Suggesting an editing action: <code>sap-icon://edit</code></li>
* </ul>
* <b>Notes:</b>
* <ul>
* <li>Use <code>sap-icon://avatar-icon-none</code> to show the badge without an icon.</li>
* <li>When using avatar-icon-none, the badge remains visible and can display background color or tooltip.</li>
* </ul>
*
* @since 1.77
*/
badgeIcon: {type: "sap.ui.core.URI", group: "Appearance", defaultValue: ""},
/**
* Defines a custom tooltip for the <code>badgeIcon</code>. If set, it overrides the available default values.
*
* If not set, default tooltips are used as follows:
* <ul>
* <li>Specific default tooltips are displayed for each of the predefined <code>badgeIcons</code>.</li>
* <li>For any other icons, the displayed tooltip is the same as the main control tooltip.</li>
* <ul>
*
* @since 1.77
*/
badgeTooltip: {type: "string", group: "Data", defaultValue: null},
/**
* Defines whether the <code>sap.m.Avatar</code> is used for decorative purposes and is ignored by accessibility tools.
*
* <b>Note:</b> This property doesn't take effect if <code>sap.m.Avatar</code> has a <code>press</code> handler.
*
* @since 1.97
*/
decorative : {type : "boolean", group : "Accessibility", defaultValue : false},
/**
* Specifies the value of the <code>aria-haspopup</code> attribute
*
* If the value is <code>None</code>, the attribute will not be rendered. Otherwise it will be rendered with the selected value.
*
* NOTE: Use this property only when an avatar is related to a popover/popup. The value needs to be equal to the main/root role of the popup - e.g. dialog,
* menu or list (examples: if you have dialog -> dialog, if you have menu -> menu; if you have list -> list; if you have dialog containing a list -> dialog).
* Do not use it, if you open a standard sap.m.Dialog, MessageBox or other type of dialogs displayed as on overlay over the application.
*
* @since 1.99.0
*/
ariaHasPopup : {type : "sap.ui.core.aria.HasPopup", group : "Accessibility", defaultValue : AriaHasPopup.None},
/**
* Visualizes the validation state of the badge, e.g. <code>Error</code>, <code>Warning</code>,
* <code>Success</code>, <code>Information</code>.
* @since 1.116.0
*/
badgeValueState: {
type: "sap.ui.core.ValueState",
group: "Appearance",
defaultValue: ValueState.None
},
/**
* Defines the color of the badge icon.
* This color is used to style the badge, indicating different statuses or categories.
* Acceptable values include predefined `sap.m.AvatarBadgeColor` options.
*
* @since 1.132.0
*/
badgeIconColor: {
type: "sap.m.AvatarBadgeColor",
group: "Appearance",
defaultValue: AvatarBadgeColor.Accent6
},
/**
* Determines whether the <code>Avatar</code> is enabled (default is set to <code>true</code>).
* A disabled <code>Button</code> has different colors depending on the {@link sap.m.AvatarColor AvatarColor}.
* @since 1.117.0
*/
enabled : {type : "boolean", group : "Behavior", defaultValue : true},
/**
* Determines whether the <code>Avatar</code> is active/toggled (default is set to <code>false</code>).
* Active state is meant to be toggled when user clicks on the <code>Avatar</code>.
* The Active state is only applied, when the <code>Avatar</code> has <code>press</code> listeners.
* @since 1.120.0
*/
active : {type : "boolean", group : "Behavior", defaultValue : false}
},
aggregations : {
/**
* A <code>sap.m.LightBox</code> instance, that will be opened automatically when the user interacts with the <code>Avatar</code> control.
*
* The <code>press</code> event will still be fired.
* @public
*/
detailBox: {type: 'sap.m.LightBox', multiple: false, bindable: "bindable"},
/**
* A <code>sap.ui.core.Icon</code> instance that shows the badge icon of the <code>Avatar</code> control.
* @private
*/
_badge: {type: "sap.ui.core.Icon", multiple: false, visibility: "hidden"},
/**
* A <code>sap.ui.core.Icon</code> instance that shows the icon of the <code>Avatar</code> control.
* @private
*/
_icon: {type: "sap.ui.core.Icon", multiple: false, visibility: "hidden"}
},
associations : {
/**
* Association to controls / ids which describe this control (see WAI-ARIA attribute aria-describedby).
*/
ariaDescribedBy : {type : "sap.ui.core.Control", multiple : true, singularName : "ariaDescribedBy"},
/**
* Association to controls / ids which label this control (see WAI-ARIA attribute aria-labelledBy).
*/
ariaLabelledBy: {type : "sap.ui.core.Control", multiple : true, singularName : "ariaLabelledBy"}
},
events : {
/**
* Fired when the user selects the control.
*/
press: {}
},
dnd: { draggable: true, droppable: false },
designtime: "sap/m/designtime/Avatar.designtime"
},
renderer: AvatarRenderer
});
/**
* This is the URI for the default icon, when <code>displayShape</code> is <code>Circle</code>.
*
* @type {string}
*/
Avatar.DEFAULT_CIRCLE_PLACEHOLDER = "sap-icon://person-placeholder";
/**
* This is the URI for the default icon, when <code>displayShape</code> is <code>Square</code>.
*
* @type {string}
*/
Avatar.DEFAULT_SQUARE_PLACEHOLDER = "sap-icon://product";
/**
* The predefined values for tooltip, when <code>badgeIcon</code> is set.
*
* @type {string}
*/
Avatar.AVATAR_BADGE_TOOLTIP = {
"sap-icon://zoom-in" : Library.getResourceBundleFor("sap.m").getText("AVATAR_TOOLTIP_ZOOMIN"),
"sap-icon://camera": Library.getResourceBundleFor("sap.m").getText("AVATAR_TOOLTIP_CAMERA"),
"sap-icon://edit": Library.getResourceBundleFor("sap.m").getText("AVATAR_TOOLTIP_EDIT")
};
Avatar.prototype.init = function () {
// Property holding the actual display type of the avatar
this._sActualType = null;
// Property that determines if the created icon is going to be the default one
this._bUseDefaultIcon = true;
this._sImageFallbackType = null;
// Property holding the currently picked random background color of the avatar, if any
this._sPickedRandomColor = null;
//Reference to badge hidden aggregation
this._badgeRef = null;
this._bImageLoadError = false;
// does not have initials by default (null value)
this._bInitialsValid = false;
};
Avatar.prototype.onBeforeRendering = function () {
if (this._getImageCustomData() && !this._iCacheBustingValue) {
this._setNewCacheBustingValue();
this._loadImage(this._getAvatarSrc());
}
// determine the actual display type of the avatar before rendering
this._setActualDisplayType();
this._setUseDefaultIcon();
};
Avatar.prototype.onAfterRendering = function() {
this._checkInitialsHolderWidth();
if (this._bImageLoadError) {
this._cleanCSS();
}
};
Avatar.prototype.setSrc = function (sSrc) {
var bIsIconURI = IconPool.isIconURI(sSrc),
oLightBox = this.getAggregation("detailBox");
this._bImageLoadError = false;
this.setProperty("src", sSrc);
this._handleDetailBoxPress(bIsIconURI, oLightBox);
this._loadImage(this._getAvatarSrc());
return this;
};
Avatar.prototype.setInitials = function (sInitials) {
this.setProperty("initials", sInitials);
this._setInitialsValid(this._areInitialsValid(sInitials));
return this;
};
Avatar.prototype.onThemeChanged = function() {
this._checkInitialsHolderWidth();
};
/**
* @returns {object} Current accessibility state of the Avatar
* @see sap.ui.core.Control#getAccessibilityInfo
* @protected
*/
Avatar.prototype.getAccessibilityInfo = function () {
return this.getDecorative() ? { description: "" } : null; // SNOW DINC0365871
};
Avatar.prototype.exit = function () {
if (this._fnLightBoxOpen) {
this._fnLightBoxOpen = null;
}
if (this._badgeRef) {
this._badgeRef.destroy();
}
if (this._oInvisibleText) {
this._oInvisibleText.destroy();
this._oInvisibleText = null;
}
this._sPickedRandomColor = null;
};
/**
* Sets the <code>detailBox</code> aggregation.
* @param {sap.m.LightBox|undefined} oLightBox - Instance of the <code>LightBox</code> control or undefined
* @returns {this} <code>this</code> for chaining
* @override
* @public
*/
Avatar.prototype.setDetailBox = function (oLightBox) {
var oCurrentDetailBox = this.getDetailBox(),
sSrc = this.getSrc(),
bIsIconURI = IconPool.isIconURI(sSrc);
if (oLightBox) {
// In case someone try's to set the same LightBox twice we don't do anything
if (oLightBox === oCurrentDetailBox) {
return this;
}
this._handleDetailBoxPress(bIsIconURI, oLightBox);
} else if (this._fnLightBoxOpen) {
// If there was a LightBox - cleanup
this.detachPress(this._fnLightBoxOpen, oCurrentDetailBox);
this._fnLightBoxOpen = null;
}
return this.setAggregation("detailBox", oLightBox);
};
Avatar.prototype._handleDetailBoxPress = function (bIsIconURI, oLightBox) {
var oCurrentDetailBox = this.getDetailBox();
// If we already have a LightBox detach old one's event
if (oCurrentDetailBox) {
this.detachPress(this._fnLightBoxOpen, oCurrentDetailBox);
}
// Bind the LightBox open method to the press event of the Avatar
// only if the Avatar's source is not an icon URI,
// otherwise, prevent the Lightbox from opening on press.
if (!bIsIconURI && oLightBox) {
this._fnLightBoxOpen = oLightBox.open;
this.attachPress(this._fnLightBoxOpen, oLightBox);
}
};
/**
* Destroys the <code>detailBox</code> aggregation.
* @returns {this} <code>this</code> for chaining
* @override
* @public
*/
Avatar.prototype.destroyDetailBox = function () {
var oCurrentDetailBox = this.getDetailBox();
if (oCurrentDetailBox) {
this.detachPress(this._fnLightBoxOpen, oCurrentDetailBox);
this._fnLightBoxOpen = null;
}
return this.destroyAggregation("detailBox");
};
Avatar.prototype.setBadgeValueState = function(sValue) {
Object.keys(ValueState).forEach(function(val){
this.toggleStyleClass('sapFAvatar' + val, val === sValue);
}.bind(this));
this.setProperty("badgeValueState", sValue, true);
return this;
};
Avatar.prototype.setBadgeIconColor = function(sValue) {
var aBadgeIconColors = Object.keys(AvatarBadgeColor);
if (aBadgeIconColors.indexOf(sValue) === -1) {
return this;
}
aBadgeIconColors.forEach(function(val) {
this.removeStyleClass('sapFAvatarBadgeColor' + val);
}.bind(this));
this.addStyleClass('sapFAvatarBadgeColor' + sValue);
this.setProperty("badgeIconColor", sValue, true);
return this;
};
/*
* @override
*/
Avatar.prototype.clone = function () {
var oClone = Control.prototype.clone.apply(this, arguments),
oCloneDetailBox = oClone.getDetailBox();
// Handle press event if DetailBox is available
if (oCloneDetailBox) {
// Detach the old event
oClone.detachPress(this._fnLightBoxOpen, this.getDetailBox());
// Attach new event with the cloned detail box
oClone._fnLightBoxOpen = oCloneDetailBox.open;
oClone.attachPress(oClone._fnLightBoxOpen, oCloneDetailBox);
}
return oClone;
};
Avatar.prototype.attachPress = function() {
Array.prototype.unshift.apply(arguments, ["press"]);
Control.prototype.attachEvent.apply(this, arguments);
if (this.hasListeners("press")) {
this.$().attr("tabindex", "0");
this.$().attr("role", "button");
}
return this;
};
Avatar.prototype.detachPress = function() {
Array.prototype.unshift.apply(arguments, ["press"]);
Control.prototype.detachEvent.apply(this, arguments);
if (!this.hasListeners("press")) {
this.$().removeAttr("tabindex");
this.$().attr("role", "img");
}
return this;
};
/**
* Called when the <code>Avatar</code> is selected.
*
* @param {jQuery.Event} oEvent The tap/click event object
* @private
*/
Avatar.prototype.ontap = function (oEvent) {
if (oEvent && this.getDetailBox()) {
oEvent.stopPropagation();
}
this._handlePress();
};
/**
* @param {jQuery.Event} oEvent - the keyboard event.
* @private
*/
Avatar.prototype.onkeydown = function (oEvent) {
if (oEvent.which === KeyCodes.SHIFT || oEvent.which === KeyCodes.ESCAPE) {
this._bShouldInterupt = this._bSpacePressed;
}
if (oEvent.which === KeyCodes.SPACE) {
this._bSpacePressed = true;
// To prevent the browser scrolling.
oEvent.preventDefault();
}
if (oEvent.which === KeyCodes.ENTER) {
this._handlePress();
}
};
/**
* Handles the key up event for SPACE.
*
* @param {jQuery.Event} oEvent - the keyboard event.
* @private
*/
Avatar.prototype.onkeyup = function (oEvent) {
if (oEvent.which === KeyCodes.SPACE) {
if (!this._bShouldInterupt) {
this._handlePress();
}
this._bShouldInterupt = false;
this._bSpacePressed = false;
//stop the propagation, it is handled by the control
oEvent.stopPropagation();
}
};
Avatar.prototype._handlePress = function () {
if (!this.getEnabled() || (this._getUseDefaultIcon() && this.getDetailBox())) {
return;
}
this.firePress({/* no parameters */});
};
/**
* Loads the image from the given source.
*
* @param {string} sSrc - The source of the image to load
* @private
*/
Avatar.prototype._loadImage = function (sSrc) {
if (!sSrc || IconPool.isIconURI(sSrc)) {
return;
}
// we perform this action in order to validate the image source and
// take further actions depending on that
this.preloadedImage = new window.Image();
this.preloadedImage.src = sSrc;
this.preloadedImage.onload = this._onImageLoad.bind(this);
this.preloadedImage.onerror = this._onImageError.bind(this, sSrc);
};
/**
* Checks the validity of the <code>initials</code> parameter and returns <code>true</code> if the
* initials are correct.
*
* @param {string} sInitials The initials value
* @returns {boolean} The initials are valid or not
* @private
*/
Avatar.prototype._areInitialsValid = function (sInitials) {
var validInitials = /^[a-zA-Z\xc0-\xd6\xd8-\xdc\xe0-\xf6\xf8-\xfc]{1,3}$/;
if (!validInitials.test(sInitials)) {
Log.warning("Initials should consist of only 1,2 or 3 latin letters", this);
// if there is no actual type or the actual type is initials but they are not valid, set the actual type to icon
return false;
}
return true;
};
/**
* Returns the validity state of the initials.
*
* @returns {boolean}
* @private
*/
Avatar.prototype._getInitialsValid = function() {
return this._bInitialsValid;
};
/**
* Sets the validity state of the initials.
*
* @param {boolean} bValue - The validity state to set
* @private
*/
Avatar.prototype._setInitialsValid = function (bValue) {
this._bInitialsValid = bValue;
};
/**
* Returns the actual display type of avatar depending on the <code>src</code> parameter - either Icon or Image.
*
* @param {string} sSrc
* @returns {sap.m.AvatarType} either Icon or Image
* @private
*/
Avatar.prototype._getActualTypeBySrc = function (sSrc) {
if (IconPool.isIconURI(sSrc)) {
return AvatarType.Icon;
} else {
return AvatarType.Image;
}
};
/**
* Validates the <code>src</code> parameter, and returns sap.ui.core.Icon object.
*
* @param {string} sSrc
* @returns {sap.ui.core.Icon|null}
* @private
*/
Avatar.prototype._getDisplayIcon = function (sSrc) {
return IconPool.isIconURI(sSrc) && IconPool.getIconInfo(sSrc) ?
IconPool.createControlByURI({
src: sSrc
}) : null;
};
/**
* Validates the entered parameters, and sets what the actual display type parameter would be.
*
* @returns {sap.m.AvatarType}
* @private
*/
Avatar.prototype._setActualDisplayType = function () {
var sSrc = this._getAvatarSrc(),
sInitials = this.getInitials();
if (sSrc) {
this._sActualType = this._getActualTypeBySrc(sSrc);
} else if (sInitials && this._getInitialsValid()) {
this._sActualType = AvatarType.Initials;
} else {
Log.warning("No src and initials were provided or initials are provided, but are not valid", this);
this._sActualType = AvatarType.Icon;
}
return this._sActualType;
};
/**
* Returns the actual display type of avatar
*
* @returns {sap.m.AvatarType}
* @private
*/
Avatar.prototype._getActualDisplayType = function () {
if (!this._sActualType) {
this._setActualDisplayType();
}
return this._sActualType;
};
/**
* Sets whether default icon should be used
*
* @param {boolean} bValue
* @private
*/
Avatar.prototype._setUseDefaultIcon = function () {
var sSrc = this.getSrc();
if (!sSrc) {
// No source: use default only if initials are invalid
this._bUseDefaultIcon = !this._getInitialsValid();
return;
}
if (IconPool.isIconURI(sSrc)) {
// Icon URI: use default if NOT found in IconPool
this._bUseDefaultIcon = !IconPool.getIconInfo(sSrc);
return;
}
// Regular image source: use default if image failed to load
this._bUseDefaultIcon = this._bImageLoadError;
};
/**
* Returns whether the default icon should be used.
*
* @returns {boolean} whether the default icon should be used
* @private
*/
Avatar.prototype._getUseDefaultIcon = function () {
return this._bUseDefaultIcon;
};
/**
* Indicates what type of fallback we should show if there is invalid image source.
*
* @returns {sap.m.AvatarType}
* @private
*/
Avatar.prototype._getImageFallbackType = function () {
var sInitials = this.getInitials();
this._sImageFallbackType = sInitials && this._getInitialsValid() ?
AvatarType.Initials : AvatarType.Icon;
return this._sImageFallbackType;
};
/**
* Returns the path for the default icon, based on the value of the <code>DisplayShape</code> property.
*
* @param {sap.m.AvatarShape} sDisplayShape
* @returns {string} the default icon
* @private
*/
Avatar.prototype._getDefaultIconPath = function (sDisplayShape) {
var sDefaultIconPath = null,
sFallbackIcon = this.getFallbackIcon();
if (sFallbackIcon && IconPool.isIconURI(sFallbackIcon)) {
sDefaultIconPath = sFallbackIcon;
} else if (sDisplayShape === AvatarShape.Circle) {
sDefaultIconPath = Avatar.DEFAULT_CIRCLE_PLACEHOLDER;
} else if (sDisplayShape === AvatarShape.Square) {
sDefaultIconPath = Avatar.DEFAULT_SQUARE_PLACEHOLDER;
}
return sDefaultIconPath;
};
/**
* Returns a control of type <code>Icon</code> and changes the <code>src</code> value if the
* <code>Icon</code> control was already created.
*
* @returns {sap.ui.core.Control}
* @private
*/
Avatar.prototype._getIcon = function () {
var sSrc = this.getSrc(),
oIcon = this.getAggregation("_icon"),
sDisplayShape = this.getDisplayShape(),
bIsIconURI = IconPool.isIconURI(sSrc),
sDefaultIconPath = this._getDefaultIconPath(sDisplayShape);
if (this._getUseDefaultIcon()) {
sSrc = sDefaultIconPath;
}
if (!oIcon) {
oIcon = IconPool.createControlByURI({
alt: "Image placeholder",
src: bIsIconURI ? sSrc : sDefaultIconPath
});
this.setAggregation("_icon", oIcon);
} else if (oIcon.getSrc() !== sSrc && (bIsIconURI || sSrc === sDefaultIconPath)) {
oIcon.setSrc(sSrc);
}
return oIcon;
};
Avatar.prototype._getDefaultTooltip = function() {
return Library.getResourceBundleFor("sap.m").getText("AVATAR_TOOLTIP");
};
Avatar.prototype._getBadgeIconSource = function() {
var sBadgeIconPath,
sSrc = this.getSrc(),
bIsIconURI = IconPool.isIconURI(sSrc);
if (this.getDetailBox() && !bIsIconURI) {
sBadgeIconPath = "sap-icon://zoom-in";
} else if (this.getBadgeIcon() !== "") {
if (this._getDisplayIcon(this.getBadgeIcon())) {
sBadgeIconPath = this.getBadgeIcon();
} else {
Log.warning("No valid Icon URI source for badge affordance was provided");
}
}
return sBadgeIconPath;
};
Avatar.prototype._getBadgeTooltip = function() {
var sBadgeTooltip = this._getDefaultTooltip(),
sBadgeIcon = this.getBadgeIcon();
if (this.getBadgeTooltip()) {
sBadgeTooltip = this.getBadgeTooltip();
} else if ( sBadgeIcon && Avatar.AVATAR_BADGE_TOOLTIP[this.getBadgeIcon()]) {
sBadgeTooltip = Avatar.AVATAR_BADGE_TOOLTIP[sBadgeIcon];
}
return sBadgeTooltip;
};
Avatar.prototype._handleEmptyBadgeIcon = function () {
var sBadgeIcon = this.getBadgeIcon(),
sBadgeTooltip = this._getBadgeTooltip();
if (sBadgeIcon === AVATAR_ICON_NONE) {
if (!this._badgeRef) {
this.setAggregation("_badge", new Icon({
src: "",
tooltip: sBadgeTooltip
}));
} else {
this._badgeRef.setTooltip(sBadgeTooltip);
}
this._badgeRef = this.getAggregation("_badge");
return this._badgeRef;
}
return null;
};
Avatar.prototype._getBadge = function () {
var sBadgeIconSrc = this._getBadgeIconSource(),
sBadgeTooltip = this._getBadgeTooltip(),
oEmptyBadge = this._handleEmptyBadgeIcon();
if (oEmptyBadge) {
return oEmptyBadge;
}
if (!sBadgeIconSrc) {return;}
if (!this._badgeRef) {
this.setAggregation("_badge", new Icon({
src: sBadgeIconSrc,
tooltip: sBadgeTooltip
}));
}
this._badgeRef = this.getAggregation("_badge");
return this._badgeRef;
};
/**
* We use this callback to make sure we hide fallback content if our original image source
* is loaded.
*
* @private
*/
Avatar.prototype._onImageLoad = function() {
this._bImageLoadError = false;
//we need to remove fallback content
if (this._getUseDefaultIcon()) {
this._setUseDefaultIcon();
this.getDetailBox() && this.invalidate();
}
delete this.preloadedImage;
};
/**
* We use the negative callback to clean the useless property.
*
* @private
*/
Avatar.prototype._onImageError = function(sSrc) {
if (this.getSrc() !== sSrc) {
return;
}
this._bImageLoadError = true;
this._cleanCSS();
if (!this._getUseDefaultIcon()) {
this._setUseDefaultIcon();
this.getDetailBox() && this.invalidate();
}
delete this.preloadedImage;
};
Avatar.prototype._cleanCSS = function () {
var sFallBackType = this._getImageFallbackType();
this.$().removeClass("sapFAvatarImage")
.addClass("sapFAvatar" + sFallBackType);
};
/**
* Returns the actual background color.
*
* @returns {sap.m.AvatarColor} The actual background color
* @private
*/
Avatar.prototype._getActualBackgroundColor = function() {
var sBackground = this.getBackgroundColor();
if (sBackground === AvatarColor.Random) {
// If the last time the "backgroundColor" property was "Random", we return the last rolled color.
// This is needed in order to prevent picking different colors on re-rendering
// of the control if the property keeps being "Random".
if (this._sPickedRandomColor) {
return this._sPickedRandomColor;
}
// Picking a random Accent property from the AvatarColor enum
// << 0 truncates the digits after the decimal (it's the same as Math.trunc())
sBackground = this._sPickedRandomColor = AvatarColor[AccentColors[AccentColors.length * Math.random() << 0]];
} else {
// In case the "backgroundColor" is different from "Random", we set the
// this._sPickedRandomColor to "null". This is needed in order to generate
// a new random color the next time "backgroundColor" is "Random".
this._sPickedRandomColor = null;
}
return sBackground;
};
// Checks the scrollWidth of the initials holder inside the control.
// This is related with the initials property and the case where there are 3 letter initials,
// which width is bigger than the initials holder`s width.
Avatar.prototype._checkInitialsHolderWidth = function() {
var $this = this.$(),
iInitials = this.getInitials().length;
this.$oInitialsHolder = $this.children(".sapFAvatarInitialsHolder");
if (this.$oInitialsHolder.length !== 0 && iInitials === 3) {
var iAvatarWidth = $this[0].offsetWidth,
iInitialsHolderWidth = this.$oInitialsHolder[0].offsetWidth;
if (iInitialsHolderWidth >= iAvatarWidth) {
this._wideInitialsIcon();
}
}
};
// In case when there are 3 initials set to the avatar and they are overflowing,
// we want to show icon instead of the initials.
Avatar.prototype._wideInitialsIcon = function() {
var $this = this.$(),
$oHiddenIcon = $this.children(".sapFAvatarHiddenIcon");
$oHiddenIcon.removeClass("sapFAvatarHiddenIcon");
this.$oInitialsHolder.css("display", "none");
$this.removeClass("sapFAvatarInitials");
$this.addClass("sapFAvatarIcon");
};
Avatar.prototype._getInvisibleText = function() {
if (!this._oInvisibleText && this.sInitials) {
this._oInvisibleText = new InvisibleText({ id: this.getId() + "-InvisibleText"});
this._oInvisibleText.setText(this.sInitials).toStatic();
}
return this._oInvisibleText;
};
Avatar.prototype._getAriaLabelledBy = function () {
var aLabelledBy = this.getAriaLabelledBy(),
sInitialsAriaLabelledBy;
this.sInitials = this.getInitials();
if (this.sInitials && aLabelledBy.length > 0) {
sInitialsAriaLabelledBy = this._getInvisibleText().getId();
aLabelledBy.push(sInitialsAriaLabelledBy);
}
return aLabelledBy;
};
/**
* Retrieves the custom data object for the Avatar control.
*
* @function
* @param {sap.m.Avatar} oAvatar - The Avatar control to retrieve the custom data for.
* @returns {sap.m.ImageCustomData|undefined} The custom data object or undefined if no custom data is found.
* @private
*/
Avatar.prototype._getImageCustomData = function (oAvatar) {
var oImageCustomData = this.getCustomData().filter(function (item) {
return item.isA("sap.m.ImageCustomData");
});
return oImageCustomData.length ? oImageCustomData[0] : undefined;
};
/**
* Sets the cache busting value for the Avatar control.
* This is needed in order to force the browser to reload the image.
*
* @function
* @private
*/
Avatar.prototype._setNewCacheBustingValue = function () {
if (this._getImageCustomData()) {
this._iCacheBustingValue = Date.now();
}
};
/**
* Returns the Avatar control's source URL with cache busting applied if necessary, based on the ImageCustomData configuration.
* If cache busting is applied, the source URL is updated; otherwise, the original source URL is returned.
*
* @function
* @returns {string} sSrc - The Avatar control's source URL
* @private
*/
Avatar.prototype._getAvatarSrc = function () {
var aImageCustomData = this._getImageCustomData(),
sSrc = this.getSrc();
if (aImageCustomData && sSrc) {
var oConfig = {
sUrl: sSrc,
sParamName: aImageCustomData.getParamName(),
sParamValue: this._iCacheBustingValue
};
return getCacheBustedUrl(oConfig);
}
return sSrc;
};
/**
* Refreshes the cache busting value for the Avatar and invalidates the control.
* It can be used when you have applied ImageCustomData to the Avatar control and you want to force the browser to reload the image.
*
* @function
* @private
* @ui5-restricted sap.fe
*/
Avatar.prototype.refreshAvatarCacheBusting = function () {
this._setNewCacheBustingValue();
this._loadImage(this._getAvatarSrc());
this.invalidate();
};
return Avatar;
});