script.js.bak-20260409-1458 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. const siteHeader = document.getElementById('siteHeader')
  2. const mainNavbar = document.getElementById('mainNavbar')
  3. const navbarToggler = document.querySelector('.navbar-toggler')
  4. const bootstrapCollapse = mainNavbar && window.bootstrap ? new bootstrap.Collapse(mainNavbar, { toggle: false }) : null
  5. const syncHeaderState = () => {
  6. const menuOpen = !!mainNavbar?.classList.contains('show')
  7. if (siteHeader) siteHeader.classList.toggle('menu-open', menuOpen)
  8. if (navbarToggler) navbarToggler.setAttribute('aria-expanded', menuOpen ? 'true' : 'false')
  9. }
  10. const onScroll = () => {
  11. if (!siteHeader || siteHeader.classList.contains('page-navbar-solid')) return
  12. if (window.scrollY > 30) siteHeader.classList.add('scrolled')
  13. else if (!siteHeader.classList.contains('menu-open')) siteHeader.classList.remove('scrolled')
  14. }
  15. window.addEventListener('scroll', onScroll)
  16. onScroll()
  17. mainNavbar?.addEventListener('show.bs.collapse', () => {
  18. siteHeader?.classList.add('menu-open', 'scrolled')
  19. document.body.classList.add('modal-open')
  20. syncHeaderState()
  21. })
  22. mainNavbar?.addEventListener('hide.bs.collapse', () => {
  23. siteHeader?.classList.remove('menu-open')
  24. document.body.classList.remove('modal-open')
  25. syncHeaderState()
  26. onScroll()
  27. })
  28. mainNavbar?.addEventListener('shown.bs.collapse', syncHeaderState)
  29. mainNavbar?.addEventListener('hidden.bs.collapse', syncHeaderState)
  30. mainNavbar?.querySelectorAll('.nav-link:not(.dropdown-toggle), .dropdown-item').forEach((link) => {
  31. link.addEventListener('click', () => {
  32. if (window.innerWidth < 992 && mainNavbar.classList.contains('show')) bootstrapCollapse?.hide()
  33. })
  34. })
  35. const openModal = (id) => {
  36. const modal = document.getElementById(id)
  37. if (!modal) return
  38. modal.classList.add('is-open')
  39. document.body.classList.add('modal-open')
  40. }
  41. const closeModal = (id) => {
  42. const modal = document.getElementById(id)
  43. if (!modal) return
  44. modal.classList.remove('is-open')
  45. if (!document.querySelector('.custom-modal.is-open') && !mainNavbar?.classList.contains('show')) document.body.classList.remove('modal-open')
  46. }
  47. document.getElementById('openLanguageModal')?.addEventListener('click', () => openModal('languageModal'))
  48. document.getElementById('openLanguageModalMobile')?.addEventListener('click', () => openModal('languageModal'))
  49. document.getElementById('openSearchModal')?.addEventListener('click', () => openModal('searchModal'))
  50. document.getElementById('openSearchModalMobile')?.addEventListener('click', () => openModal('searchModal'))
  51. document.querySelectorAll('[data-close-modal]').forEach((btn) => btn.addEventListener('click', () => closeModal(btn.dataset.closeModal)))
  52. document.querySelectorAll('.custom-modal').forEach((modal) => {
  53. modal.addEventListener('click', (e) => {
  54. if (e.target === modal) closeModal(modal.id)
  55. })
  56. })
  57. document.querySelectorAll('.footer-social-item').forEach((item) => {
  58. const closeAll = () => document.querySelectorAll('.footer-social-item.is-open').forEach((el) => el.classList.remove('is-open'))
  59. item.addEventListener('mouseenter', () => item.classList.add('is-open'))
  60. item.addEventListener('mouseleave', () => item.classList.remove('is-open'))
  61. item.addEventListener('click', (e) => {
  62. if (window.matchMedia('(hover: none)').matches) {
  63. e.preventDefault()
  64. const willOpen = !item.classList.contains('is-open')
  65. closeAll()
  66. if (willOpen) item.classList.add('is-open')
  67. }
  68. })
  69. item.addEventListener('focusin', () => item.classList.add('is-open'))
  70. item.addEventListener('focusout', () => item.classList.remove('is-open'))
  71. document.addEventListener('click', (e) => {
  72. if (!item.contains(e.target)) item.classList.remove('is-open')
  73. })
  74. })
  75. const resetSlideVideos = (selector) => {
  76. document.querySelectorAll(selector).forEach((video) => {
  77. try { video.pause(); video.currentTime = 0 } catch {}
  78. video.classList.remove('is-ready')
  79. })
  80. }
  81. document.querySelectorAll('.slide-media-layer, .card-media-layer').forEach((wrap) => {
  82. wrap.addEventListener('click', () => {
  83. const video = wrap.querySelector('.slide-video')
  84. if (!video) return
  85. video.classList.add('is-ready')
  86. video.play().catch(() => {})
  87. })
  88. })
  89. if (document.querySelector('#heroSwiper') && window.Swiper) {
  90. const heroSlides = Array.from(document.querySelectorAll('#heroSwiper .swiper-slide[data-bullet-title]'))
  91. const heroBulletTitles = heroSlides.map((slide) => slide.getAttribute('data-bullet-title') || '')
  92. new Swiper('#heroSwiper', {
  93. loop: true,
  94. speed: 900,
  95. effect: 'fade',
  96. fadeEffect: { crossFade: true },
  97. autoplay: { delay: 5000, disableOnInteraction: false },
  98. navigation: { nextEl: '.hero-next', prevEl: '.hero-prev' },
  99. pagination: {
  100. el: '.hero-pagination',
  101. clickable: true,
  102. renderBullet: function (index, className) {
  103. return `<span class="${className} hero-bar-bullet"><em>${heroBulletTitles[index] || ''}</em></span>`
  104. },
  105. },
  106. on: { slideChangeTransitionStart: () => resetSlideVideos('#heroSwiper .slide-video') },
  107. })
  108. }
  109. if (document.querySelector('#showcaseSwiper') && window.Swiper) {
  110. new Swiper('#showcaseSwiper', {
  111. loop: true,
  112. speed: 700,
  113. centeredSlides: true,
  114. slidesPerView: 1.12,
  115. spaceBetween: 12,
  116. autoplay: { delay: 4500, disableOnInteraction: false },
  117. navigation: { nextEl: '.showcase-next', prevEl: '.showcase-prev' },
  118. pagination: { el: '.showcase-pagination', clickable: true },
  119. breakpoints: {
  120. 768: { slidesPerView: 1.72, spaceBetween: 12 },
  121. 992: { slidesPerView: 2.18, spaceBetween: 12 },
  122. },
  123. on: { slideChangeTransitionStart: () => resetSlideVideos('#showcaseSwiper .slide-video') },
  124. })
  125. }