(function () { 'use strict'; gsap.registerPlugin(ScrollTrigger, ScrollToPlugin); function getHeaderEl() { return document.querySelector('.shopby-header:not(template), shopby-header-v2, .shopby-header, header'); } function getHeaderH() { var el = getHeaderEl(); if (el) { return el.offsetHeight || Math.round(el.getBoundingClientRect().height) || 0; } return 0; } function updateHeaderH() { var h = getHeaderH(); if (h > 0) { document.documentElement.style.setProperty('--header-height', h + 'px'); } return h; } updateHeaderH(); var headerReady = false; var headerCheckTimer = setInterval(function () { var h = updateHeaderH(); if (h > 0) { clearInterval(headerCheckTimer); if (!headerReady) { headerReady = true; alignToCurrentSection(); } } }, 100); setTimeout(function () { clearInterval(headerCheckTimer); }, 3000); var sections = document.querySelectorAll('.promo-section'); var indicator = document.getElementById('promoIndicator'); var indicatorDots = document.querySelectorAll('.promo-page-indicator .indicator-dot'); var isScrolling = false; var scrollCooldown = 50; var currentActiveSection = sections[0]; // inner 포커스 가능 설정 sections.forEach(function (s) { var inner = s.querySelector('.promo-section-inner'); if (inner) { inner.setAttribute('tabindex', '-1'); inner.style.outline = 'none'; } }); // 유틸 function focusInner(section) { if (!section) return; var inner = section.querySelector('.promo-section-inner'); if (inner) inner.focus({ preventScroll: true }); } function getVisibleSection() { var headerH = getHeaderH(); var best = null, bestOvr = 0; sections.forEach(function (s) { var r = s.getBoundingClientRect(); var ovr = Math.min(r.bottom, window.innerHeight) - Math.max(r.top, headerH); if (ovr > bestOvr) { bestOvr = ovr; best = s; } }); return best; } // 인디케이터 표시/숨김 function updateIndicatorVisibility() { if (!indicator || !sections.length) return; var firstRect = sections[0].getBoundingClientRect(); var lastRect = sections[sections.length - 1].getBoundingClientRect(); if (firstRect.top <= window.innerHeight && lastRect.bottom > 0) { indicator.classList.add('visible'); } else { indicator.classList.remove('visible'); } } // 인디케이터 active 업데이트 function updateActive() { var headerH = getHeaderH(); var currentId = ''; sections.forEach(function (s) { var r = s.getBoundingClientRect(); if (r.top <= headerH + 100 && r.bottom > headerH) { currentId = s.id; if (!isScrolling) currentActiveSection = s; } }); if (!currentId) return; indicatorDots.forEach(function (dot) { if (dot.getAttribute('data-target') === currentId) dot.classList.add('active'); else dot.classList.remove('active'); }); if (currentId === 'section-03') { playFullVideo(); } else { pauseFullVideo(); } if (currentId === 'section-04') { playMyNameVideo(); } else { pauseMyNameVideo(); } if (currentId !== 'section-02') { pauseYouTube(); } } // 인디케이터 도트 클릭 indicatorDots.forEach(function (dot) { dot.addEventListener('click', function () { var target = document.getElementById(dot.getAttribute('data-target')); if (!target) return; currentActiveSection = target; if (target.id === 'section-03') { playFullVideo(); } else { pauseFullVideo(); } if (target.id === 'section-04') { playMyNameVideo(); } else { pauseMyNameVideo(); } if (target.id !== 'section-02') { pauseYouTube(); } var inner = target.querySelector('.promo-section-inner'); if (inner) inner.scrollTop = 0; var headerH = getHeaderH(); var y = (window.scrollY || window.pageYOffset) + target.getBoundingClientRect().top - headerH; isScrolling = true; gsap.to(window, { scrollTo: { y: y, autoKill: false }, duration: 0.6, ease: 'power2.out', onComplete: function () { if (inner) inner.scrollTop = 0; updateActive(); focusInner(target); setTimeout(function () { isScrolling = false; }, 80); } }); }); }); // 섹션 전환 function scrollToSection(section, startAtBottom) { if (!section || isScrolling) return; currentActiveSection = section; wheelAcc = 0; if (section.id === 'section-03') { playFullVideo(); } else { pauseFullVideo(); } if (section.id === 'section-04') { playMyNameVideo(); } else { pauseMyNameVideo(); } if (section.id !== 'section-02') { pauseYouTube(); } var inner = section.querySelector('.promo-section-inner'); var isSinglePage = inner && (inner.scrollHeight <= inner.clientHeight + 2); var headerH = getHeaderH(); var y = (window.scrollY || window.pageYOffset) + section.getBoundingClientRect().top - headerH; isScrolling = true; gsap.to(window, { scrollTo: { y: y, autoKill: false }, duration: 0.6, ease: 'power2.out', onComplete: function () { if (inner) { inner.scrollTop = startAtBottom ? (inner.scrollHeight - inner.clientHeight) : 0; } updateActive(); focusInner(section); wheelAcc = 0; var actualCooldown = isSinglePage ? 250 : scrollCooldown; setTimeout(function () { isScrolling = false; wheelAcc = 0; }, actualCooldown); } }); } function getNext(cur) { var a = Array.from(sections), i = a.indexOf(cur); return i < a.length - 1 ? a[i + 1] : null; } function getPrev(cur) { var a = Array.from(sections), i = a.indexOf(cur); return i > 0 ? a[i - 1] : null; } var wheelAcc = 0, wheelThreshold = 40, singlePageThreshold = 100, wheelTimer = null; function handleGlobalWheel(e) { if (isScrolling) { e.preventDefault(); return; } var headerH = getHeaderH(); var firstSec = sections[0]; var firstSecOffset = firstSec ? Math.round(firstSec.getBoundingClientRect().top - headerH) : 0; var lastSec = sections[sections.length - 1]; var lastSecOffset = lastSec ? Math.round(lastSec.getBoundingClientRect().top - headerH) : 0; if (firstSecOffset > 5) { if (e.target && (e.target.closest && e.target.closest('.LOVE16th-promotion'))) { e.preventDefault(); window.scrollBy(0, e.deltaY); } return; } if (lastSecOffset < -10 && e.deltaY > 0) return; if (lastSecOffset < -2 && e.deltaY < 0) { e.preventDefault(); wheelAcc += e.deltaY; if (wheelAcc < -30) { scrollToSection(lastSec, true); wheelAcc = 0; } clearTimeout(wheelTimer); wheelTimer = setTimeout(function () { wheelAcc = 0; }, 300); return; } var vs = currentActiveSection || getVisibleSection(); if (!vs) return; var inner = vs.querySelector('.promo-section-inner'); if (!inner) return; var sTop = inner.scrollTop, sH = inner.scrollHeight, cH = inner.clientHeight; var atTop = sTop <= 2; var atBottom = sTop + cH >= sH - 6; var d = e.deltaY; if (sH <= cH + 2) { if (d > 0 && !getNext(vs)) { e.preventDefault(); wheelAcc += d; if (wheelAcc > singlePageThreshold) { var footer = document.getElementById('footer_wrap'); if (footer) { pauseYouTube(); pauseFullVideo(); isScrolling = true; gsap.to(window, { scrollTo: (window.scrollY || window.pageYOffset) + footer.getBoundingClientRect().top, duration: 0.6, onComplete: function () { isScrolling = false; } }); } wheelAcc = 0; } clearTimeout(wheelTimer); wheelTimer = setTimeout(function () { wheelAcc = 0; }, 300); return; } if (d < 0 && !getPrev(vs)) { e.preventDefault(); wheelAcc += d; if (wheelAcc < -singlePageThreshold) { pauseYouTube(); pauseFullVideo(); isScrolling = true; gsap.to(window, { scrollTo: 0, duration: 0.6, onComplete: function () { isScrolling = false; } }); wheelAcc = 0; } clearTimeout(wheelTimer); wheelTimer = setTimeout(function () { wheelAcc = 0; }, 300); return; } e.preventDefault(); wheelAcc += d; if (Math.abs(wheelAcc) > singlePageThreshold) { if (wheelAcc > 0) scrollToSection(getNext(vs), false); else scrollToSection(getPrev(vs), true); wheelAcc = 0; } clearTimeout(wheelTimer); wheelTimer = setTimeout(function () { wheelAcc = 0; }, 300); return; } if (d > 0 && atBottom && !getNext(vs)) { e.preventDefault(); wheelAcc += d; if (wheelAcc > 80) { var footer = document.getElementById('footer_wrap'); if (footer) { pauseYouTube(); pauseFullVideo(); isScrolling = true; gsap.to(window, { scrollTo: (window.scrollY || window.pageYOffset) + footer.getBoundingClientRect().top, duration: 0.6, onComplete: function () { isScrolling = false; } }); } wheelAcc = 0; } clearTimeout(wheelTimer); wheelTimer = setTimeout(function () { wheelAcc = 0; }, 300); return; } if (d > 0 && atBottom) { e.preventDefault(); wheelAcc += d; if (wheelAcc > wheelThreshold) { scrollToSection(getNext(vs), false); wheelAcc = 0; } clearTimeout(wheelTimer); wheelTimer = setTimeout(function () { wheelAcc = 0; }, 200); return; } if (d < 0 && atTop && !getPrev(vs)) { e.preventDefault(); wheelAcc += d; if (wheelAcc < -80) { pauseYouTube(); pauseFullVideo(); isScrolling = true; gsap.to(window, { scrollTo: 0, duration: 0.6, onComplete: function () { isScrolling = false; } }); wheelAcc = 0; } clearTimeout(wheelTimer); wheelTimer = setTimeout(function () { wheelAcc = 0; }, 300); return; } if (d < 0 && atTop) { e.preventDefault(); wheelAcc += d; if (wheelAcc < -wheelThreshold) { scrollToSection(getPrev(vs), true); wheelAcc = 0; } clearTimeout(wheelTimer); wheelTimer = setTimeout(function () { wheelAcc = 0; }, 200); return; } // 섹션 내부에서 일반 스크롤 중일 때: 윈도우 스크롤을 완전히 차단하고 inner만 스크롤 e.preventDefault(); wheelAcc = 0; inner.scrollTop += d; } // 단일 글로벌 휠 리스너 등록 window.addEventListener('wheel', handleGlobalWheel, { passive: false }); // 터치 & 스와이프 (모바일 완전 연동) var touchStartY = 0, touchLastY = 0, touchT = 0; window.addEventListener('touchstart', function (e) { if (e.touches && e.touches.length) { touchStartY = e.touches[0].clientY; touchLastY = touchStartY; touchT = Date.now(); } }, { passive: true }); window.addEventListener('touchmove', function (e) { if (!e.touches || !e.touches.length) return; var curY = e.touches[0].clientY; var delta = touchLastY - curY; touchLastY = curY; var headerH = getHeaderH(); var firstSec = sections[0]; var firstSecOffset = firstSec ? Math.round(firstSec.getBoundingClientRect().top - headerH) : 0; // 상단 배너/헤더 영역: 섹션이 상단 헤더에 도달하기 전에는 내부 스크롤을 막고 윈도우 스크롤 강제 if (firstSecOffset > 5) { if (e.target && (e.target.closest && e.target.closest('.LOVE16th-promotion'))) { e.preventDefault(); window.scrollBy(0, delta); } return; } }, { passive: false }); // 전역 touchend (푸터에서 복귀 등 감지) window.addEventListener('touchend', function (e) { if (isScrolling || !e.changedTouches || !e.changedTouches.length) return; var lastSec = sections[sections.length - 1]; var headerH = getHeaderH(); var lastSecOffset = lastSec ? Math.round(lastSec.getBoundingClientRect().top - headerH) : 0; var diff = touchStartY - e.changedTouches[0].clientY; // 푸터 영역에서 위로 스와이프 시 4번 섹션으로 정확히 복귀 if (lastSecOffset < -10 && diff < -40) { scrollToSection(lastSec, true); } }, { passive: true }); // 섹션별 touchend (섹션 간 전환) sections.forEach(function (s) { var inner = s.querySelector('.promo-section-inner'); if (!inner) return; inner.addEventListener('touchend', function (e) { if (isScrolling || !e.changedTouches || !e.changedTouches.length) return; var headerH = getHeaderH(); var firstSec = sections[0]; var firstSecOffset = firstSec ? Math.round(firstSec.getBoundingClientRect().top - headerH) : 0; if (firstSecOffset > 5) return; // 상단 헤더 도달 전에는 섹션 전환 차단 var diff = touchStartY - e.changedTouches[0].clientY; if (Date.now() - touchT > 600 || Math.abs(diff) < 50) return; var sTop = inner.scrollTop, sH = inner.scrollHeight, cH = inner.clientHeight; // 1페이지 섹션 (프로모션 등) if (sH <= cH + 2) { if (diff > 0) { if (getNext(s)) scrollToSection(getNext(s), false); else { var footer = document.getElementById('footer_wrap'); if (footer) { isScrolling = true; gsap.to(window, { scrollTo: (window.scrollY || window.pageYOffset) + footer.getBoundingClientRect().top, duration: 0.6, ease: 'power2.out', onComplete: function () { isScrolling = false; } }); } } } else { if (getPrev(s)) scrollToSection(getPrev(s), true); else { isScrolling = true; gsap.to(window, { scrollTo: 0, duration: 0.6, ease: 'power2.out', onComplete: function () { isScrolling = false; } }); } } return; } // 다중 페이지 섹션 if (diff > 0 && sTop + cH >= sH - 10) { if (getNext(s)) scrollToSection(getNext(s), false); else { var footer = document.getElementById('footer_wrap'); if (footer) { isScrolling = true; gsap.to(window, { scrollTo: (window.scrollY || window.pageYOffset) + footer.getBoundingClientRect().top, duration: 0.6, ease: 'power2.out', onComplete: function () { isScrolling = false; } }); } } } else if (diff < 0 && sTop <= 10) { if (getPrev(s)) scrollToSection(getPrev(s), true); else { isScrolling = true; gsap.to(window, { scrollTo: 0, duration: 0.6, ease: 'power2.out', onComplete: function () { isScrolling = false; } }); } } }, { passive: true }); }); // 윈도우 스크롤 var raf = null; window.addEventListener('scroll', function () { if (raf) cancelAnimationFrame(raf); raf = requestAnimationFrame(function () { updateIndicatorVisibility(); if (!isScrolling) updateActive(); }); }); // 리사이즈 + 전체화면 전환 시 페이드 오버레이 + 재초기화 var resizeOverlay = document.createElement('div'); resizeOverlay.className = 'promo-resize-overlay'; document.body.appendChild(resizeOverlay); var rt = null; var lastWidth = window.innerWidth; var lastHeight = window.innerHeight; function getScrollZone() { var headerH = getHeaderH(); var firstSec = sections[0]; var firstSecOffset = firstSec ? Math.round(firstSec.getBoundingClientRect().top - headerH) : 0; if (firstSecOffset > 5) { return { type: 'TOP', scrollY: window.scrollY || window.pageYOffset }; } var lastSec = sections[sections.length - 1]; var lastSecOffset = lastSec ? Math.round(lastSec.getBoundingClientRect().top - headerH) : 0; if (lastSecOffset < -10) { return { type: 'FOOTER', scrollY: window.scrollY || window.pageYOffset }; } var vs = getVisibleSection(); var inner = vs ? vs.querySelector('.promo-section-inner') : null; return { type: 'SECTION', sectionId: vs ? vs.id : null, innerScroll: inner ? inner.scrollTop : 0 }; } /* function handleResizeReinit() { updateHeaderH(); var newW = window.innerWidth; var newH = window.innerHeight; // 크기 변화 없으면 무시 if (newW === lastWidth && newH === lastHeight) return; lastWidth = newW; lastHeight = newH; // 현재 머물고 있는 구역(TOP / FOOTER / SECTION) 기억 var zone = getScrollZone(); // 페이드인 (흰 화면) resizeOverlay.classList.add('active'); clearTimeout(rt); rt = setTimeout(function () { // ScrollTrigger 갱신 ScrollTrigger.refresh(); if (zone.type === 'TOP') { // 상단 배너/헤더에 있었으면 그대로 상단 유지 window.scrollTo(0, 0); } else if (zone.type === 'FOOTER') { // 푸터에 있었으면 푸터 위치로 유지 var footer = document.getElementById('footer_wrap'); if (footer) { var footY = (window.scrollY || window.pageYOffset) + footer.getBoundingClientRect().top; window.scrollTo(0, footY); } } else if (zone.type === 'SECTION' && zone.sectionId) { // 풀페이지 내부 섹션에 있었을 때만 해당 섹션으로 정확히 도킹 및 내부 스크롤 복원 var target = document.getElementById(zone.sectionId); if (target) { var headerH = getHeaderH(); var y = target.getBoundingClientRect().top + (window.scrollY || window.pageYOffset) - headerH; window.scrollTo(0, y); var inner = target.querySelector('.promo-section-inner'); if (inner && zone.innerScroll) inner.scrollTop = zone.innerScroll; focusInner(target); } } updateActive(); updateIndicatorVisibility(); // 페이드아웃 setTimeout(function () { resizeOverlay.classList.remove('active'); }, 150); }, 300); } window.addEventListener('resize', handleResizeReinit); // 전체화면 전환 감지 document.addEventListener('fullscreenchange', handleResizeReinit); document.addEventListener('webkitfullscreenchange', handleResizeReinit); */ // 스크롤 위치 저장 (sessionStorage) function saveScrollState() { var zone = getScrollZone(); sessionStorage.setItem('promo_zone_type', zone.type); if (zone.type === 'TOP') { sessionStorage.setItem('promo_scrollY', zone.scrollY); } else if (zone.type === 'FOOTER') { sessionStorage.setItem('promo_zone_type', 'FOOTER'); } else if (zone.type === 'SECTION' && zone.sectionId) { sessionStorage.setItem('promo_section', zone.sectionId); sessionStorage.setItem('promo_innerScroll', zone.innerScroll); } } window.addEventListener('beforeunload', saveScrollState); // 현재 활성 섹션으로 정확하게 위치 정렬 function alignToCurrentSection() { var vs = currentActiveSection || getVisibleSection() || sections[0]; if (!vs) return; var headerH = getHeaderH(); var y = vs.getBoundingClientRect().top + (window.scrollY || window.pageYOffset) - headerH; window.scrollTo(0, y); updateActive(); updateIndicatorVisibility(); } // 댓글 영역으로 스크롤 및 입력창 포커스 function scrollToCommentBox(options) { var section05 = document.getElementById('section-05'); if (!section05) return; currentActiveSection = section05; var headerH = getHeaderH(); var secY = section05.getBoundingClientRect().top + (window.scrollY || window.pageYOffset) - headerH; if (options && options.smooth && typeof gsap !== 'undefined') { gsap.to(window, { scrollTo: { y: secY, autoKill: false }, duration: 0.5, ease: 'power2.out', onComplete: function () { updateActive(); updateIndicatorVisibility(); } }); } else { window.scrollTo(0, secY); updateActive(); updateIndicatorVisibility(); } var inner = section05.querySelector('.promo-section-inner'); if (!inner) return; var commentBox = document.getElementById('commtent_box') || section05.querySelector('.commtent_box') || section05.querySelector('article-comments'); if (commentBox) { // 1. 댓글 박스 아래 충분한 스크롤 여백(최소 300px 또는 뷰포트 높이의 40%)을 확보하여 스크롤이 바닥에 걸려 멈추지 않도록 함 var minBottomPadding = Math.max(300, Math.round(window.innerHeight * 0.4)); commentBox.style.paddingBottom = minBottomPadding + 'px'; // 2. 폼/입력 영역(#form-comment)을 타겟으로 하여, 댓글 작성창이 상단 헤더 바로 아래(약 20px 여백)에 오도록 위치 계산 var targetEl = document.getElementById('form-comment') || commentBox; var innerRect = inner.getBoundingClientRect(); var boxRect = targetEl.getBoundingClientRect(); var targetScrollTop = Math.max(0, inner.scrollTop + (boxRect.top - innerRect.top) - 20); if (options && options.smooth) { inner.scrollTo({ top: targetScrollTop, behavior: 'smooth' }); } else { inner.scrollTop = targetScrollTop; } } if (options && options.focus) { var textarea = document.querySelector('#article-comment'); if (textarea) { textarea.focus(); } } } window.LOVE16thScrollToComment = scrollToCommentBox; // 초기화 updateIndicatorVisibility(); // 저장된 위치 복원 var savedZoneType = sessionStorage.getItem('promo_zone_type'); var savedSection = sessionStorage.getItem('promo_section'); var savedInnerScroll = sessionStorage.getItem('promo_innerScroll'); var urlParams = new URLSearchParams(location.search); var isTargetComment = urlParams.get('target') === 'comment' || location.hash === '#commtent_box' || location.hash === '#comment' || sessionStorage.getItem('LOVE16th_scroll_target') === 'comment'; window.isLOVE16thTargetComment = isTargetComment; if (isTargetComment) { var section05 = document.getElementById('section-05'); if (section05) { currentActiveSection = section05; scrollToCommentBox({ smooth: false, focus: false }); focusInner(section05); var sec05Imgs = section05.querySelectorAll('img'); sec05Imgs.forEach(function (img) { if (!img.complete) { img.addEventListener('load', function () { scrollToCommentBox({ smooth: false, focus: false }); }, { once: true }); } }); } } else if (savedZoneType === 'TOP') { window.scrollTo(0, 0); } else if (savedZoneType === 'FOOTER') { var footer = document.getElementById('footer_wrap'); if (footer) { window.scrollTo(0, (window.scrollY || window.pageYOffset) + footer.getBoundingClientRect().top); } } else if (savedSection) { var target = document.getElementById(savedSection); if (target) { currentActiveSection = target; var headerH = getHeaderH(); var y = target.getBoundingClientRect().top + (window.scrollY || window.pageYOffset) - headerH; window.scrollTo(0, y); var inner = target.querySelector('.promo-section-inner'); if (inner && savedInnerScroll) { inner.scrollTop = parseInt(savedInnerScroll, 10); var targetImgs = target.querySelectorAll('img'); targetImgs.forEach(function (img) { if (!img.complete) { img.addEventListener('load', function () { if (inner && savedInnerScroll) inner.scrollTop = parseInt(savedInnerScroll, 10); }, { once: true }); } }); } focusInner(target); } } else { // 새로고침 시 첫 번째 섹션으로 정확하게 정렬 currentActiveSection = sections[0]; alignToCurrentSection(); focusInner(sections[0]); } sessionStorage.removeItem('promo_zone_type'); sessionStorage.removeItem('promo_section'); sessionStorage.removeItem('promo_innerScroll'); sessionStorage.removeItem('promo_scrollY'); // ============================================ // 카운트다운 타이머 UI 스크립트 // ============================================ function initCountdown() { var countdownBox = document.getElementById('countdown'); if (!countdownBox) return; // 목표 일시 (data-target-date 속성이 있으면 우선 사용, 없으면 아래 기본값 사용) // 형식 예: '2026-09-18T11:00:00+09:00' var DEFAULT_TARGET = '2026-09-17T11:00:00+09:00'; var targetAttr = countdownBox.getAttribute('data-target-date'); var targetTime = new Date(targetAttr || DEFAULT_TARGET).getTime(); function renderDigits(elementId, value) { var el = document.getElementById(elementId); if (!el) return; var str = String(Math.max(0, value)).padStart(2, '0'); var spans = el.querySelectorAll('span'); if (spans.length === str.length) { for (var i = 0; i < spans.length; i++) { if (spans[i].textContent !== str[i]) { spans[i].textContent = str[i]; } } } else { var html = ''; for (var i = 0; i < str.length; i++) { html += '' + str[i] + ''; } el.innerHTML = html; } } function updateCountdown() { var now = Date.now(); var distance = targetTime - now; var isFinished = distance <= 0; if (isFinished) { distance = 0; } var days = Math.floor(distance / (1000 * 60 * 60 * 24)); var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)); var seconds = Math.floor((distance % (1000 * 60)) / 1000); renderDigits('days', days); renderDigits('hours', hours); renderDigits('minutes', minutes); renderDigits('seconds', seconds); if (isFinished && timer) { clearInterval(timer); } } updateCountdown(); var timer = setInterval(updateCountdown, 1000); } // 유튜브 비디오 일시정지 function pauseYouTube() { var ytbPlayer = document.getElementById('ytbPlayer'); var iframe = ytbPlayer ? ytbPlayer.querySelector('iframe') : null; if (iframe && iframe.contentWindow) { iframe.contentWindow.postMessage(JSON.stringify({ event: 'command', func: 'pauseVideo', args: '' }), '*'); } } // 유튜브 비디오 (클릭 시 재생 / 자동재생 X / 플레이리스트 X / 최소 컨트롤) function initYouTube() { var btnYtb = document.getElementById('btnYtb'); var ytbPlayer = document.getElementById('ytbPlayer'); var ytbBox = document.getElementById('ytbBox'); if (!btnYtb || !ytbPlayer) return; var videoId = '6AMzCEWPOf0'; btnYtb.addEventListener('click', function () { btnYtb.style.display = 'none'; var originParam = location.origin && location.origin !== 'null' ? '&origin=' + encodeURIComponent(location.origin) : ''; var iframeUrl = 'https://www.youtube.com/embed/' + videoId + '?autoplay=1&mute=1&rel=0&modestbranding=1&controls=0&playsinline=1&iv_load_policy=3&enablejsapi=1&fs=0&disablekb=1' + originParam; ytbPlayer.innerHTML = ''; }); btnYtb.addEventListener('keydown', function (e) { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); btnYtb.click(); } }); // 재생 중 영상 영역 클릭 시 일시정지 / 재생 토글 var isYtbPlaying = true; if (ytbBox) { ytbBox.addEventListener('click', function () { if (btnYtb && btnYtb.style.display !== 'none') return; var iframe = ytbPlayer ? ytbPlayer.querySelector('iframe') : null; if (!iframe || !iframe.contentWindow) return; if (isYtbPlaying) { iframe.contentWindow.postMessage(JSON.stringify({ event: 'command', func: 'pauseVideo', args: '' }), '*'); isYtbPlaying = false; } else { iframe.contentWindow.postMessage(JSON.stringify({ event: 'command', func: 'playVideo', args: '' }), '*'); isYtbPlaying = true; } }); } // 뷰포트에서 영상 영역이 벗어나면 일시정지 (IntersectionObserver) if ('IntersectionObserver' in window && ytbBox) { var ytbObserver = new IntersectionObserver(function (entries) { entries.forEach(function (entry) { if (!entry.isIntersecting || entry.intersectionRatio < 0.1) { pauseYouTube(); } }); }, { threshold: [0, 0.1] }); ytbObserver.observe(ytbBox); } // 브라우저 탭 전환 시 일시정지 document.addEventListener('visibilitychange', function () { if (document.hidden) { pauseYouTube(); pauseFullVideo(); pauseMyNameVideo(); } else if (currentActiveSection && currentActiveSection.id === 'section-03') { playFullVideo(); } else if (currentActiveSection && currentActiveSection.id === 'section-04') { playMyNameVideo(); } }); } // ============================================ // 풀 비디오 (섹션 03 - 쇼츠 영상) // ============================================ function playFullVideo() { var fullVideoBox = document.getElementById('fullVideoBox'); var fullVideoPlayer = document.getElementById('fullVideoPlayer'); if (!fullVideoBox || !fullVideoPlayer) return; var videoId = 'l7OlLl7snxk'; var iframe = fullVideoPlayer.querySelector('iframe'); if (!iframe) { var originParam = location.origin && location.origin !== 'null' ? '&origin=' + encodeURIComponent(location.origin) : ''; var iframeUrl = 'https://www.youtube.com/embed/' + videoId + '?autoplay=1&mute=1&enablejsapi=1&controls=0&playsinline=1&rel=0&loop=1&playlist=' + videoId + '&iv_load_policy=3&fs=0&disablekb=1&modestbranding=1' + originParam; fullVideoPlayer.innerHTML = ''; } else if (iframe.contentWindow) { iframe.contentWindow.postMessage(JSON.stringify({ event: 'command', func: 'playVideo', args: '' }), '*'); } fullVideoBox.classList.add('is-playing'); } function pauseFullVideo() { var fullVideoBox = document.getElementById('fullVideoBox'); var fullVideoPlayer = document.getElementById('fullVideoPlayer'); if (!fullVideoBox || !fullVideoPlayer) return; var iframe = fullVideoPlayer.querySelector('iframe'); if (iframe && iframe.contentWindow) { iframe.contentWindow.postMessage(JSON.stringify({ event: 'command', func: 'pauseVideo', args: '' }), '*'); } fullVideoBox.classList.remove('is-playing'); } function initFullVideo() { var fullVideoBox = document.getElementById('fullVideoBox'); if (!fullVideoBox) return; fullVideoBox.addEventListener('click', function () { if (fullVideoBox.classList.contains('is-playing')) { pauseFullVideo(); } else { playFullVideo(); } }); fullVideoBox.addEventListener('keydown', function (e) { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); if (fullVideoBox.classList.contains('is-playing')) { pauseFullVideo(); } else { playFullVideo(); } } }); } // ============================================ // My Name 비디오 (섹션 04 - 유튜브 영상) // fullVideoBox와 같은 조건: 진입 시 자동재생, 이탈 시 일시정지, 복귀 시 이어서 재생 // ============================================ function playMyNameVideo() { var myNameVideoBox = document.getElementById('myNameVideoBox'); var myNameVideoPlayer = document.getElementById('myNameVideoPlayer'); if (!myNameVideoBox || !myNameVideoPlayer) return; var videoId = 'CHmveol4HM0'; var iframe = myNameVideoPlayer.querySelector('iframe'); if (!iframe) { var originParam = location.origin && location.origin !== 'null' ? '&origin=' + encodeURIComponent(location.origin) : ''; var iframeUrl = 'https://www.youtube.com/embed/' + videoId + '?autoplay=1&mute=1&enablejsapi=1&controls=0&playsinline=1&rel=0&loop=1&playlist=' + videoId + '&iv_load_policy=3&fs=0&disablekb=1&modestbranding=1' + originParam; myNameVideoPlayer.innerHTML = ''; } else if (iframe.contentWindow) { iframe.contentWindow.postMessage(JSON.stringify({ event: 'command', func: 'playVideo', args: '' }), '*'); } myNameVideoBox.classList.add('is-playing'); } function pauseMyNameVideo() { var myNameVideoBox = document.getElementById('myNameVideoBox'); var myNameVideoPlayer = document.getElementById('myNameVideoPlayer'); if (!myNameVideoBox || !myNameVideoPlayer) return; var iframe = myNameVideoPlayer.querySelector('iframe'); if (iframe && iframe.contentWindow) { iframe.contentWindow.postMessage(JSON.stringify({ event: 'command', func: 'pauseVideo', args: '' }), '*'); } myNameVideoBox.classList.remove('is-playing'); } function initMyNameVideo() { var myNameVideoBox = document.getElementById('myNameVideoBox'); if (!myNameVideoBox) return; myNameVideoBox.addEventListener('click', function () { if (myNameVideoBox.classList.contains('is-playing')) { pauseMyNameVideo(); } else { playMyNameVideo(); } }); myNameVideoBox.addEventListener('keydown', function (e) { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); if (myNameVideoBox.classList.contains('is-playing')) { pauseMyNameVideo(); } else { playMyNameVideo(); } } }); } initCountdown(); initYouTube(); initFullVideo(); initMyNameVideo(); updateActive(); })(); // ============================================ // 댓글 시스템 (LOVE15th.js에서 이식) // boardNo, articleNo는 실제 사용할 게시판/게시물 번호로 변경 필요 // ============================================ (() => { const { EventManager, utils } = ShopbySkin; //실제 사용할 게시판 번호, 게시물번호로 작성 const boardNo = 260850; const articleNo = 156842; let shopbyCommonData = {}; let _currentBoard = {}; let _currentComments = {}; EventManager.on("PAGE_LOAD_COMPLETED", (commonData) => { helperLMUtil.log("PAGE_LOAD_COMPLETED", commonData); shopbyCommonData = commonData; initComments(); }); let _hasScrolledToCommentOnLoad = false; const redirectLoginPage = () => { try { sessionStorage.setItem('LOVE16th_scroll_target', 'comment'); const commentVal = document.querySelector("#article-comment")?.value; if (commentVal && commentVal.trim()) { sessionStorage.setItem('LOVE16th_comment_draft', commentVal); } } catch (e) { helperLMUtil.log("redirectLoginPage error", e); } const nextUrl = `${location.origin}/pages/sign-in/sign-in.html`; const returnUrl = new URL(location.href); returnUrl.searchParams.set('target', 'comment'); returnUrl.hash = 'commtent_box'; location.href = `${nextUrl}?from=${encodeURIComponent(returnUrl.toString())}`; }; const refreshArticleComments = (page = 1) => { helperLMRequest.request(`articles/comments?article_id=${articleNo}&page=${page}`) .then(({ comments }) => presentaionArticleComments(comments)); }; const deleteAction = (state) => { const param = { boardNo: boardNo, articleNo: articleNo, }; const { password = '' } = state ?? {}; if (password) param.password = password; const { isArticleComment = false, commentNo } = state ?? {}; const deletingArticleNo = isArticleComment ? commentNo : articleNo; helperLMRequest.request(`articles/${deletingArticleNo}`, { method: "DELETE", body: JSON.stringify(param) }) .then(response => { helperLMUtil.log("deleteAction response", response); if (response.result && response.result.success) EventManager.fire('MODAL_ALERT_OPEN', { noticeType: 'SUCCESS', message: '삭제가 완료되었습니다.', onClose: () => refreshArticleComments(), }); }); }; const postArticleComment = async () => { const formData = Object.fromEntries(new FormData(document.querySelector("#form-comment"))); helperLMUtil.log("postArticleComment formData", formData); const refArticleComment = document.querySelector("#article-comment"); const refButtonArticleComment = document.querySelector("#article-comment + button"); const postData = { parentArticleNo: articleNo, boardNo: boardNo, writer: shopbyCommonData.profile?.memberName || "비회원", writerEmail: shopbyCommonData.profile?.email, memberId: shopbyCommonData.profile?.memberId || "GUEST", title: `[댓글]`, content: formData.content, }; if (!formData.content) { EventManager.fire('MODAL_ALERT_OPEN', { message: '댓글을 입력하세요', }); return; } else if (formData.secret == "1") { postData.secret = formData.secret; postData.password = formData.password; if (!formData.password) { EventManager.fire('MODAL_ALERT_OPEN', { message: "비밀번호를 입력하세요", }); return; } } refArticleComment.disabled = true; refButtonArticleComment.disabled = true; const proc = []; proc.push(helperLMUtil.wait(1000)); proc.push(helperLMRequest.request("articles", { method: "POST", body: JSON.stringify(postData) })); const res = await Promise.all(proc); helperLMUtil.log('postBoardArticle res', res); refreshArticleComments(); refArticleComment.value = ""; refArticleComment.disabled = false; refButtonArticleComment.disabled = false; }; const moduleActionHandler = { EDITOR_COMMENT: ({ target }) => { if (!utils.isSignIn() && _currentBoard.comment_permission != "all") { EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'CAUTION', message: '회원만 이용 가능합니다.
로그인 하시겠습니까?
', onConfirm: redirectLoginPage, }); target.blur(); } }, WRITE_COMMENT: ({ target }) => { helperLMUtil.log('WRITE_COMMENT', target); if (!utils.isSignIn() && _currentBoard.comment_permission != "all") { EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'CAUTION', message: '회원만 이용 가능합니다.
로그인 하시겠습니까?
', onConfirm: redirectLoginPage, }); return; } postArticleComment(); }, DELETE_COMMENT: ({ target }) => { const commentNo = target.getAttribute("shopby-article-no"); helperLMUtil.log("DELETE_COMMENT", commentNo); EventManager.fire('MODAL_CONFIRM_OPEN', { noticeType: 'WARNING', message: `게시글을 삭제하시겠습니까?`, onConfirm: () => deleteAction({ isArticleComment: true, commentNo }), }); }, MOVE_PAGE_COMMENTS: ({ target }) => { const dataParam = target.closest("[data-param]")?.getAttribute("data-param"); const page = dataParam ? dataParam.split("page=").pop() : target.textContent; const isCurrent = target.classList.contains("is-current"); helperLMUtil.log("MOVE_PAGE_COMMENTS", page, isCurrent); if (!isCurrent) refreshArticleComments(page); }, FREE_COMMENT: ({ target }) => { const refComment = target.closest("[shopby-article-no]"); const commentNo = refComment.getAttribute("shopby-article-no"); const found = _currentComments.data.find(comment => comment.id == commentNo); helperLMUtil.log("FREE_COMMENT", commentNo, found, target); window["__watchingComment"] = found; EventManager.fire('OPEN_LAYER_MODAL', { name: 'check-comment-password-form', title: '비밀번호 인증', isFull: false, onClose: ({ reason, state = {} }) => { helperLMUtil.log("check-comment-password-form", reason, state); if (reason === 'DID_SUBMIT') { refComment.classList.remove("text-muted"); refComment.setAttribute("shopby-action", "done"); refComment.innerHTML = found.content.replace(/(\r\n|\n|\r)/gm, '
'); } }, }); } }; const getMemberId = () => utils.isSignIn() ? shopbyCommonData.profile?.memberId : "GUEST"; const getMallName = () => shopbyCommonData.profile?.mallName; const checkArticleWriter = (article) => { const prefixManagers = ["운영자"]; const prefixGuests = ["GUEST"]; article.memberId = prefixManagers.includes(article.writer) ? article.writer : article.member_id && !prefixGuests.includes(article.member_id.toUpperCase()) ? article.member_id.slice(0, 3) + "*".repeat(article.member_id.length - 3) : article.writer.slice(0, 1) + "*".repeat(article.writer.length - 1); return article.memberId; }; const presentaionArticleComments = (comments) => { const supportComment = ["all", "member"]; _currentComments = comments; comments.data.forEach(element => { element.memberId = checkArticleWriter(element); element.modifiable = element.member_id != "GUEST" && element.member_id == getMemberId(); element.seceretComment = element.secret == "1" && !element.modifiable; }); comments.lastPage = Math.ceil(comments.total / comments.per_page); comments.useComment = _currentBoard.use_comment == "1"; comments.canPostComment = supportComment.includes(_currentBoard.comment_permission); comments.canCommentSecret = _currentBoard.comment_seceret != "2"; comments.disabledCommentSecret = _currentBoard.comment_seceret == "3"; comments.checkedCommentSecret = _currentBoard.comment_seceret % 2 == 1 ? "checked" : ""; comments.passwordType = utils.isSignIn() ? "hidden" : "password"; comments.prefixPassword = utils.isSignIn() ? `${getMemberId()}@${getMallName()}` : ""; if (comments.total > comments.per_page) comments.pagination = helperLMUtil.calcPagination(comments); helperLMUtil.renderTemplate(document, "article-comments", comments); var urlParams = new URLSearchParams(location.search); var isTargetComment = window.isLOVE16thTargetComment || urlParams.get('target') === 'comment' || location.hash === '#commtent_box' || location.hash === '#comment' || sessionStorage.getItem('LOVE16th_scroll_target') === 'comment'; if (isTargetComment && !_hasScrolledToCommentOnLoad) { _hasScrolledToCommentOnLoad = true; sessionStorage.removeItem('LOVE16th_scroll_target'); // 작성 중이던 댓글 내용 복원 var draft = sessionStorage.getItem('LOVE16th_comment_draft'); if (draft) { var textarea = document.querySelector('#article-comment'); if (textarea) textarea.value = draft; sessionStorage.removeItem('LOVE16th_comment_draft'); } var userInteracted = false; var onUserScroll = function () { userInteracted = true; }; var sec05Inner = document.querySelector('#section-05 .promo-section-inner'); if (sec05Inner) { sec05Inner.addEventListener('wheel', onUserScroll, { passive: true, once: true }); } setTimeout(function () { if (typeof window.LOVE16thScrollToComment === 'function') { window.LOVE16thScrollToComment({ smooth: true, focus: true }); } }, 100); setTimeout(function () { if (!userInteracted && typeof window.LOVE16thScrollToComment === 'function') { window.LOVE16thScrollToComment({ smooth: false, focus: false }); } }, 400); setTimeout(function () { if (!userInteracted && typeof window.LOVE16thScrollToComment === 'function') { window.LOVE16thScrollToComment({ smooth: false, focus: false }); } }, 800); // URL의 target=comment 파라미터 정리 if (urlParams.get('target') === 'comment') { urlParams.delete('target'); var newSearch = urlParams.toString() ? '?' + urlParams.toString() : ''; var cleanUrl = location.pathname + newSearch + location.hash; history.replaceState(null, '', cleanUrl); } } }; const initBoard = ({ board }) => { helperLMUtil.log("initBoard", board); _currentBoard = board; }; const initArticleComments = ({ comments }) => { if (!_currentBoard.id) { helperLMUtil.log("wait initArticleComments"); return setTimeout(() => initArticleComments({ comments }), 100); } presentaionArticleComments(comments); if (_currentBoard.use_comment != "1") return; document.querySelector("article-comments")?.addEventListener("click", ({ target }) => { const action = target.closest("[shopby-action]")?.getAttribute("shopby-action"); moduleActionHandler[action]?.({ target }); }); }; const initComments = () => { helperLMRequest.init({ mall_id: "energyscoop" }); helperLMRequest.request(`boards/${boardNo}`).then(initBoard); helperLMRequest.request(`articles/${articleNo}?writeHistory=${getMemberId()}&withComments=1&member_id=${getMemberId()}`) .then(({ article, navigationArticle }) => { initArticleComments({ comments: article.comments }); }); }; Handlebars.registerHelper('nl2br', function (value) { return value.replace(/>.*\n+.* match.replace(/\n/g, "")).replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, "$1
$2"); }); Handlebars.registerHelper('formatUseByDate', function (value) { if (!value) return ''; return value.substring(0, 10); }); })();