UNPKG

framework7

Version:

Full featured mobile HTML framework for building iOS & Android apps

256 lines (224 loc) 7.46 kB
import $ from 'dom7'; import Utils from '../../utils/utils'; import Support from '../../utils/support'; import Framework7Class from '../../utils/class'; class Tooltip extends Framework7Class { constructor(app, params = {}) { super(params, [app]); const tooltip = this; const defaults = Utils.extend({}, app.params.tooltip); // Extend defaults with modules params tooltip.useModulesParams(defaults); tooltip.params = Utils.extend(defaults, params); const { targetEl } = tooltip.params; if (!targetEl) return tooltip; const $targetEl = $(targetEl); if ($targetEl.length === 0) return tooltip; if ($targetEl[0].f7Tooltip) return $targetEl[0].f7Tooltip; const $el = $(tooltip.render()).eq(0); Utils.extend(tooltip, { app, $targetEl, targetEl: $targetEl && $targetEl[0], $el, el: $el && $el[0], text: tooltip.params.text || '', visible: false, opened: false, }); $targetEl[0].f7Tooltip = tooltip; const touchesStart = {}; let isTouched; function handleTouchStart(e) { if (isTouched) return; isTouched = true; touchesStart.x = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX; touchesStart.y = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY; tooltip.show(this); } function handleTouchMove(e) { if (!isTouched) return; const x = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX; const y = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY; const distance = ( ((x - touchesStart.x) ** 2) + ((y - touchesStart.y) ** 2) ) ** 0.5; if (distance > 50) { isTouched = false; tooltip.hide(); } } function handleTouchEnd() { if (!isTouched) return; isTouched = false; tooltip.hide(); } function handleMouseEnter() { tooltip.show(this); } function handleMouseLeave() { tooltip.hide(); } function handleTransitionEnd() { if (!$el.hasClass('tooltip-in')) { $el.removeClass('tooltip-out').remove(); } } tooltip.attachEvents = function attachEvents() { $el.on('transitionend', handleTransitionEnd); if (Support.touch) { const passive = Support.passiveListener ? { passive: true } : false; $targetEl.on(app.touchEvents.start, handleTouchStart, passive); app.on('touchmove', handleTouchMove); app.on('touchend:passive', handleTouchEnd); } else { $targetEl.on('mouseenter', handleMouseEnter); $targetEl.on('mouseleave', handleMouseLeave); } }; tooltip.detachEvents = function detachEvents() { $el.off('transitionend', handleTransitionEnd); if (Support.touch) { const passive = Support.passiveListener ? { passive: true } : false; $targetEl.off(app.touchEvents.start, handleTouchStart, passive); app.off('touchmove', handleTouchMove); app.off('touchend:passive', handleTouchEnd); } else { $targetEl.off('mouseenter', handleMouseEnter); $targetEl.off('mouseleave', handleMouseLeave); } }; // Install Modules tooltip.useModules(); tooltip.init(); return tooltip; } position(targetEl) { const tooltip = this; const { $el, app } = tooltip; $el.css({ left: '', top: '' }); const $targetEl = $(targetEl || tooltip.targetEl); const [width, height] = [$el.width(), $el.height()]; $el.css({ left: '', top: '' }); let targetWidth; let targetHeight; let targetOffsetLeft; let targetOffsetTop; if ($targetEl && $targetEl.length > 0) { targetWidth = $targetEl.outerWidth(); targetHeight = $targetEl.outerHeight(); const targetOffset = $targetEl.offset(); targetOffsetLeft = targetOffset.left - app.left; targetOffsetTop = targetOffset.top - app.top; const targetParentPage = $targetEl.parents('.page'); if (targetParentPage.length > 0) { targetOffsetTop -= targetParentPage[0].scrollTop; } } let [left, top] = [0, 0, 0]; // Top Position let position = 'top'; if (height < targetOffsetTop) { // On top top = targetOffsetTop - height; } else if (height < app.height - targetOffsetTop - targetHeight) { // On bottom position = 'bottom'; top = targetOffsetTop + targetHeight; } else { // On middle position = 'middle'; top = ((targetHeight / 2) + targetOffsetTop) - (height / 2); if (top <= 0) { top = 8; } else if (top + height >= app.height) { top = app.height - height - 8; } } // Horizontal Position if (position === 'top' || position === 'bottom') { left = ((targetWidth / 2) + targetOffsetLeft) - (width / 2); if (left < 8) left = 8; if (left + width > app.width) left = app.width - width - 8; if (left < 0) left = 0; } else if (position === 'middle') { left = targetOffsetLeft - width; if (left < 8 || (left + width > app.width)) { if (left < 8) left = targetOffsetLeft + targetWidth; if (left + width > app.width) left = app.width - width - 8; } } // Apply Styles $el.css({ top: `${top}px`, left: `${left}px` }); } show(aroundEl) { const tooltip = this; const { app, $el, $targetEl } = tooltip; app.root.append($el); tooltip.position(aroundEl); const $aroundEl = $(aroundEl); tooltip.visible = true; tooltip.opened = true; $targetEl.trigger('tooltip:show', tooltip); $el.trigger('tooltip:show', tooltip); if ($aroundEl.length && $aroundEl[0] !== $targetEl[0]) { $aroundEl.trigger('tooltip:show', tooltip); } tooltip.emit('local::show tooltipShow', tooltip); $el.removeClass('tooltip-out').addClass('tooltip-in'); return tooltip; } hide() { const tooltip = this; const { $el, $targetEl } = tooltip; tooltip.visible = false; tooltip.opened = false; $targetEl.trigger('tooltip:hide', tooltip); $el.trigger('tooltip:hide', tooltip); tooltip.emit('local::hide tooltipHide', tooltip); $el.addClass('tooltip-out').removeClass('tooltip-in'); return tooltip; } render() { const tooltip = this; if (tooltip.params.render) return tooltip.params.render.call(tooltip, tooltip); const { cssClass, text } = tooltip.params; return ` <div class="tooltip ${cssClass || ''}"> <div class="tooltip-content">${text || ''}</div> </div> `.trim(); } setText(newText) { const tooltip = this; if (typeof newText === 'undefined') { return tooltip; } tooltip.params.text = newText; tooltip.text = newText; if (tooltip.$el) { tooltip.$el.children('.tooltip-content').html(newText); } if (tooltip.opened) { tooltip.position(); } return tooltip; } init() { const tooltip = this; tooltip.attachEvents(); } destroy() { const tooltip = this; if (!tooltip.$targetEl || tooltip.destroyed) return; tooltip.$targetEl.trigger('tooltip:beforedestroy', tooltip); tooltip.emit('local::beforeDestroy tooltipBeforeDestroy', tooltip); tooltip.$el.remove(); delete tooltip.$targetEl[0].f7Tooltip; tooltip.detachEvents(); Utils.deleteProps(tooltip); tooltip.destroyed = true; } } export default Tooltip;