1/* global Glide */ 2 3 4document.addEventListener('DOMContentLoaded', function () { 5 6 let classSuffix = 'carrousel-cs'; 7 let selector = `.${classSuffix}`; 8 const carrousels = [...document.querySelectorAll(selector)]; 9 10 let carrouselGlideType = "glide"; 11 let carrouselGridType = "grid"; 12 13 carrousels.forEach(carrousel => { 14 15 let elementMinimalWidth = carrousel.dataset.elementWidth; 16 let carrouselType = carrouselGlideType; 17 let elementChildNodes = [...carrousel.childNodes].filter(child => { 18 if (child.nodeType === Node.ELEMENT_NODE) { 19 return child; 20 } 21 }); 22 let childrenCount = elementChildNodes.length; 23 let elementsMin = carrousel.dataset.elementsMin; 24 let isGallery = false; // more than one element is visible 25 if (elementMinimalWidth !== undefined) { 26 if (childrenCount < elementsMin) { 27 carrouselType = carrouselGridType; 28 } 29 } else { 30 isGallery = true; 31 } 32 carrousel.classList.add(`carrousel-${carrouselType}-cs`); 33 switch (carrouselType) { 34 case carrouselGridType: 35 // we can't set the height of the container to have same height component 36 // because this is a grid and in small mobile screen, the height would be double 37 carrousel.classList.add("row", "row-cols-1", `row-cols-sm-${elementsMin}`, "justify-content-center"); 38 elementChildNodes.forEach(element => { 39 let gridColContainer = document.createElement("div"); 40 gridColContainer.classList.add("col"); 41 gridColContainer.appendChild(element); 42 carrousel.appendChild(gridColContainer); 43 }); 44 break; 45 case carrouselGlideType: 46 47 /** 48 * Slides structure 49 */ 50 carrousel.classList.add("glide", "glide--ltr", "glide--carousel", "glide--swipeable"); 51 let glideTrackContainer = document.createElement("div"); 52 glideTrackContainer.classList.add("glide__track"); 53 glideTrackContainer.dataset.glideEl = "track"; 54 carrousel.appendChild(glideTrackContainer); 55 let glideSlidesContainer = document.createElement("div"); 56 glideSlidesContainer.classList.add("glide__slides"); 57 glideTrackContainer.appendChild(glideSlidesContainer); 58 elementChildNodes.forEach(element => { 59 glideSlidesContainer.appendChild(element); 60 element.classList.add("glide__slide"); 61 if (element.localName === "a") { 62 // to center the image inside the link 63 element.classList.add("justify-content-center", "align-items-center", "d-flex"); 64 } 65 }); 66 67 /** 68 * Control structure 69 */ 70 let control = carrousel.dataset.control; 71 if (control !== "none") { 72 // move per view |< and |> 73 // https://github.com/glidejs/glide/issues/346#issuecomment-1046137773 74 let controlArrowContainer = document.createElement("div"); 75 controlArrowContainer.dataset.glideEl = "controls"; 76 if (!isGallery) { 77 controlArrowContainer.classList.add("d-none", "d-sm-block"); 78 } 79 carrousel.insertAdjacentElement('beforeend', controlArrowContainer); 80 let controlArrows = ` 81<button class="glide__arrow glide__arrow--left" data-glide-dir="|<"> 82 <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24"><path d="M0 12l10.975 11 2.848-2.828-6.176-6.176H24v-3.992H7.646l6.176-6.176L10.975 1 0 12z"></path></svg> 83</button> 84<button class="glide__arrow glide__arrow--right" data-glide-dir="|>"> 85 <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24"><path d="M13.025 1l-2.847 2.828 6.176 6.176h-16.354v3.992h16.354l-6.176 6.176 2.847 2.828 10.975-11z"></path></svg> 86</button> 87`; 88 controlArrowContainer.insertAdjacentHTML('beforeend', controlArrows); 89 90 91 let controlBulletContainer = document.createElement("div"); 92 carrousel.insertAdjacentElement('beforeend', controlBulletContainer); 93 controlBulletContainer.classList.add("glide__bullets", "d-none", "d-sm-block"); 94 controlBulletContainer.dataset.glideEl = "controls[nav]"; 95 for (let i = 0; i < childrenCount; i++) { 96 let controlBullet = document.createElement("button"); 97 controlBullet.classList.add("glide__bullet"); 98 controlBullet.dataset.glideDir = `=${i}`; 99 if (i === 0) { 100 controlBullet.classList.add("glide__bullet--activeClass"); 101 } 102 controlBulletContainer.appendChild(controlBullet); 103 } 104 } 105 106 107 let callGlide = function () { 108 109 let perView = 1; 110 if (typeof elementMinimalWidth !== 'undefined') { 111 let offsetWidth = carrousel.offsetWidth; 112 perView = Math.floor(offsetWidth / elementMinimalWidth); 113 perView += 0.5; // mobile to show that there is further element on the right side 114 } 115 116 /** 117 * https://www.jsdelivr.com/package/npm/@glidejs/glide 118 * Dev: 119 * "https://cdn.jsdelivr.net/npm/@glidejs/glide@3.5.2/dist/glide.js", 120 * "sha256-zkYoJ1XwwGA4FbdmSdTz28y5PtHT8O/ZKzUAuQsmhKg=" 121 */ 122 combos.loader.loadExternalScript( 123 "https://cdn.jsdelivr.net/npm/@glidejs/glide@3.5.2/dist/glide.min.js", 124 "sha256-cXguqBvlUaDoW4nGjs4YamNC2mlLGJUOl64bhts/ztU=", 125 `snippet-${classSuffix}`, 126 function(){ 127 combos.loader.loadExternalStylesheet( 128 "https://cdn.jsdelivr.net/npm/@glidejs/glide@3.5.2/dist/css/glide.core.min.css", 129 "sha256-bmdlmBAVo1Q6XV2cHiyaBuBfe9KgYQhCrfQmoRq8+Sg=", 130 `snippet-${classSuffix}`, 131 function(){ 132 133 let glide = new Glide(carrousel, { 134 type: 'carousel', 135 perView: perView 136 }); 137 glide.mount(); 138 139 /** 140 * To be able to set percentage height value on the child elements. 141 */ 142 glideSlidesContainer.style.height = `${glideSlidesContainer.offsetHeight}px`; 143 144 } 145 ); 146 147 } 148 ); 149 150 }; 151 152 if(navigator.userAgent.includes("Node.js") || navigator.userAgent.includes("jsdom")){ 153 /** 154 * In test, in jsdom, no request animation frame 155 */ 156 callGlide() 157 } else { 158 /** 159 * To be sure that the first layout calculation has occurred 160 */ 161 window.requestAnimationFrame(callGlide); 162 } 163 break; 164 } 165 166 }); 167 168}); 169