@openui5/sap.ui.core 1.139.0 → 1.140.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 +1 -1
- 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/LanguageTag.js +1 -1
- package/src/sap/base/i18n/date/TimezoneUtils.js +1 -1
- package/src/sap/base/security/URLListValidator.js +7 -3
- 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 +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/Interface.js +1 -1
- package/src/sap/ui/base/ManagedObject.js +1 -1
- package/src/sap/ui/base/ManagedObjectMetadata.js +1 -1
- 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/core/.library +2 -2
- 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 +1 -1
- package/src/sap/ui/core/ComponentMetadata.js +1 -1
- package/src/sap/ui/core/ComponentSupport.js +1 -1
- package/src/sap/ui/core/Configuration.js +1 -1
- 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 +1 -1
- 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 +15 -108
- 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 +1 -1
- package/src/sap/ui/core/LocaleData.js +1 -1
- 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 +1 -1
- 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/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 +1 -1
- 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 +18 -3
- 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 +1 -1
- 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/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/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/themes/base/base.less +20 -20
- package/src/sap/ui/core/themes/base/shared.less +4 -1
- package/src/sap/ui/core/themes/base/skeleton.less +3 -3
- package/src/sap/ui/core/theming/Parameters.js +717 -755
- package/src/sap/ui/core/theming/ThemeHelper.js +0 -77
- package/src/sap/ui/core/theming/ThemeManager.js +535 -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/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/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/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 +9 -8
- 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 +41 -59
- package/src/sap/ui/model/odata/v2/ODataTreeBinding.js +82 -60
- package/src/sap/ui/model/odata/v4/Context.js +1 -1
- package/src/sap/ui/model/odata/v4/ODataContextBinding.js +1 -1
- package/src/sap/ui/model/odata/v4/ODataListBinding.js +1 -1
- package/src/sap/ui/model/odata/v4/ODataMetaModel.js +35 -20
- package/src/sap/ui/model/odata/v4/ODataModel.js +1 -1
- package/src/sap/ui/model/odata/v4/ODataParentBinding.js +32 -5
- package/src/sap/ui/model/odata/v4/ODataPropertyBinding.js +1 -1
- package/src/sap/ui/model/odata/v4/lib/_AggregationCache.js +11 -1
- package/src/sap/ui/model/odata/v4/lib/_Cache.js +7 -9
- package/src/sap/ui/model/odata/v4/lib/_Helper.js +12 -12
- package/src/sap/ui/model/odata/v4/lib/_Requestor.js +16 -6
- 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/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/opaQunit.js +3 -0
- 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/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,436 @@ 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")?.replace(/\?.*/, "");
|
|
282
|
+
const sUrl = libInfo.getUrl(theme).baseUrl;
|
|
283
|
+
if (!sUrl || sOldUrl !== sUrl || force) {
|
|
284
|
+
libInfo.finishedLoading = false;
|
|
285
|
+
libInfo.failed = false;
|
|
286
|
+
if (suppressFOUC) {
|
|
287
|
+
// Only add stylesheet in case there is no existing stylesheet or the href is different
|
|
229
288
|
// use the special FOUC handling for initially existing stylesheets
|
|
230
289
|
// to ensure that they are not just replaced when using the
|
|
231
290
|
// 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();
|
|
291
|
+
fnAddFoucmarker(libInfo.linkId);
|
|
244
292
|
}
|
|
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()
|
|
293
|
+
const pCssLoaded = libInfo.getUrl(theme).urlPromise.then((sUrl) => {
|
|
294
|
+
if (sUrl) {
|
|
295
|
+
Log.debug(`Add new CSS for library ${libInfo.id} with URL: ${sUrl}`, undefined, MODULE_NAME);
|
|
296
|
+
return includeStylesheet({
|
|
297
|
+
url: force ? sOldUrl : sUrl,
|
|
298
|
+
id: libInfo.linkId
|
|
299
|
+
});
|
|
300
|
+
} else {
|
|
301
|
+
// If there is no URL, a theme fallback must be detected first.
|
|
302
|
+
// We reject here because and add only a placeholder link element to the DOM.
|
|
303
|
+
// The handleThemeFailed function will process this rejection and apply the fallback
|
|
304
|
+
// theme for the library once it has been detected.
|
|
305
|
+
const oLink = document.createElement("link");
|
|
306
|
+
oLink.setAttribute("id", libInfo.linkId);
|
|
307
|
+
oLink.setAttribute("rel", "stylesheet");
|
|
308
|
+
if (libInfo.cssLinkElement) {
|
|
309
|
+
libInfo.cssLinkElement.parentNode.replaceChild(oLink, libInfo.cssLinkElement);
|
|
310
|
+
} else {
|
|
311
|
+
document.head.insertBefore(oLink, document.getElementById(CUSTOM_ID));
|
|
312
|
+
}
|
|
313
|
+
libInfo.cssLinkElement = oLink;
|
|
314
|
+
return Promise.reject();
|
|
315
|
+
}
|
|
318
316
|
});
|
|
319
|
-
}
|
|
320
|
-
};
|
|
321
317
|
|
|
318
|
+
if (libInfo.cssLoaded) {
|
|
319
|
+
libInfo.cssLoaded.aborted = true;
|
|
320
|
+
}
|
|
322
321
|
|
|
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] = {};
|
|
322
|
+
includeStyleSheetPostProcessing(libInfo, pCssLoaded, suppressFOUC);
|
|
335
323
|
}
|
|
324
|
+
}
|
|
336
325
|
|
|
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
|
-
|
|
326
|
+
/**
|
|
327
|
+
* Handles post-processing of CSS link elements after they have been requested.
|
|
328
|
+
*
|
|
329
|
+
* This function manages the lifecycle of CSS loading for a library by attaching handlers to the CSS loading promise.
|
|
330
|
+
* It handles success and failure cases, as well as generic post-processing that occurs regardless of the request status.
|
|
331
|
+
* The function is responsible for:
|
|
332
|
+
*
|
|
333
|
+
* 1. Managing the loading state of the CSS for the library
|
|
334
|
+
* 2. Removing FOUC (Flash of Unstyled Content) markers when loading completes
|
|
335
|
+
* 3. Updating references to the CSS link element
|
|
336
|
+
* 4. Triggering appropriate theme lifecycle events (success, failure, completion)
|
|
337
|
+
* 5. Updating the global CSS request promise collection
|
|
338
|
+
* 6. Managing the global theme loaded state
|
|
339
|
+
* 7. Firing the "applied" event when all CSS requests have completed
|
|
340
|
+
*
|
|
341
|
+
* The function uses promise chaining to ensure proper sequencing of operations and to handle
|
|
342
|
+
* both successful and failed CSS loading scenarios. It also includes an abort mechanism to
|
|
343
|
+
* prevent stale CSS requests from affecting the UI when a new request supersedes them.
|
|
344
|
+
*
|
|
345
|
+
* @param {object} libInfo - The library info object containing metadata about the library and its CSS
|
|
346
|
+
* @param {Promise} cssLoadededPromise - The promise that resolves when the CSS has been loaded
|
|
347
|
+
* @param {boolean} suppressFOUC - Whether to suppress Flash of Unstyled Content during theme changes
|
|
348
|
+
*/
|
|
349
|
+
function includeStyleSheetPostProcessing(libInfo, cssLoadededPromise, suppressFOUC) {
|
|
350
|
+
libInfo.cssLoaded = cssLoadededPromise.finally(function() {
|
|
351
|
+
if (!libInfo.cssLoaded.aborted) {
|
|
352
|
+
libInfo.finishedLoading = true;
|
|
353
|
+
document.querySelector(`link[data-sap-ui-foucmarker='${libInfo.linkId}']`)?.remove();
|
|
354
|
+
libInfo.cssLinkElement = document.getElementById(`${libInfo.linkId}`);
|
|
355
|
+
Log.debug(`New stylesheet loaded and old stylesheet removed for library: ${libInfo.id}`, undefined, MODULE_NAME);
|
|
356
|
+
}
|
|
357
|
+
}).then(function() {
|
|
358
|
+
if (!libInfo.cssLoaded.aborted) {
|
|
359
|
+
handleThemeSucceeded(libInfo.id);
|
|
360
|
+
}
|
|
361
|
+
}).catch(function() {
|
|
362
|
+
if (!libInfo.cssLoaded.aborted) {
|
|
363
|
+
handleThemeFailed(libInfo.id);
|
|
364
|
+
}
|
|
365
|
+
}).finally(function() {
|
|
366
|
+
if (!libInfo.cssLoaded.aborted) {
|
|
367
|
+
handleThemeFinished(libInfo.id);
|
|
368
|
+
pAllCssRequests = Promise.allSettled([...mAllLoadedLibraries.values()].map((libInfo) => libInfo.cssLoaded));
|
|
369
|
+
pAllCssRequests.finally(function() {
|
|
370
|
+
if (this === pAllCssRequests) {
|
|
371
|
+
Log.debug("Theme change finished", undefined, MODULE_NAME);
|
|
372
|
+
// Even if suppressFOUC is not set, we must fire the event if themeLoaded was previously set to false,
|
|
373
|
+
// because this indicates that at least one theme change was caused by a theming-relevant trigger.
|
|
374
|
+
if (suppressFOUC || !ThemeManager.themeLoaded) {
|
|
375
|
+
ThemeManager.themeLoaded = true;
|
|
376
|
+
oEventing.fireEvent("applied", {
|
|
377
|
+
theme: Theming.getTheme()
|
|
378
|
+
});
|
|
373
379
|
}
|
|
374
|
-
_customCSSAdded = false;
|
|
375
380
|
}
|
|
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
|
-
}
|
|
381
|
+
}.bind(pAllCssRequests));
|
|
393
382
|
}
|
|
383
|
+
});
|
|
384
|
+
}
|
|
394
385
|
|
|
386
|
+
/**
|
|
387
|
+
* Updates all existing CSS link elements to reflect the provided theme.
|
|
388
|
+
*
|
|
389
|
+
* This function iterates over all loaded library info objects and updates their CSS link elements
|
|
390
|
+
* to ensure they point to the correct theme resources. It guarantees that all CSS links are up-to-date
|
|
391
|
+
* with respect to the given theme, RTL mode, SAP UI5 distribution version, and theme roots.
|
|
392
|
+
*
|
|
393
|
+
* @param {string} themeName - The name of the theme to apply.
|
|
394
|
+
* @param {boolean} suppressFOUC - Whether to suppress Flash of Unstyled Content (FOUC) handling.
|
|
395
|
+
*/
|
|
396
|
+
function updateThemeUrls(themeName, suppressFOUC) {
|
|
397
|
+
for (const [, libInfo] of mAllLoadedLibraries) {
|
|
398
|
+
updateThemeUrl({libInfo, themeName, suppressFOUC});
|
|
395
399
|
}
|
|
400
|
+
}
|
|
396
401
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
402
|
+
/**
|
|
403
|
+
* Handles post-processing after a CSS request for a library has finished loading and was not aborted.
|
|
404
|
+
*
|
|
405
|
+
* This function checks if custom CSS needs to be added or updated for the current theme and performs the necessary actions.
|
|
406
|
+
* It also attempts to derive a fallback theme from the theme root if the requested theme could not be loaded,
|
|
407
|
+
* and applies the fallback theme for the affected library if available.
|
|
408
|
+
*
|
|
409
|
+
* @param {string} libId - The ID of the library whose CSS request has finished.
|
|
410
|
+
*/
|
|
411
|
+
function handleThemeFinished(libId) {
|
|
412
|
+
const sThemeName = Theming.getTheme();
|
|
413
|
+
const oLibThemingInfo = mAllLoadedLibraries.get(libId);
|
|
414
|
+
ThemeHelper.reset();
|
|
415
|
+
|
|
416
|
+
if (!_customCSSAdded || _themeCheckedForCustom != sThemeName) {
|
|
417
|
+
if (!ThemeHelper.isStandardTheme(sThemeName) && checkCustom(libId)) {
|
|
418
|
+
const oCustomLibInfo = getLibraryInfo({
|
|
419
|
+
id: CUSTOM_ID
|
|
420
|
+
});
|
|
421
|
+
updateThemeUrl({
|
|
422
|
+
libInfo: oCustomLibInfo,
|
|
423
|
+
suppressFOUC: true
|
|
424
|
+
});
|
|
425
|
+
_customCSSAdded = true;
|
|
426
|
+
_themeCheckedForCustom = sThemeName;
|
|
427
|
+
Log.debug("Delivered custom CSS needs to be loaded, Theme not yet applied", undefined, MODULE_NAME);
|
|
428
|
+
} else if (_customCSSAdded) {
|
|
429
|
+
// remove stylesheet once the particular class is not available (e.g. after theme switch)
|
|
430
|
+
// check for custom theme was not successful, so we need to make sure there are no custom style sheets attached
|
|
431
|
+
document.querySelector(`LINK[id='${CUSTOM_ID}']`)?.remove();
|
|
432
|
+
mAllLoadedLibraries.delete(CUSTOM_ID);
|
|
433
|
+
Log.debug("Custom CSS removed", undefined, MODULE_NAME);
|
|
434
|
+
_customCSSAdded = false;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
420
437
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
438
|
+
// Only retrieve the fallback theme once per ThemeManager cycle
|
|
439
|
+
if (!_sFallbackThemeFromThemeRoot) {
|
|
440
|
+
const sThemeRoot = Theming.getThemeRoot(sThemeName, libId);
|
|
441
|
+
if (sThemeRoot) {
|
|
442
|
+
const rBaseTheme = /~v=[^\/]+\(([a-zA-Z0-9_]+)\)/;
|
|
443
|
+
// base theme should be matched in the first capturing group
|
|
444
|
+
_sFallbackThemeFromThemeRoot = rBaseTheme.exec(sThemeRoot)?.[1];
|
|
445
|
+
|
|
446
|
+
// pass derived fallback theme through our default theme handling
|
|
447
|
+
// in case the fallback theme is not supported anymore, we fall up to the latest default theme
|
|
448
|
+
if (_sFallbackThemeFromThemeRoot) {
|
|
449
|
+
_sFallbackThemeFromThemeRoot = ThemeHelper.validateAndFallbackTheme(_sFallbackThemeFromThemeRoot);
|
|
424
450
|
}
|
|
425
451
|
}
|
|
452
|
+
}
|
|
426
453
|
|
|
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
|
-
);
|
|
454
|
+
const sFallbackTheme = _sFallbackThemeFromMetadata || _sFallbackThemeFromThemeRoot;
|
|
455
|
+
if (sFallbackTheme) {
|
|
456
|
+
for (const [sLibId, oLib] of mAllLoadedLibraries) {
|
|
457
|
+
if (oLib.failed) {
|
|
458
|
+
Log.warning(`Custom theme '${sThemeName}' could not be loaded for library '${sLibId}'. Falling back to its base theme '${sFallbackTheme}'.`, undefined, MODULE_NAME);
|
|
435
459
|
|
|
436
460
|
// Change the URL to load the fallback theme
|
|
437
|
-
updateThemeUrl(
|
|
461
|
+
updateThemeUrl({
|
|
462
|
+
libInfo: oLib,
|
|
463
|
+
theme: sFallbackTheme,
|
|
464
|
+
suppressFOUC: true
|
|
465
|
+
});
|
|
438
466
|
|
|
439
467
|
// remember the lib to prevent doing the fallback multiple times
|
|
440
468
|
// (if the fallback also can't be loaded)
|
|
441
|
-
|
|
442
|
-
}
|
|
469
|
+
oLibThemingInfo.themeFallback = true;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
443
474
|
|
|
444
|
-
|
|
445
|
-
|
|
475
|
+
/**
|
|
476
|
+
* Handles post-processing after a CSS request for a library has successfully finished loading and was not aborted.
|
|
477
|
+
*
|
|
478
|
+
* This function attempts to derive a fallback theme from the theme metadata if the requested theme could not be loaded.
|
|
479
|
+
* The fallback theme is determined from the "Extends" property in the theme metadata.
|
|
480
|
+
*
|
|
481
|
+
* @param {string} libId - The ID of the library whose CSS request has successfully finished.
|
|
482
|
+
*/
|
|
483
|
+
function handleThemeSucceeded(libId) {
|
|
484
|
+
if (!_sFallbackThemeFromMetadata) {
|
|
485
|
+
const oThemeMetaData = ThemeHelper.getMetadata(libId);
|
|
486
|
+
if (oThemeMetaData && oThemeMetaData.Extends && oThemeMetaData.Extends[0]) {
|
|
487
|
+
_sFallbackThemeFromMetadata = oThemeMetaData.Extends[0];
|
|
446
488
|
}
|
|
447
489
|
}
|
|
490
|
+
}
|
|
448
491
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
492
|
+
/**
|
|
493
|
+
* Handles post-processing after a CSS request for a library has failed and was not aborted.
|
|
494
|
+
*
|
|
495
|
+
* This function detects whether the fallback theme should be requested for the library,
|
|
496
|
+
* based on the current theme and the loading state of the CSS link element.
|
|
497
|
+
*
|
|
498
|
+
* @param {string} libId - The ID of the library whose CSS request has failed.
|
|
499
|
+
*/
|
|
500
|
+
function handleThemeFailed(libId) {
|
|
501
|
+
const oLibThemingInfo = getLibraryInfo({id: libId});
|
|
502
|
+
// Collect all libs that failed to load and no fallback has been applied, yet.
|
|
503
|
+
// The fallback relies on custom theme metadata, so it is not done for standard themes
|
|
504
|
+
if (!ThemeHelper.isStandardTheme(Theming.getTheme()) && !oLibThemingInfo.themeFallback) {
|
|
505
|
+
// Check for error marker (data-sap-ui-ready=false) and that there are no rules
|
|
506
|
+
// to be sure the stylesheet couldn't be loaded at all.
|
|
507
|
+
// E.g. in case an @import within the stylesheet fails, the error marker will
|
|
508
|
+
// also be set, but in this case no fallback should be done as there is a (broken) theme
|
|
509
|
+
if (oLibThemingInfo.cssLinkElement && !(oLibThemingInfo.cssLinkElement.sheet && hasSheetCssRules(oLibThemingInfo.cssLinkElement.sheet))) {
|
|
510
|
+
oLibThemingInfo.failed = true;
|
|
511
|
+
}
|
|
453
512
|
}
|
|
454
|
-
return res;
|
|
455
513
|
}
|
|
456
514
|
|
|
457
515
|
/**
|
|
@@ -462,7 +520,7 @@ sap.ui.define([
|
|
|
462
520
|
*/
|
|
463
521
|
function checkCustom(lib) {
|
|
464
522
|
|
|
465
|
-
|
|
523
|
+
const cssFile = window.document.getElementById(`${THEME_PREFIX}${lib}`);
|
|
466
524
|
|
|
467
525
|
if (!cssFile) {
|
|
468
526
|
return false;
|
|
@@ -472,28 +530,12 @@ sap.ui.define([
|
|
|
472
530
|
Check if custom.css indication rule is applied to <link> element
|
|
473
531
|
The rule looks like this:
|
|
474
532
|
|
|
475
|
-
link[id^="sap-ui-theme-"]::after
|
|
476
|
-
.sapUiThemeDesignerCustomCss {
|
|
477
|
-
content: '{"customcss" : true}';
|
|
478
|
-
}
|
|
533
|
+
link[id^="sap-ui-theme-"]::after
|
|
479
534
|
|
|
480
|
-
|
|
481
|
-
the second one for the Safari workaround (see below).
|
|
535
|
+
Selector is to apply it to the <link> elements.
|
|
482
536
|
*/
|
|
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
|
-
}
|
|
537
|
+
const style = window.getComputedStyle(cssFile, ':after');
|
|
538
|
+
let content = style ? style.getPropertyValue('content') : null;
|
|
497
539
|
|
|
498
540
|
if (content && content !== "none") {
|
|
499
541
|
try {
|
|
@@ -520,16 +562,16 @@ sap.ui.define([
|
|
|
520
562
|
* checks if a particular class is available at the beginning of the stylesheet
|
|
521
563
|
*/
|
|
522
564
|
|
|
523
|
-
|
|
565
|
+
const aRules = cssFile.sheet ? safeAccessSheetCssRules(cssFile.sheet) : null;
|
|
524
566
|
|
|
525
567
|
if (!aRules || aRules.length === 0) {
|
|
526
|
-
Log.warning(
|
|
568
|
+
Log.warning(`Custom check: Failed retrieving a CSS rule from stylesheet ${lib}`, undefined, MODULE_NAME);
|
|
527
569
|
return false;
|
|
528
570
|
}
|
|
529
571
|
|
|
530
572
|
// we should now have some rule name ==> try to match against custom check
|
|
531
|
-
for (
|
|
532
|
-
if (
|
|
573
|
+
for (let i = 0; (i < 2 && i < aRules.length) ; i++) {
|
|
574
|
+
if (CUSTOM_CSS_CHECK.test(aRules[i].selectorText)) {
|
|
533
575
|
return true;
|
|
534
576
|
}
|
|
535
577
|
}
|
|
@@ -537,38 +579,9 @@ sap.ui.define([
|
|
|
537
579
|
return false;
|
|
538
580
|
}
|
|
539
581
|
|
|
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
582
|
// helper to add the FOUC marker to the CSS for the given id
|
|
570
583
|
function fnAddFoucmarker(sLinkId) {
|
|
571
|
-
|
|
584
|
+
const oLink = document.getElementById(sLinkId);
|
|
572
585
|
if (oLink) {
|
|
573
586
|
oLink.dataset.sapUiFoucmarker = sLinkId;
|
|
574
587
|
}
|
|
@@ -592,146 +605,142 @@ sap.ui.define([
|
|
|
592
605
|
* @param {object} oTheme Theme object containing the old and the new theme
|
|
593
606
|
* @param {string} oTheme.new Name of the new theme
|
|
594
607
|
* @param {string} oTheme.old Name of the previous theme
|
|
595
|
-
*
|
|
596
|
-
* @private
|
|
597
608
|
*/
|
|
598
609
|
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
|
-
|
|
610
|
+
const html = document.documentElement;
|
|
611
|
+
const sTheme = oTheme.new;
|
|
611
612
|
|
|
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);
|
|
613
|
+
for (const [, oLibInfo] of mAllLoadedLibraries) {
|
|
614
|
+
delete oLibInfo.themeFallback;
|
|
626
615
|
}
|
|
627
|
-
|
|
616
|
+
_sFallbackThemeFromMetadata = _sFallbackThemeFromThemeRoot = null;
|
|
628
617
|
|
|
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
|
-
}
|
|
618
|
+
Log.debug(`ThemeManager: Theme changed from ${oTheme.old} to ${sTheme}`, undefined, MODULE_NAME);
|
|
619
|
+
updateThemeUrls(sTheme, /* bSuppressFOUC */ true);
|
|
648
620
|
|
|
649
|
-
|
|
621
|
+
// modify the <html> tag's CSS class with the theme name
|
|
622
|
+
html.classList.remove(`sapUiTheme-${oTheme.old}`);
|
|
623
|
+
html.classList.add(`sapUiTheme-${sTheme}`);
|
|
624
|
+
}
|
|
650
625
|
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
626
|
+
function safeAccessSheetCssRules(sheet) {
|
|
627
|
+
try {
|
|
628
|
+
return sheet.cssRules;
|
|
629
|
+
} catch (e) {
|
|
630
|
+
// Firefox throws a SecurityError or InvalidAccessError if "sheet.cssRules"
|
|
631
|
+
// is accessed on a stylesheet with 404 response code.
|
|
632
|
+
// Most browsers also throw when accessing from a different origin (CORS).
|
|
633
|
+
return null;
|
|
658
634
|
}
|
|
635
|
+
}
|
|
659
636
|
|
|
660
|
-
|
|
661
|
-
|
|
637
|
+
function hasSheetCssRules(sheet) {
|
|
638
|
+
const aCssRules = safeAccessSheetCssRules(sheet);
|
|
639
|
+
return !!aCssRules && aCssRules.length > 0;
|
|
640
|
+
}
|
|
662
641
|
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
642
|
+
// Collect all UI5 relevant CSS files which have been added upfront
|
|
643
|
+
// and add them to UI5 theming lifecycle
|
|
644
|
+
document.querySelectorAll(`link[id^=${THEME_PREFIX}]`).forEach(function(cssLinkElement) {
|
|
645
|
+
let bPreloadedCssReady = true;
|
|
646
|
+
const sLinkId = cssLinkElement.getAttribute("id");
|
|
647
|
+
const [,libName, variant] = (sLinkId.match(LINK_ID_WITH_VARIANT_CHECK) || sLinkId.match(LINK_ID_CHECK));
|
|
648
|
+
const oLibInfo = getLibraryInfo({
|
|
649
|
+
libName,
|
|
650
|
+
variant,
|
|
651
|
+
linkId: sLinkId
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
Log.info(`Preloaded CSS for library ${libName + (variant ? ` with variant ${variant} ` : "")} detected: ${cssLinkElement.href}`, undefined, MODULE_NAME);
|
|
655
|
+
|
|
656
|
+
const { promise: cssLoaded, resolve, reject } = Promise.withResolvers();
|
|
657
|
+
const handleReady = function(bError) {
|
|
658
|
+
if (bError) {
|
|
659
|
+
reject();
|
|
660
|
+
} else {
|
|
661
|
+
resolve();
|
|
662
|
+
}
|
|
663
|
+
};
|
|
668
664
|
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
sLibFileName = sStandardLibFilePrefix + sRTL + ".css";
|
|
672
|
-
}
|
|
665
|
+
try {
|
|
666
|
+
bPreloadedCssReady = !!(cssLinkElement.sheet?.href === cssLinkElement.href && cssLinkElement.sheet?.cssRules);
|
|
673
667
|
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
668
|
+
if (!bPreloadedCssReady) {
|
|
669
|
+
ThemeManager.themeLoaded = bPreloadedCssReady;
|
|
670
|
+
cssLinkElement.addEventListener("load", () => {
|
|
671
|
+
handleReady(false);
|
|
672
|
+
});
|
|
673
|
+
cssLinkElement.addEventListener("error", () => {
|
|
674
|
+
handleReady(true);
|
|
675
|
+
});
|
|
676
|
+
} else {
|
|
677
|
+
handleReady(!(cssLinkElement.sheet.cssRules.length > 0));
|
|
683
678
|
}
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
// the
|
|
687
|
-
|
|
688
|
-
includeStylesheet(sHref, oLink.id);
|
|
689
|
-
}
|
|
690
|
-
}
|
|
679
|
+
includeStyleSheetPostProcessing(oLibInfo, cssLoaded, true);
|
|
680
|
+
} catch (e) {
|
|
681
|
+
// If the stylesheet is cross-origin and throws a security error, we can't verify directly
|
|
682
|
+
Log.info("Could not detect ready state of preloaded CSS. Request stylesheet again to verify the response status", undefined, MODULE_NAME);
|
|
691
683
|
|
|
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
|
-
}
|
|
684
|
+
ThemeManager.themeLoaded = false;
|
|
685
|
+
|
|
686
|
+
updateThemeUrl({
|
|
687
|
+
libInfo: oLibInfo,
|
|
688
|
+
suppressFOUC: true,
|
|
689
|
+
force: true
|
|
690
|
+
});
|
|
710
691
|
}
|
|
711
|
-
|
|
712
|
-
}
|
|
692
|
+
});
|
|
713
693
|
|
|
714
694
|
// set CSS class for the theme name
|
|
715
695
|
document.documentElement.classList.add("sapUiTheme-" + Theming.getTheme());
|
|
716
|
-
Log.info(
|
|
696
|
+
Log.info(`Declared theme ${Theming.getTheme()}`, undefined, MODULE_NAME);
|
|
717
697
|
|
|
718
|
-
|
|
698
|
+
attachChange(function(oEvent) {
|
|
719
699
|
var mThemeRoots = oEvent.themeRoots;
|
|
720
700
|
var oTheme = oEvent.theme;
|
|
701
|
+
var oLib = oEvent.library;
|
|
721
702
|
if (mThemeRoots && mThemeRoots.forceUpdate) {
|
|
722
|
-
|
|
703
|
+
updateThemeUrls(Theming.getTheme());
|
|
723
704
|
}
|
|
724
705
|
if (oTheme) {
|
|
725
706
|
applyTheme(oTheme);
|
|
726
707
|
}
|
|
708
|
+
if (oLib) {
|
|
709
|
+
includeLibraryTheme(oLib);
|
|
710
|
+
}
|
|
727
711
|
});
|
|
728
712
|
|
|
729
|
-
|
|
713
|
+
// handle RTL changes
|
|
714
|
+
Localization.attachChange(function(oEvent){
|
|
715
|
+
const bRTL = oEvent.rtl;
|
|
716
|
+
if (bRTL !== undefined) {
|
|
717
|
+
updateThemeUrls(Theming.getTheme());
|
|
718
|
+
}
|
|
719
|
+
});
|
|
730
720
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
721
|
+
registerThemeManager(ThemeManager, (fireApplied) => {
|
|
722
|
+
oEventing.attachEvent("applied", fireApplied);
|
|
723
|
+
});
|
|
724
|
+
|
|
725
|
+
OwnStatics.set(ThemeManager, {
|
|
726
|
+
/**
|
|
727
|
+
* Returns libraryInfoObject
|
|
728
|
+
*
|
|
729
|
+
* @param {string} libInfoId The ID of the libraryInfo object
|
|
730
|
+
* @returns {Map<string, object>|object|undefined} A map with all available libraryInfoObjects, a specific libraryInfoObject
|
|
731
|
+
* or undefined in case a specific libraryInfoObject was requested but does not exists
|
|
732
|
+
* @private
|
|
733
|
+
* @ui5-restricted sap.ui.core.theming.Parameters
|
|
734
|
+
*/
|
|
735
|
+
getAllLibraryInfoObjects: (libInfoId) => {
|
|
736
|
+
if (libInfoId) {
|
|
737
|
+
return mAllLoadedLibraries.get(libInfoId);
|
|
738
|
+
}
|
|
739
|
+
const mAllInfoObjects = new Map(mAllLoadedLibraries);
|
|
740
|
+
mAllInfoObjects.delete(CUSTOM_ID);
|
|
741
|
+
return mAllInfoObjects;
|
|
742
|
+
}
|
|
743
|
+
});
|
|
735
744
|
|
|
736
745
|
return ThemeManager;
|
|
737
746
|
});
|