PageSourceSearch

https://www.designeroutletalgarve.com/_assets/6a101b282a6a03d13b1a…/JavaScript/modules/slider.js?1790758556

js designeroutletalgarve.com collected 2026-10-04 12:23:55 UTC 6,587 bytes, 181 lines download raw bytes

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.