Отлично! Добавим управление показом по времени и список URL-исключений.
Что будет сделано:
-
Показ 1 раз в 12 часов:
-
Используем localStorage для хранения времени последнего успешного показа видео.
-
Перед показом будем проверять, прошло ли 12 часов с последнего раза.
-
URL-исключения:
-
Создадим массив строк (URL-паттернов).
-
Перед показом будем проверять текущий URL страницы на соответствие этим паттернам.
-
Паттерн /bitrix/* будет означать “все URL, начинающиеся с /bitrix/”.
Вот полный обновленный код:
`
Видео в углу (с контролем показа и исключениями)
body { min-height: 200vh; /* Просто для демонстрации прокрутки и позиционирования / margin: 0; font-family: sans-serif; background-color: #f0f0f0; padding-bottom: 400px; / Добавляем отступ снизу */ }
.video-popup-container { position: fixed; bottom: 30px; left: 30px; width: 210px; height: 360px; /* Общая высота блока / background-color: #222; / Фон на случай, если видео не полностью загрузится / border-radius: 10px; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3); z-index: 9999; overflow: hidden; / Чтобы скруглённые углы работали для видео / display: none; / Изначально скрыт */ }
.video-popup-container.visible { /* Если будете использовать анимацию появления */ display: block; }
.video-popup-container video { width: 100%; height: 100%; object-fit: cover; display: block; }
.video-popup-close-btn { position: absolute; top: 5px; right: 5px; width: 25px; height: 25px; background-color: rgba(0, 0, 0, 0.5); color: white; border: none; border-radius: 50%; font-size: 16px; line-height: 25px; text-align: center; cursor: pointer; z-index: 10; transition: background-color 0.2s; }
.video-popup-close-btn:hover { background-color: rgba(0, 0, 0, 0.8); }
.video-popup-mute-btn { position: absolute; bottom: 10px; left: 10px; width: 30px; height: 30px; background-color: rgba(0, 0, 0, 0.5); color: white; border: none; border-radius: 5px; font-size: 18px; line-height: 30px; text-align: center; cursor: pointer; z-index: 10; transition: background-color 0.2s; }
.video-popup-mute-btn:hover { background-color: rgba(0, 0, 0, 0.8); }
Пример страницы с видео
Текущий URL:
Видео должно показываться 1 раз в 12 часов. И не показываться на URL, начинающихся с /bitrix/ или /admin/.
Прокрутите вниз.
…
Чтобы протестировать временной интервал, можно очистить LocalStorage (ключ videoPopupLastShownTime) или изменить SHOW_INTERVAL_HOURS на очень маленькое значение.
…
Еще контент…
Ваш браузер не поддерживает тег video.
× 🔇
document.addEventListener(‘DOMContentLoaded’, function() { const videoPopup = document.getElementById(‘videoPopup’); const videoElement = document.getElementById(‘myPopupVideo’); const closeButton = document.getElementById(‘videoPopupClose’); const muteButton = document.getElementById(‘videoPopupMute’);
// --- НАСТРОЙКИ --- const SHOW_INTERVAL_HOURS = 12; // Показывать раз в N часов const URL_EXCLUSIONS = [ // Список URL-ов для исключения показа (пути) ‘/bitrix/’, // Исключает все, что начинается с /bitrix/ ‘/admin/’, // Исключает все, что начинается с /admin/ ‘/cart/’, // Пример: исключить /cart/ и /cart/checkout/ // ‘/specific-page.html’ // Пример для точного совпадения ]; const LOCAL_STORAGE_KEY = ‘videoPopupLastShownTime’; const POPUP_DELAY_MS = 5000; // 5 секунд задержка перед показом const MOBILE_MAX_WIDTH = 768; // Максимальная ширина для определения мобильного // --- КОНЕЦ НАСТРОЕК ---
// Для отладки: отображаем текущий URL const currentUrlDisplay = document.getElementById(‘currentUrlDisplay’); if (currentUrlDisplay) { currentUrlDisplay.textContent = window.location.pathname; }
// Функция проверки, является ли текущий URL исключением
function isUrlExcluded() {
const currentPath = window.location.pathname;
for (const exclusionPath of URL_EXCLUSIONS) {
if (currentPath.startsWith(exclusionPath)) {
console.log(Видео не будет показано: URL "${currentPath}" соответствует исключению "${exclusionPath}".);
return true;
}
}
return false;
}
// Функция проверки, можно ли показывать видео на основе времени function canShowVideoByTime() { const lastShownTimestamp = localStorage.getItem(LOCAL_STORAGE_KEY); if (!lastShownTimestamp) { return true; // Никогда не показывали, можно показать }
const intervalMilliseconds = SHOW_INTERVAL_HOURS * 60 * 60 * 1000; const timeSinceLastShown = Date.now() - parseInt(lastShownTimestamp, 10);
if (timeSinceLastShown >= intervalMilliseconds) {
return true; // Прошло достаточно времени
} else {
const hoursRemaining = ((intervalMilliseconds - timeSinceLastShown) / (60 * 60 * 1000)).toFixed(1);
console.log(Видео не будет показано: еще не прошло ${SHOW_INTERVAL_HOURS} часов. Осталось: ${hoursRemaining} ч.);
return false;
}
}
// Определяем, мобильное ли устройство
const isMobile = window.matchMedia((max-width: ${MOBILE_MAX_WIDTH}px)).matches;
// --- ОСНОВНАЯ ЛОГИКА РЕШЕНИЯ О ПОКАЗЕ --- if (isMobile) { console.log(“Мобильное устройство. Видео не будет загружено и показано.”); if (videoPopup) videoPopup.remove(); // Полностью убираем элемент return; // Завершаем работу скрипта для попапа }
if (isUrlExcluded()) { // Сообщение уже выведено в isUrlExcluded if (videoPopup) videoPopup.remove(); return; }
if (!canShowVideoByTime()) { // Сообщение уже выведено в canShowVideoByTime if (videoPopup) videoPopup.remove(); return; }
// Если все проверки пройдены, готовим и показываем видео console.log(“Все условия для показа видео выполнены. Готовим видео…”);
window.addEventListener(‘load’, function() { // Устанавливаем источники видео const sources = videoElement.getElementsByTagName(‘source’); for (let i = 0; i < sources.length; i++) { if (sources[i].dataset.src) { sources[i].src = sources[i].dataset.src; } } videoElement.load(); // Инициируем загрузку видео
// Задержка перед показом и воспроизведением
setTimeout(function() {
if (videoPopup) { // Проверяем, что элемент еще существует
videoPopup.style.display = ‘block’;
// Сохраняем время показа ТОЛЬКО ПОСЛЕ ФАКТИЧЕСКОГО ПОКАЗА
localStorage.setItem(LOCAL_STORAGE_KEY, Date.now().toString());
console.log(Видео показано. Время показа записано: ${new Date().toLocaleString()});
videoElement.play().catch(error => { console.warn(“Autoplay видео был предотвращен браузером:”, error); }); } }, POPUP_DELAY_MS); });
// --- ОБРАБОТЧИКИ КНОПОК (только если видео инициализировано) --- if (closeButton && videoPopup) { // Убедимся, что videoPopup не был удален closeButton.addEventListener(‘click’, function() { videoPopup.style.display = ‘none’; videoElement.pause(); }); }
if (muteButton && videoElement && videoPopup) { // Убедимся, что videoPopup не был удален muteButton.addEventListener(‘click’, function() { if (videoElement.muted) { videoElement.muted = false; muteButton.textContent = ’🔊’; muteButton.setAttribute(‘aria-label’, ‘Выключить звук’); } else { videoElement.muted = true; muteButton.textContent = ’🔇’; muteButton.setAttribute(‘aria-label’, ‘Включить звук’); } });
// Инициализация иконки кнопки звука if (videoElement.muted) { muteButton.textContent = ’🔇’; muteButton.setAttribute(‘aria-label’, ‘Включить звук’); } else { muteButton.textContent = ’🔊’; muteButton.setAttribute(‘aria-label’, ‘Выключить звук’); } } });
`
Ключевые изменения и пояснения:
-
Настройки в начале скрипта:
-
SHOW_INTERVAL_HOURS: Устанавливает интервал в часах.
-
URL_EXCLUSIONS: Массив строк. Каждая строка — это начало пути URL, на котором видео не должно показываться.
-
/bitrix/ будет соответствовать /bitrix/admin/index.php, /bitrix/components/sale.order/ и т.д.
-
/cart/ будет соответствовать /cart/ и /cart/checkout/ и т.д.
-
Если нужно точное совпадение (например, только /exact-page.html, а не /exact-page.html?param=1), то логику isUrlExcluded нужно будет усложнить для проверки полного window.location.pathname + window.location.search или использовать регулярные выражения. Текущая реализация с startsWith покрывает сценарий “папки и подпапки”.
-
LOCAL_STORAGE_KEY: Имя ключа в localStorage.
-
MOBILE_MAX_WIDTH: Порог ширины для определения мобильного устройства.
-
Функция isUrlExcluded():
-
Получает текущий путь window.location.pathname.
-
Проходит по массиву URL_EXCLUSIONS.
-
Использует currentPath.startsWith(exclusionPath) для проверки, начинается ли текущий путь с одного из шаблонов исключения.
-
Функция canShowVideoByTime():
-
Читает время последнего показа из localStorage.
-
Если записи нет, значит, видео еще не показывали — можно показывать.
-
Если запись есть, сравнивает текущее время с временем последнего показа + интервал.
-
Основная логика принятия решения:
-
Сначала идет проверка на isMobile.
-
Затем проверка isUrlExcluded().
-
Затем проверка canShowVideoByTime().
-
Если хотя бы одно из этих условий предписывает не показывать видео, то элемент videoPopup удаляется из DOM (videoPopup.remove()), и скрипт прекращает дальнейшую работу с попапом. Это гарантирует, что видео не только не покажется, но и не будет загружено.
-
Если все проверки пройдены, скрипт продолжает загрузку и показ видео.
-
Запись времени показа:
-
localStorage.setItem(LOCAL_STORAGE_KEY, Date.now().toString()); вызывается только после того, как видео фактически отобразилось на странице (внутри setTimeout после videoPopup.style.display = ‘block’;). Это важно, чтобы не записывать “показ”, если пользователь закрыл вкладку до истечения 5-секундной задержки.
-
Обработчики кнопок:
-
Добавлены проверки if (videoPopup) перед добавлением обработчиков, так как videoPopup мог быть удален, если условия показа не выполнены.
Тестирование:
-
Время: Откройте страницу. Видео должно появиться. Обновите — не должно. Чтобы сбросить, очистите localStorage (в Инструментах разработчика > Application > Local Storage, найдите ваш сайт и удалите ключ videoPopupLastShownTime) или временно измените SHOW_INTERVAL_HOURS на очень маленькое значение (например, 0.001).
-
URL-исключения: Перейдите на URL, который должен быть исключен (например, если ваш сайт на localhost, попробуйте http://localhost/bitrix/test.html)). Видео не должно появиться. Перейдите на другой URL — должно (с учетом времени).
-
Мобильные: Проверьте в режиме эмуляции мобильного устройства.
Этот скрипт предоставляет надежный контроль над показом вашего видео-попапа.
Ищете надежного партнера по веб-разработке и автоматизации? Мы помогаем бизнесу расти с помощью современных технологий, автоматизации процессов и экспертного SEO. Свяжитесь с нами, чтобы обсудить вашу задачу.