UNPKG

@openui5/sap.ui.core

Version:

OpenUI5 Core Library sap.ui.core

1,548 lines (1,386 loc) 130 kB
/*! * OpenUI5 * (c) Copyright 2026 SAP SE or an SAP affiliate company. * Licensed under the Apache License, Version 2.0 - see LICENSE.txt. */ // Provides the real core class sap.ui.core.Core of SAPUI5 sap.ui.define([ "./AnimationMode", "./Component", "./Configuration", "./ControlBehavior", "./Element", "./ElementRegistry", "./Lib", "./LocaleData", "./Rendering", "./RenderManager", "./UIArea", "./Messaging", "./StaticArea", "./Supportability", "./Theming", "sap/base/assert", "sap/base/config", "sap/base/Event", "sap/base/Log", "sap/base/i18n/Formatting", "sap/base/i18n/Localization", "sap/base/util/Deferred", "sap/base/util/isEmptyObject", "sap/base/util/ObjectPath", "sap/base/util/Version", "sap/ui/Device", "sap/ui/Global", "sap/ui/VersionInfo", "sap/ui/base/EventProvider", "sap/ui/base/Interface", "sap/ui/base/ManagedObject", "sap/ui/base/Object", "sap/ui/base/syncXHRFix", "sap/ui/core/support/Hotkeys", "sap/ui/core/util/_LocalizationHelper", "sap/ui/dom/getComputedStyleFix", "sap/ui/performance/Measurement", "sap/ui/performance/trace/initTraces", "sap/ui/security/FrameOptions", "sap/ui/security/Security", "sap/ui/test/RecorderHotkeyListener", "sap/ui/thirdparty/jquery", "jquery.sap.global", // side effect: activates paste event fix "sap/ui/events/PasteEventFix", // side effect: install event simulation "sap/ui/events/jquery/EventSimulation", // side effect: make global URI available "sap/ui/thirdparty/URI", // side effect: jQuery.fn.position "sap/ui/thirdparty/jqueryui/jquery-ui-position" ], function( AnimationMode, Component, Configuration, ControlBehavior, Element, ElementRegistry, Library, LocaleData, Rendering, RenderManager, UIArea, Messaging, StaticArea, Supportability, Theming, assert, BaseConfig, BaseEvent, Log, Formatting, Localization, Deferred, isEmptyObject, ObjectPath, Version, Device, Global, VersionInfo, EventProvider, Interface, ManagedObject, BaseObject, syncXHRFix, Hotkeys, _LocalizationHelper, getComputedStyleFix, Measurement, initTraces, FrameOptions, Security, RecorderHotkeyListener, jQuery /* jQuery.sap, PasteEventFix, EventSimulation, URI, jquery-ui-position */ ) { "use strict"; var oCore; /** * The Core version, e.g. '1.127.0' * @name sap.ui.core.Core.prototype.version * @final * @type {string} * @since 1.127 * @private * @ui5-restricted sap.ui.core, sap.ui.test */ const sVersion = "1.147.0"; /** * The buildinfo. * @typedef {object} sap.ui.core.Core.BuildInfo * @property {string} buildtime the build timestamp, e.g. '20240625091308' * @since 1.127 * @private * @ui5-restricted sap.ui.core, sap.ui.test */ /** * The buildinfo, containing a build timestamp. * @name sap.ui.core.Core.prototype.buildinfo * @final * @type {sap.ui.core.Core.BuildInfo} * @since 1.127 * @private * @ui5-restricted sap.ui.core, sap.ui.test */ const oBuildinfo = Object.assign({}, Global.buildinfo); // freeze since it is exposed as a property on the Core and must not be changed at runtime // (refer to Core#getInterface) Object.freeze(oBuildinfo); // getComputedStyle polyfill + syncXHR fix for firefox if (Device.browser.firefox) { getComputedStyleFix(); if (Device.browser.version < 129) { // Firefox fixes the issue from its version 129. See // https://bugzilla.mozilla.org/show_bug.cgi?id=697151 // https://wpt.fyi/results/xhr/send-sync-blocks-async.htm?label=experimental&label=master&aligned syncXHRFix(); } } if (BaseConfig.get({ name: "sapUiNoConflict", type: BaseConfig.Type.Boolean, freeze: true })){ jQuery.noConflict(); } // set LogLevel const sLogLevel = BaseConfig.get({ name: "sapUiLogLevel", type: BaseConfig.Type.String, defaultValue: undefined, external: true }); if (sLogLevel) { Log.setLevel(Log.Level[sLogLevel.toUpperCase()] || parseInt(sLogLevel)); } else if (!globalThis["sap-ui-optimized"]) { Log.setLevel(Log.Level.DEBUG); } const oJQVersion = Version(jQuery.fn.jquery); if ( oJQVersion.compareTo("3.6.0") != 0 ) { // if the loaded jQuery version isn't SAPUI5's default version -> notify // the application Log.warning("SAPUI5's default jQuery version is 3.6.0; current version is " + jQuery.fn.jquery + ". Please note that we only support version 3.6.0."); } sap.ui.loader._.logger = Log.getLogger("sap.ui.ModuleSystem", BaseConfig.get({ name: "sapUiXxDebugModuleLoading", type: BaseConfig.Type.Boolean, external: true, freeze: true }) ? Log.Level.DEBUG : Math.min(Log.getLevel(), Log.Level.INFO)); //init Hotkeys for support tools Hotkeys.init(); RecorderHotkeyListener.init(); /** * when the Core module has been executed before, don't execute it again * @deprecated as of version 1.119 */ if (sap.ui.getCore && sap.ui.getCore()) { return sap.ui.getCore(); } // Initialize SAP Passport or FESR initTraces(); /** * EventProvider instance, EventProvider is no longer extended * @private */ var _oEventProvider; /** * Execute configured init module */ var _executeInitModule = function() { var vOnInit = BaseConfig.get({ name: "sapUiOnInit", type: (vValue) => { if (typeof vValue === "string" || typeof vValue === "function") { return vValue; } else { throw new TypeError("unsupported value"); } } }); if (vOnInit) { if (typeof vOnInit === "string") { // determine onInit being a module name prefixed via module or a global name var aResult = /^module\:((?:[_$.\-a-zA-Z0-9]+\/)*[_$.\-a-zA-Z0-9]+)$/.exec(vOnInit); if (aResult && aResult[1]) { // ensure that the require is done async and the Core is finally booted! setTimeout(sap.ui.require.bind(null, [aResult[1]]), 0); } else if (typeof globalThis[vOnInit] === "function") { globalThis[vOnInit](); } else { throw Error("Invalid init module " + vOnInit + " provided via config option 'sapUiOnInit'"); } } else { vOnInit(); } } }; /** * @deprecated As of Version 1.120 */ function _executeOnInit() { var vOnInit = BaseConfig.get({ name: "sapUiOnInit", type: BaseConfig.Type.Code, defaultValue: BaseConfig.get({ name: "sapUiEvtOninit", type: BaseConfig.Type.Code }) }); // execute a configured init hook if ( vOnInit ) { if ( typeof vOnInit === "function" ) { vOnInit(); } else if (typeof vOnInit === "string") { // determine onInit being a module name prefixed via module or a global name var aResult = /^module\:((?:[_$.\-a-zA-Z0-9]+\/)*[_$.\-a-zA-Z0-9]+)$/.exec(vOnInit); if (aResult && aResult[1]) { // ensure that the require is done async and the Core is finally booted! setTimeout(sap.ui.require.bind(sap.ui, [aResult[1]]), 0); } else { // lookup the name specified in onInit and try to call the function directly var fn = ObjectPath.get(vOnInit); if (typeof fn === "function") { fn(); } else { Log.warning("[DEPRECATED] Do not use inline JavaScript code with the oninit attribute." + " Use the module:... syntax or the name of a global function"); /* * In contrast to eval(), window.eval() executes the given string * in the global context, without closure variables. * See http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.2 */ // eslint-disable-next-line no-eval window.eval(vOnInit); // csp-ignore-legacy-api } } } } } /** * Returns the waiting behavior for the initial theme loading. * Possible values are: * <ul> * <li>undefined (default): * By default neither the initialization of the SAPUI5 Core nor the first rendering * wait for the configured theme to be loaded. * </li> * <li>"rendering": * The first (initial) rendering of the application will be delayed until the theme * has been loaded and applied (until Core.isThemeApplied()). * Helps to avoid FOUC (flash of unstyled content). * </li> * <li>"init": * Same as "rendering", but additionally delays the init event of theSAPUI5 Core until * the configured theme has been loaded. Application code that waits for this event can * then rely on the theming information to be present, * e.g. for calling sap.ui.core.theming.Parameters.get * </li> * </ul> * * @returns {string} the configured waiting behavior for the initial theme loading */ function getWaitForTheme() { var sWaitForTheme = BaseConfig.get({name: "sapUiXxWaitForTheme", type: BaseConfig.Type.String, external: true}).toLowerCase(); if (sWaitForTheme === "true" ) { sWaitForTheme = "rendering"; } if ( sWaitForTheme !== "rendering" && sWaitForTheme !== "init" ) { // invalid value or false from legacy boolean setting sWaitForTheme = undefined; } return sWaitForTheme; } function ui5ToRJS(sName) { if ( /^jquery\.sap\./.test(sName) ) { return sName; } return sName.replace(/\./g, "/"); } /* * Internal class that can help to synchronize a set of asynchronous tasks. * Each task must be registered in the sync point by calling startTask with * an (purely informative) title. The returned value must be used in a later * call to finishTask. * When finishTask has been called for all tasks that have been started, * the fnCallback will be fired. * When a timeout is given and reached, the callback is called at that * time, no matter whether all tasks have been finished or not. */ var SyncPoint = function (sName, fnCallback) { var aTasks = [], iOpenTasks = 0, iFailures = 0; this.startTask = function(sTitle) { var iId = aTasks.length; aTasks[iId] = { name : sTitle, finished : false }; iOpenTasks++; return iId; }; this.finishTask = function(iId, bSuccess) { if ( !aTasks[iId] || aTasks[iId].finished ) { throw new Error("trying to finish non existing or already finished task"); } aTasks[iId].finished = true; iOpenTasks--; if ( bSuccess === false ) { iFailures++; } if ( iOpenTasks === 0 ) { Log.info("Sync point '" + sName + "' finished (tasks:" + aTasks.length + ", open:" + iOpenTasks + ", failures:" + iFailures + ")"); finish(); } }; function finish() { if ( fnCallback ) { fnCallback(iOpenTasks, iFailures); } fnCallback = null; } Log.info("Sync point '" + sName + "' created"); }; /** * Creates a new subclass of class <code>sap.ui.core.Core</code> with name * <code>sClassName</code> and enriches it with the information contained in <code>oClassInfo</code>. * * <code>oClassInfo</code> might contain the same kind of information as described in * {@link sap.ui.base.ManagedObject.extend}. * * @param {string} sClassName * Qualified name of the newly created class * @param {object} [oClassInfo] * Object literal with information about the class * @param {sap.ui.core.Component.MetadataOptions} [oClassInfo.metadata] * The metadata object describing the class. * See {@link sap.ui.core.Component.MetadataOptions MetadataOptions} for the values allowed in every extend. * @returns {function} The created class / constructor function * @name sap.ui.core.Core.extend * @function * @static * @public * @deprecated As of version 1.119, without replacement. In future major versions, the Core no longer has * a class nature and therefore can't be extended. */ /** * Returns the metadata for class <code>sap.ui.core.Core</code>. * * @returns {sap.ui.base.Metadata} Metadata object describing this class * @public * @static * @name sap.ui.core.Core.getMetadata * @function * @deprecated As of version 1.119, without replacement. In future major versions, the Core no longer has * a class nature and no longer inherits from sap.ui.base.Object and therefore no longer has metadata. */ /** * @class Singleton Core instance of the SAP UI Library. * * The module export of <code>sap/ui/core/Core</code> is <b>not</b> a class, but the singleton Core instance itself. * The <code>sap.ui.core.Core</code> class itself must not be instantiated, except by the framework itself. * * The Core provides a {@link #ready ready function} to execute code after the Core was booted. * * Example: * <pre> * * sap.ui.require(["sap/ui/core/Core"], async function(Core) { * * // Usage of a callback function * Core.ready(function() { * ... * }); * * // Usage of Core.ready() as a Promise * await Core.ready(); * ... * }); * * </pre> * * @extends sap.ui.base.Object * @final * @author SAP SE * @version 1.147.0 * @alias sap.ui.core.Core * @public * @hideconstructor */ var Core = BaseObject.extend("sap.ui.core.Core", /** @lends sap.ui.core.Core.prototype */ { constructor : function() { BaseObject.call(this); var that = this, METHOD = "sap.ui.core.Core"; // when a Core instance has been created before, don't create another one if (oCore) { Log.error("Only the framework must create an instance of sap/ui/core/Core." + " To get access to its functionality, require sap/ui/core/Core," + " and use the module export directly without using 'new'."); return oCore; } _oEventProvider = new EventProvider(); /** * Generate all functions from EventProvider for backward compatibility * @deprecated as of version 1.119 */ ["attachEvent", "detachEvent", "getEventingParent"].forEach(function (sFuncName) { Core.prototype[sFuncName] = _oEventProvider[sFuncName].bind(_oEventProvider); }); /** * Whether the core has been booted * @private */ this.bBooted = false; /** * Whether the core has been initialized * @private */ this.bInitialized = false; /** * Whether the core is ready * @private */ this.bReady = false; /** * Available plugins in the order of registration. * @private */ this.aPlugins = []; /** * Default model used for databinding * @private */ this.oModels = {}; /** * The event bus (initialized lazily) * @private */ this.oEventBus = null; Object.defineProperty(this, "mElements", { get: function() { Log.error("oCore.mElements was a private member and has been removed. Use one of the methods in sap/ui/core/ElementRegistry instead"); return ElementRegistry.all(); // this is a very costly snapshot! }, configurable: false }); /** * Map of of created objects structured by their type which contains a map * containing the created objects keyed by their type. * * Each object registers itself in its constructor and deregisters itself in its * destroy method. * * @private * @todo get rid of this collection as it represents a candidate for memory leaks */ this.mObjects = { "template": {} }; /** * The instance of the root component (defined in the configuration {@link sap.ui.core.Configuration#getRootComponent}) * @private * @deprecated */ this.oRootComponent = null; /** * Ready Promise * @private */ this.pReady = new Deferred(); /** * Whether the legacy library has to be loaded. * @private */ this.bInitLegacyLib = false; Log.info("Creating Core",null,METHOD); Measurement.start("coreComplete", "Core.js - complete"); Measurement.start("coreBoot", "Core.js - boot"); Measurement.start("coreInit", "Core.js - init"); // freeze Config var GlobalConfigurationProvider = sap.ui.require("sap/base/config/GlobalConfigurationProvider"); GlobalConfigurationProvider.freeze(); /** * Legacy normalization of config parameters * @deprecated As of Version 1.120.0 */ (() => { const o = globalThis["sap-ui-config"]; for (const i in o) { const v = o[i]; const il = i.toLowerCase(); if ( !Object.hasOwn(o, il) ) { o[il] = v; delete o[i]; } } })(); // register resourceRoots const paths = {}; const oResourceRoots = BaseConfig.get({ name: "sapUiResourceRoots", type: BaseConfig.Type.MergedObject }) ?? {}; for (const n in oResourceRoots) { paths[ui5ToRJS(n)] = oResourceRoots[n] || "."; } sap.ui.loader.config({paths: paths}); /** * @deprecated As of Version 1.120 */ Configuration.setCore(this); /** * @deprecated as of version 1.118 */ (function() { var bHandleValidation = BaseConfig.get({ name: "sapUiXxHandleValidation", type: BaseConfig.Type.Boolean, external: true }); if (bHandleValidation) { Messaging.registerObject(this, true); } }.bind(this))(); // initialize frameOptions script (anti-clickjacking, etc.) var oFrameOptionsConfig = BaseConfig.get({ name: "sapUiFrameOptionsConfig", type: BaseConfig.Type.Object }); oFrameOptionsConfig.mode = Security.getFrameOptions(); oFrameOptionsConfig.allowlistService = Security.getAllowlistService(); this.oFrameOptions = new FrameOptions(oFrameOptionsConfig); // handle libraries & modules this.aModules = BaseConfig.get({ name: "sapUiModules", type: BaseConfig.Type.StringArray }) ?? []; this.aLibs = BaseConfig.get({ name: "sapUiLibs", type: BaseConfig.Type.StringArray }) ?? []; // as modules could also contain libraries move it to aLibs! this.aModules = this.aModules.filter((module) => { const m = module.match(/^(.*)\.library$/); if (m) { this.aLibs.push(m[1]); } else { return module; } }); /** * in case the flexibilityServices configuration was set to a non-empty, * non-default value, sap.ui.fl becomes mandatory if not overruled by * 'xx-skipAutomaticFlLibLoading'. * @deprecated As of Version 1.120.0 */ (() => { const sFlexDefault = "/sap/bc/lrep"; const vFlexibilityServices = BaseConfig.get({ name: "sapUiFlexibilityServices", type: (value) => { return value; }, external: true, defaultValue: sFlexDefault }); const bXxSkipAutomaticFlLibLoading = BaseConfig.get({ name: "sapUiXxSkipAutomaticFlLibLoading", type: BaseConfig.Type.Boolean, external: true }); if (vFlexibilityServices && vFlexibilityServices !== sFlexDefault && !bXxSkipAutomaticFlLibLoading && !this.aLibs.includes("sap.ui.fl")) { this.aLibs.push("sap.ui.fl"); } })(); /** * @deprecated */ if (Supportability.isDebugModeEnabled()) { // add debug module if configured this.aModules.unshift("sap.ui.debug.DebugEnv"); } // enforce the core library as the first loaded module var i = this.aLibs.indexOf("sap.ui.core"); if ( i != 0 ) { if ( i > 0 ) { this.aLibs.splice(i,1); } this.aLibs.unshift("sap.ui.core"); } var sPreloadMode = Library.getPreloadMode(); // This flag controls the core initialization flow. // We can switch to async when an async preload is used or the ui5loader // is in async mode. The latter might also happen for debug scenarios // where no preload is used at all. var bAsync = sPreloadMode === "async" || sap.ui.loader.config().async; // adding the following classList is done here for compatibility reasons document.documentElement.classList.add("sapUiTheme-" + Theming.getTheme()); Log.info("Declared theme " + Theming.getTheme(), null, METHOD); Log.info("Declared modules: " + this.aModules, METHOD); Log.info("Declared libraries: " + this.aLibs, METHOD); _LocalizationHelper.init(); /** * @deprecated As of Version 1.120 */ _LocalizationHelper.registerForUpdate("Core", () => { return {"Core": this}; }); this._setupBrowser(); this._setupOS(); this._setupAnimation(); // create accessor to the Core API early so that initLibrary and others can use it /** * Retrieve the {@link sap.ui.core.Core SAPUI5 Core} instance for the current window. * @returns {sap.ui.core.Core} the API of the current SAPUI5 Core instance. * @public * @function * @deprecated as of version 1.118. Please require 'sap/ui/core/Core' instead and use the * module export directly without using 'new'. * @ui5-global-only */ sap.ui.getCore = function() { return that.getInterface(); }; // sync point 1 synchronizes document ready and rest of UI5 boot var oSyncPoint1 = new SyncPoint("UI5 Document Ready", function(iOpenTasks, iFailures) { that.init(); }); var iDocumentReadyTask = oSyncPoint1.startTask("document.ready"); var iCoreBootTask = oSyncPoint1.startTask("preload and boot"); var fnContentLoadedCallback = function() { Log.trace("document is ready"); oSyncPoint1.finishTask(iDocumentReadyTask); document.removeEventListener("DOMContentLoaded", fnContentLoadedCallback); }; // immediately execute callback if the ready state is already 'complete' if (document.readyState !== "loading") { fnContentLoadedCallback(); } else { // task 1 is to wait for document.ready document.addEventListener("DOMContentLoaded", fnContentLoadedCallback); } // sync point 2 synchronizes all library preloads and the end of the bootstrap script var oSyncPoint2 = new SyncPoint("UI5 Core Preloads and Bootstrap Script", function(iOpenTasks, iFailures) { Log.trace("Core loaded: open=" + iOpenTasks + ", failures=" + iFailures); that._boot(bAsync, function() { oSyncPoint1.finishTask(iCoreBootTask); Measurement.end("coreBoot"); }); }); // a helper task to prevent the premature completion of oSyncPoint2 var iCreateTasksTask = oSyncPoint2.startTask("create sp2 tasks task"); // load the version info file in case of a custom theme to determine // the distribution version which should be provided in library.css requests. if (Library.getVersionedLibCss()) { var iVersionInfoTask = oSyncPoint2.startTask("load version info"); var fnCallback = function(oVersionInfo) { if (oVersionInfo) { Log.trace("Loaded \"sap-ui-version.json\"."); } else { Log.error("Could not load \"sap-ui-version.json\"."); } oSyncPoint2.finishTask(iVersionInfoTask); }; // use async mode if library preload is async if ( bAsync ) { VersionInfo.load().then(fnCallback, function(oError) { Log.error("Unexpected error when loading \"sap-ui-version.json\": " + oError); oSyncPoint2.finishTask(iVersionInfoTask); }); } else { fnCallback(sap.ui.getVersionInfo({ async: bAsync, failOnError: false })); // legacy-relevant: sync path } } this._polyfillFlexbox(); // when the bootstrap script has finished, it calls require("sap/ui/core/Core").boot() var iBootstrapScriptTask = oSyncPoint2.startTask("bootstrap script"); this.boot = function() { if (this.bBooted) { return; } this.bBooted = true; postConstructorTasks.call(this); oSyncPoint2.finishTask(iBootstrapScriptTask); }; function postConstructorTasks() { // when a boot task is configured, add it to syncpoint2 var fnCustomBootTask = BaseConfig.get({ name: "sapUiXxBootTask", type: BaseConfig.Type.Function }); if ( fnCustomBootTask ) { var iCustomBootTask = oSyncPoint2.startTask("custom boot task"); fnCustomBootTask( function(bSuccess) { oSyncPoint2.finishTask(iCustomBootTask, typeof bSuccess === "undefined" || bSuccess === true ); }); } if ( sPreloadMode === "sync" || sPreloadMode === "async" ) { var pLibraryPreloaded = Library._load(that.aLibs, { sync: !bAsync, preloadOnly: true }); if ( bAsync ) { var iPreloadLibrariesTask = oSyncPoint2.startTask("preload bootstrap libraries"); pLibraryPreloaded.then(function() { oSyncPoint2.finishTask(iPreloadLibrariesTask); }, function() { oSyncPoint2.finishTask(iPreloadLibrariesTask, false); }); } } // initializes the application cachebuster mechanism if configured var aACBConfig = BaseConfig.get({ name: "sapUiAppCacheBuster", type: BaseConfig.Type.StringArray, external: true, freeze: true }); if (aACBConfig && aACBConfig.length > 0) { if ( bAsync ) { var iLoadACBTask = oSyncPoint2.startTask("require AppCachebuster"); sap.ui.require(["sap/ui/core/AppCacheBuster"], function(AppCacheBuster) { AppCacheBuster.boot(oSyncPoint2, aACBConfig); // finish the task only after ACB had a chance to create its own task(s) oSyncPoint2.finishTask(iLoadACBTask); }); } /** * Sync path is deprecated * * @deprecated as of 1.120.0 */ if (!bAsync) { var AppCacheBuster = sap.ui.requireSync('sap/ui/core/AppCacheBuster'); // legacy-relevant: Synchronous path AppCacheBuster.boot(oSyncPoint2, aACBConfig); } } // Initialize support info stack if (Supportability.getSupportSettings() !== null) { var iSupportInfoTask = oSyncPoint2.startTask("support info script"); var fnCallbackSupportBootstrapInfo = function(Support, Bootstrap) { Support.initializeSupportMode(Supportability.getSupportSettings(), bAsync); Bootstrap.initSupportRules(Supportability.getSupportSettings()); oSyncPoint2.finishTask(iSupportInfoTask); }; if (bAsync) { sap.ui.require(["sap/ui/core/support/Support", "sap/ui/support/Bootstrap"], fnCallbackSupportBootstrapInfo, function (oError) { Log.error("Could not load support mode modules:", oError); }); } /** * @deprecated */ if (!bAsync) { Log.warning("Synchronous loading of Support mode. Set preload configuration to 'async' or switch to asynchronous bootstrap to prevent these synchronous request.", "SyncXHR", null, function() { return { type: "SyncXHR", name: "support-mode" }; }); fnCallbackSupportBootstrapInfo( sap.ui.requireSync("sap/ui/core/support/Support"), // legacy-relevant: Synchronous path sap.ui.requireSync("sap/ui/support/Bootstrap") // legacy-relevant: Synchronous path ); } } // Initialize test tools if (Supportability.getTestRecorderSettings() !== null) { var iTestRecorderTask = oSyncPoint2.startTask("test recorder script"); var fnCallbackTestRecorder = function (Bootstrap) { Bootstrap.init(Supportability.getTestRecorderSettings()); oSyncPoint2.finishTask(iTestRecorderTask); }; if (bAsync) { sap.ui.require([ "sap/ui/testrecorder/Bootstrap" ], fnCallbackTestRecorder, function (oError) { Log.error("Could not load test recorder:", oError); }); } /** * @deprecated */ if (!bAsync) { Log.warning("Synchronous loading of Test recorder mode. Set preload configuration to 'async' or switch to asynchronous bootstrap to prevent these synchronous request.", "SyncXHR", null, function() { return { type: "SyncXHR", name: "test-recorder-mode" }; }); fnCallbackTestRecorder( sap.ui.requireSync("sap/ui/testrecorder/Bootstrap") // legacy-relevant: Synchronous preloading ); } } oSyncPoint2.finishTask(iCreateTasksTask); } }, metadata : { // while this list contains mostly public methods, // a set of private API is exposed for sap.ui.core restricted usage publicMethods: [ // @public // - Ready Promise "ready", // @private, @ui5-restricted sap.ui.core // - Init "boot", // @deprecated "getConfiguration", "isMobile", // - Init & Plugins "isInitialized","attachInit", "lock", "unlock","isLocked", "attachInitEvent", "registerPlugin","unregisterPlugin", // - Application/Root-Component "setRoot", "getRootComponent", "getApplication", // - legacy registries & factories "getControl", "getComponent", "getTemplate", "createComponent", // - Control dev. "getCurrentFocusedControlId", "getEventBus", "byId", "attachIntervalTimer", "detachIntervalTimer", "getElementById", "byFieldGroupId", // - Libraries "getLoadedLibraries", "loadLibrary", "initLibrary", "getLibraryResourceBundle", "attachLibraryChanged", "detachLibraryChanged", "loadLibraries", // - Models & Messaging "setModel", "getModel", "hasModel", "getMessageManager", // - Events "attachEvent","detachEvent", "attachControlEvent", "detachControlEvent", "attachParseError", "detachParseError", "attachValidationError", "detachValidationError", "attachFormatError", "detachFormatError", "attachValidationSuccess", "detachValidationSuccess", "attachLocalizationChanged", "detachLocalizationChanged", "fireFormatError", "fireValidationSuccess", "fireValidationError", "fireParseError", // - UIArea & Rendering "getStaticAreaRef", "isStaticAreaRef", "createRenderManager", "createUIArea", "getUIArea", "getUIDirty", "applyChanges", "getRenderManager", "addPrerenderingTask", // - Theming "applyTheme","setThemeRoot","attachThemeChanged","detachThemeChanged", "isThemeApplied", "notifyContentDensityChanged", "includeLibraryTheme" ] } }); /* * Overwrite getInterface so that we can add the version info as a property * to the Core. */ Core.prototype.getInterface = function() { const oCoreInterface = BaseObject.prototype.getInterface.call(this); Object.defineProperties(oCoreInterface, { "version": { value: sVersion }, "buildinfo": { value: oBuildinfo } }); return oCoreInterface; }; /** * Map of event names and ids, that are provided by this class * @private */ Core.M_EVENTS = {ControlEvent: "ControlEvent", UIUpdated: "UIUpdated", ThemeChanged: "ThemeChanged", LocalizationChanged: "localizationChanged", LibraryChanged : "libraryChanged", ValidationError : "validationError", ParseError : "parseError", FormatError : "formatError", ValidationSuccess : "validationSuccess"}; /** * Set the body's browser-related attributes. * @private */ Core.prototype._setupBrowser = function() { var METHOD = "sap.ui.core.Core"; //set the browser for CSS attribute selectors. do not move this to the onload function because Safari does not //use the classes var html = document.documentElement; var b = Device.browser; var id = b.name; if (id) { if (id === b.BROWSER.SAFARI && b.mobile) { id = "m" + id; } id = id + (b.version === -1 ? "" : Math.floor(b.version)); html.dataset.sapUiBrowser = id; Log.debug("Browser-Id: " + id, null, METHOD); } }; /** * Set the body's OS-related attribute and CSS class * @private */ Core.prototype._setupOS = function() { var html = document.documentElement; html.dataset.sapUiOs = Device.os.name + Device.os.versionStr; var osCSS = null; switch (Device.os.name) { case Device.os.OS.IOS: osCSS = "sap-ios"; break; case Device.os.OS.ANDROID: osCSS = "sap-android"; break; } if (osCSS) { html.classList.add(osCSS); } }; /** * Set the body's Animation-related attribute and configures jQuery animations accordingly. * @private */ Core.prototype._setupAnimation = function() { function adaptAnimationMode() { var html = document.documentElement; var sAnimationMode = ControlBehavior.getAnimationMode(); html.dataset.sapUiAnimationMode = sAnimationMode; var bAnimation = (sAnimationMode !== AnimationMode.minimal && sAnimationMode !== AnimationMode.none); html.dataset.sapUiAnimation = bAnimation ? "on" : "off"; if (typeof jQuery !== "undefined") { jQuery.fx.off = !bAnimation; } } ControlBehavior.attachChange(function(oEvent) { if (oEvent.animationMode) { adaptAnimationMode(); } }); adaptAnimationMode(); }; /** * Initializes the jQuery.support.useFlexBoxPolyfill property * @private */ Core.prototype._polyfillFlexbox = function() { /** * Whether the current browser needs a polyfill as a fallback for flex box support * @type {boolean} * @private * @name jQuery.support.useFlexBoxPolyfill * @since 1.12.0 * @deprecated since version 1.16.0 * * For backwards compatibility we can't remove the deprecated flexbox polyfill. * However, if the compatibility version is 1.16 or higher then the polyfill * should not be used. */ jQuery.support.useFlexBoxPolyfill = false; }; /** * Boots the core and injects the necessary CSS and JavaScript files for the library. * Applications shouldn't call this method. It is automatically called by the bootstrap scripts (e.g. sap-ui-core.js) * * @param {boolean} bAsync - Flag if modules should be loaded asynchronously * @param {function} fnCallback - Callback after modules have been loaded * @returns {undefined|Promise} * @private */ Core.prototype._boot = function(bAsync, fnCallback) { // add CalendarClass to list of modules this.aModules.push("sap/ui/core/date/" + Formatting.getCalendarType()); // add FieldHelpEndpoint to list of modules this.aModules.push("sap/ui/core/boot/FieldHelpEndpoint"); // add KeyboardInteractionEndpoint to list of modules this.aModules.push("sap/ui/core/boot/KeyboardInteractionEndpoint"); // load all modules now if ( bAsync ) { return this._requireModulesAsync().then(function() { fnCallback(); }); } Log.warning("Modules and libraries declared via bootstrap-configuration are loaded synchronously. Set preload configuration to" + " 'async' or switch to asynchronous bootstrap to prevent these requests.", "SyncXHR", null, function() { return { type: "SyncXHR", name: "legacy-module" }; }); this.aLibs.forEach( function(lib) { Library._load(lib, { sync: true }); }); /** * @deprecated */ this.aModules.forEach( function(mod) { // data-sap-ui-modules might contain legacy jquery.sap.* modules sap.ui.requireSync( /^jquery\.sap\./.test(mod) ? mod : mod.replace(/\./g, "/")); // legacy-relevant: Sync loading of modules and libraries }); fnCallback(); }; Core.prototype._requireModulesAsync = function() { var aModules = []; this.aModules.forEach(function(sModule) { // data-sap-ui-modules might contain legacy jquery.sap.* modules aModules.push(/^jquery\.sap\./.test(sModule) ? sModule : sModule.replace(/\./g, "/")); }); // TODO: require libs and modules in parallel or define a sequence? return Promise.all([ Library._load(this.aLibs), new Promise(function(resolve) { sap.ui.require(aModules, function() { resolve(Array.prototype.slice.call(arguments)); }); }), LocaleData.requestInstance(Localization.getLanguageTag()) ]); }; /** * Applies the theme with the given name (by loading the respective style sheets, which does not disrupt the application). * * By default, the theme files are expected to be located at path relative to the respective control library ([libraryLocation]/themes/[themeName]). * Different locations can be configured by using the method setThemePath() or by using the second parameter "sThemeBaseUrl" of applyTheme(). * Usage of this second parameter is a shorthand for setThemePath and internally calls setThemePath, so the theme location is then known. * * sThemeBaseUrl is a single URL to specify the default location of all theme files. This URL is the base folder below which the control library folders * are located. E.g. if the CSS files are not located relative to the root location of UI5, but instead they are at locations like * http://my.server/myapp/resources/sap/ui/core/themes/my_theme/library.css * then the URL that needs to be given is: * http://my.server/myapp/resources * All theme resources are then loaded from below this folder - except if for a certain library a different location has been registered. * * If the theme resources are not all either below this base location or with their respective libraries, then setThemePath must be * used to configure individual locations. * * @param {string} sThemeName the name of the theme to be loaded * @param {string} [sThemeBaseUrl] the (optional) base location of the theme * @deprecated since 1.119. Please use {@link module:sap/ui/core/Theming.setTheme Theming.setTheme} instead. * @public */ Core.prototype.applyTheme = function(sThemeName, sThemeBaseUrl) { assert(typeof sThemeName === "string", "sThemeName must be a string"); assert(typeof sThemeBaseUrl === "string" || typeof sThemeBaseUrl === "undefined", "sThemeBaseUrl must be a string or undefined"); if (sThemeBaseUrl) { Theming.setThemeRoot(sThemeName, sThemeBaseUrl); } Theming.setTheme(sThemeName); }; /** * Defines the root directory from below which UI5 should load the theme with the given name. * Optionally allows restricting the setting to parts of a theme covering specific control libraries. * * Example: * <pre> * sap.ui.getCore().setThemeRoot("my_theme", "https://mythemeserver.com/allThemes"); * sap.ui.getCore().applyTheme("my_theme"); * </pre> * * will cause the following file to be loaded (assuming that the bootstrap is configured to load * libraries <code>sap.m</code> and <code>sap.ui.layout</code>): * <pre> * https://mythemeserver.com/allThemes/sap/ui/core/themes/my_theme/library.css * https://mythemeserver.com/allThemes/sap/ui/layout/themes/my_theme/library.css * https://mythemeserver.com/allThemes/sap/m/themes/my_theme/library.css * </pre> * * If parts of the theme are at different locations (e.g. because you provide a standard theme * like "sap_horizon" for a custom control library and this self-made part of the standard theme is at a * different location than the UI5 resources), you can also specify for which control libraries the setting * should be used, by giving an array with the names of the respective control libraries as second parameter: * <pre> * sap.ui.getCore().setThemeRoot("sap_horizon", ["my.own.library"], "https://mythemeserver.com/allThemes"); * </pre> * * This will cause the Horizon theme to be loaded from the UI5 location for all standard libraries. * Resources for styling the <code>my.own.library</code> controls will be loaded from the configured * location: * <pre> * https://sdk.openui5.org/resources/sap/ui/core/themes/sap_horizon/library.css * https://sdk.openui5.org/resources/sap/ui/layout/themes/sap_horizon/library.css * https://sdk.openui5.org/resources/sap/m/themes/sap_horizon/library.css * https://mythemeserver.com/allThemes/my/own/library/themes/sap_horizon/library.css * </pre> * * If the custom theme should be loaded initially (via bootstrap attribute), the <code>themeRoots</code> * property of the <code>window["sap-ui-config"]</code> object must be used instead of calling * <code>sap.ui.getCore().setThemeRoot(...)</code> in order to configure the theme location early enough. * * @param {string} sThemeName Name of the theme for which to configure the location * @param {string[]} [aLibraryNames] Optional library names to which the configuration should be restricted * @param {string} sThemeBaseUrl Base URL below which the CSS file(s) will be loaded from * @param {boolean} [bForceUpdate=false] Force updating URLs of currently loaded theme * @return {this} the Core, to allow method chaining * @since 1.10 * @deprecated As of version 1.119, without replacement. The need to define the location for a theme * should be fully covered with the capabilities of the {@link sap/base/config base configuration}. * @public */ Core.prototype.setThemeRoot = function(sThemeName, aLibraryNames, sThemeBaseUrl, bForceUpdate) { if (typeof aLibraryNames === "string") { bForceUpdate = sThemeBaseUrl; sThemeBaseUrl = aLibraryNames; aLibraryNames = undefined; } Theming.setThemeRoot(sThemeName, sThemeBaseUrl, aLibraryNames, bForceUpdate); return this; }; /** * Initializes the Core after the initial page was loaded * @private */ Core.prototype.init = function() { if (this.bInitialized) { return; } // provide core for event handling and UIArea creation UIArea.setCore(this); var METHOD = "sap.ui.core.Core.init()"; Log.info("Initializing",null,METHOD); Measurement.end("coreInit"); /** * @deprecated As of Version 1.120. */ this._setBodyAccessibilityRole(); var sWaitForTheme = getWaitForTheme(); // If there is no waitForTheme or ThemeManager is already available and theme is loaded render directly sync if (this.isThemeApplied() || !sWaitForTheme) { this._executeInitialization(); } else { Rendering.suspend(); if (sWaitForTheme === "rendering") { Rendering.notifyInteractionStep(); this._executeInitialization(); Rendering.getLogger().debug("delay initial rendering until theme has been loaded"); Theming.attachAppliedOnce(function() { Rendering.resume("after theme has been loaded"); }); } else if (sWaitForTheme === "init") { Rendering.getLogger().debug("delay init event and initial rendering until theme has been loaded"); Rendering.notifyInteractionStep(); Theming.attachAppliedOnce(function() { this._executeInitialization(); Rendering.resume("after theme has been loaded"); }.bind(this)); } } }; /** * Creates a "rootComponent" or "sap.ui.app.Application". * Both concepts are deprecated. * Called during Core initialization. * @deprecated since 1.95 * @private */ Core.prototype._setupRootComponent = function() { var METHOD = "sap.ui.core.Core.init()"; // load the root component // @deprecated concept, superseded by "sap/ui/core/ComponentSupport" var sRootComponent = Configuration.getRootComponent(); if (sRootComponent) { Log.info("Loading Root Component: " + sRootComponent,null,METHOD); var oComponent = sap.ui.component({ //legacy-relevant: Deprecated rootComponent API name: sRootComponent }); this.oRootComponent = oComponent; var sRootNode = BaseConfig.get({ name: "sapUiXxRootComponentNode", type: BaseConfig.Type.String }); if (sRootNode && oComponent.isA('sap.ui.core.UIComponent')) { var oRootNode = document.getElementById(sRootNode); if (oRootNode) { Log.info("Creating ComponentContainer for Root Component: " + sRootComponent,null,METHOD); var ComponentContainer = sap.ui.requireSync('sap/ui/core/ComponentContainer'), // legacy-relevant: Deprecated rootComponent API oContainer = new ComponentContainer({ component: oComponent, propagateModel: true /* TODO: is this a configuration or do this by default? right now it behaves like the application */ }); oContainer.placeAt(oRootNode); } } } else { // @deprecated concept, superseded by "sap/ui/core/Component" var sApplication = Configuration.getApplication(); if (sApplication) { Log.warning("The configuration 'application' is deprecated. Please use the configuration 'component' instead! " + "Please migrate from sap.ui.app.Application to sap.ui.core.Component.", "SyncXHR", null, function () { return { type: "Deprecation", name: "sap.ui.core" }; }); Log.info("Loading Application: " + sApplication,null,METHOD); sap.ui.requireSync(sApplication.replace(/\./g, "/")); // legacy-relevant: deprecated var oClass = ObjectPath.get(sApplication); assert(oClass !== undefined, "The specified application \"" + sApplication + "\" could not be found!"); var oApplication = new oClass(); assert(BaseObject.isObjectA(oApplication, 'sap.ui.app.Application'), "The specified application \"" + sApplication + "\" must be an instance of sap.ui.app.Application!"); } } }; /** * @deprecated As of Version 1.120. */ Core.prototype._setBodyAccessibilityRole = function() { var body = document.body; //Add ARIA role 'application' if (ControlBehavior.isAccessibilityEnabled() && Configuration.getAutoAriaBodyRole() && !body.getAttribute("role")) { body.setAttribute("role", "application"); } }; Core.prototype._executeInitialization = function() { // chain ready to be the first one that is executed var METHOD = "sap.ui.core.Core.init()"; // Because it's only used from init if (this.bInitialized) { return; } this.bInitialized = true; Log.info("Initialized",null,METHOD); // start the plugins Log.info("Starting Plugins",null,METHOD); this.startPlugins(); Log.info("Plugins started",null,METHOD); // informs native JavaScript that UI5 is initialized document.dispatchEvent(new CustomEvent("sap-ui-core-ready")); /** * @deprecated As ofVersion 1.120 */ _executeInitModule = _executeOnInit; _executeInitModule(); /** * @deprecated As of Version 1.120. */ this._setupRootComponent(); // @legacy-relevant: private API for 2 deprecated concepts "rootComponent" & "sap.ui.app.Application" this.pReady.resolve(); this.bReady = true; }; /** * Returns true if the Core has already been initialized. This means that instances * of RenderManager etc. do already exist and the init event has already been fired * (and will not be fired again). * * @return {boolean} whether the Core has already been initialized * @public * @deprecated since 1.118. Please use {@link sap.ui.core.Core.ready Core.ready} instead. */ Core.prototype.isInitialized = function () { return this.bInitialized; }; /** * Returns true, if the styles of the current theme are already applied, false otherwise. * * This function must not be used before the init event of the Core. * If the styles are not yet applied a theme changed event will follow when the styles will be applied. * * @return {boolean} whether the styles of the current theme are already applied * @deprecated since 1.119: Please use {@link module:sap/ui/core/Theming.attachApplied Theming.attachApplied} instead. * @public */ Core.prototype.isThemeApplied = function() { var bApplied = false; function fnCheckApplied() { bApplied = true; } // if theme is applied fnCheckApplied is called sync Theming.attachAppliedOnce(fnCheckApplied); return bApplied; }; /** * Attach to 'applied' event of theming in order to keep existing core event 'ThemeChanged' stable */ Theming.attachApplied(function(oEvent) { // notify the listeners via a control event _oEventProvider && _oEventProvider.fireEvent(Core.M_EVENTS.ThemeChanged, BaseEvent.getParameters(oEvent)); }); /** * Registers a given function that is executed after the framework has been initialized. * * The method is executed only once and only if the framework has not been initialized already. * This could be checked by calling {@link #isInitialized}, but in most cases it is more convenient to * use {@link #attachInit} instead. This guarantees that the given function is executed exactly once, * independent of the state of the framework. * * @param {function} fnFunction Function that is called after initialization of the framework * @public * @deprecated since 1.13.2 Register with the more convenient {@link #attachInit} function instead */ Core.prototype.attachInitEvent = function (fnFunction) { assert(typeof fnFunction === "function", "fnFunction must be a function"); if (!this.bReady) { this.pReady.promise.then(fnFunction); } }; /** * Registers a given function that is executed after the framework has been initialized. * * The given function will either be called as soon as the framework has been initialized * or, if it has been initialized already, it will be called immediately. * * More information about the initialization process and the steps it consists of can be found * in the documentation topic "{@link topic:91f2c9076f4d1014b6dd926db0e91070 Initialization Process}". * * @param {function} fnFunction Function to be after initialization of the framework * @public * @since 1.13.2 * @deprecated since 1.118. Please use {@link sap.ui.core.Core.ready Core.ready} instead. */ Core.prototype.attachInit = function (fnFunction) { assert(typeof fnFunction === "function", "fnFunction must be a function"); this.ready(fnFunction); }; /** * Locks the Core. No browser events are dispatched to the controls. * * Lock should be called before and after the DOM is modified for rendering, roundtrips... * Exceptions might be the case for asynchronous UI behavior * @public * @deprecated As of version 1.118, without a replacement. The ability to prevent * the re-rendering of all <code>UIArea</code>s wasn't really used in the past and * did not provide a meaningful feature. It therefore has been abandoned. */ Core.prototype.lock = function () { this.bLocked = true; UIArea.registry.forEach((oUiArea) => { oUiArea.lock(); }); }; /** * Unlocks the Core. * * Browser events are dispatched to the controls again after this method is called. * @public * @deprecated As of version 1.118, without a replacement. The ability to prevent * the re-rendering of all <code>UIArea</code>s wasn't really used in the past and * did not provide a meaningful feature. It therefore has been abandoned. */ Core.prototype.unlock = function () { this.bLocked = false; UIArea.registry.forEach((oUiArea) => { oUiArea.unlock(); }); }; /** * Returns the locked state of the <code>sap.ui.core.Core</code>. * * @return {boolean} locked state * @public * @deprecated As of version 1.118, without a replacement. The ability to prevent * the re-rendering of all <