PageSourceSearch

https://www.stanleyworks.pl/modules/custom/sbd_carousel/js/carousel-init.js?tm46jx

js stanleyworks.pl collected 2026-09-30 09:26:24 UTC 18,488 bytes, 425 lines download raw bytes

1(function($, Drupal, drupalSettings) {
2
3  'use strict';
4
5  Drupal.behaviors.sbdCarousel = {
6    attach: function(context, drupalSettings) {
7
8      function updateCurrentSlides($page_indicator, num) {
9        $page_indicator.find('.current').text(num);
10      }
11
12      $('.sbd-carousel-component', context).once('sbd-carousel-init').each(function () {
13        var $this = $(this);
14        var $page_indicator =  $this.find('.sbd-carousel-page-indicator');
15        var $sbd_carousel =  $this.find('.sbd-carousel');
16        var $sbd_slider =  $this.find('.sbd-slider');
17        var $sbd_pdpSlider = $this.find('#product-slider');
18        var $sbd_pdpThumbnailSlider =  $this.find('#thumbnail-slider');
19        var $sbd_pdpThumbnailSliderMobile =  $this.find('#thumbnail-slider-mobile');
20        // Override variable for CoreMDS2024.
21        if (drupalSettings.isCoreMds2024) {
22          var $sbd_pdpSlider = null;
23          var $sbd_pdpThumbnailSlider = null;
24          var $sbd_pdpThumbnailSliderMobile = null;
25          var $sbd_pdpSlider = $this.find('.slider-main #block-duplo-pdp-slider');
26          var $sbd_pdpThumbnailSlider = $this.find('.thumbnail-slider-desktop #block-duplo-pdp-slider-thumbnail');
27          var $sbd_pdpThumbnailSliderMobile = $this.find('.thumbnail-slider-mobile #block-duplo-pdp-slider');
28        }
29        var numSlides = $sbd_carousel.data('slides-to-show');
30        var numSliderSlides = $sbd_slider.data('slides-to-show');
31        var currentSlides = 0;
32        var $progressBar = $this.find('.progress');
33        var $progressBarLabel = $this.find( '.slider__label' );
34
35        // Sets PDP slider sync, the asNavFor feature is deprecated in Accessible Slick
36        // so we're replicating the behavior here
37        function setSlides(e, slider) {
38          $(slider.$slides.find('.thumbnail-image').first()).each(function(index) {
39            $(this).attr('aria-current', true);
40          });
41
42          $(slider.$slides.find('.thumbnail-image')).each(function(index) {
43            $(this).on('click', function() {
44              // Move aria-current="true" to this button
45              $(slider.$slides.find('.thumbnail-image').removeAttr('aria-current'));
46              $(this).attr('aria-current', true);
47
48              // Change the main image to match this thumbnail button
49              var index = $(this).closest('.slick-slide').data('slick-index');
50              $('#product-slider').slick('slickGoTo', index);
51              if(drupalSettings.isCoreMds2024) {
52                $('.slider-main #block-duplo-pdp-slider').slick('slickGoTo', index);
53              }
54            });
55          });
56
57          if (drupalSettings.isCoreMds2024 && slider.$slides.length > 8) {
58            var viewLessSelector = $('#block-duplo-pdp-slider-thumbnail .view-less');
59            var viewMoreSelector = $('#block-duplo-pdp-slider-thumbnail .view-more-wrapper');
60            var thumbnailSliderDesktop = $('.thumbnail-slider-desktop');
61
62            if (slider.$slider.is('#block-duplo-pdp-slider-thumbnail')) {
63              var thumbnailSlides = $('.slick-slide', thumbnailSliderDesktop).slice(8);
64              thumbnailSlides.hide();
65
66              viewMoreSelector.on('click', function() {
67                $(this).hide();
68                thumbnailSlides.show();
69                viewLessSelector.show();
70              });
71
72              viewLessSelector.on('click', function() {
73                $(this).hide();
74                viewMoreSelector.show();
75                thumbnailSlides.hide();
76              });
77            }
78          }
79        };
80
81        // Change the main image whenever a thumbnail button is activated
82        $sbd_pdpThumbnailSlider.on('init', setSlides);
83        // Change the main image whenever a thumbnail button is activated
84        $sbd_pdpThumbnailSliderMobile.on('init', setSlides);
85
86        // Initialize Slick carousel
87        $sbd_carousel.on('init', function(event, slick) {
88          // Dynamically calculate current slides per carousel
89          currentSlides = slick.$slides.filter('.slick-active').length;
90          $page_indicator.find('.total').text(slick.slideCount);  // Update total slide count
91          updateCurrentSlides($page_indicator, currentSlides);      // Update the current slide number
92        });
93
94        $sbd_carousel.on('afterChange', function(event, slick, currentSlide) {
95          // Calculate the current slide based on slick's internal state
96          currentSlides = currentSlide + slick.$slides.filter('.slick-active').length;
97          updateCurrentSlides($page_indicator, currentSlides);
98
99          var $firstCarouselItem = $(this).find(".slick-active").first().find("a").first();
100          if ($firstCarouselItem.length) {
101              $firstCarouselItem.trigger("focus");
102          }
103        });
104
105        // Progress bar for SBD carousel in core_2_0
106        $sbd_carousel.on('beforeChange', function(event, slick, currentSlide, nextSlide) {
107          Drupal.behaviors.sbdCarousel.sliderProgressCal(slick, nextSlide, $progressBar, $progressBarLabel);
108        });
109
110        $sbd_carousel.on('init', function(event, slick) {
111          Drupal.behaviors.sbdCarousel.sliderProgressCal(slick, 0, $progressBar, $progressBarLabel);
112        });
113
114        // SBD Carousel is used to render product tiles and other product carousels in various pages
115        $sbd_carousel.slick({
116          autoplay: false,
117          infinite: false,
118          slidesToShow: numSlides,
119          slidesToScroll: 1,
120          rtl: ($('html').attr('dir') === 'rtl' || $this.hasClass('rtl-test')),
121          prevArrow: ($this.find('.slick-prev')),
122          nextArrow: ($this.find('.slick-next')),
123          responsive: [
124            {
125              breakpoint: 1280,
126              settings: {
127                slidesToShow: numSlides === 1 ? 1 : 3
128              }
129            },
130            {
131              breakpoint: 1024,
132              settings: {
133                slidesToShow: numSlides === 1 ? 1 : 2
134              }
135            },
136            {
137              breakpoint: 728,
138              settings: {
139                slidesToShow: 1
140              }
141            }
142          ]
143        });
144
145        // Keydown event for handling keyboard navigation (Enter/Space for prev/next)
146        $(document).on("keydown", ".slick-prev, .slick-next", function (e) {
147          if (e.key === "Enter" || e.key === "Space") {
148              e.preventDefault(); 
149
150              var $carouselWrapper = $(this).closest(".sbd-carousel-page-indicator").siblings(".sbd-carousel").first();
151              
152              // Determine the direction (previous or next)
153              if ($(this).hasClass("slick-prev")) {
154                  $carouselWrapper.slick("slickPrev");
155              } else if ($(this).hasClass("slick-next")) {
156                  $carouselWrapper.slick("slickNext");
157              }
158          }
159        });
160        
161        // SBD Slider is used in hero slider sections
162        $sbd_slider.slick({
163          infinite: true,
164          dots: true,
165          speed: 800,
166          slidesToShow: numSliderSlides,
167          slidesToScroll: 1,
168          rtl: ($('html').attr('dir') === 'rtl' || $this.hasClass('rtl-test')),
169          pauseOnDotsHover: true,
170          pauseOnHover: true,
171          swipe: true,
172          touchMove: true,
173          autoplay: false,
174          slidesToScroll: 1,
175          useTransform: false,
176          regionLabel: 'Hero Slider',
177          responsive: [
178            {
179              breakpoint: 1280,
180              settings: {
181                slidesToShow: numSliderSlides === 1 ? 1 : 3
182              }
183            },
184            {
185              breakpoint: 1024,
186              settings: {
187                slidesToShow: numSliderSlides === 1 ? 1 : 2
188              }
189            },
190            {
191              breakpoint: 728,
192              settings: {
193                slidesToShow: 1
194              }
195            }
196          ]
197        });
198
199        // SBD PDP Slider is used in PDP pages to render product images in a gallery
200        $sbd_pdpSlider.slick({
201          regionLabel: 'Product Carousel',
202          touchMove: true,
203          infinite: true,
204          slidesToShow: 1,
205          slidesToScroll: 1,
206          autoplay: false,
207          draggable:true,
208          swipe:true,
209          fade:false,
210          speed:300,
211          cssEase:"ease",
212          pauseOnHover:false,
213          arrows:true,
214          rows: 0,
215          useTransform: true,
216          matchHeights: {"target":"slide"},
217          rtl: ($('html').attr('dir') === 'rtl' || $this.hasClass('rtl-test')),
218          prevArrow:"<button aria-label=\"Previous\" type=\"button\" class=\"slick-prev\"></button>",
219          nextArrow:"<button aria-label=\"Next\" type=\"button\" class=\"slick-next\"></button>",
220          responsive: [
221            {
222              breakpoint: 728,
223              settings: {
224                arrows: false,
225                dots: true,
226                appendDots: drupalSettings.isCoreMds2024 ? ".slider-main #block-duplo-pdp-slider" : ".pdp-product-slider",
227              }
228            }
229          ]
230        });
231
232        // SBD PDP Thumbnail Slider controls the navigation on PDP slider
233        $sbd_pdpThumbnailSlider.slick({
234          rows: 0,
235          regionLabel: 'Product Thumbnail Carousel',
236          slidesToShow: 99,
237          slidesToScroll: 99,
238          cssEase: "ease",
239          draggable: false,
240          rtl: ($('html').attr('dir') === 'rtl' || $this.hasClass('rtl-test')),
241        });
242
243        // SBD PDP Thumbnail Slider controls the navigation on PDP slider
244        $sbd_pdpThumbnailSliderMobile.slick({
245          rows: 0,
246          regionLabel: 'Product Thumbnail Mobile Carousel',
247          slidesToShow: drupalSettings.isCoreMds2024 ? 4.3 : 3,
248          slidesToScroll: 1,
249          draggable:true,
250          swipe: true,
251          speed:300,
252          cssEase: "ease",
253          infinite: false,
254          rtl: ($('html').attr('dir') === 'rtl' || $this.hasClass('rtl-test')),
255        });
256
257        updateCurrentSlides($page_indicator, currentSlides);
258
259        // Update the thumbnail slider when the user changes the main slider directly.
260        $('#product-slider, .slider-main #block-duplo-pdp-slider').on('beforeChange', function(e, slider, currentSlide, nextSlide) {
261          // Remove aria-current from the last selected thumbnail image button
262          $('#thumbnail-slider .thumbnail-image[aria-current="true"]').removeAttr('aria-current');
263          $('#thumbnail-slider-mobile .thumbnail-image[aria-current="true"]').removeAttr('aria-current');
264
265          // Select the thumbnail image button that goes with this main image. Most importantly, this updates Slick's internal state to be consistent with the visual change.
266          $('#thumbnail-slider').slick('slickGoTo', nextSlide);
267          $('#thumbnail-slider-mobile').slick('slickGoTo', nextSlide);
268
269          // Add aria-current="true" to the correct thumbnail image button to convey to screen readers that it's active.
270          $('#thumbnail-slider .thumbnail-image').eq(nextSlide).attr('aria-current', true);
271          $('#thumbnail-slider-mobile .thumbnail-image').eq(nextSlide).attr('aria-current', true);
272
273          // Only trigger for core 2024
274          if (drupalSettings.isCoreMds2024) {
275            // Remove aria-current from the last selected thumbnail image button
276            $('.thumbnail-slider-desktop .thumbnail-image[aria-current="true"]').removeAttr('aria-current');
277            $('.thumbnail-slider-mobile .thumbnail-image[aria-current="true"]').removeAttr('aria-current');
278
279            // Select the thumbnail image button that goes with this main image. Most importantly, this updates Slick's internal state to be consistent with the visual change.
280            $('.thumbnail-slider-desktop #block-duplo-pdp-slider-thumbail').slick('slickGoTo', nextSlide);
281            $('.thumbnail-slider-mobile #block-duplo-pdp-slider').slick('slickGoTo', nextSlide);
282
283            // Add aria-current="true" to the correct thumbnail image button to convey to screen readers that it's active.
284            $('.thumbnail-slider-desktop .thumbnail-image').eq(nextSlide).attr('aria-current', true);
285            $('.thumbnail-slider-mobile .thumbnail-image').eq(nextSlide).attr('aria-current', true);
286
287            var slides = slider.$slides;
288            if (slides.length > 8) {
289              var viewLessSelector = $('#block-duplo-pdp-slider-thumbnail .view-less');
290              var viewMoreSelector = $('#block-duplo-pdp-slider-thumbnail .view-more-wrapper');
291              var thumbnailSlides = $('.thumbnail-slider-desktop .slick-slide:gt(7)');
292              if (nextSlide > 6) {
293                thumbnailSlides.show();
294                viewMoreSelector.hide();
295                viewLessSelector.show();
296              } else if (nextSlide < 7) {
297                thumbnailSlides.hide();
298                viewMoreSelector.show();
299                viewLessSelector.hide();
300              }
301            }
302          }
303        });
304        // Only trigger for core 2024
305        if (drupalSettings.isCoreMds2024) {
306          // Button title translateable.
307          $('.sbd-carousel-page-indicator').each(function() {
308            // Button title translateable.
309            var title_next = $(this).find('.slick-next').attr('title');
310            var title_previous = $(this).find('.slick-prev .slick-sr-only').text();
311            $(this).find('.slick-next').attr('title', Drupal.t(title_next));
312            $(this).find('.slick-prev').attr('title', title_previous);
313          });
314        }
315
316        // Remove empty ID's from cloned slides
317        const slickSlideClones = document.querySelectorAll('.slick-cloned');
318        slickSlideClones.forEach(slickSlideClone => {
319          slickSlideClone.removeAttribute('id');
320        });
321
322        // Set aria disabled on inactive carousel slides
323        const slickSlides = document.querySelectorAll('.sbd-carousel .slick-slide');
324        slickSlides.forEach(slickSlide => {
325          if (slickSlide.classList.contains('slick-active')) {
326            slickSlide.setAttribute('aria-disabled', false);
327          } else {
328            slickSlide.setAttribute('aria-disabled', true);
329          }
330        });
331
332        // Temporarily removing this, it negatively affects all carousels including carousels in tabs
333        // We Need a better solution
334        // Customs slider logic to remove non existing product tiles
335          // if ($('.custom-slider').find('.product-teaser-section').length > 0) {
336      
337          //   $('.custom-slider').each(function () {
338          //     if ($(this).find('.product-teaser-section').length > 0) {
339          //       var count = $(this).find('.product-teaser-section').length;
340          //       var counter = 0;
341          //       $this = $(this);
342          //       $(this).find('.product-teaser-section').each(function () {
343          //         if ($(this).children().length == 0) {
344          //           $(this).closest('.slick-slide').remove();
345          //           counter = counter + 1;
346          //           $(this).closest('.sbd-carousel').addClass('hide-carousel');
347          //         }
348          //       });
349      
350          //       if ($this.find('.sbd-carousel .slick-track .slick-slide').length == 0) {
351          //         console.log('length is 0');
352          //         $this.closest('.sbd-carousel-component').hide();
353          //       } else {
354          //         if (count > counter) {
355          //           var newCount = count - counter;
356          //         }
357          //         $(this).find('.sbd-carousel').attr('data-slides-to-show', newCount);
358          //         $(this).parent().find('.top-header-container .total').text(newCount);
359          //         if (newCount < 3) {
360          //           $(this).parent().find('.top-header-container .current').text(newCount);
361          //         }
362          //         $(this).find(".sbd-carousel.slick-initialized").slick('reinit');
363          //       }
364          //     }
365          //   });
366          // }
367          // if ($('.coh-style-grid-container').find('.product-teaser-section').length > 0) {
368          //   $('.coh-style-grid-container').each(function () {
369          //     if ($(this).find('.product-teaser-section').length > 0) {
370          //       var count = $(this).find('.product-teaser-section').length;
371          //       var counter = 0;
372          //       $this = $(this);
373          //       $($this).find('.product-teaser-section').each(function () {
374          //         console.log($(this).parent);
375          //         if ($(this).children().length == 0) {
376          //           $(this).parent().remove();
377          //           counter = counter + 1;
378          //         }
379          //       });
380          //       if (count == counter) {
381          //         $(this).remove();
382          //       }
383          //     }
384          //   });
385          // }
386      });
387
388      // Reinitialize slick on tab change, this solves an issue in which
389      // the slider did not display properly when opening a new tab
390      $('.coh-style-tab-items:not(.is-active) > a').once().on('click', function (e) {
391        $(".sbd-carousel.slick-initialized").slick('reinit');
392      });
393
394      // Reinitialize slick on accordion for mobile
395      $('.coh-style-accordion-items').once().on('click', function () {
396        $('.sbd-carousel').slick('reinit');
397
398        // add a opacity on accordion for gsap fadein sections.
399        if (drupalSettings.isCoreMds2024) {
400          $(".page-node-type-sku .gsap-fadein-section, .page-node-type-sku .gsap-fadein-section .fifty-fifty-component").css({
401            "opacity": 1,
402            "visibility" : "visible",
403          });
404        }
405      });
406
407      // Changing the aria label on sbd carousels as this cannot be the same for each element.
408      // This is appending a number count at the end of the aria label.
409      var count = 1;
410      $('.sbd-carousel').each(function(){
411        var label = this.ariaLabel;
412        $(this).attr('aria-label', label + '-' + count++);
413      });
414  },
415  sliderProgressCal: function (slick, nextSlide=0, $progressBar, $progressBarLabel){
416    var slickIntCount = slick.$slider.find('.slick-active').length;
417    var calc = ( (nextSlide + slickIntCount) / (slick.slideCount) ) * 100;
418
419    $progressBar
420      .css('background-size', calc + '% 100%')
421      .attr('aria-valuenow', calc );
422    $progressBarLabel.text( calc + '% completed' );
423  }
424}
425})(jQuery, Drupal, drupalSettings);

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.