text: /*!
   * UI development toolkit for HTML5 (OpenUI5)
   * (c) Copyright 2009-2018 SAP SE or an SAP affiliate company.
   * Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
   */
  
  // Provides control sap.m.Text
  sap.ui.define([
  	'./library',
  	'sap/ui/core/Control',
  	'sap/ui/core/library',
  	'sap/ui/Device',
  	'./TextRenderer'
  ],
  	function(library, Control, coreLibrary, Device, TextRenderer) {
  	"use strict";
  
  	// shortcut for sap.ui.core.TextAlign
  	var TextAlign = coreLibrary.TextAlign;
  
  	// shortcut for sap.ui.core.TextDirection
  	var TextDirection = coreLibrary.TextDirection;
  
  	/**
  	 * Constructor for a new Text.
  	 *
  	 * @param {string} [sId] ID for the new control, generated automatically if no ID is given
  	 * @param {object} [mSettings] Initial settings for the new control
  	 *
  	 * @class
  	 * The <code>Text</code> control can be used for embedding longer text paragraphs, that need text wrapping, into your app.
  	 * If the configured text value contains HTML code or script tags, those will be escaped.<br>
  	 * <b>Note: </b>Line breaks will always be visualized except when the <code>wrapping</code> property is set to <code>false</code>. In addition, tabs and whitespace can be preserved by setting the <code>renderWhitespace</code> property to <code>true</code>
  	 * @extends sap.ui.core.Control
  	 * @implements sap.ui.core.IShrinkable, sap.ui.core.IFormContent
  	 *
  	 * @author SAP SE
  	 * @version 1.54.6
  	 *
  	 * @constructor
  	 * @public
  	 * @alias sap.m.Text
  	 * @ui5-metamodel This control/element also will be described in the UI5 (legacy) designtime metamodel
  	 */
  	var Text = Control.extend("sap.m.Text", /** @lends sap.m.Text.prototype */ { metadata : {
  
  		interfaces : [
  			"sap.ui.core.IShrinkable",
  			"sap.ui.core.IFormContent"
  		],
  		library : "sap.m",
  		properties : {
  
  			/**
  			 * Determines the text to be displayed.
  			 */
  			text : {type : "string", defaultValue : '', bindable : "bindable"},
  
  			/**
  			 * Available options for the text direction are LTR and RTL. By default the control inherits the text direction from its parent control.
  			 */
  			textDirection : {type : "sap.ui.core.TextDirection", group : "Appearance", defaultValue : TextDirection.Inherit},
  
  			/**
  			 * Enables text wrapping.
  			 */
  			wrapping : {type : "boolean", group : "Appearance", defaultValue : true},
  
  			/**
  			 * Sets the horizontal alignment of the text.
  			 */
  			textAlign : {type : "sap.ui.core.TextAlign", group : "Appearance", defaultValue : TextAlign.Begin},
  
  			/**
  			 * Sets the width of the Text control. By default, the Text control uses the full width available. Set this property to restrict the width to a custom value.
  			 */
  			width : {type : "sap.ui.core.CSSSize", group : "Dimension", defaultValue : null},
  
  			/**
  			 * Limits the number of lines for wrapping texts.
  			 *
  			 * <b>Note</b>: The multi-line overflow indicator depends on the browser line clamping support. For such browsers, this will be shown as ellipsis, for the other browsers the overflow will just be hidden.
  			 * @since 1.13.2
  			 */
  			maxLines : {type : "int", group : "Appearance", defaultValue : null},
  
  			/**
  			 * Specifies how whitespace and tabs inside the control are handled. If true, whitespace will be preserved by the browser.
  			 * Depending on wrapping property text will either only wrap on line breaks or wrap when necessary, and on line breaks.
  			 *
  			 * @since 1.51
  			 */
  			renderWhitespace : {type : "boolean", group : "Appearance", defaultValue : false}
  
  		},
  		designtime: "sap/m/designtime/Text.designtime"
  	}});
  
  	/**
  	 * Default line height value as a number when line height is normal.
  	 *
  	 * This value is required during max height calculation for the browsers that do not support line clamping.
  	 * It is better to define line height in CSS instead of "normal" to get consistent <code>maxLines</code> results since normal line height
  	 * not only varies from browser to browser but it also varies from one font face to another and can also vary within a given face.
  	 *
  	 * @since 1.22
  	 * @protected
  	 * @type {int}
  	 */
  	Text.prototype.normalLineHeight = 1.2;
  
  	/**
  	 * Determines per instance whether line height should be cached or not.
  	 *
  	 * Default value is true.
  	 *
  	 * @since 1.22
  	 * @protected
  	 * @type {boolean}
  	 */
  	Text.prototype.cacheLineHeight = true;
  
  	/**
  	 * Ellipsis(...) text to indicate more text when clampText function is used.
  	 *
  	 * Can be overwritten with 3dots(...) if fonts do not support this UTF-8 character.
  	 *
  	 * @since 1.13.2
  	 * @protected
  	 * @type {string}
  	 */
  	Text.prototype.ellipsis = '...';
  
  	/**
  	 * Defines whether browser supports native line clamp or not and if browser is Chrome
  	 *
  	 * @since 1.13.2
  	 * @returns {boolean}
  	 * @protected
  	 * @readonly
  	 * @static
  	 */
  	Text.hasNativeLineClamp = (function() {
  		return typeof document.documentElement.style.webkitLineClamp != "undefined" && Device.browser.chrome;
  	})();
  
  	/**
  	 * To prevent from the layout thrashing of the <code>textContent</code> call, this method
  	 * first tries to set the <code>nodeValue</code> of the first child if it exists.
  	 *
  	 * @name sap.m.Text.setNodeValue
  	 * @method
  	 * @protected
  	 * @static
  	 * @param {HTMLElement} oDomRef DOM reference of the text node container.
  	 * @param {String} [sNodeValue] new Node value.
  	 * @since 1.30.3
  	 */
  	Text.setNodeValue = function(oDomRef, sNodeValue) {
  		sNodeValue = sNodeValue || "";
  		var aChildNodes = oDomRef.childNodes;
  		if (aChildNodes.length === 1 && aChildNodes[0].nodeType === window.Node.TEXT_NODE) {
  			aChildNodes[0].nodeValue = sNodeValue;
  		} else {
  			oDomRef.textContent = sNodeValue;
  		}
  	};
  
  	/**
  	 * Sets the text.
  	 *
  	 * @name sap.m.Text.setText
  	 * @method
  	 * @public
  	 * @param {string} sText Text value.
  	 * @returns {sap.m.Text} this Text reference for chaining.
  	 */
  	Text.prototype.setText = function(sText) {
  		// suppress invalidation of text property setter
  		this.setProperty("text", sText , true);
  
  		// check text dom ref
  		var oDomRef = this.getTextDomRef();
  		if (oDomRef) {
  			// update the node value of the DOM text
  			Text.setNodeValue(oDomRef, this.getText(true));
  
  			// toggles the sapMTextBreakWord class when the text value is changed
  			if (this.getWrapping()) {
  				// no space text must break
  				if (sText && !/\s/.test(sText)) {
  					this.$().addClass("sapMTextBreakWord");
  				} else {
  					this.$().removeClass("sapMTextBreakWord");
  				}
  			}
  		}
  
  		return this;
  	};
  
  	/**
  	 * Gets the text.
  	 *
  	 * @name sap.m.Text.getText
  	 * @method
  	 * @public
  	 * @param {boolean} bNormalize Indication for normalized text.
  	 * @returns {string} Text value.
  	 */
  	Text.prototype.getText = function(bNormalize) {
  		// returns the text value and normalize line-ending character for rendering
  		var sText = this.getProperty("text");
  
  		// handle line ending characters for renderer
  		if (bNormalize) {
  			return sText.replace(/\r\n|\n\r|\r/g, "\n");
  		}
  
  		return sText;
  	};
  
  	/**
  	 * Overwrites onAfterRendering
  	 *
  	 * @name sap.m.Text.onAfterRendering
  	 * @method
  	 * @public
  	 */
  	Text.prototype.onAfterRendering = function() {
  		// required adaptations after rendering
  		// check visible, max-lines and line-clamping support
  		if (this.getVisible() &&
  			this.hasMaxLines() &&
  			!this.canUseNativeLineClamp()) {
  
  			// set max-height for maxLines support
  			this.clampHeight();
  		}
  	};
  
  	/**
  	 * Determines whether max lines should be rendered or not.
  	 *
  	 * @name sap.m.Text.hasMaxLines
  	 * @method
  	 * @protected
  	 * @returns {HTMLElement|null} Max lines of the text.
  	 * @since 1.22
  	 */
  	Text.prototype.hasMaxLines = function() {
  		return (this.getWrapping() && this.getMaxLines() > 1);
  	};
  
  	/**
  	 * Returns the text node container's DOM reference.
  	 * This can be different from <code>getDomRef</code> when inner wrapper is needed.
  	 *
  	 * @name sap.m.Text.getTextDomRef
  	 * @method
  	 * @protected
  	 * @returns {HTMLElement|null} DOM reference of the text.
  	 * @since 1.22
  	 */
  	Text.prototype.getTextDomRef = function() {
  		if (!this.getVisible()) {
  			return null;
  		}
  
  		if (this.hasMaxLines()) {
  			return this.getDomRef("inner");
  		}
  
  		return this.getDomRef();
  	};
  
  	/**
  	 * Decides whether the control can use native line clamp feature or not.
  	 *
  	 * In RTL mode native line clamp feature is not supported.
  	 *
  	 * @since 1.20
  	 * @protected
  	 * @return {Boolean}
  	 */
  	Text.prototype.canUseNativeLineClamp = function() {
  		// has line clamp feature
  		if (!Text.hasNativeLineClamp) {
  			return false;
  		}
  
  		// is text direction rtl
  		if (this.getTextDirection() == TextDirection.RTL) {
  			return false;
  		}
  
  		// is text direction inherited as rtl
  		if (this.getTextDirection() == TextDirection.Inherit && sap.ui.getCore().getConfiguration().getRTL()) {
  			return false;
  		}
  
  		return true;
  	};
  
  	/**
  	 * Caches and returns the computed line height of the text.
  	 *
  	 * @name sap.m.Text.getLineHeight
  	 * @method
  	 * @protected
  	 * @param {HTMLElement} [oDomRef] DOM reference of the text container.
  	 * @returns {int} returns calculated line height
  	 * @see sap.m.Text#cacheLineHeight
  	 * @since 1.22
  	 */
  	Text.prototype.getLineHeight = function(oDomRef) {
  		// return cached value if possible and available
  		if (this.cacheLineHeight && this._fLineHeight) {
  			return this._fLineHeight;
  		}
  
  		// check whether dom ref exist or not
  		oDomRef = oDomRef || this.getTextDomRef();
  		if (!oDomRef) {
  			return 0;
  		}
  
  		// check line-height
  		var oStyle = window.getComputedStyle(oDomRef),
  			sLineHeight = oStyle.lineHeight,
  			fLineHeight;
  
  		// calculate line-height in px
  		if (/px$/i.test(sLineHeight)) {
  			// we can rely on calculated px line-height value
  			fLineHeight = parseFloat(sLineHeight);
  		} else if (/^normal$/i.test(sLineHeight)) {
  			// use default value to calculate normal line-height
  			fLineHeight = parseFloat(oStyle.fontSize) * this.normalLineHeight;
  		} else {
  			// calculate line-height with using font-size and line-height
  			fLineHeight = parseFloat(oStyle.fontSize) * parseFloat(sLineHeight);
  		}
  
  		// on rasterizing the font, sub pixel line-heights are converted to integer
  		// for most of the font rendering engine but this is not the case for firefox
  		if (!Device.browser.firefox) {
  			fLineHeight = Math.floor(fLineHeight);
  		}
  
  		// cache line height
  		if (this.cacheLineHeight && fLineHeight) {
  			this._fLineHeight = fLineHeight;
  		}
  
  		// return
  		return fLineHeight;
  	};
  
  	/**
  	 * Returns the max height according to max lines and line height calculation.
  	 * This is not calculated max height!
  	 *
  	 * @name sap.m.Text.getClampHeight
  	 * @method
  	 * @protected
  	 * @param {HTMLElement} [oDomRef] DOM reference of the text container.
  	 * @returns {int} The clamp height of the text.
  	 * @since 1.22
  	 */
  	Text.prototype.getClampHeight = function(oDomRef) {
  		oDomRef = oDomRef || this.getTextDomRef();
  		return this.getMaxLines() * this.getLineHeight(oDomRef);
  	};
  
  	/**
  	 * Sets the max height to support <code>maxLines</code> property.
  	 *
  	 * @name sap.m.Text.clampHeight
  	 * @method
  	 * @protected
  	 * @param {HTMLElement} [oDomRef] DOM reference of the text container.
  	 * @returns {int} Calculated max height value.
  	 * @since 1.22
  	 */
  	Text.prototype.clampHeight = function(oDomRef) {
  		oDomRef = oDomRef || this.getTextDomRef();
  		if (!oDomRef) {
  			return 0;
  		}
  
  		// calc the max height and set on dom
  		var iMaxHeight = this.getClampHeight(oDomRef);
  		if (iMaxHeight) {
  			oDomRef.style.maxHeight = iMaxHeight + "px";
  		}
  
  		return iMaxHeight;
  	};
  
  	/**
  	 * Clamps the wrapping text according to max lines and returns the found ellipsis position.
  	 * Parameters can be used for better performance.
  	 *
  	 * @name sap.m.Text.clampText
  	 * @method
  	 * @protected
  	 * @param {HTMLElement} [oDomRef] DOM reference of the text container.
  	 * @param {int} [iStartPos] Start point of the ellipsis search.
  	 * @param {int} [iEndPos] End point of the ellipsis search.
  	 * @returns {int|undefined} Returns found ellipsis position or undefined.
  	 * @since 1.20
  	 */
  	Text.prototype.clampText = function(oDomRef, iStartPos, iEndPos) {
  		// check DOM reference
  		oDomRef = oDomRef || this.getTextDomRef();
  		if (!oDomRef) {
  			return;
  		}
  
  		// init
  		var iEllipsisPos;
  		var sText = this.getText(true);
  		var iMaxHeight = this.getClampHeight(oDomRef);
  
  		// init positions
  		iStartPos = iStartPos || 0;
  		iEndPos = iEndPos || sText.length;
  
  		// update only the node value without layout thrashing
  		Text.setNodeValue(oDomRef, sText.slice(0, iEndPos));
  
  		// if text overflow
  		if (oDomRef.scrollHeight > iMaxHeight) {
  
  			// cache values
  			var oStyle = oDomRef.style,
  				sHeight = oStyle.height,
  				sEllipsis = this.ellipsis,
  				iEllipsisLen = sEllipsis.length;
  
  			// set height during ellipsis search
  			oStyle.height = iMaxHeight + "px";
  
  			// implementing binary search to find the position of ellipsis
  			// complexity O(logn) so 1024 characters text can be found within 10 steps!
  			while ((iEndPos - iStartPos) > iEllipsisLen) {
  
  				// check the middle position and update text
  				iEllipsisPos = (iStartPos + iEndPos) >> 1;
  
  				// update only the node value without layout thrashing
  				Text.setNodeValue(oDomRef, sText.slice(0, iEllipsisPos - iEllipsisLen) + sEllipsis);
  
  				// check overflow
  				if (oDomRef.scrollHeight > iMaxHeight) {
  					iEndPos = iEllipsisPos;
  				} else {
  					iStartPos = iEllipsisPos;
  				}
  			}
  
  			// last check maybe we overflowed on last character
  			if (oDomRef.scrollHeight > iMaxHeight && iStartPos > 0) {
  				iEllipsisPos = iStartPos;
  				oDomRef.textContent = sText.slice(0, iEllipsisPos - iEllipsisLen) + sEllipsis;
  			}
  
  			// reset height
  			oStyle.height = sHeight;
  		}
  
  		// return the found position
  		return iEllipsisPos;
  	};
  
  	/**
  	 * Gets the accessibility information for the text.
  	 *
  	 * @name sap.m.Text.getAccessibilityInfo
  	 * @method
  	 * @protected
  	 * @returns {object} Accessibility information for the text.
  	 * @see sap.ui.core.Control#getAccessibilityInfo
  	 */
  	Text.prototype.getAccessibilityInfo = function() {
  		return {description: this.getText()};
  	};
  
  	return Text;
  
  });
  