// Hearthframe Application Logic document.addEventListener('DOMContentLoaded', function() { // Sample data for initial load const samplePhotos = [ 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjAwIiBoZWlnaHQ9IjQwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjZjBmMGYwIi8+PHRleHQgeD0iNTAlIiB5PSI1MCUiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxOCIgZmlsbD0iIzMzMyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZG9taW5hbnQtYmFzaWxpbmU9Im1pZGRsZSI+U2FtcGxlIFBob3RvIDE8L3RleHQ+PC9zdmc+', 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjAwIiBoZWlnaHQ9IjQwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjZjVmNWY1Ii8+PHRleHQgeD0iNTAlIiB5PSI1MCUiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxOCIgZmlsbD0iIzMzMyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZG9taW5hbnQtYmFzaWxpbmU9Im1pZGRsZSI+U2FtcGxlIFBob3RvIDI8L3RleHQ+PC9zdmc+', 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjAwIiBoZWlnaHQ9IjQwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjZjhmOGY4Ii8+PHRleHQgeD0iNTAlIiB5PSI1MCUiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxOCIgZmlsbD0iIzMzMyIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZG9taW5hbnQtYmFzaWxpbmU9Im1pZGRsZSI+U2FtcGxlIFBob3RvIDM8L3RleHQ+PC9zdmc+' ]; // State management let state = { photos: samplePhotos, currentIndex: 0, frameStyle: 'classic', clockStyle: 'digital', transition: 'fade', caption: 'Our family memories', isPlaying: false, intervalId: null }; // DOM Elements const elements = { photoInput: document.getElementById('photo-input'), photoContainer: document.getElementById('photo-container'), dropZone: document.getElementById('drop-zone'), frameSelect: document.getElementById('frame-style'), clockSelect: document.getElementById('clock-style'), transitionSelect: document.getElementById('transition'), captionInput: document.getElementById('caption'), previewBtn: document.getElementById('preview-btn'), downloadBtn: document.getElementById('download-btn'), playBtn: document.getElementById('play-btn'), prevBtn: document.getElementById('prev-btn'), nextBtn: document.getElementById('next-btn'), slideshowContainer: document.getElementById('slideshow'), slideshowImage: document.getElementById('slideshow-image'), slideshowCaption: document.getElementById('slideshow-caption'), slideshowClock: document.getElementById('slideshow-clock'), closeSlideshowBtn: document.getElementById('close-slideshow') }; // Frame styles const frameStyles = { classic: { border: 'solid 20px #8B4513', background: '#f5f5dc' }, modern: { border: 'solid 15px #333', background: '#fff' }, vintage: { border: 'solid 25px #d2b48c', background: '#f0e6d2' }, minimalist: { border: 'solid 10px #eee', background: '#fff' } }; // Initialize the app function init() { setupEventListeners(); renderPhotoGrid(); updateTime(); setInterval(updateTime, 1000); } // Set up event listeners function setupEventListeners() { elements.photoInput.addEventListener('change', handlePhotoUpload); elements.dropZone.addEventListener('click', () => elements.photoInput.click()); elements.dropZone.addEventListener('dragover', handleDragOver); elements.dropZone.addEventListener('dragleave', handleDragLeave); elements.dropZone.addEventListener('drop', handleDrop); elements.frameSelect.addEventListener('change', updateFrameStyle); elements.clockSelect.addEventListener('change', updateClockStyle); elements.transitionSelect.addEventListener('change', updateTransition); elements.captionInput.addEventListener('input', updateCaption); elements.previewBtn.addEventListener('click', toggleSlideshow); elements.downloadBtn.addEventListener('click', downloadFrame); elements.playBtn.addEventListener('click', togglePlay); elements.prevBtn.addEventListener('click', showPrevPhoto); elements.nextBtn.addEventListener('click', showNextPhoto); elements.closeSlideshowBtn.addEventListener('click', closeSlideshow); } // Handle drag over function handleDragOver(event) { event.preventDefault(); elements.dropZone.classList.add('dragover'); } // Handle drag leave function handleDragLeave(event) { event.preventDefault(); elements.dropZone.classList.remove('dragover'); } // Handle drop function handleDrop(event) { event.preventDefault(); elements.dropZone.classList.remove('dragover'); const files = Array.from(event.dataTransfer.files); processFiles(files); } // Handle photo upload function handlePhotoUpload(event) { const files = Array.from(event.target.files); processFiles(files); } // Process uploaded files function processFiles(files) { const imageFiles = files.filter(file => file.type.startsWith('image/')); if (imageFiles.length === 0) return; const newPhotos = []; let processedCount = 0; imageFiles.forEach(file => { const reader = new FileReader(); reader.onload = function(e) { newPhotos.push(e.target.result); processedCount++; if (processedCount === imageFiles.length) { state.photos = [...state.photos, ...newPhotos]; renderPhotoGrid(); } }; reader.readAsDataURL(file); }); } // Render photo grid function renderPhotoGrid() { elements.photoContainer.innerHTML = ''; state.photos.forEach((photo, index) => { const img = document.createElement('img'); img.src = photo; img.alt = `Uploaded photo ${index + 1}`; img.className = 'thumbnail'; elements.photoContainer.appendChild(img); }); } // Update frame style function updateFrameStyle() { state.frameStyle = elements.frameSelect.value; if (elements.slideshowContainer.style.display !== 'none') { applyFrameStyle(); } } // Apply frame style to slideshow function applyFrameStyle() { const style = frameStyles[state.frameStyle]; const slideshowFrame = document.getElementById('slideshow-frame'); if (slideshowFrame) { slideshowFrame.style.border = style.border; slideshowFrame.style.background = style.background; } } // Update clock style function updateClockStyle() { state.clockStyle = elements.clockSelect.value; } // Update transition effect function updateTransition() { state.transition = elements.transitionSelect.value; } // Update caption function updateCaption() { state.caption = elements.captionInput.value; elements.slideshowCaption.textContent = state.caption; } // Toggle slideshow function toggleSlideshow() { if (elements.slideshowContainer.style.display === 'none') { showSlideshow(); } else { closeSlideshow(); } } // Show slideshow function showSlideshow() { elements.slideshowContainer.style.display = 'block'; document.querySelector('.app-container').style.display = 'none'; updateSlideshow(); applyFrameStyle(); } // Close slideshow function closeSlideshow() { elements.slideshowContainer.style.display = 'none'; document.querySelector('.app-container').style.display = 'block'; stopSlideshow(); } // Update slideshow display with proper transitions function updateSlideshow() { if (state.photos.length > 0) { elements.slideshowImage.src = state.photos[state.currentIndex]; elements.slideshowCaption.textContent = state.caption; // Apply transition effect based on selection switch (state.transition) { case 'fade': elements.slideshowImage.style.opacity = '0'; elements.slideshowImage.style.transition = 'opacity 1s ease'; setTimeout(() => { elements.slideshowImage.style.opacity = '1'; }, 50); break; case 'slide': elements.slideshowImage.style.transform = 'translateX(100%)'; elements.slideshowImage.style.transition = 'transform 0.5s ease'; setTimeout(() => { elements.slideshowImage.style.transform = 'translateX(0)'; }, 50); break; case 'none': elements.slideshowImage.style.transition = 'none'; elements.slideshowImage.style.opacity = '1'; elements.slideshowImage.style.transform = 'none'; break; } } } // Show previous photo function showPrevPhoto() { if (state.photos.length > 0) { state.currentIndex = (state.currentIndex - 1 + state.photos.length) % state.photos.length; updateSlideshow(); } } // Show next photo function showNextPhoto() { if (state.photos.length > 0) { state.currentIndex = (state.currentIndex + 1) % state.photos.length; updateSlideshow(); } } // Toggle play/pause function togglePlay() { if (state.isPlaying) { stopSlideshow(); elements.playBtn.textContent = '▶ Play'; } else { startSlideshow(); elements.playBtn.textContent = '⏸ Pause'; } } // Start slideshow function startSlideshow() { state.isPlaying = true; state.intervalId = setInterval(() => { state.currentIndex = (state.currentIndex + 1) % state.photos.length; updateSlideshow(); }, 5000); } // Stop slideshow function stopSlideshow() { state.isPlaying = false; if (state.intervalId) { clearInterval(state.intervalId); state.intervalId = null; } } // Update time display function updateTime() { const now = new Date(); if (state.clockStyle === 'digital') { elements.slideshowClock.textContent = now.toLocaleTimeString(); } else { elements.slideshowClock.textContent = now.toLocaleDateString() + ' ' + now.toLocaleTimeString(); } } // Download frame as HTML file function downloadFrame() { const htmlContent = generateHTML(); const blob = new Blob([htmlContent], { type: 'text/html' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'hearthframe.html'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } // Generate standalone HTML file function generateHTML() { return `