// =============================== // header.js (FINAL - Cafe24 + fullpage/normal both) // - Topbar theme(light/dark) + logo swap // - Menu icon swap by section theme (white/black) // - Open/close icon swap by menu state // - (index/fullpage) uses window.goToIndex if exists // - (normal pages) uses [data-topbar] scroll-based theme // - Mobile menu toggle // - Close on outside click / ESC / resize // - Language dropdown // =============================== (() => { // 0) °øÅë Àû¿ë: topbar ¸ðµå + ·Î°í ±³Ã¼ function applyTopbarMode({ mode = "dark", topbar, logoImg }) { if (!topbar) return; const isLight = mode === "light"; topbar.classList.toggle("is-light", isLight); document.body.classList.toggle("theme-light", isLight); if (logoImg) { const lightSrc = logoImg.getAttribute("data-logo-light"); const darkSrc = logoImg.getAttribute("data-logo-dark"); if (isLight && lightSrc) logoImg.src = lightSrc; if (!isLight && darkSrc) logoImg.src = darkSrc; } // ✅ topbar Å׸¶°¡ ¹Ù²ð ¶§ ¸Þ´º ¾ÆÀÌÄܵµ ÇÔ²² °»½Å const toggleBtn = document.querySelector(".menu-toggle"); const menu = document.querySelector(".gnb"); if (toggleBtn) { const isOpen = !!(menu && menu.classList.contains("active")); setToggleIcon({ toggleBtn, isOpen, topbar }); } } // 1) Ç®ÆäÀÌÁö(¼½¼Ç idx ±â¹Ý)¿¡¼­ »ç¿ë function setTopbarThemeBySection({ sections, idx, topbar, logoImg }) { const mode = sections && sections[idx] ? sections[idx].dataset.topbar : null; applyTopbarMode({ mode: mode || "dark", topbar, logoImg }); } window.setTopbarThemeBySection = setTopbarThemeBySection; // 2) ÀÏ¹Ý ÆäÀÌÁö: data-topbar¸¦ ½ºÅ©·Ñ ±âÁØÀ¸·Î Àû¿ë function initTopbarThemeByDataAttr({ topbar, logoImg, selector = "[data-topbar]", }) { if (!topbar) return; const targets = Array.from(document.querySelectorAll(selector)); const first = targets[0] || null; applyTopbarMode({ mode: (first && first.dataset.topbar) || "dark", topbar, logoImg, }); if (!targets.length) return; const getTopbarH = () => { const v = getComputedStyle(document.documentElement).getPropertyValue("--topbar-h"); const num = parseFloat(v); if (Number.isFinite(num) && num > 0) return num; return topbar.getBoundingClientRect().height || 0; }; const update = () => { const threshold = getTopbarH() + 1; let current = first; for (const el of targets) { const r = el.getBoundingClientRect(); if (r.top <= threshold) current = el; } applyTopbarMode({ mode: (current && current.dataset.topbar) || "dark", topbar, logoImg, }); }; window.addEventListener("scroll", update, { passive: true }); window.addEventListener("resize", update); update(); } // 3) ¸Þ´º Åä±Û ¹öư À̹ÌÁö ¿ä¼Ò °¡Á®¿À±â function getToggleIconEl(toggleBtn) { if (!toggleBtn) return null; return toggleBtn.querySelector("img"); } // 4) ÇöÀç topbar ¸ðµå + ¸Þ´º open »óÅ¿¡ µû¶ó ¾ÆÀÌÄÜ º¯°æ function setToggleIcon({ toggleBtn, isOpen, topbar }) { const img = getToggleIconEl(toggleBtn); if (!img) return; const isLight = !!(topbar && topbar.classList.contains("is-light")); const menuDark = img.getAttribute("data-menu-dark") || "./img/menu_white.svg"; const menuLight = img.getAttribute("data-menu-light") || "./img/menu_black.svg"; const closeDark = img.getAttribute("data-close-dark") || "./img/close_white.svg"; const closeLight = img.getAttribute("data-close-light") || "./img/close_black.svg"; if (isOpen) { img.src = isLight ? closeLight : closeDark; img.alt = "Close menu"; } else { img.src = isLight ? menuLight : menuDark; img.alt = "Open menu"; } } // 5) ¸ð¹ÙÀÏ ¸Þ´º ´Ý±â/Åä±Û function initMobileMenu({ toggleBtn, menu, topbar }) { function closeMenu(force = false) { if (!menu || !toggleBtn) return; if (!force && !menu.classList.contains("active")) return; menu.classList.remove("active"); toggleBtn.setAttribute("aria-expanded", "false"); setToggleIcon({ toggleBtn, isOpen: false, topbar }); } function closeMenuIfMobile() { if (window.matchMedia("(max-width: 768px)").matches) closeMenu(true); } if (toggleBtn && menu) { // Ãʱ⠾ÆÀÌÄÜ ¼¼ÆÃ setToggleIcon({ toggleBtn, isOpen: menu.classList.contains("active"), topbar, }); toggleBtn.addEventListener("click", () => { const isOpen = menu.classList.toggle("active"); toggleBtn.setAttribute("aria-expanded", String(isOpen)); setToggleIcon({ toggleBtn, isOpen, topbar }); }); // ¸Þ´º ¹Û Ŭ¸¯ ½Ã ´Ý±â document.addEventListener("click", (e) => { if (!window.matchMedia("(max-width: 768px)").matches) return; if (!menu.classList.contains("active")) return; const t = e.target; const inMenu = t.closest && t.closest(".gnb"); const inBtn = t.closest && t.closest(".menu-toggle"); if (!inMenu && !inBtn) closeMenu(true); }); // ESC ´Ý±â document.addEventListener("keydown", (e) => { if (e.key !== "Escape") return; if (!menu.classList.contains("active")) return; closeMenu(true); }); // PC Àüȯ ½Ã °­Á¦ ´Ý±â window.addEventListener("resize", () => { if (!window.matchMedia("(max-width: 768px)").matches) closeMenu(true); }); } return { closeMenu, closeMenuIfMobile }; } // 6) ³×ºñ Ŭ¸¯ ¹ÙÀεù function bindNavClicks({ btns, closeMenuIfMobile }) { btns.forEach((btn) => { btn.addEventListener("click", (e) => { const href = (btn.getAttribute("href") || "").trim(); const idx = Number(btn.dataset.goto); // Ç®ÆäÀÌÁö À̵¿ if (Number.isFinite(idx) && typeof window.goToIndex === "function") { e.preventDefault(); const bizKey = btn.dataset.biz || null; window.goToIndex(idx, { focus: true, bizKey }); closeMenuIfMobile?.(); return; } // data-goto´Â Àִµ¥ goToIndex°¡ ¾øÀ¸¸é ±âº» À̵¿¸¸ Çã¿ë if (Number.isFinite(idx) && typeof window.goToIndex !== "function") { closeMenuIfMobile?.(); return; } // href°¡ ¾ø°Å³ª #ÀÌ¸é ¸·±â if (!href || href === "#") { e.preventDefault(); closeMenuIfMobile?.(); return; } closeMenuIfMobile?.(); }); }); } // 7) ·Î°í data-goto Áö¿ø function bindLogoGoto() { document.querySelectorAll("[data-goto]").forEach((el) => { if ( el.classList.contains("gnb__link") || el.classList.contains("indexNav__item") ) { return; } el.addEventListener("click", (e) => { const idx = Number(el.dataset.goto); if (!Number.isFinite(idx)) return; if (typeof window.goToIndex === "function") { e.preventDefault(); window.goToIndex(idx, { focus: true }); } }); }); } // 8) Language Dropdown function initLanguageDropdown() { const wrap = document.querySelector("[data-lang]"); if (!wrap) return; const langBtn = wrap.querySelector(".langSelect__btn"); const langMenu = wrap.querySelector(".langSelect__menu"); if (!langBtn || !langMenu) return; const close = () => { wrap.classList.remove("is-open"); langBtn.setAttribute("aria-expanded", "false"); }; const open = () => { wrap.classList.add("is-open"); langBtn.setAttribute("aria-expanded", "true"); }; langBtn.addEventListener("click", (e) => { e.stopPropagation(); wrap.classList.contains("is-open") ? close() : open(); }); document.addEventListener("click", (e) => { if (!wrap.contains(e.target)) close(); }); document.addEventListener("keydown", (e) => { if (e.key === "Escape") close(); }); langMenu.addEventListener("click", (e) => { const a = e.target.closest("a"); if (a) close(); }); } // 9) ÃʱâÈ­ document.addEventListener("DOMContentLoaded", () => { const topbar = document.querySelector("#topbar"); const logoImg = document.querySelector("#topbarLogo"); const toggleBtn = document.querySelector(".menu-toggle"); const menu = document.querySelector(".gnb"); const { closeMenuIfMobile } = initMobileMenu({ toggleBtn, menu, topbar }); const isFullpage = !!document.querySelector("#track") && document.querySelectorAll(".section").length > 0; if (isFullpage) { const sections = Array.from(document.querySelectorAll(".section")); applyTopbarMode({ mode: (sections[0] && sections[0].dataset.topbar) || "dark", topbar, logoImg, }); } else { initTopbarThemeByDataAttr({ topbar, logoImg }); } const navBtns = Array.from( document.querySelectorAll(".gnb__link, .indexNav__item") ); if (navBtns.length) { bindNavClicks({ btns: navBtns, closeMenuIfMobile }); } bindLogoGoto(); initLanguageDropdown(); }); })();