1/** Front-page behaviors. Lower pages never load this file. */ 2(function (Drupal, once) { 3 'use strict'; 4 const carouselSpeed = 450; 5 const carouselDelay = 3250; 6 function carousel(section, trackSelector, viewportSelector, prevSelector, nextSelector, delay, mobileOnly = false) { 7 if (!section) return; 8 const track = section.querySelector(trackSelector); 9 const viewport = section.querySelector(viewportSelector); 10 const previous = section.querySelector(prevSelector); 11 const next = section.querySelector(nextSelector); 12 const originals = [...track.children]; 13 if (!originals.length) { section.hidden = true; return; } 14 const dots = section.querySelector('.pickup-dots'); 15 const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)'); 16 const count = originals.length; 17 const cloneCard = card => { 18 const clone = card.cloneNode(true); 19 clone.removeAttribute('id'); 20 clone.querySelectorAll('[id]').forEach(element => element.removeAttribute('id')); 21 return clone; 22 }; 23 const before = originals.map(cloneCard); 24 const after = originals.map(cloneCard); 25 const normalize = value => (value % count + count) % count; 26 let index = 0, shown = 3, timer, settleTimer, startX, moving = false, looping = false; 27 const stop = () => window.clearInterval(timer); 28 const start = () => { 29 stop(); 30 if (looping && !reducedMotion.matches && !document.hidden && !section.matches(':hover') && !section.contains(document.activeElement)) { 31 timer = window.setInterval(() => move(index + 1), delay); 32 } 33 }; 34 const render = (animate = true) => { 35 const step = originals[0].getBoundingClientRect().width + (parseFloat(getComputedStyle(track).columnGap) || 0); 36 track.style.transition = animate && !reducedMotion.matches ? `transform ${carouselSpeed}ms ease` : 'none'; 37 const position = looping ? count + index : 0; 38 track.style.transform = `translateX(${-position * step}px)`; 39 [...track.children].forEach((card, i) => { 40 const visible = i >= position && i < position + shown; 41 card.inert = !visible; 42 card.setAttribute('aria-hidden', String(!visible)); 43 }); 44 dots?.querySelectorAll('button').forEach((dot, i) => { 45 dot.classList.toggle('is-active', i === normalize(index)); 46 dot.setAttribute('aria-current', String(i === normalize(index))); 47 }); 48 }; 49 const settle = () => { 50 window.clearTimeout(settleTimer); 51 index = normalize(index); 52 render(false); 53 moving = false; 54 }; 55 track.addEventListener('transitionend', event => { 56 if (event.target === track && event.propertyName === 'transform' && moving) settle(); 57 }); 58 const move = (target) => { 59 if (moving || !looping) return; 60 index = target; 61 moving = true; 62 render(); 63 // Reduced motion has no transitionend; the timeout also covers interrupted transitions. 64 if (reducedMotion.matches) settle(); 65 else settleTimer = window.setTimeout(settle, carouselSpeed + 50); 66 }; 67 const resize = () => { 68 window.clearTimeout(settleTimer); 69 moving = false; 70 const desktop = window.matchMedia('(min-width: 737px)').matches; 71 shown = desktop ? (mobileOnly ? count : 3) : 1; 72 looping = count > 1 && !(mobileOnly && desktop); 73 index = looping ? normalize(index) : 0; 74 track.replaceChildren(...(looping ? [...before, ...originals, ...after] : originals)); 75 previous.hidden = next.hidden = !looping; 76 if (dots) { 77 dots.replaceChildren(); 78 if (looping) for (let i = 0; i < count; i++) { 79 const dot = document.createElement('button'); dot.type = 'button'; 80 dot.setAttribute('aria-label', `${i + 1}ä»¶ç®ã®è¨äºã表示`); 81 dot.addEventListener('click', () => { move(i); start(); }); dots.append(dot); 82 } 83 } 84 render(false); start(); 85 }; 86 previous.addEventListener('click', () => { move(index - 1); start(); }); 87 next.addEventListener('click', () => { move(index + 1); start(); }); 88 section.addEventListener('mouseenter', stop); 89 section.addEventListener('mouseleave', start);
90 section.addEventListener('focusin', stop); 91 section.addEventListener('focusout', () => window.setTimeout(start, 0)); 92 viewport.addEventListener('touchstart', e => { startX = e.changedTouches[0].clientX; stop(); }, { passive: true }); 93 viewport.addEventListener('touchend', e => { 94 const distance = e.changedTouches[0].clientX - startX; 95 if (Math.abs(distance) > 40) move(index + (distance < 0 ? 1 : -1)); start(); 96 }, { passive: true }); 97 window.addEventListener('resize', resize); 98 document.addEventListener('visibilitychange', start); 99 reducedMotion.addEventListener('change', start); 100 resize(); 101 } 102 103 function switchResponsiveImages(body) { 104 const update = () => { 105 const suffix = window.innerWidth > 736 ? '_pc.' : '_sp.'; 106 body.querySelectorAll('img.jsSwitch').forEach(image => { 107 image.src = image.src.replace(/_(?:pc|sp)\./, suffix); 108 image.style.visibility = 'visible'; 109 }); 110 }; 111 update(); 112 window.addEventListener('resize', update); 113 } 114 115 function newsSwiper(body) { 116 const slider = body.querySelector('.swiperNews'); 117 if (!slider || typeof window.Swiper !== 'function') return; 118 const slides = slider.querySelectorAll('.swiper-slide'); 119 new window.Swiper(slider, { 120 slidesPerView: 'auto', 121 spaceBetween: 30, 122 centeredSlides: false, 123 loop: slides.length > 1, 124 speed: carouselSpeed, 125 autoplay: { 126 delay: carouselDelay, 127 pauseOnMouseEnter: true, 128 waitForTransition: false, 129 }, 130 navigation: { 131 nextEl: body.querySelector('.swiper-button-next'), 132 prevEl: body.querySelector('.swiper-button-prev'), 133 }, 134 breakpoints: { 135 812: { 136 spaceBetween: 30, 137 roundLengths: true, 138 }, 139 }, 140 }); 141 } 142 143 Drupal.behaviors.front = { 144 attach(context) { 145 once('front', 'body.tg-front', context).forEach(body => { 146 switchResponsiveImages(body); 147 newsSwiper(body); 148 carousel(body.querySelector('.tg-purpose'), '.purpose-cards', '.purpose-viewport', '.purpose-slide-prev', '.purpose-slide-next', carouselDelay, true); 149 }); 150 } 151 }; 152})(Drupal, once);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.