PageSourceSearch

https://alliancerm.org/wp-content/plugins/supreme-oxy-widgets/js/resource-hero-slider.js

js alliancerm.org collected 2026-10-02 14:39:39 UTC 5,093 bytes, 170 lines download raw bytes

1/**
2 * Resource Hero Slider
3 * Handles slider functionality for the Resource Hero component
4 */
5(function () {
6  if (window.ResourceHeroSlider) return; // Only define once
7
8  window.ResourceHeroSlider = class {
9    constructor(element) {
10      this.slider = element;
11      if (!this.slider) return;
12
13      // Get slider elements
14      this.track = this.slider.querySelector(".slider-track");
15      this.slides = this.slider.querySelectorAll(".slider-slide");
16      this.prevBtn = this.slider.querySelector(".slider-prev");
17      this.nextBtn = this.slider.querySelector(".slider-next");
18
19      // Exit if there's only one slide
20      if (this.slides.length <= 1) return;
21
22      // Initialize state
23      this.currentSlide = 1; // Start at 1 because of cloned slide
24      this.isAnimating = false;
25      this.slideCount = this.slides.length;
26
27      // Clone first and last slides for infinite loop
28      this.setupInfiniteLoop();
29
30      // Set initial position
31      this.track.style.transform = `translateX(-${100}%)`; // Start at first real slide
32
33      this.init();
34    }
35
36    setupInfiniteLoop() {
37      // Clone first and last slides
38      const firstSlideClone = this.slides[0].cloneNode(true);
39      const lastSlideClone =
40        this.slides[this.slides.length - 1].cloneNode(true);
41
42      // Add classes to identify clones
43      firstSlideClone.classList.add("clone");
44      lastSlideClone.classList.add("clone");
45
46      // Append clones
47      this.track.appendChild(firstSlideClone);
48      this.track.insertBefore(lastSlideClone, this.track.firstChild);
49    }
50
51    init() {
52      // Bind methods
53      this.goToSlide = this.goToSlide.bind(this);
54      this.handlePrevClick = this.handlePrevClick.bind(this);
55      this.handleNextClick = this.handleNextClick.bind(this);
56      this.handleTouchStart = this.handleTouchStart.bind(this);
57      this.handleTouchEnd = this.handleTouchEnd.bind(this);
58      this.updateTrackHeight = this.updateTrackHeight.bind(this);
59
60      // Set initial height
61      this.updateTrackHeight();
62
63      // Add event listeners
64      if (this.prevBtn) {
65        this.prevBtn.addEventListener("click", this.handlePrevClick);
66      }
67
68      if (this.nextBtn) {
69        this.nextBtn.addEventListener("click", this.handleNextClick);
70      }
71
72      // Touch events
73      this.track.addEventListener("touchstart", this.handleTouchStart, {
74        passive: true,
75      });
76      this.track.addEventListener("touchend", this.handleTouchEnd, {
77        passive: true,
78      });
79
80      // Update height on window resize
81      window.addEventListener("resize", this.updateTrackHeight);
82    }
83
84    updateTrackHeight() {
85      // Only adjust height on mobile-sm (screen width <= 576px)
86      if (window.innerWidth > 576) {
87        this.track.style.height = "";
88        return;
89      }
90
91      // Get the current active slide (accounting for cloned slides)
92      const activeSlideIndex = this.currentSlide;
93      const allSlides = this.track.children;
94
95      if (activeSlideIndex >= 0 && activeSlideIndex < allSlides.length) {
96        const activeSlide = allSlides[activeSlideIndex];
97        const slideHeight = activeSlide.offsetHeight;
98
99        // Set the track height to match the current slide
100        this.track.style.height = slideHeight + "px";
101      }
102    }
103
104    goToSlide(index, immediate = false) {
105      if (this.isAnimating || index === this.currentSlide) return;
106      this.isAnimating = true;
107
108      // Update slides with transition
109      if (immediate) {
110        this.track.style.transition = "none";
111      } else {
112        this.track.style.transition = "transform 0.5s ease";
113      }
114
115      // Update transform
116      this.track.style.transform = `translateX(-${index * 100}%)`;
117
118      this.currentSlide = index;
119
120      // Update track height for mobile-sm
121      this.updateTrackHeight();
122
123      // Handle infinite loop transitions
124      setTimeout(() => {
125        this.isAnimating = false;
126
127        // If we're at the last clone, jump to first real slide
128        if (index === this.slideCount + 1) {
129          this.goToSlide(1, true);
130        }
131        // If we're at the first clone, jump to last real slide
132        else if (index === 0) {
133          this.goToSlide(this.slideCount, true);
134        }
135      }, 500);
136    }
137
138    handlePrevClick() {
139      this.goToSlide(this.currentSlide - 1);
140    }
141
142    handleNextClick() {
143      this.goToSlide(this.currentSlide + 1);
144    }
145
146    handleTouchStart(e) {
147      this.touchStartX = e.changedTouches[0].screenX;
148    }
149
150    handleTouchEnd(e) {
151      this.touchEndX = e.changedTouches[0].screenX;
152      const diff = this.touchStartX - this.touchEndX;
153
154      if (Math.abs(diff) > 50) {
155        // Minimum swipe distance
156        if (diff > 0) {
157          this.handleNextClick();
158        } else {
159          this.handlePrevClick();
160        }
161      }
162    }
163  };
164
165  // Initialize all resource hero sliders on the page
166  document.addEventListener("DOMContentLoaded", () => {
167    const sliders = document.querySelectorAll(".featured-resource-slider");
168    sliders.forEach((slider) => new ResourceHeroSlider(slider));
169  });
170})();

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.