PageSourceSearch

https://www.upv.es/js/carousel.js

js upv.es collected 2026-09-24 07:43:05 UTC 6,812 bytes, 204 lines download raw bytes

1document.addEventListener(
2  "DOMContentLoaded",
3  function () {
4    const sliders = document.querySelectorAll(".upv-carousel")
5
6    sliders.forEach((slide) => {
7      const isFullSlider = slide.classList.contains("upv-carousel-full")
8      const slideWidth = isFullSlider ? slide.parentNode.offsetWidth : Number(slide.dataset.width)
9      const gap = isFullSlider ? 0 : Number(slide.dataset.gap)
10      const slider = slide.querySelector(".slider-content")
11      const slides = slider.children
12
13      // if (slides.length < 2) return // Stop if min slides
14
15      let mm = gsap.matchMedia() // Start gsap matchmedia
16      slider.style.gap = `${gap}px` // Define grid
17
18      if (isFullSlider) {
19        slider.style.gridTemplateColumns = `repeat(${slides.length}, ${slideWidth}px)` // Define grid
20        slider.style.width = `calc(${slides.length} * ${slideWidth}px )` // Define slider width
21      } else {
22        slider.style.gridTemplateColumns = `repeat(${slides.length}, min(${slideWidth}px, 80vw))` // Define grid
23        slider.style.width = `calc(${slides.length} * min(${slideWidth}px, 80vw) + ${(slides.length - 1) * gap}px)` // Define slider width
24      }
25
26      let currentPosition = 0 // Start position
27      let usableSlides = 2
28
29      // Get elements
30      const preBtn = slide.querySelector(".pre-btn")
31      const nextBtn = slide.querySelector(".next-btn")
32      const lineElement = slide.querySelector(".slider-progress-active")
33
34      //Define document width
35      let documentWidth = document.documentElement.clientWidth
36
37      // Check if buttons is availables after update
38      function checkButtons() {
39        currentPosition === 0 ? (preBtn.disabled = true) : (preBtn.disabled = false)
40
41        currentPosition < usableSlides - 1 ? (nextBtn.disabled = false) : (nextBtn.disabled = true)
42      }
43
44      function calcUsablesSlides() {
45        const containerWidth = slide.offsetWidth
46        const vw = isFullSlider ? documentWidth : documentWidth * 0.8
47        const slidePlusGapWitdh = Math.min(slideWidth, vw) + gap
48        usableSlides = 2
49        while (containerWidth > Math.min(slideWidth, vw) * usableSlides + gap * (usableSlides - 1)) {
50          usableSlides++
51        }
52        if (usableSlides < 2) {
53          usableSlides = 1
54        }
55        usableSlides = slides.length - usableSlides + 2
56        return { usableSlides, vw, gap, slidePlusGapWitdh }
57      }
58
59      //Reusable functions to calc positions
60
61      function calcDraggable() {
62        const { usableSlides, vw, gap } = calcUsablesSlides()
63        return Math.min(slideWidth, vw) * usableSlides * -1 - gap * (usableSlides - 1)
64      }
65
66      function calcSnaps() {
67        const { usableSlides, slidePlusGapWitdh } = calcUsablesSlides()
68        return Array.apply(null, { length: usableSlides }).map((el, index) => slidePlusGapWitdh * index * -1)
69      }
70
71      function updateLine() {
72        if (!lineElement) return
73        lineElement.style.width = `${(100 / slides.length) * (currentPosition + 1)}%`
74      }
75
76      let draggable = calcDraggable()
77      let snaps = calcSnaps()
78
79      mm.add("(min-width: 200px)", () => {
80        updateLine()
81
82        drag = Draggable.create(slider, {
83          trigger: slider,
84          type: "x",
85          bounds: {
86            minX: draggable - 150,
87            minY: 0,
88            maxX: 150,
89            maxY: 0,
90          },
91          onDragEnd() {
92            if (!snaps.find((el) => el === this.endX)) {
93              const snapsCopy = [...snaps]
94              let closest = snapsCopy.sort((a, b) => {
95                return Math.abs(a - this.endX) - Math.abs(b - this.endX)
96              })[0]
97              gsap.to(slider, { x: closest, duration: 0.5 })
98              currentPosition = snaps.indexOf(closest)
99              if (isFullSlider) return
100
101              updateLine()
102              checkButtons()
103            } else {
104              currentPosition = snaps.indexOf(this.endX)
105              if (isFullSlider) return
106              updateLine()
107              checkButtons()
108            }
109          },
110        })
111      })
112      if (preBtn) {
113        preBtn.addEventListener(
114          "click",
115          function () {
116            if (currentPosition !== 0) {
117              currentPosition = currentPosition - 1
118              gsap.to(slider, { x: snaps[currentPosition], duration: 0.5 })
119              if (isFullSlider) return
120
121              updateLine()
122              checkButtons()
123            }
124          },
125          false
126        )
127      }
128
129      if (nextBtn) {
130        nextBtn.addEventListener(
131          "click",
132          function () {
133            if (currentPosition < slides.length - 1) {
134              currentPosition = currentPosition + 1
135              gsap.to(slider, { x: snaps[currentPosition], duration: 0.5 })
136              if (isFullSlider) return
137
138              updateLine()
139              checkButtons()
140            }
141          },
142          false
143        )
144      }
145
146      window.addEventListener("resize", () => {
147        documentWidth = document.documentElement.clientWidth
148        snaps = calcSnaps()
149        draggable = calcDraggable()
150        updateLine()
151        gsap.matchMediaRefresh()
152      })
153    })
154
155    let carousels = document.querySelectorAll(".sidebar-carousel")
156
157    carousels.forEach((carousel) => {
158      let position = 0
159      let slides = carousel.querySelectorAll(".carousel-content > p")
160      let preBtn = carousel.querySelector("#pre-btn")
161      let nextBtn = carousel.querySelector("#next-btn")
162      let navigator = Array.from(carousel.querySelectorAll(".manual-navigator > button"))
163
164      preBtn.addEventListener("click", prev, false)
165      nextBtn.addEventListener("click", next, false)
166
167      navigator.forEach((btn) => {
168        btn.addEventListener(
169          "click",
170          () => {
171            goToPosition(Number(btn.id))
172          },
173          false
174        )
175      })
176
177      function prev() {
178        position = position - 1
179        goToPosition(position)
180      }
181      function next() {
182        position = position + 1
183        goToPosition(position)
184      }
185      function goToPosition(index) {
186        slides.forEach((slide) => (slide.style.transform = `translateX(calc(-100% * ${index} ))`))
187        navigator.forEach((el) => el.classList.remove("active"))
188        navigator[index].classList.add("active")
189
190        if (index >= slides.length - 1) {
191          nextBtn.disabled = true
192        } else {
193          nextBtn.disabled = false
194        }
195        if (index === 0) {
196          preBtn.disabled = true
197        } else {
198          preBtn.disabled = false
199        }
200      }
201    })
202  },
203  false
204)

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.