'use strict';

Liferay.Loader.define("frontend-taglib-clay$clay-tooltip@2.24.1/lib/ClayTooltip", ['module', 'exports', 'require', 'frontend-taglib-clay$clay-component', 'frontend-js-metal-web$metal-soy', 'frontend-js-metal-web$metal-position', 'frontend-js-metal-web$metal-state', 'frontend-js-metal-web$metal-events', 'frontend-js-metal-web$metal', 'frontend-js-metal-web$metal-dom', './ClayTooltip.soy'], function (module, exports, require) {
	var define = undefined;
	var global = window;
	{
		Object.defineProperty(exports, "__esModule", {
			value: true
		});
		exports.ClayTooltip = undefined;

		var _createClass = function () {
			function defineProperties(target, props) {
				for (var i = 0; i < props.length; i++) {
					var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);
				}
			}return function (Constructor, protoProps, staticProps) {
				if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;
			};
		}();

		var _clayComponent = require("frontend-taglib-clay$clay-component");

		var _clayComponent2 = _interopRequireDefault(_clayComponent);

		var _metalSoy = require("frontend-js-metal-web$metal-soy");

		var _metalSoy2 = _interopRequireDefault(_metalSoy);

		var _metalPosition = require("frontend-js-metal-web$metal-position");

		var _metalState = require("frontend-js-metal-web$metal-state");

		var _metalEvents = require("frontend-js-metal-web$metal-events");

		var _metal = require("frontend-js-metal-web$metal");

		var _metalDom = require("frontend-js-metal-web$metal-dom");

		var _ClayTooltipSoy = require("./ClayTooltip.soy");

		var _ClayTooltipSoy2 = _interopRequireDefault(_ClayTooltipSoy);

		function _interopRequireDefault(obj) {
			return obj && obj.__esModule ? obj : { default: obj };
		}

		function _defineProperty(obj, key, value) {
			if (key in obj) {
				Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true });
			} else {
				obj[key] = value;
			}return obj;
		}

		function _possibleConstructorReturn(self, call) {
			if (!self) {
				throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
			}return call && (typeof call === "object" || typeof call === "function") ? call : self;
		}

		function _inherits(subClass, superClass) {
			if (typeof superClass !== "function" && superClass !== null) {
				throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
			}subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
		}

		function _classCallCheck(instance, Constructor) {
			if (!(instance instanceof Constructor)) {
				throw new TypeError("Cannot call a class as a function");
			}
		}

		/**
   * Singleton enforcer class
   */
		var SingletonEnforcer = function SingletonEnforcer() {
			_classCallCheck(this, SingletonEnforcer);
		};

		/**
   * Implementation of ClayTooltip.
   * @extends ClayComponent
   */

		var ClayTooltip = function (_ClayComponent) {
			_inherits(ClayTooltip, _ClayComponent);

			/**
    * @inheritDoc
    */
			function ClayTooltip(enforcer, config, parentElement) {
				_classCallCheck(this, ClayTooltip);

				if (!enforcer) {
					throw new Error('Use ClayTooltip.init to initialize ClayTooltip');
				}

				var _this = _possibleConstructorReturn(this, (ClayTooltip.__proto__ || Object.getPrototypeOf(ClayTooltip)).call(this, config, parentElement));

				_this._timer = undefined;
				return _this;
			}

			/**
    * Returns the instance for this ClayTooltip.
    * @memberof ClayTooltip
    * @param {Object=} config An object with the initial values for this
    *                         component's state.
    * @param {boolean|string|Element=} parentElement The element where the
    * component should be rendered. Can be given as a selector or an element.
    * If `false` is passed, the component won't be rendered automatically
    * after created.
    * @static
    * @return {ClayTooltip}
    */

			_createClass(ClayTooltip, [{
				key: 'created',

				/**
     * @inheritDoc
     */
				value: function created() {
					this._eventHandler = new _metalEvents.EventHandler();
				}

				/**
     * @inheritDoc
     */

			}, {
				key: 'attached',
				value: function attached() {
					this.addListener('transitionend', this._handleTransitionEnd, true);

					if (!this.visible) {
						this.element.style.display = 'none';
					}
				}

				/**
     * @inheritDoc
     */

			}, {
				key: 'rendered',
				value: function rendered() {
					if (this._target) {
						var alignedPosition = _metalPosition.Align.align(this.element, this._target, this.position, this.bestAlign);

						if (this.alignedPosition !== alignedPosition) {
							this.alignedPosition = alignedPosition;
						}
					}
				}

				/**
     * @inheritDoc
     */

			}, {
				key: 'detached',
				value: function detached() {
					this._eventHandler.removeAllListeners();
				}

				/**
     * @inheritDoc
     */

			}, {
				key: 'disposed',
				value: function disposed() {
					this._eventHandler.removeAllListeners();
				}

				/**
     * Handles mouseenter event.
     * @memberof ClayTooltip
     * @param {!Element} element
     * @return {!String}
     * @private
     */

			}, {
				key: '_getContent',
				value: function _getContent(element) {
					var titleAttribute = element.getAttribute('title');

					if (titleAttribute) {
						element.setAttribute('data-title', titleAttribute);
						element.setAttribute('data-restore-title', 'true');
						element.removeAttribute('title');
					} else if (element.tagName === 'svg') {
						var titleTag = element.querySelector('title');

						if (titleTag) {
							element.setAttribute('data-title', titleTag.innerHTML);
							element.setAttribute('data-restore-title', 'true');
							titleTag.remove();
						}
					}

					return element.getAttribute('data-title');
				}

				/**
     * Handles click event.
     * @memberof ClayTooltip
     * @param {!Event} event
     * @private
     */

			}, {
				key: '_handleMouseClick',
				value: function _handleMouseClick(event) {
					this._restoreTitle(event.delegateTarget);

					this._isTransitioning = true;
					this.visible = false;
				}

				/**
     * Handles mouseenter event.
     * @memberof ClayTooltip
     * @param {!Event} event
     * @private
     */

			}, {
				key: '_handleMouseEnter',
				value: function _handleMouseEnter(event) {
					this._showTooltip(event.delegateTarget);
				}

				/**
     * Handles tooltip element mouseenter event.
     * @memberof ClayTooltip
     * @private
     */

			}, {
				key: '_handleMouseEnterTooltip',
				value: function _handleMouseEnterTooltip() {
					if (this._isTransitioning) {
						this.visible = true;
					}
				}

				/**
     * Handles mouseleave events.
     * @memberof ClayTooltip
     * @param {!Event} event
     * @private
     */

			}, {
				key: '_handleMouseLeave',
				value: function _handleMouseLeave(event) {
					this._hideTooltip(event.delegateTarget);
				}

				/**
     * Handles touchstart events.
     * @memberof ClayTooltip
     * @param {!Event} event
     * @private
     */

			}, {
				key: '_handleTouchStart',
				value: function _handleTouchStart(event) {
					var _this2 = this;

					this._timer = setTimeout(function () {
						_this2._showTooltip(event.srcElement);
						clearTimeout(_this2._timer);
					}, 500);
				}

				/**
     * Handle touchend events.
     * @memberof ClayTooltip
     * @param {!Event} event
     * @private
     */

			}, {
				key: '_handleTouchEnd',
				value: function _handleTouchEnd(event) {
					this._hideTooltip(event.srcElement);
				}

				/**
     * Handles transitionend event.
     * @memberof ClayTooltip
     * @private
     */

			}, {
				key: '_handleTransitionEnd',
				value: function _handleTransitionEnd() {
					this._isTransitioning = false;

					if (!this.visible) {
						this.element.style.display = 'none';
					}
				}

				/**
     * Hides the tooltip on the given element.
     * @param {!Element} element
     * @private
     */

			}, {
				key: '_hideTooltip',
				value: function _hideTooltip(element) {
					if (this._timer) {
						clearTimeout(this._timer);
						this._timer = undefined;
					}
					if (this.visible) {
						this._restoreTitle(element);

						this._isTransitioning = true;
						this.visible = false;
					}
				}

				/**
     * Restores the title attribute to an element
     * @memberof ClayTooltip
     * @param {Element} element
     * @private
     */

			}, {
				key: '_restoreTitle',
				value: function _restoreTitle(element) {
					var title = element.getAttribute('data-title');
					var restoreTitle = element.getAttribute('data-restore-title');

					if (title && restoreTitle === 'true') {
						if (element.tagName === 'svg') {
							var titleTag = document.createElement('title');
							titleTag.innerHTML = title;

							element.appendChild(titleTag);
						} else {
							element.setAttribute('title', title);
						}

						element.removeAttribute('data-restore-title');
					}
				}

				/**
     * Set preferred alignment with Align API.
     * @private
     * @param {!string} value
     * @return {number}
     */

			}, {
				key: '_setPreferredAlign',
				value: function _setPreferredAlign(value) {
					switch (value) {
						case 'TopCenter':
							return _metalPosition.Align.TopCenter;
						case 'RightCenter':
							return _metalPosition.Align.RightCenter;
						case 'BottomCenter':
							return _metalPosition.Align.BottomCenter;
						case 'LeftCenter':
							return _metalPosition.Align.LeftCenter;
						case 'TopRight':
							return _metalPosition.Align.TopRight;
						case 'BottomRight':
							return _metalPosition.Align.BottomRight;
						case 'BottomLeft':
							return _metalPosition.Align.BottomLeft;
						case 'TopLeft':
							return _metalPosition.Align.TopLeft;
						default:
							return _metalPosition.Align.TopCenter;
					}
				}

				/**
     * The setter function for the `classMap` state.
     * @memberof ClayTooltip
     * @param {Object} val
     * @return {!Object}
     * @private
     */

			}, {
				key: 'setterClassMapFn_',
				value: function setterClassMapFn_(val) {
					return _metal.object.mixin(this.valueClassMapFn_(), val);
				}

				/**
     * Shows the tooltip on a given element.
     * @memberof ClayTooltip
     * @param {!Element} target
     * @private
     */

			}, {
				key: '_showTooltip',
				value: function _showTooltip(target) {
					var content = this._getContent(target);
					this._target = target;

					this._content = content;

					if (!this.visible) {
						this.element.style.display = 'block';
					}
					this._isTransitioning = true;
					this.visible = true;
				}

				/**
     * Sync selectors
     * @memberof ClayTooltip
     * @param {Array.<string>} newValue  The new value of `this.selectors`.
     * @param {Array.<string>} prevValue The previous value of `this.selectors`.
     * @private
     */

			}, {
				key: 'syncSelectors',
				value: function syncSelectors(newValue, prevValue) {
					if (newValue) {
						var prevSelectors = Array.isArray(prevValue) ? prevValue : [];

						var newSelectors = newValue.reduce(function (arr, val) {
							if (arr.indexOf(val) === -1) {
								arr.push(val);
							}
							return arr;
						}, prevSelectors);

						this._eventHandler.removeAllListeners();

						for (var i = 0, l = newSelectors.length; i < l; i++) {
							var _eventHandler;

							var selector = newSelectors[i];
							var handlers = [];

							if (/iPad|iPhone|iPod|android/i.test(navigator.userAgent)) {
								handlers.push(_metalDom.dom.delegate(document, 'touchstart', selector, this._handleTouchStart.bind(this)), _metalDom.dom.delegate(document, 'touchend', selector, this._handleTouchEnd.bind(this)), _metalDom.dom.delegate(document, 'touchcancel', selector, this._handleTouchEnd.bind(this)));
							} else {
								handlers.push(_metalDom.dom.delegate(document, 'blur', selector, this._handleMouseLeave.bind(this)), _metalDom.dom.delegate(document, 'click', selector, this._handleMouseClick.bind(this)), _metalDom.dom.delegate(document, 'focus', selector, this._handleMouseEnter.bind(this)), _metalDom.dom.delegate(document, 'mouseenter', selector, this._handleMouseEnter.bind(this)), _metalDom.dom.delegate(document, 'mouseleave', selector, this._handleMouseLeave.bind(this)));
							}

							(_eventHandler = this._eventHandler).add.apply(_eventHandler, handlers);
						}
					}
				}

				/**
     * @inheritDoc
     */

			}, {
				key: 'syncVisible',
				value: function syncVisible() {}
				// This is needed to make fade transition work


				/**
     * Gets the default value for the `classMap` state.
     * @return {!Object}
     * @private
     */

			}, {
				key: 'valueClassMapFn_',
				value: function valueClassMapFn_() {
					var _ref;

					return _ref = {}, _defineProperty(_ref, _metalPosition.Align.TopLeft, 'clay-tooltip-top-left'), _defineProperty(_ref, _metalPosition.Align.TopCenter, 'clay-tooltip-top'), _defineProperty(_ref, _metalPosition.Align.TopRight, 'clay-tooltip-top-right'), _defineProperty(_ref, _metalPosition.Align.BottomLeft, 'clay-tooltip-bottom-left'), _defineProperty(_ref, _metalPosition.Align.BottomCenter, 'clay-tooltip-bottom'), _defineProperty(_ref, _metalPosition.Align.BottomRight, 'clay-tooltip-bottom-right'), _defineProperty(_ref, _metalPosition.Align.RightCenter, 'clay-tooltip-right'), _defineProperty(_ref, _metalPosition.Align.LeftCenter, 'clay-tooltip-left'), _ref;
				}
			}], [{
				key: 'init',
				value: function init(config, parentElement) {
					if (!this._instance) {
						this._instance = new ClayTooltip(new SingletonEnforcer(), config, parentElement);
					}
					return this._instance;
				}
			}]);

			return ClayTooltip;
		}(_clayComponent2.default);

		/**
   * State definition.
   * @static
   * @type {!Object}
   */

		ClayTooltip.STATE = {
			/**
    * Content of the tooltip.
    * @default undefined
    * @instance
    * @memberof ClayTooltip
    * @type {!(html|string)}
    */
			_content: _metalState.Config.any().value('').internal(),

			/**
    * The current position of the tooltip after being aligned via `Align.align`.
    * @default undefined
    * @type {number}
    * @instance
    * @memberof ClayTooltip
    */
			alignedPosition: {
				validator: _metalPosition.Align.isValidPosition
			},

			/**
    * Flag to activate the auto best position.
    * @default true
    * @instance
    * @memberof ClayTooltip
    * @type {?bool}
    */
			bestAlign: _metalState.Config.bool().value(true),

			/**
    * Data to add to the element.
    * @default undefined
    * @instance
    * @memberof ClayTooltip
    * @type {?object}
    */
			data: _metalState.Config.object(),

			/**
    * Object that wires events with default listeners
    * @default undefined
    * @instance
    * @memberof ClayTooltip
    * @review
    * @type {?(object|undefined)}
    */
			defaultEventHandler: _metalState.Config.object(),

			/**
    * Element classes.
    * @default undefined
    * @instance
    * @memberof ClayTooltip
    * @type {string}
    */
			elementClasses: _metalState.Config.string(),

			/**
    * A map from `Align` position constants to the CSS class that should be
    * added to the tooltip when it's aligned in that position.
    * @instance
    * @memberof ClayTooltip
    * @type {!Object}
    */
			classMap: {
				setter: 'setterClassMapFn_',
				validator: _metal.core.isObject,
				valueFn: 'valueClassMapFn_'
			},

			/**
    * Tooltip position
    * @default TopCenter
    * @instance
    * @memberof ClayTooltip
    * @type {!string}
    */
			position: _metalState.Config.oneOf(['BottomCenter', 'BottomLeft', 'BottomRight', 'LeftCenter', 'RightCenter', 'TopCenter', 'TopLeft', 'TopRight']).setter('_setPreferredAlign').value('TopCenter'),

			/**
    * Selectors
    * @default ['[data-title]', '[title]']
    * @instance
    * @memberof ClayTooltip
    * @type {!Array.<string>}
    */
			selectors: _metalState.Config.array().value(['[data-title]:not([data-title=""])', '[title]:not([title=""]']),

			/**
    * Tooltip visible when show is called.
    * @default false
    * @instance
    * @memberof ClayTooltip
    * @private
    * @type {?bool}
    */
			visible: _metalState.Config.bool().value(false)
		};

		_metalSoy2.default.register(ClayTooltip, _ClayTooltipSoy2.default);

		exports.ClayTooltip = ClayTooltip;
		exports.default = ClayTooltip;
		//# sourceMappingURL=ClayTooltip.js.map
	}
});
//# sourceMappingURL=ClayTooltip.js.map