/** * YS Project - User-facing Popup Display System * - Mobile: Full-screen popups, one at a time (highest priority first) * - PC: Up to 3 popups side by side, overflow stacked behind * - "오늘하루 보지않기" uses localStorage with date key */ (function () { 'use strict'; var MOBILE_BREAKPOINT = 768; var PC_MAX_VISIBLE = 3; // ── Cookie / localStorage helpers ── function getTodayKey() { var d = new Date(); var y = d.getFullYear(); var m = String(d.getMonth() + 1).padStart(2, '0'); var dd = String(d.getDate()).padStart(2, '0'); return 'ys_popup_hide_' + y + m + dd; } function getHiddenPopupIds() { try { var key = getTodayKey(); var stored = localStorage.getItem(key); if (stored) { return JSON.parse(stored); } } catch (e) {} return []; } function hidePopupForToday(popupId) { try { var key = getTodayKey(); var ids = getHiddenPopupIds(); if (ids.indexOf(popupId) === -1) { ids.push(popupId); } localStorage.setItem(key, JSON.stringify(ids)); // Clean up old keys (keep only today's) cleanupOldKeys(key); } catch (e) {} } function cleanupOldKeys(todayKey) { try { var keysToRemove = []; for (var i = 0; i < localStorage.length; i++) { var k = localStorage.key(i); if (k && k.indexOf('ys_popup_hide_') === 0 && k !== todayKey) { keysToRemove.push(k); } } for (var j = 0; j < keysToRemove.length; j++) { localStorage.removeItem(keysToRemove[j]); } } catch (e) {} } // ── Check if mobile ── function isMobile() { return window.innerWidth <= MOBILE_BREAKPOINT; } // ── Fetch popups and display ── function init() { fetch('/api/popups.php') .then(function (r) { return r.json(); }) .then(function (data) { if (!data.success || !data.data.popups || data.data.popups.length === 0) { return; } var hiddenIds = getHiddenPopupIds(); var popups = data.data.popups.filter(function (p) { return hiddenIds.indexOf(String(p.popup_id)) === -1 && hiddenIds.indexOf(Number(p.popup_id)) === -1; }); if (popups.length === 0) return; renderPopups(popups); }) .catch(function () { // Silently fail - popups are not critical }); } // ── Render popup UI ── function renderPopups(popups) { // Create overlay var overlay = document.createElement('div'); overlay.className = 'popup-overlay'; overlay.id = 'ysPopupOverlay'; // Create container var container = document.createElement('div'); container.className = 'popup-container'; container.id = 'ysPopupContainer'; // Track state var state = { popups: popups, mobileIndex: 0, // current popup index for mobile }; // Create popup windows for (var i = 0; i < popups.length; i++) { var popup = popups[i]; var win = createPopupWindow(popup, i, state, overlay); container.appendChild(win); } overlay.appendChild(container); document.body.appendChild(overlay); // Apply visibility based on device updateVisibility(state, overlay); // Handle resize var resizeTimer; window.addEventListener('resize', function () { clearTimeout(resizeTimer); resizeTimer = setTimeout(function () { updateVisibility(state, overlay); }, 150); }); // Prevent body scroll when popup is open document.body.style.overflow = 'hidden'; } // ── Create individual popup window ── function createPopupWindow(popup, index, state, overlay) { var win = document.createElement('div'); win.className = 'popup-window'; win.setAttribute('data-popup-id', popup.popup_id); win.setAttribute('data-popup-index', index); // Content area var content = document.createElement('div'); content.className = 'popup-window__content'; content.innerHTML = popup.content; win.appendChild(content); // Footer with buttons var footer = document.createElement('div'); footer.className = 'popup-window__footer'; // "오늘하루 보지않기" button var btnToday = document.createElement('button'); btnToday.className = 'popup-window__btn popup-window__btn--today'; btnToday.type = 'button'; btnToday.textContent = '오늘하루 보지않기'; btnToday.addEventListener('click', function () { hidePopupForToday(String(popup.popup_id)); closePopup(win, index, state, overlay); }); footer.appendChild(btnToday); // "닫기" button var btnClose = document.createElement('button'); btnClose.className = 'popup-window__btn popup-window__btn--close'; btnClose.type = 'button'; btnClose.textContent = '닫기'; btnClose.addEventListener('click', function () { closePopup(win, index, state, overlay); }); footer.appendChild(btnClose); win.appendChild(footer); return win; } // ── Close a popup ── function closePopup(win, index, state, overlay) { // Mark this popup as closed win.setAttribute('data-closed', '1'); win.style.display = 'none'; if (isMobile()) { // Show next unclosed popup var nextFound = false; var windows = overlay.querySelectorAll('.popup-window'); for (var i = 0; i < windows.length; i++) { if (windows[i].getAttribute('data-closed') !== '1') { state.mobileIndex = parseInt(windows[i].getAttribute('data-popup-index')); nextFound = true; break; } } if (!nextFound) { // All popups closed removeOverlay(overlay); return; } updateVisibility(state, overlay); } else { // PC: check if all visible popups are closed var anyVisible = false; var windows = overlay.querySelectorAll('.popup-window'); for (var i = 0; i < windows.length; i++) { if (windows[i].getAttribute('data-closed') !== '1') { anyVisible = true; break; } } if (!anyVisible) { removeOverlay(overlay); return; } // Re-layout remaining popups updateVisibility(state, overlay); } } // ── Remove overlay entirely ── function removeOverlay(overlay) { document.body.style.overflow = ''; if (overlay.parentNode) { overlay.parentNode.removeChild(overlay); } } // ── Update visibility of popup windows based on device ── function updateVisibility(state, overlay) { var windows = overlay.querySelectorAll('.popup-window'); var mobile = isMobile(); // Collect unclosed windows var unclosed = []; for (var i = 0; i < windows.length; i++) { if (windows[i].getAttribute('data-closed') !== '1') { unclosed.push(windows[i]); } } if (unclosed.length === 0) { removeOverlay(overlay); return; } if (mobile) { // Mobile: show only the first unclosed popup for (var i = 0; i < unclosed.length; i++) { if (i === 0) { unclosed[i].style.display = ''; unclosed[i].classList.remove('popup-window--mobile-hidden'); unclosed[i].classList.remove('popup-window--stacked'); } else { unclosed[i].classList.add('popup-window--mobile-hidden'); unclosed[i].classList.remove('popup-window--stacked'); unclosed[i].style.display = 'none'; } } } else { // PC: show first 3, stack the rest for (var i = 0; i < unclosed.length; i++) { unclosed[i].style.display = ''; unclosed[i].classList.remove('popup-window--mobile-hidden'); if (i < PC_MAX_VISIBLE) { unclosed[i].classList.remove('popup-window--stacked'); unclosed[i].style.zIndex = PC_MAX_VISIBLE - i; } else { unclosed[i].classList.add('popup-window--stacked'); unclosed[i].style.zIndex = 0; } } } } // ── Start after DOM is ready ── if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();