1'use strict'; 2/* eslint-disable */ //TODO: be aware of unused vars 3function slider_script(params) { 4 5 const sliders = document.querySelectorAll('.fr-slider'); 6 const inBuilder = document.querySelector('.iframe.mounted'); 7 8 const { isWpgb = false } = params || {}; 9 const processedLazyImages = new WeakSet(); 10 if (isWpgb) { 11 sliders.forEach((slider) => { 12 13 14 // remove pagination 15 const list = slider.querySelector('.splide__list'); 16 17 const pagination = slider.querySelector('.splide__pagination'); 18 if (pagination) pagination.remove(); 19 if (list.classList.contains('.wpgb-enabled')) { 20 const children = list.children; 21 22 for (let i = 0; i < children.length; i++) { 23 children[i].remove(); 24 } 25 26 } 27 }); 28 return; 29 } 30 31 const { isBricksFilters = false } = params || {}; 32 33 storeID(sliders); 34 addSlideClasses(sliders); 35 initiateSliders(sliders); 36 // switchIds(sliders) 37 // setBreakoutOverflow(sliders) 38 // paginationRender(sliders) 39 40 41 function afterSplideMounted() { 42 // storeID(sliders) 43 switchIds(sliders); 44 setBreakoutOverflow(sliders);
45 customAriaControls(sliders); 46 setListItemRoles(sliders); 47 fixLazyLoadedImages(sliders, true); 48 } 49 50 function fixLazyLoadedImages(sliders, triggerBricksLazyLoad) { 51 sliders.forEach((slider) => { 52 slider.querySelectorAll('img[loading="lazy"]').forEach((img) => { 53 if (processedLazyImages.has(img)) return; 54 processedLazyImages.add(img); 55 img.setAttribute('loading', 'eager'); 56 if (!img.complete && img.src) { 57 const reload = () => { img.src = img.src; }; 58 if (typeof img.decode === 'function') { 59 img.decode().catch(() => {}).finally(reload); 60 } else { 61 reload(); 62 } 63 } 64 }); 65 }); 66 67 if (triggerBricksLazyLoad && typeof bricksLazyLoad === 'function') { 68 bricksLazyLoad(); 69 } 70 } 71 72 function customAriaControls(sliders) { 73 74 [...sliders] 75 .map((slider) => { 76 const options = sliderOptions(slider); 77 const slides = slider.querySelectorAll('.splide__slide:not(.splide__slide--clone)'); 78 const paginationList = slider.querySelectorAll('.splide__pagination'); 79 80 return { slides, paginationList, options }; 81 }) 82 .filter(({ options, paginationList }) => (options.pagination && paginationList)) 83 .forEach(({ slides, paginationList }) => [...paginationList].flatMap(getFixedAriaIDs).forEach(fixAriaIDs(slides)) 84 ); 85 86 function fixAriaIDs() { 87 return ({ child, index }) => { 88 const slides = document.querySelectorAll('.splide__slide'); 89 const slideId = slides[index].id; 90 const childBullet = child.querySelector('button'); 91 childBullet.setAttribute('aria-controls', slideId); 92 }; 93 } 94 95 function getFixedAriaIDs(pagination) { 96 return [...pagination.querySelectorAll('li')] 97 .map((child, index) => ({ child, index })); 98 } 99 100 } 101 102 function setListItemRoles(sliders) { 103 sliders.forEach((slider) => { 104 const hasPagination = slider.querySelector('.splide__pagination'); 105 const list = slider.querySelector('.splide__list'); 106 const slides = slider.querySelectorAll('.splide__slide'); 107 108 // Remove any existing roles first 109 list.removeAttribute('role');
110 slides.forEach(slide => slide.removeAttribute('role')); 111 112 if (hasPagination) { 113 // When pagination is visible 114 list.setAttribute('role', 'tablist'); 115 slides.forEach(slide => { 116 if (slide.tagName === 'LI') { 117 slide.setAttribute('role', 'tab'); 118 } 119 }); 120 } else { 121 // When pagination is hidden 122 list.setAttribute('role', 'list'); 123 slides.forEach(slide => { 124 if (slide.tagName === 'LI') { 125 slide.setAttribute('role', 'listitem'); 126 } 127 }); 128 } 129 }); 130 } 131 132 133 removeExtraPaginationInBuilder(sliders); 134 removeExtraPaginationInBricksFilters(sliders); 135 136 function storeID(sliders) { 137 sliders.forEach((slider) => { 138 const list = slider.querySelector('.splide__list'); 139 const children = list.children; 140 for (let i = 0; i < children.length; i++) { 141 // if(!children[i].id){ 142 // children[i].id = `demo-${[i]}` 143 144 // } 145 children[i].dataset.slideId = children[i].id; 146 } 147 }); 148 } 149 150 151 function addSlideClasses(sliders) { 152 sliders.forEach((slider) => { 153 const list = slider.querySelector('.splide__list'); 154 const children = list.children; 155 156 157 for (let i = 0; i < children.length; i++) { 158 159 if (children[i].classList.contains('brx-nestable-children-placeholder')) { 160 continue; 161 } 162 if (children[i].classList.contains('splide__slide')) { 163 } 164 children[i].classList.add('splide__slide'); 165 } 166 167 if (children.length > 1 && inBuilder) { 168 for (let i = 0; i < children.length; i++) { 169 if (children[i].classList.contains('brx-nestable-children-placeholder')) { 170 children[i].remove(); 171 } 172 } 173 } 174 175 }); 176 } 177 178 function switchIds(sliders) { 179 sliders.forEach((slider) => { 180 const list = slider.querySelector('.splide__list'); 181 const children = list.children; 182 for (let i = 0; i < children.length; i++) { 183 const child = children[i]; 184 // Jira issue: FC-100 185 child.dataset.splideSlide = child.id; 186 if(child.dataset.slideId) { 187 child.id = child.dataset.slideId; 188 } else { 189 child.dataset.slideId = child.dataset.splideSlide; 190 } 191 } 192 }); 193 } 194 195 function manageSlideTabindex(splideInstance) { 196 const originalTabindices = new WeakMap(); 197 const focusableSelector = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), details, [tabindex]:not([tabindex="-1"])'; 198 199 function lockFocus(slide) { 200 slide.querySelectorAll(focusableSelector).forEach((el) => { 201 if (!originalTabindices.has(el)) { 202 originalTabindices.set(el, el.getAttribute('tabindex')); 203 } 204 el.setAttribute('tabindex', '-1'); 205 }); 206 } 207 208 function unlockFocus(slide) { 209 slide.querySelectorAll('[tabindex="-1"]').forEach((el) => { 210 if (!originalTabindices.has(el)) return; 211 const original = originalTabindices.get(el); 212 originalTabindices.delete(el); 213 if (original === null) { 214 el.removeAttribute('tabindex'); 215 } else { 216 el.setAttribute('tabindex', original); 217 } 218 }); 219 } 220 221 splideInstance.on('hidden', ({ slide }) => lockFocus(slide)); 222 splideInstance.on('visible', ({ slide }) => unlockFocus(slide)); 223 splideInstance.on('mounted', () => { 224 splideInstance.Components.Slides.forEach(({ slide }) => { 225 if (slide.getAttribute('aria-hidden') === 'true') lockFocus(slide); 226 }); 227 }); 228 } 229 230 function AutoplayLoopFix(splide) { 231 let patched = false; 232 233 function fix(options) { 234 if (!options.autoplay || options.type !== 'loop') return; 235 236 const realSlides = splide.Components.Slides.filter((s) => !s.isClone); 237 if (realSlides.length > options.perPage) return; 238 239 // In loop mode, movement is always possible via clones. 240 // Splide's canMove() check incorrectly uses real slide count, blocking autoplay. 241 if (!patched) { 242 const Move = splide.Components.Move; 243 if (Move) { 244 Move.canMove = () => true; 245 patched = true; 246 } 247 } 248 249 splide.Components.Autoplay?.play(); 250 } 251 252 return { 253 mount() { 254 splide.on('mounted', () => fix(splide.options)); 255 splide.on('updated', () => fix(splide.options)); 256 }, 257 }; 258 } 259 260 // function initiateSliders 261 function initiateSliders(sliders) { 262 263 const slidersToSync = Array.from(sliders).filter((slider) => { 264 return slider.dataset.frSliderSync === 'true'; 265 }); 266 267 const slidersSingles = Array.from(sliders).filter((slider) => { 268 return slider.dataset.frSliderSync === 'false'; 269 }); 270 271 const slidersToSyncByID = slidersToSync.reduce((acc, slider) => { 272 const id = slider.dataset.frSliderSyncId; 273 if (!acc[id]) { 274 acc[id] = []; 275 } 276 acc[id].push(slider); 277 return acc; 278 }, {}); 279 280 const slidersSync = []; 281
282 Object.keys(slidersToSyncByID).forEach((id) => { 283 const slidersInstance = []; 284 slidersToSyncByID[id].forEach((slider) => { 285 const splideInstance = new Splide(slider); 286 splideInstance.on('mounted', afterSplideMounted); 287 manageSlideTabindex(splideInstance); 288 slidersInstance.push(splideInstance); 289 }); 290 291 292 const sortedSliderInstances = slidersInstance.sort((a, b) => { 293 const aIsNavigation = JSON.parse(a.root.dataset.splide)?.isNavigation ?? false; 294 const bIsNavigation = JSON.parse(b.root.dataset.splide)?.isNavigation ?? false; 295 return aIsNavigation - bIsNavigation; 296 }); 297 298 slidersSync.push({ id, slidersInstance: sortedSliderInstances }); 299 300 }); 301 302 slidersSync.forEach((group) => { 303 group.slidersInstance.forEach((slider, index) => { 304 305 slider.on('move', (newIndex) => { 306 syncOtherSliders(group.slidersInstance, index, newIndex); 307 fixLazyLoadedImages(sliders, false); 308 }); 309 310 311 if (turnAutoScroll(slider.root)) { 312 slider.mount({ ...window.splide.Extensions, AutoplayLoopFix }); 313 } else { 314 slider.mount({ AutoplayLoopFix }); 315 } 316 317 slider.on('moved', () => { 318 updateButtonState(group.id, slider); 319 }); 320 321 updateButtonState(group.id, slider); 322 323 if (index === 0) { 324 customNavButton(group.id, slider, 'next'); 325 customNavButton(group.id, slider, 'prev'); 326 progressBar(group.id, slider); 327 } 328 329 window.bricksData.splideInstances[group.id] = slider; 330 331 }); 332 }); 333 334 slidersSingles.forEach((slider) => { 335 336 const splide = new Splide(slider); 337 splide.on('mounted', afterSplideMounted); 338 splide.on('move', () => fixLazyLoadedImages(sliders, false)); 339 manageSlideTabindex(splide); 340 if (turnAutoScroll(slider)) { 341 splide.mount({ ...window.splide.Extensions, AutoplayLoopFix }); 342 } else { 343 splide.mount({ AutoplayLoopFix }); 344 } 345 346 window.bricksData.splideInstances[slider.id] = splide; 347 }); 348 349 } 350 // end function initiateSliders 351 352 function syncOtherSliders(sliders, sourceIndex, newIndex) { 353 sliders.forEach((otherSlider, otherIndex) => { 354 if (otherIndex !== sourceIndex) { 355 otherSlider.go(newIndex); 356 } 357 }); 358 } 359 360 361 362 // breakout 363 364 function setBreakoutOverflow(sliders) { 365 sliders.forEach((slider) => { 366 const isBreakout = slider.dataset.frSliderBreakout; 367 if (isBreakout === 'false') return; 368 const list = slider.querySelector('.fr-slider__list'); 369 const track = slider.querySelector('.fr-slider__track'); 370 list.style.overflow = 'visible'; 371 track.style.overflow = 'visible'; 372 373 }); 374 } 375 376 // Auto Scroll 377 378 function turnAutoScroll(slider) { 379 const autoScroll = slider.dataset.frSliderAutoScroll; 380 if (autoScroll === 'true') { 381 return true; 382 } 383 return false; 384 } 385 386 // Custom Controls 387 388 function getSliderSyncID(slider) { 389 if (slider.dataset.frSliderSyncId) { 390 return slider.dataset.frSliderSyncId; 391 } else { 392 return null; 393 } 394 } 395 396 function customNavButton(id, slider, direction) { 397 const customNavs = document.querySelectorAll('.fr-slider-custom-navigation'); 398 customNavs.forEach((nav) => { 399 if (nav.dataset.frSliderNavType === 'next' || nav.dataset.frSliderNavType === 'nextPrev' || nav.dataset.frSliderNavType === 'prev') { 400 const syncID = nav.dataset.frSliderNavSyncId; 401 if (syncID === id) { 402 const buttons = nav.querySelectorAll(`.fr-slider__custom-arrow--${direction}`); 403 buttons.forEach((button) => { 404 button.addEventListener('click', function () { 405 const perMove = slider.options.perMove || 1; 406 const command = direction === 'next' ? `+${perMove}` : `-${perMove}`; 407 slider.go(command); 408 updateButtonState(id, slider); // call updateButtonState after the slide change 409 }); 410 }); 411 } 412 } 413 }); 414 } 415 416 417 function updateButtonState(id, slider) { 418 const customNavs = document.querySelectorAll('.fr-slider-custom-navigation'); 419 420 customNavs.forEach((nav) => { 421 if (nav.dataset.frSliderNavType === 'next' || nav.dataset.frSliderNavType === 'nextPrev' || nav.dataset.frSliderNavType === 'prev') { 422 const syncID = nav.dataset.frSliderNavSyncId; 423 if (syncID === id) { 424 const buttons = nav.querySelectorAll('.fr-slider__custom-arrow'); 425 426 // Skip if we don't have any buttons 427 if (!buttons || buttons.length === 0) { 428 return; 429 } 430 431 const type = slider.options.type; 432 const rewind = slider.options.rewind; 433 const getIndex = slider.index; 434 const slidesCount = slider.length; 435 const perPage = slider.options.perPage; 436 437 // Handle next button (which might be at index 1 or 0 depen
437ding on the nav type) 438 const nextButton = nav.querySelector('.fr-slider__custom-arrow--next'); 439 if (nextButton) { 440 if ((getIndex >= slidesCount - perPage) && type !== 'loop' && rewind !== true) { 441 nextButton.setAttribute('disabled', ''); 442 } else { 443 nextButton.removeAttribute('disabled'); 444 } 445 } 446 447 // Handle prev button 448 const prevButton = nav.querySelector('.fr-slider__custom-arrow--prev'); 449 if (prevButton) { 450 if (getIndex === 0 && type !== 'loop' && rewind !== true) { 451 prevButton.setAttribute('disabled', ''); 452 } else { 453 prevButton.removeAttribute('disabled'); 454 } 455 } 456 } 457 } 458 }); 459 } 460 function goToSlide(slider, index) { 461 slider.go(index); 462 } 463 464 function progressBar(id, slider) { 465 466 const customNavs = document.querySelectorAll('.fr-slider-custom-navigation[data-fr-slider-nav-sync-id="' + id + '"]'); 467 customNavs.forEach((nav) => { 468 if (nav.dataset.frSliderNavType === 'progress') { 469 let counter = 0; 470 const bar = nav.querySelector('.fr-slider__progress-bar'); 471 const syncID = nav.dataset.frSliderNavSyncId; 472 if (syncID === id) { 473 474 function updateProgress() { 475 const end = slider.Components.Controller.getEnd() + 1; 476 const rate = Math.min((slider.index + 1) / end, 1); 477 bar.style.width = String(100 * rate) + '%'; 478 } 479 480 updateProgress(); 481 slider.on('mounted move', updateProgress); 482 483 484 } 485 486 const buttonsWrapper = nav.querySelector('.fr-slider__progress-buttons'); 487 const slides = slider.Components.Elements.slides; 488 const labelTemplate = buttonsWrapper.dataset.frSliderProgressButtonLabel || 'Go to slide %s'; 489 490 slides.forEach((slide, index) => { 491 492 const button = document.createElement('button'); 493 button.classList.add('fr-slider__progress-button'); 494 button.setAttribute('type', 'button'); 495 button.setAttribute('data-index', index); 496 // Progress buttons have no visible text, so they need an accessible name. 497 button.setAttribute('aria-label', labelTemplate.replace('%s', String(index + 1))); 498 buttonsWrapper.appendChild(button); 499 }); 500 501 const buttons = buttonsWrapper.querySelectorAll('.fr-slider__progress-button'); 502 buttons.forEach((button) => { 503 button.addEventListener('click', function () { 504 const index = Number(button.dataset.index); 505 506 slider.go(index); 507 }); 508 }); 509 510 } 511 512 }); 513 } 514 515 516 517 function paginationRender(sliders) { 518 519 sliders.forEach((slider) => { 520 const paginationList = slider.querySelectorAll('.fr-slider__pagination'); 521 paginationList.forEach((pagination, index) => { 522 if (index === 0) { 523 return; 524 } 525 pagination.remove(); 526 }); 527 528 }); 529 } 530 531 532 function sliderOptions(slider) { 533 return slider.dataset.splide ? JSON.parse(slider.dataset.splide) : {}; 534 } 535 536 537 function removeExtraPaginationInBuilder(sliders) { 538 539 if (inBuilder) { 540 sliders.forEach((slider) => { 541 const slidesList = slider.querySelector('.splide__list'); 542 const children = slidesList.children.length; 543 const slidesLength = children - 1; 544 const paginationList = slider.querySelectorAll('.splide__pagination'); 545 546 const options = sliderOptions(slider); 547 548 paginationList.forEach((pagination, index) => { 549 if (pagination.children.length > slidesLength) { 550 const children = pagination.querySelectorAll('li'); 551 const childrenLength = children.length; 552 children.forEach((child, index) => { 553 if (index > slidesLength && options.perPage <= 1) { 554 child.remove(); 555 } else if (index > slidesLength / options.perPage && options.perPage > 1) { 556 child.remove(); 557 } 558 559 }); 560 } 561 }); 562 }); 563 } 564 } 565 566 function removeExtraPaginationInBricksFilters(sliders) { 567 if (!isBricksFilters) return; 568 569 sliders.forEach((slider) => { 570 const sliderList = slider.querySelector('.splide__list'); 571 const slidesList = sliderList.querySelectorAll('.splide__slide:not(.splide__slide--clone)'); 572 const slidesLength = slidesList.length; 573 const paginationList = slider.querySelectorAll('.splide__pagination'); 574 575 paginationList.forEach((pagination, index) => { 576 const paginationItems = pagination.querySelectorAll('li'); 577 578 if (paginationItems.length <= slidesLength) return; 579
580 Array.from(paginationItems).forEach((item, index) => { 581 if (index <= slidesLength) return; 582 item.remove(); 583 }); 584 585 const sliderId = slider.id; 586 refreshSliderInstance(sliderId); 587 588 }); 589 }); 590 } 591 592 function refreshSliderInstance(sliderId) { 593 const sliderInstance = window.bricksData.splideInstances[sliderId]; 594 if (!sliderInstance) return; 595 sliderInstance.refresh(); 596 } 597 598} 599 600// document.addEventListener("DOMContentLoaded", slider_script); 601 602function wpgb_slider_script() { 603 604 // check for the presence of WP_GRID_Builder 605 if (window.WP_Grid_Builder) { 606 WP_Grid_Builder.on('init', function (wpgb) { 607 608 // check for wpgb.facets, if no facets dont run the code 609 if (wpgb.facets) { 610 wpgb.facets.on('appended', function (nodes) { 611 612 613 let isFacetSlider = false; 614 615 const sliders = document.querySelectorAll('.fr-slider'); 616 sliders.forEach((slider) => { 617 if (slider.querySelector('.wpgb-enabled')) { 618 isFacetSlider = true; 619 console.log('isFacetSlider', isFacetSlider); 620 } 621 }); 622 623 if (isFacetSlider) { 624 slider_script(); 625 } 626 627 }); 628 629 wpgb.facets.on('change', function () { 630 631 let isFacetSlider = false;
632 633 const sliders = document.querySelectorAll('.fr-slider'); 634 sliders.forEach((slider) => { 635 if (slider.querySelector('.wpgb-enabled')) { 636 isFacetSlider = true; 637 console.log('isFacetSlider', isFacetSlider); 638 } 639 }); 640 641 if (isFacetSlider) { 642 slider_script({ isWpgb: true }); 643 } 644 645 // slider_script({ isWpgb: true }) 646 647 }); 648 } 649 650 }); 651 } 652} 653 654function runSliderScriptsOnBricksFilters() { 655 656 if (typeof window.bricksFilters !== 'function') return; 657 658 659 const bricksFilterRun = bricksFiltersFn.run; 660 bricksFiltersFn.run = function () { 661 662 bricksFilterRun.apply(this, arguments); 663 setTimeout(() => { 664 slider_script({isBricksFilters: true}); 665 }); 666 }; 667} 668 669document.addEventListener('DOMContentLoaded', function (e) { 670 671 bricksIsFrontend && slider_script(); 672 bricksIsFrontend && wpgb_slider_script(); 673 bricksIsFrontend && runSliderScriptsOnBricksFilters(); 674 675}); 676 677
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.