<commit_before>/*!
 * ${copyright}
 */

// Provides the base class for all controls and UI elements.
sap.ui.define([
	'../base/DataType',
	'../base/Object',
	'../base/ManagedObject',
	'../base/ManagedObjectRegistry',
	'./ElementMetadata',
	'../Device',
	"sap/ui/performance/trace/Interaction",
	"sap/base/Log",
	"sap/base/assert",
	"sap/ui/thirdparty/jquery",
	"sap/ui/events/F6Navigation",
	"./RenderManager"
],
	function(
		DataType,
		BaseObject,
		ManagedObject,
		ManagedObjectRegistry,
		ElementMetadata,
		Device,
		Interaction,
		Log,
		assert,
		jQuery,
		F6Navigation,
		RenderManager
	) {
	"use strict";

	/**
	 * Constructs and initializes a UI Element with the given <code>sId</code> and settings.
	 *
	 *
	 * <h3>Uniqueness of IDs</h3>
	 *
	 * Each <code>Element</code> must have an ID. If no <code>sId</code> or <code>mSettings.id</code> is
	 * given at construction time, a new ID will be created automatically. The IDs of all elements that exist
	 * at the same time in the same window must be different. Providing an ID which is already used by another
	 * element throws an error.
	 *
	 * When an element is created from a declarative source (e.g. XMLView), then an ID defined in that
	 * declarative source needs to be unique only within the declarative source. Declarative views will
	 * prefix that ID with their own ID (and some separator) before constructing the element.
	 * Programmatically created views (JSViews) can do the same with the {@link sap.ui.core.mvc.View#createId} API.
	 * Similarly, UIComponents can prefix the IDs of elements created in their context with their own ID.
	 * Also see {@link sap.ui.core.UIComponent#getAutoPrefixId UIComponent#getAutoPrefixId}.
	 *
	 *
	 * <h3>Settings</h3>
	 * If the optional <code>mSettings</code> are given, they must be a JSON-like object (object literal)
	 * that defines values for properties, aggregations, associations or events keyed by their name.
	 *
	 * <b>Valid Names:</b>
	 *
	 * The property (key) names supported in the object literal are exactly the (case sensitive)
	 * names documented in the JSDoc for the properties, aggregations, associations and events
	 * of the control and its base classes. Note that for  0..n aggregations and associations this
	 * usually is the plural name, whereas it is the singular name in case of 0..1 relations.
	 *
	 * Each subclass should document the set of supported names in its constructor documentation.
	 *
	 * <b>Valid Values:</b>
	 *
	 * <ul>
	 * <li>for normal properties, the value has to be of the correct simple type (no type conversion occurs)</li>
	 * <li>for 0..1 aggregations, the value has to be an instance of the aggregated control or element type</li>
	 * <li>for 0..n aggregations, the value has to be an array of instances of the aggregated type</li>
	 * <li>for 0..1 associations, an instance of the associated type or an id (string) is accepted</li>
	 * <li>0..n associations are not supported yet</li>
	 * <li>for events either a function (event handler) is accepted or an array of length 2
	 *     where the first element is a function and the 2nd element is an object to invoke the method on.</li>
	 * </ul>
	 *
	 * Special aggregation <code>dependents</code> is connected to the lifecycle management and databinding,
	 * but not rendered automatically and can be used for popups or other dependent controls or elements.
	 * This allows the definition of popup controls in declarative views and enables propagation of model
	 * and context information to them.
	 *
	 * @param {string} [sId] id for the new control; generated automatically if no non-empty id is given
	 *      Note: this can be omitted, no matter whether <code>mSettings</code> will be given or not!
	 * @param {object} [mSettings] optional map/JSON-object with initial property values, aggregated objects etc. for the new element
	 *
	 * @abstract
	 *
	 * @class Base Class for UI Elements.
	 *
	 * <code>Element</code> is the most basic building block for UI5 UIs. An <code>Element</code> has state like a
	 * <code>ManagedObject</code>, it has a unique ID by which the framework remembers it. It can have associated
	 * DOM, but it can't render itself. Only {@link sap.ui.core.Control Controls} can render themselves and also
	 * take care of rendering <code>Elements</code> that they aggregate as children. If an <code>Element</code>
	 * has been rendered, its related DOM gets the same ID as the <code>Element</code> and thereby can be retrieved
	 * via API. When the state of an <code>Element</code> changes, it informs its parent <code>Control</code> which
	 * usually re-renders then.
	 *
	 * <h3>Dispatching Events</h3>
	 *
	 * The UI5 framework already registers generic listeners for common browser events, such as <code>click</code>
	 * or <code>keydown</code>. When called, the generic listener first determines the corresponding target element
	 * using {@link jQuery#control}. Then it checks whether the element has an event handler method for the event.
	 * An event handler method by convention has the same name as the event, but prefixed with "on": Method
	 * <code>onclick</code> is the handler for the <code>click</code> event, method <code>onkeydown</code> the handler
	 * for the <code>keydown</code> event and so on. If there is such a method, it will be called with the original
	 * event as the only parameter. If the element has a list of delegates registered, their handler functions will
	 * be called the same way, where present. The set of implemented handlers might differ between element and
	 * delegates. Not each handler implemented by an element has to be implemented by its delegates, and delegates
	 * can implement handlers that the corresponding element doesn't implement.
	 *
	 * A list of browser events that are handled that way can be found in {@link module:sap/ui/events/ControlEvents}.
	 * Additionally, the framework dispatches pseudo events ({@link module:sap/ui/events/PseudoEvents}) using the same
	 * naming convention. Last but not least, some framework events are also dispatched that way, e.g.
	 * <code>BeforeRendering</code>, <code>AfterRendering</code> (only for controls) and <code>ThemeChanged</code>.
	 *
	 * If further browser events are needed, controls can register listeners on the DOM using native APIs in their
	 * <code>onAfterRendering</code> handler. If needed, they can do this for their aggregated elements as well.
	 * If events might fire often (e.g. <code>mousemove</code>), it is best practice to register them only while
	 * needed, and deregister afterwards. Anyhow, any registered listeners must be cleaned up in the
	 * <code>onBeforeRendering</code> listener and before destruction in the <code>exit</code> hook.
	 *
	 * @extends sap.ui.base.ManagedObject
	 * @author SAP SE
	 * @version ${version}
	 * @public
	 * @alias sap.ui.core.Element
	 * @ui5-metamodel This control/element also will be described in the UI5 (legacy) designtime metamodel
	 */
	var Element = ManagedObject.extend("sap.ui.core.Element", {

		metadata : {
			stereotype : "element",
			"abstract" : true,
			publicMethods : [ "getId", "getMetadata", "getTooltip_AsString", "getTooltip_Text", "getModel", "setModel", "hasModel", "bindElement", "unbindElement", "getElementBinding", "prop", "getLayoutData", "setLayoutData" ],
			library : "sap.ui.core",
			aggregations : {

				/**
				 * The tooltip that should be shown for this Element.
				 *
				 * In the most simple case, a tooltip is a string that will be rendered by the control and
				 * displayed by the browser when the mouse pointer hovers over the control's DOM. In this
				 * variant, <code>tooltip</code> behaves like a simple control property.
				 *
				 * Controls need to explicitly support this kind of tooltip as they have to render it,
				 * but most controls do. Exceptions will be documented for the corresponding controls
				 * (e.g. <code>sap.ui.core.HTML</code> does not support tooltips).
				 *
				 * Alternatively, <code>tooltip</code> can act like a 0..1 aggregation and can be set to a
				 * tooltip control (an instance of a subclass of <code>sap.ui.core.TooltipBase</code>). In
				 * that case, the framework will take care of rendering the tooltip control in a popup-like
				 * manner. Such a tooltip control can display arbitrary content, not only a string.
				 *
				 * UI5 currently does not provide a recommended implementation of <code>TooltipBase</code>
				 * as the use of content-rich tooltips is discouraged by the Fiori Design Guidelines.
				 * Existing subclasses of <code>TooltipBase</code> therefore have been deprecated.
				 * However, apps can still subclass from <code>TooltipBase</code> and create their own
				 * implementation when needed (potentially taking the deprecated implementations as a
				 * starting point).
				 *
				 * See the section {@link https://experience.sap.com/fiori-design-web/using-tooltips/ Using Tooltips}
				 * in the Fiori Design Guideline.
				 */
				tooltip : {name : "tooltip", type : "sap.ui.core.TooltipBase", altTypes : ["string"], multiple : false},

				/**
				 * Custom Data, a data structure like a map containing arbitrary key value pairs.
				 */
				customData : {name : "customData", type : "sap.ui.core.CustomData", multiple : true, singularName : "customData"},

				/**
				 * Defines the layout constraints for this control when it is used inside a Layout.
				 * LayoutData classes are typed classes and must match the embedding Layout.
				 * See VariantLayoutData for aggregating multiple alternative LayoutData instances to a single Element.
				 */
				layoutData : {name : "layoutData", type : "sap.ui.core.LayoutData", multiple : false, singularName : "layoutData"},

				/**
				 * Dependents are not rendered, but their databinding context and lifecycle are bound to the aggregating Element.
				 * @since 1.19
				 */
				dependents : {name : "dependents", type : "sap.ui.core.Element", multiple : true},

				/**
				 * Defines the drag-and-drop configuration.
				 * <b>Note:</b> This configuration might be ignored due to control {@link sap.ui.core.Element.extend metadata} restrictions.
				 *
				 * @since 1.56
				 */
				dragDropConfig : {name : "dragDropConfig", type : "sap.ui.core.dnd.DragDropBase", multiple : true, singularName : "dragDropConfig"}
			}
		},

		constructor : function(sId, mSettings) {
			ManagedObject.apply(this, arguments);
		},

		renderer : null // Element has no renderer

	}, /* Metadata constructor */ ElementMetadata);

	// apply the registry mixin
	ManagedObjectRegistry.apply(Element, {
		onDuplicate: function(sId, oldElement, newElement) {
			if ( oldElement._sapui_candidateForDestroy ) {
				Log.debug("destroying dangling template " + oldElement + " when creating new object with same ID");
				oldElement.destroy();
			} else {
				var sMsg = "adding element with duplicate id '" + sId + "'";
				// duplicate ID detected => fail or at least log a warning
				if (sap.ui.getCore().getConfiguration().getNoDuplicateIds()) {
					Log.error(sMsg);
					throw new Error("Error: " + sMsg);
				} else {
					Log.warning(sMsg);
				}
			}
		}
	});

	/**
	 * Creates metadata for a UI Element by extending the Object Metadata.
	 *
	 * @param {string} sClassName name of the class to build the metadata for
	 * @param {object} oStaticInfo static information used to build the metadata
	 * @param {function} [fnMetaImpl=sap.ui.core.ElementMetadata] constructor to be used for the metadata
	 * @return {sap.ui.core.ElementMetadata} the created metadata
	 * @static
	 * @public
	 * @deprecated Since 1.3.1. Use the static <code>extend</code> method of the desired base class (e.g. {@link sap.ui.core.Element.extend})
	 */
	Element.defineClass = function(sClassName, oStaticInfo, fnMetaImpl) {
		// create and attach metadata but with an Element specific implementation
		return BaseObject.defineClass(sClassName, oStaticInfo, fnMetaImpl || ElementMetadata);
	};

	/**
	 * @see sap.ui.base.Object#getInterface
	 * @public
	 */
	Element.prototype.getInterface = function() {
		return this;
	};

	/**
	 * Defines a new subclass of Element with the name <code>sClassName</code> and enriches it with
	 * the information contained in <code>oClassInfo</code>.
	 *
	 * <code>oClassInfo</code> can contain the same information that {@link sap.ui.base.ManagedObject.extend} already accepts,
	 * plus the following <code>dnd</code> property to configure drag-and-drop behavior in the metadata object literal:
	 *
	 * Example:
	 * <pre>
	 * Element.extend('sap.mylib.MyElement', {
	 *   metadata : {
	 *     library : 'sap.mylib',
	 *     properties : {
	 *       value : 'string',
	 *       width : 'sap.ui.core.CSSSize'
	 *     },
	 *     dnd : { draggable: true, droppable: false },
	 *     aggregations : {
	 *       items : { type: 'sap.ui.core.Control', multiple : true, dnd : {draggable: false, dropppable: true, layout: "Horizontal" } },
	 *       header : {type : "sap.ui.core.Control", multiple : false, dnd : true },
	 *     }
	 *   }
	 * });
	 * </pre>
	 *
	 * <h3><code>dnd</code> key as a metadata property</h3>
	 *
	 * <b>dnd</b>: <i>object|boolean</i><br>
	 * Defines draggable and droppable configuration of the element.
	 * The following keys can be provided via <code>dnd</code> object literal to configure drag-and-drop behavior of the element:
	 * <ul>
	 *  <li><code>[draggable=false]: <i>boolean</i></code> Defines whether the element is draggable or not. The default value is <code>false</code>.</li>
	 *  <li><code>[droppable=false]: <i>boolean</i></code> Defines whether the element is droppable (it allows being dropped on by a draggable element) or not. The default value is <code>false</code>.</li>
	 * </ul>
	 * If <code>dnd</code> property is of type Boolean, then the <code>draggable</code> and <code>droppable</code> configuration are set to this Boolean value.
	 *
	 * <h3><code>dnd</code> key as an aggregation metadata property</h3>
	 *
	 * <b>dnd</b>: <i>object|boolean</i><br>
	 * In addition to draggable and droppable configuration, the layout of the aggregation can be defined as a hint at the drop position indicator.
	 * <ul>
	 *  <li><code>[layout="Vertical"]: </code> The arrangement of the items in this aggregation. This setting is recommended for the aggregation with multiplicity 0..n (<code>multiple: true</code>). Possible values are <code>Vertical</code> (e.g. rows in a table) and <code>Horizontal</code> (e.g. columns in a table). It is recommended to use <code>Horizontal</code> layout if the arrangement is multidimensional.</li>
	 * </ul>
	 *
	 * @param {string} sClassName fully qualified name of the class that is described by this metadata object
	 * @param {object} oStaticInfo static info to construct the metadata from
	 * @returns {function} Created class / constructor function
	 *
	 * @public
	 * @static
	 * @name sap.ui.core.Element.extend
	 * @function
	 */

	/**
	 * Dispatches the given event, usually a browser event or a UI5 pseudo event.
	 * @private
	 */
	Element.prototype._handleEvent = function (oEvent) {

		var that = this,
			sHandlerName = "on" + oEvent.type;

		function each(aDelegates) {
			var i,l,oDelegate;
			if ( aDelegates && (l = aDelegates.length) > 0 ) {
				// To be robust against concurrent modifications of the delegates list, we loop over a copy.
				// When there is only a single entry, the loop is safe without a copy (length is determined only once!)
				aDelegates = l === 1 ? aDelegates : aDelegates.slice();
				for (i = 0; i < l; i++ ) {
					if (oEvent.isImmediateHandlerPropagationStopped()) {
						return;
					}
					oDelegate = aDelegates[i].oDelegate;
					if (oDelegate[sHandlerName]) {
						oDelegate[sHandlerName].call(aDelegates[i].vThis === true ? that : aDelegates[i].vThis || oDelegate, oEvent);
					}
				}
			}
		}

		each(this.aBeforeDelegates);
		if ( oEvent.isImmediateHandlerPropagationStopped() ) {
			return;
		}
		if ( this[sHandlerName] ) {
			this[sHandlerName](oEvent);
		}
		each(this.aDelegates);

	};


	/**
	 * Initializes the element instance after creation.
	 *
	 * Applications must not call this hook method directly, it is called by the framework
	 * while the constructor of an element is executed.
	 *
	 * Subclasses of Element should override this hook to implement any necessary initialization.
	 *
	 * @protected
	 */
	Element.prototype.init = function() {
		// Before adding any implementation, please remember that this method was first implemented in release 1.54.
		// Therefore, many subclasses will not call this method at all.
	};

	/**
	 * Hook method for cleaning up the element instance before destruction.
	 *
	 * Applications must not call this hook method directly, it is called by the framework
	 * when the element is {@link #destroy destroyed}.
	 *
	 * Subclasses of Element should override this hook to implement any necessary cleanup.
	 *
	 * <pre>
	 * exit: function() {
	 *     // ... do any further cleanups of your subclass e.g. detach events...
	 *     this.$().off("click", this.handleClick);
	 *
	 *     if (Element.prototype.exit) {
	 *         Element.prototype.exit.apply(this, arguments);
	 *     }
	 * }
	 * </pre>
	 *
	 * For a more detailed description how to to use the exit hook, see Section
	 * {@link topic:d4ac0edbc467483585d0c53a282505a5 exit() Method} in the documentation.
	 *
	 * @protected
	 */
	Element.prototype.exit = function() {
		// Before adding any implementation, please remember that this method was first implemented in release 1.54.
		// Therefore, many subclasses will not call this method at all.
	};

	/**
	 * Creates a new Element from the given data.
	 *
	 * If <code>vData</code> is an Element already, that element is returned.
	 * If <code>vData</code> is an object (literal), then a new element is created with <code>vData</code> as settings.
	 * The type of the element is either determined by a property named <code>Type</code> in the <code>vData</code> or
	 * by a type information in the <code>oKeyInfo</code> object
	 * @param {sap.ui.core.Element|object} vData Data to create the element from
	 * @param {object} [oKeyInfo] An entity information (e.g. aggregation info)
	 * @param {string} [oKeyInfo.type] Type info for the entity
	 * @public
	 * @static
	 * @deprecated As of 1.44, use the more flexible {@link sap.ui.base.ManagedObject.create}.
	 * @function
	 */
	Element.create = ManagedObject.create;

	/**
	 * Returns a simple string representation of this element.
	 *
	 * Mainly useful for tracing purposes.
	 * @public
	 * @return {string} a string description of this element
	 */
	Element.prototype.toString = function() {
		return "Element " + this.getMetadata().getName() + "#" + this.sId;
	};


	/**
	 * Returns the best suitable DOM Element that represents this UI5 Element.
	 * By default the DOM Element with the same ID as this Element is returned.
	 * Subclasses should override this method if the lookup via id is not sufficient.
	 *
	 * Note that such a DOM Element does not necessarily exist in all cases.
	 * Some elements or controls might not have a DOM representation at all (e.g.
	 * a naive FlowLayout) while others might not have one due to their current
	 * state (e.g. an initial, not yet rendered control).
	 *
	 * If an ID suffix is given, the ID of this Element is concatenated with the suffix
	 * (separated by a single dash) and the DOM node with that compound ID will be returned.
	 * This matches the UI5 naming convention for named inner DOM nodes of a control.
	 *
	 * @param {string} [sSuffix] ID suffix to get the DOMRef for
	 * @return {Element} The Element's DOM Element sub DOM Element or null
	 * @protected
	 */
	Element.prototype.getDomRef = function(sSuffix) {
		return document.getElementById(sSuffix ? this.getId() + "-" + sSuffix : this.getId());
	};

	/**
	 * Returns the best suitable DOM node that represents this Element wrapped as jQuery object.
	 * I.e. the element returned by {@link sap.ui.core.Element#getDomRef} is wrapped and returned.
	 *
	 * If an ID suffix is given, the ID of this Element is concatenated with the suffix
	 * (separated by a single dash) and the DOM node with that compound ID will be wrapped by jQuery.
	 * This matches the UI5 naming convention for named inner DOM nodes of a control.
	 *
	 * @param {string} [sSuffix] ID suffix to get a jQuery object for
	 * @return {jQuery} The jQuery wrapped element's DOM reference
	 * @protected
	 */

	Element.prototype.$ = function(sSuffix) {
		return jQuery(this.getDomRef(sSuffix));
	};

	/**
	 * Checks whether this element has an active parent.
	 *
	 * @type boolean
	 * @return true if this element has an active parent
	 * @private
	 */
	Element.prototype.isActive = function() {
		return this.oParent && this.oParent.isActive();
	};

	/**
	 * This function either calls set[sPropertyName] or get[sPropertyName] with the specified property name
	 * depending if an <code>oValue</code> is provided or not.
	 *
	 * @param {string}  sPropertyName name of the property to set
	 * @param {any}     [oValue] value to set the property to
	 * @return {any|sap.ui.core.Element} Returns <code>this</code> to allow method chaining in case of setter and the property value in case of getter
	 * @public
	 * @deprecated Since 1.28.0 The contract of this method is not fully defined and its write capabilities overlap with applySettings
	 */
	Element.prototype.prop = function(sPropertyName, oValue) {

		var oPropertyInfo = this.getMetadata().getAllSettings()[sPropertyName];
		if (oPropertyInfo) {
			if (arguments.length == 1) {
				// getter
				return this[oPropertyInfo._sGetter]();
			} else {
				// setter
				this[oPropertyInfo._sMutator](oValue);
				return this;
			}
		}
	};

	Element.prototype.insertDependent = function(oElement, iIndex) {
		this.insertAggregation("dependents", oElement, iIndex, true);
		return this; // explicitly return 'this' to fix controls that override insertAggregation wrongly
	};

	Element.prototype.addDependent = function(oElement) {
		this.addAggregation("dependents", oElement, true);
		return this; // explicitly return 'this' to fix controls that override addAggregation wrongly
	};

	Element.prototype.removeDependent = function(vElement) {
		return this.removeAggregation("dependents", vElement, true);
	};

	Element.prototype.removeAllDependents = function() {
		return this.removeAllAggregation("dependents", true);
	};

	Element.prototype.destroyDependents = function() {
		this.destroyAggregation("dependents", true);
		return this; // explicitly return 'this' to fix controls that override destroyAggregation wrongly
	};


	/// cyclic dependency
	//jQuery.sap.require("sap.ui.core.TooltipBase"); /// cyclic dependency


	/**
	 * This triggers immediate rerendering of its parent and thus of itself and its children.
	 *
	 * As <code>sap.ui.core.Element</code> "bubbles up" the rerender, changes to
	 * child-<code>Elements</code> will also result in immediate rerendering of the whole sub tree.
	 * @protected
	 */
	Element.prototype.rerender = function() {
		if (this.oParent) {
			this.oParent.rerender();
		}
	};


	/**
	 * Returns the UI area of this element, if any.
	 *
	 * @return {sap.ui.core.UIArea} The UI area of this element or null
	 * @private
	 */
	Element.prototype.getUIArea = function() {
		return this.oParent ? this.oParent.getUIArea() : null;
	};

	/**
	 * Cleans up the resources associated with this element and all its children.
	 *
	 * After an element has been destroyed, it can no longer be used in the UI!
	 *
	 * Applications should call this method if they don't need the element any longer.
	 *
	 * @param {boolean}
	 *            [bSuppressInvalidate] if true, the UI element is removed from DOM synchronously and parent will not be invalidated.
	 * @public
	 */
	Element.prototype.destroy = function(bSuppressInvalidate) {
		// ignore repeated calls
		if (this.bIsDestroyed) {
			return;
		}

		// determine whether parent exists or not
		var bHasNoParent = !this.getParent();

		// update the focus information (potentially) stored by the central UI5 focus handling
		Element._updateFocusInfo(this);

		ManagedObject.prototype.destroy.call(this, bSuppressInvalidate);

		// wrap custom data API to avoid creating new objects
		this.data = noCustomDataAfterDestroy;

		// exit early if there is no control DOM to remove
		var oDomRef = this.getDomRef();
		if (!oDomRef) {
			return;
		}

		// Determine whether to remove the control DOM from the DOM Tree or not:
		// If parent invalidation is not possible, either bSuppressInvalidate=true or there is no parent to invalidate then we must remove the control DOM synchronously.
		// Controls that implement marker interface sap.ui.core.PopupInterface are by contract not rendered by their parent so we cannot keep the DOM of these controls.
		// If the control is destroyed while its content is in the preserved area then we must remove DOM synchronously since we cannot invalidate the preserved area.
		var bKeepDom = (bSuppressInvalidate === "KeepDom");
		if (bSuppressInvalidate === true || (!bKeepDom && bHasNoParent) || this.isA("sap.ui.core.PopupInterface") || RenderManager.isPreservedContent(oDomRef)) {
			jQuery(oDomRef).remove();
		} else {
			// Make sure that the control DOM won't get preserved after it is destroyed (even if bSuppressInvalidate="KeepDom")
			oDomRef.removeAttribute("data-sap-ui-preserve");
			if (!bKeepDom) {
				// On destroy we do not remove the control DOM synchronously and just let the invalidation happen on the parent.
				// At the next tick of the RenderManager, control DOM nodes will be removed via rerendering of the parent anyway.
				// To make this new behavior more compatible we are changing the id of the control's DOM and all child nodes that start with the control id.
				oDomRef.id = "sap-ui-destroyed-" + this.getId();
				for (var i = 0, aDomRefs = oDomRef.querySelectorAll('[id^="' + this.getId() + '-"]'); i < aDomRefs.length; i++) {
					aDomRefs[i].id = "sap-ui-destroyed-" + aDomRefs[i].id;
				}
			}
		}
	};

	/*
	 * Class <code>sap.ui.core.Element</code> intercepts fireEvent calls to enforce an 'id' property
	 * and to notify others like interaction detection etc.
	 */
	Element.prototype.fireEvent = function(sEventId, mParameters, bAllowPreventDefault, bEnableEventBubbling) {
		if (this.hasListeners(sEventId)) {
			Interaction.notifyStepStart(this);
		}

		// get optional parameters right
		if (typeof mParameters === 'boolean') {
			bEnableEventBubbling = bAllowPreventDefault;
			bAllowPreventDefault = mParameters;
			mParameters = null;
		}

		mParameters = mParameters || {};
		mParameters.id = mParameters.id || this.getId();

		if (Element._interceptEvent) {
			Element._interceptEvent(sEventId, this, mParameters);
		}

		return ManagedObject.prototype.fireEvent.call(this, sEventId, mParameters, bAllowPreventDefault, bEnableEventBubbling);
	};

	/**
	 * Intercepts an event. This method is meant for private usages. Apps are not supposed to used it.
	 * It is created for an experimental purpose.
	 * Implementation should be injected by outside.
	 *
	 * @param {string} sEventId the name of the event
	 * @param {sap.ui.core.Element} oElement the element itself
	 * @param {object} mParameters The parameters which complement the event. Hooks must not modify the parameters.
	 * @function
	 * @private
	 * @ui5-restricted
	 * @experimental Since 1.58
	 */
	Element._interceptEvent = undefined;

	/**
	 * Adds a delegate that listens to the events of this element.
	 *
	 * Note that the default behavior (delegate attachments are not cloned when a control is cloned) is usually the desired behavior in control development
	 * where each control instance typically creates a delegate and adds it to itself. (As opposed to application development where the application may add
	 * one delegate to a template and then expects aggregation binding to add the same delegate to all cloned elements.)
	 *
	 * To avoid double registrations, all registrations of the given delegate are first removed and then the delegate is added.
	 *
	 * @param {object} oDelegate the delegate object
	 * @param {boolean} [bCallBefore=false] if true, the delegate event listeners are called before the event listeners of the element; default is "false". In order to also set bClone, this parameter must be given.
	 * @param {object} [oThis=oDelegate] if given, this object will be the "this" context in the listener methods; default is the delegate object itself
	 * @param {boolean} [bClone=false] if true, this delegate will also be attached to any clones of this element; default is "false"
	 * @return {sap.ui.core.Element} Returns <code>this</code> to allow method chaining
	 * @private
	 */
	Element.prototype.addDelegate = function (oDelegate, bCallBefore, oThis, bClone) {
		assert(oDelegate, "oDelegate must be not null or undefined");

		if (!oDelegate) {
			return this;
		}

		this.removeDelegate(oDelegate);

		// shift parameters
		if (typeof bCallBefore === "object") {
			bClone = oThis;
			oThis = bCallBefore;
			bCallBefore = false;
		}

		if (typeof oThis === "boolean") {
			bClone = oThis;
			oThis = undefined;
		}

		(bCallBefore ? this.aBeforeDelegates : this.aDelegates).push({oDelegate:oDelegate, bClone: !!bClone, vThis: ((oThis === this) ? true : oThis)}); // special case: if this element is the given context, set a flag, so this also works after cloning (it should be the cloned element then, not the given one)
		return this;
	};

	/**
	 * Removes the given delegate from this element.
	 *
	 * This method will remove all registrations of the given delegate, not only one.
	 * If the delegate was marked to be cloned and this element has been cloned, the delegate will not be removed from any clones.
	 *
	 * @param {object} oDelegate the delegate object
	 * @return {sap.ui.core.Element} Returns <code>this</code> to allow method chaining
	 * @private
	 */
	Element.prototype.removeDelegate = function (oDelegate) {
		var i;
		for (i = 0; i < this.aDelegates.length; i++) {
			if (this.aDelegates[i].oDelegate == oDelegate) {
				this.aDelegates.splice(i, 1);
				i--; // One element removed means the next element now has the index of the current one
			}
		}
		for (i = 0; i < this.aBeforeDelegates.length; i++) {
			if (this.aBeforeDelegates[i].oDelegate == oDelegate) {
				this.aBeforeDelegates.splice(i, 1);
				i--; // One element removed means the next element now has the index of the current one
			}
		}
		return this;
	};


	/**
	 * Adds a delegate that can listen to the browser-, pseudo- and framework events that are handled by this
	 * <code>Element</code> (as opposed to events which are fired by this <code>Element</code>).
	 *
	 * Delegates are simple objects that can have an arbitrary number of event handler methods. See the section
	 * "Handling of Events" in the {@link #constructor} documentation to learn how events will be dispatched
	 * and how event handler methods have to be named to be found.
	 *
	 * If multiple delegates are registered for the same element, they will be called in the order of their
	 * registration. Double registrations are prevented. Before a delegate is added, all registrations of the same
	 * delegate (no matter what value for <code>oThis</code> was used for their registration) are removed and only
	 * then the delegate is added. Note that this might change the position of the delegate in the list of delegates.
	 *
	 * When an element is cloned, all its event delegates will be added to the clone. This behavior is well-suited
	 * for applications which want to add delegates that also work with templates in aggregation bindings.
	 * For control development, the internal <code>addDelegate</code> method may be more suitable. Delegates added
	 * via that method are not cloned automatically, as typically each control instance takes care of adding its
	 * own delegates.
	 *
	 * <strong>Important:</strong> If event delegates were added, the delegate will still be called even if
	 * the event was processed and/or cancelled via <code>preventDefault</code> by the Element or another event delegate.
	 * <code>preventDefault</code> only prevents the event from bubbling.
	 * It should be checked e.g. in the event delegate's listener whether an Element is still enabled via <code>getEnabled</code>.
	 * Additionally there might be other things that delegates need to check depending on the event
	 * (e.g. not adding a key twice to an output string etc.).
	 *
	 * See {@link topic:bdf3e9818cd84d37a18ee5680e97e1c1 Event Handler Methods} for a general explanation of
	 * event handling in controls.
	 *
	 * @example <caption>Adding a delegate for the keydown and afterRendering event</caption>
	 * <pre>
	 * var oDelegate = {
	 *   onkeydown: function(){
	 *     // Act when the keydown event is fired on the element
	 *   },
	 *   onAfterRendering: function(){
	 *     // Act when the afterRendering event is fired on the element
	 *   }
	 * };
	 * oElement.addEventDelegate(oDelegate);
	 * </pre>
	 *
	 * @param {object} oDelegate The delegate object which consists of the event handler names and the corresponding event handler functions
	 * @param {object} [oThis=oDelegate] If given, this object will be the "this" context in the listener methods; default is the delegate object itself
	 * @returns {sap.ui.core.Element} Returns <code>this</code> to allow method chaining
	 * @since 1.9.0
	 * @public
	 */
	Element.prototype.addEventDelegate = function (oDelegate, oThis) {
		return this.addDelegate(oDelegate, false, oThis, true);
	};

	/**
	 * Removes the given delegate from this element.
	 *
	 * This method will remove all registrations of the given delegate, not only one.
	 *
	 * @example <caption>Removing a delegate for the keydown and afterRendering event. The delegate object which was used when adding the event delegate</caption>
	 * <pre>
	 * var oDelegate = {
	 *   onkeydown: function(){
	 *     // Act when the keydown event is fired on the element
	 *   },
	 *   onAfterRendering: function(){
	 *     // Act when the afterRendering event is fired on the element
	 *   }
	 * };
	 * oElement.removeEventDelegate(oDelegate);
	 * </pre>
	 * @param {object} oDelegate The delegate object which consists of the event handler names and the corresponding event handler functions
	 * @return {sap.ui.core.Element} Returns <code>this</code> to allow method chaining
	 * @since 1.9.0
	 * @public
	 */
	Element.prototype.removeEventDelegate = function (oDelegate) {
		return this.removeDelegate(oDelegate);
	};

	/**
	 * Returns the DOM Element that should get the focus.
	 *
	 * To be overwritten by the specific control method.
	 *
	 * @return {Element} Returns the DOM Element that should get the focus
	 * @protected
	 */
	Element.prototype.getFocusDomRef = function () {
		return this.getDomRef() || null;
	};

	function getAncestorScrollPositions(oDomRef) {
		var oParentDomRef,
			aScrollHierarchy = [];

		oParentDomRef = oDomRef.parentNode;
		while (oParentDomRef) {
			aScrollHierarchy.push({
				node: oParentDomRef,
				scrollLeft: oParentDomRef.scrollLeft,
				scrollTop: oParentDomRef.scrollTop
			});
			oParentDomRef = oParentDomRef.parentNode;
		}

		return aScrollHierarchy;
	}

	function restoreScrollPositions(aScrollHierarchy) {
		aScrollHierarchy.forEach(function(oScrollInfo) {
			var oDomRef = oScrollInfo.node;

			if (oDomRef.scrollLeft !== oScrollInfo.scrollLeft) {
				oDomRef.scrollLeft = oScrollInfo.scrollLeft;
			}

			if (oDomRef.scrollTop !== oScrollInfo.scrollTop) {
				oDomRef.scrollTop = oScrollInfo.scrollTop;
			}
		});
	}

	/**
	 * Sets the focus to the stored focus DOM reference
	 *
	 * @param {object} oFocusInfo
	 * @param {boolean} [oFocusInfo.preventScroll=false] @since 1.60 if it's set to true, the focused
	 *   element won't be shifted into the viewport if it's not completely visible before the focus is set
	 * @public
	 */
	Element.prototype.focus = function (oFocusInfo) {
		var oFocusDomRef = this.getFocusDomRef(),
			aScrollHierarchy = [];

		oFocusInfo = oFocusInfo || {};

		if (oFocusDomRef) {
			// save the scroll position of all ancestor DOM elements
			// before the focus is set, because preventScroll is not supported by the following browsers
			if (Device.browser.safari || Device.browser.msie || Device.browser.edge) {
				if (oFocusInfo.preventScroll === true) {
					aScrollHierarchy = getAncestorScrollPositions(oFocusDomRef);
				}
				oFocusDomRef.focus();
				if (aScrollHierarchy.length > 0) {
					// restore the scroll position if it's changed after setting focus
					// Safari, IE11 and Edge need a little delay to get the scroll position updated
					setTimeout(restoreScrollPositions.bind(null, aScrollHierarchy), 0);
				}
			} else if (oFocusInfo.preventScroll === true) {
				oFocusDomRef.focus(oFocusInfo);
			} else {
				oFocusDomRef.focus();<commit_msg>[INTERNAL] Revert "[FIX] core/Element: Focus shouldn't be called with empty object"<commit_after>/*!
 * ${copyright}
 */

// Provides the base class for all controls and UI elements.
sap.ui.define([
	'../base/DataType',
	'../base/Object',
	'../base/ManagedObject',
	'../base/ManagedObjectRegistry',
	'./ElementMetadata',
	'../Device',
	"sap/ui/performance/trace/Interaction",
	"sap/base/Log",
	"sap/base/assert",
	"sap/ui/thirdparty/jquery",
	"sap/ui/events/F6Navigation",
	"./RenderManager"
],
	function(
		DataType,
		BaseObject,
		ManagedObject,
		ManagedObjectRegistry,
		ElementMetadata,
		Device,
		Interaction,
		Log,
		assert,
		jQuery,
		F6Navigation,
		RenderManager
	) {
	"use strict";

	/**
	 * Constructs and initializes a UI Element with the given <code>sId</code> and settings.
	 *
	 *
	 * <h3>Uniqueness of IDs</h3>
	 *
	 * Each <code>Element</code> must have an ID. If no <code>sId</code> or <code>mSettings.id</code> is
	 * given at construction time, a new ID will be created automatically. The IDs of all elements that exist
	 * at the same time in the same window must be different. Providing an ID which is already used by another
	 * element throws an error.
	 *
	 * When an element is created from a declarative source (e.g. XMLView), then an ID defined in that
	 * declarative source needs to be unique only within the declarative source. Declarative views will
	 * prefix that ID with their own ID (and some separator) before constructing the element.
	 * Programmatically created views (JSViews) can do the same with the {@link sap.ui.core.mvc.View#createId} API.
	 * Similarly, UIComponents can prefix the IDs of elements created in their context with their own ID.
	 * Also see {@link sap.ui.core.UIComponent#getAutoPrefixId UIComponent#getAutoPrefixId}.
	 *
	 *
	 * <h3>Settings</h3>
	 * If the optional <code>mSettings</code> are given, they must be a JSON-like object (object literal)
	 * that defines values for properties, aggregations, associations or events keyed by their name.
	 *
	 * <b>Valid Names:</b>
	 *
	 * The property (key) names supported in the object literal are exactly the (case sensitive)
	 * names documented in the JSDoc for the properties, aggregations, associations and events
	 * of the control and its base classes. Note that for  0..n aggregations and associations this
	 * usually is the plural name, whereas it is the singular name in case of 0..1 relations.
	 *
	 * Each subclass should document the set of supported names in its constructor documentation.
	 *
	 * <b>Valid Values:</b>
	 *
	 * <ul>
	 * <li>for normal properties, the value has to be of the correct simple type (no type conversion occurs)</li>
	 * <li>for 0..1 aggregations, the value has to be an instance of the aggregated control or element type</li>
	 * <li>for 0..n aggregations, the value has to be an array of instances of the aggregated type</li>
	 * <li>for 0..1 associations, an instance of the associated type or an id (string) is accepted</li>
	 * <li>0..n associations are not supported yet</li>
	 * <li>for events either a function (event handler) is accepted or an array of length 2
	 *     where the first element is a function and the 2nd element is an object to invoke the method on.</li>
	 * </ul>
	 *
	 * Special aggregation <code>dependents</code> is connected to the lifecycle management and databinding,
	 * but not rendered automatically and can be used for popups or other dependent controls or elements.
	 * This allows the definition of popup controls in declarative views and enables propagation of model
	 * and context information to them.
	 *
	 * @param {string} [sId] id for the new control; generated automatically if no non-empty id is given
	 *      Note: this can be omitted, no matter whether <code>mSettings</code> will be given or not!
	 * @param {object} [mSettings] optional map/JSON-object with initial property values, aggregated objects etc. for the new element
	 *
	 * @abstract
	 *
	 * @class Base Class for UI Elements.
	 *
	 * <code>Element</code> is the most basic building block for UI5 UIs. An <code>Element</code> has state like a
	 * <code>ManagedObject</code>, it has a unique ID by which the framework remembers it. It can have associated
	 * DOM, but it can't render itself. Only {@link sap.ui.core.Control Controls} can render themselves and also
	 * take care of rendering <code>Elements</code> that they aggregate as children. If an <code>Element</code>
	 * has been rendered, its related DOM gets the same ID as the <code>Element</code> and thereby can be retrieved
	 * via API. When the state of an <code>Element</code> changes, it informs its parent <code>Control</code> which
	 * usually re-renders then.
	 *
	 * <h3>Dispatching Events</h3>
	 *
	 * The UI5 framework already registers generic listeners for common browser events, such as <code>click</code>
	 * or <code>keydown</code>. When called, the generic listener first determines the corresponding target element
	 * using {@link jQuery#control}. Then it checks whether the element has an event handler method for the event.
	 * An event handler method by convention has the same name as the event, but prefixed with "on": Method
	 * <code>onclick</code> is the handler for the <code>click</code> event, method <code>onkeydown</code> the handler
	 * for the <code>keydown</code> event and so on. If there is such a method, it will be called with the original
	 * event as the only parameter. If the element has a list of delegates registered, their handler functions will
	 * be called the same way, where present. The set of implemented handlers might differ between element and
	 * delegates. Not each handler implemented by an element has to be implemented by its delegates, and delegates
	 * can implement handlers that the corresponding element doesn't implement.
	 *
	 * A list of browser events that are handled that way can be found in {@link module:sap/ui/events/ControlEvents}.
	 * Additionally, the framework dispatches pseudo events ({@link module:sap/ui/events/PseudoEvents}) using the same
	 * naming convention. Last but not least, some framework events are also dispatched that way, e.g.
	 * <code>BeforeRendering</code>, <code>AfterRendering</code> (only for controls) and <code>ThemeChanged</code>.
	 *
	 * If further browser events are needed, controls can register listeners on the DOM using native APIs in their
	 * <code>onAfterRendering</code> handler. If needed, they can do this for their aggregated elements as well.
	 * If events might fire often (e.g. <code>mousemove</code>), it is best practice to register them only while
	 * needed, and deregister afterwards. Anyhow, any registered listeners must be cleaned up in the
	 * <code>onBeforeRendering</code> listener and before destruction in the <code>exit</code> hook.
	 *
	 * @extends sap.ui.base.ManagedObject
	 * @author SAP SE
	 * @version ${version}
	 * @public
	 * @alias sap.ui.core.Element
	 * @ui5-metamodel This control/element also will be described in the UI5 (legacy) designtime metamodel
	 */
	var Element = ManagedObject.extend("sap.ui.core.Element", {

		metadata : {
			stereotype : "element",
			"abstract" : true,
			publicMethods : [ "getId", "getMetadata", "getTooltip_AsString", "getTooltip_Text", "getModel", "setModel", "hasModel", "bindElement", "unbindElement", "getElementBinding", "prop", "getLayoutData", "setLayoutData" ],
			library : "sap.ui.core",
			aggregations : {

				/**
				 * The tooltip that should be shown for this Element.
				 *
				 * In the most simple case, a tooltip is a string that will be rendered by the control and
				 * displayed by the browser when the mouse pointer hovers over the control's DOM. In this
				 * variant, <code>tooltip</code> behaves like a simple control property.
				 *
				 * Controls need to explicitly support this kind of tooltip as they have to render it,
				 * but most controls do. Exceptions will be documented for the corresponding controls
				 * (e.g. <code>sap.ui.core.HTML</code> does not support tooltips).
				 *
				 * Alternatively, <code>tooltip</code> can act like a 0..1 aggregation and can be set to a
				 * tooltip control (an instance of a subclass of <code>sap.ui.core.TooltipBase</code>). In
				 * that case, the framework will take care of rendering the tooltip control in a popup-like
				 * manner. Such a tooltip control can display arbitrary content, not only a string.
				 *
				 * UI5 currently does not provide a recommended implementation of <code>TooltipBase</code>
				 * as the use of content-rich tooltips is discouraged by the Fiori Design Guidelines.
				 * Existing subclasses of <code>TooltipBase</code> therefore have been deprecated.
				 * However, apps can still subclass from <code>TooltipBase</code> and create their own
				 * implementation when needed (potentially taking the deprecated implementations as a
				 * starting point).
				 *
				 * See the section {@link https://experience.sap.com/fiori-design-web/using-tooltips/ Using Tooltips}
				 * in the Fiori Design Guideline.
				 */
				tooltip : {name : "tooltip", type : "sap.ui.core.TooltipBase", altTypes : ["string"], multiple : false},

				/**
				 * Custom Data, a data structure like a map containing arbitrary key value pairs.
				 */
				customData : {name : "customData", type : "sap.ui.core.CustomData", multiple : true, singularName : "customData"},

				/**
				 * Defines the layout constraints for this control when it is used inside a Layout.
				 * LayoutData classes are typed classes and must match the embedding Layout.
				 * See VariantLayoutData for aggregating multiple alternative LayoutData instances to a single Element.
				 */
				layoutData : {name : "layoutData", type : "sap.ui.core.LayoutData", multiple : false, singularName : "layoutData"},

				/**
				 * Dependents are not rendered, but their databinding context and lifecycle are bound to the aggregating Element.
				 * @since 1.19
				 */
				dependents : {name : "dependents", type : "sap.ui.core.Element", multiple : true},

				/**
				 * Defines the drag-and-drop configuration.
				 * <b>Note:</b> This configuration might be ignored due to control {@link sap.ui.core.Element.extend metadata} restrictions.
				 *
				 * @since 1.56
				 */
				dragDropConfig : {name : "dragDropConfig", type : "sap.ui.core.dnd.DragDropBase", multiple : true, singularName : "dragDropConfig"}
			}
		},

		constructor : function(sId, mSettings) {
			ManagedObject.apply(this, arguments);
		},

		renderer : null // Element has no renderer

	}, /* Metadata constructor */ ElementMetadata);

	// apply the registry mixin
	ManagedObjectRegistry.apply(Element, {
		onDuplicate: function(sId, oldElement, newElement) {
			if ( oldElement._sapui_candidateForDestroy ) {
				Log.debug("destroying dangling template " + oldElement + " when creating new object with same ID");
				oldElement.destroy();
			} else {
				var sMsg = "adding element with duplicate id '" + sId + "'";
				// duplicate ID detected => fail or at least log a warning
				if (sap.ui.getCore().getConfiguration().getNoDuplicateIds()) {
					Log.error(sMsg);
					throw new Error("Error: " + sMsg);
				} else {
					Log.warning(sMsg);
				}
			}
		}
	});

	/**
	 * Creates metadata for a UI Element by extending the Object Metadata.
	 *
	 * @param {string} sClassName name of the class to build the metadata for
	 * @param {object} oStaticInfo static information used to build the metadata
	 * @param {function} [fnMetaImpl=sap.ui.core.ElementMetadata] constructor to be used for the metadata
	 * @return {sap.ui.core.ElementMetadata} the created metadata
	 * @static
	 * @public
	 * @deprecated Since 1.3.1. Use the static <code>extend</code> method of the desired base class (e.g. {@link sap.ui.core.Element.extend})
	 */
	Element.defineClass = function(sClassName, oStaticInfo, fnMetaImpl) {
		// create and attach metadata but with an Element specific implementation
		return BaseObject.defineClass(sClassName, oStaticInfo, fnMetaImpl || ElementMetadata);
	};

	/**
	 * @see sap.ui.base.Object#getInterface
	 * @public
	 */
	Element.prototype.getInterface = function() {
		return this;
	};

	/**
	 * Defines a new subclass of Element with the name <code>sClassName</code> and enriches it with
	 * the information contained in <code>oClassInfo</code>.
	 *
	 * <code>oClassInfo</code> can contain the same information that {@link sap.ui.base.ManagedObject.extend} already accepts,
	 * plus the following <code>dnd</code> property to configure drag-and-drop behavior in the metadata object literal:
	 *
	 * Example:
	 * <pre>
	 * Element.extend('sap.mylib.MyElement', {
	 *   metadata : {
	 *     library : 'sap.mylib',
	 *     properties : {
	 *       value : 'string',
	 *       width : 'sap.ui.core.CSSSize'
	 *     },
	 *     dnd : { draggable: true, droppable: false },
	 *     aggregations : {
	 *       items : { type: 'sap.ui.core.Control', multiple : true, dnd : {draggable: false, dropppable: true, layout: "Horizontal" } },
	 *       header : {type : "sap.ui.core.Control", multiple : false, dnd : true },
	 *     }
	 *   }
	 * });
	 * </pre>
	 *
	 * <h3><code>dnd</code> key as a metadata property</h3>
	 *
	 * <b>dnd</b>: <i>object|boolean</i><br>
	 * Defines draggable and droppable configuration of the element.
	 * The following keys can be provided via <code>dnd</code> object literal to configure drag-and-drop behavior of the element:
	 * <ul>
	 *  <li><code>[draggable=false]: <i>boolean</i></code> Defines whether the element is draggable or not. The default value is <code>false</code>.</li>
	 *  <li><code>[droppable=false]: <i>boolean</i></code> Defines whether the element is droppable (it allows being dropped on by a draggable element) or not. The default value is <code>false</code>.</li>
	 * </ul>
	 * If <code>dnd</code> property is of type Boolean, then the <code>draggable</code> and <code>droppable</code> configuration are set to this Boolean value.
	 *
	 * <h3><code>dnd</code> key as an aggregation metadata property</h3>
	 *
	 * <b>dnd</b>: <i>object|boolean</i><br>
	 * In addition to draggable and droppable configuration, the layout of the aggregation can be defined as a hint at the drop position indicator.
	 * <ul>
	 *  <li><code>[layout="Vertical"]: </code> The arrangement of the items in this aggregation. This setting is recommended for the aggregation with multiplicity 0..n (<code>multiple: true</code>). Possible values are <code>Vertical</code> (e.g. rows in a table) and <code>Horizontal</code> (e.g. columns in a table). It is recommended to use <code>Horizontal</code> layout if the arrangement is multidimensional.</li>
	 * </ul>
	 *
	 * @param {string} sClassName fully qualified name of the class that is described by this metadata object
	 * @param {object} oStaticInfo static info to construct the metadata from
	 * @returns {function} Created class / constructor function
	 *
	 * @public
	 * @static
	 * @name sap.ui.core.Element.extend
	 * @function
	 */

	/**
	 * Dispatches the given event, usually a browser event or a UI5 pseudo event.
	 * @private
	 */
	Element.prototype._handleEvent = function (oEvent) {

		var that = this,
			sHandlerName = "on" + oEvent.type;

		function each(aDelegates) {
			var i,l,oDelegate;
			if ( aDelegates && (l = aDelegates.length) > 0 ) {
				// To be robust against concurrent modifications of the delegates list, we loop over a copy.
				// When there is only a single entry, the loop is safe without a copy (length is determined only once!)
				aDelegates = l === 1 ? aDelegates : aDelegates.slice();
				for (i = 0; i < l; i++ ) {
					if (oEvent.isImmediateHandlerPropagationStopped()) {
						return;
					}
					oDelegate = aDelegates[i].oDelegate;
					if (oDelegate[sHandlerName]) {
						oDelegate[sHandlerName].call(aDelegates[i].vThis === true ? that : aDelegates[i].vThis || oDelegate, oEvent);
					}
				}
			}
		}

		each(this.aBeforeDelegates);
		if ( oEvent.isImmediateHandlerPropagationStopped() ) {
			return;
		}
		if ( this[sHandlerName] ) {
			this[sHandlerName](oEvent);
		}
		each(this.aDelegates);

	};


	/**
	 * Initializes the element instance after creation.
	 *
	 * Applications must not call this hook method directly, it is called by the framework
	 * while the constructor of an element is executed.
	 *
	 * Subclasses of Element should override this hook to implement any necessary initialization.
	 *
	 * @protected
	 */
	Element.prototype.init = function() {
		// Before adding any implementation, please remember that this method was first implemented in release 1.54.
		// Therefore, many subclasses will not call this method at all.
	};

	/**
	 * Hook method for cleaning up the element instance before destruction.
	 *
	 * Applications must not call this hook method directly, it is called by the framework
	 * when the element is {@link #destroy destroyed}.
	 *
	 * Subclasses of Element should override this hook to implement any necessary cleanup.
	 *
	 * <pre>
	 * exit: function() {
	 *     // ... do any further cleanups of your subclass e.g. detach events...
	 *     this.$().off("click", this.handleClick);
	 *
	 *     if (Element.prototype.exit) {
	 *         Element.prototype.exit.apply(this, arguments);
	 *     }
	 * }
	 * </pre>
	 *
	 * For a more detailed description how to to use the exit hook, see Section
	 * {@link topic:d4ac0edbc467483585d0c53a282505a5 exit() Method} in the documentation.
	 *
	 * @protected
	 */
	Element.prototype.exit = function() {
		// Before adding any implementation, please remember that this method was first implemented in release 1.54.
		// Therefore, many subclasses will not call this method at all.
	};

	/**
	 * Creates a new Element from the given data.
	 *
	 * If <code>vData</code> is an Element already, that element is returned.
	 * If <code>vData</code> is an object (literal), then a new element is created with <code>vData</code> as settings.
	 * The type of the element is either determined by a property named <code>Type</code> in the <code>vData</code> or
	 * by a type information in the <code>oKeyInfo</code> object
	 * @param {sap.ui.core.Element|object} vData Data to create the element from
	 * @param {object} [oKeyInfo] An entity information (e.g. aggregation info)
	 * @param {string} [oKeyInfo.type] Type info for the entity
	 * @public
	 * @static
	 * @deprecated As of 1.44, use the more flexible {@link sap.ui.base.ManagedObject.create}.
	 * @function
	 */
	Element.create = ManagedObject.create;

	/**
	 * Returns a simple string representation of this element.
	 *
	 * Mainly useful for tracing purposes.
	 * @public
	 * @return {string} a string description of this element
	 */
	Element.prototype.toString = function() {
		return "Element " + this.getMetadata().getName() + "#" + this.sId;
	};


	/**
	 * Returns the best suitable DOM Element that represents this UI5 Element.
	 * By default the DOM Element with the same ID as this Element is returned.
	 * Subclasses should override this method if the lookup via id is not sufficient.
	 *
	 * Note that such a DOM Element does not necessarily exist in all cases.
	 * Some elements or controls might not have a DOM representation at all (e.g.
	 * a naive FlowLayout) while others might not have one due to their current
	 * state (e.g. an initial, not yet rendered control).
	 *
	 * If an ID suffix is given, the ID of this Element is concatenated with the suffix
	 * (separated by a single dash) and the DOM node with that compound ID will be returned.
	 * This matches the UI5 naming convention for named inner DOM nodes of a control.
	 *
	 * @param {string} [sSuffix] ID suffix to get the DOMRef for
	 * @return {Element} The Element's DOM Element sub DOM Element or null
	 * @protected
	 */
	Element.prototype.getDomRef = function(sSuffix) {
		return document.getElementById(sSuffix ? this.getId() + "-" + sSuffix : this.getId());
	};

	/**
	 * Returns the best suitable DOM node that represents this Element wrapped as jQuery object.
	 * I.e. the element returned by {@link sap.ui.core.Element#getDomRef} is wrapped and returned.
	 *
	 * If an ID suffix is given, the ID of this Element is concatenated with the suffix
	 * (separated by a single dash) and the DOM node with that compound ID will be wrapped by jQuery.
	 * This matches the UI5 naming convention for named inner DOM nodes of a control.
	 *
	 * @param {string} [sSuffix] ID suffix to get a jQuery object for
	 * @return {jQuery} The jQuery wrapped element's DOM reference
	 * @protected
	 */

	Element.prototype.$ = function(sSuffix) {
		return jQuery(this.getDomRef(sSuffix));
	};

	/**
	 * Checks whether this element has an active parent.
	 *
	 * @type boolean
	 * @return true if this element has an active parent
	 * @private
	 */
	Element.prototype.isActive = function() {
		return this.oParent && this.oParent.isActive();
	};

	/**
	 * This function either calls set[sPropertyName] or get[sPropertyName] with the specified property name
	 * depending if an <code>oValue</code> is provided or not.
	 *
	 * @param {string}  sPropertyName name of the property to set
	 * @param {any}     [oValue] value to set the property to
	 * @return {any|sap.ui.core.Element} Returns <code>this</code> to allow method chaining in case of setter and the property value in case of getter
	 * @public
	 * @deprecated Since 1.28.0 The contract of this method is not fully defined and its write capabilities overlap with applySettings
	 */
	Element.prototype.prop = function(sPropertyName, oValue) {

		var oPropertyInfo = this.getMetadata().getAllSettings()[sPropertyName];
		if (oPropertyInfo) {
			if (arguments.length == 1) {
				// getter
				return this[oPropertyInfo._sGetter]();
			} else {
				// setter
				this[oPropertyInfo._sMutator](oValue);
				return this;
			}
		}
	};

	Element.prototype.insertDependent = function(oElement, iIndex) {
		this.insertAggregation("dependents", oElement, iIndex, true);
		return this; // explicitly return 'this' to fix controls that override insertAggregation wrongly
	};

	Element.prototype.addDependent = function(oElement) {
		this.addAggregation("dependents", oElement, true);
		return this; // explicitly return 'this' to fix controls that override addAggregation wrongly
	};

	Element.prototype.removeDependent = function(vElement) {
		return this.removeAggregation("dependents", vElement, true);
	};

	Element.prototype.removeAllDependents = function() {
		return this.removeAllAggregation("dependents", true);
	};

	Element.prototype.destroyDependents = function() {
		this.destroyAggregation("dependents", true);
		return this; // explicitly return 'this' to fix controls that override destroyAggregation wrongly
	};


	/// cyclic dependency
	//jQuery.sap.require("sap.ui.core.TooltipBase"); /// cyclic dependency


	/**
	 * This triggers immediate rerendering of its parent and thus of itself and its children.
	 *
	 * As <code>sap.ui.core.Element</code> "bubbles up" the rerender, changes to
	 * child-<code>Elements</code> will also result in immediate rerendering of the whole sub tree.
	 * @protected
	 */
	Element.prototype.rerender = function() {
		if (this.oParent) {
			this.oParent.rerender();
		}
	};


	/**
	 * Returns the UI area of this element, if any.
	 *
	 * @return {sap.ui.core.UIArea} The UI area of this element or null
	 * @private
	 */
	Element.prototype.getUIArea = function() {
		return this.oParent ? this.oParent.getUIArea() : null;
	};

	/**
	 * Cleans up the resources associated with this element and all its children.
	 *
	 * After an element has been destroyed, it can no longer be used in the UI!
	 *
	 * Applications should call this method if they don't need the element any longer.
	 *
	 * @param {boolean}
	 *            [bSuppressInvalidate] if true, the UI element is removed from DOM synchronously and parent will not be invalidated.
	 * @public
	 */
	Element.prototype.destroy = function(bSuppressInvalidate) {
		// ignore repeated calls
		if (this.bIsDestroyed) {
			return;
		}

		// determine whether parent exists or not
		var bHasNoParent = !this.getParent();

		// update the focus information (potentially) stored by the central UI5 focus handling
		Element._updateFocusInfo(this);

		ManagedObject.prototype.destroy.call(this, bSuppressInvalidate);

		// wrap custom data API to avoid creating new objects
		this.data = noCustomDataAfterDestroy;

		// exit early if there is no control DOM to remove
		var oDomRef = this.getDomRef();
		if (!oDomRef) {
			return;
		}

		// Determine whether to remove the control DOM from the DOM Tree or not:
		// If parent invalidation is not possible, either bSuppressInvalidate=true or there is no parent to invalidate then we must remove the control DOM synchronously.
		// Controls that implement marker interface sap.ui.core.PopupInterface are by contract not rendered by their parent so we cannot keep the DOM of these controls.
		// If the control is destroyed while its content is in the preserved area then we must remove DOM synchronously since we cannot invalidate the preserved area.
		var bKeepDom = (bSuppressInvalidate === "KeepDom");
		if (bSuppressInvalidate === true || (!bKeepDom && bHasNoParent) || this.isA("sap.ui.core.PopupInterface") || RenderManager.isPreservedContent(oDomRef)) {
			jQuery(oDomRef).remove();
		} else {
			// Make sure that the control DOM won't get preserved after it is destroyed (even if bSuppressInvalidate="KeepDom")
			oDomRef.removeAttribute("data-sap-ui-preserve");
			if (!bKeepDom) {
				// On destroy we do not remove the control DOM synchronously and just let the invalidation happen on the parent.
				// At the next tick of the RenderManager, control DOM nodes will be removed via rerendering of the parent anyway.
				// To make this new behavior more compatible we are changing the id of the control's DOM and all child nodes that start with the control id.
				oDomRef.id = "sap-ui-destroyed-" + this.getId();
				for (var i = 0, aDomRefs = oDomRef.querySelectorAll('[id^="' + this.getId() + '-"]'); i < aDomRefs.length; i++) {
					aDomRefs[i].id = "sap-ui-destroyed-" + aDomRefs[i].id;
				}
			}
		}
	};

	/*
	 * Class <code>sap.ui.core.Element</code> intercepts fireEvent calls to enforce an 'id' property
	 * and to notify others like interaction detection etc.
	 */
	Element.prototype.fireEvent = function(sEventId, mParameters, bAllowPreventDefault, bEnableEventBubbling) {
		if (this.hasListeners(sEventId)) {
			Interaction.notifyStepStart(this);
		}

		// get optional parameters right
		if (typeof mParameters === 'boolean') {
			bEnableEventBubbling = bAllowPreventDefault;
			bAllowPreventDefault = mParameters;
			mParameters = null;
		}

		mParameters = mParameters || {};
		mParameters.id = mParameters.id || this.getId();

		if (Element._interceptEvent) {
			Element._interceptEvent(sEventId, this, mParameters);
		}

		return ManagedObject.prototype.fireEvent.call(this, sEventId, mParameters, bAllowPreventDefault, bEnableEventBubbling);
	};

	/**
	 * Intercepts an event. This method is meant for private usages. Apps are not supposed to used it.
	 * It is created for an experimental purpose.
	 * Implementation should be injected by outside.
	 *
	 * @param {string} sEventId the name of the event
	 * @param {sap.ui.core.Element} oElement the element itself
	 * @param {object} mParameters The parameters which complement the event. Hooks must not modify the parameters.
	 * @function
	 * @private
	 * @ui5-restricted
	 * @experimental Since 1.58
	 */
	Element._interceptEvent = undefined;

	/**
	 * Adds a delegate that listens to the events of this element.
	 *
	 * Note that the default behavior (delegate attachments are not cloned when a control is cloned) is usually the desired behavior in control development
	 * where each control instance typically creates a delegate and adds it to itself. (As opposed to application development where the application may add
	 * one delegate to a template and then expects aggregation binding to add the same delegate to all cloned elements.)
	 *
	 * To avoid double registrations, all registrations of the given delegate are first removed and then the delegate is added.
	 *
	 * @param {object} oDelegate the delegate object
	 * @param {boolean} [bCallBefore=false] if true, the delegate event listeners are called before the event listeners of the element; default is "false". In order to also set bClone, this parameter must be given.
	 * @param {object} [oThis=oDelegate] if given, this object will be the "this" context in the listener methods; default is the delegate object itself
	 * @param {boolean} [bClone=false] if true, this delegate will also be attached to any clones of this element; default is "false"
	 * @return {sap.ui.core.Element} Returns <code>this</code> to allow method chaining
	 * @private
	 */
	Element.prototype.addDelegate = function (oDelegate, bCallBefore, oThis, bClone) {
		assert(oDelegate, "oDelegate must be not null or undefined");

		if (!oDelegate) {
			return this;
		}

		this.removeDelegate(oDelegate);

		// shift parameters
		if (typeof bCallBefore === "object") {
			bClone = oThis;
			oThis = bCallBefore;
			bCallBefore = false;
		}

		if (typeof oThis === "boolean") {
			bClone = oThis;
			oThis = undefined;
		}

		(bCallBefore ? this.aBeforeDelegates : this.aDelegates).push({oDelegate:oDelegate, bClone: !!bClone, vThis: ((oThis === this) ? true : oThis)}); // special case: if this element is the given context, set a flag, so this also works after cloning (it should be the cloned element then, not the given one)
		return this;
	};

	/**
	 * Removes the given delegate from this element.
	 *
	 * This method will remove all registrations of the given delegate, not only one.
	 * If the delegate was marked to be cloned and this element has been cloned, the delegate will not be removed from any clones.
	 *
	 * @param {object} oDelegate the delegate object
	 * @return {sap.ui.core.Element} Returns <code>this</code> to allow method chaining
	 * @private
	 */
	Element.prototype.removeDelegate = function (oDelegate) {
		var i;
		for (i = 0; i < this.aDelegates.length; i++) {
			if (this.aDelegates[i].oDelegate == oDelegate) {
				this.aDelegates.splice(i, 1);
				i--; // One element removed means the next element now has the index of the current one
			}
		}
		for (i = 0; i < this.aBeforeDelegates.length; i++) {
			if (this.aBeforeDelegates[i].oDelegate == oDelegate) {
				this.aBeforeDelegates.splice(i, 1);
				i--; // One element removed means the next element now has the index of the current one
			}
		}
		return this;
	};


	/**
	 * Adds a delegate that can listen to the browser-, pseudo- and framework events that are handled by this
	 * <code>Element</code> (as opposed to events which are fired by this <code>Element</code>).
	 *
	 * Delegates are simple objects that can have an arbitrary number of event handler methods. See the section
	 * "Handling of Events" in the {@link #constructor} documentation to learn how events will be dispatched
	 * and how event handler methods have to be named to be found.
	 *
	 * If multiple delegates are registered for the same element, they will be called in the order of their
	 * registration. Double registrations are prevented. Before a delegate is added, all registrations of the same
	 * delegate (no matter what value for <code>oThis</code> was used for their registration) are removed and only
	 * then the delegate is added. Note that this might change the position of the delegate in the list of delegates.
	 *
	 * When an element is cloned, all its event delegates will be added to the clone. This behavior is well-suited
	 * for applications which want to add delegates that also work with templates in aggregation bindings.
	 * For control development, the internal <code>addDelegate</code> method may be more suitable. Delegates added
	 * via that method are not cloned automatically, as typically each control instance takes care of adding its
	 * own delegates.
	 *
	 * <strong>Important:</strong> If event delegates were added, the delegate will still be called even if
	 * the event was processed and/or cancelled via <code>preventDefault</code> by the Element or another event delegate.
	 * <code>preventDefault</code> only prevents the event from bubbling.
	 * It should be checked e.g. in the event delegate's listener whether an Element is still enabled via <code>getEnabled</code>.
	 * Additionally there might be other things that delegates need to check depending on the event
	 * (e.g. not adding a key twice to an output string etc.).
	 *
	 * See {@link topic:bdf3e9818cd84d37a18ee5680e97e1c1 Event Handler Methods} for a general explanation of
	 * event handling in controls.
	 *
	 * @example <caption>Adding a delegate for the keydown and afterRendering event</caption>
	 * <pre>
	 * var oDelegate = {
	 *   onkeydown: function(){
	 *     // Act when the keydown event is fired on the element
	 *   },
	 *   onAfterRendering: function(){
	 *     // Act when the afterRendering event is fired on the element
	 *   }
	 * };
	 * oElement.addEventDelegate(oDelegate);
	 * </pre>
	 *
	 * @param {object} oDelegate The delegate object which consists of the event handler names and the corresponding event handler functions
	 * @param {object} [oThis=oDelegate] If given, this object will be the "this" context in the listener methods; default is the delegate object itself
	 * @returns {sap.ui.core.Element} Returns <code>this</code> to allow method chaining
	 * @since 1.9.0
	 * @public
	 */
	Element.prototype.addEventDelegate = function (oDelegate, oThis) {
		return this.addDelegate(oDelegate, false, oThis, true);
	};

	/**
	 * Removes the given delegate from this element.
	 *
	 * This method will remove all registrations of the given delegate, not only one.
	 *
	 * @example <caption>Removing a delegate for the keydown and afterRendering event. The delegate object which was used when adding the event delegate</caption>
	 * <pre>
	 * var oDelegate = {
	 *   onkeydown: function(){
	 *     // Act when the keydown event is fired on the element
	 *   },
	 *   onAfterRendering: function(){
	 *     // Act when the afterRendering event is fired on the element
	 *   }
	 * };
	 * oElement.removeEventDelegate(oDelegate);
	 * </pre>
	 * @param {object} oDelegate The delegate object which consists of the event handler names and the corresponding event handler functions
	 * @return {sap.ui.core.Element} Returns <code>this</code> to allow method chaining
	 * @since 1.9.0
	 * @public
	 */
	Element.prototype.removeEventDelegate = function (oDelegate) {
		return this.removeDelegate(oDelegate);
	};

	/**
	 * Returns the DOM Element that should get the focus.
	 *
	 * To be overwritten by the specific control method.
	 *
	 * @return {Element} Returns the DOM Element that should get the focus
	 * @protected
	 */
	Element.prototype.getFocusDomRef = function () {
		return this.getDomRef() || null;
	};

	function getAncestorScrollPositions(oDomRef) {
		var oParentDomRef,
			aScrollHierarchy = [];

		oParentDomRef = oDomRef.parentNode;
		while (oParentDomRef) {
			aScrollHierarchy.push({
				node: oParentDomRef,
				scrollLeft: oParentDomRef.scrollLeft,
				scrollTop: oParentDomRef.scrollTop
			});
			oParentDomRef = oParentDomRef.parentNode;
		}

		return aScrollHierarchy;
	}

	function restoreScrollPositions(aScrollHierarchy) {
		aScrollHierarchy.forEach(function(oScrollInfo) {
			var oDomRef = oScrollInfo.node;

			if (oDomRef.scrollLeft !== oScrollInfo.scrollLeft) {
				oDomRef.scrollLeft = oScrollInfo.scrollLeft;
			}

			if (oDomRef.scrollTop !== oScrollInfo.scrollTop) {
				oDomRef.scrollTop = oScrollInfo.scrollTop;
			}
		});
	}

	/**
	 * Sets the focus to the stored focus DOM reference
	 *
	 * @param {object} oFocusInfo
	 * @param {boolean} [oFocusInfo.preventScroll=false] @since 1.60 if it's set to true, the focused
	 *   element won't be shifted into the viewport if it's not completely visible before the focus is set
	 * @public
	 */
	Element.prototype.focus = function (oFocusInfo) {
		var oFocusDomRef = this.getFocusDomRef(),
			aScrollHierarchy = [];

		oFocusInfo = oFocusInfo || {};

		if (oFocusDomRef) {
			// save the scroll position of all ancestor DOM elements
			// before the focus is set, because preventScroll is not supported by the following browsers
			if (Device.browser.safari || Device.browser.msie || Device.browser.edge) {
				if (oFocusInfo.preventScroll === true) {
					aScrollHierarchy = getAncestorScrollPositions(oFocusDomRef);
				}
				oFocusDomRef.focus();
				if (aScrollHierarchy.length > 0) {
					// restore the scroll position if it's changed after setting focus
					// Safari, IE11 and Edge need a little delay to get the scroll position updated
					setTimeout(restoreScrollPositions.bind(null, aScrollHierarchy), 0);
				}
			} else {
				oFocusDomRef.focus(oFocusInfo);
{'fraction_non_alphanumeric': 0.09794982429003676, 'fraction_numerical': 0.0033649475583777694, 'mean_word_length': 3.650848741086641, 'pattern_counts': {'":': 2, '<': 455, '<?xml version=': 0, '>': 453, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4321580', 'n_tokens_mistral': 22619, 'n_tokens_neox': 20284, 'n_words': 8294}