frontblocks-advanced-option.js
1 week ago
frontblocks-advanced-option.jsx
1 week ago
frontblocks-carousel-editor.css
4 months ago
frontblocks-carousel.css
1 week ago
frontblocks-carousel.js
1 week ago
glide.min.js
8 months ago
frontblocks-carousel.js
173 lines
| 1 | window.addEventListener('load', function (event) { |
| 2 | const carouselItem = document.querySelectorAll('.frontblocks-carousel'); |
| 3 | |
| 4 | if (carouselItem.length > 0) { |
| 5 | carouselItem.forEach((item) => { |
| 6 | // Check if carousel should be disabled on desktop. |
| 7 | const disableOnDesktop = item.getAttribute('data-disable-on-desktop') === 'true'; |
| 8 | const isDesktop = window.innerWidth >= 768; |
| 9 | |
| 10 | // Skip initialization if disabled on desktop and current viewport is desktop. |
| 11 | if (disableOnDesktop && isDesktop) { |
| 12 | return; |
| 13 | } |
| 14 | |
| 15 | // First Parent. |
| 16 | const parent = item.parentNode; |
| 17 | const wrapper = document.createElement('div'); |
| 18 | |
| 19 | parent.replaceChild(wrapper, item); |
| 20 | wrapper.appendChild(item); |
| 21 | |
| 22 | wrapper.classList.add('glide__track'); |
| 23 | wrapper.setAttribute('data-glide-el', 'track'); |
| 24 | |
| 25 | // Second Parent. |
| 26 | const parentwrap = wrapper.parentNode; |
| 27 | const wrapperParent = document.createElement('div'); |
| 28 | |
| 29 | parentwrap.replaceChild(wrapperParent, wrapper); |
| 30 | wrapperParent.appendChild(wrapper); |
| 31 | wrapperParent.classList.add('frontblocks', 'glide'); |
| 32 | |
| 33 | // Options |
| 34 | const carouselType = item.getAttribute('data-type') ? item.getAttribute('data-type') : 'carousel'; |
| 35 | const carouselbuttons = item.getAttribute('data-buttons') ? item.getAttribute('data-buttons') : 'bullets'; |
| 36 | const carouselView = item.getAttribute('data-view') ? parseInt(item.getAttribute('data-view')) : 4; |
| 37 | const carouselLaptopView = item.getAttribute('data-laptop-view') ? parseInt(item.getAttribute('data-laptop-view')) : 3; |
| 38 | const carouselTabletView = item.getAttribute('data-tablet-view') ? parseInt(item.getAttribute('data-tablet-view')) : 2; |
| 39 | const carouselMobileView = item.getAttribute('data-mobile-view') ? parseInt(item.getAttribute('data-mobile-view')) : 1; |
| 40 | const autoplayAttr = item.getAttribute('data-autoplay'); |
| 41 | const carouselAutoplay = (autoplayAttr !== '' && autoplayAttr !== null && autoplayAttr !== undefined) ? parseInt(autoplayAttr, 10) : 0; |
| 42 | const carouselGap = item.getAttribute('data-gap') ? parseInt(item.getAttribute('data-gap'), 10) : 20; |
| 43 | const carouselRewind = item.getAttribute('data-rewind') ? item.getAttribute('data-rewind') : false; |
| 44 | const carouselbuttonsColor = item.getAttribute('data-buttons-color') ? item.getAttribute('data-buttons-color') : 'black'; |
| 45 | const carouselbuttonsBackgroundColor = item.getAttribute('data-buttons-background-color') ? item.getAttribute('data-buttons-background-color') : 'transparent'; |
| 46 | const carouselbuttonsPosition = item.getAttribute('data-buttons-position') ? item.getAttribute('data-buttons-position') : 'side'; |
| 47 | const carouselArrowLeftUrl = item.getAttribute('data-arrow-left-url') || ''; |
| 48 | const carouselArrowRightUrl = item.getAttribute('data-arrow-right-url') || ''; |
| 49 | |
| 50 | |
| 51 | // Add classes |
| 52 | item.classList.add('glide__slides', 'glide-' + Math.floor(Math.random() * 1000)); |
| 53 | // Force flex layout via inline style to beat WP grid CSS (columns-N, is-layout-grid). |
| 54 | if (item.classList.contains('wp-block-post-template')) { |
| 55 | item.style.setProperty('display', 'flex', 'important'); |
| 56 | item.style.setProperty('flex-wrap', 'nowrap', 'important'); |
| 57 | item.style.setProperty('max-width', 'none', 'important'); |
| 58 | item.style.setProperty('grid-template-columns', 'none', 'important'); |
| 59 | item.style.setProperty('list-style', 'none', 'important'); |
| 60 | item.style.setProperty('padding-left', '0', 'important'); |
| 61 | item.style.setProperty('margin-left', '0', 'important'); |
| 62 | } |
| 63 | for (const child of item.children) { |
| 64 | child.classList.add('glide__slide'); |
| 65 | } |
| 66 | |
| 67 | // Don't show bullets on responsive and more than 10 items. |
| 68 | let showBullets = false; |
| 69 | if (window.screen.availWidth < 768 && item.children.length <= 10) { |
| 70 | showBullets = true; |
| 71 | } else if (window.screen.availWidth > 768) { |
| 72 | showBullets = true; |
| 73 | } |
| 74 | |
| 75 | if (showBullets && carouselbuttons == 'bullets') { |
| 76 | const bullets = document.createElement('div'); |
| 77 | bullets.classList.add('glide__bullets'); |
| 78 | bullets.setAttribute('data-glide-el', 'controls[nav]'); |
| 79 | bullets.setAttribute('role', 'group'); |
| 80 | bullets.setAttribute('aria-label', 'Slide navigation'); |
| 81 | |
| 82 | for (let i = 0; i < item.children.length; i++) { |
| 83 | const bullet = document.createElement('button'); |
| 84 | bullet.classList.add('glide__bullet'); |
| 85 | bullet.setAttribute('data-glide-dir', '=' + i); |
| 86 | bullet.setAttribute('aria-label', 'Go to slide ' + (i + 1)); |
| 87 | bullets.appendChild(bullet); |
| 88 | } |
| 89 | |
| 90 | wrapperParent.appendChild(bullets); |
| 91 | |
| 92 | // Set bullet colors via CSS custom properties on the wrapper. |
| 93 | // This avoids specificity conflicts with the stylesheet. |
| 94 | if (carouselbuttonsColor) { |
| 95 | wrapperParent.style.setProperty('--frbl-bullet-color', carouselbuttonsColor); |
| 96 | } |
| 97 | if (carouselbuttonsBackgroundColor && carouselbuttonsBackgroundColor !== 'transparent') { |
| 98 | wrapperParent.style.setProperty('--frbl-bullet-bg', carouselbuttonsBackgroundColor); |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | if (carouselbuttons == 'arrows') { |
| 103 | const arrows = document.createElement('div'); |
| 104 | arrows.classList.add('glide__arrows'); |
| 105 | |
| 106 | const positionClassMap = { |
| 107 | 'side': 'glide__arrows--side', |
| 108 | 'bottom': 'glide__arrows--bottom-left', |
| 109 | 'bottom-left': 'glide__arrows--bottom-left', |
| 110 | 'bottom-right': 'glide__arrows--bottom-right', |
| 111 | 'top-left': 'glide__arrows--top-left', |
| 112 | 'top-right': 'glide__arrows--top-right', |
| 113 | }; |
| 114 | arrows.classList.add(positionClassMap[carouselbuttonsPosition] || 'glide__arrows--side'); |
| 115 | |
| 116 | arrows.setAttribute('data-glide-el', 'controls'); |
| 117 | |
| 118 | const defaultLeftSvg = '<svg width="7" height="12" viewBox="0 0 7 12" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M6 1L1 6L6 11" stroke="' + carouselbuttonsColor + '" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>'; |
| 119 | const defaultRightSvg = '<svg width="7" height="12" viewBox="0 0 7 12" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1 11L6 6L1 1" stroke="' + carouselbuttonsColor + '" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>'; |
| 120 | const leftSvg = carouselArrowLeftUrl ? '<img src="' + carouselArrowLeftUrl + '" alt="" aria-hidden="true">' : defaultLeftSvg; |
| 121 | const rightSvg = carouselArrowRightUrl ? '<img src="' + carouselArrowRightUrl + '" alt="" aria-hidden="true">' : defaultRightSvg; |
| 122 | |
| 123 | arrowsHTML = '<button class="glide__arrow glide__arrow--left" data-glide-dir="<"'; |
| 124 | arrowsHTML += ' aria-label="Previous slide"'; |
| 125 | arrowsHTML += ' style="background-color: ' + carouselbuttonsBackgroundColor + '"'; |
| 126 | arrowsHTML += '>' + leftSvg + '</button>'; |
| 127 | arrowsHTML += '<button class="glide__arrow glide__arrow--right" data-glide-dir=">"'; |
| 128 | arrowsHTML += ' aria-label="Next slide"'; |
| 129 | arrowsHTML += ' style="background-color: ' + carouselbuttonsBackgroundColor + '"'; |
| 130 | arrowsHTML += '>' + rightSvg + '</button>'; |
| 131 | arrows.innerHTML = arrowsHTML; |
| 132 | wrapperParent.appendChild(arrows); |
| 133 | } |
| 134 | const glideFrontBlocks = new Glide(wrapperParent, { |
| 135 | type: carouselType, |
| 136 | perView: carouselView, |
| 137 | startAt: 0, |
| 138 | autoplay: carouselAutoplay > 0 ? carouselAutoplay : false, |
| 139 | gap: isNaN(carouselGap) ? 20 : carouselGap, |
| 140 | rewind: carouselRewind, |
| 141 | breakpoints: { |
| 142 | 768: { |
| 143 | perView: carouselMobileView |
| 144 | }, |
| 145 | 1024: { |
| 146 | perView: carouselTabletView |
| 147 | }, |
| 148 | 1440: { |
| 149 | perView: carouselLaptopView |
| 150 | } |
| 151 | } |
| 152 | }); |
| 153 | |
| 154 | if ('slider' === carouselType) { |
| 155 | glideFrontBlocks.on('run.after', () => { |
| 156 | const currentIndex = glideFrontBlocks.index; |
| 157 | const lastIndex = glideFrontBlocks.selector.querySelectorAll('.glide__slide').length; |
| 158 | |
| 159 | actualView = parseInt(currentIndex) + parseInt(carouselView); |
| 160 | |
| 161 | if (actualView > lastIndex) { |
| 162 | setTimeout(() => { |
| 163 | glideFrontBlocks.go('=0'); |
| 164 | }, 5); |
| 165 | } |
| 166 | }); |
| 167 | } |
| 168 | |
| 169 | glideFrontBlocks.mount(); |
| 170 | }); |
| 171 | } |
| 172 | }); |
| 173 |