(function () {
const INSERT_POSITION = 'beforeend';
const HIDDEN_CLASS = 'hidden';
const insertHTML = (html, target, position = INSERT_POSITION) => {
target.insertAdjacentHTML(position, html);
};
const padNumber = (value) => String(value).length === 1 ? `0${value}` : value;
// Конфигурации для разных типов баннеров
const BANNER_CONFIGS = {
corner: {
url: '/cst-banner',
storagePrefix: 'ipBannerStateId-',
className: 'ip-banner',
itemClassName: 'ip-banner-item',
hideTime: 600000, // 10 минут
maxClicks: 3,
isFullscreen: false
},
fullscreen: {
url: '/cst-banner-full',
storagePrefix: 'ipBannerFullStateId-',
className: 'ip-banner-full',
itemClassName: 'ip-banner-full-item',
hideTime: 21600000, // 6 часов
maxClicks: 1,
isFullscreen: true
}
};
class Banner {
#originalHTML = null;
#bannerElement = null;
#countdownTime = null;
#bannerContainer = null;
#closeButton = null;
#contentContainer = null;
#contentFrame = null;
#bannerItem = null;
#countdownElement = null;
#timerInterval = null;
#bannerId = null;
#imageElements = null;
#storage = localStorage;
#config = null;
constructor(bannerContent, config) {
this.#originalHTML = bannerContent.outerHTML;
this.#bannerContainer = document.querySelector('.gc-main-content');
this.#config = config;
}
get templateStyle() {
if (this.#config.isFullscreen) {
return `
`;
} else {
return `
`;
}
}
get template() {
const containerClass = this.#config.isFullscreen ? 'ip-banner-full__container' : '';
const contentClass = this.#config.isFullscreen ? 'ip-banner-full__content' : 'ip-banner__content';
const closeClass = this.#config.isFullscreen ? 'ip-banner-full__close' : 'ip-banner__close';
return `
${this.#originalHTML}
`;
}
get element() {
if (!this.#bannerElement) {
this.#bannerElement = this.template;
}
return this.#bannerElement;
}
init() {
// Insert banner styles and HTML
insertHTML(this.templateStyle, this.#bannerContainer);
insertHTML(this.element, this.#bannerContainer);
// Show first banner item
this.#showFirstBannerItem();
// Get banner elements
this.#bannerContainer = document.querySelector(`.${this.#config.className}`);
const closeSelector = this.#config.isFullscreen ? '.ip-banner-full__close' : '.ip-banner__close';
const contentSelector = this.#config.isFullscreen ? '.ip-banner-full__content' : '.ip-banner__content';
this.#closeButton = this.#bannerContainer.querySelector(closeSelector);
this.#contentContainer = this.#bannerContainer.querySelector(contentSelector);
this.#contentFrame = this.#contentContainer.querySelector('.lite-page.block-set');
// Modify content frame classes
const frameClass = this.#config.isFullscreen ? 'ip-banner-full__content-frame' : 'ip-banner__content-frame';
this.#contentFrame.classList.add(frameClass);
this.#contentFrame.classList.remove('lite-page');
this.#contentFrame.classList.remove('block-set');
// Get banner item and images
this.#bannerItem = this.#bannerContainer.querySelector(`.${this.#config.itemClassName}`);
this.#imageElements = this.#bannerContainer.querySelectorAll('.image-box img');
if (this.#bannerItem) {
this.#countdownElement = this.#bannerItem.querySelector('.countdown-el');
this.#countdownTime = this.#countdownElement?.dataset.time;
this.#bannerId = this.#bannerItem.className.split(`${this.#config.itemClassName}-`)[1];
if (this.#countdownElement) {
this.#startCountdown(this.#countdownTime);
}
} else {
this.#bannerContainer.classList.add(HIDDEN_CLASS);
}
// Load lazy images
if (this.#imageElements.length) {
for (const image of this.#imageElements) {
image.src = image.dataset.src;
}
}
// Add event listeners
this.#closeButton.addEventListener('click', this.#handleCloseClick);
if (this.#config.isFullscreen) {
this.#bannerContainer.addEventListener('click', this.#handleBackgroundClick);
document.addEventListener('keydown', this.#handleKeyPress);
}
}
#showFirstBannerItem() {
const bannerItems = document.querySelectorAll(`.${this.#config.itemClassName}`);
if (bannerItems.length) {
// Отключаем jQuery countdown на всех элементах
bannerItems.forEach(item => {
const countdownEl = item.querySelector('.countdown-el');
if (countdownEl) {
try {
$(countdownEl).countdown('destroy');
} catch (e) {
console.log('Countdown already destroyed');
}
}
});
// Удаляем все баннеры кроме первого из DOM
for (let i = 1; i < bannerItems.length; i++) {
bannerItems[i].remove();
}
// Показываем первый баннер
bannerItems[0].style.display = 'block';
}
}
#startCountdown(endTime) {
if (!endTime) return;
const [date, time] = endTime.split(' ');
const endDateTime = moment(`${date}T${time}:00Z`);
const now = moment(new Date());
let timeLeft = endDateTime.valueOf() - now.valueOf();
const intervalMs = 1000;
const countdownDisplay = document.querySelector(`.${this.#config.itemClassName}-${this.#bannerId} .countdown-el`);
setInterval(() => {
timeLeft = moment.duration(timeLeft - intervalMs, 'milliseconds');
countdownDisplay.textContent = timeLeft - intervalMs > 0
? `${padNumber(timeLeft.days())}Д : ${padNumber(timeLeft.hours())}Ч : ${padNumber(timeLeft.minutes())}М : ${padNumber(timeLeft.seconds())}С`
: '00Д : 00Ч : 00М : 00С';
}, intervalMs);
}
#handleCloseClick = () => {
this.#bannerContainer.classList.add(HIDDEN_CLASS);
this.#saveBannerState();
if (this.#config.isFullscreen) {
document.removeEventListener('keydown', this.#handleKeyPress);
}
};
#handleBackgroundClick = (event) => {
if (event.target.classList.contains(this.#config.className)) {
this.#bannerContainer.classList.add(HIDDEN_CLASS);
this.#saveBannerState();
document.removeEventListener('keydown', this.#handleKeyPress);
}
};
#handleKeyPress = (event) => {
if (event.key === 'Escape') {
this.#bannerContainer.classList.add(HIDDEN_CLASS);
this.#saveBannerState();
document.removeEventListener('keydown', this.#handleKeyPress);
}
};
#saveBannerState = () => {
const bannerId = this.#bannerId;
if (bannerId >= 1) {
const currentTime = moment(new Date());
const storageKey = `${this.#config.storagePrefix}${bannerId}`;
const storedState = this.#storage.getItem(storageKey);
let clickCount = 0;
if (storedState) {
try {
clickCount = JSON.parse(storedState).count || 0;
} catch (error) {
clickCount = 0;
}
}
this.#storage.setItem(
storageKey,
JSON.stringify({
id: bannerId,
count: clickCount + 1,
timeCloseClick: currentTime
})
);
}
};
}
// Функция для проверки конкретного баннера по ID
const shouldShowBannerById = (config, bannerId) => {
const storageKey = `${config.storagePrefix}${bannerId}`;
const storedState = localStorage.getItem(storageKey);
if (!storedState) {
console.log(`${config.className} ID ${bannerId}: No saved state, CAN SHOW`);
return true; // Нет записи - показываем
}
try {
const parsedState = JSON.parse(storedState);
const clickCount = parsedState.count || 0;
const timeCloseClick = moment(parsedState.timeCloseClick);
const currentTime = moment(new Date());
const timeDiff = currentTime.valueOf() - timeCloseClick.valueOf();
const shouldShow = timeDiff >= config.hideTime && clickCount < config.maxClicks;
console.log(`${config.className} ID ${bannerId}:`, {
clickCount,
timeDiff,
hideTime: config.hideTime,
maxClicks: config.maxClicks,
shouldShow
});
return shouldShow;
} catch (error) {
console.log(`Error parsing state for ID ${bannerId}:`, error);
return true; // При ошибке показываем
}
};
// Check if current page should show banner
const shouldShowBanner = () => {
const currentPath = location.pathname;
const allowedPaths = [
'/teach/control/stream',
'/pl/teach/control/lesson',
'/sales/control',
'/profile',
'/src-main',
'/src-library/cases',
'/cst-banner-manipulator'
];
return allowedPaths.some(path => currentPath.indexOf(path) !== -1);
};
const bannerDeleted = localStorage.getItem('DeleteCSTBanner');
const isShow = shouldShowBanner();
console.log('Banner script started:', {
isShow,
bannerDeleted,
path: location.pathname
});
if (isShow && !bannerDeleted) {
// Загружаем оба баннера
['corner', 'fullscreen'].forEach(bannerType => {
const config = BANNER_CONFIGS[bannerType];
console.log(`\n=== Processing ${bannerType} banner ===`);
// Всегда делаем fetch, но проверяем после получения HTML
fetch(config.url)
.then(response => response.text())
.then(html => {
const doc = new DOMParser().parseFromString(html, 'text/html');
const bannerItem = doc.querySelector(`.${config.itemClassName}`);
if (!bannerItem) {
console.log(`${config.className}: Banner item not found in HTML`);
return null;
}
const bannerId = bannerItem.className.split(`${config.itemClassName}-`)[1];
console.log(`${config.className}: Found banner with ID ${bannerId}`);
// Проверяем конкретный баннер по ID
if (shouldShowBannerById(config, bannerId)) {
console.log(`${config.className}: Banner ${bannerId} will be shown`);
return doc.querySelector('.lite-page.block-set');
} else {
console.log(`${config.className}: Banner ${bannerId} is hidden`);
return null;
}
})
.then(bannerContent => {
if (bannerContent) {
new Banner(bannerContent, config).init();
}
})
.catch(error => console.log(`Failed to fetch ${bannerType} banner: `, error));
});
}
})();