tooltip-plugin
Version:
A javascript plugin for tooltip
263 lines (213 loc) • 7.18 kB
JavaScript
import { Utils, DomUtils } from './utils';
/**
* Available data attributes (data-tooltip-*)
* @property {string} tooltip - Text to show (data-tooltip="")
* @property {string} [position=auto] - Position of tooltip (top, bottom, left, right, auto)
* @property {string} [fontSize=14px] - Text font size
* @property {number} [margin=8] - Space between tooltip and its activator (in pixel)
* @property {number} [offset=5] - Space between tooltip and window edge (in pixel)
* @property {number} [enterDelay=0] - Delay time before showing tooltip (in milliseconds)
* @property {number} [exitDelay=0] - Delay time before hiding tooltip (in milliseconds)
* @property {number} [showDuration=300] - Transition duration for show animation (in milliseconds)
* @property {number} [hideDuration=200] - Transition duration for hide animation (in milliseconds)
* @property {number} [transitionDistance=10] - Distance to translate on show/hide animation (in pixel)
* @property {number} [zIndex=1] - CSS z-index value for tooltip
* @property {boolean} [ellipsisOnly=false] - Show the tooltip only if element text is partially hidden with ellipsis
* @property {boolean} [allowHtml=false] - Allow html elements in the tooltip text
* @property {string} [alignment=left] - CSS text-align value
* @property {string} [maxWidth=300px] - CSS max-width for tootltip box
* @property {boolean} [hideOnClick=true] - Hide tooltip on clicking the element
* @property {boolean} [hideArrowIcon=false] - Hide arrow icon in the tooltip
* @property {string} [additionalClasses] - Additional classes for tooltip which could be used to customize tooltip in CSS
*/
(function () {
if (window.tooltipComponentInitiated) {
return;
} else {
window.tooltipComponentInitiated = true;
}
let $body;
let $popperEle;
let $triggerEle;
let $arrowEle;
let $scrollableElems;
let options = {};
let popper;
let isInitiated = false;
initTooltip();
window.addEventListener('load', initTooltip);
function initTooltip() {
if (isInitiated) {
return;
}
$body = document.querySelector('body');
if (!$body) {
return;
}
addEvents();
isInitiated = true;
}
/** event methods - start */
function addEvents() {
document.addEventListener('mouseover', onMouseOver);
document.addEventListener('mouseout', onMouseOut);
document.addEventListener('touchmove', onTouchMove);
document.addEventListener('click', onClick);
}
function onMouseOver(e) {
if ($triggerEle) {
return;
}
let target = e.target.closest('[data-tooltip]');
if (!target) {
return;
}
$triggerEle = target;
showTooltip();
}
function onMouseOut(e) {
if (!$triggerEle) {
return;
}
let target = e.relatedTarget;
while (target) {
if (target === $triggerEle) {
return;
}
target = target.parentNode;
}
hideTooltip();
}
function onTouchMove() {
hideTooltip();
}
function onClick() {
if (options.hideOnClick) {
hideTooltip();
}
}
/** event methods - end */
function showTooltip() {
if (!$triggerEle) {
return;
}
let convertToBoolean = Utils.convertToBoolean;
let convertToFloat = Utils.convertToFloat;
let dataset = $triggerEle.dataset;
options = {
tooltip: dataset.tooltip,
position: dataset.tooltipPosition || 'auto',
zIndex: convertToFloat(dataset.tooltipZIndex, 1),
enterDelay: convertToFloat(dataset.tooltipEnterDelay, 0),
exitDelay: convertToFloat(dataset.tooltipExitDelay, 0),
fontSize: dataset.tooltipFontSize || '14px',
margin: convertToFloat(dataset.tooltipMargin, 8),
offset: convertToFloat(dataset.tooltipOffset, 5),
showDuration: convertToFloat(dataset.tooltipShowDuration, 300),
hideDuration: convertToFloat(dataset.tooltipHideDuration, 200),
transitionDistance: convertToFloat(dataset.tooltipTransitionDistance, 10),
ellipsisOnly: convertToBoolean(dataset.tooltipEllipsisOnly),
allowHtml: convertToBoolean(dataset.tooltipAllowHtml),
hideOnClick: convertToBoolean(dataset.tooltipHideOnClick, true),
hideArrowIcon: convertToBoolean(dataset.tooltipHideArrowIcon),
alignment: dataset.tooltipAlignment || 'left',
maxWidth: dataset.tooltipMaxWidth || '300px',
additionalClasses: dataset.tooltipAdditionalClasses,
};
if (!options.tooltip || isTooltipDisabled()) {
hideTooltip();
return;
}
removeTooltip();
renderTooltip();
initPopper();
addScrollEventListeners();
}
function renderTooltip() {
let classNames = 'tooltip-comp';
if (options.hideArrowIcon) {
classNames += ' hide-arrow-icon';
}
if (options.additionalClasses) {
classNames += ' ' + options.additionalClasses;
}
let html = `<div class="${classNames}">
<i class="tooltip-comp-arrow"></i>
<div class="tooltip-comp-content"></div>
</div>`;
$body.insertAdjacentHTML('beforeend', html);
let setStyle = DomUtils.setStyle;
$popperEle = document.querySelector('.tooltip-comp');
$arrowEle = $popperEle.querySelector('.tooltip-comp-arrow');
let $popperContent = $popperEle.querySelector('.tooltip-comp-content');
if (options.allowHtml) {
$popperContent.innerHTML = options.tooltip;
} else {
$popperContent.innerText = options.tooltip;
}
setStyle($popperEle, 'zIndex', options.zIndex);
setStyle($popperEle, 'fontSize', options.fontSize);
setStyle($popperEle, 'textAlign', options.alignment);
setStyle($popperEle, 'maxWidth', options.maxWidth);
}
function hideTooltip() {
if (!isTooltipShown()) {
return;
}
hidePopper();
removeScrollEventListeners();
$triggerEle = null;
}
function removeTooltip() {
if ($popperEle) {
$popperEle.remove();
}
}
function isTooltipDisabled() {
return options.ellipsisOnly && !DomUtils.hasEllipsis($triggerEle);
}
function initPopper() {
let data = {
$popperEle,
$triggerEle,
$arrowEle,
position: options.position,
margin: options.margin,
offset: options.offset,
enterDelay: options.enterDelay,
exitDelay: options.exitDelay,
showDuration: options.showDuration,
hideDuration: options.hideDuration,
transitionDistance: options.transitionDistance,
zIndex: options.zIndex,
};
popper = new PopperComponent(data);
popper.show();
}
function hidePopper() {
if (popper) {
popper.hide();
}
}
function isTooltipShown() {
return $popperEle || $triggerEle;
}
function addScrollEventListeners() {
$scrollableElems = DomUtils.getScrollableParents($triggerEle);
$scrollableElems.forEach(($ele) => {
$ele.addEventListener('scroll', onScroll);
});
}
function removeScrollEventListeners() {
if (!$scrollableElems) {
return;
}
$scrollableElems.forEach(($ele) => {
$ele.removeEventListener('scroll', onScroll);
});
$scrollableElems = null;
}
function onScroll() {
hideTooltip();
}
})();