PageSourceSearch

https://splinecloud.com/js/card-carousel.js

js splinecloud.com collected 2026-10-07 14:56:28 UTC 7,535 bytes, 319 lines download raw bytes

1// https://codepen.io/WillyW/pen/wZebow
2
3
4class DraggingEvent {
5  constructor(target = undefined) {
6    this.target = target;
7  }
8  
9  event(callback) {
10    let handler;
11    
12    this.target.addEventListener("mousedown", e => {
13      e.preventDefault()
14      
15      handler = callback(e)
16      
17      window.addEventListener("mousemove", handler)
18      
19      document.addEventListener("mouseleave", clearDraggingEvent)
20      
21      window.addEventListener("mouseup", clearDraggingEvent)
22      
23      function clearDraggingEvent() {
24        window.removeEventListener("mousemove", handler)
25        window.removeEventListener("mouseup", clearDraggingEvent)
26      
27        document.removeEventListener("mouseleave", clearDraggingEvent)
28        
29        handler(null)
30      }
31    })
32    
33    this.target.addEventListener("touchstart", e => {
34      handler = callback(e)
35      
36      window.addEventListener("touchmove", handler)
37      
38      window.addEventListener("touchend", clearDraggingEvent)
39      
40      document.body.addEventListener("mouseleave", clearDraggingEvent)
41      
42      function clearDraggingEvent() {
43        window.removeEventListener("touchmove", handler)
44        window.removeEventListener("touchend", clearDraggingEvent)
45        
46        handler(null)
47      }
48    })
49  }
50  
51  // Get the distance that the user has dragged
52  getDistance(callback) {
53    function distanceInit(e1) {
54      let startingX, startingY;
55      
56      if ("touches" in e1) {
57        startingX = e1.touches[0].clientX
58        startingY = e1.touches[0].clientY
59      } else {
60        startingX = e1.clientX
61        startingY = e1.clientY
62      }
63      
64
65      return function(e2) {
66        if (e2 === null) {
67          return callback(null)
68        } else {
69          
70          if ("touches" in e2) {
71            return callback({
72              x: e2.touches[0].clientX - startingX,
73              y: e2.touches[0].clientY - startingY
74            })
75          } else {
76            return callback({
77              x: e2.clientX - startingX,
78              y: e2.clientY - startingY
79            })
80          }
81        }
82      }
83    }
84    
85    this.event(distanceInit)
86  }
87}
88
89
90class CardCarousel extends DraggingEvent {
91  constructor(container, controller = undefined) {
92    super(container)
93    
94    // DOM elements
95    this.container = container
96    this.controllerElement = controller
97    this.cards = container.querySelectorAll(".card")
98    
99    // Carousel data
100    this.centerIndex = (this.cards.length - 1) / 2;
101    this.cardWidth = this.cards[0].offsetWidth / this.container.offsetWidth * 100
102    this.xScale = {};
103    
104    // Resizing
105    window.addEventListener("resize", this.updateCardWidth.bind(this))
106    
107    if (this.controllerElement) {
108      this.controllerElement.addEventListener("keydown", this.controller.bind(this))      
109    }
110
111    
112    // Initializers
113    this.build()
114    
115    // Bind dragging event
116    super.getDistance(this.moveCards.bind(this))
117  }
118  
119  updateCardWidth() {
120    this.cardWidth = this.cards[0].offsetWidth / this.container.offsetWidth * 100
121    
122    this.build()
123  }
124  
125  build(fix = 0) {
126    for (let i = 0; i < this.cards.length; i++) {
127      const x = i - this.centerIndex;
128      const scale = this.calcScale(x)
129      const scale2 = this.calcScale2(x)
130      const zIndex = -(Math.abs(i - this.centerIndex))
131      
132      const leftPos = this.calcPos(x, scale2)
133     
134      
135      this.xScale[x] = this.cards[i]
136      
137      this.updateCards(this.cards[i], {
138        x: x,
139        scale: scale,
140        leftPos: leftPos,
141        zIndex: zIndex
142      })
143    }
144  }
145  
146  
147  controller(e) {
148    const temp = {...this.xScale};
149      
150      if (e.keyCode === 39) {
151        // Left arrow
152        for (let x in this.xScale) {
153          const newX = (parseInt(x) - 1 < -this.centerIndex) ? this.centerIndex : parseInt(x) - 1;
154
155          temp[newX] = this.xScale[x]
156        }
157      }
158      
159      if (e.keyCode == 37) {
160        // Right arrow
161        for (let x in this.xScale) {
162          const newX = (parseInt(x) + 1 > this.centerIndex) ? -this.centerIndex : parseInt(x) + 1;
163
164          temp[newX] = this.xScale[x]
165        }
166      }
167      
168      this.xScale = temp;
169      
170      for (let x in temp) {
171        const scale = this.calcScale(x),
172              scale2 = this.calcScale2(x),
173              leftPos = this.calcPos(x, scale2),
174              zIndex = -Math.abs(x)
175
176        this.updateCards(this.xScale[x], {
177          x: x,
178          scale: scale,
179          leftPos: leftPos,
180          zIndex: zIndex
181        })
182      }
183  }
184  
185  calcPos(x, scale) {
186    let formula;
187    
188    if (x < 0) {
189      formula = (scale * 100 - this.cardWidth) / 2
190      
191      return formula
192
193    } else if (x > 0) {
194      formula = 100 - (scale * 100 + this.cardWidth) / 2
195      
196      return formula
197    } else {
198      formula = 100 - (scale * 100 + this.cardWidth) / 2
199      
200      return formula
201    }
202  }
203  
204  updateCards(card, data) {
205    if (data.x || data.x == 0) {
206      card.setAttribute("data-x", data.x)
207    }
208    
209    if (data.scale || data.scale == 0) {
210      card.style.transform = `scale(${data.scale})`
211
212      if (data.scale == 0) {
213        card.style.opacity = data.scale
214      } else {
215        card.style.opacity = 1;
216      }
217    }
218   
219    if (data.leftPos) {
220      card.style.left = `${data.leftPos}%`        
221    }
222    
223    if (data.zIndex || data.zIndex == 0) {
224      if (data.zIndex == 0) {
225        card.classList.add("highlight")
226      } else {
227        card.classList.remove("highlight")
228      }
229      
230      card.style.zIndex = data.zIndex  
231    }
232  }
233  
234  calcScale2(x) {
235    let formula;
236   
237    if (x <= 0) {
238      formula = 1 - -1 / 5 * x
239      
240      return formula
241    } else if (x > 0) {
242      formula = 1 - 1 / 5 * x
243      
244      return formula
245    }
246  }
247  
248  calcScale(x) {
249    const formula = 1 - 1 / 5 * Math.pow(x, 2)
250    
251    if (formula <= 0) {
252      return 0 
253    } else {
254      return formula      
255    }
256  }
257  
258  checkOrdering(card, x, xDist) {    
259    const original = parseInt(card.dataset.x)
260    const rounded = Math.round(xDist)
261    let newX = x
262    
263    if (x !== x + rounded) {
264      if (x + rounded > original) {
265        if (x + rounded > this.centerIndex) {
266          
267          newX = ((x + rounded - 1) - this.centerIndex) - rounded + -this.centerIndex
268        }
269      } else if (x + rounded < original) {
270        if (x + rounded < -this.centerIndex) {
271          
272          newX = ((x + rounded + 1) + this.centerIndex) - rounded + this.centerIndex
273        }
274      }
275      
276      this.xScale[newX + rounded] = card;
277    }
278    
279    const temp = -Math.abs(newX + rounded)
280    
281    this.updateCards(card, {zIndex: temp})
282
283    return newX;
284  }
285  
286  moveCards(data) {
287    let xDist;
288    
289    if (data != null) {
290      this.container.classList.remove("smooth-return")
291      xDist = data.x / 250;
292    } else {
293
294      
295      this.container.classList.add("smooth-return")
296      xDist = 0;
297
298      for (let x in this.xScale) {
299        this.updateCards(this.xScale[x], {
300          x: x,
301          zIndex: Math.abs(Math.abs(x) - this.centerIndex)
302        })
303      }
304    }
305
306    for (let i = 0; i < this.cards.length; i++) {
307      const x = this.checkOrdering(this.cards[i], parseInt(this.cards[i].dataset.x), xDist),
308            scale = this.calcScale(x + xDist),
309            scale2 = this.calcScale2(x + xDist),
310            leftPos = this.calcPos(x + xDist, scale2)
311      
312      
313      this.updateCards(this.cards[i], {
314        scale: scale,
315        leftPos: leftPos
316      })
317    }
318  }
319}

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.