PageSourceSearch

https://decidim-website.netlify.app/javascripts/carousel.js

js decidim-website.netlify.app collected 2026-10-03 08:17:08 UTC 3,310 bytes, 115 lines download raw bytes

1/**
2 * Initialises drag-to-scroll behaviour on all elements marked with
3 * [data-scroll-gallery]. Supports mouse (click & drag) and touch (swipe).
4 *
5 * Cursor position relative to the gallerys left edge
6 * used to calculate the distance moved during a drag/swipe.
7 *
8 * @returns {void}
9 */
10
11const scrollGallery = function () {
12  const galleries = document.querySelectorAll("[data-scroll-gallery]");
13  galleries.forEach((gallery) => {
14    const track = gallery.querySelector("[data-scroll-track]");
15    if (!track) {
16      return;
17    }
18
19    let isDown = false;
20    let startX = 0;
21    let startTranslateX = 0;
22
23    const getTranslateX = () => {
24      const transform = window.getComputedStyle(track).transform;
25      if (transform === "none") {
26        return 0;
27      }
28      const match = transform.match(/matrix.*\((.+)\)/);
29      if (!match) {
30        return 0;
31      }
32      const values = match[1].split(", ");
33      return parseFloat(values[4]) || 0;
34    };
35
36    const startDrag = (pageX) => {
37      isDown = true;
38      startX = pageX - gallery.offsetLeft;
39      startTranslateX = getTranslateX();
40      track.classList.remove("animate-slide-x");
41      track.style.transform = `translateX(${startTranslateX}px)`;
42    };
43
44    const endDrag = () => {
45      if (!isDown) {
46        return;
47      }
48      isDown = false;
49
50      const currentTx = getTranslateX();
51
52      const targetStr =
53        getComputedStyle(track).getPropertyValue("--translate-x") || "-50%";
54      const targetFraction = parseFloat(targetStr) / 100;
55      const targetPx = targetFraction * track.scrollWidth;
56      const duration =
57        parseFloat(getComputedStyle(track).animationDuration) || 15;
58
59      let progress = targetPx !== 0
60        ? currentTx / targetPx
61        : 0;
62      progress = ((progress % 1) + 1) % 1;
63
64      track.style.animationDelay = `${-duration * progress}s`;
65      track.style.transform = "";
66      track.classList.add("animate-slide-x");
67    };
68
69    gallery.addEventListener("mousedown", (e) => {
70      startDrag(e.pageX);
71      gallery.classList.add("cursor-grabbing");
72      gallery.classList.remove("cursor-grab");
73    });
74
75    gallery.addEventListener("mouseleave", () => {
76      if (!isDown) {
77        return;
78      }
79      endDrag();
80      gallery.classList.remove("cursor-grabbing");
81      gallery.classList.add("cursor-grab");
82    });
83
84    gallery.addEventListener("mouseup", () => {
85      endDrag();
86      gallery.classList.remove("cursor-grabbing");
87      gallery.classList.add("cursor-grab");
88    });
89
90    gallery.addEventListener("mousemove", (e) => {
91      if (!isDown) {
92        return;
93      }
94      e.preventDefault();
95      const xAxis = e.pageX - gallery.offsetLeft;
96      const walk = (xAxis - startX) * 1.5;
97      track.style.transform = `translateX(${startTranslateX + walk}px)`;
98    });
99
100    gallery.addEventListener("touchstart", (e) => {
101      startDrag(e.touches[0].pageX);
102    }, { passive: true });
103
104    gallery.addEventListener("touchmove", (e) => {
105      const xAxis = e.touches[0].pageX - gallery.offsetLeft;
106      const walk = (xAxis - startX) * 1.5;
107      track.style.transform = `translateX(${startTranslateX + walk}px)`;
108    }, { passive: true });
109
110    gallery.addEventListener("touchend", () => {
111      endDrag();
112    }, { passive: true });
113  });
114};
115scrollGallery();

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.