@openui5/sap.ui.core
Version:
OpenUI5 Core Library sap.ui.core
1,292 lines (1,173 loc) • 91.4 kB
JavaScript
/*!
* OpenUI5
* (c) Copyright 2009-2021 SAP SE or an SAP affiliate company.
* Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
*/
/*global ActiveXObject, XMLHttpRequest, localStorage, alert, confirm, console, document, Promise */
/**
* Provides base functionality of the SAP jQuery plugin as extension of the jQuery framework.<br/>
* See also <a href="http://api.jquery.com/jQuery/">jQuery</a> for details.<br/>
* Although these functions appear as static ones, they are meant to be used on jQuery instances.<br/>
* If not stated differently, the functions follow the fluent interface paradigm and return the jQuery instance for chaining of statements.
*
* Example for usage of an instance method:
* <pre>
* var oRect = jQuery("#myDiv").rect();
* alert("Top Position: " + oRect.top);
* </pre>
*
* @namespace jQuery
* @public
*/
sap.ui.define([
// new sap/base/* modules
"sap/base/util/now", "sap/base/util/Version", "sap/base/assert", "sap/base/Log",
// new sap/ui/* modules
"sap/ui/dom/getComputedStyleFix", "sap/ui/dom/activeElementFix", "sap/ui/dom/includeScript",
"sap/ui/dom/includeStylesheet", "sap/ui/core/support/Hotkeys", "sap/ui/test/RecorderHotkeyListener",
"sap/ui/security/FrameOptions", "sap/ui/performance/Measurement", "sap/ui/performance/trace/Interaction",
"sap/ui/base/syncXHRFix", "sap/base/util/LoaderExtensions",
// former sap-ui-core.js dependencies
"sap/ui/Device",
"sap/ui/thirdparty/jquery",
"sap/ui/thirdparty/jqueryui/jquery-ui-position",
"ui5loader-autoconfig",
"jquery.sap.stubs",
"sap/ui/thirdparty/URI", // side effect: make global URI available
"sap/ui/events/PasteEventFix" // side effect: activates paste event fix
], function(now, Version, assert, Log,
getComputedStyleFix, activeElementFix, includeScript,
includeStylesheet, SupportHotkeys, TestRecorderHotkeyListener,
FrameOptions, Measurement, Interaction,
syncXHRFix, LoaderExtensions,
Device,
jQuery /*, jqueryUiPosition, ui5loaderAutoconfig, jquerySapStubs, URI, PasteEventFix */) {
"use strict";
if ( !jQuery ) {
throw new Error("Loading of jQuery failed");
}
var ui5loader = sap.ui.loader;
if ( !ui5loader || !ui5loader._ ) {
throw new Error("The UI5 compatilbility module requires a UI5 specific AMD implementation");
}
var _ui5loader = ui5loader._;
// early logging support
var _earlyLogs = [];
function _earlyLog(sLevel, sMessage) {
_earlyLogs.push({
level: sLevel,
message: sMessage
});
}
var oJQVersion = Version(jQuery.fn.jquery);
(function() {
/**
* Holds information about the browser's capabilities and quirks.
* This object is provided and documented by jQuery.
* But it is extended by SAPUI5 with detection for features not covered by jQuery. This documentation ONLY covers the detection properties added by UI5.
* For the standard detection properties, please refer to the jQuery documentation.
*
* These properties added by UI5 are only available temporarily until jQuery adds feature detection on their own.
*
* @name jQuery.support
* @namespace
* @private
* @deprecated since 1.58 use {@link sap.ui.Device} instead
*/
jQuery.support = jQuery.support || {};
/**
* Whether the device has a retina display (window.devicePixelRatio >= 2)
* @type {boolean}
* @public
* @deprecated since 1.58 use {@link sap.ui.Device.support.retina} instead
*/
jQuery.support.retina = Device.support.retina;
// this is also defined by jquery-mobile-custom.js, but this information is needed earlier
jQuery.support.touch = Device.support.touch;
/**
* Whether the current browser supports (2D) CSS transforms
* @type {boolean}
* @private
* @name jQuery.support.cssTransforms
*/
jQuery.support.cssTransforms = true;
/**
* Whether the current browser supports 3D CSS transforms
* @type {boolean}
* @private
* @name jQuery.support.cssTransforms3d
*/
jQuery.support.cssTransforms3d = true;
/**
* Whether the current browser supports CSS transitions
* @type {boolean}
* @private
* @name jQuery.support.cssTransitions
*/
jQuery.support.cssTransitions = true;
/**
* Whether the current browser supports (named) CSS animations
* @type {boolean}
* @private
* @name jQuery.support.cssAnimations
*/
jQuery.support.cssAnimations = true;
/**
* Whether the current browser supports CSS gradients. Note that ANY support for CSS gradients leads to "true" here, no matter what the syntax is.
* @type {boolean}
* @private
* @name jQuery.support.cssGradients
*/
jQuery.support.cssGradients = true;
/**
* Whether the current browser supports only prefixed flexible layout properties
* @type {boolean}
* @private
* @name jQuery.support.flexBoxPrefixed
*/
jQuery.support.flexBoxPrefixed = false;
/**
* Whether the current browser supports the OLD CSS3 Flexible Box Layout directly or via vendor prefixes
* @type {boolean}
* @private
* @name jQuery.support.flexBoxLayout
*/
jQuery.support.flexBoxLayout = false;
/**
* Whether the current browser supports the NEW CSS3 Flexible Box Layout directly or via vendor prefixes
* @type {boolean}
* @private
* @name jQuery.support.newFlexBoxLayout
*/
jQuery.support.newFlexBoxLayout = true;
/**
* Whether the current browser supports the IE10 CSS3 Flexible Box Layout directly or via vendor prefixes
* @type {boolean}
* @private
* @name jQuery.support.ie10FlexBoxLayout
*/
jQuery.support.ie10FlexBoxLayout = false;
/**
* Whether the current browser supports any kind of Flexible Box Layout directly or via vendor prefixes
* @type {boolean}
* @private
* @name jQuery.support.hasFlexBoxSupport
*/
jQuery.support.hasFlexBoxSupport = true;
}());
// XHR overrides for IE
if ( Device.browser.msie ) {
// Fixes the CORS issue (introduced by jQuery 1.7) when loading resources
// (e.g. SAPUI5 script) from other domains for IE browsers.
// The CORS check in jQuery filters out such browsers who do not have the
// property "withCredentials" which is the IE and Opera and prevents those
// browsers to request data from other domains with jQuery.ajax. The CORS
// requests are simply forbidden nevertheless if it works. In our case we
// simply load our script resources from another domain when using the CDN
// variant of SAPUI5. The following fix is also recommended by jQuery:
jQuery.support.cors = true;
// Fixes XHR factory issue (introduced by jQuery 1.11). In case of IE
// it uses by mistake the ActiveXObject XHR. In the list of XHR supported
// HTTP methods PATCH and MERGE are missing which are required for OData.
// The related ticket is: #2068 (no downported to jQuery 1.x planned)
// the fix will only be applied to jQuery >= 1.11.0 (only for jQuery 1.x)
if ( window.ActiveXObject !== undefined && oJQVersion.inRange("1.11", "2") ) {
var fnCreateStandardXHR = function() {
try {
return new XMLHttpRequest();
} catch (e) { /* ignore */ }
};
var fnCreateActiveXHR = function() {
try {
return new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) { /* ignore */ }
};
jQuery.ajaxSettings = jQuery.ajaxSettings || {};
jQuery.ajaxSettings.xhr = function() {
return !this.isLocal ? fnCreateStandardXHR() : fnCreateActiveXHR();
};
}
}
// getComputedStyle polyfill for firefox
if ( Device.browser.firefox ) {
getComputedStyleFix();
}
// document.activeElement iframe fix
if (Device.browser.msie || Device.browser.edge) {
activeElementFix();
}
// XHR proxy for Firefox
if ( Device.browser.firefox && window.Proxy ) {
syncXHRFix();
}
/*
* Merged, raw (un-interpreted) configuration data from the following sources
* (last one wins)
* <ol>
* <li>global configuration object <code>window["sap-ui-config"]</code> (could be either a string/url or a conffiguration object)</li>
* <li><code>data-sap-ui-config</code> attribute of the bootstrap script tag</li>
* <li>other <code>data-sap-ui-<i>xyz</i></code> attributes of the bootstrap tag</li>
* </ol>
*/
var oCfgData = window["sap-ui-config"] = (function() {
function normalize(o) {
for (var i in o) {
var v = o[i];
var il = i.toLowerCase();
if ( !o.hasOwnProperty(il) ) {
o[il] = v;
delete o[i];
}
}
return o;
}
function loadExternalConfig(url) {
var sCfgFile = "sap-ui-config.json",
config;
Log.warning("Loading external bootstrap configuration from \"" + url + "\". This is a design time feature and not for productive usage!");
if (url !== sCfgFile) {
Log.warning("The external bootstrap configuration file should be named \"" + sCfgFile + "\"!");
}
var xhr = new XMLHttpRequest();
xhr.addEventListener('load', function(e) {
if ( xhr.status === 200 && xhr.responseText ) {
try {
config = JSON.parse( xhr.responseText );
} catch (error) {
Log.error("Parsing externalized bootstrap configuration from \"" + url + "\" failed! Reason: " + error + "!");
}
} else {
Log.error("Loading externalized bootstrap configuration from \"" + url + "\" failed! Response: " + xhr.status + "!");
}
});
xhr.open('GET', url, false);
try {
xhr.send();
} catch (error) {
Log.error("Loading externalized bootstrap configuration from \"" + url + "\" failed! Reason: " + error + "!");
}
config = config || {};
config.__loaded = true; // mark config as 'being loaded', needed to detect sync call
return config;
}
function getInfo() {
function check(oScript, rUrlPattern) {
var sUrl = oScript && oScript.getAttribute("src");
var oMatch = rUrlPattern.exec(sUrl);
if ( oMatch ) {
return {
tag: oScript,
url: sUrl,
resourceRoot: oMatch[1] || ""
};
}
}
var rResources = /^((?:.*\/)?resources\/)/,
rBootScripts, aScripts, i, oResult;
// 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(document.querySelector('SCRIPT[src][id=sap-ui-bootstrap]'), rResources);
if ( !oResult ) {
aScripts = 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 || {};
}
var _oBootstrap = getInfo(),
oScriptTag = _oBootstrap.tag,
oCfg = window["sap-ui-config"];
// load the configuration from an external JSON file
if (typeof oCfg === "string") {
oCfg = loadExternalConfig(oCfg);
}
oCfg = normalize(oCfg || {});
oCfg.resourceroots = oCfg.resourceroots || {};
oCfg.themeroots = oCfg.themeroots || {};
// map loadall mode to sync preload mode
if ( /(^|\/)(sap-?ui5|[^\/]+-all).js([?#]|$)/.test(_oBootstrap.url) ) {
Log.error(
"The all-in-one file 'sap-ui-core-all.js' has been abandoned in favour of standard preloads." +
" Please migrate to sap-ui-core.js and consider to use async preloads.");
oCfg.preload = 'sync';
}
// if a script tag has been identified, collect its configuration info
if ( oScriptTag ) {
// evaluate the config attribute first - if present
var sConfig = oScriptTag.getAttribute("data-sap-ui-config");
if ( sConfig ) {
try {
var oParsedConfig;
try {
// first try to parse the config as a plain JSON
oParsedConfig = JSON.parse("{" + sConfig + "}");
} catch (e) {
// if the JSON.parse fails, we fall back to the more lenient "new Function" eval for compatibility reasons
Log.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 */
}
Object.assign(oCfg, normalize(oParsedConfig));
} catch (e) {
// no log yet, how to report this error?
Log.error("failed to parse data-sap-ui-config attribute: " + (e.message || e));
}
}
// merge with any existing "data-sap-ui-" attributes
for (var i = 0; i < oScriptTag.attributes.length; i++) {
var attr = oScriptTag.attributes[i];
var m = attr.name.match(/^data-sap-ui-(.*)$/);
if ( m ) {
// the following (deactivated) conversion would implement multi-word names like "resource-roots"
m = m[1].toLowerCase(); // .replace(/\-([a-z])/g, function(s,w) { return w.toUpperCase(); })
if ( m === 'resourceroots' ) {
// merge map entries instead of overwriting map
Object.assign(oCfg[m], JSON.parse(attr.value));
} else if ( m === 'theme-roots' ) {
// merge map entries, but rename to camelCase
Object.assign(oCfg.themeroots, JSON.parse(attr.value));
} else if ( m !== 'config' ) {
oCfg[m] = attr.value;
}
}
}
}
return oCfg;
}());
var syncCallBehavior = 0; // ignore
if ( oCfgData['xx-nosync'] === 'warn' || /(?:\?|&)sap-ui-xx-nosync=(?:warn)/.exec(window.location.search) ) {
syncCallBehavior = 1;
}
if ( oCfgData['xx-nosync'] === true || oCfgData['xx-nosync'] === 'true' || /(?:\?|&)sap-ui-xx-nosync=(?:x|X|true)/.exec(window.location.search) ) {
syncCallBehavior = 2;
}
ui5loader.config({
reportSyncCalls: syncCallBehavior
});
if ( syncCallBehavior && oCfgData.__loaded ) {
_earlyLog(syncCallBehavior === 1 ? "warning" : "error", "[nosync]: configuration loaded via sync XHR");
}
// check whether noConflict must be used...
if ( oCfgData.noconflict === true || oCfgData.noconflict === "true" || oCfgData.noconflict === "x" ) {
jQuery.noConflict();
}
/**
* Root Namespace for the jQuery plug-in provided by SAP SE.
*
* @version 1.87.1
* @namespace
* @public
* @static
* @deprecated since 1.58. To avoid usage of global variables in general, please
* do not use the jQuery.sap namespace any longer. Most of the jQuery.sap functionalities
* are replaced by alternative modules which can be found in the API doc.
*/
jQuery.sap = jQuery.sap || {}; // namespace already created by jquery.sap.stubs
// -------------------------- VERSION -------------------------------------
/**
* Returns a Version instance created from the given parameters.
*
* This function can either be called as a constructor (using <code>new</code>) or as a normal function.
* It always returns an immutable Version instance.
*
* The parts of the version number (major, minor, patch, suffix) can be provided in several ways:
* <ul>
* <li>Version("1.2.3-SNAPSHOT") - as a dot-separated string. Any non-numerical char or a dot followed
* by a non-numerical char starts the suffix portion. Any missing major,
* minor or patch versions will be set to 0.</li>
* <li>Version(1,2,3,"-SNAPSHOT") - as individual parameters. Major, minor and patch must be integer numbers
* or empty, suffix must be a string not starting with digits.</li>
* <li>Version([1,2,3,"-SNAPSHOT"]) - as an array with the individual parts. The same type restrictions apply
* as before.</li>
* <li>Version(otherVersion) - as a Version instance (cast operation). Returns the given instance instead
* of creating a new one.</li>
* </ul>
*
* To keep the code size small, this implementation mainly validates the single string variant.
* All other variants are only validated to some degree. It is the responsibility of the caller to
* provide proper parts.
*
* @param {int|string|any[]|jQuery.sap.Version} vMajor the major part of the version (int) or any of the single
* parameter variants explained above.
* @param {int} iMinor the minor part of the version number
* @param {int} iPatch the patch part of the version number
* @param {string} sSuffix the suffix part of the version number
* @return {jQuery.sap.Version} the version object as determined from the parameters
*
* @class Represents a version consisting of major, minor, patch version and suffix, e.g. '1.2.7-SNAPSHOT'.
*
* @public
* @since 1.15.0
* @alias jQuery.sap.Version
* @deprecated since 1.58 use {@link module:sap/base/util/Version} instead
*/
jQuery.sap.Version = Version;
/**
* Returns a string representation of this version.
* @name jQuery.sap.Version#toString
* @return {string} a string representation of this version.
* @public
* @since 1.15.0
* @function
*/
/**
* Returns the major version part of this version.
* @name jQuery.sap.Version#getMajor
* @function
* @return {int} the major version part of this version
* @public
* @since 1.15.0
*/
/**
* Returns the minor version part of this version.
* @name jQuery.sap.Version#getMinor
* @return {int} the minor version part of this version
* @public
* @since 1.15.0
* @function
*/
/**
* Returns the patch (or micro) version part of this version.
* @name jQuery.sap.Version#getPatch
* @return {int} the patch version part of this version
* @public
* @since 1.15.0
* @function
*/
/**
* Returns the version suffix of this version.
*
* @name jQuery.sap.Version#getSuffix
* @return {string} the version suffix of this version
* @public
* @since 1.15.0
* @function
*/
/**
* Compares this version with a given one.
*
* The version with which this version should be compared can be given as a <code>jQuery.sap.Version</code> instance,
* as a string (e.g. <code>v.compareto("1.4.5")</code>). Or major, minor, patch and suffix values can be given as
* separate parameters (e.g. <code>v.compareTo(1, 4, 5)</code>) or in an array (e.g. <code>v.compareTo([1, 4, 5])</code>).
*
* @name jQuery.sap.Version#compareTo
* @return {int} 0, if the given version is equal to this version, a negative value if the given other version is greater
* and a positive value otherwise
* @public
* @since 1.15.0
* @function
*/
/**
* Checks whether this version is in the range of the given interval (start inclusive, end exclusive).
*
* The boundaries against which this version should be checked can be given as <code>jQuery.sap.Version</code>
* instances (e.g. <code>v.inRange(v1, v2)</code>), as strings (e.g. <code>v.inRange("1.4", "2.7")</code>)
* or as arrays (e.g. <code>v.inRange([1,4], [2,7])</code>).
*
* @name jQuery.sap.Version#inRange
* @param {string|any[]|jQuery.sap.Version} vMin the start of the range (inclusive)
* @param {string|any[]|jQuery.sap.Version} vMax the end of the range (exclusive)
* @return {boolean} <code>true</code> if this version is greater or equal to <code>vMin</code> and smaller
* than <code>vMax</code>, <code>false</code> otherwise.
* @public
* @since 1.15.0
* @function
*/
/**
* Returns a high resolution timestamp in microseconds if supported by the environment, otherwise in milliseconds.
* The timestamp is based on 01/01/1970 00:00:00 (UNIX epoch) as float with microsecond precision or
* with millisecond precision, if high resolution timestamps are not available.
* The fractional part of the timestamp represents fractions of a millisecond.
* Converting to a <code>Date</code> is possible by using <code>require(["sap/base/util/now"], function(now){new Date(now());}</code>
*
* @returns {float} timestamp in microseconds if supported by the environment otherwise in milliseconds
* @public
* @function
* @deprecated since 1.58 use {@link module:sap/base/util/now} instead
*/
jQuery.sap.now = now;
// Reads the value for the given key from the localStorage or writes a new value to it.
var fnMakeLocalStorageAccessor = function(key, type, callback) {
return function(value) {
try {
if ( value != null || type === 'string' ) {
if (value) {
localStorage.setItem(key, type === 'boolean' ? 'X' : value);
} else {
localStorage.removeItem(key);
}
callback(value);
}
value = localStorage.getItem(key);
return type === 'boolean' ? value === 'X' : value;
} catch (e) {
Log.warning("Could not access localStorage while accessing '" + key + "' (value: '" + value + "', are cookies disabled?): " + e.message);
}
};
};
jQuery.sap.debug = fnMakeLocalStorageAccessor.call(this, 'sap-ui-debug', '', function(vDebugInfo) {
/*eslint-disable no-alert */
alert("Usage of debug sources is " + (vDebugInfo ? "on" : "off") + " now.\nFor the change to take effect, you need to reload the page.");
/*eslint-enable no-alert */
});
/**
* Sets the URL to reboot this app from, the next time it is started. Only works with localStorage API available
* (and depending on the browser, if cookies are enabled, even though cookies are not used).
*
* @param {string} sRebootUrl the URL to sap-ui-core.js, from which the application should load UI5 on next restart; undefined clears the restart URL
* @returns {string} the current reboot URL or undefined in case of an error or when the reboot URL has been cleared
*
* @private
* @function
* @deprecated since 1.58
*/
jQuery.sap.setReboot = fnMakeLocalStorageAccessor.call(this, 'sap-ui-reboot-URL', 'string', function(sRebootUrl) { // null-ish clears the reboot request
if ( sRebootUrl ) {
/*eslint-disable no-alert */
alert("Next time this app is launched (only once), it will load UI5 from:\n" + sRebootUrl + ".\nPlease reload the application page now.");
/*eslint-enable no-alert */
}
});
jQuery.sap.statistics = fnMakeLocalStorageAccessor.call(this, 'sap-ui-statistics', 'boolean', function(bUseStatistics) {
/*eslint-disable no-alert */
alert("Usage of Gateway statistics " + (bUseStatistics ? "on" : "off") + " now.\nFor the change to take effect, you need to reload the page.");
/*eslint-enable no-alert */
});
// -------------------------- Logging -------------------------------------
/**
* Creates a new Logger instance which will use the given component string
* for all logged messages without a specific component.
*
* @name jQuery.sap.log.Logger
* @param {string} sDefaultComponent The component to use
* @class A Logger class
* @since 1.1.2
* @public
* @deprecated since 1.58 use {@link module:sap/base/Log.getLogger} instead
*/
/**
* Creates a new fatal-level entry in the log with the given message, details and calling component.
*
* @param {string} sMessage Message text to display
* @param {string} [sDetails=''] Details about the message, might be omitted
* @param {string} [sComponent=''] Name of the component that produced the log entry
* @param {function} [fnSupportInfo] Callback that returns an additional support object to be logged in support mode.
* This function is only called if support info mode is turned on with <code>logSupportInfo(true)</code>.
* To avoid negative effects regarding execution times and memory consumption, the returned object should be a simple
* immutable JSON object with mostly static and stable content.
* @return {jQuery.sap.log.Logger} The log instance for method chaining
* @public
* @SecSink {0 1 2|SECRET} Could expose secret data in logs
* @name jQuery.sap.log.Logger#fatal
* @function
*/
/**
* Creates a new error-level entry in the log with the given message, details and calling component.
*
* @param {string} sMessage Message text to display
* @param {string} [sDetails=''] Details about the message, might be omitted
* @param {string} [sComponent=''] Name of the component that produced the log entry
* @param {function} [fnSupportInfo] Callback that returns an additional support object to be logged in support mode.
* This function is only called if support info mode is turned on with <code>logSupportInfo(true)</code>.
* To avoid negative effects regarding execution times and memory consumption, the returned object should be a simple
* immutable JSON object with mostly static and stable content.
* @return {jQuery.sap.log.Logger} The log instance
* @public
* @SecSink {0 1 2|SECRET} Could expose secret data in logs
* @name jQuery.sap.log.Logger#error
* @function
*/
/**
* Creates a new warning-level entry in the log with the given message, details and calling component.
*
* @param {string} sMessage Message text to display
* @param {string} [sDetails=''] Details about the message, might be omitted
* @param {string} [sComponent=''] Name of the component that produced the log entry
* @param {function} [fnSupportInfo] Callback that returns an additional support object to be logged in support mode.
* This function is only called if support info mode is turned on with <code>logSupportInfo(true)</code>.
* To avoid negative effects regarding execution times and memory consumption, the returned object should be a simple
* immutable JSON object with mostly static and stable content.
* @return {jQuery.sap.log.Logger} The log instance
* @public
* @SecSink {0 1 2|SECRET} Could expose secret data in logs
* @name jQuery.sap.log.Logger#warning
* @function
*/
/**
* Creates a new info-level entry in the log with the given message, details and calling component.
*
* @param {string} sMessage Message text to display
* @param {string} [sDetails=''] Details about the message, might be omitted
* @param {string} [sComponent=''] Name of the component that produced the log entry
* @param {function} [fnSupportInfo] Callback that returns an additional support object to be logged in support mode.
* This function is only called if support info mode is turned on with <code>logSupportInfo(true)</code>.
* To avoid negative effects regarding execution times and memory consumption, the returned object should be a simple
* immutable JSON object with mostly static and stable content.
* @return {jQuery.sap.log.Logger} The log instance
* @public
* @SecSink {0 1 2|SECRET} Could expose secret data in logs
* @name jQuery.sap.log.Logger#info
* @function
*/
/**
* Creates a new debug-level entry in the log with the given message, details and calling component.
*
* @param {string} sMessage Message text to display
* @param {string} [sDetails=''] Details about the message, might be omitted
* @param {string} [sComponent=''] Name of the component that produced the log entry
* @param {function} [fnSupportInfo] Callback that returns an additional support object to be logged in support mode.
* This function is only called if support info mode is turned on with <code>logSupportInfo(true)</code>.
* To avoid negative effects regarding execution times and memory consumption, the returned object should be a simple
* immutable JSON object with mostly static and stable content.
* @return {jQuery.sap.log.Logger} The log instance
* @public
* @SecSink {0 1 2|SECRET} Could expose secret data in logs
* @name jQuery.sap.log.Logger#debug
* @function
*/
/**
* Creates a new trace-level entry in the log with the given message, details and calling component.
*
* @param {string} sMessage Message text to display
* @param {string} [sDetails=''] Details about the message, might be omitted
* @param {string} [sComponent=''] Name of the component that produced the log entry
* @param {function} [fnSupportInfo] Callback that returns an additional support object to be logged in support mode.
* This function is only called if support info mode is turned on with <code>logSupportInfo(true)</code>.
* To avoid negative effects regarding execution times and memory consumption, the returned object should be a simple
* immutable JSON object with mostly static and stable content.
* @return {jQuery.sap.log.Logger} The log-instance
* @public
* @SecSink {0 1 2|SECRET} Could expose secret data in logs
* @name jQuery.sap.log.Logger#trace
* @function
*/
/**
* Defines the maximum <code>jQuery.sap.log.Level</code> of log entries that will be recorded.
* Log entries with a higher (less important) log level will be omitted from the log.
* When a component name is given, the log level will be configured for that component
* only, otherwise the log level for the default component of this logger is set.
* For the global logger, the global default level is set.
*
* <b>Note</b>: Setting a global default log level has no impact on already defined
* component log levels. They always override the global default log level.
*
* @param {jQuery.sap.log.Level} iLogLevel The new log level
* @param {string} [sComponent] The log component to set the log level for
* @return {jQuery.sap.log.Logger} This logger object to allow method chaining
* @public
* @name jQuery.sap.log.Logger#setLevel
* @function
*/
/**
* Returns the log level currently effective for the given component.
* If no component is given or when no level has been configured for a
* given component, the log level for the default component of this logger is returned.
*
* @param {string} [sComponent] Name of the component to retrieve the log level for
* @return {int} The log level for the given component or the default log level
* @public
* @since 1.1.2
* @name jQuery.sap.log.Logger#getLevel
* @function
*/
/**
* Checks whether logging is enabled for the given log level,
* depending on the currently effective log level for the given component.
*
* If no component is given, the default component of this logger will be taken into account.
*
* @param {int} [iLevel=Level.DEBUG] The log level in question
* @param {string} [sComponent] Name of the component to check the log level for
* @return {boolean} Whether logging is enabled or not
* @public
* @since 1.13.2
* @name jQuery.sap.log.Logger#isLoggable
* @function
*/
/**
* A Logging API for JavaScript.
*
* Provides methods to manage a client-side log and to create entries in it. Each of the logging methods
* {@link jQuery.sap.log.debug}, {@link jQuery.sap.log.info}, {@link jQuery.sap.log.warning},
* {@link jQuery.sap.log.error} and {@link jQuery.sap.log.fatal} creates and records a log entry,
* containing a timestamp, a log level, a message with details and a component info.
* The log level will be one of {@link jQuery.sap.log.Level} and equals the name of the concrete logging method.
*
* By using the {@link jQuery.sap.log.setLevel} method, consumers can determine the least important
* log level which should be recorded. Less important entries will be filtered out. (Note that higher numeric
* values represent less important levels). The initially set level depends on the mode that UI5 is running in.
* When the optimized sources are executed, the default level will be {@link jQuery.sap.log.Level.ERROR}.
* For normal (debug sources), the default level is {@link jQuery.sap.log.Level.DEBUG}.
*
* All logging methods allow to specify a <b>component</b>. These components are simple strings and
* don't have a special meaning to the UI5 framework. However they can be used to semantically group
* log entries that belong to the same software component (or feature). There are two APIs that help
* to manage logging for such a component. With <code>{@link jQuery.sap.log.getLogger}(sComponent)</code>,
* one can retrieve a logger that automatically adds the given <code>sComponent</code> as component
* parameter to each log entry, if no other component is specified. Typically, JavaScript code will
* retrieve such a logger once during startup and reuse it for the rest of its lifecycle.
* Second, the {@link jQuery.sap.log.Logger#setLevel}(iLevel, sComponent) method allows to set the log level
* for a specific component only. This allows a more fine granular control about the created logging entries.
* {@link jQuery.sap.log.Logger#getLevel} allows to retrieve the currently effective log level for a given
* component.
*
* {@link jQuery.sap.log.getLogEntries} returns an array of the currently collected log entries.
*
* Furthermore, a listener can be registered to the log. It will be notified whenever a new entry
* is added to the log. The listener can be used for displaying log entries in a separate page area,
* or for sending it to some external target (server).
*
* @since 0.9.0
* @namespace
* @public
* @borrows jQuery.sap.log.Logger#fatal as fatal
* @borrows jQuery.sap.log.Logger#error as error
* @borrows jQuery.sap.log.Logger#warning as warning
* @borrows jQuery.sap.log.Logger#info as info
* @borrows jQuery.sap.log.Logger#debug as debug
* @borrows jQuery.sap.log.Logger#trace as trace
* @borrows jQuery.sap.log.Logger#getLevel as getLevel
* @borrows jQuery.sap.log.Logger#setLevel as setLevel
* @borrows jQuery.sap.log.Logger#isLoggable as isLoggable
* @deprecated since 1.58 use {@link module:sap/base/Log} instead
*/
jQuery.sap.log = Object.assign(Log.getLogger(), /** @lends jQuery.sap.log */ {
/**
* Enumeration of the configurable log levels that a Logger should persist to the log.
*
* Only if the current LogLevel is higher than the level {@link jQuery.sap.log.Level} of the currently added log entry,
* then this very entry is permanently added to the log. Otherwise it is ignored.
* @see jQuery.sap.log.Logger#setLevel
* @enum {int}
* @public
* @deprecated since 1.58 use {@link module:sap/base/Log.Level} instead
*/
Level: Log.Level,
/**
* Do not log anything
* @public
* @name jQuery.sap.log.Level.NONE
* @type {int}
*/
/**
* Fatal level. Use this for logging unrecoverable situations
* @public
* @name jQuery.sap.log.Level.FATAL
* @type {int}
*/
/**
* Error level. Use this for logging of erroneous but still recoverable situations
* @public
* @name jQuery.sap.log.Level.ERROR
* @type {int}
*/
/**
* Warning level. Use this for logging unwanted but foreseen situations
* @public
* @name jQuery.sap.log.Level.WARNING
* @type {int}
*/
/**
* Info level. Use this for logging information of purely informative nature
* @public
* @name jQuery.sap.log.Level.INFO
* @type {int}
*/
/**
* Debug level. Use this for logging information necessary for debugging
* @public
* @name jQuery.sap.log.Level.DEBUG
* @type {int}
*/
/**
* Trace level. Use this for tracing the program flow.
* @public
* @name jQuery.sap.log.Level.TRACE
* @type {int}
*/
/**
* Trace level to log everything.
* @public
* @name jQuery.sap.log.Level.ALL
* @type {int}
*/
/**
* Returns a {@link jQuery.sap.log.Logger} for the given component.
*
* The method might or might not return the same logger object across multiple calls.
* While loggers are assumed to be light weight objects, consumers should try to
* avoid redundant calls and instead keep references to already retrieved loggers.
*
* The optional second parameter <code>iDefaultLogLevel</code> allows to specify
* a default log level for the component. It is only applied when no log level has been
* defined so far for that component (ignoring inherited log levels). If this method is
* called multiple times for the same component but with different log levels,
* only the first call one might be taken into account.
*
* @param {string} sComponent Component to create the logger for
* @param {int} [iDefaultLogLevel] a default log level to be used for the component,
* if no log level has been defined for it so far.
* @return {jQuery.sap.log.Logger} A logger for the component.
* @public
* @static
* @since 1.1.2
* @function
*/
getLogger: Log.getLogger,
/**
* Returns the logged entries recorded so far as an array.
*
* Log entries are plain JavaScript objects with the following properties
* <ul>
* <li>timestamp {number} point in time when the entry was created</li>
* <li>level {int} LogLevel level of the entry</li>
* <li>message {string} message text of the entry</li>
* </ul>
*
* @return {object[]} an array containing the recorded log entries
* @public
* @static
* @since 1.1.2
* @function
*/
getLogEntries: Log.getLogEntries,
/**
* Allows to add a new LogListener that will be notified for new log entries.
*
* The given object must provide method <code>onLogEntry</code> and can also be informed
* about <code>onDetachFromLog</code> and <code>onAttachToLog</code>
* @param {object} oListener The new listener object that should be informed
* @return {jQuery.sap.log} The global logger
* @public
* @static
* @function
*/
addLogListener: Log.addLogListener,
/**
* Allows to remove a registered LogListener.
* @param {object} oListener The new listener object that should be removed
* @return {jQuery.sap.log} The global logger
* @public
* @static
* @function
*/
removeLogListener: Log.removeLogListener,
/**
* Enables or disables whether additional support information is logged in a trace.
* If enabled, logging methods like error, warning, info and debug are calling the additional
* optional callback parameter fnSupportInfo and store the returned object in the log entry property supportInfo.
*
* @param {boolean} bEnabled true if the support information should be logged
* @private
* @static
* @since 1.46.0
* @function
*/
logSupportInfo: Log.logSupportInfo,
/**
* Enumeration of levels that can be used in a call to {@link jQuery.sap.log.Logger#setLevel}(iLevel, sComponent).
*
* @deprecated Since 1.1.2. To streamline the Logging API a bit, the separation between Level and LogLevel has been given up.
* Use the (enriched) enumeration {@link jQuery.sap.log.Level} instead.
* @enum
* @public
*/
LogLevel: Log.Level,
/**
* Retrieves the currently recorded log entries.
* @deprecated Since 1.1.2. To avoid confusion with getLogger, this method has been renamed to {@link jQuery.sap.log.getLogEntries}.
* @function
* @public
*/
getLog: Log.getLogEntries
});
var sWindowName = (typeof window === "undefined" || window.top == window) ? "" : "[" + window.location.pathname.split('/').slice(-1)[0] + "] ";
/**
* A simple assertion mechanism that logs a message when a given condition is not met.
*
* <b>Note:</b> Calls to this method might be removed when the JavaScript code
* is optimized during build. Therefore, callers should not rely on any side effects
* of this method.
*
* @param {boolean} bResult Result of the checked assertion
* @param {string|function} vMessage Message that will be logged when the result is <code>false</code>. In case this is a function, the return value of the function will be displayed. This can be used to execute complex code only if the assertion fails.
*
* @public
* @static
* @SecSink {1|SECRET} Could expose secret data in logs
* @function
* @deprecated since 1.58 use {@link module:sap/base/assert} instead
*/
jQuery.sap.assert = function(bResult, vMessage) {
if (!bResult) {
var sMessage = typeof vMessage === "function" ? vMessage() : vMessage;
assert(bResult, sWindowName + sMessage);
}
};
// evaluate configuration
oCfgData.loglevel = (function() {
var m = /(?:\?|&)sap-ui-log(?:L|-l)evel=([^&]*)/.exec(window.location.search);
return m && m[1];
}()) || oCfgData.loglevel;
if ( oCfgData.loglevel ) {
Log.setLevel(Log.Level[oCfgData.loglevel.toUpperCase()] || parseInt(oCfgData.loglevel));
} else if (!window["sap-ui-optimized"]) {
Log.setLevel(Log.Level.DEBUG);
}
Log.info("SAP Logger started.");
// log early logs
jQuery.each(_earlyLogs, function(i,e) {
Log[e.level](e.message);
});
_earlyLogs = null;
// ------------------------------------------- OBJECT --------------------------------------------------------
/**
* Returns a new constructor function that creates objects with
* the given prototype.
*
* As of 1.45.0, this method has been deprecated. Use the following code pattern instead:
* <pre>
* function MyFunction() {
* };
* MyFunction.prototype = oPrototype;
* </pre>
* @param {object} oPrototype Prototype to use for the new objects
* @return {function} the newly created constructor function
* @public
* @static
* @deprecated As of 1.45.0, define your own function and assign <code>oPrototype</code> to its <code>prototype</code> property instead.
*/
jQuery.sap.factory = function factory(oPrototype) {
jQuery.sap.assert(typeof oPrototype == "object", "oPrototype must be an object (incl. null)");
function Factory() {}
Factory.prototype = oPrototype;
return Factory;
};
/**
* Returns a new object which has the given <code>oPrototype</code> as its prototype.
*
* If several objects with the same prototype are to be created,
* {@link jQuery.sap.factory} should be used instead.
*
* @param {object} oPrototype Prototype to use for the new object
* @return {object} new object
* @public
* @static
* @deprecated As of 1.45.0, use <code>Object.create(oPrototype)</code> instead.
*/
jQuery.sap.newObject = function newObject(oPrototype) {
jQuery.sap.assert(typeof oPrototype == "object", "oPrototype must be an object (incl. null)");
// explicitly fall back to null for best compatibility with old implementation
return Object.create(oPrototype || null);
};
/**
* Returns a new function that returns the given <code>oValue</code> (using its closure).
*
* Avoids the need for a dedicated member for the value.
*
* As closures don't come for free, this function should only be used when polluting
* the enclosing object is an absolute "must-not" (as it is the case in public base classes).
*
* @param {object} oValue The value that the getter should return
* @returns {function} The new getter function
* @public
* @static
* @function
* @deprecated since 1.58
*/
jQuery.sap.getter = function(oValue) {
return function() {
return oValue;
};
};
/**
* Returns a JavaScript object which is identified by a sequence of names.
*
* A call to <code>getObject("a.b.C")</code> has essentially the same effect
* as accessing <code>window.a.b.C</code> but with the difference that missing
* intermediate objects (a or b in the example above) don't lead to an exception.
*
* When the addressed object exists, it is simply returned. If it doesn't exists,
* the behavior depends on the value of the second, optional parameter
* <code>iNoCreates</code> (assuming 'n' to be the number of names in the name sequence):
* <ul>
* <li>NaN: if iNoCreates is not a number and the addressed object doesn't exist,
* then <code>getObject()</code> returns <code>undefined</code>.
* <li>0 < iNoCreates < n: any non-existing intermediate object is created, except
* the <i>last</i> <code>iNoCreates</code> ones.
* </ul>
*
* Example:
* <pre>
* getObject() -- returns the context object (either param or window)
* getObject("a.b.C") -- will only try to get a.b.C and return undefined if not found.
* getObject("a.b.C", 0) -- will create a, b, and C in that order if they don't exists
* getObject("a.b.c", 1) -- will create a and b, but not C.
* </pre>
*
* When a <code>oContext</code> is given, the search starts in that object.
* Otherwise it starts in the <code>window</code> object that this plugin
* has been created in.
*
* Note: Although this method internally uses <code>object["key"]</code> to address object
* properties, it does not support all possible characters in a name.
* Especially the dot ('.') is not supported in the individual name segments,
* as it is always interpreted as a name separator.
*
* @param {string} sName a dot separated sequence of names that identify the required object
* @param {int} [iNoCreates=NaN] number of objects (from the right) that should not be created
* @param {object} [oContext=window] the context to execute the search in
* @returns {function} The value of the named object
*
* @public
* @static
* @deprecated since 1.58 use {@link module:sap/base/util/ObjectPath.get} or
* {@link module:sap/base/util/ObjectPath.set} instead
*/
jQuery.sap.getObject = function(sName, iNoCreates, oContext) {
var oObject = oContext || window,
aNames = (sName || "").split("."),
l = aNames.length,
iEndCreate = isNaN(iNoCreates) ? 0 : l - iNoCreates,
i;
if ( syncCallBehavior && oContext === window ) {
Log.error("[nosync] getObject called to retrieve global name '" + sName + "'");
}
for (i = 0; oObject && i < l; i++) {
if (!oObject[aNames[i]] && i < iEndCreate ) {
oObject[aNames[i]] = {};
}
oObject = oObject[aNames[i]];
}
return oObject;
};
/**
* Sets an object property to a given value, where the property is
* identified by a sequence of names (path).
*
* When a <code>oContext</code> is given, the path starts in that object.
* Otherwise it starts in the <code>window</code> object that this plugin
* has been created for.
*
* Note: Although this method internally uses <code>object["key"]</code> to address object
* properties, it does not support all possible characters in a name.
* Especially the dot ('.') is not supported in the individual name segments,
* as it is always interpreted as a name separator.
*
* @param {string} sName a dot separated sequence of names that identify the property
* @param {any} vValue value to be set, can have any type
* @param {object} [oContext=window] the context to execute the search in
* @public
* @static
* @deprecated since 1.58 use {@link module:sap/base/util/ObjectPath.set} instead
*/
jQuery.sap.setObject = function (sName, vValue, oContext) {
var oObject = oContext || window,
aNames = (sName || "").split("."),
l = aNames.length, i;
if ( l > 0 ) {
for (i = 0; oObject && i < l - 1; i++) {
if (!oObject[aNames[i]] ) {
oObject[aNames[i]] = {};
}
oObject = oObject[aNames[i]];
}
oObject[aNames[l - 1]] = vValue;
}
};
// ---------------------- performance measurement -----------------------------------------------------------
/**
* Namespace for the jQuery performance measurement plug-in provided by SAP SE.
*
* @name jQuery.sap.measure
* @namespace
* @public
* @static
* @deprecated since 1.58 use {@link module:sap/ui/performance/Measurement} or {@link module:sap/ui/performance/trace/Interaction} instead
*/
jQuery.sap.measure = Measurement;
/**
* Gets the current state of the performance measurement functionality
*
* @name jQuery.sap.measure.getActive
* @function
* @return {boolean} current state of the performance measurement functionality
* @public
* @deprecated since 1.58 use {@link module:sap/ui/performance/Measurement.getActive} instead
*/
/**
* Activates or deactivates the performance measure functionality
* Optionally a category or list of categories can be passed to restrict measurements to certain categories
* like "javascript", "require", "xmlhttprequest", "render"
* @param {boolean} bOn - state of the performance measurement functionality to set
* @param {string | string[]} aCategories - An optional list of categories that should be measured
*
* @return {boolean} current state of the performance measurement functionality
* @name jQuery.sap.measure#setActive
* @function
* @public
* @deprecated since 1.58 use {@link module:sap/ui/performance/Measurement.setActive} instead
*/
/**
* Starts a performance measure.
* Optionally a category or list of categories can be passed to allow filtering of measurements.
*
* @name jQuery.sap.measure.start
* @function
* @param {string} sId ID of the measurement
* @param {string} sInfo Info for the measurement
* @param {string | string[]} [aCategories = "javascript"] An optional list of categories for the measure
*
* @return {object} current measurement containing id, info and start-timestamp (false if error)
* @public
* @deprecated since 1.58 use {@link module:sap/ui/performance/Measurement.start} instead
*/
/**
* Pauses a performance measure
*
* @name jQuery.sap.measure.pause
* @function
* @param {string} sId ID of the measurement
* @return {object} current measurement containing id, info and start-timestamp, pause-timestamp (false if error)
* @public
* @deprecated since 1.58 use {@link module:sap/ui/performance/Measurement.pause} instead
*/
/**
* Resumes a performance measure
*
* @name jQuery.sap.measure.resume
* @function
* @param {string} sId ID of the measurement
* @return {object} current measurement containing id, info and start-timestamp, resume-timestamp (false if error)
* @public
* @deprecated since 1.58 use {@link module:sap/ui/performance/Measurement.resume} instead
*/
/**
* Ends a performance measure
*
* @name jQuery.sap.measure.end
* @function
* @param {string} sId ID of the measurement
* @return {object} current measurement containing id, info and start-timestamp, end-timestamp, time, duration (false if error)
* @public
* @deprecated since 1.58 use {@link module:sap/ui/performance/Measurement.end} instead
*/
/**
* Clears all performance measurements
*
* @name jQuery.sap.measure.clear
* @function
* @public
* @deprecated since 1.58 use {@link module:sap/ui/performance/Measurement.clear} instead
*/
/**
* Removes a performance measure
*
* @nam