1(function ($) { 2 window.SR_ROS_SLIDER = { 3 4 initOnDOMReady: function (rawRoot) { 5 var root = (typeof SR_ROS !== 'undefined') ? SR_ROS.getRootItem(rawRoot) : $(rawRoot || document); 6 7 var $complexSliders = root.find('.slider--slots, .slider--ticker, .slider--brands, .slider--instafeed'); 8 if ($complexSliders.length) { 9 this.initComplexSlider($complexSliders); 10 } 11 12 if (root.find('.slider--media').length) { 13 this.initMediaSlider(root); 14 } 15 }, 16 17 initComplexSlider: function ($elements) { 18 var _this = this; 19 $elements.each(function () { 20 var $el = $(this), 21 $wrapper = $el.find('.slider__wrapper'), 22 isTicker = $el.attr('data-tickermode') === 'true', 23 isBrands = $el.hasClass('slider--brands'); 24 25 if ($el.data('swiper-initialized') || $wrapper.find('li').length === 0) return; 26 27 // Swiper DOM Struktur aufbauen 28 $wrapper.addClass('swiper-wrapper').children('li').addClass('swiper-slide'); 29 $wrapper.wrap('<div class="swiper"></div>'); 30 31 // FOCUS-SENTINEL: Ein unsichtbarer Anker nach dem Slider 32 // Er dient als "Ausgang" für den Tabulator 33 if (!$el.find('.swiper-focus-sentinel').length) { 34 $el.append('<div class="swiper-focus-sentinel" tabindex="0" style="position:absolute; width:1px; height:1px; opacity:0; pointer-events:none;"></div>'); 35 } 36 37 var rawSpeed = parseInt($el.attr('data-tickerspeed')) || 5000; 38 var calculatedSpeed = isTicker ? (rawSpeed / 10) : 400; 39 40 var config = { 41 speed: calculatedSpeed, 42 loop: isTicker, 43 autoplay: isTicker ? { 44 delay: 0, 45 disableOnInteraction: false, 46 pauseOnMouseEnter: true 47 } : false, 48 slidesPerView: isBrands ? 2.5 : 1.6, 49 spaceBetween: isBrands ? 8 : 16, 50 watchOverflow: true, 51 grabCursor: true, 52 freeMode: isTicker ? { 53 enabled: true, 54 momentum: false, 55 sticky: false 56 } : false, 57
58 // Wir schalten Swipers eigene A11y-Fokus-Logik weitgehend aus, 59 // um dem Browser das Feld zu überlassen 60 a11y: { 61 enabled: true, 62 limitTabKeyNavigation: true, 63 }, 64 65 navigation: { 66 nextEl: $el.parent().find('.swiper-next')[0], 67 prevEl: $el.parent().find('.swiper-prev')[0], 68 }, 69 70 breakpoints: { 71 480: { slidesPerView: parseInt($el.attr('data-s--slots')) || (isBrands ? 3 : 2), spaceBetween: 16 }, 72 768: { slidesPerView: parseInt($el.attr('data-m--slots')) || (isBrands ? 4 : 3), spaceBetween: 16 }, 73 1024: { slidesPerView: parseInt($el.attr('data-l--slots')) || (isBrands ? 5 : 4), spaceBetween: 24 }, 74 1280: { slidesPerView: parseInt($el.attr('data-xl--slots')) || (isBrands ? 6 : 5), spaceBetween: 24 } 75 }, 76 77 on: { 78 init: function () { 79 $el.data('swiper-initialized', true); 80 }, 81 } 82 }; 83 84 var swiper = new Swiper($el.find('.swiper')[0], config); 85 $el.data('sliderobj', swiper); 86 87 // Native focus management for ticker mode to prevent loop-tabbing 88 if (isTicker) { 89 $el.on('focusin', function () { 90 var swiperObj = $el.data('sliderobj'); 91 if (swiperObj && swiperObj.params.loop) { 92 swiperObj.autoplay.stop(); 93 swiperObj.setTransition(0); 94 95 swiperObj.params.loop = false; 96 if (typeof swiperObj.loopDestroy === 'function') { 97 swiperObj.loopDestroy(); 98 } 99 swiperObj.update(); 100 // Jump to the first real slide if we were on a clone 101 swiperObj.slideTo(0, 0); 102 } 103 }); 104 105 $el.on('focusout', function (e) { 106 // Check if focus actually left the slider 107 setTimeout(function() { 108 if (!$el[0].contains(document.activeElement)) { 109 var swiperObj = $el.data('sliderobj'); 110 if (swiperObj && !swiperObj.params.loop && $el.attr('data-tickermode') === 'true') { 111 swiperObj.params.loop = true; 112 if (typeof swiperObj.loopCreate === 'function') { 113 swiperObj.loopCreate(); 114 } 115 swiperObj.update(); 116 swiperObj.autoplay.start(); 117 } 118 } 119 }, 10); 120 }); 121 } 122 123 // SENTINEL EVENT: Wenn der Tabulator den Sentinel erreicht, 124 // erzwingen wir den Fokus auf das nächste Element AUSSERHALB des Sliders 125 $el.find('.swiper-focus-sentinel').on('focus', function(e) { 126 var focusableElements = 'a, button, input, textarea, select, details, [tabindex]:not([tabindex="-1"])'; 127 var allFocusable = $(focusableElements).filter(':visible'); 128 var index = allFocusable.index(this); 129 if (index > -1 && index < allFocusable.length - 1) { 130 allFocusable.eq(index + 1).focus(); 131 } 132 }); 133 }); 134 }, 135 136 initMediaSlider: function (root) { 137 var _this = this; 138 root.find('.slider--media').each(function () { 139 var $container = $(this), 140 $wrapper = $container.find('.slider__wrapper'); 141 142 if ($container.data('swiper-initialized') || $wrapper.find('li').length <= 1) return; 143 144 $wrapper.addClass('swiper-wrapper').children('li').addClass('swiper-slide'); 145 $wrapper.wrap('<div class="swiper"></div>'); 146 147 var swiper = new Swiper($container.find('.swiper')[0], { 148 speed: 400, 149 loop: false, 150 navigation: { 151 nextEl: $container.parent().find('.swiper-next')[0], 152 prevEl: $container.parent().find('.swiper-prev')[0], 153 }, 154 on: { 155 init: function () { 156 $container.data('swiper-initialized', true); 157 _this.handleMediaOffset($container); 158 } 159 } 160 }); 161 }); 162 }, 163 164 handleMediaOffset: function ($container) { 165 var $img = $container.find('.swiper-slide-active img'); 166 if ($img.length) { 167 var offset = ($container.find('figure').height() - $img.height()) / 2;
168 $container.find('.swiper-controls').css('margin-top', -offset + 'px'); 169 } 170 } 171 }; 172 173 $(function () { 174 SR_ROS_SLIDER.initOnDOMReady(); 175 }); 176 177 $(document).on('mms:contentupdate', function (event) { 178 SR_ROS_SLIDER.initOnDOMReady(event.target); 179 }); 180 181})(jQuery);
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.