|
|
|
|
@@ -8,15 +8,18 @@ const attributeToOption = (attribute) => {
|
|
|
|
|
return attribute.charAt(0).toLowerCase() + attribute.slice(1);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const isTouchDevice = () => 'ontouchstart' in window || navigator.maxTouchPoints > 0;
|
|
|
|
|
|
|
|
|
|
let visibilityListenerRegistered = false;
|
|
|
|
|
const handleVisibilityChange = () => {
|
|
|
|
|
if (document.hidden) {
|
|
|
|
|
// Скрываем все активные всплывающие подсказки
|
|
|
|
|
for (const $tooltip of document.querySelectorAll('.tooltip')) {
|
|
|
|
|
if ($tooltip._reference?._tooltip?.isVisible) {
|
|
|
|
|
$tooltip._reference._tooltip.hide({ immediately: true });
|
|
|
|
|
const ref = $tooltip._reference;
|
|
|
|
|
if (ref?._tooltip) {
|
|
|
|
|
// Очищаем таймеры появления при скрытии страницы
|
|
|
|
|
clearTimeout(ref._tooltip._showTimeout);
|
|
|
|
|
if (ref._tooltip.isVisible) {
|
|
|
|
|
ref._tooltip.hide({ immediately: true });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -55,8 +58,6 @@ export const createTooltip = ($el, content, options) => {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let showTimeout;
|
|
|
|
|
let hideTimeout;
|
|
|
|
|
let rafId;
|
|
|
|
|
const listeners = [];
|
|
|
|
|
|
|
|
|
|
@@ -67,6 +68,8 @@ export const createTooltip = ($el, content, options) => {
|
|
|
|
|
$container: undefined,
|
|
|
|
|
$arrow: undefined,
|
|
|
|
|
$interactive: undefined,
|
|
|
|
|
_showTimeout: undefined,
|
|
|
|
|
_hideTimeout: undefined,
|
|
|
|
|
autoUpdateCleanup: () => {},
|
|
|
|
|
|
|
|
|
|
setContent(updatedContent) {
|
|
|
|
|
@@ -164,8 +167,8 @@ export const createTooltip = ($el, content, options) => {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
clearTimeout(showTimeout);
|
|
|
|
|
clearTimeout(hideTimeout);
|
|
|
|
|
clearTimeout($el._tooltip._showTimeout);
|
|
|
|
|
clearTimeout($el._tooltip._hideTimeout);
|
|
|
|
|
cancelAnimationFrame(rafId);
|
|
|
|
|
|
|
|
|
|
$el._tooltip.$tooltip?.remove();
|
|
|
|
|
@@ -189,7 +192,7 @@ export const createTooltip = ($el, content, options) => {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$el._tooltip.show = async ({ immediately } = {}) => {
|
|
|
|
|
clearTimeout(hideTimeout);
|
|
|
|
|
clearTimeout($el._tooltip._hideTimeout);
|
|
|
|
|
|
|
|
|
|
if (!$el._tooltip.$tooltip) {
|
|
|
|
|
const { computePosition, offset, flip, shift, arrow } = await import('@floating-ui/dom');
|
|
|
|
|
@@ -296,10 +299,18 @@ export const createTooltip = ($el, content, options) => {
|
|
|
|
|
|
|
|
|
|
const { autoUpdate } = await import('@floating-ui/dom');
|
|
|
|
|
|
|
|
|
|
showTimeout = setTimeout(
|
|
|
|
|
$el._tooltip._showTimeout = setTimeout(
|
|
|
|
|
async () => {
|
|
|
|
|
// Проверяем $el._tooltip на сущестование
|
|
|
|
|
if (!$el._tooltip || $el._tooltip.isVisible) {
|
|
|
|
|
const isMouseEnterTrigger = options.trigger.includes('mouseenter');
|
|
|
|
|
const isHovering = $el.matches(':hover');
|
|
|
|
|
|
|
|
|
|
// Проверяем $el._tooltip на сущестование и актуальность показа всплывающей подсказки
|
|
|
|
|
if (
|
|
|
|
|
!$el._tooltip ||
|
|
|
|
|
$el._tooltip.isVisible ||
|
|
|
|
|
(isMouseEnterTrigger && !isHovering) ||
|
|
|
|
|
document.hidden
|
|
|
|
|
) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -336,8 +347,8 @@ export const createTooltip = ($el, content, options) => {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$el._tooltip.hide = ({ immediately } = {}) => {
|
|
|
|
|
clearTimeout(showTimeout);
|
|
|
|
|
hideTimeout = setTimeout(
|
|
|
|
|
clearTimeout($el._tooltip._showTimeout);
|
|
|
|
|
$el._tooltip._hideTimeout = setTimeout(
|
|
|
|
|
async () => {
|
|
|
|
|
// Проверяем $el._tooltip на сущестование
|
|
|
|
|
if (!$el._tooltip || !$el._tooltip.isVisible) {
|
|
|
|
|
@@ -397,21 +408,34 @@ export const createTooltip = ($el, content, options) => {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$el._tooltip.clickListener = () => {
|
|
|
|
|
if (document.hidden) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!$el._tooltip.isVisible) {
|
|
|
|
|
$el._tooltip.show();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$el._tooltip.mouseEnterListener = () => {
|
|
|
|
|
$el._tooltip.mouseEnterListener = (event) => {
|
|
|
|
|
if (event.pointerType !== 'mouse' || document.hidden) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
$el._tooltip.show();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$el._tooltip.mouseLeaveListener = ({ relatedTarget }) => {
|
|
|
|
|
if (options.interactive && relatedTarget && $el._tooltip.$tooltip?.contains(relatedTarget)) {
|
|
|
|
|
$el._tooltip.mouseLeaveListener = (event) => {
|
|
|
|
|
if (event.pointerType !== 'mouse') {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (options.interactive && event.relatedTarget && $el._tooltip.$tooltip?.contains(event.relatedTarget)) {
|
|
|
|
|
$el._tooltip.$tooltip.addEventListener(
|
|
|
|
|
'mouseleave',
|
|
|
|
|
({ relatedTarget }) => {
|
|
|
|
|
if (!relatedTarget || !$el.contains(relatedTarget)) {
|
|
|
|
|
'pointerleave',
|
|
|
|
|
(event) => {
|
|
|
|
|
if (event.pointerType !== 'mouse') {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!event.relatedTarget || !$el.contains(event.relatedTarget)) {
|
|
|
|
|
$el._tooltip.hide();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
@@ -423,6 +447,9 @@ export const createTooltip = ($el, content, options) => {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$el._tooltip.focusListener = () => {
|
|
|
|
|
if (document.hidden) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
$el._tooltip.show();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
@@ -434,13 +461,11 @@ export const createTooltip = ($el, content, options) => {
|
|
|
|
|
for (const trigger of options.trigger.split(' ')) {
|
|
|
|
|
switch (trigger) {
|
|
|
|
|
case 'mouseenter': {
|
|
|
|
|
if (!isTouchDevice()) {
|
|
|
|
|
$el.addEventListener('mouseenter', $el._tooltip.mouseEnterListener);
|
|
|
|
|
listeners.push({ el: $el, event: 'mouseenter', listener: $el._tooltip.mouseEnterListener });
|
|
|
|
|
$el.addEventListener('pointerenter', $el._tooltip.mouseEnterListener);
|
|
|
|
|
listeners.push({ el: $el, event: 'pointerenter', listener: $el._tooltip.mouseEnterListener });
|
|
|
|
|
|
|
|
|
|
$el.addEventListener('mouseleave', $el._tooltip.mouseLeaveListener);
|
|
|
|
|
listeners.push({ el: $el, event: 'mouseleave', listener: $el._tooltip.mouseLeaveListener });
|
|
|
|
|
}
|
|
|
|
|
$el.addEventListener('pointerleave', $el._tooltip.mouseLeaveListener);
|
|
|
|
|
listeners.push({ el: $el, event: 'pointerleave', listener: $el._tooltip.mouseLeaveListener });
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 'click': {
|
|
|
|
|
@@ -448,8 +473,8 @@ export const createTooltip = ($el, content, options) => {
|
|
|
|
|
listeners.push({ el: $el, event: 'click', listener: $el._tooltip.clickListener });
|
|
|
|
|
|
|
|
|
|
if (!options.interactive) {
|
|
|
|
|
$el.addEventListener('mouseleave', $el._tooltip.mouseLeaveListener);
|
|
|
|
|
listeners.push({ el: $el, event: 'mouseleave', listener: $el._tooltip.mouseLeaveListener });
|
|
|
|
|
$el.addEventListener('pointerleave', $el._tooltip.mouseLeaveListener);
|
|
|
|
|
listeners.push({ el: $el, event: 'pointerleave', listener: $el._tooltip.mouseLeaveListener });
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|