var frontCommon = frontCommon || {}; frontCommon.Html = (function () { var instance = null; function init() { instance = { reset: function () { frontCommonResize(); frontCommonScroll(); lenis(); header(); buttonPressed(); activeAnimationType_1('[active-animation="type-1"]'); activeAnimationType_2('[active-animation="type-2"]'); //accordion(); //activeItemOnlyPc('.process, .feature'); //activeItemOnlyMo('.feature'); scrollTopBtn(); setTimeout(() => { modalCloseCheck(); }, 200); modalOpen(); //footer(); //localAnimations(); //business_Interaction(); //scrollTopBtn(); }, }; return instance; } if (instance) { return instance; } else { return init(); } })(); function frontCommonResize() { window.addEventListener("resize", () => { activeAnimationType_1('[active-animation="type-1"]'); activeAnimationType_2('[active-animation="type-2"]'); activeAnimationType_3('[active-animation="type-3"]'); }); } function frontCommonScroll() { window.addEventListener("scroll", () => { activeAnimationType_1('[active-animation="type-1"]'); activeAnimationType_2('[active-animation="type-2"]'); activeAnimationType_3('[active-animation="type-3"]'); }); } let lenisBody; function lenis() { const $body = $('body'); if ($body.length) { lenisBody = new Lenis({ wrapper: $body[0], content: $body.find('#wrap')[0] }); } function raf(time) { if (lenisBody) lenisBody.raf(time); requestAnimationFrame(raf); } requestAnimationFrame(raf); } // header function header() { const $body = $('body'); const $header = $('#header'); const isDesktop = () => window.innerWidth >= 1199; let mobileEventsBound = false; let desktopEventsBound = false; const addDesktopEvents = () => { if (desktopEventsBound) return; desktopEventsBound = true; $('.gnb-list .gnb-item.ir').removeClass('has-2depth'); $(document).on('mouseenter', '#header', function () { $(this).addClass('hover'); }); $(document).on('mouseleave', '#header', function () { $(this).removeClass('hover'); }); $(document).on('mouseenter', '#header .has-2depth', function () { $(this).addClass('active-pc'); $(this).find('.lnb').addClass('active'); }); $(document).on('mouseleave', '#header .has-2depth', function () { $(this).removeClass('active-pc'); $(this).find('.lnb').removeClass('active'); }); $(function () { $(document).on('click', '.page-util .language', function (e) { e.preventDefault(); }); }); }; const addMobileEvents = () => { if (mobileEventsBound) return; mobileEventsBound = true; $('.gnb-list .gnb-item.ir').addClass('has-2depth'); $(document).on('touchstart', '.gnb-name', function () { const $this = $(this); $this.closest('.gnb-item').addClass('pressed'); }); $(document).on('touchend', '.gnb-name', function () { const $this = $(this); $this.closest('.gnb-item').removeClass('pressed'); }); $(document).on('click', '.page-util .language', function (e) { e.preventDefault(); const $this = $(this); const $util = $this.closest('.page-util'); if($util.hasClass('active-pc')) { $util.removeClass('active-pc'); $this.next('.lnb').removeClass('active'); $header.removeClass('hover'); }else{ $util.addClass('active-pc'); $this.next('.lnb').addClass('active'); $header.addClass('hover'); } }); $(document).on('click', '.goto-page-navi', function () { $('.page-util').removeClass('active-pc').find('.lnb').removeClass('active'); if (isDesktop()) return false; if ($header.hasClass('mo-menu-open')) { $header.removeClass('mo-menu-open'); $body.removeClass('mo-menu-open'); $('.goto-page-navi').removeClass('active'); $header.removeClass('hover'); $('.gnb-item').removeClass('active-mo'); $('.gnb-item .lnb').css({ height: '0px' }); //$('.page-util').removeClass('active-pc').find('.lnb').removeClass('active'); lenis(); } else { $body.addClass('mo-menu-open'); $header.addClass('mo-menu-open'); $('.goto-page-navi').addClass('active'); $header.removeClass('hover'); if (lenisBody) { lenisBody.destroy(); lenisBody = null; } $(document).on('keydown', function (e) { if (e.key === 'Tab') { setTimeout(() => { if ($('.gnb-list .gnb-item').first().find('.gnb-name').first().length) { $('.gnb-list .gnb-item').first().find('.gnb-name').first().focus(); $(document).off('keydown'); } }, 10); } }); } }); $(document).on('click', '#header .has-2depth .gnb-name', function (e) { e.preventDefault(); const $this = $(this); const $this2depthH = $this.siblings('.lnb').find('.lnb-list').innerHeight(); if (isDesktop()){ alert(isDesktop()); return false; } if ($this.closest('.gnb-item').hasClass('active-mo')) { $this.closest('.gnb-item').removeClass('active-mo'); $this.siblings('.lnb').css({ height: '0px' }); } else { $('.gnb-item').removeClass('active-mo'); $('.lnb').css({ height: '0px' }); $this.closest('.gnb-item').addClass('active-mo'); $this.siblings('.lnb').css({ height: `${$this2depthH}px` }); } }); }; const removeDesktopEvents = () => { desktopEventsBound = false; $(document).off('mouseenter', '#header'); $(document).off('mouseleave', '#header'); $(document).off('mouseenter focusin', '#header .has-2depth'); $(document).off('mouseleave focusout', '#header .has-2depth'); }; const removeMobileEvents = () => { mobileEventsBound = false; $body.removeClass('mo-menu-open'); $header.removeClass('mo-menu-open'); $('.page-control .goto-page-navi').removeClass('active'); $('.gnb-item').removeClass('active-mo'); $('.gnb-item .lnb').css({ height: '0px' }); $('.page-util').removeClass('active-pc').find('.lnb').removeClass('active'); //$('.page-navi').css({'overflow':'unset'}); // 모바일 관련 이벤트도 오프 $(document).off('click', '.page-util .language'); $(document).off('click', '.goto-page-navi'); $(document).off('click', '#header .has-2depth .gnb-name'); $(document).off('keydown'); }; const initHeaderPcEvent = () => { if (isDesktop()) { addDesktopEvents(); removeMobileEvents(); } else { removeDesktopEvents(); } }; const initHeaderMobileEvent = () => { if (isDesktop()) { removeMobileEvents(); } else { addMobileEvents(); removeDesktopEvents(); } }; const handleScroll = () => { if ($header.hasClass('mo-menu-open')) return; let winScrollTop = $(window).scrollTop(); $header.toggleClass('scroll', winScrollTop > 0); if($('.page-util').hasClass('active-pc')) { $('.page-util').removeClass('active-pc') $('.lnb.language').removeClass('active'); } }; let lastScrollTop = 0; // 초기 실행 initHeaderPcEvent(); initHeaderMobileEvent(); const handleResize = () => { initHeaderPcEvent(); initHeaderMobileEvent(); }; window.addEventListener('resize', handleResize); window.addEventListener('scroll', handleScroll); } function naviDisplay() { let swiper = null; const toggleSwiper = () => { const isMobile = window.innerWidth <= 1024; if (isMobile && !swiper) { const activeSlide = document.querySelector('.navi-wrap .swiper-slide.active'); const slides = Array.from(document.querySelectorAll('.navi-wrap .swiper-slide')); const initialIndex = activeSlide ? slides.indexOf(activeSlide) : 0; swiper = new Swiper(".navi-wrap", { slidesPerView: "auto", freeMode: true, initialSlide: initialIndex, slideToClickedSlide: true, }); // 초기 로드시 active 슬라이드를 왼쪽에 위치시킴 setTimeout(() => { if (activeSlide && swiper.wrapperEl) { swiper.wrapperEl.scrollLeft = activeSlide.offsetLeft; } }, 100); // 슬라이드 클릭 시 active 슬라이드를 왼쪽에 위치시킴 swiper.on('slideChangeTransitionEnd', () => { const activeSlide = document.querySelector('.navi-wrap .swiper-slide-active'); swiper.wrapperEl.scrollLeft = activeSlide.offsetLeft; }); } else if (!isMobile && swiper) { swiper.destroy(true, true); swiper = null; } }; toggleSwiper(); window.addEventListener("resize", toggleSwiper); console.log() setTimeout(() => { const $active2depthH = $('.local.module-a .navi-list .navi-item.active').find('.lnb .lnb-list').innerHeight(); $('.local.module-a .navi-list .navi-item.active').find('.lnb').css({ height: `${$active2depthH}px` }); }, 200); $(document).on('click', '.local.module-a .navi-list .navi-item .navi-name', function () { const $this = $(this); const $this2depthH = $this.siblings('.lnb').find('.lnb-list').innerHeight(); if ($this.closest('.navi-item').hasClass('active')) { $this.closest('.navi-item').removeClass('active'); $this.siblings('.lnb').css({ height: '0px' }); //$this.siblings('.lnb').slideUp(200); } else { $('.navi-item').removeClass('active'); //$('.lnb').slideUp(200); $('.lnb').css({ height: '0px' }); $this.closest('.navi-item').addClass('active'); $this.siblings('.lnb').css({ height: `${$this2depthH}px` }); //$this.siblings('.lnb').slideDown(200); } }); } function buttonPressed() { // touchstart document.addEventListener('touchstart', (e) => { const btn = e.target.closest('.btn'); if (btn) btn.classList.add('pressed'); }); // touchend document.addEventListener('touchend', (e) => { const btn = e.target.closest('.btn'); if (btn) btn.classList.remove('pressed'); }); // touchcancel document.addEventListener('touchcancel', (e) => { const btn = e.target.closest('.btn'); if (btn) btn.classList.remove('pressed'); }); } function initMarquee() { const mediaQuery = window.matchMedia("(min-width: 1200px)"); // 텍스트 실제 너비 측정용 함수 function getAccurateTextWidth(el) { const clone = el.cloneNode(true); clone.style.position = 'absolute'; clone.style.visibility = 'hidden'; clone.style.whiteSpace = 'nowrap'; clone.style.width = 'auto'; clone.style.font = getComputedStyle(el).font; document.body.appendChild(clone); const width = clone.scrollWidth; document.body.removeChild(clone); return width; } // 마퀴 활성화 function activateMarquee() { const marquees = document.querySelectorAll(".marquee"); marquees.forEach((marquee) => { const originalSpan = marquee.querySelector("span"); if (!originalSpan) return; if (marquee.dataset.marqueeInit === "true") return; const wrapper = document.createElement("div"); wrapper.className = "marquee-inner"; const cloneSpan = originalSpan.cloneNode(true); cloneSpan.classList.add("clone"); wrapper.appendChild(originalSpan); wrapper.appendChild(cloneSpan); marquee.appendChild(wrapper); const handleMouseEnter = () => { const containerWidth = marquee.offsetWidth; const contentWidth = getAccurateTextWidth(originalSpan); if (contentWidth > containerWidth) { marquee.classList.add("is-hovered"); } }; const handleMouseLeave = () => { marquee.classList.remove("is-hovered"); }; marquee.addEventListener("mouseenter", handleMouseEnter); marquee.addEventListener("mouseleave", handleMouseLeave); marquee._handleMouseEnter = handleMouseEnter; marquee._handleMouseLeave = handleMouseLeave; marquee.dataset.marqueeInit = "true"; }); } // 마퀴 제거 function destroyMarquee() { document.querySelectorAll(".marquee").forEach((marquee) => { marquee.classList.remove("is-hovered"); marquee.dataset.marqueeInit = ""; if (marquee._handleMouseEnter) { marquee.removeEventListener("mouseenter", marquee._handleMouseEnter); delete marquee._handleMouseEnter; } if (marquee._handleMouseLeave) { marquee.removeEventListener("mouseleave", marquee._handleMouseLeave); delete marquee._handleMouseLeave; } const wrapper = marquee.querySelector(".marquee-inner"); if (wrapper) { const originalSpan = wrapper.querySelector("span:not(.clone)"); marquee.innerHTML = ""; if (originalSpan) marquee.appendChild(originalSpan); } }); } // 화면 전환 감지 function handleMediaChange(e) { if (e.matches) { activateMarquee(); } else { destroyMarquee(); } } // 미디어쿼리 변경 감지 등록 mediaQuery.addEventListener("change", handleMediaChange); // 초기 진입 시 조건 확인 if (mediaQuery.matches) { activateMarquee(); } } // tab function tab() { const tabDisplay = document.querySelectorAll(".tab-display") tabDisplay.forEach(tab => { const firstTab = tab.querySelector(".tab-item:first-child") firstTab.classList.add("active") firstTab.querySelector(".tab-text").setAttribute("aria-selected", "true") const tabList = tab.querySelector(".tab-list") tabList.addEventListener("keydown", function(e) { e = event || window.event; let keycode = e.keyCode || e.which; if(!e.shiftKey && keycode === 9) { let tabItem = this.querySelectorAll(".tab-item"); tabItem.forEach(item => { if(item.classList.contains("active")) { const button = item.querySelector(".tab-text"); button.setAttribute("tabindex", "0"); button.setAttribute("aria-selected", "true") } else { const button = item.querySelector(".tab-text"); button.setAttribute("tabindex", "-1"); button.setAttribute("aria-selected", "false"); } }); let siblingTabPanels = document.querySelectorAll(".panel-item.hidden"); siblingTabPanels.forEach(panel => { // panel.tabIndex = "-1"; }); } }) const tabButton = tab.querySelectorAll(".tab-text") tabButton.forEach(button => { button.addEventListener("keydown", function(e) { e = event || window.event; let keycode = e.keyCode || e.which; switch(keycode) { case 37: if(this.closest('.tab-item').previousElementSibling) { this.setAttribute("tabindex", "-1") this.closest('.tab-item').previousElementSibling.querySelector('.tab-text').setAttribute("tabindex", "0") this.closest('.tab-item').previousElementSibling.querySelector('.tab-text').focus(); } break; case 39: if(this.closest('.tab-item').nextElementSibling) { this.setAttribute("tabindex", "-1") this.closest('.tab-item').nextElementSibling.querySelector('.tab-text').setAttribute("tabindex", "0") this.closest('.tab-item').nextElementSibling.querySelector('.tab-text').focus(); } break; case 32: case 13: if(this) { tabButton.forEach(button => { button.setAttribute("aria-selected", "false"); }); this.setAttribute("aria-selected", "true"); } break; } }) }); }); const panelDisplay = document.querySelectorAll(".panel-display") panelDisplay.forEach(panel => { const panelItems = panel.querySelectorAll(".panel-item") panelItems.forEach((item, i) => { i != 0 ? item.classList.add("hidden") : "" }); }); tabDisplay.forEach((tab, tabDisplayIndex) => { const tabItems = tab.querySelectorAll(".tab-item") tabItems.forEach((item, tabIndex) => { const button = item.querySelector(".tab-text") button.addEventListener("click", () => { const curTab = button.closest(".tab-item") tabItems.forEach(item => { item.classList.remove("active") item.querySelector('.tab-text').setAttribute("tabindex", "-1") item.querySelector('.tab-text').setAttribute("aria-selected", "false") }); curTab.classList.add("active") button.setAttribute("tabindex", "0") button.setAttribute("aria-selected", "true") panelDisplay.forEach((panelDisplay, panelDisplayIndex) => { if(tabDisplayIndex == panelDisplayIndex) { const panelItems = panelDisplay.querySelectorAll(".panel-item") panelItems.forEach((item, panelIndex) => { item.classList.add("hidden") tabIndex == panelIndex ? item.classList.remove("hidden") : "" }); } }); }) }); }); new Swiper(".tab-wrap", { slidesPerView: "auto", freeMode: true, }); // jQuery Scroll Event $(function () { var $tabDisplay = $(".tab-display.module-b"); // 요소가 존재할 때만 실행 if ($tabDisplay.length) { var tabDisplayOffset = $tabDisplay.offset().top - 64; var placeholder = $("
").height($tabDisplay.outerHeight()).hide(); $tabDisplay.before(placeholder); $(window).scroll(function () { var scrollTop = $(this).scrollTop(); if (tabDisplayOffset <= scrollTop) { $tabDisplay.addClass("fixed"); placeholder.show(); $("#header").css({ "box-shadow": "none" }); } else { $tabDisplay.removeClass("fixed"); placeholder.hide(); $("#header").css({ "box-shadow": "0px 4px 28px 0px rgba(0, 0, 0, 0.04)" }); } }); } }); } function activeAnimationType_1(selector) { $(selector).each(function() { var $selector = $(this); var start = $selector.offset().top - ($(window).innerHeight() * 0.8); var end = $selector.offset().top + $selector.innerHeight(); var scrollAmt = $(document).scrollTop(); if (scrollAmt < start) { //$selector.removeClass('active-animation-01'); } else if (scrollAmt > end) { //$selector.removeClass('active-animation-01'); } else { if( $selector.hasClass('active-animation-01') === false) { //.removeClass('active-animation-01'); } $selector.addClass('active-animation-01'); } }); } function activeAnimationType_2(selector) { $(selector).each(function() { var $selector = $(this); var start = $selector.offset().top - ($(window).innerHeight() * 0.8); var end = $selector.offset().top + $selector.innerHeight(); var scrollAmt = $(document).scrollTop(); if (scrollAmt < start) { //$selector.removeClass('active-animation-01'); } else if (scrollAmt > end) { //$selector.removeClass('active-animation-01'); } else { if( $selector.hasClass('active') === false) { //.removeClass('active-animation-01'); } $selector.addClass('active'); } }); } function activeAnimationType_3(selector) { $(selector).each(function() { var $selector = $(this); var start = $selector.offset().top - ($(window).innerHeight() * 1); var end = $selector.offset().top + $selector.innerHeight(); var scrollAmt = $(document).scrollTop(); if (scrollAmt < start) { //$selector.removeClass('active-animation-01'); } else if (scrollAmt > end) { //$selector.removeClass('active-animation-01'); } else { if( $selector.hasClass('active') === false) { //.removeClass('active-animation-01'); } $selector.addClass('active'); } }); } // 탑 버튼 function scrollTopBtn() { const FloatingDisplay = document.querySelector('.floating-display'); const scrollTopBtn = document.querySelector('#topBtn'); let scrollTimeout; scrollTopBtn.addEventListener('click', function(){ if (lenisBody) { lenisBody.scrollTo(0, { duration: 1.5 }); } else { window.scroll({ top: 0, behavior: 'smooth' }); } }); function handleScroll() { const scrollTop = window.pageYOffset || document.documentElement.scrollTop; const pageBodyHeight = parseInt(document.querySelector('#wrap').clientHeight); const showLine = pageBodyHeight * 0.05; // 요소의 높이를 기준으로 5% const contentHeight = document.querySelector('#main').clientHeight; const hotLine = contentHeight - window.innerHeight; const windowWidth = window.innerWidth; if (windowWidth <= 1199) { FloatingDisplay.classList.add('active'); clearTimeout(scrollTimeout); scrollTimeout = setTimeout(() => { FloatingDisplay.classList.remove('active'); }, 1000); }else{ if (scrollTop >= showLine) { FloatingDisplay.classList.add('active'); } else { FloatingDisplay.classList.remove('active'); } } if (scrollTop >= hotLine) { FloatingDisplay.classList.add('fixed'); } else { FloatingDisplay.classList.remove('fixed'); } } window.addEventListener('scroll', handleScroll); window.addEventListener('resize', handleScroll); handleScroll(); } // 링크 복사 function copyLink(buttonEl) { const root = buttonEl.closest('.navi-ask') || buttonEl.closest('.btn-area')?.parentElement; if (!root) return; // 우선순위: data-email > .email 요소 const emailText = buttonEl.dataset.email || root.querySelector('.email')?.textContent.trim().replace('- ', ''); const tooltip = root.querySelector('.tooltip'); if (!emailText || !tooltip) return; function fallbackCopy(text) { const textarea = document.createElement('textarea'); textarea.value = text; textarea.setAttribute('readonly', ''); textarea.style.position = 'absolute'; textarea.style.left = '-9999px'; document.body.appendChild(textarea); textarea.select(); const success = document.execCommand('copy'); document.body.removeChild(textarea); return success ? Promise.resolve() : Promise.reject(); } const copyPromise = navigator.clipboard?.writeText ? navigator.clipboard.writeText(emailText) : fallbackCopy(emailText); copyPromise.then(() => { requestAnimationFrame(() => { tooltip.offsetHeight; // iOS 강제 리플로우 tooltip.classList.add('show'); const timeoutId = setTimeout(() => { tooltip.classList.remove('show'); }, 2000); function hideTooltip(event) { if (!tooltip.contains(event.target) && event.target !== buttonEl) { tooltip.classList.remove('show'); document.removeEventListener('click', hideTooltip); document.removeEventListener('touchstart', hideTooltip); clearTimeout(timeoutId); } } document.addEventListener('click', hideTooltip); document.addEventListener('touchstart', hideTooltip); }); }).catch(err => { console.error('클립보드 복사 실패:', err); alert('클립보드 복사에 실패했습니다. 수동으로 복사해주세요.'); }); } //검색 기능 function initSearchToggle(formSelector = '.form.input.module-a') { const form = document.querySelector(formSelector); if (!form) return; const searchBtn = form.querySelector('.search'); const input = form.querySelector('.input-elem'); if (!searchBtn || !input) return; searchBtn.addEventListener('click', (e) => { e.stopPropagation(); form.classList.toggle('active'); if (form.classList.contains('active')) { input.focus(); } }); document.addEventListener('click', (e) => { if (!form.contains(e.target)) { form.classList.remove('active'); } }); } function modalUnfold() { const modals = document.querySelectorAll('.modal'); modals.forEach(modal => { const dragArea = modal.querySelector('.btn.open'); if (!dragArea) return; let startY = 0; let endY = 0; dragArea.addEventListener('touchstart', (e) => { startY = e.touches[0].clientY; }); dragArea.addEventListener('touchmove', (e) => { endY = e.touches[0].clientY; }); dragArea.addEventListener('touchend', () => { const diffY = endY - startY; if (diffY < -30) { modal.classList.add('unfold'); } else if (diffY > 30) { modal.classList.remove('unfold'); } // 초기화 startY = 0; endY = 0; }); }); } function openModalWithCheck(modalId) { const modalEl = document.getElementById(modalId); const modalDimed = document.querySelector('.popup-dimed'); const body = document.body; const head = document.querySelector('.page-head'); let originalPaddingRight; if (modalEl) { const modalInstance = new bootstrap.Modal(modalEl); modalInstance.show(); originalPaddingRight = window.getComputedStyle(body).paddingRight head.style.paddingRight = originalPaddingRight; modalEl.addEventListener('shown.bs.modal', () => { modalOpenCheck(); modalUnfold(); modalDimed.classList.add('show'); }, { once: true }); } } function modalOpenCheck() { const openedModals = document.querySelectorAll('.modal.show'); if (openedModals.length > 0) { if (lenisBody) { lenisBody.destroy(); lenisBody = null; } } else { if (!lenisBody) { lenis(); } } } function modalCloseCheck() { const closeBtns = document.querySelectorAll('.modal .btn.close'); const modalDimed = document.querySelector('.popup-dimed'); const body = document.body; const head = document.querySelector('.page-head'); const originalPaddingRight = window.getComputedStyle(body).paddingRight; const originalDataPadding = body.getAttribute('data-bs-padding-right'); closeBtns.forEach(btn => { btn.addEventListener('click', function () { const modal = this.closest('.modal'); if (modal) { modal.addEventListener('hidden.bs.modal', function onHidden() { modal.removeEventListener('hidden.bs.modal', onHidden); const openedModals = document.querySelectorAll('.modal.show'); if (openedModals.length > 0) { if (lenisBody) { lenisBody.destroy(); lenisBody = null; } body.classList.add('modal-open'); modalDimed.classList.add('show'); head.style.paddingRight = originalPaddingRight; body.style.paddingRight = originalPaddingRight; body.style.overflow = 'hidden'; body.setAttribute('data-bs-overflow', 'hidden'); body.setAttribute('data-bs-padding-right', originalDataPadding); } else { lenis(); body.classList.remove('modal-open'); modalDimed.classList.remove('show'); head.style.paddingRight = ''; body.style.paddingRight = ''; body.style.overflow = ''; body.removeAttribute('data-bs-overflow'); body.removeAttribute('data-bs-padding-right'); } }); } }); }); } function modalOpen() { document.addEventListener('click', function (e) { const target = e.target.closest('.btn-modal'); if (target) { e.preventDefault(); // 혹시 버튼이 form 안에 있으면 기본 동작 방지 const modalId = target.getAttribute('data-modal-id'); if (modalId) { openModalWithCheck(modalId); } } }); } window.addEventListener('load', () => { document.body.classList.remove('fonts-loading'); document.body.classList.add('fonts-loaded'); });