(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);
});
})();