PageSourceSearch

https://asrockstudios.in/assets/js/home-hero-showcase.js?v=3

js asrockstudios.in collected 2026-10-05 19:03:30 UTC 9,611 bytes, 299 lines download raw bytes

1function initHeroShowcase(root) {
2  if (!root || root.dataset.showcaseReady === "1") return;
3  root.dataset.showcaseReady = "1";
4
5  const ring = root.querySelector("[data-orbit-ring]");
6  const track = root.querySelector(".home-hero-showcase__orbit-track");
7  const cards = Array.from(root.querySelectorAll("[data-orbit-card]"));
8  const terminal = root.querySelector("[data-hero-terminal]");
9  const stage = root.querySelector(".home-hero-showcase__stage");
10  if (!ring || !cards.length) return;
11
12  const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
13  const finePointer = window.matchMedia("(hover: hover) and (pointer: fine)").matches;
14  const isCompact =
15    root.classList.contains("home-plugin-strip--beside") || !!root.querySelector(".home-hero-showcase--compact");
16
17  let activeIndex = 0;
18  let autoplayTimer = null;
19  let paused = false;
20  let sectionVisible = true;
21  let dragPointerId = null;
22  let dragStartX = 0;
23  let dragMoved = false;
24  let dragStartIndex = 0;
25
26  const DRAG_CLICK_THRESHOLD = 10;
27  const DRAG_SLIDE_PX = 56;
28
29  if (isCompact) root.classList.add("is-plugin-coverflow");
30
31  function ensureCardFaces() {
32    cards.forEach((card, i) => {
33      card.style.setProperty("--orbit-index", String(i));
34      card.dataset.orbitIndex = String(i);
35      if (card.querySelector(".home-hero-showcase__card-face")) return;
36      const face = document.createElement("div");
37      face.className = "home-hero-showcase__card-face";
38      while (card.firstChild) face.appendChild(card.firstChild);
39      card.appendChild(face);
40    });
41  }
42
43  function wrappedDelta(i, active) {
44    const n = cards.length;
45    let d = i - active;
46    if (d > n / 2) d -= n;
47    if (d < -n / 2) d += n;
48    return d;
49  }
50
51  function layoutCoverflow() {
52    // Flat coverflow — no orbit ring rotation (avoids mirrored/overlapping faces).
53    ring.style.transform = "none";
54    cards.forEach((card, i) => {
55      const d = wrappedDelta(i, activeIndex);
56      const abs = Math.abs(d);
57      const face = card.querySelector(".home-hero-showcase__card-face");
58      if (face) face.style.transform = "none";
59
60      card.classList.toggle("is-front", d === 0);
61      card.classList.toggle("is-prev", d === -1);
62      card.classList.toggle("is-next", d === 1);
63      card.classList.toggle("is-far", abs > 1);
64
65      if (abs > 1) {
66        card.style.opacity = "0";
67        card.style.visibility = "hidden";
68        card.style.pointerEvents = "none";
69        card.style.transform = "translate(-50%, -50%) scale(0.6)";
70        card.style.zIndex = "0";
71        return;
72      }
73
74      card.style.visibility = "visible";
75      card.style.pointerEvents = d === 0 ? "auto" : "auto";
76      card.style.zIndex = String(5 - abs);
77
78      if (d === 0) {
79        card.style.opacity = "1";
80        card.style.filter = "none";
81        card.style.transform = "translate(-50%, -50%) translateX(0) translateZ(40px) rotateY(0deg) scale(1)";
82      } else if (d === -1) {
83        card.style.opacity = "0.55";
84        card.style.filter = "grayscale(0.35) brightness(0.72)";
85        card.style.transform = "translate(-50%, -50%) translateX(-86px) translateZ(0) rotateY(18deg) scale(0.82)";
86      } else {
87        card.style.opacity = "0.55";
88        card.style.filter = "grayscale(0.35) brightness(0.72)";
89        card.style.transform = "translate(-50%, -50%) translateX(86px) translateZ(0) rotateY(-18deg) scale(0.82)";
90      }
91    });
92  }
93
94  // Legacy full orbit (only if not compact)
95  let angle = 0;
96  let targetAngle = 0;
97  let raf = null;
98  const stepDeg = 360 / cards.length;
99
100  function applyOrbitAngle(deg) {
101    ring.style.setProperty("--orbit-angle", `${deg.toFixed(2)}deg`);
102    ring.style.transform = `rotateY(${deg.toFixed(2)}deg)`;
103    cards.forEach((card, i) => {
104      const total = deg + i * stepDeg;
105      const face = card.querySelector(".home-hero-showcase__card-face");
106      if (face) face.style.transform = `rotateY(${(-total).toFixed(2)}deg)`;
107      const d = wrappedDelta(i, activeIndex);
108      card.classList.toggle("is-front", d === 0);
109      card.classList.toggle("is-prev", d === -1);
110      card.classList.toggle("is-next", d === 1);
111      card.classList.toggle("is-far", Math.abs(d) > 1);
112    });
113  }
114
115  function indexFromAngle(deg) {
116    const raw = Math.round(-deg / stepDeg);
117    return ((raw % cards.length) + cards.length) % cards.length;
118  }
119
120  function tickOrbit() {
121    const diff = targetAngle - angle;
122    angle += diff * 0.1;
123    if (Math.abs(diff) < 0.05) angle = targetAngle;
124    applyOrbitAngle(angle);
125    if (Math.abs(diff) > 0.05) raf = requestAnimationFrame(tickOrbit);
126    else raf = null;
127  }
128
129  function setActive(index, { animate = true } = {}) {
130    activeIndex = ((index % cards.length) + cards.length) % cards.length;
131    if (isCompact) {
132      layoutCoverflow();
133      return;
134    }
135    targetAngle = -activeIndex * stepDeg;
136    if (!animate) {
137      angle = targetAngle;
138      applyOrbitAngle(angle);
139    } else if (raf == null) {
140      raf = requestAnimationFrame(tickOrbit);
141    }
142  }
143
144  ensureCardFaces();
145  ring.style.setProperty("--orbit-step", `${stepDeg}deg`);
146  setActive(0, { animate: false });
147
148  function startAutoplay() {
149    stopAutoplay();
150    if (reduceMotion || paused || dragPointerId != null || !sectionVisible) return;
151    autoplayTimer = setInterval(() => setActive(activeIndex + 1), 4200);
152  }
153
154  function stopAutoplay() {
155    if (autoplayTimer) {
156      clearInterval(autoplayTimer);
157      autoplayTimer = null;
158    }
159  }
160
161  function endDrag() {
162    if (dragPointerId == null) return;
163    if (track?.hasPointerCapture?.(dragPointerId)) {
164      try {
165        track.releasePointerCapture(dragPointerId);
166      } catch {
167        /* ignore */
168      }
169    }
170    track?.classList.remove("is-orbit-dragging");
171    const wasDrag = dragMoved;
172    dragPointerId = null;
173    if (wasDrag) {
174      window.setTimeout(() => {
175        dragMoved = false;
176      }, 280);
177    } else {
178      dragMoved = false;
179    }
180    if (!root.matches(":hover")) {
181      paused = false;
182      startAutoplay();
183    }
184  }
185
186  const dragSurface = track || stage || root;
187  if (!reduceMotion && dragSurface) {
188    dragSurface.addEventListener(
189      "pointerdown",
190      (e) => {
191        if (e.button !== 0 && e.pointerType !== "touch") return;
192        dragPointerId = e.pointerId;
193        dragStartX = e.clientX;
194        dragStartIndex = activeIndex;
195        dragMoved = false;
196        paused = true;
197        stopAutoplay();
198        dragSurface.setPointerCapture?.(e.pointerId);
199        track?.classList.add("is-orbit-dragging");
200      },
201      { passive: true }
202    );
203
204    dragSurface.addEventListener(
205      "pointermove",
206      (e) => {
207        if (e.pointerId !== dragPointerId) return;
208        const dx = e.clientX - dragStartX;
209        if (Math.abs(dx) > DRAG_CLICK_THRESHOLD) dragMoved = true;
210        if (!dragMoved) return;
211        e.preventDefault();
212        if (isCompact) {
213          const steps = Math.round(-dx / DRAG_SLIDE_PX);
214          setActive(dragStartIndex + steps);
215        } else {
216          angle = -dragStartIndex * stepDeg + dx * 0.42;
217          targetAngle = angle;
218          activeIndex = indexFromAngle(angle);
219          applyOrbitAngle(angle);
220          if (raf) {
221            cancelAnimationFrame(raf);
222            raf = null;
223          }
224        }
225      },
226      { passive: false }
227    );
228
229    dragSurface.addEventListener("pointerup", (e) => {
230      if (!isCompact && dragMoved) setActive(indexFromAngle(angle));
231      endDrag();
232    });
233    dragSurface.addEventListener("pointercancel", endDrag);
234  }
235
236  cards.forEach((card, i) => {
237    card.addEventListener("click", (e) => {
238      if (dragMoved) {
239        e.preventDefault();
240        e.stopPropagation();
241        return;
242      }
243      if (i !== activeIndex) {
244        e.preventDefault();
245        setActive(i);
246      }
247    });
248    card.addEventListener("mouseenter", () => {
249      if (dragPointerId != null) return;
250      paused = true;
251      stopAutoplay();
252      setActive(i);
253    });
254  });
255
256  root.addEventListener("mouseleave", () => {
257    if (dragPointerId != null) return;
258    paused = false;
259    startAutoplay();
260  });
261
262  if (terminal && !reduceMotion) {
263    const terminalLines = [
264      "> Bootstrapping OnlineSubsystem… OK",
265      "> Loading PlayFab backend module… OK",
266      "> Spawning lobby session… 128 slots",
267      "> Steam auth ticket validated",
268      "> Matchmaking queue: READY",
269      "> Shipping build: v5.4.2 ✓",
270    ];
271    let terminalIdx = 0;
272    setInterval(() => {
273      terminalIdx = (terminalIdx + 1) % terminalLines.length;
274      terminal.innerHTML = `<span data-terminal-line>${terminalLines[terminalIdx]}</span>`;
275    }, 2800);
276  }
277
278  if ("IntersectionObserver" in window) {
279    const sectionIo = new IntersectionObserver(
280      (entries) => {
281        entries.forEach((entry) => {
282          sectionVisible = entry.isIntersecting && entry.intersectionRatio >= 0.08;
283          if (sectionVisible) startAutoplay();
284          else stopAutoplay();
285        });
286      },
287      { threshold: [0, 0.08, 0.2] }
288    );
289    sectionIo.observe(root);
290  }
291
292  startAutoplay();
293}
294
295window.__initHeroShowcase = initHeroShowcase;
296
297document.addEventListener("DOMContentLoaded", () => {
298  document.querySelectorAll("[data-hero-showcase]").forEach(initHeroShowcase);
299});

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.