1/******/ (() => { // webpackBootstrap 2/******/ "use strict"; 3 4;// ./js/config.js 5 6 7const TEMPLATE_FOLDER = (/* unused pure expression or super */ null && (`${WPGlobal.themeUrl}/includes/dist/templates/`)); 8const MARKER_FOLDER = (/* unused pure expression or super */ null && (`${WPGlobal.pluginsUrl}/find-a-retailer/images/`)); 9const COOKIE = 'far_completed=true; path=/;' 10const PAGES = { 11 car: 'contact-a-retailer', 12 far: 'find-a-retailer' 13}; 14 15const SELECTORS = { 16 main_header: '#masthead', 17 navbar_mobile: '#navbar', 18 navbar_desktop: '#navbar-desktop', 19 navbar_inner_desktop: '#navbar-desktop .site-navigation-inner', 20 navbar_toggle: '.navbar-toggle', 21 navbar_mobile_link: '#navbar a', 22 navbar_mobile_buttons_container: '.site-navigation-buttons', 23 navbar_link_with_submenu: '.site-navigation .menu-item.menu-item-has-children>a', 24 dropdown_open: '.dropdown.open', 25 dropdown_menu: '.dropdown-menu', 26 dropdown_toggle: '.dropdown-toggle', 27 search_bar_input: '.search-field', 28 wp_admin_bar: '#wpadminbar', 29 header: '.far-header', 30 header_navigation: '#header-navigation', 31 header_country_selector: '.header-navigation-item.country-selector', 32 map: '.far-map', 33 tab: '.far-tab', 34 slider: '.far-slider', 35 gallery: '.far-gallery', 36 reviewsSlider: '.far-reviews-slider', 37 gallery_counter: '.far-gallery-counter', 38 gallery_counter_current: '.far-gallery-counter-current', 39 gallery_counter_size: '.far-gallery-counter-size', 40 content: '.far-main-content', 41 back_button: '.far__back-button', 42 email_button: '.far-retailer-card-button-email', 43 data_retailer_id: 'data-retailer-id', 44 retailer_id: '#far-retailer', 45 retailer_status: 'data-retailer-status', 46 breadcrumbs_item: '.far__breadcrumbs-item', 47 reviews: '.far-section--reviews', 48 rating_star: '.far-rating-star', 49 rating_stars_wrapper: '.far-rating-stars', 50 rating_stars_container: '.far-rating-stars-items-wrapper' 51} 52 53const CLASSES = { 54 slider_initialized: 'slick-initialized', 55 no_scroll: 'no-scroll', 56 active: 'active', 57 hidden: 'hidden', 58 open: 'open', 59 expanded: 'expanded', 60 desktop: 'desktop' 61} 62 63const BREAKPOINTS = { 64 phone_landscape: 576, 65 tablet: 768, 66 desktop: 992, 67 desktop_l: 1200, 68 desktop_xl: 1400, 69} 70 71const debounce = (func, delay) => { 72 let timeoutId; 73 return function (...args) { 74 clearTimeout(timeoutId); 75 timeoutId = setTimeout(() => func.apply(this, args), delay); 76 }; 77} 78 79const mobileAndTabletCheck = () => {
80 let check = false; 81 ((a) => { 82 // @ts-ignore 83 if ( 84 /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test( 85 a, 86 ) || 87 /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test( 88 a.substr(0, 4), 89 ) 90 ) { 91 check = true; 92 } 93 })(navigator.userAgent || navigator.vendor); 94 return check || 'ontouchstart' in window; 95} 96 97;// ./js/services/swiper-init.service.js 98const createSwiperInstance = (element, config = {}) => { 99 if (!element || typeof window === 'undefined' || typeof window.Swiper === 'undefined') { 100 return null; 101 } 102 103 return new window.Swiper(element, config); 104}; 105 106;// ./js/components/latest-news-slider.js 107 108 109 110const latestNewsSliders = []; 111let resizeFrame = null; 112let isResizeBound = false; 113 114const getLatestNewsSlidesPerView = () => { 115 if (window.innerWidth >= BREAKPOINTS.desktop_l) { 116 return 3; 117 } 118 119 return "auto"; 120}; 121 122const resizeLatestNewsSlider = (sliderItem) => { 123 const swiper = sliderItem?.instance; 124 if (!swiper) { 125 return; 126 } 127 128 const nextSlidesPerView = getLatestNewsSlidesPerView(); 129 const shouldUpdateSlidesPerView = swiper.params.slidesPerView !== nextSlidesPerView; 130 if (shouldUpdateSlidesPerView) { 131 swiper.params.slidesPerView = nextSlidesPerView; 132 } 133 134 swiper.update(); 135 equalizeLatestNewsContentHeight(sliderItem?.listElement || null); 136}; 137 138const equalizeLatestNewsContentHeight = (scopeElement = null) => { 139 const root = scopeElement || document; 140 const contentElements = Array.from(root.querySelectorAll('.wp-block-latest-posts__content')); 141 if (!contentElements.length) { 142 return; 143 } 144 145 contentElements.forEach((element) => { 146 element.style.minHeight = ''; 147 }); 148 149 let maxHeight = 0; 150 contentElements.forEach((element) => { 151 maxHeight = Math.max(maxHeight, Math.ceil(element.getBoundingClientRect().height)); 152 }); 153 154 if (maxHeight <= 0) { 155 return; 156 } 157 158 contentElements.forEach((element) => { 159 element.style.minHeight = `${maxHeight}px`; 160 }); 161}; 162 163const initLatestNewsSliders = () => { 164 const latestNewsLists = document.querySelectorAll('.home-page-section .wp-block-latest-posts'); 165 if (!latestNewsLists.length) { 166 return; 167 } 168 169 latestNewsLists.forEach((listElement) => { 170 if (listElement.classList.contains('latest-news-swiper__wrapper')) { 171 return; 172 } 173 174 const slides = Array.from(listElement.children); 175 if (slides.length < 2) { 176 return; 177 } 178 179 const container = document.createElement('div'); 180 container.className = 'latest-news-swiper swiper'; 181 182 const parent = listElement.parentNode; 183 if (!parent) { 184 return; 185 } 186 187 parent.insertBefore(container, listElement); 188 container.appendChild(listElement); 189 190 listElement.classList.add('latest-news-swiper__wrapper', 'swiper-wrapper');
191 slides.forEach((slide) => slide.classList.add('swiper-slide')); 192 193 const instance = createSwiperInstance(container, { 194 slidesPerView: getLatestNewsSlidesPerView(), 195 spaceBetween: 24, 196 loop: false, 197 observer: true, 198 observeParents: true, 199 watchOverflow: true, 200 navigation: { 201 enabled: false, 202 } 203 }); 204 205 if (!instance) { 206 return; 207 } 208 209 const sliderItem = { 210 instance, 211 slidesCount: slides.length, 212 listElement 213 }; 214 215 latestNewsSliders.push(sliderItem); 216 resizeLatestNewsSlider(sliderItem); 217 }); 218 219 document.querySelectorAll('.home-page-section .wp-block-latest-posts').forEach((listElement) => { 220 equalizeLatestNewsContentHeight(listElement); 221 }); 222 223 bindLatestNewsResize(); 224}; 225 226const updateLatestNewsSliders = () => { 227 if (!latestNewsSliders.length) { 228 return; 229 } 230 231 latestNewsSliders.forEach((sliderItem) => { 232 resizeLatestNewsSlider(sliderItem); 233 }); 234 235 document.querySelectorAll('.home-page-section .wp-block-latest-posts').forEach((listElement) => { 236 equalizeLatestNewsContentHeight(listElement); 237 }); 238}; 239 240const handleWindowResize = () => { 241 if (resizeFrame !== null) { 242 window.cancelAnimationFrame(resizeFrame); 243 } 244 245 resizeFrame = window.requestAnimationFrame(() => { 246 resizeFrame = null; 247 updateLatestNewsSliders(); 248 }); 249}; 250 251const bindLatestNewsResize = () => { 252 if (isResizeBound) { 253 return; 254 } 255 256 window.addEventListener('resize', handleWindowResize); 257 isResizeBound = true; 258}; 259 260 261 262;// ./js/applications/theme-header.js 263 264 265 266 267 268const Header = { 269 DEBOUNCE_DELAY_MS: 50, 270 isMobile: mobileAndTabletCheck(), 271 wpNavbarHeight: document.querySelector(SELECTORS.wp_admin_bar)?.clientHeight || 0, 272 header: document.querySelector(SELECTORS.main_header), 273 navbarMobile: document.querySelector(SELECTORS.navbar_mobile), 274 navbarDesktop: document.querySelector(SELECTORS.navbar_desktop), 275 navbarInnerDesktop: document.querySelector(SELECTORS.navbar_inner_desktop), 276 homeSliderElement: null, 277 homeSliderInstance: null, 278 lastScrollTop: 0, 279 isKioskMode: new URLSearchParams(window.location.search).get('kiosk')?.toLowerCase() === 'true', 280 281 init() { 282 this.initHandlers(); 283 this.setInitialNavbarTop(); 284 this.adjustHeaderAndNavbarForWPNavbar(); 285 this.displayMobileCountrySelector(); 286 this.waitForFontApply('Roboto').then(this.controlDesktopNavbarDisplay.bind(this)); 287 this.initHomeSlider(); 288 initLatestNewsSliders(); 289 this.moveBlockBackgroundToSection(); 290 }, 291 292 initHandlers() { 293 this.scrollHandler(); 294 this.navbarButtonAttributeHandler(); 295 this.searchBarInputHandler(); 296 this.resizeHandler(); 297 this.tooltipHandlers(); 298 this.navbarDesktopMutationObserver(); 299 this.handleMobileNavbarLinkClick(); 300 this.setupLinkWithSubmenuHandlers(); 301 }, 302 303 scrollHandler() { 304 window.addEventListener('scroll', debounce(this.updateNavbarOnScroll.bind(this), this.DEBOUNCE_DELAY_MS)) 305 }, 306 307 updateNavbarOnScroll() { 308 if (!this.header || !this.navbarDesktop || (this.isMobile && !this.isDesktopResolution()) || this.isDesktopNavbarOverflowing()) { 309 return; 310 } 311 312 this.closeAllDesktopDropdown(); 313 314 const pageHasScroll = !!window.scrollY; 315 const direction = this.getScrollDirection(); 316 const offset = this.getHeaderOffsetTop(); 317 318 switch (direction) { 319 case 'down': 320 this.navbarDesktop.style.top = `${offset - (pageHasScroll ? this.navbarDesktop.clientHeight : 0)}px`; 321 break; 322 case 'up': 323 this.setInitialNavbarTop(); 324 } 325 326 this.navbarDesktop.classList.toggle(CLASSES.hidden, this.isKioskMode || (direction === 'down' && pageHasScroll)); 327 }, 328 329 getScrollDirection() { 330 const currentScroll = window.scrollY; 331 const delta = 5; 332 333 if (Math.abs(currentScroll - this.lastScrollTop) <= delta) { 334 return null; 335 } 336 337 const direction = currentScroll > this.lastScrollTop ? 'down' : 'up'; 338 this.lastScrollTop = currentScroll <= 0 ? 0 : currentScroll; 339 340 return direction; 341 }, 342 343 setInitialNavbarTop() { 344 const offsetTop = this.getHeaderOffsetTop(); 345 const isOpenMobileMenu = document.querySelector(SELECTORS.navbar_toggle) 346 .getAttribute('aria-expanded') === 'true'; 347 348 this.navbarDesktop.style.top = `${offsetTop}px`; 349 Object.assign(this.navbarMobile.style, { 350 top: this.isDesktopResolution() || isOpenMobileMenu ? `${offsetTop}px`: '', 351 height: this.isDesktopResolution() || isOpenMobileMenu ? `calc(100% - ${offsetTop}px)`: '', 352 }); 353 354 this.setHeaderTopOffsetCSSVar(); 355 }, 356 357 getHeaderOffsetTop() { 358 return this.header.clientHeight + this.wpNavbarHeight; 359 }, 360 361 setHeaderTopOffsetCSSVar() { 362 document.documentElement.setAttribute( 363 'style', 364 `--headerOffsetTop:${this.getHeaderOffsetTop()}px` 365 ); 366 }, 367 368 adjustHeaderAndNavbarForWPNavbar() { 369 this.header.style.top = `${this.wpNavbarHeight}px`; 370 this.navbarDesktop.style.top = `${this.getHeaderAndWPNavbarOffsetTop()}px`; 371 }, 372 373 getHeaderAndWPNavbarOffsetTop() { 374 return this.wpNavbarHeight + this.header.clientHeight; 375 }, 376 377 navbarButtonAttributeHandler() { 378 const navBarToggle = document.querySelector(SELECTORS.navbar_toggle); 379 380 const mutationObserver = new MutationObserver(mutations => { 381 for (const mutation of mutations) { 382 if (mutation.type === 'attributes' && mutation.attributeName === 'aria-expanded') { 383 this.onNavbarClick(navBarToggle); 384 } 385 } 386 }); 387 388 mutationObserver.observe(navBarToggle, { attributes: true }); 389 }, 390 391 navbarDesktopMutationObserver() { 392 const mutationObserver = new MutationObserver(mutations => { 393 for (const mutation of mutations) { 394 if (mutation.attributeName === 'style' && this.lastScrollTop <= this.getHeaderOffsetTop()) { 395 this.setHeaderTopOffsetCSSVar(); 396 } 397 } 398 }); 399 400 mutationObserver.observe(this.navbarDesktop, { attributes: true }); 401 }, 402 403 resizeHandler() { 404 window.addEventListener('resize', debounce(this.onResize.bind(this), this.DEBOUNCE_DELAY_MS)); 405 }, 406 407 onResize() { 408 this.setInitialNavbarTop(); 409 this.controlDesktopNavbarDisplay(); 410 this.updateHomeSliderDirection(); 411 this.updateHomeSliderHeight(); 412 }, 413 414 onNavbarClick(button) { 415 const isOpen = button.getAttribute('aria-expanded') === 'true'; 416 const offsetTop = this.getHeaderAndWPNavbarOffsetTop(); 417 const activeMobileNavbarStatus = this.isMobile || this.isDesktopResolution() && this.isDesktopNavbarOverflowing(); 418 419 Object.assign(this.navbarMobile.style, { 420 top: isOpen ? `${offsetTop}px`: '', 421 height: isOpen ? `calc(100% - ${offsetTop}px)`: '', 422 }); 423 424 document.body.classList.toggle(CLASSES.no_scroll, isOpen); 425 this.navbarMobile.classList.toggle(CLASSES.active, isOpen && activeMobileNavbarStatus); 426 }, 427 428 controlDesktopNavbarDisplay() { 429 this.displayMobileCountrySelector(); 430 431 if (!this.isDesktopResolution()) { 432 return; 433 } 434 435 const isOverflowing = this.isDesktopNavbarOverflowing(); 436 const navbarToggleButton = document.querySelector(SELECTORS.navbar_toggle); 437 const hideDesktopNavbar = this.isKioskMode || !this.isDesktopResolution() || isOverflowing || (this.isMobile && !this.isDesktopResolution()); 438 const headerCountrySelector = document.querySelector(SELECTORS.header_country_selector); 439 440 this.navbarDesktop.classList.toggle(CLASSES.hidden, hideDesktopNavbar); 441 navbarToggleButton.classList.toggle(CLASSES.active, hideDesktopNavbar); 442 headerCountrySelector.classList.toggle(CLASSES.hidden, !hideDesktopNavbar); 443 headerCountrySelector.classList.toggle(CLASSES.desktop, !hideDesktopNavbar); 444 navbarToggleButton.setAttribute( 445 'aria-expanded', 446 hideDesktopNavbar ? 'false' : navbarToggleButton.getAttribute('aria-expanded') 447 ); 448 }, 449 450 displayMobileCountrySelector() { 451 if (!this.isDesktopResolution()) { 452 const headerCountrySelector = document.querySelector(SELECTORS.header_country_selector); 453 headerCountrySelector.classList.remove(CLASSES.hidden); 454 } 455 }, 456 457 searchBarInputHandler() { 458 const searchInput = document.querySelector(SELECTORS.search_bar_input); 459 const submitButton = searchInput?.closest('form')?.querySelector('[type="submit"]'); 460 461 searchInput.addEventListener('input', () => { 462 submitButton?.toggleAttribute('disabled', !searchInput.value.trim()); 463 }); 464 }, 465 466 handleMobileNavbarLinkClick() { 467 this.navbarMobile.addEventListener('click', event => { 468 const parent = event.target?.parentElement; 469 470 if (!parent) { 471 return; 472 } 473 474 const openedDropdownParent = parent.closest(SELECTORS.dropdown_open); 475 const dropdownMenu = parent.closest(SELECTORS.dropdown_menu); 476 const navbarButtonsClicked = document.querySelector(SELECTORS.navbar_mobile_buttons_container)?.contains(event.target); 477 const clickOutsideLink = this.navbarMobile.contains(event.target) && !event.target?.closest('a'); 478 479 if (openedDropdownParent && dropdownMenu || navbarButtonsClicked || clickOutsideLink) { 480 event.stopImmediatePropagation(); 481 } 482 }) 483 }, 484 485 tooltipHandlers() { 486 window.addEventListener('mouseover', this.preventTitleTooltipOnHover.bind(this)); 487 window.addEventListener('mouseout', this.preventTitleTooltipOnHover.bind(this)); 488 }, 489 490 preventTitleTooltipOnHover(event) { 491 const titleAttr = 'title'; 492 const dataAttr = 'data-title'; 493 const attrForChange = event.type === 'mouseover' ? titleAttr : dataAttr; 494 const target = event.target.closest(`[${attrForChange}]`); 495 496 if (!target) { 497 return; 498 } 499 500 switch (event.type) { 501 case 'mouseover': 502 this.moveElementAttribute(target, titleAttr, dataAttr); 503 break; 504 case 'mouseout': 505 this.moveElementAttribute(target, dataAttr, titleAttr); 506 break; 507 } 508 }, 509 510 moveElementAttribute(element, fromAttr, toAttr) { 511 const attrValue = element.getAttribute(fromAttr); 512 513 element.setAttribute(toAttr, attrValue); 514 element.removeAttribute(fromAttr); 515 }, 516 517 isDesktopNavbarOverflowing() { 518 return this.navbarInnerDesktop.scrollWidth > this.navbarInnerDesktop.clientWidth; 519 }, 520 521 isDesktopResolution() { 522 return window.innerWidth >= BREAKPOINTS.desktop; 523 }, 524 525 setupLinkWithSubmenuHandlers() { 526 const links = document.querySelectorAll(SELECTORS.navbar_link_with_
526submenu); 527 links.forEach(link => { 528 this.removeHrefAttribute(link); 529 this.handleLinkWithSubmenuClick(link); 530 }); 531 }, 532 533 removeHrefAttribute(element) { 534 element.removeAttribute('href'); 535 }, 536 537 handleLinkWithSubmenuClick(link) { 538 link.addEventListener('click', this.onLinkWithSubmenuClick.bind(this, link)); 539 }, 540 541 onLinkWithSubmenuClick(linkElement, event) { 542 const hasDropdownParent = !!linkElement.parentElement.closest(SELECTORS.dropdown_menu); 543 544 if (!hasDropdownParent) { 545 return; 546 } 547 548 event.preventDefault(); 549 event.stopPropagation(); 550 551 if (!event.currentTarget.parentElement.classList.contains(CLASSES.expanded)) { 552 this.handleParentMenuToggle(linkElement); 553 } 554 555 event.currentTarget.parentElement.classList.toggle(CLASSES.expanded); 556 }, 557 558 handleParentMenuToggle(linkElement) { 559 const parentMenu = linkElement.closest(SELECTORS.dropdown_open); 560 const dropdownButton = parentMenu.querySelector(SELECTORS.dropdown_toggle); 561 const observer = new MutationObserver(mutations => { 562 for (const mutation of mutations) { 563 if (mutation.type === 'attributes' && mutation.attributeName === 'aria-expanded') { 564 const isOpen = dropdownButton.getAttribute('aria-expanded') === 'true'; 565 if (!isOpen) { 566 linkElement.parentElement.classList.remove(CLASSES.expanded); 567 observer.disconnect(); 568 } 569 } 570 } 571 }); 572 573 observer.observe(dropdownButton, { attributes: true }); 574 }, 575 576 closeAllDesktopDropdown() { 577 const dropdowns = this.navbarDesktop.querySelectorAll(SELECTORS.dropdown_toggle); 578 dropdowns.forEach(dropdown => { 579 dropdown.setAttribute('aria-expanded', 'false'); 580 dropdown.parentElement.classList.remove(CLASSES.open); 581 }); 582 }, 583 584 waitForFontApply(fontFamily = 'Roboto', fontSize = '16px', text = 'FontReady') { 585 if (!document.fonts || typeof document.fonts.load !== 'function') { 586 return Promise.resolve(); 587 } 588 589 return document.fonts 590 .load(`${fontSize} "${fontFamily}"`, text) 591 .then(() => undefined, () => undefined); 592 }, 593 594 initHomeSlider() { 595 const sliderElement = document.querySelector('.home-slider.swiper'); 596 597 if (!sliderElement || typeof window.Swiper === 'undefined') { 598 return; 599 } 600 601 this.homeSliderElement = sliderElement; 602 603 const slidesCount = Number.parseInt(sliderElement.dataset.slidesCount, 10) || 0; 604 const sliderConfig = WPGlobal?.homeSliderConfig || {}; 605 const autoplayConfig = sliderConfig.autoplay ? { 606 delay: sliderConfig.delay || 15000, 607 disableOnInteraction: false 608 } : false; 609 610 this.homeSliderInstance = new window.Swiper(sliderElement, { 611 slidesPerView: 1, 612 spaceBetween: 0, 613 speed: sliderConfig.speed || 600, 614 loop: Boolean(sliderConfig.loop) && slidesCount > 2, 615 roundLengths: true, 616 autoplay: autoplayConfig, 617 direction: 'horizontal', 618 observer: true, 619 observeParents: true, 620 updateOnWindowResize: true, 621 keyboard: { 622 enabled: true, 623 onlyInViewport: true, 624 }, 625 a11y: { 626 enabled: true, 627 containerRoleDescriptionMessage: 'carousel', 628 containerMessage: 'Homepage featured slides', 629 slideRole: 'group', 630 slideLabelMessage: '{{index}} / {{slidesLength}}', 631 paginationBulletMessage: 'Go to slide {{index}}' 632 }, 633 pagination: { 634 el: '.home-slider .swiper-pagination', 635 clickable: true 636 } 637 }); 638 639 this.homeSliderInstance.on('slideChangeTransitionEnd', this.updateHomeSliderHeight.bind(this)); 640 this.applyHomeSliderSlideBackgrounds(sliderElement); 641 this.updateHomeSliderHeight(); 642 }, 643 644 applyHomeSliderSlideBackgrounds(sliderElement = this.homeSliderElement) { 645 if (!sliderElement) { 646 return; 647 } 648 649 const slideElements = Array.from(sliderElement.querySelectorAll('.swiper-slide')); 650 651 slideElements.forEach((slideElement) => {
652 this.applyHomeSliderSlideBackground(slideElement); 653 }); 654 }, 655 656 applyHomeSliderSlideBackground(slideElement) { 657 if (!slideElement || slideElement.dataset.backgroundColorApplied === 'true') { 658 return; 659 } 660 661 const imageElement = this.getHomeSliderSlideImage(slideElement); 662 663 if (!imageElement) { 664 return; 665 } 666 667 this.whenImageReady(imageElement) 668 .then((image) => { 669 const backgroundColor = this.getImageGeneralColor(image); 670 671 if (!backgroundColor) { 672 return; 673 } 674 675 slideElement.style.backgroundColor = backgroundColor; 676 slideElement.style.setProperty('--home-slide-background', backgroundColor); 677 slideElement.dataset.backgroundColorApplied = 'true'; 678 }) 679 .catch(() => {}); 680 }, 681 682 getHomeSliderSlideImage(slideElement) { 683 return slideElement.querySelector('.slide-image img, .home-slider-image img, picture img, img'); 684 }, 685 686 whenImageReady(imageElement) { 687 if (imageElement.complete && imageElement.naturalWidth && imageElement.naturalHeight) { 688 return Promise.resolve(imageElement); 689 } 690 691 return new Promise((resolve, reject) => { 692 imageElement.addEventListener('load', () => resolve(imageElement), { once: true }); 693 imageElement.addEventListener('error', reject, { once: true }); 694 }); 695 }, 696 697 getImageGeneralColor(imageElement) { 698 const naturalWidth = imageElement.naturalWidth || imageElement.width;
699 const naturalHeight = imageElement.naturalHeight || imageElement.height; 700 701 if (!naturalWidth || !naturalHeight) { 702 return null; 703 } 704 705 const sampleSize = 24; 706 const scale = Math.min(sampleSize / naturalWidth, sampleSize / naturalHeight, 1); 707 const canvas = document.createElement('canvas'); 708 const context = canvas.getContext('2d', { willReadFrequently: true }); 709 710 if (!context) { 711 return null; 712 } 713 714 canvas.width = Math.max(1, Math.round(naturalWidth * scale)); 715 canvas.height = Math.max(1, Math.round(naturalHeight * scale)); 716 717 try { 718 context.drawImage(imageElement, 0, 0, canvas.width, canvas.height); 719 const pixels = context.getImageData(0, 0, canvas.width, canvas.height).data; 720 const colorBuckets = {}; 721 722 for (let index = 0; index < pixels.length; index += 4) { 723 const alpha = pixels[index + 3]; 724 725 if (alpha < 128) { 726 continue; 727 } 728 729 const red = pixels[index]; 730 const green = pixels[index + 1]; 731 const blue = pixels[index + 2]; 732 const bucketKey = [ 733 Math.round(red / 24), 734 Math.round(green / 24), 735 Math.round(blue / 24) 736 ].join('-'); 737 738 if (!colorBuckets[bucketKey]) { 739 colorBuckets[bucketKey] = { 740 count: 0, 741 red: 0, 742 green: 0, 743 blue: 0 744 }; 745 } 746 747 colorBuckets[bucketKey].count += 1; 748 colorBuckets[bucketKey].red += red; 749 colorBuckets[bucketKey].green += green; 750 colorBuckets[bucketKey].blue += blue; 751 } 752 753 const dominantBucket = Object.values(colorBuckets).sort((bucketA, bucketB) => bucketB.count - bucketA.count)[0]; 754 755 if (!dominantBucket) { 756 return null; 757 } 758 759 return `rgb(${Math.round(dominantBucket.red / dominantBucket.count)}, ${Math.round(dominantBucket.green / dominantBucket.count)}, ${Math.round(dominantBucket.blue / dominantBucket.count)})`; 760 } catch (error) { 761 return null; 762 } 763 }, 764 765 getHomeSliderDirection() { 766 return this.isDesktopResolution() ? 'vertical' : 'horizontal'; 767 }, 768 769 updateHomeSliderDirection() { 770 if (!this.homeSliderInstance || typeof this.homeSliderInstance.changeDirection !== 'function') { 771 return; 772 } 773 774 const nextDirection = this.getHomeSliderDirection(); 775 const currentDirection = this.homeSliderInstance.params?.direction; 776 777 if (currentDirection === nextDirection) { 778 return; 779 } 780 781 this.homeSliderInstance.changeDirection(nextDirection); 782 this.homeSliderInstance.update(); 783 this.updateHomeSliderHeight(); 784 }, 785 786 updateHomeSliderHeight() { 787 const sliderElement = this.homeSliderElement || document.querySelector('.home-slider.swiper'); 788 789 if (!sliderElement) { 790 return; 791 } 792 793 const wrapperElement = sliderElement.querySelector('.swiper-wrapper'); 794 const slideElements = Array.from(sliderElement.querySelectorAll('.swiper-slide')); 795 const isVerticalSlider = this.homeSliderInstance?.params?.direction === 'vertical'; 796 797 // Reset previous inline dimensions before measuring real block height from CSS. 798 sliderElement.style.removeProperty('height'); 799 wrapperElement?.style.removeProperty('height'); 800 slideElements.forEach((slide) => slide.style.removeProperty('height')); 801 802 if (!isVerticalSlider) { 803 this.homeSliderInstance?.update(); 804 return; 805 } 806 807 const activeSlide = slideElements[this.homeSliderInstance?.activeIndex || 0] || slideElements[0]; 808 const activeSlideContent = activeSlide?.firstElementChild; 809 const activeSlideHeight = Math.ceil( 810 activeSlideContent?.getBoundingClientRect().height || 811 activeSlide?.getBoundingClientRect().height || 812 0 813 ); 814 815 if (!activeSlideHeight) { 816 this.homeSliderInstance?.update(); 817 return; 818 } 819 820 const sliderHeightPx = `${activeSlideHeight}px`; 821 sliderElement.style.height = sliderHeightPx; 822 wrapperElement?.style.setProperty('height', sliderHeightPx); 823 slideElements.forEach((slide) => slide.style.setProperty('height', sliderHeightPx)); 824 825 this.homeSliderInstance?.update(); 826 }, 827 828 moveBlockBackgroundToSection() { 829 const sectionEntries = document.querySelectorAll('.home-page-section .entry-content'); 830 831 sectionEntries.forEach((entry) => { 832 const sourceElement = Array.from(entry.querySelectorAll('*')).find((element) => { 833 const classes = Array.from(element.classList || []); 834 return classes.some((className) => className.indexOf('wp-block-') === 0); 835 }); 836 837 if (!sourceElement) { 838 return; 839 } 840 841 const styleAttr = sourceElement.getAttribute('style') || '';
842 const colorMatch = styleAttr.match(/(?:^|;)\s*background-color\s*:\s*([^;]+)\s*(?=;|$)/i); 843 844 if (!colorMatch || !colorMatch[1]) { 845 return; 846 } 847 848 const backgroundColor = colorMatch[1].trim(); 849 const styleWithoutBackground = styleAttr 850 .replace(/(?:^|;)\s*background-color\s*:\s*[^;]+(?=;|$)\s*;?/ig, ';') 851 .replace(/\s*;\s*/g, '; ') 852 .replace(/;{2,}/g, ';') 853 .trim() 854 .replace(/^;\s*|\s*;$/g, ''); 855 856 if (styleWithoutBackground) { 857 sourceElement.setAttribute('style', styleWithoutBackground); 858 } else { 859 sourceElement.removeAttribute('style'); 860 } 861 862 entry.style.backgroundColor = backgroundColor; 863 }); 864 }, 865 866} 867 868Header.init(); 869 870/******/ })() 871;
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.