-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpresentation-manager.js
More file actions
219 lines (185 loc) · 6.87 KB
/
presentation-manager.js
File metadata and controls
219 lines (185 loc) · 6.87 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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
let currentSlideIndex = 0;
let manifest = null;
let enabledSlides = [];
const slideContainer = document.getElementById('slideContainer');
// Cache for loaded slides
const slideCache = new Map();
// Load the manifest
async function loadManifest() {
try {
const response = await fetch('slides/manifest.json');
if (!response.ok) {
throw new Error('Failed to load manifest');
}
manifest = await response.json();
// Filter enabled slides
enabledSlides = manifest.slides.filter(slide => slide.enabled);
// Update total slides display
document.getElementById('totalSlides').textContent = enabledSlides.length;
return manifest;
} catch (error) {
console.error('Error loading manifest:', error);
return null;
}
}
async function loadSlide(slideIndex) {
const slide = enabledSlides[slideIndex];
if (!slide) {
return `<h2>Error</h2><p>Slide not found at index ${slideIndex}</p>`;
}
const cacheKey = slide.id;
// Check cache first
if (slideCache.has(cacheKey)) {
return slideCache.get(cacheKey);
}
try {
const response = await fetch(`slides/${slide.file}`);
if (!response.ok) {
throw new Error(`Failed to load slide ${slide.id} (${slide.file})`);
}
const slideContent = await response.text();
// Cache the slide content
slideCache.set(cacheKey, slideContent);
return slideContent;
} catch (error) {
console.error('Error loading slide:', error);
return `<h2>Error Loading Slide</h2><p>Could not load "${slide.title}" (${slide.file})</p>`;
}
}
async function showSlide(index) {
const slide = enabledSlides[index];
if (!slide) {
console.error('No slide found at index:', index);
return;
}
// Add loading state
slideContainer.classList.add('loading');
try {
const slideContent = await loadSlide(index);
slideContainer.innerHTML = slideContent;
// Apply special class for final slide
if (slide.id === 'finale') {
slideContainer.classList.add('final-slide');
} else {
slideContainer.classList.remove('final-slide');
}
// Initialize any slide-specific JavaScript
initializeSlideInteractions();
} catch (error) {
console.error('Error showing slide:', error);
slideContainer.innerHTML = `<h2>Error</h2><p>Could not load slide "${slide.title}"</p>`;
} finally {
slideContainer.classList.remove('loading');
}
// Update slide counter (1-based display)
document.getElementById('currentSlide').textContent = index + 1;
// Update navigation buttons
document.getElementById('prevBtn').disabled = index === 0;
document.getElementById('nextBtn').disabled = index === enabledSlides.length - 1;
}
function initializeSlideInteractions() {
// Stop any existing auto-progress animation
if (typeof stopAutoProgress === 'function') {
stopAutoProgress();
}
// Enhanced intersection observer for scroll items with status tracking
const scrollItems = document.querySelectorAll('.scroll-item');
if (scrollItems.length > 0) {
const watchingCountEl = document.getElementById('watching-count');
const visibleCountEl = document.getElementById('visible-count');
// Update watching count immediately
if (watchingCountEl) {
watchingCountEl.textContent = scrollItems.length;
}
const updateVisibleCount = () => {
if (visibleCountEl) {
const visibleItems = document.querySelectorAll('.scroll-item.visible');
visibleCountEl.textContent = visibleItems.length;
}
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
const badge = entry.target.querySelector('.visibility-badge');
if (entry.isIntersecting) {
// Add visible class with slight delay for dramatic effect
setTimeout(() => {
entry.target.classList.add('visible');
if (badge) {
badge.textContent = 'VISIBLE';
}
// Update count after DOM changes
updateVisibleCount();
}, 100);
} else {
// Remove visible class when not intersecting
entry.target.classList.remove('visible');
if (badge) {
badge.textContent = 'Hidden';
}
// Update count immediately for hiding
updateVisibleCount();
}
});
}, {
// Enhanced options for better demo visibility
threshold: 0.3, // Trigger when 30% visible
rootMargin: '-20px' // Add some margin for better effect
});
scrollItems.forEach(item => observer.observe(item));
// Add some initial demo instructions via console
console.log('🕵️ Intersection Observer Demo initialized!');
console.log(`👁️ Watching ${scrollItems.length} elements for visibility changes`);
}
// Check if this is the progress slide and start auto-animation
const installProgress = document.getElementById('install');
if (installProgress && typeof startAutoProgress === 'function') {
// Small delay to ensure the slide is fully loaded
setTimeout(() => {
startAutoProgress();
}, 100);
}
// Initialize CSS if() function demo
if (typeof window.demoFunctions !== 'undefined' && window.demoFunctions.initializeIfDemo) {
window.demoFunctions.initializeIfDemo();
}
}
function nextSlide() {
if (currentSlideIndex < enabledSlides.length - 1) {
currentSlideIndex++;
showSlide(currentSlideIndex);
}
}
function previousSlide() {
if (currentSlideIndex > 0) {
currentSlideIndex--;
showSlide(currentSlideIndex);
}
}
// Keyboard navigation
document.addEventListener('keydown', (e) => {
if (e.key === 'ArrowRight' || e.key === ' ') {
e.preventDefault();
nextSlide();
} else if (e.key === 'ArrowLeft') {
e.preventDefault();
previousSlide();
}
});
// Preload next slide for better performance
function preloadNextSlide() {
if (currentSlideIndex < enabledSlides.length - 1) {
loadSlide(currentSlideIndex + 1); // Preload next slide
}
}
// Initialize - load manifest and first slide
document.addEventListener('DOMContentLoaded', async () => {
await loadManifest();
await showSlide(0);
preloadNextSlide();
});
// Preload next slide when navigating
const originalNextSlide = nextSlide;
nextSlide = function () {
originalNextSlide();
preloadNextSlide();
};