bootstrap 5 автоматическое исчезновение popover
В Bootstrap 5 popover по умолчанию не исчезает автоматически — он остаётся открытым, пока пользователь не кликнет вне его или не закроет вручную. Однако вы можете настроить автоматическое исчезновение (автозакрытие) через JavaScript, используя setTimeout.
Вот пример, как сделать так, чтобы popover автоматически закрывался через, например, 2 секунды после открытия:
<button type="button" class="btn btn-lg btn-danger" data-bs-toggle="popover" title="Заголовок" data-bs-content="Этот popover исчезнет через 2 секунды.">
Наведи и подожди
</button>
// Инициализация всех popover'ов
const popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'));
const popoverList = popoverTriggerList.map(function (popoverTriggerEl) {
return new bootstrap.Popover(popoverTriggerEl, {
trigger: 'hover focus', // или 'click', как вам нужно
delay: { show: 0, hide: 100 } // опционально
});
});
// Автоматическое скрытие через 2 секунды после открытия
document.addEventListener('shown.bs.popover', function (event) {
const popover = bootstrap.Popover.getInstance(event.target);
setTimeout(() => {
if (popover) {
popover.hide();
}
}, 2000); // 2000 мс = 2 секунды
});
💡 Примечания:
- Событие
shown.bs.popoverсрабатывает после полного отображения popover’а. bootstrap.Popover.getInstance(element)— метод, который возвращает экземпляр popover’а, привязанный к элементу.- Если вы используете
trigger: 'hover', убедитесь, что пользователь не уводит курсор слишком быстро — иначе popover может закрыться раньше таймера.
🔁 Альтернатива: только при наведении (без клика)
Если вы хотите, чтобы popover появлялся при наведении и исчезал через N секунд даже если курсор всё ещё над ним, то текущий подход подойдёт. Но если вы хотите, чтобы он оставался, пока курсор над элементом или popover’ом — тогда логика усложняется (нужно отслеживать mouseenter/mouseleave).
Но для простого автозакрытия — приведённый выше код работает отлично.
Чтобы реализовать автоматическое исчезновение popover через N секунд, но отменять это исчезновение, если пользователь навёл курсор на сам popover, нужно:
- Запускать таймер при открытии popover’а.
- Сохранять ID таймера (например, в
datasetили через замыкание). - При наведении на popover — очищать таймер.
- При уходе с popover — снова запускать таймер (опционально).
- При закрытии popover — очищать таймер, чтобы избежать утечек.
Вот полный рабочий пример:
<button
type="button"
class="btn btn-lg btn-primary"
data-bs-toggle="popover"
title="Авто-закрытие"
data-bs-content="Наведи на меня или на этот popover, чтобы отменить автозакрытие."
>
Наведи курсор
</button>
// Хранилище таймеров для каждого popover'а (по элементу-триггеру)
const popoverTimers = new Map();
// Инициализация popover'ов
document.querySelectorAll('[data-bs-toggle="popover"]').forEach(trigger => {
const popover = new bootstrap.Popover(trigger, {
trigger: 'hover',
placement: 'top',
html: true // если нужно HTML-содержимое
});
// Когда popover показан
trigger.addEventListener('shown.bs.popover', () => {
const popoverElement = document.querySelector('.popover');
if (!popoverElement) return;
// Функция для скрытия
const hidePopover = () => {
popover.hide();
popoverTimers.delete(trigger);
};
// Устанавливаем таймер
const timerId = setTimeout(hidePopover, 2000); // 2 секунды
popoverTimers.set(trigger, timerId);
// Обработчики для popover-элемента
const onMouseEnter = () => {
clearTimeout(popoverTimers.get(trigger));
popoverTimers.delete(trigger);
};
const onMouseLeave = () => {
const newTimer = setTimeout(hidePopover, 2000);
popoverTimers.set(trigger, newTimer);
};
// Добавляем обработчики на сам popover
popoverElement.addEventListener('mouseenter', onMouseEnter);
popoverElement.addEventListener('mouseleave', onMouseLeave);
// Сохраняем обработчики, чтобы потом удалить
trigger._popoverHandlers = { onMouseEnter, onMouseLeave, popoverElement };
});
// При скрытии popover'а — очищаем всё
trigger.addEventListener('hide.bs.popover', () => {
const timerId = popoverTimers.get(trigger);
if (timerId) {
clearTimeout(timerId);
popoverTimers.delete(trigger);
}
// Удаляем обработчики с popover-элемента
if (trigger._popoverHandlers) {
const { onMouseEnter, onMouseLeave, popoverElement } = trigger._popoverHandlers;
popoverElement?.removeEventListener('mouseenter', onMouseEnter);
popoverElement?.removeEventListener('mouseleave', onMouseLeave);
delete trigger._popoverHandlers;
}
});
});
💡 Как это работает:
- При наведении на кнопку — popover появляется.
- Через 2 секунды он закроется автоматически.
- Но если в эти 2 секунды пользователь навёл курсор на сам popover, таймер останавливается.
- Если пользователь убирает курсор с popover’а, таймер запускается снова.
- При закрытии popover’а (автоматически или вручную) — все обработчики и таймеры корректно удаляются.
⚠️ Важно:
- Bootstrap создаёт popover вне DOM-дерева триггера, обычно в конце
<body>, поэтому мы ищем его черезdocument.querySelector('.popover'). - Если у вас несколько popover’ов одновременно, этот подход может работать некорректно, потому что
.popoverможет указывать не на тот элемент. В таком случае лучше использоватьidили уникальные классы.
🔐 Улучшение для нескольких popover’ов
Если у вас может быть несколько открытых popover’ов, лучше использовать id или привязку через data:
// В shown.bs.popover:
const id = 'popover-' + Date.now();
const popoverElement = document.querySelector('.popover:not([data-handled])');
if (popoverElement) {
popoverElement.dataset.handled = 'true';
popoverElement.dataset.triggerId = id;
trigger.dataset.popoverId = id;
// ... и далее работать по id
}
Но для большинства случаев (один popover за раз) — первый вариант отлично подойдёт.
Share this content:



Отправить комментарий