Merge pull request #87 from tfwmedia/main-mkdocs
Adding slideshow js file
This commit is contained in:
@@ -0,0 +1,221 @@
|
|||||||
|
// Slideshow functionality for FAQ answers - OPTIMIZED VERSION
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', initSlideshows);
|
||||||
|
document.addEventListener('DOMContentSwap', initSlideshows);
|
||||||
|
document.addEventListener('mdContentChanged', initSlideshows);
|
||||||
|
|
||||||
|
// Track initialized slideshows to prevent double-initialization
|
||||||
|
const initializedSlideshows = new Set();
|
||||||
|
|
||||||
|
// Function to initialize all slideshows on the page
|
||||||
|
function initSlideshows() {
|
||||||
|
const slideshows = document.querySelectorAll('.faq-slideshow');
|
||||||
|
|
||||||
|
if (slideshows.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Slideshows found:', slideshows.length);
|
||||||
|
|
||||||
|
slideshows.forEach((slideshow, slideshowIndex) => {
|
||||||
|
// Create unique ID for this slideshow
|
||||||
|
const slideshowId = `slideshow-${slideshowIndex}`;
|
||||||
|
|
||||||
|
// Skip if already initialized
|
||||||
|
if (initializedSlideshows.has(slideshowId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
slideshow.setAttribute('id', slideshowId);
|
||||||
|
initializedSlideshows.add(slideshowId);
|
||||||
|
|
||||||
|
// Get slideshow elements
|
||||||
|
const container = slideshow.querySelector('.faq-slideshow-container');
|
||||||
|
const slides = slideshow.querySelectorAll('.faq-slide');
|
||||||
|
const prevBtn = slideshow.querySelector('button.faq-slideshow-prev');
|
||||||
|
const nextBtn = slideshow.querySelector('button.faq-slideshow-next');
|
||||||
|
const dotsContainer = slideshow.querySelector('.faq-slideshow-dots');
|
||||||
|
|
||||||
|
console.log('Slideshow elements found:', {
|
||||||
|
container: !!container,
|
||||||
|
slides: slides.length,
|
||||||
|
prevBtn: !!prevBtn,
|
||||||
|
nextBtn: !!nextBtn,
|
||||||
|
dotsContainer: !!dotsContainer
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!container || slides.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Current slide index
|
||||||
|
let currentSlide = 0;
|
||||||
|
|
||||||
|
// Function to go to a specific slide
|
||||||
|
function goToSlide(index) {
|
||||||
|
console.log(`goToSlide called for slideshow ${slideshowId} with index ${index}`);
|
||||||
|
|
||||||
|
// Handle wrapping around
|
||||||
|
if (index < 0) {
|
||||||
|
index = slides.length - 1;
|
||||||
|
console.log(`Wrapped to last slide: ${index}`);
|
||||||
|
} else if (index >= slides.length) {
|
||||||
|
index = 0;
|
||||||
|
console.log(`Wrapped to first slide: ${index}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update current slide index
|
||||||
|
const previousSlide = currentSlide;
|
||||||
|
currentSlide = index;
|
||||||
|
console.log(`Changing slide from ${previousSlide} to ${currentSlide}`);
|
||||||
|
|
||||||
|
// Move the container to show the current slide (OPTIMIZED)
|
||||||
|
const transformValue = `translateX(-${currentSlide * 100}%)`;
|
||||||
|
console.log(`Setting transform to: ${transformValue}`);
|
||||||
|
container.style.transform = transformValue;
|
||||||
|
|
||||||
|
// Update active dot (OPTIMIZED)
|
||||||
|
if (dotsContainer) {
|
||||||
|
const dots = dotsContainer.querySelectorAll('.faq-slideshow-dot');
|
||||||
|
const activeDot = dotsContainer.querySelector('.faq-slideshow-dot.active');
|
||||||
|
const newActiveDot = dots[currentSlide];
|
||||||
|
|
||||||
|
if (activeDot && activeDot !== newActiveDot) {
|
||||||
|
activeDot.classList.remove('active');
|
||||||
|
}
|
||||||
|
if (newActiveDot && !newActiveDot.classList.contains('active')) {
|
||||||
|
newActiveDot.classList.add('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Updated active dot to index ${currentSlide}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create dots if they don't exist
|
||||||
|
if (dotsContainer && dotsContainer.children.length === 0) {
|
||||||
|
for (let i = 0; i < slides.length; i++) {
|
||||||
|
const dot = document.createElement('div');
|
||||||
|
dot.className = 'faq-slideshow-dot';
|
||||||
|
if (i === 0) {
|
||||||
|
dot.classList.add('active');
|
||||||
|
}
|
||||||
|
dot.addEventListener('click', () => {
|
||||||
|
goToSlide(i);
|
||||||
|
});
|
||||||
|
dotsContainer.appendChild(dot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXED: Only use addEventListener (remove onclick to prevent double execution)
|
||||||
|
if (prevBtn) {
|
||||||
|
console.log('Adding click event listener to prev button for slideshow', slideshowId);
|
||||||
|
|
||||||
|
// Remove any existing handlers
|
||||||
|
prevBtn.onclick = null;
|
||||||
|
|
||||||
|
// Add single event listener
|
||||||
|
prevBtn.addEventListener('click', (e) => {
|
||||||
|
console.log('Prev button clicked for slideshow', slideshowId);
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
goToSlide(currentSlide - 1);
|
||||||
|
}, { once: false, passive: false });
|
||||||
|
|
||||||
|
prevBtn.style.cursor = 'pointer';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextBtn) {
|
||||||
|
console.log('Adding click event listener to next button for slideshow', slideshowId);
|
||||||
|
|
||||||
|
// Remove any existing handlers
|
||||||
|
nextBtn.onclick = null;
|
||||||
|
|
||||||
|
// Add single event listener
|
||||||
|
nextBtn.addEventListener('click', (e) => {
|
||||||
|
console.log('Next button clicked for slideshow', slideshowId);
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
goToSlide(currentSlide + 1);
|
||||||
|
}, { once: false, passive: false });
|
||||||
|
|
||||||
|
nextBtn.style.cursor = 'pointer';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the first slide
|
||||||
|
goToSlide(0);
|
||||||
|
|
||||||
|
// Add keyboard navigation when slideshow is in focus
|
||||||
|
slideshow.tabIndex = 0;
|
||||||
|
slideshow.addEventListener('keydown', (e) => {
|
||||||
|
if (e.key === 'ArrowLeft') {
|
||||||
|
goToSlide(currentSlide - 1);
|
||||||
|
} else if (e.key === 'ArrowRight') {
|
||||||
|
goToSlide(currentSlide + 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add optimized swipe support for touch devices
|
||||||
|
let touchStartX = 0;
|
||||||
|
let touchEndX = 0;
|
||||||
|
|
||||||
|
slideshow.addEventListener('touchstart', (e) => {
|
||||||
|
touchStartX = e.changedTouches[0].screenX;
|
||||||
|
}, { passive: true });
|
||||||
|
|
||||||
|
slideshow.addEventListener('touchend', (e) => {
|
||||||
|
touchEndX = e.changedTouches[0].screenX;
|
||||||
|
handleSwipe();
|
||||||
|
}, { passive: true });
|
||||||
|
|
||||||
|
function handleSwipe() {
|
||||||
|
const swipeThreshold = 50;
|
||||||
|
|
||||||
|
if (touchEndX < touchStartX - swipeThreshold) {
|
||||||
|
goToSlide(currentSlide + 1);
|
||||||
|
} else if (touchEndX > touchStartX + swipeThreshold) {
|
||||||
|
goToSlide(currentSlide - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// MutationObserver to detect when new slideshows are added to the DOM
|
||||||
|
// FIXED: Renamed to avoid conflicts and added throttling
|
||||||
|
const slideshowObserver = new MutationObserver((mutations) => {
|
||||||
|
let hasRelevantMutation = false;
|
||||||
|
|
||||||
|
mutations.forEach((mutation) => {
|
||||||
|
if (mutation.addedNodes && mutation.addedNodes.length > 0) {
|
||||||
|
for (let i = 0; i < mutation.addedNodes.length; i++) {
|
||||||
|
const node = mutation.addedNodes[i];
|
||||||
|
if (node.nodeType === 1 && (node.classList?.contains('faq-slideshow') ||
|
||||||
|
node.querySelector?.('.faq-slideshow'))) {
|
||||||
|
hasRelevantMutation = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (hasRelevantMutation) {
|
||||||
|
setTimeout(initSlideshows, 100);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Start observing the document
|
||||||
|
slideshowObserver.observe(document.body, {
|
||||||
|
childList: true,
|
||||||
|
subtree: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// Additional event listener for dynamically loaded content
|
||||||
|
window.addEventListener('load', function() {
|
||||||
|
setTimeout(initSlideshows, 500);
|
||||||
|
});
|
||||||
|
|
||||||
|
// For Material for MkDocs specific events
|
||||||
|
if (typeof document$.subscribe === 'function') {
|
||||||
|
document$.subscribe(function() {
|
||||||
|
setTimeout(initSlideshows, 100);
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user