UNPKG

@openui5/sap.m

Version:

OpenUI5 UI Library sap.m

596 lines (495 loc) 19.3 kB
/*! * OpenUI5 * (c) Copyright 2026 SAP SE or an SAP affiliate company. * Licensed under the Apache License, Version 2.0 - see LICENSE.txt. */ sap.ui.define([ 'sap/base/i18n/Formatting', 'sap/base/i18n/Localization', 'sap/ui/core/Element', 'sap/ui/core/Theming', "sap/ui/core/Lib", 'sap/ui/unified/calendar/CalendarDate', 'sap/ui/unified/calendar/CalendarUtils', 'sap/ui/unified/calendar/Month', 'sap/ui/core/IconPool',// side effect: required when calling RenderManager#icon './PlanningCalendarLegend', 'sap/ui/core/InvisibleText', 'sap/ui/unified/library', 'sap/ui/core/date/UI5Date' ], function( Formatting, Localization, Element, Theming, Library, CalendarDate, CalendarUtils, Month, _IconPool, PlanningCalendarLegend, InvisibleText, unifiedLibrary, UI5Date ) { "use strict"; // shortcut for sap.ui.unified.CalendarDayType var CalendarDayType = unifiedLibrary.CalendarDayType; /** * SinglePlanningCalendarMonthGrid renderer. * @namespace */ var SinglePlanningCalendarMonthGridRenderer = { apiVersion: 2 }; /** * Renders the HTML for the given control, 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.SinglePlanningCalendarMonthGrid} oControl An object representation of the control that should be rendered */ SinglePlanningCalendarMonthGridRenderer.render = function(oRm, oControl) { var oLocaleData = oControl._getCoreLocaleData(); var oDensitySizes = oControl._getDensitySizes(); oRm.openStart("div", oControl); oRm.attr("role", "group"); oRm.class("sapMSinglePCGrid"); oRm.class("sapMSPCMonthGrid"); oRm.openEnd(); this.renderDayNames(oRm, oControl, oLocaleData); oRm.openStart("div"); oRm.class("sapMSinglePCGridContent"); oRm.openEnd(); this.renderCells(oRm, oControl, oLocaleData, oDensitySizes); oRm.close("div"); // END .sapMSinglePCGridContent oRm.close("div"); // END .sapMSinglePCGrid }; SinglePlanningCalendarMonthGridRenderer.renderCells = function(oRm, oControl, oLocaleData, oDensitySizes) { var aCells = oControl._getCells(), aVerticalLabels = oControl._getVerticalLabels(), iColumns = oControl._getColumns(), sWeekText = Library.getResourceBundleFor("sap.ui.unified").getText("CALENDAR_WEEK"), aMoreCountPerCell = [], aAppsPerDay = [], iCellIndex, iWeekNumber, oDay, aApps, aPreviousWeekApps, aPreviousWeekAppsPerDay = [], iMoreCount, iWeekMaxAppCount, i, j; for (i = 0; i < oControl._getRows(); i++) { iWeekMaxAppCount = 0; iWeekNumber = aVerticalLabels[i]; oRm.openStart("div"); oRm.attr("role", "grid"); oRm.class("sapMSPCMonthWeek"); oRm.openEnd(); // render week number oRm.openStart("div"); oRm.class("sapMSPCMonthWeekNumber"); oRm.attr("role", "row"); oRm.attr("id", `${oControl.getId()}-week-${iWeekNumber}`); oRm.attr("aria-label", `${sWeekText} ${iWeekNumber}`); oRm.openEnd(); oRm.openStart("span"); oRm.attr("role", "gridcell"); oRm.openEnd(); oRm.text(iWeekNumber); oRm.close("span"); oRm.close("div"); for (j = 0; j < iColumns; j++) { iCellIndex = i * iColumns + j; oDay = aCells[iCellIndex]; aApps = oControl._getAppointmetsForADay(oDay); aPreviousWeekApps = oControl._getPreviousAppointmetsForADay(oDay); aPreviousWeekAppsPerDay.push(aPreviousWeekApps); iMoreCount = oControl._aMoreCountPerDay[iCellIndex]; aMoreCountPerCell.push(iMoreCount); aAppsPerDay.push(aApps); iWeekMaxAppCount = Math.max(iWeekMaxAppCount, oControl._aAppsLevelsPerDay[iCellIndex].length); } oRm.openStart("div"); oRm.class("sapMSPCMonthDays"); oRm.class("sapMSPCMonthDaysMax" + iWeekMaxAppCount); oRm.attr("role", "row"); oRm.openEnd(); for (j = 0; j < iColumns; j++) { iCellIndex = i * iColumns + j; oDay = aCells[iCellIndex]; this.renderDay(oRm, oControl, oDay, iCellIndex, iWeekNumber); } oRm.openStart("div"); oRm.attr("role", "gridcell" ); oRm.openEnd(); oRm.openStart("div"); oRm.class("sapMSinglePCBlockers"); oRm.class("sapUiCalendarRowVisFilled"); oRm.attr("role", "list" ); oRm.openEnd(); for (j = 0; j < iColumns; j++) { iCellIndex = i * iColumns + j; oDay = aCells[iCellIndex]; // render appointments which started in previous rows if (j === 0) { this.renderAppointments(oRm, oControl, aPreviousWeekAppsPerDay[iCellIndex], j, aMoreCountPerCell[iCellIndex], oDensitySizes, i, oDay, aCells, iCellIndex); } this.renderAppointments(oRm, oControl, aAppsPerDay[iCellIndex], j, aMoreCountPerCell[iCellIndex], oDensitySizes, i, oDay, aCells, iCellIndex); } oRm.close("div"); // end appointments oRm.close("div"); oRm.close("div"); // end cells oRm.close("div"); // end grid } }; SinglePlanningCalendarMonthGridRenderer.renderDay = function(oRm, oControl, oDay, iCellIndex, iWeekNumber) { var aSpecialDates = oControl._getSpecialDates(), aDayTypes = Month.prototype._getDateTypes.call(oControl, oDay), oFormat = oControl._getDateFormatter(), bToday = oDay.isSame(CalendarDate.fromLocalJSDate(UI5Date.getInstance())), oType, sLegendItemType; oRm.openStart("div"); oRm.class("sapMSPCMonthDay"); if (oControl._checkDateSelected(oDay)) { oRm.class("sapMSPCMonthDaySelected"); } if (bToday) { oRm.class("sapMSPCMonthDayToday"); } oRm.attr("role", "gridcell"); if (oControl._isNonWorkingDay(oDay)) { oRm.class("nonWorkingTimeframe"); } if (aSpecialDates) { if (aDayTypes && aDayTypes[0]) { oType = aDayTypes[0]; oRm.class("sapUiCalendarSpecialDay" + oType.type); sLegendItemType = PlanningCalendarLegend.findLegendItemForItem(Element.getElementById(oControl._sLegendId), oType); } } oRm.attr("sap-ui-date", oDay.valueOf().toString()); oRm.attr("tabindex", -1); oRm.attr("aria-labelledby", `${oFormat.format(oDay.toLocalJSDate())}-Descr ${oControl.getId()}-week-${iWeekNumber}`); oRm.openEnd(); this.renderDndPlaceholder(oRm, oControl.getAggregation("_appsPlaceholders")[iCellIndex]); if (bToday) { oRm.openStart("div"); oRm.class("sapMSPCMonthNowMarker"); oRm.openEnd(); } oRm.openStart("div"); oRm.class("specialDateIndicator"); if (aDayTypes[0]?.color) { oRm.style("background-color", aDayTypes[0].color); } oRm.openEnd(); oRm.close("div"); //render day number oRm.openStart("div"); oRm.class("sapMSPCMonthDayNumber"); oRm.openEnd(); oRm.text(oDay.getDate()); oRm.close("div"); oRm.openStart("span", oFormat.format(oDay.toLocalJSDate()) + "-Descr"); oRm.class("sapUiInvisibleText"); oRm.openEnd(); oRm.text(oControl._getCellStartInfo(oDay)); //acc for day view + special dates + legend if (oControl._sLegendId && sLegendItemType) { oRm.text(sLegendItemType); } if (oControl._doesContainAppointments(oDay)) { oRm.text(oControl._getCellDescription()); } oRm.close("span"); if (bToday) { oRm.close("div"); // close today wrapper } oRm.close("div"); }; SinglePlanningCalendarMonthGridRenderer.renderAppointments = function(oRm, oControl, apps, iColumn, iMore, oDensitySizes, iRow, oDay, aDays, iCellIndex) { var MAX_APPS = oControl._getMaxAppointments(), iMaxLvl = iMore ? MAX_APPS - 2 : MAX_APPS - 1, iColumns = oControl._getColumns(), iRowEndIndex, oApp, bRenderDateOutsideRow; for (var i = 0; i < apps.length; i++) { oApp = apps[i]; iRowEndIndex = oControl._getRowEndIndex(aDays, aDays.indexOf(oDay), iColumns); if (oApp.level <= iMaxLvl) { bRenderDateOutsideRow = oApp._nextDay > iRowEndIndex; if (oApp._nextDay === undefined || bRenderDateOutsideRow) { continue; } this.renderAppointment(oRm, oControl, oApp, iColumn, oDensitySizes, iRow, oDay); if (oApp.level === iMaxLvl && iMore) { this.renderMoreLink(oRm, oControl, iMore, oDay, iColumn, iColumns, oApp, oDensitySizes, iCellIndex); } } else if (oApp._overflows) { //If it's an overflowing appointment, start from first available level of next day. oApp.level = oApp._nextDayLevel; if (oApp._nextDay && oApp._nextDayLevel < oControl._getMaxAppointments() - 1) { this.renderAppointment(oRm, oControl, oApp, oApp._nextDay, oDensitySizes, iRow, oDay); } } } }; SinglePlanningCalendarMonthGridRenderer.renderAppointment = function(oRm, oControl, app, iColumn, oDensitySizes, iRow, oDay) { var oAppointment = app.data, iWidth = app.width, iLevel = app.level, aCells = oControl._getCells(), iColumns = oControl._getColumns(), sTooltip = oAppointment.getTooltip_AsString(), sType = oAppointment.getType(), sColor = oAppointment.getColor(), sTitle = oAppointment.getTitle(), sText = oAppointment.getText(), sIcon = oAppointment.getIcon(), sId = oAppointment.getId(), oStartDate = oAppointment.getStartDate(), oEndDate = oAppointment.getEndDate(), oCustomDatas = oAppointment.getCustomData()?.filter((oCustomData) => oCustomData.getWriteToDom()), bHasCustomData = !!oCustomDatas?.length, aCustomContent = oAppointment.getCustomContent(), bHasCustomContent = !!aCustomContent.length, bIsFullDay = !oEndDate || oControl._isAllDayAppointment(oStartDate, oEndDate), oValue = bIsFullDay ? InvisibleText.getStaticId("sap.ui.unified", "CALENDAR_ALL_DAY_PREFIX") : InvisibleText.getStaticId("sap.ui.unified", "APPOINTMENT"), bDraggable = oAppointment.getParent().getEnableAppointmentsDragAndDrop(), oToday = oDay && oDay.isSame(CalendarDate.fromLocalJSDate(UI5Date.getInstance())), mAccProps = { role: "listitem", labelledby: { value: oValue, append: true }, // Prevents aria-selected from being added on the appointment selected: null }, iRight = iColumns - iColumn - iWidth, bIsRTL = Localization.getRTL(), sThemeName = Theming.getTheme(), iAppStartDateIndex = oControl._findStartDateIndex(aCells, app, oControl._iStartDayOffset), bFirstRenderedDayIsAfterStart = app._nextDay > iAppStartDateIndex, oNextDate = aCells[app._nextDay], iAppNextDateColumn = oControl._getDateColumn(aCells, oNextDate, iColumns), iAppNextDateRow = oControl._getDateRow(aCells, oNextDate, iColumns), bNextDateIsWithinRow = iAppNextDateRow === iRow, aClasses, iBorderThickness, iAppEndDateColumn, bAppContinuesOutsideCells, oEndCalendarDate; if (app._overflows || bNextDateIsWithinRow) { if (!app._partRendered) { app._partRendered = true; bFirstRenderedDayIsAfterStart = app._nextDay > iAppStartDateIndex; iColumn = iAppNextDateColumn; iRight = iColumns - iAppNextDateColumn + 1 - iWidth; oEndCalendarDate = CalendarDate.fromLocalJSDate(oEndDate); iAppEndDateColumn = oControl._getDateColumn(aCells, oEndCalendarDate, iColumns); if (iRight > 0 || bAppContinuesOutsideCells) { iRight = iColumns - iAppEndDateColumn - 1; if (iAppEndDateColumn < iColumn || bAppContinuesOutsideCells) { iRight = 0; } } } } if (app._overflows) { iLevel = app.level; } iBorderThickness = this.getBorderThickness(sThemeName, oToday); iRight = iRight < 0 ? 0 : iRight; if (!bHasCustomContent && sTitle) { mAccProps["labelledby"].value = `${mAccProps["labelledby"].value} ${sId}-${iColumn}_${iRow}-Title`; } // Put start/end information after the title mAccProps["labelledby"].value = `${mAccProps["labelledby"].value} ${sId}-${iColumn}_${iRow}-Descr`; if (!bHasCustomContent && sText) { mAccProps["labelledby"].value = `${mAccProps["labelledby"].value} ${sId}-${iColumn}_${iRow}-Text`; } if (oAppointment.getTentative()) { mAccProps["labelledby"].value = `${mAccProps["labelledby"].value} ${InvisibleText.getStaticId("sap.ui.unified", "APPOINTMENT_TENTATIVE")}`; } if (oAppointment.getSelected()) { mAccProps["describedby"] = { value: InvisibleText.getStaticId("sap.ui.unified", "APPOINTMENT_SELECTED"), append: true }; } oRm.openStart("div", oAppointment.getId() + "-" + iColumn + "_" + iRow); oRm.attr("draggable", bDraggable); oRm.attr("data-sap-ui-draggable", bDraggable); oRm.attr("data-sap-ui-related", oAppointment.getId()); oRm.attr("data-sap-level", iLevel); oRm.attr("data-sap-width", iWidth); oRm.attr("tabindex", 0); if (bHasCustomData) { oCustomDatas.forEach((oCustomData) => { oRm.attr(`data-${oCustomData.getKey()}`, oCustomData.getValue()); }); } if (sTooltip) { oRm.attr("title", sTooltip); } oRm.accessibilityState(oAppointment, mAccProps); oRm.class("sapMSinglePCAppointmentWrap"); oRm.class("sapUiCalendarRowApps"); // TODO: when refactor the CSS of appointments maybe we won't need this class if (!sColor && sType !== CalendarDayType.None) { oRm.class("sapUiCalendarApp" + sType); } if (sColor) { if (Localization.getRTL()) { oRm.style("border-right-color", sColor); } else { oRm.style("border-left-color", sColor); } } oRm.style(bIsRTL ? "right" : "left", "calc(" + (iColumn * 100) / iColumns + "% + " + iBorderThickness + "rem)"); oRm.style(bIsRTL ? "left" : "right", "calc(" + (iRight * 100) / iColumns + "% + " + iBorderThickness + "rem)"); oRm.style("top", (iLevel * oDensitySizes.appHeight + oDensitySizes.cellHeaderHeight) + "rem"); oRm.openEnd(); oRm.openStart("div"); oRm.class("sapUiCalendarApp"); if (oAppointment.getSelected()) { oRm.class("sapUiCalendarAppSel"); } if (oAppointment.getTentative()) { oRm.class("sapUiCalendarAppTent"); } if (sIcon) { oRm.class("sapUiCalendarAppWithIcon"); } oRm.openEnd(); // div element // extra content DIV to make some styling possible oRm.openStart("div"); oRm.class("sapUiCalendarAppCont"); if (sColor && !oAppointment.getSelected()) { oRm.style("background-color", oAppointment._getCSSColorForBackground(sColor)); } oRm.openEnd(); // div element if ((app.hasPrevious < 0 || app._overflows || bFirstRenderedDayIsAfterStart)) { aClasses = ["sapUiCalendarAppArrowIconLeft", "sapUiCalendarAppArrowIcon"]; oRm.icon("sap-icon://arrow-left", aClasses, { title: null, role: "img" }); } if (!bHasCustomContent && sIcon) { aClasses = ["sapUiCalendarAppIcon"]; var mAttributes = {}; mAttributes["id"] = `${sId}-${iColumn}_${iRow}-Icon`; mAttributes["title"] = null; mAttributes["role"] = "presentation"; oRm.icon(sIcon, aClasses, mAttributes); } if (!bHasCustomContent && sTitle) { oRm.openStart("span", `${sId}-${iColumn}_${iRow}-Title`); oRm.class("sapUiCalendarAppTitle"); oRm.openEnd(); // span element oRm.text(sTitle, true); oRm.close("span"); } if (bHasCustomContent) { aCustomContent.forEach(function (oContent) { oRm.renderControl(oContent); }); } if (app.hasNext < 0) { aClasses = ["sapUiCalendarAppArrowIconRight", "sapUiCalendarAppArrowIcon"]; oRm.icon("sap-icon://arrow-right", aClasses, { title: null, role: "img" }); } oRm.openStart("span", `${sId}-${iColumn}_${iRow}-Descr`); oRm.class("sapUiInvisibleText"); oRm.openEnd(); // span element oRm.text(oControl._getAppointmentAnnouncementInfo(oAppointment)); oRm.close("span"); oRm.close("div"); oRm.close("div"); oRm.close("div"); }; SinglePlanningCalendarMonthGridRenderer.renderMoreLink = function(oRm, oControl, iMore, oDay, iColumn, iColumns, app, oDensitySizes, iCellIndex) { const oFormat = oControl._getDateFormatter(); const sMoreLinkDescId = oFormat.format(oDay.toLocalJSDate()) + "-MoreLinkDesc"; const oToday = oDay && oDay.isSame(CalendarDate.fromLocalJSDate(UI5Date.getInstance())); const iBorderThickness = this.getBorderThickness(Theming.getTheme(), oToday); const iLevel = app.level; const iRight = iColumns - iColumn - 1; const bIsRTL = Localization.getRTL(); oRm.openStart("div"); oRm.attr("role", "listitem"); oRm.class("sapMSPCMonthLnkMore"); oRm.style(bIsRTL ? "right" : "left", "calc(" + ((iColumn) * 100) / (iColumns) + "% + " + iBorderThickness + "rem)"); oRm.style(bIsRTL ? "left" : "right", "calc(" + ((iRight ) * 100) / (iColumns) + "% + " + iBorderThickness + "rem)"); oRm.style("top", ((iLevel + 1) * oDensitySizes.appHeight + oDensitySizes.cellHeaderHeight) + "rem"); oRm.style("z-index", "1"); oRm.openEnd(); oRm.renderControl(oControl._getMoreLink(iMore, oDay, iCellIndex, sMoreLinkDescId)); oRm.openStart("span", sMoreLinkDescId); oRm.class("sapUiInvisibleText"); oRm.openEnd(); oRm.text(oControl._getMoreLinkDescription(iMore, oDay.toLocalJSDate())); oRm.close("span"); oRm.close("div"); }; SinglePlanningCalendarMonthGridRenderer.getBorderThickness = function(sThemeName, oToday) { if (sThemeName.includes("horizon")){ if (oToday) { return sThemeName.indexOf("_hc") ? 0.4375 : 0.0625; } return sThemeName.indexOf("_hc") ? 0.1875 : 0.0625; } if (oToday) { return sThemeName.indexOf("_hc") ? 0.3125 : 0.0625; } return sThemeName.indexOf("_hc") ? 0.125 : 0.0625; }; SinglePlanningCalendarMonthGridRenderer.renderDayNames = function(oRm, oControl, oLocaleData) { var iFirstDayOfWeek = oControl._getFirstDayOfWeek(), sId = oControl.getId(), sDayId, sCalendarType = Formatting.getCalendarType(), aWeekDays = oLocaleData.getDaysStandAlone("abbreviated", sCalendarType), aWeekDaysWide = oLocaleData.getDaysStandAlone("wide", sCalendarType), oStartDate = UI5Date.getInstance(oControl.getStartDate()), oFirstRenderedDate, iDayIndex; oStartDate.setDate(oStartDate.getDate() - oStartDate.getDay() + iFirstDayOfWeek); oFirstRenderedDate = CalendarDate.fromLocalJSDate(oStartDate); oRm.openStart("div", `${sId}-Names`); oRm.class("sapMSPCMonthDayNames"); oRm.openEnd(); // span element for (var i = 0; i < 7; i++) { iDayIndex = (i + iFirstDayOfWeek) % 7; sDayId = `${sId}-WH${iDayIndex}`; oRm.openStart("div", sDayId); oRm.class("sapUiCalWH"); if (i === 0) { oRm.class("sapUiCalFirstWDay"); } if (CalendarUtils._isWeekend(oFirstRenderedDate, oLocaleData)) { oRm.class("sapUiCalItemWeekEnd"); } oFirstRenderedDate.setDate(oFirstRenderedDate.getDate() + 1); oRm.accessibilityState(null, { label: aWeekDaysWide[iDayIndex] }); oRm.openEnd(); oRm.text(aWeekDays[iDayIndex % 7]); oRm.close("div"); } oRm.close("div"); }; SinglePlanningCalendarMonthGridRenderer.renderDndPlaceholder = function(oRm, oPlaceholder) { oRm.openStart("div"); oRm.class("sapMSinglePCOverlay"); oRm.openEnd(); // span element oRm.renderControl(oPlaceholder); oRm.close("div"); }; return SinglePlanningCalendarMonthGridRenderer; }, true /* bExport */);