diff options
Diffstat (limited to 'node_modules/materialize-css/js/tooltip.js')
-rw-r--r-- | node_modules/materialize-css/js/tooltip.js | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/node_modules/materialize-css/js/tooltip.js b/node_modules/materialize-css/js/tooltip.js new file mode 100644 index 0000000000..b30dce2b82 --- /dev/null +++ b/node_modules/materialize-css/js/tooltip.js @@ -0,0 +1,303 @@ +(function($, anim) { + 'use strict'; + + let _defaults = { + exitDelay: 200, + enterDelay: 0, + html: null, + margin: 5, + inDuration: 250, + outDuration: 200, + position: 'bottom', + transitionMovement: 10 + }; + + /** + * @class + * + */ + class Tooltip extends Component { + /** + * Construct Tooltip instance + * @constructor + * @param {Element} el + * @param {Object} options + */ + constructor(el, options) { + super(Tooltip, el, options); + + this.el.M_Tooltip = this; + this.options = $.extend({}, Tooltip.defaults, options); + + this.isOpen = false; + this.isHovered = false; + this.isFocused = false; + this._appendTooltipEl(); + this._setupEventHandlers(); + } + + static get defaults() { + return _defaults; + } + + static init(els, options) { + return super.init(this, els, options); + } + + /** + * Get Instance + */ + static getInstance(el) { + let domElem = !!el.jquery ? el[0] : el; + return domElem.M_Tooltip; + } + + /** + * Teardown component + */ + destroy() { + $(this.tooltipEl).remove(); + this._removeEventHandlers(); + this.el.M_Tooltip = undefined; + } + + _appendTooltipEl() { + let tooltipEl = document.createElement('div'); + tooltipEl.classList.add('material-tooltip'); + this.tooltipEl = tooltipEl; + + let tooltipContentEl = document.createElement('div'); + tooltipContentEl.classList.add('tooltip-content'); + tooltipContentEl.innerHTML = this.options.html; + tooltipEl.appendChild(tooltipContentEl); + document.body.appendChild(tooltipEl); + } + + _updateTooltipContent() { + this.tooltipEl.querySelector('.tooltip-content').innerHTML = this.options.html; + } + + _setupEventHandlers() { + this._handleMouseEnterBound = this._handleMouseEnter.bind(this); + this._handleMouseLeaveBound = this._handleMouseLeave.bind(this); + this._handleFocusBound = this._handleFocus.bind(this); + this._handleBlurBound = this._handleBlur.bind(this); + this.el.addEventListener('mouseenter', this._handleMouseEnterBound); + this.el.addEventListener('mouseleave', this._handleMouseLeaveBound); + this.el.addEventListener('focus', this._handleFocusBound, true); + this.el.addEventListener('blur', this._handleBlurBound, true); + } + + _removeEventHandlers() { + this.el.removeEventListener('mouseenter', this._handleMouseEnterBound); + this.el.removeEventListener('mouseleave', this._handleMouseLeaveBound); + this.el.removeEventListener('focus', this._handleFocusBound, true); + this.el.removeEventListener('blur', this._handleBlurBound, true); + } + + open(isManual) { + if (this.isOpen) { + return; + } + isManual = isManual === undefined ? true : undefined; // Default value true + this.isOpen = true; + // Update tooltip content with HTML attribute options + this.options = $.extend({}, this.options, this._getAttributeOptions()); + this._updateTooltipContent(); + this._setEnterDelayTimeout(isManual); + } + + close() { + if (!this.isOpen) { + return; + } + + this.isHovered = false; + this.isFocused = false; + this.isOpen = false; + this._setExitDelayTimeout(); + } + + /** + * Create timeout which delays when the tooltip closes + */ + _setExitDelayTimeout() { + clearTimeout(this._exitDelayTimeout); + + this._exitDelayTimeout = setTimeout(() => { + if (this.isHovered || this.isFocused) { + return; + } + + this._animateOut(); + }, this.options.exitDelay); + } + + /** + * Create timeout which delays when the toast closes + */ + _setEnterDelayTimeout(isManual) { + clearTimeout(this._enterDelayTimeout); + + this._enterDelayTimeout = setTimeout(() => { + if (!this.isHovered && !this.isFocused && !isManual) { + return; + } + + this._animateIn(); + }, this.options.enterDelay); + } + + _positionTooltip() { + let origin = this.el, + tooltip = this.tooltipEl, + originHeight = origin.offsetHeight, + originWidth = origin.offsetWidth, + tooltipHeight = tooltip.offsetHeight, + tooltipWidth = tooltip.offsetWidth, + newCoordinates, + margin = this.options.margin, + targetTop, + targetLeft; + + (this.xMovement = 0), (this.yMovement = 0); + + targetTop = origin.getBoundingClientRect().top + M.getDocumentScrollTop(); + targetLeft = origin.getBoundingClientRect().left + M.getDocumentScrollLeft(); + + if (this.options.position === 'top') { + targetTop += -tooltipHeight - margin; + targetLeft += originWidth / 2 - tooltipWidth / 2; + this.yMovement = -this.options.transitionMovement; + } else if (this.options.position === 'right') { + targetTop += originHeight / 2 - tooltipHeight / 2; + targetLeft += originWidth + margin; + this.xMovement = this.options.transitionMovement; + } else if (this.options.position === 'left') { + targetTop += originHeight / 2 - tooltipHeight / 2; + targetLeft += -tooltipWidth - margin; + this.xMovement = -this.options.transitionMovement; + } else { + targetTop += originHeight + margin; + targetLeft += originWidth / 2 - tooltipWidth / 2; + this.yMovement = this.options.transitionMovement; + } + + newCoordinates = this._repositionWithinScreen( + targetLeft, + targetTop, + tooltipWidth, + tooltipHeight + ); + $(tooltip).css({ + top: newCoordinates.y + 'px', + left: newCoordinates.x + 'px' + }); + } + + _repositionWithinScreen(x, y, width, height) { + let scrollLeft = M.getDocumentScrollLeft(); + let scrollTop = M.getDocumentScrollTop(); + let newX = x - scrollLeft; + let newY = y - scrollTop; + + let bounding = { + left: newX, + top: newY, + width: width, + height: height + }; + + let offset = this.options.margin + this.options.transitionMovement; + let edges = M.checkWithinContainer(document.body, bounding, offset); + + if (edges.left) { + newX = offset; + } else if (edges.right) { + newX -= newX + width - window.innerWidth; + } + + if (edges.top) { + newY = offset; + } else if (edges.bottom) { + newY -= newY + height - window.innerHeight; + } + + return { + x: newX + scrollLeft, + y: newY + scrollTop + }; + } + + _animateIn() { + this._positionTooltip(); + this.tooltipEl.style.visibility = 'visible'; + anim.remove(this.tooltipEl); + anim({ + targets: this.tooltipEl, + opacity: 1, + translateX: this.xMovement, + translateY: this.yMovement, + duration: this.options.inDuration, + easing: 'easeOutCubic' + }); + } + + _animateOut() { + anim.remove(this.tooltipEl); + anim({ + targets: this.tooltipEl, + opacity: 0, + translateX: 0, + translateY: 0, + duration: this.options.outDuration, + easing: 'easeOutCubic' + }); + } + + _handleMouseEnter() { + this.isHovered = true; + this.isFocused = false; // Allows close of tooltip when opened by focus. + this.open(false); + } + + _handleMouseLeave() { + this.isHovered = false; + this.isFocused = false; // Allows close of tooltip when opened by focus. + this.close(); + } + + _handleFocus() { + if (M.tabPressed) { + this.isFocused = true; + this.open(false); + } + } + + _handleBlur() { + this.isFocused = false; + this.close(); + } + + _getAttributeOptions() { + let attributeOptions = {}; + let tooltipTextOption = this.el.getAttribute('data-tooltip'); + let positionOption = this.el.getAttribute('data-position'); + + if (tooltipTextOption) { + attributeOptions.html = tooltipTextOption; + } + + if (positionOption) { + attributeOptions.position = positionOption; + } + return attributeOptions; + } + } + + M.Tooltip = Tooltip; + + if (M.jQueryLoaded) { + M.initializeJqueryWrapper(Tooltip, 'tooltip', 'M_Tooltip'); + } +})(cash, M.anime); |