@openui5/sap.m
Version:
OpenUI5 UI Library sap.m
402 lines (321 loc) • 12.3 kB
JavaScript
/*!
* OpenUI5
* (c) Copyright 2009-2023 SAP SE or an SAP affiliate company.
* Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
*/
sap.ui.define([
"sap/m/library",
"sap/base/strings/capitalize",
"sap/ui/core/Core",
"sap/ui/Device"
], function (library, capitalize, Core, Device) {
"use strict";
// shortcut for sap.m.CarouselArrowsPlacement
var CarouselArrowsPlacement = library.CarouselArrowsPlacement;
// shortcut for sap.m.PlacementType
var PlacementType = library.PlacementType;
var oResourceBundle = Core.getLibraryResourceBundle("sap.m");
/**
* Carousel renderer.
* @namespace
*/
var CarouselRenderer = {
apiVersion: 2
};
//The number 9 is by visual specification. Less than 9 pages - bullets for page indicator. 9 or more pages - numeric page indicator.
CarouselRenderer._BULLETS_TO_NUMBERS_THRESHOLD = 9;
/**
* Renders the Carousel's HTML, using the provided {@link sap.ui.core.RenderManager}.
*
* @param {sap.ui.core.RenderManager} oRM The RenderManager that can be used for writing to the render output buffer
* @param {sap.m.Carousel} oCarousel An object representation of the control that should be rendered
*/
CarouselRenderer.render = function (oRM, oCarousel){
var aPages = oCarousel.getPages(),
iPageCount = aPages.length,
sPageIndicatorPlacement = oCarousel.getPageIndicatorPlacement(),
sArrowsPlacement = oCarousel.getArrowsPlacement(),
iIndex = oCarousel._iCurrSlideIndex;
this._renderOpeningDiv(oRM, oCarousel);
this._renderDummyArea(oRM, oCarousel, "before");
//visual indicator
if (sPageIndicatorPlacement === PlacementType.Top) {
this._renderPageIndicatorAndArrows(oRM, oCarousel, {
iPageCount: iPageCount,
iIndex: iIndex,
sArrowsPlacement : sArrowsPlacement,
bBottom: false,
bShowPageIndicator: oCarousel.getShowPageIndicator()
});
}
this._renderInnerDiv(oRM, oCarousel, aPages, sPageIndicatorPlacement);
if (Device.system.desktop && iPageCount > oCarousel._getNumberOfItemsToShow() && sArrowsPlacement === CarouselArrowsPlacement.Content) {
this._renderHudArrows(oRM, oCarousel);
}
//visual indicator
if (sPageIndicatorPlacement === PlacementType.Bottom) {
this._renderPageIndicatorAndArrows(oRM, oCarousel, {
iPageCount: iPageCount,
iIndex: iIndex,
sArrowsPlacement : sArrowsPlacement,
bBottom: true,
bShowPageIndicator: oCarousel.getShowPageIndicator()
});
}
this._renderDummyArea(oRM, oCarousel, "after");
oRM.close("div");
//page-wrap ends
};
CarouselRenderer._renderOpeningDiv = function (oRM, oCarousel) {
var sTooltip = oCarousel.getTooltip_AsString();
var sBackgroundDesign = "sapMCrslBackground-" + oCarousel.getBackgroundDesign();
//Outer carousel div
oRM.openStart("div", oCarousel)
.class("sapMCrsl")
.class(sBackgroundDesign)
.class("sapMCrslFluid") // sapMCrslFluid is originally from mobify-carousel
.style("width", oCarousel.getWidth())
.style("height", oCarousel.getHeight())
.attr("data-sap-ui-customfastnavgroup", true) // custom F6 handling
.accessibilityState(oCarousel, {
role: "listbox"
});
if (sTooltip) {
oRM.attr("title", sTooltip);
}
oRM.openEnd();
};
CarouselRenderer._renderInnerDiv = function (oRM, oCarousel, aPages, sPageIndicatorPlacement) {
oRM.openStart("div").class("sapMCrslInner");
if (!aPages.length) {
oRM.class("sapMCrslInnerNoPages");
}
if (aPages.length > 1 && (oCarousel.getShowPageIndicator() || oCarousel.getArrowsPlacement() === CarouselArrowsPlacement.PageIndicator)) {
if (sPageIndicatorPlacement === PlacementType.Bottom) {
oRM.class("sapMCrslBottomOffset");
if (oCarousel.getArrowsPlacement() === CarouselArrowsPlacement.PageIndicator) {
oRM.class("sapMCrslBottomArrowsOffset");
}
} else {
oRM.class("sapMCrslTopOffset");
if (oCarousel.getArrowsPlacement() === CarouselArrowsPlacement.PageIndicator) {
oRM.class("sapMCrslTopArrowsOffset");
}
}
}
oRM.openEnd();
// Render Pages
if (aPages.length) {
aPages.forEach(function (oPage, iIndex, aArray) {
CarouselRenderer._renderPage(oRM, oPage, oCarousel, iIndex, aArray);
});
} else {
CarouselRenderer._renderNoData(oRM, oCarousel);
}
oRM.close("div");
};
CarouselRenderer._renderPage = function (oRM, oPage, oCarousel, iIndex, aArray) {
var bSelected = oCarousel.getActivePage() === oPage.getId();
oRM.openStart("div", oCarousel.getId() + "-" + oPage.getId() + "-slide")
.class("sapMCrslItem")
.accessibilityState(oPage, {
role: "option",
posinset: iIndex + 1,
setsize: aArray.length,
selected: bSelected,
hidden: !oCarousel._isPageDisplayed(iIndex)
})
.attr("tabindex", bSelected ? 0 : -1)
.openEnd();
CarouselRenderer._renderPageInScrollContainer(oRM, oCarousel, oPage);
oRM.close("div");
};
CarouselRenderer._renderNoData = function (oRM, oCarousel) {
var oEmptyPage = oCarousel._getEmptyPage();
var oAccInfo = oEmptyPage.getAccessibilityInfo();
oRM.openStart("div", oCarousel.getId() + "-noData")
.attr("tabindex", 0)
.class("sapMCrslNoDataItem")
.accessibilityState({
label: oAccInfo.type + " " + oAccInfo.description
})
.openEnd();
oRM.renderControl(oCarousel._getEmptyPage());
oRM.close("div");
};
/**
* Renders the page indicator, using the provided {@link sap.ui.core.RenderManager}.
* Page indicator is only rendered if there is more than one carousel page
*
* @param {sap.ui.core.RenderManager} oRM the RenderManager that can be used for writing to the render output buffer
* @param {sap.m.Carousel} oCarousel the control being rendered
* @param {object} mSettings
* @param {int} mSettings.iPageCount
* @param {int} mSettings.iIndex
* @param {boolean} mSettings.bBottom
* @param {sap.m.CarouselArrowsPlacement} mSettings.sArrowsPlacement
* @param {boolean} mSettings.bShowPageIndicator
* @private
*/
CarouselRenderer._renderPageIndicatorAndArrows = function (oRM, oCarousel, mSettings) {
var iPageCount = mSettings.iPageCount,
bShowIndicatorArrows = Device.system.desktop && mSettings.sArrowsPlacement === CarouselArrowsPlacement.PageIndicator,
sId = oCarousel.getId(),
aOffsetClasses = [],
iNumberOfItemsToShow = oCarousel._getNumberOfItemsToShow(),
sPageIndicatorBackgroundDesign = "sapMCrslControlsBackground-" + oCarousel.getPageIndicatorBackgroundDesign(),
sPageIndicatorBorderDesign = "sapMCrslControlsBorder-" + oCarousel.getPageIndicatorBorderDesign();
// If there is only one page - do not render the indicator
if (iPageCount <= oCarousel._getNumberOfItemsToShow()) {
return;
}
if (!mSettings.bShowPageIndicator && !bShowIndicatorArrows) {
return;
}
if (mSettings.bBottom) {
aOffsetClasses.push("sapMCrslControlsBottom");
} else {
aOffsetClasses.push("sapMCrslControlsTop");
}
if (bShowIndicatorArrows) {
oRM.openStart("div").class("sapMCrslControls");
} else {
oRM.openStart("div").class("sapMCrslControlsNoArrows");
}
oRM.class(sPageIndicatorBackgroundDesign).class(sPageIndicatorBorderDesign);
aOffsetClasses.forEach(function (sClass) { oRM.class(sClass); });
oRM.openEnd();
if (bShowIndicatorArrows) {
oRM.openStart("div").class("sapMCrslControlsContainer");
aOffsetClasses.forEach(function (sClass) { oRM.class(sClass); });
oRM.openEnd();
}
// left arrow
if (bShowIndicatorArrows) {
this._renderArrow(oRM, oCarousel, "previous");
}
// page indicator
oRM.openStart("div", sId + "-pageIndicator");
if (!mSettings.bShowPageIndicator) {
oRM.style("opacity", "0");
}
if (iPageCount < CarouselRenderer._BULLETS_TO_NUMBERS_THRESHOLD) {
oRM.class("sapMCrslBulleted").openEnd();
for (var i = 1; i <= iPageCount - iNumberOfItemsToShow + 1; i++) {
oRM.openStart("span")
.attr("data-slide", i)
.accessibilityState({
role: "img",
label: oResourceBundle.getText("CAROUSEL_POSITION", [i, iPageCount])
}).openEnd()
.close("span");
}
} else {
oRM.class("sapMCrslNumeric").openEnd();
var sTextBetweenNumbers = oResourceBundle.getText("CAROUSEL_PAGE_INDICATOR_TEXT", [mSettings.iIndex + 1, iPageCount - iNumberOfItemsToShow + 1]);
oRM.openStart("span", sId + "-" + "slide-number").openEnd()
.text(sTextBetweenNumbers)
.close("span");
}
oRM.close("div");
// page indicator end
// right arrow
if (bShowIndicatorArrows) {
this._renderArrow(oRM, oCarousel, "next");
}
if (!bShowIndicatorArrows) {
oRM.close("div");
}
if (bShowIndicatorArrows) {
oRM.close("div")
.close("div");
}
};
CarouselRenderer._renderHudArrows = function (oRM, oCarousel) {
var sArrowPositionHudClass;
if (oCarousel.getShowPageIndicator()) {
if (oCarousel.getPageIndicatorPlacement() === PlacementType.Top) {
sArrowPositionHudClass = "sapMCrslHudTop";
} else if (oCarousel.getPageIndicatorPlacement() === PlacementType.Bottom) {
sArrowPositionHudClass = "sapMCrslHudBottom";
}
} else {
sArrowPositionHudClass = "sapMCrslHudMiddle";
}
//heads up controls for desktop browsers
oRM.openStart("div", oCarousel.getId() + "-hud")
.class("sapMCrslHud")
.class(sArrowPositionHudClass)
.openEnd();
this._renderArrow(oRM, oCarousel, "previous");
this._renderArrow(oRM, oCarousel, "next");
oRM.close("div");
};
CarouselRenderer._renderArrow = function (oRM, oCarousel, sDirection) {
var sShort = sDirection.slice(0, 4),
bLoop = oCarousel.getLoop(),
bFirstPageIsActive = oCarousel._aAllActivePagesIndexes[0] === 0,
bLastPageIsActive = oCarousel._aAllActivePagesIndexes[oCarousel._aAllActivePagesIndexes.length - 1] === oCarousel.getPages().length - 1;
oRM.openStart("span", oCarousel.getId() + "-arrow-" + sDirection)
.class("sapMCrslArrow")
.class("sapMCrsl" + capitalize(sShort))
.attr("data-slide", sShort)
.attr("title", oResourceBundle.getText("PAGINGBUTTON_" + sDirection.toUpperCase()));
// Hide unneeded arrow when we are on the first or last page and "loop" property is set to false
if (bFirstPageIsActive && sDirection === "previous" && !bLoop) {
oRM.class("sapMCrslLeftmost");
} else if (bLastPageIsActive && sDirection !== "previous" && !bLoop) {
oRM.class("sapMCrslRightmost");
}
oRM.openEnd();
oRM.openStart("div").class("sapMCrslArrowInner").openEnd();
oRM.renderControl(oCarousel._getNavigationArrow(sDirection === "previous" ? "Left" : "Right"));
oRM.close("div").close("span");
};
/**
* Private method that places a given page control into
* a scroll container which does not scroll. That container does
* not scroll itself. This is necessary to achieve the 100% height
* effect with an offset for the page indicator.
*
* @param {sap.ui.core.RenderManager} oRM The RenderManager that can be used for writing to the render output buffer
* @param {sap.m.Carousel} oCarousel the carousel containg the page
* @param {sap.ui.core.Control} oPage the page to check
* @private
*/
CarouselRenderer._renderPageInScrollContainer = function (oRM, oCarousel, oPage) {
// wrap in scrollcontainer
oRM.openStart("div").class("sapMScrollCont")
.class("sapMScrollContH")
.style("width", "100%")
.style("height", "100%")
.openEnd();
oRM.openStart("div").class("sapMScrollContScroll").openEnd();
oRM.openStart("div").class("sapMCrslItemTable").openEnd();
oRM.openStart("div").class("sapMCrslItemTableCell");
if (oPage.isA("sap.m.Image")) {
var sImgClass = "sapMCrslImgNoArrows",
bShowIndicatorArrows = Device.system.desktop && oCarousel.getArrowsPlacement() === CarouselArrowsPlacement.PageIndicator;
if (bShowIndicatorArrows) {
sImgClass = "sapMCrslImg";
}
oRM.class(sImgClass);
}
oRM.openEnd();
oRM.renderControl(oPage.addStyleClass("sapMCrsPage"));
oRM.close("div");
oRM.close("div");
oRM.close("div");
oRM.close("div");
// end wrapping in scroll container
};
CarouselRenderer._renderDummyArea = function(oRM, oControl, sAreaId) {
oRM.openStart("div", oControl.getId() + "-" + sAreaId)
.class("sapMCrslDummyArea")
.attr("role", "none")
.attr("tabindex", 0)
.openEnd()
.close("div");
};
return CarouselRenderer;
}, /* bExport= */ true);