1/** 2 * Swiper Initializations 3 * 4 * Consolidates all inline Swiper inits into one cacheable file. 5 * 6 * @package ChildTheme 7 * @since 1.0.0 8 */ 9/* global manageSwiperTabindex */ 10(function () { 11 12 const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches; 13 14 function init() { 15 16 // Guard: skip if Swiper library has not loaded yet. 17 if (typeof Swiper === 'undefined') { 18 return; 19 } 20 21 // Helper to find tabbable elements in document order 22 function getTabbableElements() { 23 return Array.from(document.querySelectorAll( 24 'a[href], button, input:not([type="hidden"]), select, textarea, [tabindex]' 25 )).filter(function(el) { 26 // Exclude elements with tabindex="-1", disabled, or not visible 27 return el.offsetParent !== null && 28 !el.disabled && 29 el.getAttribute('tabindex') !== '-1'; 30 }); 31 } 32 33 // Find element before swiper section (skip any swiper-related elements) 34 function getElementBeforeSwiper(swiperEl) { 35 const section = swiperEl.closest('section.featured-posts-swiper') || swiperEl.closest('section.press-release') || swiperEl.closest('section') || swiperEl; 36 const tabbables = getTabbableElements(); 37 38 // Find first tabbable inside swiper section 39 for (let i = 0; i < tabbables.length; i++) { 40 if (section.contains(tabbables[i])) { 41 // Go backwards to find element NOT in any swiper section 42 for (let j = i - 1; j >= 0; j--) { 43 const el = tabbables[j]; 44 // Skip if element is inside any swiper/carousel 45 if (!el.closest('.swiper, .swiper-container, .featured-posts-swiper, .trending-posts, .press-release, .pr-swiper')) { 46 return el; 47 } 48 } 49 return null; 50 } 51 } 52 return null; 53 } 54 55 // Find next tabbable element after the swiper container 56 function getElementAfterSwiper(swiperEl) { 57 const tabbables = getTabbableElements(); 58 // Find last tabbable inside the swiper container (not the whole section) 59 for (let i = tabbables.length - 1; i >= 0; i--) { 60 if (swiperEl.contains(tabbables[i])) { 61 return i < tabbables.length - 1 ? tabbables[i + 1] : null; 62 } 63 } 64 return null; 65 } 66 67 // Make swiper containers accessible for keyboard navigation 68 document.querySelectorAll('.swiper, .swiper-container, .trending-posts').forEach(function (el) { 69 el.setAttribute('tabindex', '-1'); 70 if (!el.hasAttribute('role')) { 71 el.setAttribute('role', 'region'); 72 } 73 if (!el.hasAttribute('aria-label')) { 74 el.setAttribute('aria-label', 'Carousel'); 75 } 76 77 // Handle Tab/Shift+Tab to exit swiper properly 78 el.addEventListener('keydown', function(e) { 79 if (e.key !== 'Tab') return; 80 81 const visibleLinks = Array.from(el.querySelectorAll( 82 '.swiper-slide-visible:not(.swiper-slide-duplicate) a:not([tabindex="-1"]), ' + 83 '.swiper-slide-active:not(.swiper-slide-duplicate) a:not([tabindex="-1"])' 84 )); 85 86 if (!visibleLinks.length) return; 87 88 const firstLink = visibleLinks[0]; 89 const lastLink = visibleLinks[visibleLinks.length - 1]; 90 const activeEl = document.activeElement; 91 92 if (e.shiftKey && activeEl === firstLink) { 93 e.preventDefault(); 94 const prevEl = getElementBeforeSwiper(el);
95 if (prevEl) prevEl.focus(); 96 } else if (!e.shiftKey && activeEl === lastLink) { 97 e.preventDefault(); 98 const nextEl = getElementAfterSwiper(el); 99 if (nextEl) nextEl.focus(); 100 } 101 }); 102 }); 103 104 // Press Releases carousel (front-page) 105 if (document.querySelector('.pr-swiper')) { 106 new Swiper('.pr-swiper', { 107 slidesPerView: 3, 108 spaceBetween: 30, 109 loop: true, 110 keyboard: { enabled: true }, 111 a11y: { enabled: true }, 112 watchSlidesProgress: true, 113 autoplay: reducedMotion ? false : { 114 delay: 4000, 115 disableOnInteraction: false, 116 pauseOnMouseEnter: true 117 }, 118 navigation: { 119 nextEl: '.press-release .swiper-button-next', 120 prevEl: '.press-release .swiper-button-prev' 121 }, 122 pagination: { 123 el: '.press-release .swiper-pagination', 124 clickable: true 125 }, 126 breakpoints: { 127 0: { 128 slidesPerView: 1 129 }, 130 768: { 131 slidesPerView: 2 132 }, 133 1200: { 134 slidesPerView: 3 135 } 136 }, 137 on: { 138 init: function (swiper) { 139 manageSwiperTabindex(swiper); 140 141 // Pause autoplay on keyboard focus (WCAG 2.2.2). 142 swiper.el.addEventListener('focusin', function () { 143 if (swiper.autoplay && swiper.autoplay.running) { 144 swiper.autoplay.stop(); 145 } 146 }); 147 }, 148 slideChange: manageSwiperTabindex 149 } 150 }); 151 } 152 153 // Trending posts carousel (front-page) 154 if (document.querySelector('.trending-posts')) { 155 new Swiper('.trending-posts', { 156 slidesPerView: 1, 157 spaceBetween: 30, 158 loop: true, 159 speed: 800, 160 keyboard: { enabled: true }, 161 a11y: { enabled: true }, 162 watchSlidesProgress: true, 163 // autoplay: { 164 // delay: 3500, 165 // disableOnInteraction: false, 166 // }, 167 breakpoints: { 168 980: { 169 slidesPerView: 4, 170 }, 171 768: { 172 slidesPerView: 3, 173 spaceBetween: 25, 174 }, 175 480: { 176 slidesPerView: 1, 177 spaceBetween: 20, 178 }, 179 }, 180 navigation: { 181 prevEl: '.trending-navigation .swiper-button-prev', 182 nextEl: '.trending-navigation .swiper-button-next', 183 }, 184 on: { 185 init: manageSwiperTabindex, 186 slideChange: manageSwiperTabindex 187 } 188 }); 189 } 190 191 // Testimonial carousel (front-page) 192 if (document.querySelector('.testimonial-swiper')) { 193 new Swiper('.testimonial-swiper', { 194 slidesPerView: 1, 195 spaceBetween: 30, 196 loop: true, 197 speed: 700, 198 keyboard: { enabled: true }, 199 a11y: { enabled: true }, 200 effect: 'fade', 201 fadeEffect: { 202 crossFade: true 203 }, 204 navigation: { 205 prevEl: '.testimonial-navigation .swiper-button-prev', 206 nextEl: '.testimonial-navigation .swiper-button-next', 207 }, 208 // autoplay: { 209 // delay: 5000, 210 // disableOnInteraction: false, 211 // }, 212 on: { 213 init: manageSwiperTabindex, 214 slideChange: manageSwiperTabindex 215 } 216 }); 217 } 218 219 // Featured posts carousel (index, archive, single, about, team, contact, 404) 220 if (document.querySelector('.featured-posts-swiper .swiper-container')) { 221 new Swiper('.featured-posts-swiper .swiper-container', { 222 slidesPerView: 1.5, 223 centeredSlides: true, 224 spaceBetween: 5, 225 loop: true, 226 keyboard: { enabled: true }, 227 a11y: { enabled: true }, 228 watchSlidesProgress: true, 229 autoplay: reducedMotion ? false : { 230 delay: 3500, 231 disableOnInteraction: false, 232 pauseOnMouseEnter: true, 233 }, 234 speed: 800, 235 breakpoints: { 236 1300: { 237 slidesPerView: 3.5 238 }, 239 1000: { 240 slidesPerView: 2.5 241 } 242 }, 243 on: { 244 init: manageSwiperTabindex, 245 slideChange: manageSwiperTabindex 246 } 247 }); 248 } 249 250 // Image gallery with thumbnails (single post) 251 if (document.querySelector('.gallery-thumbs')) { 252 const galleryThumbs = new Swiper('.gallery-thumbs', { 253 spaceBetween: 10, 254 slidesPerView: 6, 255 freeMode: true, 256 keyboard: { enabled: true }, 257 a11y: { enabled: true }, 258 watchSlidesProgress: true, 259 watchSlidesVisibility: true, 260 slideToClickedSlide: true, 261 breakpoints: { 262 700: { 263 slidesPerView: 6 264 }, 265 480: { 266 slidesPerView: 3 267 } 268 }, 269 loop: true, 270 on: { 271 init: manageSwiperTabindex, 272 slideChange: manageSwiperTabindex 273 } 274 }); 275 276 new Swiper('.gallery-top', { 277 spaceBetween: 10, 278 keyboard: { enabled: true }, 279 a11y: { enabled: true }, 280 navigation: { 281 nextEl: '.swiper-button-next', 282 prevEl: '.swiper-button-prev' 283 }, 284 thumbs: { 285 swiper: galleryThumbs 286 }, 287 loop: true, 288 autoHeight: false, 289 on: { 290 init: manageSwiperTabindex, 291 slideChange: manageSwiperTabindex 292 } 293 }); 294 } 295 } 296 297 // Use readyState check so swipers initialize even when FlyingPress delays scripts 298 // past DOMContentLoaded. 299 if (document.readyState === 'loading') { 300 document.addEventListener('DOMContentLoaded', init); 301 } else { 302 init(); 303 } 304 305})();
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.