1document.addEventListener("DOMContentLoaded", function (event) { 2 3 //Tooltip initialization 4 const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')) 5 const tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) { 6 return new bootstrap.Tooltip(tooltipTriggerEl) 7 }); 8 9 //DistanceCalculation Badge initialization 10 const calcDistanceItems = document.querySelectorAll(".bemDistanceCalculation[data-lon][data-lat]"); 11 calcDistanceItems.forEach(function (calcDistanceItem) { 12 new DistanceCalcluation(calcDistanceItem, ".bemDistanceCalculation--value").init(); 13 }); 14 15 //------------------------------------------------------------- 16 // Helper: Splide erst mounten, wenn sichtbar (fix für display:none) 17 //------------------------------------------------------------- 18 function mountWhenVisible(instance, el) { 19 if (el.offsetWidth > 0) { 20 instance.mount(); 21 return; 22 } 23 const interval = setInterval(() => { 24 if (el.offsetWidth > 0) { 25 clearInterval(interval); 26 instance.mount(); 27 } 28 }, 120); 29 } 30 31 //------------------------------------------------------------- 32 // Splide initialization 33 //------------------------------------------------------------- 34 35 // ID-Fix: Alle Slider mit einer Splide-Auto-ID (z.B. splide01, splide02, ...) 36 // erhalten eine eindeutige ID, um doppelte IDs auf der Seite zu vermeiden. 37 //let bemSliderCounter = 0; 38 //document.querySelectorAll(".splide[id]").forEach(function (el) { 39 // if (/^splide\d+$/.test(el.id)) { 40 // el.id = "bemSlider-" + (++bemSliderCounter); 41 // } 42 //}); 43 44 const splideElements = document.querySelectorAll(".splide:not(.splide--custom)"); 45 46 splideElements.forEach(function (splideElement) { 47 48 const slideCount = splideElement.querySelectorAll(".splide__slide").length; 49 const sliderType = splideElement.getAttribute("data-slider-type") || "loop"; 50 const sliderAutoplay = splideElement.getAttribute("data-slider-autoplay") === "true"; 51 const sliderAutoplayInterval = splideElement.getAttribute("data-slider-autoplayInterval"); 52 const sliderPagination = splideElement.getAttribute("data-slider-pagination") === "true"; 53 const sliderArrowsAttr = splideElement.getAttribute("data-slider-arrows") === "true"; 54 const useProgressbar = splideElement.getAttribute("data-slider-progressbar") === "true"; 55 56 const ORIGINAL_PER_PAGE = parseInt(splideElement.getAttribute("data-slider-perPage")) || 4; 57 const slideGap = splideElement.getAttribute("data-slider-gap") || "1em"; 58 const slideHeight = splideElement.getAttribute("data-slider-height"); 59 60 const sliderBreakpoints = splideElement.getAttribute("data-slider-breakpoints"); 61 const sanitized_sliderBreakpoints = sliderBreakpoints ? sliderBreakpoints.replace(/(['"])?([a-z0-9A-Z_]+)(['"])?:/g, '"$2": ') : ""; 62 63 const splideOptions = { 64 type: sliderType, 65 perPage: ORIGINAL_PER_PAGE, 66 gap: slideGap, 67 autoplay: sliderAutoplay, 68 interval: sliderAutoplayInterval, 69 pauseOnHover: false, 70 pauseOnFocus: false, 71 arrows: useProgressbar ? false : sliderArrowsAttr, 72 pagination: sliderPagination, 73 drag: true, 74 fixedHeight: slideHeight, 75 classes: { 76 pagination: 'bemContentSlider__pagination splide__pagination', 77 page: 'bemContentSlider__pagination__page splide__pagination__page' 78 }, 79 breakpoints: sanitized_sliderBreakpoints ? JSON.parse(sanitized_sliderBreakpoints) : {} 80 }; 81 82 const splide = new Splide(splideElement, splideOptions); 83 let isManuallyPaused = false; 84 let pendingToggle = false; 85 86 function bindAutoplayToggleFallback() { 87 const toggleButton = splide.root.querySelector(".bemContentSlider__toggle"); 88 if (!toggleButton) return; 89 if (toggleButton.dataset.autoplayToggleBound === "true") return; 90 91 toggleButton.dataset.autoplayToggleBound = "true"; 92 93 const syncToggleState = () => { 94 toggleButton.classList.toggle("is-active", !isManuallyPaused); 95 toggleButton.setAttribute("aria-pressed", isManuallyPaused ? "true" : "false"); 96 }; 97 98 const executeToggle = () => { 99 const autoplayComp = splide.Components && splide.Components.Autoplay; 100 101 if (!autoplayComp) { 102 pendingToggle = true; 103 return; 104 } 105 106 if (isManuallyPaused) { 107 autoplayComp.play(); 108 isManuallyPaused = false; 109 } else { 110 autoplayComp.pause(); 111 isManuallyPaused = true; 112 } 113 114 pendingToggle = false; 115 syncToggleState(); 116 }; 117 118 // Verhindert, dass der erste Klick nur den Fokus setzt. 119 toggleButton.addEventListener("pointerdown", function (e) { 120 e.preventDefault(); 121 }); 122 123 toggleButton.addEventListener("click", function (e) { 124 e.preventDefault(); 125 e.stopPropagation(); 126 127 executeToggle(); 128 }); 129 130 syncToggleState(); 131 132 splide.on("mounted", () => { 133 if (pendingToggle) { 134 executeToggle(); 135 } else { 136 syncToggleState(); 137 } 138 }); 139 } 140 141 bindAutoplayToggleFallback(); 142 143 const bar = splide.root.querySelector('.my-carousel-progress-bar'); 144 145 //------------------------------------------------------------- 146 // grouped slider (10er-Sets) 147 //------------------------------------------------------------- 148 const isGroupedSlider = (splideOptions.type === "fade" && useProgressbar); 149 150 if (isGroupedSlider) { 151 152 // Custom Progressbar 153 splide.on('mounted move', () => { 154 const end = splide.Components.Controller.getEnd() + 1; 155 const rate = Math.min((splide.index + 1) / end, 1); 156 if (bar) 157 bar.style.width = `${100 * rate}%`; 158 } 159 ); 160
161 splide.on('mounted', () => { 162 const arrows = splide.root.querySelector('.splide__arrows'); 163 if (arrows) 164 arrows.style.display = 'none'; 165 } 166 ); 167 168 // Custom arrows 169 const nextBtn = splide.root.querySelector(".bemSliderButton--next"); 170 const prevBtn = splide.root.querySelector(".bemSliderButton--prev"); 171 if (nextBtn) { 172 nextBtn.addEventListener('click', () => splide.go('+1')); 173 if (!nextBtn.hasAttribute('aria-label')) 174 nextBtn.setAttribute('aria-label', 'Next'); 175 } 176 if (prevBtn) { 177 prevBtn.addEventListener('click', () => splide.go('-1')); 178 if (!prevBtn.hasAttribute('aria-label')) 179 prevBtn.setAttribute('aria-label', 'Previous'); 180 } 181 182 // Gruppieren 183 const splideList = splideElement.querySelector(".splide__list"); 184 const splideItems = Array.from(splideElement.querySelectorAll(".splide__listItem")); 185 let itemArray = []; 186 187 splideItems.forEach((item, index) => { 188 itemArray.push(item); 189 if (itemArray.length === 10 || index === splideItems.length - 1) { 190 const newSlide = document.createElement("li"); 191 newSlide.classList.add("splide__slide"); 192 const ul = document.createElement("ul"); 193 ul.classList.add("splide__entryList"); 194 itemArray.forEach(entry => ul.appendChild(entry)); 195 newSlide.appendChild(ul); 196 splideList.appendChild(newSlide); 197 itemArray = []; 198 } 199 } 200 ); 201 } 202 203 //------------------------------------------------------------- 204 // Prüfen ob Slideable 205 //------------------------------------------------------------- 206 splide.on("mounted", () => { 207 if (isGroupedSlider) 208 return; 209 210 const arrows = splide.root.querySelector(".splide__arrows"); 211 const totalSlides = slideCount; 212 const perPage = splide.options.perPage; 213 214 if (splide.options.type !== "loop" && totalSlides <= perPage) { 215 splide.options = { 216 arrows: false, 217 drag: false, 218 swipe: false 219 }; 220 if (arrows) 221 arrows.style.display = "none"; 222 } 223 } 224 ); 225 226 //------------------------------------------------------------- 227 // i18n Ãbersetzungen laden â danach mounten 228 //------------------------------------------------------------- 229 const dataURL = "/system/web/getjsontext.ashx?group=pt_splideSlider"; 230 231 function safeMount() { 232 // FIX für display:none container 233 if (splideElement.offsetWidth > 0) { 234 splide.mount(); 235 } else { 236 setTimeout(safeMount, 120); 237 } 238 } 239 240 if (rissprachid != 2) { 241 getJSONData(dataURL, function (dataTextJSON) { 242 243 splide.options = { 244 ...splide.options, 245 i18n: { 246 prev: dataTextJSON["T-304117524"], 247 next: dataTextJSON["T-304117525"], 248 slideX: dataTextJSON["T-304117526"], 249 first: dataTextJSON["T-304117765"], 250 last: dataTextJSON["T-304117766"], 251 play: dataTextJSON["T-304117768"], 252 pause: dataTextJSON["T-304117769"], 253 carousel: dataTextJSON["T-304117770"], 254 select: dataTextJSON["T-304117771"], 255 slide: dataTextJSON["T-304117772"], 256 slideLabel: dataTextJSON["T-304117773"], 257 }, 258 }; 259 260 // i18n aria-labels für Custom-Arrows (grouped
260slider) 261 if (isGroupedSlider) { 262 const nextBtn = splide.root.querySelector(".bemSliderButton--next"); 263 const prevBtn = splide.root.querySelector(".bemSliderButton--prev"); 264 if (nextBtn) nextBtn.setAttribute('aria-label', dataTextJSON["T-304117525"]); 265 if (prevBtn) prevBtn.setAttribute('aria-label', dataTextJSON["T-304117524"]); 266 } 267 268 safeMount(); 269 }); 270 } else { 271 safeMount(); 272 } 273 }); 274 275 function getJSONData(dataURL, callback) { 276 fetch(dataURL).then(response => response.json()).then(data => { 277 dataTextJSON = data; 278 callback(data); 279 } 280 ).catch(error => console.error('Error fetching JSON data:', error)); 281 } 282 283 //isNewEntryModifier 284 const isNewEntryModifier = document.querySelectorAll("[data-isnewentry-timespan]"); 285 isNewEntryModifier.forEach(function (thisEl) { 286 let timespan = thisEl.getAttribute("data-isnewentry-timespan"); 287 let wording = thisEl.getAttribute("data-isnewentry-wording"); 288 let icon = thisEl.getAttribute("data-isnewentry-icon"); 289 290 if (timespan) { 291 let thisValueEl = thisEl.querySelector(".bemText--value"); 292 let thisIconEl = thisEl.querySelector(".bemText--icon"); 293 294 let entryDateStr = (thisValueEl.innerText).split("."); 295 let entryDate = new Date(Date.UTC(entryDateStr[2], entryDateStr[1] - 1, entryDateStr[0])); 296 let todayMinusTimespan = new Date(); 297 todayMinusTimespan.setDate(todayMinusTimespan.getDate() - timespan); 298 299 if (entryDate.getTime() > todayMinusTimespan.getTime()) { 300 thisValueEl.innerText = wording; 301 302 if (icon) { 303 thisIconEl.className = thisIconEl.className.replace(new RegExp(/fa[srlb]\sfa-[\w-]+/), icon); 304 } 305 } 306 } 307 }); 308 309});
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.