UNPKG

@openui5/sap.ui.core

Version:

OpenUI5 Core Library sap.ui.core

1,294 lines (1,171 loc) 40 kB
/*! * OpenUI5 * (c) Copyright 2026 SAP SE or an SAP affiliate company. * Licensed under the Apache License, Version 2.0 - see LICENSE.txt. */ /* * IMPORTANT: This is a private module, its API must not be used and is subject to change. * Code other than the OpenUI5 libraries must not introduce dependencies to this module. */ (function() { /* * This module tries to detect a bootstrap script tag in the current page and * to derive the path for 'resources/' from it. For that purpose it checks for a * hard coded set of well-known bootstrap script names: * - sap-ui-custom(-suffix)?.js * - sap-ui-core(-suffix)?.js * - jquery.sap.global.js * - ui5loader-autoconfig.js */ /*global define */ "use strict"; /** BaseConfiguration */ var ui5loader = globalThis.sap && globalThis.sap.ui && globalThis.sap.ui.loader; if (ui5loader == null) { throw new Error("ui5loader-autoconfig.js: ui5loader is needed, but could not be found"); } const origDefine = globalThis.define; globalThis.define = function define(moduleId, dependencies, callback) { const imports = dependencies.map((dep) => sap.ui.require(dep)); const moduleExport = callback(...imports); ui5loader._.defineModuleSync(`${moduleId}.js`, moduleExport); }; define("sap/base/strings/_camelize", [], function () { var rCamelCase = /[-\.]([a-z0-9])/ig; var fnCamelize = function (sString) { var sNormalizedString = sString.replace( rCamelCase, function( sMatch, sChar ) { return sChar.toUpperCase(); }); if (/^[a-z][A-Za-z0-9]*$/.test(sNormalizedString)) { return sNormalizedString; } return undefined; }; return fnCamelize; }); /* helper for finding the bootstrap tag */ function getBootstrapTag() { var oResult; function check(oScript, rUrlPattern) { var sUrl = oScript && oScript.getAttribute("src"); var oMatch = rUrlPattern.exec(sUrl); var oTagInfo; if (oMatch) { oTagInfo = { tag: oScript, url: sUrl, resourceRoot: oMatch[1] || "" }; } return oTagInfo; } if (globalThis.document) { var rResources = /^((?:.*\/)?resources\/)/, rBootScripts, aScripts, i; // Prefer script tags which have the sap-ui-bootstrap ID // This prevents issues when multiple script tags point to files named // "sap-ui-core.js", for example when using the cache buster for UI5 resources oResult = check(globalThis.document.querySelector('SCRIPT[src][id=sap-ui-bootstrap]'), rResources); if (!oResult) { aScripts = globalThis.document.querySelectorAll('SCRIPT[src]'); rBootScripts = /^([^?#]*\/)?(?:sap-ui-(?:core|custom|boot|merged)(?:-[^?#/]*)?|jquery.sap.global|ui5loader(?:-autoconfig)?)\.js(?:[?#]|$)/; for (i = 0; i < aScripts.length; i++) { oResult = check(aScripts[i], rBootScripts); if (oResult) { break; } } } } return oResult || {}; } /** * @deprecated As of Version 1.120 */ function _createGlobalConfig() { var sCfgFile = "sap-ui-config.json", url = globalThis["sap-ui-config"]; if (typeof url === "string") { if (globalThis.XMLHttpRequest) { ui5loader._.logger.warning("Loading external bootstrap configuration from \"" + url + "\". This is a design time feature and not for productive usage!"); if (url !== sCfgFile) { ui5loader._.logger.warning("The external bootstrap configuration file should be named \"" + sCfgFile + "\"!"); } try { var xhr = new XMLHttpRequest(); xhr.open("GET", url, false); xhr.setRequestHeader("Accept", "application/json, text/javascript"); xhr.addEventListener("load", function() { try { if (xhr.responseType === "json") { globalThis["sap-ui-config"] = xhr.response; } else { globalThis["sap-ui-config"] = JSON.parse(xhr.responseText); } } catch (error) { ui5loader._.logger.error("Parsing externalized bootstrap configuration from \"" + url + "\" failed! Reason: " + error + "!"); } }); xhr.addEventListener("error", function() { ui5loader._.logger.error("Loading externalized bootstrap configuration from \"" + url + "\" failed! Response: " + xhr.status + "!"); }); xhr.send(null); globalThis["sap-ui-config"].__loaded = true; } catch (error) { ui5loader._.logger.error("Loading externalized bootstrap configuration from \"" + url + "\" failed! Reason: " + error + "!"); } } } var bootstrap = getBootstrapTag(); if (bootstrap.tag) { var dataset = bootstrap.tag.dataset; if (dataset["sapUiConfig"]) { var sConfig = dataset["sapUiConfig"]; var oParsedConfig; try { oParsedConfig = JSON.parse("{" + sConfig + "}"); } catch (exc) { ui5loader._.logger.error("JSON.parse on the data-sap-ui-config attribute failed. Please check the config for JSON syntax violations."); /*eslint-disable no-new-func */ oParsedConfig = (new Function("return {" + sConfig + "};"))(); /*eslint-enable no-new-func */ } if (oParsedConfig) { if (!globalThis["sap-ui-config"]) { globalThis["sap-ui-config"] = {}; } Object.assign(globalThis["sap-ui-config"], oParsedConfig); } } } } /** * @deprecated As of Version 1.120 */ _createGlobalConfig(); define("sap/base/config/GlobalConfigurationProvider", [ "sap/base/strings/_camelize" ], function (camelize) { var oConfig; var oWriteableConfig = Object.create(null); var rAlias = /^(sapUiXx|sapUi|sap)((?:[A-Z0-9][a-z]*)+)$/; //for getter var mFrozenProperties = Object.create(null); const multipleParams = new Map(); var bFrozen = false; var Configuration; function createConfig() { oConfig = Object.create(null); globalThis["sap-ui-config"] ??= {}; var mOriginalGlobalParams = {}; var oGlobalConfig = globalThis["sap-ui-config"]; if (typeof oGlobalConfig === "object") { for (var sKey in oGlobalConfig) { var sNormalizedKey = camelize("sapUi-" + sKey); var vFrozenValue = mFrozenProperties[sNormalizedKey]; if (!sNormalizedKey) { ui5loader._.logger.error("Invalid configuration option '" + sKey + "' in global['sap-ui-config']!"); } else if (Object.hasOwn(oConfig, sNormalizedKey)) { multipleParams.set(sNormalizedKey, mOriginalGlobalParams[sNormalizedKey]); } else if (Object.hasOwn(mFrozenProperties, sNormalizedKey) && oGlobalConfig[sKey] !== vFrozenValue) { oConfig[sNormalizedKey] = vFrozenValue; ui5loader._.logger.error("Configuration option '" + sNormalizedKey + "' was frozen and cannot be changed to " + oGlobalConfig[sKey] + "!"); } else { oConfig[sNormalizedKey] = oGlobalConfig[sKey]; mOriginalGlobalParams[sNormalizedKey] = sKey; } } } mOriginalGlobalParams = undefined; } function freeze() { if (!bFrozen) { createConfig(); Configuration._.invalidate(); bFrozen = true; } } function get(sKey, bFreeze) { var vValue = oWriteableConfig[sKey] || oConfig[sKey]; if (multipleParams.has(sKey)) { ui5loader._.logger.error("Configuration option '" + multipleParams.get(sKey) + "' was set multiple times. Value '" + vValue + "' will be used"); multipleParams.delete(sKey); } if (Object.hasOwn(mFrozenProperties,sKey)) { return mFrozenProperties[sKey]; } if (!Object.hasOwn(oConfig, sKey) && !Object.hasOwn(oWriteableConfig, sKey)) { var vMatch = sKey.match(rAlias); var sLowerCaseAlias = vMatch ? vMatch[1] + vMatch[2][0] + vMatch[2].slice(1).toLowerCase() : undefined; if (sLowerCaseAlias) { vValue = oWriteableConfig[sLowerCaseAlias] || oConfig[sLowerCaseAlias]; if (vValue) { ui5loader._.logger.warning(`Deprecated configuration option '${sLowerCaseAlias.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()}' given in global configuration. Please use '${sKey.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase()}' instead.`); } } } if (bFreeze) { mFrozenProperties[sKey] = vValue; } return vValue; } function set(sKey, vValue) { if (Object.hasOwn(mFrozenProperties, sKey) || bFrozen) { ui5loader._.logger.error("Configuration option '" + sKey + "' was frozen and cannot be changed to " + vValue + "!"); } else { oWriteableConfig[sKey] = vValue; } } function setConfiguration(Config) { Configuration = Config; } var GlobalConfigurationProvider = { get: get, set: set, freeze: freeze, setConfiguration: setConfiguration, /** * @deprecated As of Version 1.120 */ _: { configLoaded() { return !!globalThis["sap-ui-config"].__loaded; } } }; createConfig(); return GlobalConfigurationProvider; }); define("sap/ui/core/config/BootstrapConfigurationProvider", [ "sap/base/strings/_camelize" ], function(camelize) { var oConfig = Object.create(null); var rAlias = /^(sapUiXx|sapUi|sap)((?:[A-Z0-9][a-z]*)+)$/; //for getter const multipleParams = new Map(); var bootstrap = getBootstrapTag(); if (bootstrap.tag) { var dataset = bootstrap.tag.dataset; if (dataset) { for (var sKey in dataset) { var sNormalizedKey = camelize(sKey); if (!sNormalizedKey) { ui5loader._.logger.error("Invalid configuration option '" + sKey + "' in bootstrap!"); } else if (Object.hasOwn(oConfig, sNormalizedKey)) { multipleParams.set(sNormalizedKey, sKey); } else { oConfig[sNormalizedKey] = dataset[sKey]; } } } } function get(sKey) { var vValue = oConfig[sKey]; if (multipleParams.has(sKey)) { ui5loader._.logger.error("Configuration option '" + multipleParams.get(sKey) + "' was set multiple times. Value '" + vValue + "' will be used"); multipleParams.delete(sKey); } if (vValue === undefined) { var vMatch = sKey.match(rAlias); var sLowerCaseAlias = vMatch ? vMatch[1] + vMatch[2][0] + vMatch[2].slice(1).toLowerCase() : undefined; if (sLowerCaseAlias) { vValue = oConfig[sLowerCaseAlias]; if (vValue) { ui5loader._.logger.warning(`Deprecated configuration option '${sLowerCaseAlias.replace(/([a-z0-9])([A-Z])/g, '$1-$2').replace(/([A-Z])([A-Z][a-z])/g, '$1-$2').toLowerCase()}' given in bootstrap configuration. Please use '${sKey.replace(/([a-z0-9])([A-Z])/g, '$1-$2').replace(/([A-Z])([A-Z][a-z])/g, '$1-$2').toLowerCase()}' instead.`); } } } return vValue; } var BootstrapConfigurationProvider = { get: get }; return BootstrapConfigurationProvider; }); define("sap/ui/base/config/URLConfigurationProvider", [ "sap/base/strings/_camelize" ], function(camelize) { var oConfig = Object.create(null); const multipleParams = new Map(); if (globalThis.location) { oConfig = Object.create(null); var mOriginalUrlParams = {}; var sLocation = globalThis.location.search; var urlParams = new URLSearchParams(sLocation); urlParams.forEach(function(value, key) { const bSapParam = /sap\-?([Uu]?i\-?)?/.test(key); var sNormalizedKey = camelize(key); if (sNormalizedKey) { if (Object.hasOwn(oConfig, sNormalizedKey)) { multipleParams.set(sNormalizedKey, mOriginalUrlParams[sNormalizedKey]); } else { oConfig[sNormalizedKey] = value; mOriginalUrlParams[sNormalizedKey] = key; } } else if (bSapParam) { ui5loader._.logger.error("Invalid configuration option '" + key + "' in url!"); } }); mOriginalUrlParams = undefined; } function get(sKey) { if (multipleParams.has(sKey)) { ui5loader._.logger.error("Configuration option '" + multipleParams.get(sKey) + "' was set multiple times. Value '" + oConfig[sKey] + "' will be used"); multipleParams.delete(sKey); } return oConfig[sKey]; } var URLConfigurationProvider = { external: true, get: get }; return URLConfigurationProvider; }); define("sap/ui/base/config/MetaConfigurationProvider", [ "sap/base/strings/_camelize" ], function (camelize) { var oConfig = Object.create(null); const multipleParams = new Map(); if (globalThis.document) { oConfig = Object.create(null); var mOriginalTagNames = {}; var allMetaTags = globalThis.document.querySelectorAll("meta"); allMetaTags.forEach(function(tag) { var sNormalizedKey = camelize(tag.name); const bSapParam = /sap\-?([Uu]?i\-?)?/.test(tag.name); if (sNormalizedKey) { if (Object.hasOwn(oConfig, sNormalizedKey)) { multipleParams.set(sNormalizedKey, mOriginalTagNames[sNormalizedKey]); } else { oConfig[sNormalizedKey] = tag.content; mOriginalTagNames[sNormalizedKey] = tag.name; } } else if (tag.name && bSapParam) { // tags without explicit name (tag.name === "") are ignored silently ui5loader._.logger.error("Invalid configuration option '" + tag.name + "' in meta tag!"); } }); mOriginalTagNames = undefined; } function get(sKey) { if (multipleParams.has(sKey)) { ui5loader._.logger.error("Configuration option '" + multipleParams.get(sKey) + "' was set multiple times. Value '" + oConfig[sKey] + "' will be used"); multipleParams.delete(sKey); } return oConfig[sKey]; } var MetaConfigurationProvider = { get: get }; return MetaConfigurationProvider; }); define("sap/base/config/_Configuration", [ "sap/base/config/GlobalConfigurationProvider" ], function _Configuration(GlobalConfigurationProvider) { var rValidKey = /^[a-z][A-Za-z0-9]*$/; var rXXAlias = /^(sapUi(?!Xx))(.*)$/; var mCache = Object.create(null); var aProvider = [GlobalConfigurationProvider]; var mUrlParamOptions = { name: "sapUiIgnoreUrlParams", type: "boolean" }; var mInternalDefaultValues = { "boolean": false, "code": undefined, "integer": 0, "string": "", "string[]": [], "function[]": [], "function": undefined, "object": {}, "mergedObject": {} }; /** * Enum for available types of configuration entries. * * @enum {string} * @alias module:sap/base/config.Type * @private * @ui5-restricted sap.ui.core, sap.ui.fl, sap.ui.integration, sap.ui.export */ var TypeEnum = { /** * defaultValue: false * @private * @ui5-restricted sap.ui.core, sap.ui.fl, sap.ui.integration, sap.ui.export */ "Boolean": "boolean", /** * defaultValue: undefined * @private * @ui5-restricted sap.ui.core, sap.ui.fl, sap.ui.integration, sap.ui.export * @deprecated As of Version 1.120, without replacement as code execution with eval() is not supported anymore due to CSP compliance */ "Code": "code", /** * defaultValue: 0 * @private * @ui5-restricted sap.ui.core, sap.ui.fl, sap.ui.integration, sap.ui.export */ "Integer": "integer", /** * defaultValue: "" * @private * @ui5-restricted sap.ui.core, sap.ui.fl, sap.ui.integration, sap.ui.export */ "String": "string", /** * defaultValue: [] * @private * @ui5-restricted sap.ui.core, sap.ui.fl, sap.ui.integration, sap.ui.export */ "StringArray": "string[]", /** * defaultValue: [] * @private * @ui5-restricted sap.ui.core, sap.ui.fl, sap.ui.integration, sap.ui.export */ "FunctionArray": "function[]", /** * defaultValue: undefined * @private * @ui5-restricted sap.ui.core, sap.ui.fl, sap.ui.integration, sap.ui.export */ "Function": "function", /** * defaultValue: {} * @private * @ui5-restricted sap.ui.core, sap.ui.fl, sap.ui.integration, sap.ui.export */ "Object": "object", /** * defaultValue: {} * @private * @ui5-restricted sap.ui.core, sap.ui.fl, sap.ui.integration, sap.ui.export */ "MergedObject": "mergedObject" }; var bGlobalIgnoreExternal = get(mUrlParamOptions); function deepClone(src) { if (src == null) { return src; } else if (Array.isArray(src)) { return cloneArray(src); } else if (typeof src === "object") { return cloneObject(src); } else { return src; } } function cloneArray(src) { var aClone = []; for (var i = 0; i < src.length; i++) { aClone.push(deepClone(src[i])); } return aClone; } function cloneObject(src) { var oClone = {}; for (var key in src) { if (key === "__proto__") { continue; } oClone[key] = deepClone(src[key]); } return oClone; } function getCachedValue(sCacheKey, mOptions) { var vCachedValue = mCache[sCacheKey]; if (mOptions.type === TypeEnum.StringArray || mOptions.type === TypeEnum.Object || mOptions.type === TypeEnum.MergedObject) { vCachedValue = deepClone(vCachedValue); } return vCachedValue; } /** Register a new Configuration provider * * @name module:sap/base/config.registerProvider * @function * @param {object} oProvider The provider instance * @private * @ui5-restricted sap.ui.core */ function registerProvider(oProvider) { if (aProvider.indexOf(oProvider) === -1) { aProvider.push(oProvider); Configuration._.invalidate(); bGlobalIgnoreExternal = get(mUrlParamOptions); } } /** * Converts a given value to the given type. * * @name module:sap/base/config.convertToType * @function * @param {any} vValue The value to be converted * @param {string} vType The resulting type * @param {string} [sName] The property name of the enumeration to check * @returns {any} The converted value * @throws {TypeError} Throws an TypeError if the given value could not be converted to the requested type * * @private */ function convertToType(vValue, vType, sName) { if (vValue === undefined || vValue === null) { return vValue; } if (typeof vType === "string") { switch (vType) { case TypeEnum.Boolean: if (typeof vValue === "string") { return vValue.toLowerCase() === "true" || vValue.toLowerCase() === "x"; } else { vValue = !!vValue; } break; /** * @deprecated As of Version 1.120 */ case TypeEnum.Code: vValue = typeof vValue === "function" ? vValue : String(vValue); break; case TypeEnum.Integer: if (typeof vValue === "string") { vValue = parseInt(vValue); } if (typeof vValue !== 'number' && isNaN(vValue)) { throw new TypeError("unsupported value"); } break; case TypeEnum.String: vValue = '' + vValue; // enforce string break; case TypeEnum.StringArray: if (Array.isArray(vValue)) { return vValue; } else if (typeof vValue === "string") { // enforce array vValue = vValue ? vValue.split(/[,;]/).map(function(s) { return s.trim(); }) : []; return vValue; } else { throw new TypeError("unsupported value"); } case TypeEnum.FunctionArray: vValue.forEach(function(fnFunction) { if ( typeof fnFunction !== "function" ) { throw new TypeError("Not a function: " + fnFunction); } }); break; case TypeEnum.Function: if (typeof vValue !== "function") { throw new TypeError("unsupported value"); } break; case TypeEnum.Object: case TypeEnum.MergedObject: if (typeof vValue === "string") { vValue = JSON.parse(vValue); } if (typeof vValue !== "object") { throw new TypeError("unsupported value"); } break; default: throw new TypeError("unsupported type"); } } else if (typeof vType === "object" && !Array.isArray(vType)) { vValue = checkEnum(vType, vValue, sName); } else if (typeof vType === "function") { vValue = vType(vValue); } else { throw new TypeError("unsupported type"); } return vValue; } /** * Checks if a value exists within an enumerable list. * * @name module:sap/base/config._.checkEnum * @function * @param {object} oEnum Enumeration object with values for validation * @param {string} sValue Value to check against enumerable list * @param {string} sPropertyName Name of the property which is checked * @returns {string} Value passed to the function for check * @throws {TypeError} If the value could not be found, an TypeError is thrown * * @private */ function checkEnum(oEnum, sValue, sPropertyName) { var aValidValues = []; for (var sKey in oEnum) { if (oEnum.hasOwnProperty(sKey)) { if (oEnum[sKey] === sValue) { return sValue; } aValidValues.push(oEnum[sKey]); } } throw new TypeError("Unsupported Enumeration value for " + sPropertyName + ", valid values are: " + aValidValues.join(", ")); } /** * Generic getter for configuration options that are not explicitly exposed via a dedicated own getter. * * @name module:sap/base/config.get * @function * @param {object} mOptions The options object that contains the following properties * @param {string} mOptions.name Name of the configuration parameter. Must start with 'sapUi/sapUiXx' prefix followed by letters only. The name must be camel-case * @param {module:sap/base/config.Type|object<string, string>|function} mOptions.type Type of the configuration parameter. This argument can be a <code>module:sap/base/config.Type</code>, object or function. * @param {any} [mOptions.defaultValue=undefined] Default value of the configuration parameter corresponding to the given type or a function returning the default value. * @param {boolean} [mOptions.external=false] Whether external (e.g. url-) parameters should be included or not * @param {boolean} [mOptions.freeze=false] Freezes parameter and parameter can't be changed afterwards. * @returns {any} Value of the configuration parameter * @throws {TypeError} Throws an error if the given parameter name does not match the definition. * @private * @ui5-restricted sap.ui.core, sap.ui.fl, sap.ui.integration, sap.ui.export */ function get(mOptions) { var sCacheKey = mOptions.name; if (mOptions.provider) { sCacheKey += "-" + mOptions.provider.getId(); } if (sCacheKey in mCache) { return getCachedValue(sCacheKey, mOptions); } if (typeof mOptions.name !== "string" || !rValidKey.test(mOptions.name)) { throw new TypeError( "Invalid configuration key '" + mOptions.name + "'!" ); } mOptions = Object.assign({}, mOptions); var vValue; var bIgnoreExternal = bGlobalIgnoreExternal || !mOptions.external; var sName = mOptions.name; var vMatch = sName.match(rXXAlias); var vDefaultValue = mOptions.hasOwnProperty("defaultValue") ? mOptions.defaultValue : mInternalDefaultValues[mOptions.type]; const aAllProvider = [...aProvider, ...(mOptions.provider ? [mOptions.provider] : [])]; for (var i = aAllProvider.length - 1; i >= 0; i--) { if (!aAllProvider[i].external || !bIgnoreExternal) { const vProviderValue = convertToType(aAllProvider[i].get(sName, mOptions.freeze), mOptions.type, mOptions.name); if (vProviderValue !== undefined) { if (mOptions.type === TypeEnum.MergedObject) { vValue = Object.assign({}, vProviderValue, vValue); } else { vValue = vProviderValue; break; } } } } if (vValue === undefined && (vMatch && vMatch[1] === "sapUi")) { mOptions.name = vMatch[1] + "Xx" + vMatch[2]; vValue = get(mOptions); } if (vValue === undefined) { if (typeof vDefaultValue === 'function') { vDefaultValue = vDefaultValue(); } vValue = vDefaultValue; } mCache[sCacheKey] = vValue; return getCachedValue(sCacheKey, mOptions); } function invalidate() { mCache = Object.create(null); } var Configuration = { get: get, registerProvider: registerProvider, Type: TypeEnum, _: { checkEnum: checkEnum, invalidate: invalidate } }; //forward Configuration to Global provider to invalidate the cache when freezing GlobalConfigurationProvider.setConfiguration(Configuration); return Configuration; }); globalThis.define = origDefine; function _setupConfiguration() { var BaseConfiguration = sap.ui.require('sap/base/config/_Configuration'); //register config provider BaseConfiguration.registerProvider(sap.ui.require("sap/ui/core/config/BootstrapConfigurationProvider")); BaseConfiguration.registerProvider(sap.ui.require("sap/ui/base/config/MetaConfigurationProvider")); BaseConfiguration.registerProvider(sap.ui.require("sap/ui/base/config/URLConfigurationProvider")); } /** init configuration */ _setupConfiguration(); var BaseConfig = sap.ui.require("sap/base/config/_Configuration"); /** autoconfig */ var sBaseUrl, bNojQuery, aScripts, rBootScripts, i, sBootstrapUrl; function findBaseUrl(oScript, rUrlPattern) { var sUrl = oScript && oScript.getAttribute("src"), oMatch = rUrlPattern.exec(sUrl); if ( oMatch ) { sBaseUrl = oMatch[1] || ""; sBootstrapUrl = sUrl; bNojQuery = /sap-ui-core-nojQuery\.js(?:[?#]|$)/.test(sUrl); return true; } return false; } function ensureSlash(path) { return path && path[path.length - 1] !== '/' ? path + '/' : path; } // Prefer script tags which have the sap-ui-bootstrap ID // This prevents issues when multiple script tags point to files named // "sap-ui-core.js", for example when using the cache buster for UI5 resources if ( !findBaseUrl(document.querySelector('SCRIPT[src][id=sap-ui-bootstrap]'), /^((?:[^?#]*\/)?resources\/)/ ) ) { // only when there's no such script tag, check all script tags rBootScripts = /^([^?#]*\/)?(?:sap-ui-(?:core|custom|boot|merged)(?:-[^?#/]*)?|jquery.sap.global|ui5loader(?:-autoconfig)?)\.js(?:[?#]|$)/; aScripts = document.scripts; for ( i = 0; i < aScripts.length; i++ ) { if ( findBaseUrl(aScripts[i], rBootScripts) ) { break; } } } // configuration via window['sap-ui-config'] always overrides an auto detected base URL var mResourceRoots = BaseConfig.get({ name: "sapUiResourceRoots", type: BaseConfig.Type.MergedObject }); if (typeof mResourceRoots[''] === 'string' ) { sBaseUrl = mResourceRoots['']; } if (sBaseUrl == null) { throw new Error("ui5loader-autoconfig.js: could not determine base URL. No known script tag and no configuration found!"); } /** * Determine whether a bootstrap reboot URL is set to reboot UI5 from a different URL */ (function() { var sRebootUrl; try { // Necessary for FF when Cookies are disabled sRebootUrl = window.localStorage.getItem("sap-ui-reboot-URL"); } catch (e) { /* no warning, as this will happen on every startup, depending on browser settings */ } /* * Determine whether sap-bootstrap-debug is set, run debugger statement * to allow early debugging in browsers with broken dev tools */ var bDebugBootstrap = BaseConfig.get({ name: "sapBootstrapDebug", type: BaseConfig.Type.Boolean, external: true, freeze: true }); if (bDebugBootstrap) { /*eslint-disable no-debugger */ debugger; /*eslint-enable no-debugger */ } if (sRebootUrl) { var sDebugRebootPath = ensureSlash(sBaseUrl) + 'sap/ui/core/support/debugReboot.js'; // This won't work in case this script is loaded async (e.g. dynamic script tag) document.write("<script src=\"" + sDebugRebootPath + "\"></script>"); var oRestart = new Error("This is not a real error. Aborting UI5 bootstrap and rebooting from: " + sRebootUrl); oRestart.name = "Restart"; throw oRestart; } })(); /** * Determine whether to use debug sources depending on URL parameter, local storage * and script tag attribute. * If full debug mode is required, restart with a debug version of the bootstrap. */ (function() { // check URI param var vDebugInfo = BaseConfig.get({ name: "sapUiDebug", type: BaseConfig.Type.String, defaultValue: false, external: true, freeze: true }); // check local storage try { vDebugInfo = vDebugInfo || window.localStorage.getItem("sap-ui-debug"); } catch (e) { // access to localStorage might be disallowed } // normalize vDebugInfo; afterwards, it either is a boolean or a string not representing a boolean if ( typeof vDebugInfo === 'string' ) { if ( /^(?:false|true|x|X)$/.test(vDebugInfo) ) { vDebugInfo = vDebugInfo !== 'false'; } } else { vDebugInfo = !!vDebugInfo; } // if bootstrap URL explicitly refers to a debug source, generally use debug sources if ( /-dbg\.js([?#]|$)/.test(sBootstrapUrl) ) { window['sap-ui-loaddbg'] = true; vDebugInfo = vDebugInfo || true; } // export resulting debug mode under legacy property window["sap-ui-debug"] = vDebugInfo; // check for optimized sources by testing variable names in a local function // (check for native API ".getAttribute" to make sure that the function's source can be retrieved) window["sap-ui-optimized"] = window["sap-ui-optimized"] || (/\.getAttribute/.test(findBaseUrl) && !/oScript/.test(findBaseUrl)); if ( window["sap-ui-optimized"] && vDebugInfo ) { // if current sources are optimized and any debug sources should be used, enable the "-dbg" suffix window['sap-ui-loaddbg'] = true; // if debug sources should be used in general, restart with debug URL (if not disabled, e.g. by test runner) if ( vDebugInfo === true && !window["sap-ui-debug-no-reboot"] ) { var sDebugUrl; if ( sBootstrapUrl != null ) { sDebugUrl = sBootstrapUrl.replace(/\/(?:sap-ui-cachebuster\/)?([^\/]+)\.js/, "/$1-dbg.js"); } else { // when no boot script could be identified, we can't derive the name of the // debug boot script from it, so fall back to a default debug boot script sDebugUrl = ensureSlash(sBaseUrl) + 'sap-ui-core.js'; } // revert changes to global names ui5loader.config({ amd:false }); window["sap-ui-optimized"] = false; if (ui5loader.config().async) { var script = document.createElement("script"); script.src = sDebugUrl; document.head.appendChild(script); } else { document.write("<script src=\"" + sDebugUrl + "\"></script>"); } var oRestart = new Error("This is not a real error. Aborting UI5 bootstrap and restarting from: " + sDebugUrl); oRestart.name = "Restart"; throw oRestart; } } function makeRegExp(sGlobPattern) { if (!/\/\*\*\/$/.test(sGlobPattern)) { sGlobPattern = sGlobPattern.replace(/\/$/, '/**/'); } return sGlobPattern.replace(/\*\*\/|\*|[[\]{}()+?.\\^$|]/g, function(sMatch) { switch (sMatch) { case '**/': return '(?:[^/]+/)*'; case '*': return '[^/]*'; default: return '\\' + sMatch; } }); } var fnIgnorePreload; if (typeof vDebugInfo === 'string') { var sPattern = "^(?:" + vDebugInfo.split(/,/).map(makeRegExp).join("|") + ")", rFilter = new RegExp(sPattern); fnIgnorePreload = function(sModuleName) { return rFilter.test(sModuleName); }; ui5loader._.logger.debug("Modules that should be excluded from preload: '" + sPattern + "'"); } else if (vDebugInfo === true) { fnIgnorePreload = function() { return true; }; ui5loader._.logger.debug("All modules should be excluded from preload"); } ui5loader.config({ debugSources: !!window['sap-ui-loaddbg'], ignoreBundledResources: fnIgnorePreload }); })(); const bFuture = BaseConfig.get({ name: "sapUiXxFuture", type: BaseConfig.Type.Boolean, external: true, freeze: true }); /** * Evaluate legacy configuration. * @deprecated As of version 1.120 */ (() => { // xx-future implicitly sets the loader to async const bAsync = BaseConfig.get({ name: "sapUiAsync", type: BaseConfig.Type.Boolean, external: true, freeze: true }) || bFuture; if (bAsync) { ui5loader.config({ async: true }); } })(); // Note: loader converts any NaN value to a default value ui5loader._.maxTaskDuration = BaseConfig.get({ name: "sapUiXxMaxLoaderTaskDuration", type: BaseConfig.Type.Integer, defaultValue: undefined, external: true, freeze: true }); // support legacy switch 'noLoaderConflict', but 'amdLoader' has higher precedence const bExposeAsAMDLoader = BaseConfig.get({ name: "sapUiAmd", type: BaseConfig.Type.Boolean, defaultValue: !BaseConfig.get({ name: "sapUiNoLoaderConflict", type: BaseConfig.Type.Boolean, defaultValue: true, external: true, freeze: true }), external: true, freeze: true }); // calculate syncCallBehavior let syncCallBehavior = 0; // ignore let sNoSync = BaseConfig.get({ // call must be made to ensure freezing name: "sapUiXxNoSync", type: BaseConfig.Type.String, external: true, freeze: true }); // sap-ui-xx-future enforces strict sync call behavior sNoSync = bFuture ? "x" : sNoSync; if (sNoSync === 'warn') { syncCallBehavior = 1; } else if (/^(true|x)$/i.test(sNoSync)) { syncCallBehavior = 2; } /** * @deprecated As of version 1.120 */ (() => { const GlobalConfigurationProvider = sap.ui.require("sap/base/config/GlobalConfigurationProvider"); if ( syncCallBehavior && GlobalConfigurationProvider._.configLoaded()) { const sMessage = "[nosync]: configuration loaded via sync XHR"; if (syncCallBehavior === 1) { ui5loader._.logger.warning(sMessage); } else { ui5loader._.logger.error(sMessage); } } })(); ui5loader.config({ baseUrl: sBaseUrl, amd: bExposeAsAMDLoader, map: { "*": { 'blanket': 'sap/ui/thirdparty/blanket', 'crossroads': 'sap/ui/thirdparty/crossroads', 'd3': 'sap/ui/thirdparty/d3', 'handlebars': 'sap/ui/thirdparty/handlebars', 'hasher': 'sap/ui/thirdparty/hasher', 'IPv6': 'sap/ui/thirdparty/IPv6', 'jquery': 'sap/ui/thirdparty/jquery', 'jszip': 'sap/ui/thirdparty/jszip', 'less': 'sap/ui/thirdparty/less', 'OData': 'sap/ui/thirdparty/datajs', 'punycode': 'sap/ui/thirdparty/punycode', 'SecondLevelDomains': 'sap/ui/thirdparty/SecondLevelDomains', 'sinon': 'sap/ui/thirdparty/sinon', 'signals': 'sap/ui/thirdparty/signals', 'URI': 'sap/ui/thirdparty/URI', 'URITemplate': 'sap/ui/thirdparty/URITemplate' } }, reportSyncCalls: syncCallBehavior, shim: { 'sap/ui/thirdparty/bignumber': { amd: true, exports: 'BigNumber' }, 'sap/ui/thirdparty/blanket': { amd: true, exports: 'blanket' // '_blanket', 'esprima', 'falafel', 'inBrowser', 'parseAndModify' }, 'sap/ui/thirdparty/caja-html-sanitizer': { amd: false, exports: 'html' // 'html_sanitizer', 'html4' }, 'sap/ui/thirdparty/crossroads': { amd: true, exports: 'crossroads', deps: ['sap/ui/thirdparty/signals'] }, 'sap/ui/thirdparty/d3': { amd: true, exports: 'd3' }, 'sap/ui/thirdparty/datajs': { amd: true, exports: 'OData' // 'datajs' }, 'sap/ui/thirdparty/handlebars': { amd: true, exports: 'Handlebars' }, 'sap/ui/thirdparty/hasher': { amd: true, exports: 'hasher', deps: ['sap/ui/thirdparty/signals'] }, 'sap/ui/thirdparty/IPv6': { amd: true, exports: 'IPv6' }, 'sap/ui/thirdparty/jquery': { amd: true, exports: 'jQuery', deps: ['sap/ui/thirdparty/jquery-compat'] }, 'sap/ui/thirdparty/jqueryui/jquery-ui-datepicker': { deps: ['sap/ui/thirdparty/jqueryui/jquery-ui-core'], exports: 'jQuery' }, 'sap/ui/thirdparty/jqueryui/jquery-ui-draggable': { deps: ['sap/ui/thirdparty/jqueryui/jquery-ui-mouse'], exports: 'jQuery' }, 'sap/ui/thirdparty/jqueryui/jquery-ui-droppable': { deps: ['sap/ui/thirdparty/jqueryui/jquery-ui-mouse', 'sap/ui/thirdparty/jqueryui/jquery-ui-draggable'], exports: 'jQuery' }, 'sap/ui/thirdparty/jqueryui/jquery-ui-effect': { deps: ['sap/ui/thirdparty/jquery'], exports: 'jQuery' }, 'sap/ui/thirdparty/jqueryui/jquery-ui-mouse': { deps: ['sap/ui/thirdparty/jqueryui/jquery-ui-core', 'sap/ui/thirdparty/jqueryui/jquery-ui-widget'], exports: 'jQuery' }, 'sap/ui/thirdparty/jqueryui/jquery-ui-position': { deps: ['sap/ui/thirdparty/jquery'], exports: 'jQuery' }, 'sap/ui/thirdparty/jqueryui/jquery-ui-resizable': { deps: ['sap/ui/thirdparty/jqueryui/jquery-ui-mouse'], exports: 'jQuery' }, 'sap/ui/thirdparty/jqueryui/jquery-ui-selectable': { deps: ['sap/ui/thirdparty/jqueryui/jquery-ui-mouse'], exports: 'jQuery' }, 'sap/ui/thirdparty/jqueryui/jquery-ui-sortable': { deps: ['sap/ui/thirdparty/jqueryui/jquery-ui-mouse'], exports: 'jQuery' }, 'sap/ui/thirdparty/jqueryui/jquery-ui-widget': { deps: ['sap/ui/thirdparty/jquery'], exports: 'jQuery' }, 'sap/ui/thirdparty/jquery-mobile-custom': { amd: true, deps: ['sap/ui/thirdparty/jquery', 'sap/ui/Device'], exports: 'jQuery.mobile' }, 'sap/ui/thirdparty/jszip': { amd: true, exports: 'JSZip' }, 'sap/ui/thirdparty/less': { amd: true, exports: 'less' }, 'sap/ui/thirdparty/qunit-2': { amd: false, exports: 'QUnit' }, 'sap/ui/thirdparty/punycode': { amd: true, exports: 'punycode' }, 'sap/ui/thirdparty/RequestRecorder': { amd: true, exports: 'RequestRecorder', deps: ['sap/ui/thirdparty/URI', 'sap/ui/thirdparty/sinon'] }, 'sap/ui/thirdparty/require': { exports: 'define' // 'require', 'requirejs' }, 'sap/ui/thirdparty/SecondLevelDomains': { amd: true, exports: 'SecondLevelDomains' }, 'sap/ui/thirdparty/signals': { amd: true, exports: 'signals' }, 'sap/ui/thirdparty/sinon': { amd: true, exports: 'sinon' }, 'sap/ui/thirdparty/sinon-4': { amd: true, exports: 'sinon' }, 'sap/ui/thirdparty/sinon-server': { amd: true, exports: 'sinon' // really sinon! sinon-server is a subset of server and uses the same global for export }, 'sap/ui/thirdparty/URI': { amd: true, exports: 'URI' }, 'sap/ui/thirdparty/URITemplate': { amd: true, exports: 'URITemplate', deps: ['sap/ui/thirdparty/URI'] }, 'sap/ui/thirdparty/vkbeautify': { amd: false, exports: 'vkbeautify' }, 'sap/ui/thirdparty/zyngascroll': { amd: false, exports: 'Scroller' // 'requestAnimationFrame', 'cancelRequestAnimationFrame', 'core' }, 'sap/viz/libs/canvg': { deps: ['sap/viz/libs/rgbcolor'] }, 'sap/viz/libs/rgbcolor': { }, 'sap/viz/libs/sap-viz': { deps: ['sap/viz/library', 'sap/ui/thirdparty/jquery', 'sap/ui/thirdparty/d3', 'sap/viz/libs/canvg'] }, 'sap/viz/libs/sap-viz-info-charts': { amd: true, deps: ['sap/viz/libs/sap-viz-info-framework'] }, 'sap/viz/libs/sap-viz-info-framework': { amd: true, deps: ['sap/ui/thirdparty/jquery', 'sap/ui/thirdparty/d3'] }, 'sap/viz/ui5/container/libs/sap-viz-controls-vizcontainer': { deps: ['sap/viz/libs/sap-viz', 'sap/viz/ui5/container/libs/common/libs/rgbcolor/rgbcolor_static'] }, 'sap/viz/ui5/controls/libs/sap-viz-vizframe/sap-viz-vizframe': { deps: ['sap/viz/libs/sap-viz-info-charts'] }, 'sap/viz/ui5/controls/libs/sap-viz-vizservices/sap-viz-vizservices': { deps: ['sap/viz/libs/sap-viz-info-charts'] }, 'sap/viz/resources/chart/templates/standard_fiori/template': { deps: ['sap/viz/libs/sap-viz-info-charts'] } } }); var defineModuleSync = ui5loader._.defineModuleSync; defineModuleSync('ui5loader.js', null); defineModuleSync('ui5loader-autoconfig.js', null); if (bNojQuery && typeof jQuery === 'function') { // when we're executed in the context of the sap-ui-core-noJQuery file, // we try to detect an existing jQuery / jQuery position plugin and register them as modules defineModuleSync('sap/ui/thirdparty/jquery.js', jQuery); if (jQuery.ui && jQuery.ui.position) { defineModuleSync('sap/ui/thirdparty/jqueryui/jquery-ui-position.js', jQuery); } } var sMainModule = BaseConfig.get({ name: "sapUiMain", type: BaseConfig.Type.String, freeze: true }); if ( sMainModule ) { sap.ui.require(sMainModule.trim().split(/\s*,\s*/)); } }());