-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhowto.js
More file actions
180 lines (143 loc) · 5.69 KB
/
Copy pathhowto.js
File metadata and controls
180 lines (143 loc) · 5.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
class FinishedCarousel {
constructor() {
this.currentSlide = 0;
this.totalSlides = 15; // number of slides
this.grid = document.getElementById('finishedGrid');
this.prevBtn = document.getElementById('prevBtn');
this.nextBtn = document.getElementById('nextBtn');
this.isTransitioning = false;
this.slideWidth = 440; // Width of each slide (400px image + 40px padding)
this.init();
}
init() {
this.createInfiniteLoop();
this.setupEventListeners();
this.startAutoPlay();
this.addTouchSupport();
}
createInfiniteLoop() {
const slides = Array.from(this.grid.children);
// Clone last slide and prepend to beginning
const firstClone = slides[slides.length - 1].cloneNode(true);
firstClone.classList.add('clone');
this.grid.insertBefore(firstClone, slides[0]);
// Clone first slide and append to end
const lastClone = slides[0].cloneNode(true);
lastClone.classList.add('clone');
this.grid.appendChild(lastClone);
// Start at the first real slide (index 1 now because of prepended clone)
this.currentSlide = 1;
// To center: move left by (slideIndex * slideWidth) - (carousel center - slide center)
const carouselCenter = 360; // 720px / 2
const slideCenter = 220; // 440px / 2
const centerOffset = carouselCenter - slideCenter; // 140px
const initialTransform = (this.currentSlide * this.slideWidth) - centerOffset;
this.grid.style.transform = `translateX(-${initialTransform}px)`;
this.grid.style.transition = 'none';
}
setupEventListeners() {
this.prevBtn.addEventListener('click', () => this.previousSlide());
this.nextBtn.addEventListener('click', () => this.nextSlide());
// Handle transition end for seamless loop
this.grid.addEventListener('transitionend', () => {
this.handleTransitionEnd();
});
}
goToSlide(slideIndex, withTransition = true) {
if (this.isTransitioning && withTransition) return;
this.isTransitioning = withTransition;
this.currentSlide = slideIndex;
this.grid.style.transition = withTransition ? 'transform 0.5s ease-in-out' : 'none';
// Calculate transform to center the target slide
const carouselCenter = 360; // 720px / 2
const slideCenter = 220; // 440px / 2
const centerOffset = carouselCenter - slideCenter; // 140px
const translateX = (slideIndex * this.slideWidth) - centerOffset;
this.grid.style.transform = `translateX(-${translateX}px)`;
}
nextSlide() {
if (this.isTransitioning) return;
this.goToSlide(this.currentSlide + 1);
}
previousSlide() {
if (this.isTransitioning) return;
this.goToSlide(this.currentSlide - 1);
}
handleTransitionEnd() {
// If on a clone, jump to the real slide instantly (no animation)
if (this.currentSlide === 0) {
this.goToSlide(this.totalSlides, false);
} else if (this.currentSlide === this.totalSlides + 1) {
this.goToSlide(1, false);
}
this.isTransitioning = false;
}
startAutoPlay() {
// Slow autoplay - 12 seconds between slides
this.autoPlayInterval = setInterval(() => {
this.nextSlide();
}, 12000);
const carousel = document.querySelector('.finished-carousel');
carousel.addEventListener('mouseenter', () => {
clearInterval(this.autoPlayInterval);
});
carousel.addEventListener('mouseleave', () => {
this.startAutoPlay();
});
}
addTouchSupport() {
let startX = 0;
let isDragging = false;
this.grid.addEventListener('touchstart', (e) => {
startX = e.touches[0].clientX;
isDragging = true;
});
this.grid.addEventListener('touchmove', (e) => {
if (!isDragging) return;
e.preventDefault();
});
this.grid.addEventListener('touchend', (e) => {
if (!isDragging) return;
isDragging = false;
const endX = e.changedTouches[0].clientX;
const diffX = startX - endX;
if (Math.abs(diffX) > 50) {
if (diffX > 0) {
this.nextSlide();
} else {
this.previousSlide();
}
}
});
}
}
function createSeamlessScroll() {
const track = document.getElementById('testimonials-track');
if (!track) return;
const cards = Array.from(track.children); // static array
// Only clone the original cards, not the clones
for (let i = 0; i < cards.length; i++) {
const clone = cards[i].cloneNode(true);
track.appendChild(clone);
}
}
document.addEventListener('DOMContentLoaded', function () {
// Process Steps
const stepTiles = document.querySelectorAll('.step-tile');
const stepDetails = document.querySelectorAll('.step-detail');
stepTiles.forEach(tile => {
tile.addEventListener('click', function () {
const step = this.getAttribute('data-step');
// Remove active from all
stepTiles.forEach(t => t.classList.remove('active'));
stepDetails.forEach(d => d.classList.remove('active'));
// Add active to selected
this.classList.add('active');
document.querySelector('.step-detail[data-step="' + step + '"]').classList.add('active');
});
});
// Initialize the Finished carousel
new FinishedCarousel();
// Initialise Testimonials Scroll
createSeamlessScroll();
});