PageSourceSearch

https://ocf.ie/wp-content/plugins/breakdance/subplugins/breakdance…/breakdance-swiper.js?bd_ver=2.6.1

js ocf.ie collected 2026-09-24 12:45:02 UTC 12,181 bytes, 348 lines download raw bytes

1// Support for swiper v8
2(function () {
3  function BreakdanceSwiper() {
4    const { mergeObjects, matchMedia, getCurrentBreakpoint, is, isBuilder } = BreakdanceFrontend.utils;
5
6    function isElementInDom(selector) {
7      // An element can be "hidden" (aka not in the DOM) with Hide on breakpoint -> in builder preview
8      // and Swiper needs the element to be part of the DOM to work on it
9      // This code was removed in https://github.com/soflyy/breakdance-elements/pull/2184/files#diff-897333d33555b463d7a30b1328e025df240eeb851ed79e85b643c65c6c6b4bffL12
10      // but that introduced the following bug: https://github.com/soflyy/breakdance/issues/5956
11      // so we put this code back, since the element might be SSRing.
12      const isElementInDom = document.querySelector(selector);
13      return !!isElementInDom;
14    }
15
16    function setBreakpoint(swiper, settings) {
17      const { BASE_BREAKPOINT_ID } = window.BreakdanceFrontend.data;
18      const isLoop = settings.infinite === "enabled" && !isBuilder();
19      const slidesPerView = settings.advanced.slides_per_view;
20      const slidesPerGroup = settings.advanced.slides_per_group;
21      const spaceBetween = settings.advanced.between_slides;
22
23      const onePerViewAt = settings.advanced.one_per_view_at;
24      const onePerViewAtDesktop = onePerViewAt === BASE_BREAKPOINT_ID;
25      const alwaysOne = settings.effect === "fade" || settings.effect === "flip" || onePerViewAtDesktop;
26
27      const { activeIndex, initialized, loopedSlides = 0 } = swiper;
28      const needsReLoop = isLoop && ((slidesPerView !== swiper.params.slidesPerView) || (slidesPerGroup !== swiper.params.slidesPerGroup));
29
30      if (alwaysOne || matchMedia(onePerViewAt)) {
31        swiper.params.slidesPerView = 1;
32        swiper.params.slidesPerGroup = 1;
33      } else {
34        setBreakpointProperty(swiper, "slidesPerView", slidesPerView);
35        setBreakpointProperty(swiper, "slidesPerGroup", slidesPerGroup);
36      }
37
38      setBreakpointProperty(swiper, "spaceBetween", spaceBetween);
39
40      // A reloop is necessary when changing `slidesPerView` or `direction`*
41      // when swiper has already been initialized.
42      // *cargo cult addition: when slidesPerGroup was implemented, it was added to the needsReLoop calculation without
43      // taking into consideration whether it is required
44      if (needsReLoop && initialized) {
45        // Tip: This logic is different on >= v9.
46        // See: https://github.com/nolimits4web/swiper/blob/master/src/core/breakpoints/setBreakpoint.js
47        swiper.loopDestroy();
48        swiper.loopCreate();
49        swiper.updateSlides();
50        swiper.slideTo(activeIndex - loopedSlides + swiper.loopedSlides, 0, false);
51      } else {
52        swiper.updateSlides();
53        swiper.slideReset(0);
54      }
55    }
56
57    function setBreakpointProperty(swiper, key, value) {
58      if (Number.isFinite(value)) {
59        // version >= 1.3 - backwards compatibility for non-breakpoint values.
60        swiper.params[key] = value;
61      } else if (is.obj(value)) {
62        // The value is an object, but we don't know if it's a breakpoint yet.
63        const availableBreakpoints = Object.keys(value);
64        const currBreakpoint = getCurrentBreakpoint(availableBreakpoints);
65        const bpValue = value[currBreakpoint.id];
66
67        // Found a breakpoint value, use it.
68        if (bpValue) {
69          swiper.params[key] = isUnitValue(bpValue) ? bpValue.number : bpValue;
70        } else if (isUnitValue(value) && !isResponsiveValue(value)) {
71          // Otherwise, if the value is a unit value, use it.
72          // Due to unknown reasons, the value is sometimes a breakpoint + unit value object, we ignore those.
73          swiper.params[key] = value.number;
74        }
75      }
76    }
77
78    function isResponsiveValue(value) {
79      const { breakpoints } = window.BreakdanceFrontend.data;
80      const ids = breakpoints.map((bp) => bp.id);
81      return Object.keys(value).some(key => ids.includes(key));
82    }
83
84    function isUnitValue(value) {
85      return is.obj(value) && "number" in value;
86    }
87
88    function resetSlideAnimations(slide) {
89      const customEvent = new Event("breakdance_reset_animations", { bubbles: true });
90      slide.dispatchEvent(customEvent);
91    }
92
93    function playSlideAnimations(slide, delay) {
94      const customEvent = new CustomEvent("breakdance_play_animations", {
95        bubbles: true,
96        detail: { delay: delay / 1000 }
97      });
98      slide.dispatchEvent(customEvent);
99    }
100
101    function supportEntranceAnimations(swiper, settings) {
102      let lastVisibleSlides = swiper.visibleSlides || [];
103      const playOn = settings.advanced.play_animations_on || "transition_end";
104
105      const getNewestSlides = () => swiper.visibleSlides?.filter(x => !lastVisibleSlides.includes(x)) || [];
106      const getHiddenSlides = () => swiper.slides?.filter((slide) => !swiper.visibleSlides.includes(slide)) || [];
107
108      // This is a workaround for when the user drags the slider before slideChange is triggered.
109      swiper.on("sliderFirstMove", () => {
110        const hiddenSlides = getHiddenSlides();
111        hiddenSlides.forEach((slide) => resetSlideAnimations(slide));
112      });
113
114      swiper.on("slideChange", () => {
115        const delay = playOn === "transition_start" ? 0 : swiper.params.speed * 0.3;
116        const newSlides = getNewestSlides();
117
118        newSlides.forEach(slide => {
119          resetSlideAnimations(slide);
120          playSlideAnimations(slide, delay);
121        });
122
123        lastVisibleSlides = swiper.visibleSlides;
124      });
125    }
126
127    // This prevents memory leak from event listeners
128    function destroy(id) {
129      if (
130        window.swiperInstances &&
131        window.swiperInstances[id] &&
132        // if the element is not in the DOM, "el" will be the selector instead of the element reference
133        typeof window.swiperInstances[id].el === "object"
134      ) {
135        window.swiperInstances[id].destroy(true, true);
136        delete window.swiperInstances[id];
137      }
138    }
139
140    function update({ id, selector, settings, paginationSettings, extras }) {
141
142      if (!isElementInDom(`${selector} > .breakdance-swiper-wrapper > .swiper`)) return;
143
144      destroy(id);
145
146      const defaultOptions = {
147        settings: {
148          effect: "slide",
149          coverflow: {
150            rotate: {
151              number: 50
152            },
153            depth: {
154              number: 100
155            },
156            stretch: {
157              number: 0
158            }
159          },
160          speed: { number: 1000 },
161          autoplay_settings: {
162            speed: {
163              number: 3000
164            }
165          },
166          advanced: {
167            between_slides: 0,
168            slides_per_view: 1,
169            slides_per_group: 1,
170            initial_slide: 0,
171          },
172          direction: "horizontal",
173        },
174        pagination: {
175          type: "bullets"
176        }
177      };
178
179      settings = mergeObjects(defaultOptions.settings, settings);
180      paginationSettings = mergeObjects(
181        defaultOptions.pagination,
182        paginationSettings
183      );
184
185      const advancedSettings = settings.advanced;
186      const isBuilder = !!window?.BreakdanceFrontend.utils.isBuilder();
187
188      const isCoverflowEffect = settings.effect === "coverflow";
189      const coverFlowEffect = isCoverflowEffect
190        ? {
191          coverflowEffect: {
192            rotate: settings.coverflow.rotate.number,
193            slideShadows: !!settings.coverflow.shadow,
194            depth: settings.coverflow.depth.number,
195            stretch: settings.coverflow.stretch.number
196          }
197        }
198        : {};
199
200      const fadeEffect =
201        settings.effect === "fade"
202          ? {
203            fadeEffect: {
204              crossFade: true
205            }
206          }
207          : {};
208
209      const builderOnlySettings = isBuilder
210        ? {
211          // this prevents bugs caused by Swiper swallowing events
212          preventClicksPropagation: false,
213          preventClicks: false,
214          simulateTouch: false,
215          // doesn't play nice with our drag events
216          allowTouchMove: false
217        }
218        : {};
219
220      const forceAutoplay = extras && extras.autoplay === true;
221
222      const swiperInstance = new Swiper(
223        `${selector} > .breakdance-swiper-wrapper > .swiper`,
224        {
225          ...extras,
226          speed: settings.speed.number,
227          loop: settings.infinite === "enabled" && !isBuilder,
228          autoplay:
229            settings.autoplay === "enabled" && (!isBuilder || forceAutoplay)
230              ? {
231                delay: settings.autoplay_settings.speed.number,
232                pauseOnMouseEnter:
233                  !!settings.autoplay_settings.pause_on_hover,
234                disableOnInteraction:
235                  !!settings.autoplay_settings.stop_on_interaction,
236                stopOnLastSlide: settings.infinite !== "enabled",
237              }
238              : false,
239
240          effect: settings.effect,
241          pagination: {
242            el: `${selector} > .breakdance-swiper-wrapper > .swiper-pagination`,
243            type: paginationSettings.type,
244            clickable: true,
245          },
246          navigation: {
247            nextEl: `${selector} > .breakdance-swiper-wrapper > .swiper-button-next`,
248            prevEl: `${selector} > .breakdance-swiper-wrapper > .swiper-button-prev`,
249          },
250          keyboard: !advancedSettings.disable_keyboard_control,
251          ...coverFlowEffect,
252          ...fadeEffect,
253
254          ...builderOnlySettings,
255
256          // Advanced options
257          mousewheel: advancedSettings.swipe_on_scroll
258            ? {
259              releaseOnEdges: true
260            }
261            : false,
262
263          autoHeight: !!advancedSettings.auto_height,
264          loopPreventsSlide: false,
265          centeredSlides: isCoverflowEffect
266            ? // We decided to make it always true because otherwise it looks ugly
267            true
268            : settings.center_slides,
269          // Swiper docs advise to do this
270          watchSlidesProgress: advancedSettings.slides_per_view !== 1,
271          // doesn't do anything on its own, but enables elements to create cool effects with HTML
272          parallax: true,
273
274          direction: settings.direction,
275          a11y: {
276            slideRole: ""
277          },
278          initialSlide: settings.advanced.initial_slide,
279        });
280
281      setBreakpoint(swiperInstance, settings);
282      supportEntranceAnimations(swiperInstance, settings);
283
284      swiperInstance.on("resize", () => {
285        setBreakpoint(swiperInstance, settings);
286      });
287
288      window.swiperInstances = {
289        ...window.swiperInstances,
290        [id]: swiperInstance
291      };
292    }
293
294    function updateSliderFromChild(id) {
295      const sliderId = document
296        // select itself
297        .querySelector(`[data-node-id="${id}"]`)
298        // get parent (slider) node id
299        .parentElement.closest("[data-node-id]").dataset.nodeId;
300
301      const sliderIdNumber = sliderId && parseInt(sliderId);
302
303      if (window.swiperInstances && window.swiperInstances[sliderIdNumber]) {
304        window.swiperInstances[sliderIdNumber].update();
305      }
306    }
307
308    function selectSlide(id) {
309      const slideElement = document
310        .querySelector(`[data-node-id="${id}"]`)
311        .closest(".swiper-slide");
312
313      if (slideElement) {
314        const slideIndex = Array.from(
315          slideElement.parentElement.children
316        ).indexOf(slideElement);
317
318        const sliderElement =
319          slideElement.parentElement &&
320          slideElement.parentElement.closest("[data-node-id]");
321
322        const sliderId = sliderElement ? sliderElement.dataset.nodeId : null;
323
324        if (
325          sliderId &&
326          slideIndex !== null &&
327          window.swiperInstances &&
328          window.swiperInstances[sliderId]
329        ) {
330          if (window.swiperInstances[sliderId].visibleSlides.includes(slideElement)) {
331            return;
332          }
333
334          window.swiperInstances[sliderId].slideTo(slideIndex, 0);
335        }
336      }
337    }
338
339    return {
340      update,
341      destroy,
342      updateSliderFromChild,
343      selectSlide
344    };
345  }
346
347  window.BreakdanceSwiper = BreakdanceSwiper;
348})();

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.