@openui5/sap.ui.core 1.139.0 → 1.141.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRDPARTY.txt +2 -2
- package/package.json +1 -1
- package/src/jquery.sap.global.js +1 -1
- package/src/jquery.sap.mobile.js +0 -8
- package/src/jquery.sap.properties.js +1 -1
- package/src/jquery.sap.resources.js +1 -1
- package/src/jquery.sap.script.js +1 -1
- package/src/jquery.sap.storage.js +3 -3
- package/src/sap/base/Event.js +1 -1
- package/src/sap/base/Eventing.js +1 -1
- package/src/sap/base/config.js +1 -1
- package/src/sap/base/i18n/Formatting.js +1 -1
- package/src/sap/base/i18n/LanguageTag.js +9 -9
- package/src/sap/base/i18n/Localization.js +2 -2
- package/src/sap/base/i18n/date/TimezoneUtils.js +1 -1
- package/src/sap/base/security/URLListValidator.js +7 -3
- package/src/sap/base/security/encodeURL.js +1 -1
- package/src/sap/base/util/resolveReference.js +3 -1
- package/src/sap/base/util/restricted/_CancelablePromise.js +1 -1
- package/src/sap/base/util/restricted/_castArray.js +1 -1
- package/src/sap/base/util/restricted/_compact.js +1 -1
- package/src/sap/base/util/restricted/_curry.js +1 -1
- package/src/sap/base/util/restricted/_debounce.js +1 -1
- package/src/sap/base/util/restricted/_difference.js +1 -1
- package/src/sap/base/util/restricted/_differenceBy.js +1 -1
- package/src/sap/base/util/restricted/_differenceWith.js +1 -1
- package/src/sap/base/util/restricted/_flatMap.js +1 -1
- package/src/sap/base/util/restricted/_flatMapDeep.js +1 -1
- package/src/sap/base/util/restricted/_flatMapDepth.js +1 -1
- package/src/sap/base/util/restricted/_flatten.js +1 -1
- package/src/sap/base/util/restricted/_flattenDeep.js +1 -1
- package/src/sap/base/util/restricted/_flattenDepth.js +1 -1
- package/src/sap/base/util/restricted/_intersection.js +1 -1
- package/src/sap/base/util/restricted/_intersectionBy.js +1 -1
- package/src/sap/base/util/restricted/_intersectionWith.js +1 -1
- package/src/sap/base/util/restricted/_isEqual.js +1 -1
- package/src/sap/base/util/restricted/_isEqualWith.js +1 -1
- package/src/sap/base/util/restricted/_isNil.js +1 -1
- package/src/sap/base/util/restricted/_max.js +1 -1
- package/src/sap/base/util/restricted/_merge.js +1 -1
- package/src/sap/base/util/restricted/_mergeWith.js +1 -1
- package/src/sap/base/util/restricted/_min.js +1 -1
- package/src/sap/base/util/restricted/_omit.js +1 -1
- package/src/sap/base/util/restricted/_pick.js +1 -1
- package/src/sap/base/util/restricted/_pickBy.js +1 -1
- package/src/sap/base/util/restricted/_throttle.js +1 -1
- package/src/sap/base/util/restricted/_toArray.js +1 -1
- package/src/sap/base/util/restricted/_union.js +1 -1
- package/src/sap/base/util/restricted/_unionBy.js +1 -1
- package/src/sap/base/util/restricted/_unionWith.js +1 -1
- package/src/sap/base/util/restricted/_uniq.js +1 -1
- package/src/sap/base/util/restricted/_uniqBy.js +1 -1
- package/src/sap/base/util/restricted/_uniqWith.js +1 -1
- package/src/sap/base/util/restricted/_without.js +1 -1
- package/src/sap/base/util/restricted/_xor.js +1 -1
- package/src/sap/base/util/restricted/_xorBy.js +1 -1
- package/src/sap/base/util/restricted/_xorWith.js +1 -1
- package/src/sap/base/util/restricted/_zipObject.js +1 -1
- package/src/sap/base/util/restricted/_zipObjectDeep.js +1 -1
- package/src/sap/ui/Device.js +3 -3
- package/src/sap/ui/Global.js +3 -3
- package/src/sap/ui/base/BindingParser.js +22 -5
- package/src/sap/ui/base/DataType.js +1 -1
- package/src/sap/ui/base/Event.js +1 -1
- package/src/sap/ui/base/EventProvider.js +1 -1
- package/src/sap/ui/base/ExpressionParser.js +5 -1
- package/src/sap/ui/base/Interface.js +1 -1
- package/src/sap/ui/base/ManagedObject.js +1 -1
- package/src/sap/ui/base/ManagedObjectMetadata.js +3 -3
- package/src/sap/ui/base/Metadata.js +1 -1
- package/src/sap/ui/base/Object.js +1 -1
- package/src/sap/ui/base/ObjectPool.js +1 -1
- package/src/sap/ui/base/SyncPromise.js +3 -2
- package/src/sap/ui/core/.library +3 -3
- package/src/sap/ui/core/BusyIndicator.js +1 -1
- package/src/sap/ui/core/Component.js +1 -1
- package/src/sap/ui/core/ComponentContainer.js +2 -2
- package/src/sap/ui/core/ComponentMetadata.js +1 -1
- package/src/sap/ui/core/ComponentSupport.js +3 -3
- package/src/sap/ui/core/Configuration.js +4 -4
- package/src/sap/ui/core/Control.js +1 -1
- package/src/sap/ui/core/Core.js +2 -11
- package/src/sap/ui/core/CustomData.js +1 -1
- package/src/sap/ui/core/DeclarativeSupport.js +1 -1
- package/src/sap/ui/core/Element.js +3 -3
- package/src/sap/ui/core/ElementMetadata.js +1 -1
- package/src/sap/ui/core/EnabledPropagator.js +1 -1
- package/src/sap/ui/core/EventBus.js +1 -1
- package/src/sap/ui/core/Fragment.js +1 -1
- package/src/sap/ui/core/HTML.js +1 -1
- package/src/sap/ui/core/History.js +1 -1
- package/src/sap/ui/core/Icon.js +1 -1
- package/src/sap/ui/core/IndicationColorSupport.js +1 -1
- package/src/sap/ui/core/IntervalTrigger.js +1 -1
- package/src/sap/ui/core/InvisibleMessage.js +1 -1
- package/src/sap/ui/core/InvisibleRenderer.js +1 -1
- package/src/sap/ui/core/InvisibleText.js +1 -1
- package/src/sap/ui/core/Item.js +1 -1
- package/src/sap/ui/core/LabelEnablement.js +1 -1
- package/src/sap/ui/core/LayoutData.js +1 -1
- package/src/sap/ui/core/Lib.js +50 -140
- package/src/sap/ui/core/ListItem.js +1 -1
- package/src/sap/ui/core/LocalBusyIndicator.js +1 -1
- package/src/sap/ui/core/Locale.js +7 -7
- package/src/sap/ui/core/LocaleData.js +7 -4
- package/src/sap/ui/core/Manifest.js +1 -1
- package/src/sap/ui/core/Message.js +1 -1
- package/src/sap/ui/core/RenderManager.js +1 -1
- package/src/sap/ui/core/Renderer.js +1 -1
- package/src/sap/ui/core/ResizeHandler.js +1 -1
- package/src/sap/ui/core/ScrollBar.js +1 -1
- package/src/sap/ui/core/SeparatorItem.js +1 -1
- package/src/sap/ui/core/Theming.js +145 -76
- package/src/sap/ui/core/Title.js +1 -1
- package/src/sap/ui/core/TooltipBase.js +1 -1
- package/src/sap/ui/core/UIArea.js +1 -1
- package/src/sap/ui/core/UIComponent.js +16 -7
- package/src/sap/ui/core/UIComponentMetadata.js +1 -1
- package/src/sap/ui/core/ValueStateSupport.js +1 -1
- package/src/sap/ui/core/VariantLayoutData.js +1 -1
- package/src/sap/ui/core/XMLComposite.js +1 -1
- package/src/sap/ui/core/XMLCompositeMetadata.js +1 -1
- package/src/sap/ui/core/XMLTemplateProcessor.js +1 -1
- package/src/sap/ui/core/_IconRegistry.js +19 -39
- package/src/sap/ui/core/date/UI5Date.js +1 -1
- package/src/sap/ui/core/delegate/ItemNavigation.js +1 -1
- package/src/sap/ui/core/delegate/ScrollEnablement.js +1 -1
- package/src/sap/ui/core/dnd/DragDropBase.js +1 -1
- package/src/sap/ui/core/dnd/DragDropInfo.js +1 -1
- package/src/sap/ui/core/dnd/DragInfo.js +1 -1
- package/src/sap/ui/core/dnd/DropInfo.js +1 -1
- package/src/sap/ui/core/format/FormatUtils.js +1 -1
- package/src/sap/ui/core/format/NumberFormat.js +2 -2
- package/src/sap/ui/core/format/TimezoneUtil.js +1 -1
- package/src/sap/ui/core/getCompatibilityVersion.js +1 -1
- package/src/sap/ui/core/hyphenation/Hyphenation.js +1 -1
- package/src/sap/ui/core/library.js +3 -3
- package/src/sap/ui/core/message/ControlMessageProcessor.js +1 -1
- package/src/sap/ui/core/message/Message.js +1 -1
- package/src/sap/ui/core/message/MessageManager.js +1 -1
- package/src/sap/ui/core/message/MessageParser.js +1 -1
- package/src/sap/ui/core/message/MessageProcessor.js +1 -1
- package/src/sap/ui/core/messagebundle_ar.properties +26 -11
- package/src/sap/ui/core/messagebundle_bg.properties +21 -6
- package/src/sap/ui/core/messagebundle_ca.properties +24 -9
- package/src/sap/ui/core/messagebundle_cnr.properties +23 -8
- package/src/sap/ui/core/messagebundle_cs.properties +24 -9
- package/src/sap/ui/core/messagebundle_cy.properties +24 -9
- package/src/sap/ui/core/messagebundle_da.properties +21 -6
- package/src/sap/ui/core/messagebundle_de.properties +16 -1
- package/src/sap/ui/core/messagebundle_el.properties +26 -11
- package/src/sap/ui/core/messagebundle_en.properties +24 -9
- package/src/sap/ui/core/messagebundle_en_GB.properties +24 -9
- package/src/sap/ui/core/messagebundle_en_US_saprigi.properties +24 -9
- package/src/sap/ui/core/messagebundle_es.properties +21 -6
- package/src/sap/ui/core/messagebundle_es_MX.properties +24 -9
- package/src/sap/ui/core/messagebundle_et.properties +31 -16
- package/src/sap/ui/core/messagebundle_fi.properties +20 -5
- package/src/sap/ui/core/messagebundle_fr.properties +22 -7
- package/src/sap/ui/core/messagebundle_fr_CA.properties +20 -5
- package/src/sap/ui/core/messagebundle_hi.properties +24 -9
- package/src/sap/ui/core/messagebundle_hr.properties +20 -5
- package/src/sap/ui/core/messagebundle_hu.properties +23 -8
- package/src/sap/ui/core/messagebundle_id.properties +20 -5
- package/src/sap/ui/core/messagebundle_it.properties +23 -8
- package/src/sap/ui/core/messagebundle_iw.properties +21 -6
- package/src/sap/ui/core/messagebundle_ja.properties +19 -4
- package/src/sap/ui/core/messagebundle_kk.properties +22 -7
- package/src/sap/ui/core/messagebundle_ko.properties +20 -5
- package/src/sap/ui/core/messagebundle_lt.properties +20 -5
- package/src/sap/ui/core/messagebundle_lv.properties +20 -5
- package/src/sap/ui/core/messagebundle_mk.properties +25 -10
- package/src/sap/ui/core/messagebundle_ms.properties +24 -9
- package/src/sap/ui/core/messagebundle_nl.properties +22 -7
- package/src/sap/ui/core/messagebundle_no.properties +22 -7
- package/src/sap/ui/core/messagebundle_pl.properties +19 -4
- package/src/sap/ui/core/messagebundle_pt.properties +20 -5
- package/src/sap/ui/core/messagebundle_pt_PT.properties +18 -3
- package/src/sap/ui/core/messagebundle_ro.properties +22 -7
- package/src/sap/ui/core/messagebundle_ru.properties +19 -4
- package/src/sap/ui/core/messagebundle_sh.properties +23 -8
- package/src/sap/ui/core/messagebundle_sk.properties +23 -8
- package/src/sap/ui/core/messagebundle_sl.properties +20 -5
- package/src/sap/ui/core/messagebundle_sr.properties +23 -8
- package/src/sap/ui/core/messagebundle_sv.properties +23 -8
- package/src/sap/ui/core/messagebundle_th.properties +20 -5
- package/src/sap/ui/core/messagebundle_tr.properties +20 -5
- package/src/sap/ui/core/messagebundle_uk.properties +22 -7
- package/src/sap/ui/core/messagebundle_vi.properties +18 -3
- package/src/sap/ui/core/messagebundle_zh_CN.properties +24 -9
- package/src/sap/ui/core/messagebundle_zh_TW.properties +20 -5
- package/src/sap/ui/core/mvc/HTMLView.js +1 -1
- package/src/sap/ui/core/mvc/JSONView.js +1 -1
- package/src/sap/ui/core/mvc/JSView.js +1 -1
- package/src/sap/ui/core/mvc/TemplateView.js +1 -1
- package/src/sap/ui/core/mvc/View.js +2 -2
- package/src/sap/ui/core/mvc/XMLView.js +1 -1
- package/src/sap/ui/core/plugin/DeclarativeSupport.js +1 -1
- package/src/sap/ui/core/plugin/TemplatingSupport.js +1 -1
- package/src/sap/ui/core/postmessage/Bus.js +1 -1
- package/src/sap/ui/core/postmessage/confirmationDialog.js +1 -1
- package/src/sap/ui/core/routing/History.js +14 -5
- package/src/sap/ui/core/routing/Route.js +1 -1
- package/src/sap/ui/core/routing/Router.js +19 -1
- package/src/sap/ui/core/search/OpenSearchProvider.js +1 -1
- package/src/sap/ui/core/search/SearchProvider.js +1 -1
- package/src/sap/ui/core/service/Service.js +1 -1
- package/src/sap/ui/core/service/ServiceFactory.js +1 -1
- package/src/sap/ui/core/service/ServiceFactoryRegistry.js +1 -1
- package/src/sap/ui/core/support/Plugin.js +1 -1
- package/src/sap/ui/core/support/Support.js +1 -1
- package/src/sap/ui/core/support/ViewInfo.css +12 -12
- package/src/sap/ui/core/support/plugins/ControlTree.js +1 -1
- package/src/sap/ui/core/support/plugins/Interaction.js +1 -1
- package/src/sap/ui/core/support/plugins/LocalStorage.js +1 -1
- package/src/sap/ui/core/support/plugins/Performance.js +1 -1
- package/src/sap/ui/core/support/plugins/Selector.js +1 -1
- package/src/sap/ui/core/support/plugins/TechInfo.js +1 -1
- package/src/sap/ui/core/support/plugins/Trace.js +1 -1
- package/src/sap/ui/core/support/plugins/ViewInfo.js +1 -1
- package/src/sap/ui/core/support/techinfo/TechnicalInfo.js +1 -3
- package/src/sap/ui/core/support/trace/E2eTraceLib.js +13 -7
- package/src/sap/ui/core/themes/base/BrowserScrollbar.less +0 -28
- package/src/sap/ui/core/themes/base/ScrollBar.less +4 -0
- package/src/sap/ui/core/themes/base/base.less +80 -31
- package/src/sap/ui/core/themes/base/global.less +5 -0
- package/src/sap/ui/core/themes/base/shared.less +4 -1
- package/src/sap/ui/core/themes/base/skeleton.less +7 -3
- package/src/sap/ui/core/themes/sap_hcb/LocalBusyIndicator.less +4 -0
- package/src/sap/ui/core/themes/sap_hcb/base_LocalBusyIndicator.less +4 -0
- package/src/sap/ui/core/themes/sap_hcb/base_ScrollBar.less +4 -0
- package/src/sap/ui/core/theming/Parameters.js +729 -754
- package/src/sap/ui/core/theming/ThemeHelper.js +0 -77
- package/src/sap/ui/core/theming/ThemeManager.js +536 -526
- package/src/sap/ui/core/tmpl/DOMAttribute.js +1 -1
- package/src/sap/ui/core/tmpl/DOMElement.js +1 -1
- package/src/sap/ui/core/tmpl/HandlebarsTemplate.js +1 -1
- package/src/sap/ui/core/tmpl/Template.js +1 -1
- package/src/sap/ui/core/tmpl/TemplateControl.js +1 -1
- package/src/sap/ui/core/util/AsyncHintsHelper.js +1 -1
- package/src/sap/ui/core/util/DraftEnabledMockServer.js +47 -43
- package/src/sap/ui/core/util/Export.js +1 -1
- package/src/sap/ui/core/util/ExportCell.js +1 -1
- package/src/sap/ui/core/util/ExportColumn.js +1 -1
- package/src/sap/ui/core/util/ExportRow.js +1 -1
- package/src/sap/ui/core/util/ExportType.js +1 -1
- package/src/sap/ui/core/util/ExportTypeCSV.js +1 -1
- package/src/sap/ui/core/util/File.js +1 -1
- package/src/sap/ui/core/util/LibraryInfo.js +1 -1
- package/src/sap/ui/core/util/MockServer.js +1 -1
- package/src/sap/ui/core/util/PasteHelper.js +1 -1
- package/src/sap/ui/core/util/serializer/HTMLViewSerializer.js +1 -1
- package/src/sap/ui/core/util/serializer/Serializer.js +1 -1
- package/src/sap/ui/core/util/serializer/ViewSerializer.js +1 -1
- package/src/sap/ui/core/util/serializer/XMLViewSerializer.js +1 -1
- package/src/sap/ui/core/util/serializer/delegate/Delegate.js +1 -1
- package/src/sap/ui/core/util/serializer/delegate/HTML.js +1 -1
- package/src/sap/ui/core/util/serializer/delegate/XML.js +1 -1
- package/src/sap/ui/core/webc/WebComponent.js +93 -45
- package/src/sap/ui/core/webc/WebComponentMetadata.js +40 -6
- package/src/sap/ui/core/ws/ReadyState.js +1 -1
- package/src/sap/ui/core/ws/SapPcpWebSocket.js +1 -1
- package/src/sap/ui/core/ws/WebSocket.js +1 -1
- package/src/sap/ui/debug/ControlTree.js +1 -1
- package/src/sap/ui/debug/DebugEnv.js +1 -1
- package/src/sap/ui/debug/PropertyList.js +1 -1
- package/src/sap/ui/dom/includeStylesheet.js +4 -1
- package/src/sap/ui/events/F6Navigation.js +11 -3
- package/src/sap/ui/model/ClientModel.js +1 -1
- package/src/sap/ui/model/CompositeDataState.js +1 -1
- package/src/sap/ui/model/CompositeType.js +1 -1
- package/src/sap/ui/model/DataState.js +1 -1
- package/src/sap/ui/model/MetaModel.js +1 -1
- package/src/sap/ui/model/Model.js +7 -7
- package/src/sap/ui/model/SelectionModel.js +1 -1
- package/src/sap/ui/model/SimpleType.js +1 -1
- package/src/sap/ui/model/TreeAutoExpandMode.js +1 -1
- package/src/sap/ui/model/Type.js +1 -1
- package/src/sap/ui/model/json/JSONModel.js +1 -1
- package/src/sap/ui/model/json/TypedJSONContext.js +16 -0
- package/src/sap/ui/model/json/TypedJSONModel.js +16 -0
- package/src/sap/ui/model/message/MessageModel.js +1 -1
- package/src/sap/ui/model/odata/AnnotationHelper.js +1 -1
- package/src/sap/ui/model/odata/ODataAnnotations.js +1 -1
- package/src/sap/ui/model/odata/ODataMessageParser.js +1 -1
- package/src/sap/ui/model/odata/ODataMetaModel.js +1 -1
- package/src/sap/ui/model/odata/ODataMetadata.js +4 -4
- package/src/sap/ui/model/odata/ODataModel.js +1 -1
- package/src/sap/ui/model/odata/ODataTreeBindingFlat.js +33 -80
- package/src/sap/ui/model/odata/_AnnotationHelperExpression.js +2 -2
- package/src/sap/ui/model/odata/type/Boolean.js +1 -1
- package/src/sap/ui/model/odata/type/Byte.js +1 -1
- package/src/sap/ui/model/odata/type/Currency.js +1 -1
- package/src/sap/ui/model/odata/type/Date.js +1 -1
- package/src/sap/ui/model/odata/type/DateTime.js +1 -1
- package/src/sap/ui/model/odata/type/DateTimeBase.js +1 -1
- package/src/sap/ui/model/odata/type/DateTimeOffset.js +1 -1
- package/src/sap/ui/model/odata/type/DateTimeWithTimezone.js +1 -1
- package/src/sap/ui/model/odata/type/Decimal.js +1 -1
- package/src/sap/ui/model/odata/type/Double.js +1 -1
- package/src/sap/ui/model/odata/type/Guid.js +1 -1
- package/src/sap/ui/model/odata/type/Int.js +1 -1
- package/src/sap/ui/model/odata/type/Int16.js +1 -1
- package/src/sap/ui/model/odata/type/Int32.js +1 -1
- package/src/sap/ui/model/odata/type/Int64.js +1 -1
- package/src/sap/ui/model/odata/type/ODataType.js +1 -1
- package/src/sap/ui/model/odata/type/Raw.js +1 -1
- package/src/sap/ui/model/odata/type/SByte.js +1 -1
- package/src/sap/ui/model/odata/type/Single.js +1 -1
- package/src/sap/ui/model/odata/type/Stream.js +1 -1
- package/src/sap/ui/model/odata/type/String.js +1 -1
- package/src/sap/ui/model/odata/type/Time.js +1 -1
- package/src/sap/ui/model/odata/type/TimeOfDay.js +1 -1
- package/src/sap/ui/model/odata/type/Unit.js +1 -1
- package/src/sap/ui/model/odata/v2/Context.js +1 -1
- package/src/sap/ui/model/odata/v2/ODataAnnotations.js +1 -1
- package/src/sap/ui/model/odata/v2/ODataContextBinding.js +2 -2
- package/src/sap/ui/model/odata/v2/ODataListBinding.js +2 -2
- package/src/sap/ui/model/odata/v2/ODataModel.js +63 -67
- package/src/sap/ui/model/odata/v2/ODataTreeBinding.js +84 -70
- package/src/sap/ui/model/odata/v4/AnnotationHelper.js +11 -7
- package/src/sap/ui/model/odata/v4/Context.js +27 -27
- package/src/sap/ui/model/odata/v4/ODataBinding.js +44 -28
- package/src/sap/ui/model/odata/v4/ODataContextBinding.js +16 -15
- package/src/sap/ui/model/odata/v4/ODataListBinding.js +35 -23
- package/src/sap/ui/model/odata/v4/ODataMetaModel.js +81 -53
- package/src/sap/ui/model/odata/v4/ODataModel.js +40 -24
- package/src/sap/ui/model/odata/v4/ODataParentBinding.js +50 -19
- package/src/sap/ui/model/odata/v4/ODataPropertyBinding.js +3 -3
- package/src/sap/ui/model/odata/v4/_AnnotationHelperExpression.js +14 -14
- package/src/sap/ui/model/odata/v4/lib/_AggregationCache.js +68 -18
- package/src/sap/ui/model/odata/v4/lib/_Batch.js +10 -7
- package/src/sap/ui/model/odata/v4/lib/_Cache.js +64 -74
- package/src/sap/ui/model/odata/v4/lib/_GroupLock.js +1 -1
- package/src/sap/ui/model/odata/v4/lib/_Helper.js +15 -15
- package/src/sap/ui/model/odata/v4/lib/_MetadataConverter.js +35 -4
- package/src/sap/ui/model/odata/v4/lib/_Requestor.js +29 -16
- package/src/sap/ui/model/odata/v4/lib/_V2Requestor.js +2 -2
- package/src/sap/ui/model/resource/ResourceModel.js +1 -1
- package/src/sap/ui/model/type/Boolean.js +1 -1
- package/src/sap/ui/model/type/Currency.js +1 -1
- package/src/sap/ui/model/type/Date.js +1 -1
- package/src/sap/ui/model/type/DateInterval.js +1 -1
- package/src/sap/ui/model/type/DateTime.js +1 -1
- package/src/sap/ui/model/type/DateTimeInterval.js +1 -1
- package/src/sap/ui/model/type/FileSize.js +1 -1
- package/src/sap/ui/model/type/Float.js +1 -1
- package/src/sap/ui/model/type/Integer.js +1 -1
- package/src/sap/ui/model/type/String.js +1 -1
- package/src/sap/ui/model/type/Time.js +1 -1
- package/src/sap/ui/model/type/TimeInterval.js +1 -1
- package/src/sap/ui/model/type/Unit.js +19 -5
- package/src/sap/ui/model/xml/XMLModel.js +1 -1
- package/src/sap/ui/performance/XHRInterceptor.js +14 -9
- package/src/sap/ui/performance/trace/FESR.js +4 -11
- package/src/sap/ui/performance/trace/Passport.js +3 -10
- package/src/sap/ui/performance/trace/_InteractionImpl.js +4 -10
- package/src/sap/ui/qunit/utils/ControlIterator.js +1 -2
- package/src/sap/ui/qunit/utils/MemoryLeakCheck.js +1 -1
- package/src/sap/ui/test/TestUtils.js +27 -15
- package/src/sap/ui/test/generic/TestBase.js +1 -1
- package/src/sap/ui/test/generic/Utils.js +6 -6
- package/src/sap/ui/test/gherkin/dataTableUtils.js +2 -2
- package/src/sap/ui/test/opaQunit.js +3 -0
- package/src/sap/ui/thirdparty/caja-html-sanitizer.js +8 -2
- package/src/sap/ui/thirdparty/qunit-2.js +4 -1
- package/src/sap/ui/util/Mobile.js +0 -9
- package/src/sap/ui/util/Storage.js +1 -1
- package/src/sap/ui/util/isCrossOriginURL.js +1 -1
- package/src/ui5loader.js +1 -1
- package/ui5.yaml +0 -1
- package/src/sap/ui/core/plugin/LessSupport.js +0 -542
|
@@ -11,11 +11,8 @@ sap.ui.define([
|
|
|
11
11
|
"sap/base/future",
|
|
12
12
|
"sap/base/Log",
|
|
13
13
|
"sap/base/i18n/Localization",
|
|
14
|
-
"sap/base/
|
|
15
|
-
"sap/base/util/LoaderExtensions",
|
|
16
|
-
"sap/ui/Device",
|
|
14
|
+
"sap/ui/base/OwnStatics",
|
|
17
15
|
"sap/ui/VersionInfo",
|
|
18
|
-
"sap/ui/core/Lib",
|
|
19
16
|
"sap/ui/core/Theming",
|
|
20
17
|
"sap/ui/core/theming/ThemeHelper",
|
|
21
18
|
"sap/ui/dom/includeStylesheet"
|
|
@@ -25,73 +22,57 @@ sap.ui.define([
|
|
|
25
22
|
future,
|
|
26
23
|
Log,
|
|
27
24
|
Localization,
|
|
28
|
-
|
|
29
|
-
LoaderExtensions,
|
|
30
|
-
Device,
|
|
25
|
+
OwnStatics,
|
|
31
26
|
VersionInfo,
|
|
32
|
-
Library,
|
|
33
27
|
Theming,
|
|
34
28
|
ThemeHelper,
|
|
35
29
|
includeStylesheet
|
|
36
30
|
) {
|
|
37
31
|
"use strict";
|
|
38
32
|
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
// Collect all UI5 relevant CSS files which have been added upfront
|
|
48
|
-
// and add them to UI5 theming lifecycle
|
|
49
|
-
document.querySelectorAll(`link[id^=${_THEME_PREFIX}]`).forEach(function(linkNode) {
|
|
50
|
-
let bPreloadedCssReady = true;
|
|
51
|
-
const sLibId = linkNode.getAttribute("id").replace(_THEME_PREFIX, "");
|
|
52
|
-
|
|
53
|
-
mAllLoadedLibraries[sLibId] = {};
|
|
54
|
-
linkNode.removeAttribute("data-sap-ui-ready");
|
|
55
|
-
|
|
56
|
-
Log.info(`ThemeManager: Preloaded CSS for library ${sLibId} detected: ${linkNode.href}`, undefined, "sap.ui.core.theming.ThemeManager");
|
|
57
|
-
|
|
58
|
-
try {
|
|
59
|
-
bPreloadedCssReady = !!(linkNode.sheet?.href === linkNode.href && linkNode.sheet?.cssRules);
|
|
33
|
+
const CUSTOM_CSS_CHECK = /\.sapUiThemeDesignerCustomCss/i;
|
|
34
|
+
const MODULE_NAME = "sap.ui.core.theming.ThemeManager";
|
|
35
|
+
const CUSTOM_ID = "sap-ui-core-customcss";
|
|
36
|
+
const THEME_PREFIX = "sap-ui-theme-";
|
|
37
|
+
const LINK_ID_REGGEX_STRING = `^${THEME_PREFIX}(.*)`;
|
|
38
|
+
const LINK_ID_CHECK = new RegExp(LINK_ID_REGGEX_STRING);
|
|
39
|
+
const LINK_ID_WITH_VARIANT_CHECK = new RegExp(`${LINK_ID_REGGEX_STRING}-(?=\\[(.*)\\]).*$`);
|
|
60
40
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const bError = oEvent.type === "error";
|
|
65
|
-
linkNode.setAttribute("data-sap-ui-ready", !bError);
|
|
66
|
-
});
|
|
67
|
-
} else {
|
|
68
|
-
linkNode.setAttribute("data-sap-ui-ready", linkNode.sheet.cssRules.length > 0);
|
|
69
|
-
}
|
|
70
|
-
} catch (e) {
|
|
71
|
-
// If the stylesheet is cross-origin and throws a security error, we can't verify directly
|
|
72
|
-
Log.info("Could not detect ready state of preloaded CSS. Request stylesheet again to verify the response status", undefined, "sap.ui.core.theming.ThemeManager");
|
|
41
|
+
const oEventing = new Eventing();
|
|
42
|
+
const mAllLoadedLibraries = new Map();
|
|
43
|
+
const { attachChange, registerThemeManager, getThemePath } = OwnStatics.get(Theming);
|
|
73
44
|
|
|
74
|
-
|
|
45
|
+
let CORE_VERSION;
|
|
75
46
|
|
|
76
|
-
|
|
77
|
-
url: linkNode.href,
|
|
78
|
-
id: linkNode.getAttribute("id")
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
let _iCount = 0; // Prevent endless loop
|
|
47
|
+
let pAllCssRequests = Promise.resolve();
|
|
84
48
|
let _customCSSAdded = false;
|
|
85
49
|
let _themeCheckedForCustom = null;
|
|
86
|
-
let
|
|
87
|
-
let
|
|
88
|
-
let
|
|
50
|
+
let _sFallbackThemeFromMetadata = null;
|
|
51
|
+
let _sFallbackThemeFromThemeRoot = null;
|
|
52
|
+
let sUi5Version;
|
|
53
|
+
let mAllDistLibraries;
|
|
54
|
+
|
|
55
|
+
function isVersionInfoNeeded() {
|
|
56
|
+
const theme = Theming.getTheme();
|
|
57
|
+
return !ThemeHelper.isStandardTheme(theme) && Theming.getThemeRoot(theme);
|
|
58
|
+
}
|
|
59
|
+
// UI5 version is only needed in case a theming service is active but we always add it to the request
|
|
60
|
+
// therefore request it as early as possible
|
|
61
|
+
const versionInfoLoaded = VersionInfo.load().then((oVersionInfo) => {
|
|
62
|
+
sUi5Version = oVersionInfo.version;
|
|
63
|
+
mAllDistLibraries = new Set(oVersionInfo.libraries.map((library) => library.name));
|
|
64
|
+
}, (e) => {
|
|
65
|
+
if (isVersionInfoNeeded()) {
|
|
66
|
+
Log.error("UI5 theming lifecycle requires valid version information when a theming service is active. Please check why the version info could not be loaded in this system.", e, MODULE_NAME);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
89
69
|
|
|
90
70
|
/**
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
71
|
+
* The ThemeManager is responsible for managing and applying themes within the application.
|
|
72
|
+
* It handles the addition and updating of library CSS, including custom CSS if needed. It also
|
|
73
|
+
* detects and deals with UI5 relevant library CSS added to the DOM for preloading and includes
|
|
74
|
+
* them into the lifecycle. Additionally, it notifies subscribers after a theme has been applied,
|
|
75
|
+
* regardless of whether the theme was applied successfully or not.
|
|
95
76
|
*
|
|
96
77
|
* @namespace
|
|
97
78
|
* @author SAP SE
|
|
@@ -99,359 +80,437 @@ sap.ui.define([
|
|
|
99
80
|
* @ui5-restricted sap.ui.core
|
|
100
81
|
* @alias sap.ui.core.theming.ThemeManager
|
|
101
82
|
*/
|
|
102
|
-
|
|
83
|
+
const ThemeManager = {
|
|
103
84
|
/**
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
themeLoaded:
|
|
85
|
+
* Wether theme is already loaded or not
|
|
86
|
+
* @private
|
|
87
|
+
* @ui5-restricted sap.ui.core
|
|
88
|
+
*/
|
|
89
|
+
themeLoaded: true
|
|
90
|
+
};
|
|
109
91
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
* @private
|
|
114
|
-
* @ui5-restricted sap.ui.core
|
|
115
|
-
*/
|
|
116
|
-
checkThemeApplied : function() {
|
|
117
|
-
ThemeManager.reset();
|
|
118
|
-
delayedCheckTheme(true);
|
|
119
|
-
if (!_sThemeCheckId) {
|
|
120
|
-
ThemeManager.fireThemeApplied();
|
|
121
|
-
}
|
|
122
|
-
},
|
|
92
|
+
/**
|
|
93
|
+
* Helper functions
|
|
94
|
+
*/
|
|
123
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Retrieves the library info object for theming.
|
|
98
|
+
*
|
|
99
|
+
* If the library info object does not exist yet, it will be created and stored.
|
|
100
|
+
* Otherwise, the existing object is returned.
|
|
101
|
+
*
|
|
102
|
+
* @param {object} libInfo - The library info configuration.
|
|
103
|
+
* @param {string} libInfo.libName - The name of the library.
|
|
104
|
+
* @param {string} [libInfo.variant] - Optional variant name.
|
|
105
|
+
* @param {string} [libInfo.fileName] - Optional file name for the CSS file.
|
|
106
|
+
* @returns {object} The library info object with theming metadata and helper methods.
|
|
107
|
+
*/
|
|
108
|
+
function getLibraryInfo(libInfo) {
|
|
124
109
|
/**
|
|
125
|
-
*
|
|
110
|
+
* Creates a new library info object for theming purposes.
|
|
126
111
|
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
112
|
+
* The returned object contains metadata and helper methods for managing the theme CSS of a UI5 library,
|
|
113
|
+
* including its ID, name, link ID, CSS link element, loading state, variant, and file name.
|
|
114
|
+
* It also provides a method to generate the correct CSS URL for the library, considering RTL mode,
|
|
115
|
+
* variants, and versioning.
|
|
116
|
+
*
|
|
117
|
+
* If the ID matches the custom CSS ID, the file name and library name are set accordingly.
|
|
118
|
+
* The link ID and CSS link element are automatically determined.
|
|
119
|
+
*
|
|
120
|
+
* @param {object} libInfo - The library info configuration.
|
|
121
|
+
* @param {string} libInfo.id - The unique ID for the library info object.
|
|
122
|
+
* @param {string} libInfo.libName - The name of the library.
|
|
123
|
+
* @param {string} [libInfo.variant] - Optional variant name.
|
|
124
|
+
* @param {string} [libInfo.fileName] - Optional file name for the CSS file.
|
|
125
|
+
* @returns {object} The library info object with theming metadata and helper methods.
|
|
129
126
|
*/
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
127
|
+
function createLibraryInfoObject(libInfo) {
|
|
128
|
+
const oLibInfoTemplate = {
|
|
129
|
+
id: "",
|
|
130
|
+
libName: "",
|
|
131
|
+
linkId: "",
|
|
132
|
+
cssLinkElement: null,
|
|
133
|
+
cssLoaded: null,
|
|
134
|
+
failed: false,
|
|
135
|
+
customCss: false,
|
|
136
|
+
fileName: "library",
|
|
137
|
+
variant: "",
|
|
138
|
+
themeFallback: false,
|
|
139
|
+
getUrl: function(sTheme) {
|
|
140
|
+
const buildUrl = (skipVersionInfo) => {
|
|
141
|
+
sTheme ??= Theming.getTheme();
|
|
142
|
+
/**
|
|
143
|
+
* Custom libs which are not part of the DIST layer have no custom theme
|
|
144
|
+
* except they provide it as part of the library (no themeroots for the custom library)
|
|
145
|
+
*/
|
|
146
|
+
if (mAllDistLibraries && !mAllDistLibraries.has(this.libName) &&
|
|
147
|
+
!ThemeHelper.isStandardTheme(sTheme) && Theming.getThemeRoot(sTheme, this.libName)) {
|
|
148
|
+
sTheme = _sFallbackThemeFromMetadata || _sFallbackThemeFromThemeRoot;
|
|
149
|
+
if (!sTheme) {
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const sCssBasePath = new URL(getThemePath(this.libName, sTheme), document.baseURI).toString();
|
|
154
|
+
const sVariant = this.variant || "";
|
|
155
|
+
let sCssPath;
|
|
156
|
+
|
|
157
|
+
/*
|
|
158
|
+
* Create the library file name.
|
|
159
|
+
* By specifying a library name containing a colon (":") you can specify
|
|
160
|
+
* the file name of the CSS file to include (ignoring RTL).
|
|
161
|
+
*/
|
|
162
|
+
const iIdx = this.libName.indexOf(":");
|
|
163
|
+
if (this.libName && iIdx == -1) {
|
|
164
|
+
sCssPath = `${sCssBasePath}${this.fileName}${sVariant}${Localization.getRTL() ? "-RTL" : ""}.css`;
|
|
165
|
+
} else {
|
|
166
|
+
sCssPath = `${sCssBasePath}${this.libName.substring(iIdx + 1)}${sVariant}.css`;
|
|
167
|
+
}
|
|
168
|
+
// Create a link tag and set the URL as href in order to ensure AppCacheBuster handling.
|
|
169
|
+
// AppCacheBuster ID is added to the href by defineProperty for the "href" property of
|
|
170
|
+
// HTMLLinkElement in AppCacheBuster.js
|
|
171
|
+
// Note: Considered to use AppCacheBuster.js#convertURL for adding the AppCachebuster ID
|
|
172
|
+
// but there would be a dependency to AppCacheBuster as trade-off
|
|
173
|
+
const oTmpLink = document.createElement("link");
|
|
174
|
+
oTmpLink.href = `${sCssPath}${skipVersionInfo ? "" : `?sap-ui-dist-version=${sUi5Version || CORE_VERSION || ""}`}`;
|
|
175
|
+
return oTmpLink.href;
|
|
176
|
+
};
|
|
177
|
+
return {
|
|
178
|
+
urlPromise: versionInfoLoaded.then(buildUrl),
|
|
179
|
+
url: buildUrl(),
|
|
180
|
+
baseUrl: buildUrl(true)
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
};
|
|
140
184
|
|
|
141
|
-
|
|
142
|
-
* Includes a library theme into the current page (if a variant is specified it
|
|
143
|
-
* will include the variant library theme) and ensure theme root
|
|
144
|
-
* @param {object} [oLibThemingInfo] to be used only by the Core
|
|
145
|
-
* @private
|
|
146
|
-
* @ui5-restricted sap.ui.core
|
|
147
|
-
*/
|
|
148
|
-
_includeLibraryThemeAndEnsureThemeRoot: function(oLibThemingInfo) {
|
|
149
|
-
var sLibName = oLibThemingInfo.name;
|
|
150
|
-
// ensure to register correct library theme module path even when "preloadLibCss" prevents
|
|
151
|
-
// including the library theme as controls might use it to calculate theme-specific URLs
|
|
152
|
-
_ensureThemeRoot(sLibName, Theming.getTheme());
|
|
153
|
-
|
|
154
|
-
// also ensure correct theme root for the library's base theme which might be relevant in some cases
|
|
155
|
-
// (e.g. IconPool which includes font files from sap.ui.core base theme)
|
|
156
|
-
_ensureThemeRoot(sLibName, "base");
|
|
157
|
-
|
|
158
|
-
// Assume CSS is preloaded in case we detect a link tag with corresponding ID
|
|
159
|
-
const sLinkId = `${sLibName}${oLibThemingInfo.variant ? "-[" + oLibThemingInfo.variant + "]" : ""}`;
|
|
160
|
-
oLibThemingInfo.preloadedCss = oLibThemingInfo.preloadedCss || !!mAllLoadedLibraries[sLinkId];
|
|
161
|
-
mAllLoadedLibraries[sLinkId] = oLibThemingInfo;
|
|
162
|
-
if (!oLibThemingInfo.preloadedCss) {
|
|
163
|
-
ThemeManager.includeLibraryTheme(sLibName, oLibThemingInfo.variant, oLibThemingInfo);
|
|
164
|
-
}
|
|
165
|
-
},
|
|
185
|
+
const newLibInfo = Object.assign(oLibInfoTemplate, libInfo);
|
|
166
186
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
* @param {string} sLibName the name of the UI library
|
|
171
|
-
* @param {string} [sVariant] the variant to include (optional)
|
|
172
|
-
* @param {string|object} [vQueryOrLibInfo] to be used only by the Core
|
|
173
|
-
* @private
|
|
174
|
-
* @ui5-restricted sap.ui.core
|
|
175
|
-
*/
|
|
176
|
-
includeLibraryTheme: function(sLibName, sVariant, vQueryOrLibInfo) {
|
|
177
|
-
assert(typeof sLibName === "string", "sLibName must be a string");
|
|
178
|
-
assert(sVariant === undefined || typeof sVariant === "string", "sVariant must be a string or undefined");
|
|
179
|
-
var sQuery = vQueryOrLibInfo;
|
|
180
|
-
|
|
181
|
-
if (typeof sQuery === "object") {
|
|
182
|
-
// check for configured query parameters and use them
|
|
183
|
-
sQuery = getLibraryCssQueryParams(vQueryOrLibInfo);
|
|
187
|
+
if (newLibInfo.id === CUSTOM_ID) {
|
|
188
|
+
newLibInfo.fileName = "custom";
|
|
189
|
+
newLibInfo.libName = "sap.ui.core";
|
|
184
190
|
}
|
|
185
191
|
|
|
192
|
+
newLibInfo.linkId = `${newLibInfo.id === CUSTOM_ID ? "" : THEME_PREFIX}${newLibInfo.id}`;
|
|
193
|
+
newLibInfo.cssLinkElement ??= document.querySelector(`link[id='${newLibInfo.linkId}']`);
|
|
194
|
+
|
|
195
|
+
return newLibInfo;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
libInfo.id ??= `${libInfo.libName}${libInfo.variant ? `-[${libInfo.variant}]` : ""}`;
|
|
199
|
+
|
|
200
|
+
if (!mAllLoadedLibraries.has(libInfo.id)) {
|
|
201
|
+
libInfo = createLibraryInfoObject(libInfo);
|
|
202
|
+
mAllLoadedLibraries.set(libInfo.id, libInfo);
|
|
203
|
+
} else {
|
|
204
|
+
libInfo = mAllLoadedLibraries.get(libInfo.id);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return libInfo;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Includes a library theme into the current page (if a variant is specified it
|
|
212
|
+
* will include the variant library theme)
|
|
213
|
+
* @param {string} libraryInfo the library info object
|
|
214
|
+
* @private
|
|
215
|
+
* @ui5-restricted sap.ui.core
|
|
216
|
+
*/
|
|
217
|
+
function includeLibraryTheme(libraryInfo) {
|
|
218
|
+
const { libName, variant, version } = libraryInfo;
|
|
219
|
+
assert(typeof libName === "string", "libName must be a string");
|
|
220
|
+
assert(variant === undefined || typeof variant === "string", "variant must be a string or undefined");
|
|
221
|
+
|
|
222
|
+
if (libName === "sap.ui.core") {
|
|
223
|
+
CORE_VERSION = version;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (!mAllLoadedLibraries.has(libName)) {
|
|
186
227
|
/**
|
|
187
228
|
* include the stylesheet for the library (except for "classic" and "legacy" lib)
|
|
188
229
|
* @deprecated
|
|
189
230
|
*/
|
|
190
|
-
if (
|
|
231
|
+
if (libName === "sap.ui.legacy" || libName === "sap.ui.classic") {
|
|
191
232
|
return;
|
|
192
233
|
}
|
|
193
234
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// determine RTL
|
|
200
|
-
var sRtl = (Localization.getRTL() ? "-RTL" : "");
|
|
235
|
+
const oLibInfo = getLibraryInfo({
|
|
236
|
+
libName,
|
|
237
|
+
variant
|
|
238
|
+
});
|
|
201
239
|
|
|
240
|
+
if (!oLibInfo.cssLinkElement) {
|
|
241
|
+
updateThemeUrl({
|
|
242
|
+
libInfo: oLibInfo,
|
|
243
|
+
suppressFOUC: true
|
|
244
|
+
});
|
|
202
245
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
* By specifying a library name containing a colon (":") you can specify
|
|
206
|
-
* the file name of the CSS file to include (ignoring RTL).
|
|
207
|
-
*/
|
|
208
|
-
var sLibFileName,
|
|
209
|
-
sLibId = sLibName + (sVariant.length > 0 ? "-[" + sVariant + "]" : sVariant);
|
|
210
|
-
if (sLibName && sLibName.indexOf(":") == -1) {
|
|
211
|
-
sLibFileName = "library" + sVariant + sRtl;
|
|
212
|
-
} else {
|
|
213
|
-
sLibFileName = sLibName.substring(sLibName.indexOf(":") + 1) + sVariant;
|
|
214
|
-
sLibName = sLibName.substring(0, sLibName.indexOf(":"));
|
|
246
|
+
// if parameters have been used, update them with the new style sheet
|
|
247
|
+
sap.ui.require("sap/ui/core/theming/Parameters")?._addLibraryTheme(oLibInfo.id);
|
|
215
248
|
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
216
251
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
252
|
+
/**
|
|
253
|
+
* Adds or updates the CSS link element for the specified library info object and theme.
|
|
254
|
+
*
|
|
255
|
+
* If a link element for the library already exists, this function compares the current stylesheet URL
|
|
256
|
+
* with the new one for the given theme and determines whether an update is necessary.
|
|
257
|
+
* If the URLs differ, it loads the new stylesheet, manages the loading state, handles FOUC (Flash of Unstyled Content) markers,
|
|
258
|
+
* and updates the internal state accordingly. The function also triggers theme lifecycle events such as success, failure,
|
|
259
|
+
* and completion, and manages the global themeLoaded flag.
|
|
260
|
+
*
|
|
261
|
+
* Additionally, the function adds the CSS loading promise to the collection of all requested CSS promises,
|
|
262
|
+
* ensuring that the themeApplied event is fired only after all CSS files have finished loading.
|
|
263
|
+
*
|
|
264
|
+
* @param {object} params - Parameters for updating the theme URL.
|
|
265
|
+
* @param {object} params.libInfo - The library info object containing theming metadata.
|
|
266
|
+
* @param {string} params.theme - The name of the theme to apply.
|
|
267
|
+
* @param {boolean} params.suppressFOUC - Whether to suppress Flash of Unstyled Content (FOUC) handling.
|
|
268
|
+
* @param {boolean} params.force - Whether to including stylesheet regardless the baseUrl is identical or not.
|
|
269
|
+
* Use the old URL to prevent unnecessary requests.
|
|
270
|
+
*/
|
|
271
|
+
function updateThemeUrl({libInfo, theme, suppressFOUC, force}) {
|
|
272
|
+
if (suppressFOUC) {
|
|
273
|
+
pAllCssRequests = Promise.resolve();
|
|
274
|
+
ThemeManager.themeLoaded = false;
|
|
275
|
+
Log.debug(`Register theme change for library ${libInfo.id}`, undefined, MODULE_NAME);
|
|
276
|
+
}
|
|
277
|
+
if (!sUi5Version && isVersionInfoNeeded()) {
|
|
278
|
+
Log.error("UI5 theming lifecycle requires valid version information when a theming service is active. Please check why the version info could not be loaded in this system.", undefined, MODULE_NAME);
|
|
279
|
+
}
|
|
280
|
+
// Compare the link including the UI5 version only if it is already available; otherwise, compare the link without the version to prevent unnecessary requests.
|
|
281
|
+
const sOldUrl = libInfo.cssLinkElement?.getAttribute("href");
|
|
282
|
+
const sOldUrlWoVersion = sOldUrl?.replace(/\?.*/, "");
|
|
283
|
+
const sUrl = libInfo.getUrl(theme).baseUrl;
|
|
284
|
+
if (!sUrl || sOldUrlWoVersion !== sUrl || force) {
|
|
285
|
+
libInfo.finishedLoading = false;
|
|
286
|
+
libInfo.failed = false;
|
|
287
|
+
if (suppressFOUC) {
|
|
288
|
+
// Only add stylesheet in case there is no existing stylesheet or the href is different
|
|
229
289
|
// use the special FOUC handling for initially existing stylesheets
|
|
230
290
|
// to ensure that they are not just replaced when using the
|
|
231
291
|
// includeStyleSheet API and to be removed later
|
|
232
|
-
fnAddFoucmarker(
|
|
233
|
-
|
|
234
|
-
// log and include
|
|
235
|
-
Log.info("Including " + sCssPathAndName + " - sap.ui.core.theming.ThemeManager.includeLibraryTheme()");
|
|
236
|
-
includeStylesheet(sCssPathAndName, sLinkId);
|
|
237
|
-
|
|
238
|
-
// if parameters have been used, update them with the new style sheet
|
|
239
|
-
var Parameters = sap.ui.require("sap/ui/core/theming/Parameters");
|
|
240
|
-
if (Parameters) {
|
|
241
|
-
Parameters._addLibraryTheme(sLibId);
|
|
242
|
-
}
|
|
243
|
-
ThemeManager.checkThemeApplied();
|
|
292
|
+
fnAddFoucmarker(libInfo.linkId);
|
|
244
293
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
* @param {string} sThemeName The name of the theme to update
|
|
269
|
-
* @param {boolean} bSuppressFOUC If FOUC-Marker should be added or not
|
|
270
|
-
* @private
|
|
271
|
-
* @ui5-restricted sap.ui.core.Core
|
|
272
|
-
*/
|
|
273
|
-
_updateThemeUrls: function(sThemeName, bSuppressFOUC) {
|
|
274
|
-
// select "our" stylesheets
|
|
275
|
-
var oQueryResult = document.querySelectorAll(`link[id^=${_THEME_PREFIX}]`);
|
|
276
|
-
|
|
277
|
-
Array.prototype.forEach.call(oQueryResult, function(oHTMLElement) {
|
|
278
|
-
updateThemeUrl(oHTMLElement, sThemeName, bSuppressFOUC);
|
|
279
|
-
});
|
|
280
|
-
},
|
|
281
|
-
/**
|
|
282
|
-
* Attach to the theme applied event
|
|
283
|
-
*
|
|
284
|
-
* @param {function(module:sap/ui/core/Theming$AppliedEvent)} fnCallback The event handler
|
|
285
|
-
* @private
|
|
286
|
-
* @ui5-restricted sap.ui.core
|
|
287
|
-
*/
|
|
288
|
-
_attachThemeApplied: function (fnCallback) {
|
|
289
|
-
oEventing.attachEvent("applied", fnCallback);
|
|
290
|
-
},
|
|
291
|
-
/**
|
|
292
|
-
* Detach from the theme applied event
|
|
293
|
-
*
|
|
294
|
-
* @param {function(module:sap/ui/core/Theming$AppliedEvent)} fnCallback The event handler
|
|
295
|
-
* @private
|
|
296
|
-
* @ui5-restricted sap.ui.core
|
|
297
|
-
*/
|
|
298
|
-
_detachThemeApplied: function (fnCallback) {
|
|
299
|
-
oEventing.detachEvent("applied", fnCallback);
|
|
300
|
-
},
|
|
301
|
-
/**
|
|
302
|
-
* Notify theme change
|
|
303
|
-
*
|
|
304
|
-
* @private
|
|
305
|
-
* @ui5-restricted sap.ui.core
|
|
306
|
-
*/
|
|
307
|
-
fireThemeApplied: function () {
|
|
308
|
-
ThemeHelper.reset();
|
|
309
|
-
// special hook for resetting theming parameters before the controls get
|
|
310
|
-
// notified (lightweight coupling to static Parameters module)
|
|
311
|
-
var ThemeParameters = sap.ui.require("sap/ui/core/theming/Parameters");
|
|
312
|
-
if (ThemeParameters) {
|
|
313
|
-
ThemeParameters._reset(/* bOnlyWhenNecessary= */ true);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
oEventing.fireEvent("applied", {
|
|
317
|
-
theme: Theming.getTheme()
|
|
294
|
+
const pCssLoaded = libInfo.getUrl(theme).urlPromise.then((sUrl) => {
|
|
295
|
+
if (sUrl) {
|
|
296
|
+
Log.debug(`Add new CSS for library ${libInfo.id} with URL: ${sUrl}`, undefined, MODULE_NAME);
|
|
297
|
+
return includeStylesheet({
|
|
298
|
+
url: force ? sOldUrl : sUrl,
|
|
299
|
+
id: libInfo.linkId
|
|
300
|
+
});
|
|
301
|
+
} else {
|
|
302
|
+
// If there is no URL, a theme fallback must be detected first.
|
|
303
|
+
// We reject here because and add only a placeholder link element to the DOM.
|
|
304
|
+
// The handleThemeFailed function will process this rejection and apply the fallback
|
|
305
|
+
// theme for the library once it has been detected.
|
|
306
|
+
const oLink = document.createElement("link");
|
|
307
|
+
oLink.setAttribute("id", libInfo.linkId);
|
|
308
|
+
oLink.setAttribute("rel", "stylesheet");
|
|
309
|
+
if (libInfo.cssLinkElement) {
|
|
310
|
+
libInfo.cssLinkElement.parentNode.replaceChild(oLink, libInfo.cssLinkElement);
|
|
311
|
+
} else {
|
|
312
|
+
document.head.insertBefore(oLink, document.getElementById(CUSTOM_ID));
|
|
313
|
+
}
|
|
314
|
+
libInfo.cssLinkElement = oLink;
|
|
315
|
+
return Promise.reject();
|
|
316
|
+
}
|
|
318
317
|
});
|
|
319
|
-
}
|
|
320
|
-
};
|
|
321
318
|
|
|
319
|
+
if (libInfo.cssLoaded) {
|
|
320
|
+
libInfo.cssLoaded.aborted = true;
|
|
321
|
+
}
|
|
322
322
|
|
|
323
|
-
|
|
324
|
-
var sThemeName = Theming.getTheme();
|
|
325
|
-
var sPath = ThemeManager._getThemePath("sap.ui.core", sThemeName) + "custom.css";
|
|
326
|
-
var bIsStandardTheme = ThemeHelper.isStandardTheme(Theming.getTheme());
|
|
327
|
-
var res = true;
|
|
328
|
-
|
|
329
|
-
var aFailedLibs = [];
|
|
330
|
-
|
|
331
|
-
if (_customCSSAdded && _themeCheckedForCustom === sThemeName) {
|
|
332
|
-
// include custom style sheet here because it has already been added using sap/ui/dom/includeStyleSheet
|
|
333
|
-
// hence, needs to be checked for successful inclusion, too
|
|
334
|
-
mAllLoadedLibraries[_CUSTOMID] = {};
|
|
323
|
+
includeStyleSheetPostProcessing(libInfo, pCssLoaded, suppressFOUC);
|
|
335
324
|
}
|
|
325
|
+
}
|
|
336
326
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
327
|
+
/**
|
|
328
|
+
* Handles post-processing of CSS link elements after they have been requested.
|
|
329
|
+
*
|
|
330
|
+
* This function manages the lifecycle of CSS loading for a library by attaching handlers to the CSS loading promise.
|
|
331
|
+
* It handles success and failure cases, as well as generic post-processing that occurs regardless of the request status.
|
|
332
|
+
* The function is responsible for:
|
|
333
|
+
*
|
|
334
|
+
* 1. Managing the loading state of the CSS for the library
|
|
335
|
+
* 2. Removing FOUC (Flash of Unstyled Content) markers when loading completes
|
|
336
|
+
* 3. Updating references to the CSS link element
|
|
337
|
+
* 4. Triggering appropriate theme lifecycle events (success, failure, completion)
|
|
338
|
+
* 5. Updating the global CSS request promise collection
|
|
339
|
+
* 6. Managing the global theme loaded state
|
|
340
|
+
* 7. Firing the "applied" event when all CSS requests have completed
|
|
341
|
+
*
|
|
342
|
+
* The function uses promise chaining to ensure proper sequencing of operations and to handle
|
|
343
|
+
* both successful and failed CSS loading scenarios. It also includes an abort mechanism to
|
|
344
|
+
* prevent stale CSS requests from affecting the UI when a new request supersedes them.
|
|
345
|
+
*
|
|
346
|
+
* @param {object} libInfo - The library info object containing metadata about the library and its CSS
|
|
347
|
+
* @param {Promise} cssLoadededPromise - The promise that resolves when the CSS has been loaded
|
|
348
|
+
* @param {boolean} suppressFOUC - Whether to suppress Flash of Unstyled Content during theme changes
|
|
349
|
+
*/
|
|
350
|
+
function includeStyleSheetPostProcessing(libInfo, cssLoadededPromise, suppressFOUC) {
|
|
351
|
+
libInfo.cssLoaded = cssLoadededPromise.finally(function() {
|
|
352
|
+
if (!libInfo.cssLoaded.aborted) {
|
|
353
|
+
libInfo.finishedLoading = true;
|
|
354
|
+
document.querySelector(`link[data-sap-ui-foucmarker='${libInfo.linkId}']`)?.remove();
|
|
355
|
+
libInfo.cssLinkElement = document.getElementById(`${libInfo.linkId}`);
|
|
356
|
+
Log.debug(`New stylesheet loaded and old stylesheet removed for library: ${libInfo.id}`, undefined, MODULE_NAME);
|
|
357
|
+
}
|
|
358
|
+
}).then(function() {
|
|
359
|
+
if (!libInfo.cssLoaded.aborted) {
|
|
360
|
+
handleThemeSucceeded(libInfo.id);
|
|
361
|
+
}
|
|
362
|
+
}).catch(function() {
|
|
363
|
+
if (!libInfo.cssLoaded.aborted) {
|
|
364
|
+
handleThemeFailed(libInfo.id);
|
|
365
|
+
}
|
|
366
|
+
}).finally(function() {
|
|
367
|
+
if (!libInfo.cssLoaded.aborted) {
|
|
368
|
+
handleThemeFinished(libInfo.id);
|
|
369
|
+
pAllCssRequests = Promise.allSettled([...mAllLoadedLibraries.values()].map((libInfo) => libInfo.cssLoaded));
|
|
370
|
+
pAllCssRequests.finally(function() {
|
|
371
|
+
if (this === pAllCssRequests) {
|
|
372
|
+
Log.debug("Theme change finished", undefined, MODULE_NAME);
|
|
373
|
+
// Even if suppressFOUC is not set, we must fire the event if themeLoaded was previously set to false,
|
|
374
|
+
// because this indicates that at least one theme change was caused by a theming-relevant trigger.
|
|
375
|
+
if (suppressFOUC || !ThemeManager.themeLoaded) {
|
|
376
|
+
ThemeManager.themeLoaded = true;
|
|
377
|
+
oEventing.fireEvent("applied", {
|
|
378
|
+
theme: Theming.getTheme()
|
|
379
|
+
});
|
|
373
380
|
}
|
|
374
|
-
_customCSSAdded = false;
|
|
375
381
|
}
|
|
376
|
-
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
// Collect all libs that failed to load and no fallback has been applied, yet.
|
|
381
|
-
// The fallback relies on custom theme metadata, so it is not done for standard themes
|
|
382
|
-
if (!bIsStandardTheme && currentRes && !_mThemeFallback[lib]) {
|
|
383
|
-
var oStyle = document.getElementById(`${_THEME_PREFIX}${lib}`);
|
|
384
|
-
// Check for error marker (data-sap-ui-ready=false) and that there are no rules
|
|
385
|
-
// to be sure the stylesheet couldn't be loaded at all.
|
|
386
|
-
// E.g. in case an @import within the stylesheet fails, the error marker will
|
|
387
|
-
// also be set, but in this case no fallback should be done as there is a (broken) theme
|
|
388
|
-
if (oStyle && oStyle.getAttribute("data-sap-ui-ready") === "false" &&
|
|
389
|
-
!(oStyle.sheet && ThemeHelper.hasSheetCssRules(oStyle.sheet))
|
|
390
|
-
) {
|
|
391
|
-
aFailedLibs.push(lib);
|
|
392
|
-
}
|
|
382
|
+
}.bind(pAllCssRequests));
|
|
393
383
|
}
|
|
384
|
+
});
|
|
385
|
+
}
|
|
394
386
|
|
|
387
|
+
/**
|
|
388
|
+
* Updates all existing CSS link elements to reflect the provided theme.
|
|
389
|
+
*
|
|
390
|
+
* This function iterates over all loaded library info objects and updates their CSS link elements
|
|
391
|
+
* to ensure they point to the correct theme resources. It guarantees that all CSS links are up-to-date
|
|
392
|
+
* with respect to the given theme, RTL mode, SAP UI5 distribution version, and theme roots.
|
|
393
|
+
*
|
|
394
|
+
* @param {string} themeName - The name of the theme to apply.
|
|
395
|
+
* @param {boolean} suppressFOUC - Whether to suppress Flash of Unstyled Content (FOUC) handling.
|
|
396
|
+
*/
|
|
397
|
+
function updateThemeUrls(themeName, suppressFOUC) {
|
|
398
|
+
for (const [, libInfo] of mAllLoadedLibraries) {
|
|
399
|
+
updateThemeUrl({libInfo, themeName, suppressFOUC});
|
|
395
400
|
}
|
|
401
|
+
}
|
|
396
402
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
403
|
+
/**
|
|
404
|
+
* Handles post-processing after a CSS request for a library has finished loading and was not aborted.
|
|
405
|
+
*
|
|
406
|
+
* This function checks if custom CSS needs to be added or updated for the current theme and performs the necessary actions.
|
|
407
|
+
* It also attempts to derive a fallback theme from the theme root if the requested theme could not be loaded,
|
|
408
|
+
* and applies the fallback theme for the affected library if available.
|
|
409
|
+
*
|
|
410
|
+
* @param {string} libId - The ID of the library whose CSS request has finished.
|
|
411
|
+
*/
|
|
412
|
+
function handleThemeFinished(libId) {
|
|
413
|
+
const sThemeName = Theming.getTheme();
|
|
414
|
+
const oLibThemingInfo = mAllLoadedLibraries.get(libId);
|
|
415
|
+
ThemeHelper.reset();
|
|
416
|
+
|
|
417
|
+
if (!_customCSSAdded || _themeCheckedForCustom != sThemeName) {
|
|
418
|
+
if (!ThemeHelper.isStandardTheme(sThemeName) && checkCustom(libId)) {
|
|
419
|
+
const oCustomLibInfo = getLibraryInfo({
|
|
420
|
+
id: CUSTOM_ID
|
|
421
|
+
});
|
|
422
|
+
updateThemeUrl({
|
|
423
|
+
libInfo: oCustomLibInfo,
|
|
424
|
+
suppressFOUC: true
|
|
425
|
+
});
|
|
426
|
+
_customCSSAdded = true;
|
|
427
|
+
_themeCheckedForCustom = sThemeName;
|
|
428
|
+
Log.debug("Delivered custom CSS needs to be loaded, Theme not yet applied", undefined, MODULE_NAME);
|
|
429
|
+
} else if (_customCSSAdded) {
|
|
430
|
+
// remove stylesheet once the particular class is not available (e.g. after theme switch)
|
|
431
|
+
// check for custom theme was not successful, so we need to make sure there are no custom style sheets attached
|
|
432
|
+
document.querySelector(`LINK[id='${CUSTOM_ID}']`)?.remove();
|
|
433
|
+
mAllLoadedLibraries.delete(CUSTOM_ID);
|
|
434
|
+
Log.debug("Custom CSS removed", undefined, MODULE_NAME);
|
|
435
|
+
_customCSSAdded = false;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
420
438
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
439
|
+
// Only retrieve the fallback theme once per ThemeManager cycle
|
|
440
|
+
if (!_sFallbackThemeFromThemeRoot) {
|
|
441
|
+
const sThemeRoot = Theming.getThemeRoot(sThemeName, libId);
|
|
442
|
+
if (sThemeRoot) {
|
|
443
|
+
const rBaseTheme = /~v=[^\/]+\(([a-zA-Z0-9_]+)\)/;
|
|
444
|
+
// base theme should be matched in the first capturing group
|
|
445
|
+
_sFallbackThemeFromThemeRoot = rBaseTheme.exec(sThemeRoot)?.[1];
|
|
446
|
+
|
|
447
|
+
// pass derived fallback theme through our default theme handling
|
|
448
|
+
// in case the fallback theme is not supported anymore, we fall up to the latest default theme
|
|
449
|
+
if (_sFallbackThemeFromThemeRoot) {
|
|
450
|
+
_sFallbackThemeFromThemeRoot = ThemeHelper.validateAndFallbackTheme(_sFallbackThemeFromThemeRoot);
|
|
424
451
|
}
|
|
425
452
|
}
|
|
453
|
+
}
|
|
426
454
|
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
Log.warning(
|
|
432
|
-
"ThemeManager: Custom theme '" + sThemeName + "' could not be loaded for library '" + lib + "'. " +
|
|
433
|
-
"Falling back to its base theme '" + _sFallbackTheme + "'."
|
|
434
|
-
);
|
|
455
|
+
const sFallbackTheme = _sFallbackThemeFromMetadata || _sFallbackThemeFromThemeRoot;
|
|
456
|
+
if (sFallbackTheme) {
|
|
457
|
+
for (const [sLibId, oLib] of mAllLoadedLibraries) {
|
|
458
|
+
if (oLib.failed) {
|
|
459
|
+
Log.warning(`Custom theme '${sThemeName}' could not be loaded for library '${sLibId}'. Falling back to its base theme '${sFallbackTheme}'.`, undefined, MODULE_NAME);
|
|
435
460
|
|
|
436
461
|
// Change the URL to load the fallback theme
|
|
437
|
-
updateThemeUrl(
|
|
462
|
+
updateThemeUrl({
|
|
463
|
+
libInfo: oLib,
|
|
464
|
+
theme: sFallbackTheme,
|
|
465
|
+
suppressFOUC: true
|
|
466
|
+
});
|
|
438
467
|
|
|
439
468
|
// remember the lib to prevent doing the fallback multiple times
|
|
440
469
|
// (if the fallback also can't be loaded)
|
|
441
|
-
|
|
442
|
-
}
|
|
470
|
+
oLibThemingInfo.themeFallback = true;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
443
475
|
|
|
444
|
-
|
|
445
|
-
|
|
476
|
+
/**
|
|
477
|
+
* Handles post-processing after a CSS request for a library has successfully finished loading and was not aborted.
|
|
478
|
+
*
|
|
479
|
+
* This function attempts to derive a fallback theme from the theme metadata if the requested theme could not be loaded.
|
|
480
|
+
* The fallback theme is determined from the "Extends" property in the theme metadata.
|
|
481
|
+
*
|
|
482
|
+
* @param {string} libId - The ID of the library whose CSS request has successfully finished.
|
|
483
|
+
*/
|
|
484
|
+
function handleThemeSucceeded(libId) {
|
|
485
|
+
if (!_sFallbackThemeFromMetadata) {
|
|
486
|
+
const oThemeMetaData = ThemeHelper.getMetadata(libId);
|
|
487
|
+
if (oThemeMetaData && oThemeMetaData.Extends && oThemeMetaData.Extends[0]) {
|
|
488
|
+
_sFallbackThemeFromMetadata = oThemeMetaData.Extends[0];
|
|
446
489
|
}
|
|
447
490
|
}
|
|
491
|
+
}
|
|
448
492
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
493
|
+
/**
|
|
494
|
+
* Handles post-processing after a CSS request for a library has failed and was not aborted.
|
|
495
|
+
*
|
|
496
|
+
* This function detects whether the fallback theme should be requested for the library,
|
|
497
|
+
* based on the current theme and the loading state of the CSS link element.
|
|
498
|
+
*
|
|
499
|
+
* @param {string} libId - The ID of the library whose CSS request has failed.
|
|
500
|
+
*/
|
|
501
|
+
function handleThemeFailed(libId) {
|
|
502
|
+
const oLibThemingInfo = getLibraryInfo({id: libId});
|
|
503
|
+
// Collect all libs that failed to load and no fallback has been applied, yet.
|
|
504
|
+
// The fallback relies on custom theme metadata, so it is not done for standard themes
|
|
505
|
+
if (!ThemeHelper.isStandardTheme(Theming.getTheme()) && !oLibThemingInfo.themeFallback) {
|
|
506
|
+
// Check for error marker (data-sap-ui-ready=false) and that there are no rules
|
|
507
|
+
// to be sure the stylesheet couldn't be loaded at all.
|
|
508
|
+
// E.g. in case an @import within the stylesheet fails, the error marker will
|
|
509
|
+
// also be set, but in this case no fallback should be done as there is a (broken) theme
|
|
510
|
+
if (oLibThemingInfo.cssLinkElement && !(oLibThemingInfo.cssLinkElement.sheet && hasSheetCssRules(oLibThemingInfo.cssLinkElement.sheet))) {
|
|
511
|
+
oLibThemingInfo.failed = true;
|
|
512
|
+
}
|
|
453
513
|
}
|
|
454
|
-
return res;
|
|
455
514
|
}
|
|
456
515
|
|
|
457
516
|
/**
|
|
@@ -462,7 +521,7 @@ sap.ui.define([
|
|
|
462
521
|
*/
|
|
463
522
|
function checkCustom(lib) {
|
|
464
523
|
|
|
465
|
-
|
|
524
|
+
const cssFile = window.document.getElementById(`${THEME_PREFIX}${lib}`);
|
|
466
525
|
|
|
467
526
|
if (!cssFile) {
|
|
468
527
|
return false;
|
|
@@ -472,28 +531,12 @@ sap.ui.define([
|
|
|
472
531
|
Check if custom.css indication rule is applied to <link> element
|
|
473
532
|
The rule looks like this:
|
|
474
533
|
|
|
475
|
-
link[id^="sap-ui-theme-"]::after
|
|
476
|
-
.sapUiThemeDesignerCustomCss {
|
|
477
|
-
content: '{"customcss" : true}';
|
|
478
|
-
}
|
|
534
|
+
link[id^="sap-ui-theme-"]::after
|
|
479
535
|
|
|
480
|
-
|
|
481
|
-
the second one for the Safari workaround (see below).
|
|
536
|
+
Selector is to apply it to the <link> elements.
|
|
482
537
|
*/
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
if (!content && Device.browser.safari) {
|
|
487
|
-
|
|
488
|
-
// Safari has a bug which prevents reading properties of hidden pseudo elements
|
|
489
|
-
// As a workaround: Add "sapUiThemeDesignerCustomCss" class on html element
|
|
490
|
-
// in order to get the computed "content" value and remove it again.
|
|
491
|
-
var html = document.documentElement;
|
|
492
|
-
|
|
493
|
-
html.classList.add("sapUiThemeDesignerCustomCss");
|
|
494
|
-
content = window.getComputedStyle(html, ":after").getPropertyValue("content");
|
|
495
|
-
html.classList.remove("sapUiThemeDesignerCustomCss");
|
|
496
|
-
}
|
|
538
|
+
const style = window.getComputedStyle(cssFile, ':after');
|
|
539
|
+
let content = style ? style.getPropertyValue('content') : null;
|
|
497
540
|
|
|
498
541
|
if (content && content !== "none") {
|
|
499
542
|
try {
|
|
@@ -520,16 +563,16 @@ sap.ui.define([
|
|
|
520
563
|
* checks if a particular class is available at the beginning of the stylesheet
|
|
521
564
|
*/
|
|
522
565
|
|
|
523
|
-
|
|
566
|
+
const aRules = cssFile.sheet ? safeAccessSheetCssRules(cssFile.sheet) : null;
|
|
524
567
|
|
|
525
568
|
if (!aRules || aRules.length === 0) {
|
|
526
|
-
Log.warning(
|
|
569
|
+
Log.warning(`Custom check: Failed retrieving a CSS rule from stylesheet ${lib}`, undefined, MODULE_NAME);
|
|
527
570
|
return false;
|
|
528
571
|
}
|
|
529
572
|
|
|
530
573
|
// we should now have some rule name ==> try to match against custom check
|
|
531
|
-
for (
|
|
532
|
-
if (
|
|
574
|
+
for (let i = 0; (i < 2 && i < aRules.length) ; i++) {
|
|
575
|
+
if (CUSTOM_CSS_CHECK.test(aRules[i].selectorText)) {
|
|
533
576
|
return true;
|
|
534
577
|
}
|
|
535
578
|
}
|
|
@@ -537,38 +580,9 @@ sap.ui.define([
|
|
|
537
580
|
return false;
|
|
538
581
|
}
|
|
539
582
|
|
|
540
|
-
function delayedCheckTheme(bFirst) {
|
|
541
|
-
_iCount++;
|
|
542
|
-
|
|
543
|
-
var bEmergencyExit = _iCount > maxThemeCheckCycles;
|
|
544
|
-
|
|
545
|
-
if (!checkTheme() && !bEmergencyExit) {
|
|
546
|
-
// Use dynamic delay to have a fast check for most use cases
|
|
547
|
-
// but not cause too much CPU usage for long running css requests
|
|
548
|
-
var iDelay;
|
|
549
|
-
if (_iCount <= 100) {
|
|
550
|
-
iDelay = 2; // 1. Initial interval
|
|
551
|
-
} else if (_iCount <= 110) {
|
|
552
|
-
iDelay = 500; // 2. After 100 cycles
|
|
553
|
-
} else {
|
|
554
|
-
iDelay = 1000; // 3. After another 10 cycles (about 5 seconds)
|
|
555
|
-
}
|
|
556
|
-
_sThemeCheckId = setTimeout(delayedCheckTheme, iDelay);
|
|
557
|
-
} else if (!bFirst) {
|
|
558
|
-
ThemeManager.reset();
|
|
559
|
-
ThemeManager.themeLoaded = true;
|
|
560
|
-
ThemeManager.fireThemeApplied();
|
|
561
|
-
if (bEmergencyExit) {
|
|
562
|
-
future.errorThrows("ThemeManager: max. check cycles reached.");
|
|
563
|
-
}
|
|
564
|
-
} else {
|
|
565
|
-
ThemeManager.themeLoaded = true;
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
|
|
569
583
|
// helper to add the FOUC marker to the CSS for the given id
|
|
570
584
|
function fnAddFoucmarker(sLinkId) {
|
|
571
|
-
|
|
585
|
+
const oLink = document.getElementById(sLinkId);
|
|
572
586
|
if (oLink) {
|
|
573
587
|
oLink.dataset.sapUiFoucmarker = sLinkId;
|
|
574
588
|
}
|
|
@@ -592,146 +606,142 @@ sap.ui.define([
|
|
|
592
606
|
* @param {object} oTheme Theme object containing the old and the new theme
|
|
593
607
|
* @param {string} oTheme.new Name of the new theme
|
|
594
608
|
* @param {string} oTheme.old Name of the previous theme
|
|
595
|
-
*
|
|
596
|
-
* @private
|
|
597
609
|
*/
|
|
598
610
|
function applyTheme(oTheme) {
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
ThemeManager._updateThemeUrls(sTheme, /* bSuppressFOUC */ true);
|
|
602
|
-
|
|
603
|
-
// modify the <html> tag's CSS class with the theme name
|
|
604
|
-
html.classList.remove("sapUiTheme-" + oTheme.old);
|
|
605
|
-
html.classList.add("sapUiTheme-" + sTheme);
|
|
606
|
-
|
|
607
|
-
// notify the listeners
|
|
608
|
-
ThemeManager.checkThemeApplied();
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
+
const html = document.documentElement;
|
|
612
|
+
const sTheme = oTheme.new;
|
|
611
613
|
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
* in case a themeRoot has been defined.
|
|
615
|
-
*
|
|
616
|
-
* @param {string} sLibName Library name (dot separated)
|
|
617
|
-
* @param {string} sThemeName Theme name
|
|
618
|
-
* @private
|
|
619
|
-
*/
|
|
620
|
-
function _ensureThemeRoot(sLibName, sThemeName) {
|
|
621
|
-
var sThemeRoot = Theming.getThemeRoot(sThemeName, sLibName);
|
|
622
|
-
if (sThemeRoot) {
|
|
623
|
-
// check whether for this combination (theme+lib) a URL is registered or for this theme a default location is registered
|
|
624
|
-
sThemeRoot = sThemeRoot + (sThemeRoot.slice( -1) == "/" ? "" : "/") + sLibName.replace(/\./g, "/") + "/themes/" + sThemeName + "/";
|
|
625
|
-
LoaderExtensions.registerResourcePath((sLibName + ".themes." + sThemeName).replace(/\./g, "/"), sThemeRoot);
|
|
614
|
+
for (const [, oLibInfo] of mAllLoadedLibraries) {
|
|
615
|
+
delete oLibInfo.themeFallback;
|
|
626
616
|
}
|
|
627
|
-
|
|
617
|
+
_sFallbackThemeFromMetadata = _sFallbackThemeFromThemeRoot = null;
|
|
628
618
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
var sLibName,
|
|
632
|
-
iQueryIndex = oLink.href.search(/[?#]/),
|
|
633
|
-
sLibFileName,
|
|
634
|
-
sQuery,
|
|
635
|
-
sStandardLibFilePrefix = "library",
|
|
636
|
-
sRTL = Localization.getRTL() ? "-RTL" : "",
|
|
637
|
-
sHref,
|
|
638
|
-
pos;
|
|
639
|
-
|
|
640
|
-
// derive lib name from id via regex
|
|
641
|
-
var mLinkId = new RegExp(`^${_THEME_PREFIX}(.*)$`, "i").exec(oLink.id);
|
|
642
|
-
if (Array.isArray(mLinkId)) {
|
|
643
|
-
sLibName = mLinkId[1];
|
|
644
|
-
} else {
|
|
645
|
-
// fallback to legacy logic
|
|
646
|
-
sLibName = oLink.id.slice(_THEME_PREFIX.length);
|
|
647
|
-
}
|
|
619
|
+
Log.debug(`ThemeManager: Theme changed from ${oTheme.old} to ${sTheme}`, undefined, MODULE_NAME);
|
|
620
|
+
updateThemeUrls(sTheme, /* bSuppressFOUC */ true);
|
|
648
621
|
|
|
649
|
-
|
|
622
|
+
// modify the <html> tag's CSS class with the theme name
|
|
623
|
+
html.classList.remove(`sapUiTheme-${oTheme.old}`);
|
|
624
|
+
html.classList.add(`sapUiTheme-${sTheme}`);
|
|
625
|
+
}
|
|
650
626
|
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
627
|
+
function safeAccessSheetCssRules(sheet) {
|
|
628
|
+
try {
|
|
629
|
+
return sheet.cssRules;
|
|
630
|
+
} catch (e) {
|
|
631
|
+
// Firefox throws a SecurityError or InvalidAccessError if "sheet.cssRules"
|
|
632
|
+
// is accessed on a stylesheet with 404 response code.
|
|
633
|
+
// Most browsers also throw when accessing from a different origin (CORS).
|
|
634
|
+
return null;
|
|
658
635
|
}
|
|
636
|
+
}
|
|
659
637
|
|
|
660
|
-
|
|
661
|
-
|
|
638
|
+
function hasSheetCssRules(sheet) {
|
|
639
|
+
const aCssRules = safeAccessSheetCssRules(sheet);
|
|
640
|
+
return !!aCssRules && aCssRules.length > 0;
|
|
641
|
+
}
|
|
662
642
|
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
643
|
+
// Collect all UI5 relevant CSS files which have been added upfront
|
|
644
|
+
// and add them to UI5 theming lifecycle
|
|
645
|
+
document.querySelectorAll(`link[id^=${THEME_PREFIX}]`).forEach(function(cssLinkElement) {
|
|
646
|
+
let bPreloadedCssReady = true;
|
|
647
|
+
const sLinkId = cssLinkElement.getAttribute("id");
|
|
648
|
+
const [,libName, variant] = (sLinkId.match(LINK_ID_WITH_VARIANT_CHECK) || sLinkId.match(LINK_ID_CHECK));
|
|
649
|
+
const oLibInfo = getLibraryInfo({
|
|
650
|
+
libName,
|
|
651
|
+
variant,
|
|
652
|
+
linkId: sLinkId
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
Log.info(`Preloaded CSS for library ${libName + (variant ? ` with variant ${variant} ` : "")} detected: ${cssLinkElement.href}`, undefined, MODULE_NAME);
|
|
656
|
+
|
|
657
|
+
const { promise: cssLoaded, resolve, reject } = Promise.withResolvers();
|
|
658
|
+
const handleReady = function(bError) {
|
|
659
|
+
if (bError) {
|
|
660
|
+
reject();
|
|
661
|
+
} else {
|
|
662
|
+
resolve();
|
|
663
|
+
}
|
|
664
|
+
};
|
|
668
665
|
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
sLibFileName = sStandardLibFilePrefix + sRTL + ".css";
|
|
672
|
-
}
|
|
666
|
+
try {
|
|
667
|
+
bPreloadedCssReady = !!(cssLinkElement.sheet?.href === cssLinkElement.href && cssLinkElement.sheet?.cssRules);
|
|
673
668
|
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
669
|
+
if (!bPreloadedCssReady) {
|
|
670
|
+
ThemeManager.themeLoaded = bPreloadedCssReady;
|
|
671
|
+
cssLinkElement.addEventListener("load", () => {
|
|
672
|
+
handleReady(false);
|
|
673
|
+
});
|
|
674
|
+
cssLinkElement.addEventListener("error", () => {
|
|
675
|
+
handleReady(true);
|
|
676
|
+
});
|
|
677
|
+
} else {
|
|
678
|
+
handleReady(!(cssLinkElement.sheet.cssRules.length > 0));
|
|
683
679
|
}
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
// the
|
|
687
|
-
|
|
688
|
-
includeStylesheet(sHref, oLink.id);
|
|
689
|
-
}
|
|
690
|
-
}
|
|
680
|
+
includeStyleSheetPostProcessing(oLibInfo, cssLoaded, true);
|
|
681
|
+
} catch (e) {
|
|
682
|
+
// If the stylesheet is cross-origin and throws a security error, we can't verify directly
|
|
683
|
+
Log.info("Could not detect ready state of preloaded CSS. Request stylesheet again to verify the response status", undefined, MODULE_NAME);
|
|
691
684
|
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
* @private
|
|
700
|
-
*/
|
|
701
|
-
function getLibraryCssQueryParams(oLibInfo) {
|
|
702
|
-
var sQuery;
|
|
703
|
-
if (oLibInfo) {
|
|
704
|
-
sQuery = "?version=" + oLibInfo.version;
|
|
705
|
-
|
|
706
|
-
// distribution version may not be available (will be loaded in Core constructor syncpoint2)
|
|
707
|
-
if (VersionInfo._content) {
|
|
708
|
-
sQuery += "&sap-ui-dist-version=" + VersionInfo._content.version;
|
|
709
|
-
}
|
|
685
|
+
ThemeManager.themeLoaded = false;
|
|
686
|
+
|
|
687
|
+
updateThemeUrl({
|
|
688
|
+
libInfo: oLibInfo,
|
|
689
|
+
suppressFOUC: true,
|
|
690
|
+
force: true
|
|
691
|
+
});
|
|
710
692
|
}
|
|
711
|
-
|
|
712
|
-
}
|
|
693
|
+
});
|
|
713
694
|
|
|
714
695
|
// set CSS class for the theme name
|
|
715
696
|
document.documentElement.classList.add("sapUiTheme-" + Theming.getTheme());
|
|
716
|
-
Log.info(
|
|
697
|
+
Log.info(`Declared theme ${Theming.getTheme()}`, undefined, MODULE_NAME);
|
|
717
698
|
|
|
718
|
-
|
|
699
|
+
attachChange(function(oEvent) {
|
|
719
700
|
var mThemeRoots = oEvent.themeRoots;
|
|
720
701
|
var oTheme = oEvent.theme;
|
|
702
|
+
var oLib = oEvent.library;
|
|
721
703
|
if (mThemeRoots && mThemeRoots.forceUpdate) {
|
|
722
|
-
|
|
704
|
+
updateThemeUrls(Theming.getTheme());
|
|
723
705
|
}
|
|
724
706
|
if (oTheme) {
|
|
725
707
|
applyTheme(oTheme);
|
|
726
708
|
}
|
|
709
|
+
if (oLib) {
|
|
710
|
+
includeLibraryTheme(oLib);
|
|
711
|
+
}
|
|
727
712
|
});
|
|
728
713
|
|
|
729
|
-
|
|
714
|
+
// handle RTL changes
|
|
715
|
+
Localization.attachChange(function(oEvent){
|
|
716
|
+
const bRTL = oEvent.rtl;
|
|
717
|
+
if (bRTL !== undefined) {
|
|
718
|
+
updateThemeUrls(Theming.getTheme());
|
|
719
|
+
}
|
|
720
|
+
});
|
|
730
721
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
722
|
+
registerThemeManager(ThemeManager, (fireApplied) => {
|
|
723
|
+
oEventing.attachEvent("applied", fireApplied);
|
|
724
|
+
});
|
|
725
|
+
|
|
726
|
+
OwnStatics.set(ThemeManager, {
|
|
727
|
+
/**
|
|
728
|
+
* Returns libraryInfoObject
|
|
729
|
+
*
|
|
730
|
+
* @param {string} libInfoId The ID of the libraryInfo object
|
|
731
|
+
* @returns {Map<string, object>|object|undefined} A map with all available libraryInfoObjects, a specific libraryInfoObject
|
|
732
|
+
* or undefined in case a specific libraryInfoObject was requested but does not exists
|
|
733
|
+
* @private
|
|
734
|
+
* @ui5-restricted sap.ui.core.theming.Parameters
|
|
735
|
+
*/
|
|
736
|
+
getAllLibraryInfoObjects: (libInfoId) => {
|
|
737
|
+
if (libInfoId) {
|
|
738
|
+
return mAllLoadedLibraries.get(libInfoId);
|
|
739
|
+
}
|
|
740
|
+
const mAllInfoObjects = new Map(mAllLoadedLibraries);
|
|
741
|
+
mAllInfoObjects.delete(CUSTOM_ID);
|
|
742
|
+
return mAllInfoObjects;
|
|
743
|
+
}
|
|
744
|
+
});
|
|
735
745
|
|
|
736
746
|
return ThemeManager;
|
|
737
747
|
});
|