@openui5/sap.ui.core
Version:
OpenUI5 Core Library sap.ui.core
1,548 lines (1,386 loc) • 130 kB
JavaScript
/*!
* 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 <