PageSourceSearch

https://www.bne-online.de/wp-content/plugins/frames-plugin/classes/Widgets/slider/js/slider.js?ver=1786206062

js bne-online.de collected 2026-09-24 22:18:49 UTC 18,476 bytes, 677 lines download raw bytes

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.