diff --git a/themes/one-pager/assets/css/style.css b/themes/one-pager/assets/css/style.css index 8129a16..ee733e8 100644 --- a/themes/one-pager/assets/css/style.css +++ b/themes/one-pager/assets/css/style.css @@ -1571,5 +1571,366 @@ button { letter-spacing: 2px; } } +/* ============================================ + * MUSIC LIGHTBOX + * ============================================ */ + +.music-lightbox { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 10000; + background: rgba(0, 0, 0, 0.92); + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + align-items: center; + justify-content: center; + animation: musicFadeIn 0.4s ease; /* Changed from fadeIn to musicFadeIn */ +} + +.music-lightbox.active { + display: flex; +} + +.music-lightbox-background { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-size: cover; + background-position: center; + opacity: 0.15; + filter: blur(40px); + z-index: 0; +} + +.music-lightbox-content { + position: relative; + z-index: 1; + display: flex; + flex-direction: column; + align-items: center; + gap: 2rem; + max-width: 600px; + width: 90%; + padding: 2rem; +} + +/* Album art image container */ +.music-lightbox-album-art { + position: relative; + width: 280px; + height: 280px; + border-radius: 12px; + overflow: hidden; + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6); + border: 2px solid var(--accent-yellow); + background: rgba(0, 0, 0, 0.3); +} + +.music-lightbox-album-art img { + width: 100%; + height: 100%; + object-fit: cover; + display: block; +} + +/* Album name text in info section */ +.music-lightbox-album-name { + font-family: 'Poppins', sans-serif; + font-weight: 300; + font-size: 0.9rem; + color: rgba(255, 255, 255, 0.6); + letter-spacing: 1px; + margin-bottom: 1rem; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 100%; + text-align: center; +} + + + +.music-lightbox-info { + text-align: center; + width: 100%; + color: white; +} + +.music-lightbox-info h2 { + font-family: 'Poppins', sans-serif; + font-weight: 700; + font-size: 1.8rem; + letter-spacing: -1px; + margin-bottom: 0.3rem; + text-shadow: 0 2px 20px rgba(0, 0, 0, 0.5); +} + +.music-lightbox-artist { + font-family: 'Poppins', sans-serif; + font-weight: 400; + font-size: 1.1rem; + color: var(--accent-yellow); + letter-spacing: 2px; + margin-bottom: 0.2rem; +} + +.music-lightbox-album { + font-family: 'Poppins', sans-serif; + font-weight: 300; + font-size: 0.9rem; + color: rgba(255, 255, 255, 0.6); + letter-spacing: 1px; + margin-bottom: 1rem; +} + +.music-lightbox-progress { + display: flex; + align-items: center; + gap: 1rem; + width: 100%; + max-width: 400px; + margin: 0 auto 1rem; +} + +.music-lightbox-time { + font-family: 'Poppins', sans-serif; + font-weight: 300; + font-size: 0.7rem; + color: rgba(255, 255, 255, 0.6); + letter-spacing: 1px; + min-width: 40px; +} + +.music-lightbox-progress-bar { + flex: 1; + height: 4px; + background: rgba(255, 255, 255, 0.2); + border-radius: 2px; + cursor: pointer; + position: relative; + transition: height 0.2s ease; +} + +.music-lightbox-progress-bar:hover { + height: 6px; +} + +.music-lightbox-progress-fill { + height: 100%; + background: var(--accent-yellow); + border-radius: 2px; + width: 0%; + transition: width 0.1s linear; + box-shadow: 0 0 20px rgba(255, 215, 0, 0.3); +} + +.music-lightbox-controls { + display: flex; + align-items: center; + justify-content: center; + gap: 2rem; +} + +.music-lightbox-control-btn { + background: none; + border: none; + color: white; + font-size: 1.8rem; + cursor: pointer; + transition: all 0.3s ease; + padding: 0.5rem; + border-radius: 50%; + width: 60px; + height: 60px; + display: flex; + align-items: center; + justify-content: center; + opacity: 0.7; +} + +.music-lightbox-control-btn:hover { + opacity: 1; + transform: scale(1.1); + background: rgba(255, 255, 255, 0.1); +} + +.music-lightbox-control-btn.play-btn { + background: var(--accent-yellow); + color: var(--accent-black); + font-size: 1.8rem; + width: 70px; + height: 70px; + opacity: 1; + box-shadow: 0 4px 30px rgba(255, 215, 0, 0.3); +} + +.music-lightbox-control-btn.play-btn:hover { + transform: scale(1.1); + box-shadow: 0 8px 40px rgba(255, 215, 0, 0.5); +} + +.music-lightbox-close { + position: fixed; + top: 20px; + right: 30px; + z-index: 10001; + background: none; + border: none; + color: white; + font-size: 2.5rem; + cursor: pointer; + transition: all 0.3s ease; + opacity: 0.6; +} + +.music-lightbox-close:hover { + opacity: 1; + transform: rotate(90deg); +} + +/* Responsive music lightbox */ +@media (max-width: 768px) { + .music-lightbox-album { + width: 200px; + height: 200px; + } + + .music-lightbox-info h2 { + font-size: 1.4rem; + } + + .music-lightbox-control-btn { + width: 50px; + height: 50px; + font-size: 1.4rem; + } + + .music-lightbox-control-btn.play-btn { + width: 60px; + height: 60px; + font-size: 1.6rem; + } + + .music-lightbox-play-btn { + width: 60px; + height: 60px; + font-size: 2rem; + } + + .music-lightbox-close { + font-size: 2rem; + top: 15px; + right: 20px; + } +} + +@media (max-width: 480px) { + .music-lightbox-album { + width: 160px; + height: 160px; + } + + .music-lightbox-info h2 { + font-size: 1.2rem; + } + + .music-lightbox-controls { + gap: 1rem; + } + + .music-lightbox-control-btn { + width: 40px; + height: 40px; + font-size: 1.2rem; + } + + .music-lightbox-control-btn.play-btn { + width: 50px; + height: 50px; + font-size: 1.4rem; + } +} + +@keyframes musicFadeIn { + from { opacity: 0; transform: scale(0.95); } + to { opacity: 1; transform: scale(1); } +} + +/* Music card play overlay */ +.music-image-wrapper { + position: relative; + overflow: hidden; + border-radius: 8px; +} + +.music-image { + width: 100%; + height: 200px; + object-fit: cover; + display: block; + transition: transform 0.3s ease; +} + +.music-card:hover .music-image { + transform: scale(1.03); +} + +.music-play-overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + background: rgba(0, 0, 0, 0.4); + opacity: 0; + transition: opacity 0.3s ease; + cursor: pointer; +} + +.music-card:hover .music-play-overlay { + opacity: 1; +} + +.music-play-circle { + width: 60px; + height: 60px; + border-radius: 50%; + background: var(--accent-yellow); + color: var(--accent-black); + display: flex; + align-items: center; + justify-content: center; + font-size: 1.8rem; + border: 3px solid rgba(255, 255, 255, 0.3); + box-shadow: 0 4px 30px rgba(255, 215, 0, 0.3); + transition: all 0.3s ease; +} + +.music-play-circle:hover { + transform: scale(1.1); + box-shadow: 0 8px 40px rgba(255, 215, 0, 0.5); +} + +.music-card.clickable { + cursor: pointer; +} + +.music-card.clickable .music-image { + cursor: pointer; +} + +/* Hide default audio controls on card */ +.music-card audio { + display: none; +} /* ============ END CYBERPUNK FOOTER ============ */ diff --git a/themes/one-pager/assets/js/scripts.js b/themes/one-pager/assets/js/scripts.js index 37cbdcf..ec69201 100644 --- a/themes/one-pager/assets/js/scripts.js +++ b/themes/one-pager/assets/js/scripts.js @@ -31,37 +31,13 @@ function isAllowedArtist(artist) { } // ============================================ -// 2. CUSTOM LIGHTBOX (UPDATED) +// 2. PHOTO LIGHTBOX // ============================================ let allPicturesArray = []; let currentPhotoIndex = 0; -// Helper function to create a picture element -function createPictureElement(picture) { - const item = document.createElement('div'); - item.className = 'photo-item'; - item.dataset.image = picture.url; - item.dataset.alt = picture.alt; - item.dataset.created = picture.created_at; - item.dataset.pubkey = picture.pubkey || ''; - - const date = new Date(picture.created_at * 1000); - const dateStr = date.toLocaleDateString('en-US', { - year: 'numeric', month: 'short', day: 'numeric' - }); - item.dataset.date = dateStr; - - item.innerHTML = ` - ${picture.url ? `${picture.alt}` : ''} -
📅 ${dateStr}
- `; - - return item; -} - -// Open lightbox -function openLightbox(index) { +function openPhotoLightbox(index) { const lightbox = document.getElementById('customLightbox'); const lightboxImage = document.getElementById('lightboxImage'); const lightboxCaption = document.getElementById('lightboxCaption'); @@ -75,57 +51,46 @@ function openLightbox(index) { currentPhotoIndex = index; const photo = allPicturesArray[currentPhotoIndex]; - lightboxImage.src = photo.url; lightboxImage.alt = photo.alt; lightboxCaption.textContent = photo.alt; + let metaText = ''; const date = new Date(photo.created_at * 1000); const dateStr = date.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' }); + if (dateStr) metaText += `📅 ${dateStr}`; + if (photo.pubkey) { + if (metaText) metaText += ' | '; + metaText += `🖊️ ${photo.pubkey}`; + } - let metaText = `📅 ${dateStr}`; - - lightboxMeta.textContent = metaText; - + lightboxMeta.textContent = metaText || '📅 No date available'; lightboxCounter.textContent = `${currentPhotoIndex + 1} / ${allPicturesArray.length}`; lightbox.classList.add('active'); document.body.style.overflow = 'hidden'; - - // Preload next and previous images - preloadAdjacentImages(currentPhotoIndex); } -function preloadAdjacentImages(index) { - const nextIndex = (index + 1) % allPicturesArray.length; - if (nextIndex !== index) { - const nextImg = new Image(); - nextImg.src = allPicturesArray[nextIndex].url; - } - - const prevIndex = (index - 1 + allPicturesArray.length) % allPicturesArray.length; - if (prevIndex !== index) { - const prevImg = new Image(); - prevImg.src = allPicturesArray[prevIndex].url; - } -} - -// Close lightbox -function closeLightbox() { +function closePhotoLightbox() { const lightbox = document.getElementById('customLightbox'); if (!lightbox) return; lightbox.classList.remove('active'); document.body.style.overflow = ''; } -// Navigate -function prevPhoto() { openLightbox(currentPhotoIndex - 1); } -function nextPhoto() { openLightbox(currentPhotoIndex + 1); } +function prevPhoto() { + if (allPicturesArray.length === 0) return; + openPhotoLightbox(currentPhotoIndex - 1); +} -// Initialize lightbox event listeners -function initLightbox() { +function nextPhoto() { + if (allPicturesArray.length === 0) return; + openPhotoLightbox(currentPhotoIndex + 1); +} + +function initPhotoLightbox() { const lightbox = document.getElementById('customLightbox'); const lightboxClose = document.getElementById('lightboxClose'); const lightboxPrev = document.getElementById('lightboxPrev'); @@ -133,50 +98,62 @@ function initLightbox() { if (!lightbox) return; - // Photo click listeners + // Remove old listeners by cloning + const newClose = lightboxClose.cloneNode(true); + const newPrev = lightboxPrev.cloneNode(true); + const newNext = lightboxNext.cloneNode(true); + + lightboxClose.parentNode.replaceChild(newClose, lightboxClose); + lightboxPrev.parentNode.replaceChild(newPrev, lightboxPrev); + lightboxNext.parentNode.replaceChild(newNext, lightboxNext); + + // Add new listeners + newClose.addEventListener('click', closePhotoLightbox); + newPrev.addEventListener('click', prevPhoto); + newNext.addEventListener('click', nextPhoto); + + // Click outside to close + lightbox.removeEventListener('click', handlePhotoClick); + lightbox.addEventListener('click', handlePhotoClick); + + // Keyboard controls + document.removeEventListener('keydown', handlePhotoKeydown); + document.addEventListener('keydown', handlePhotoKeydown); + + // Setup photo click listeners document.querySelectorAll('.photo-item img').forEach((img) => { - img.removeEventListener('click', img._lightboxClick); - img._lightboxClick = function(e) { + img.removeEventListener('click', img._photoClick); + img._photoClick = function(e) { e.preventDefault(); const url = this.src; const fullIndex = allPicturesArray.findIndex(p => p.url === url); if (fullIndex !== -1) { - openLightbox(fullIndex); + openPhotoLightbox(fullIndex); } }; - img.addEventListener('click', img._lightboxClick); + img.addEventListener('click', img._photoClick); }); - - // Control listeners - lightboxClose.removeEventListener('click', closeLightbox); - lightboxClose.addEventListener('click', closeLightbox); - - lightboxPrev.removeEventListener('click', prevPhoto); - lightboxPrev.addEventListener('click', prevPhoto); - - lightboxNext.removeEventListener('click', nextPhoto); - lightboxNext.addEventListener('click', nextPhoto); - - // Keyboard controls - document.removeEventListener('keydown', handleLightboxKeydown); - document.addEventListener('keydown', handleLightboxKeydown); - - // Click outside to close - lightbox.removeEventListener('click', handleLightboxClick); - lightbox.addEventListener('click', handleLightboxClick); } -function handleLightboxKeydown(e) { +function handlePhotoKeydown(e) { const lightbox = document.getElementById('customLightbox'); if (!lightbox || !lightbox.classList.contains('active')) return; - if (e.key === 'Escape') closeLightbox(); - else if (e.key === 'ArrowLeft') prevPhoto(); - else if (e.key === 'ArrowRight') nextPhoto(); + + if (e.key === 'Escape') { + e.preventDefault(); + closePhotoLightbox(); + } else if (e.key === 'ArrowLeft') { + e.preventDefault(); + prevPhoto(); + } else if (e.key === 'ArrowRight') { + e.preventDefault(); + nextPhoto(); + } } -function handleLightboxClick(e) { +function handlePhotoClick(e) { const lightbox = document.getElementById('customLightbox'); - if (e.target === lightbox) closeLightbox(); + if (e.target === lightbox) closePhotoLightbox(); } // ============================================ @@ -202,48 +179,104 @@ function renderMusicTracks(tracks, containerId, randomize = false) { return; } - let selected; - if (randomize) { - const shuffled = shuffleArray(filteredTracks); - selected = shuffled.slice(0, 6); - } else { - const sorted = [...filteredTracks].sort((a, b) => b.created_at - a.created_at); - selected = sorted.slice(0, 6); - } - - container.innerHTML = ''; - - selected.forEach(track => { - let title = '', url = '', image = '', artist = '', album = '', - genreTags = [], alt = '', content = ''; - + // Build playlist from ALL filtered tracks + window.musicPlaylist = []; + filteredTracks.forEach(track => { + let title = '', url = '', image = '', artist = '', album = '', duration = ''; if (track.tags) { track.tags.forEach(tag => { const key = tag[0]; const value = tag[1]; - if (key === 'title') title = value; else if (key === 'url') url = value; else if (key === 'image') image = value; else if (key === 'artist') artist = value; else if (key === 'album') album = value; - else if (key === 't') genreTags.push(value); - else if (key === 'alt') alt = value; + else if (key === 'duration') duration = parseFloat(value); }); } - content = track.content || ''; + if (url) { + window.musicPlaylist.push({ + title: title || 'Untitled', + url: url, + image: image || '', + artist: artist || 'Unknown Artist', + album: album || '', + duration: duration || 0, + created_at: track.created_at || 0 + }); + } + }); + // Randomize or sort the playlist + if (randomize) { + window.musicPlaylist = shuffleArray(window.musicPlaylist); + } else { + window.musicPlaylist.sort((a, b) => (b.created_at || 0) - (a.created_at || 0)); + } + + // Render only 6 cards + const displayTracks = window.musicPlaylist.slice(0, 6); + + container.innerHTML = ''; + + displayTracks.forEach((track, index) => { const card = document.createElement('div'); - card.className = 'music-card'; + card.className = 'music-card clickable'; + card.dataset.playlistIndex = index; + + // Click on card opens lightbox + card.addEventListener('click', function(e) { + if (e.target.closest('audio') || e.target.closest('.lyrics-toggle') || e.target.closest('.lyrics')) { + return; + } + const idx = parseInt(this.dataset.playlistIndex); + if (!isNaN(idx) && idx >= 0) { + openMusicLightbox(idx); + } + }); + + // Find genre tags from the original track data + let genreTags = []; + let content = ''; + let alt = ''; + + // Find the original track data to get tags and content + const originalTrack = filteredTracks.find(t => { + let url = ''; + if (t.tags) { + t.tags.forEach(tag => { + if (tag[0] === 'url') url = tag[1]; + }); + } + return url === track.url; + }); + + if (originalTrack && originalTrack.tags) { + originalTrack.tags.forEach(tag => { + const key = tag[0]; + const value = tag[1]; + if (key === 't') genreTags.push(value); + if (key === 'alt') alt = value; + }); + content = originalTrack.content || ''; + } let cardHTML = ` - ${image ? `${title}` : ''} -
-

${title || 'Untitled'}

- ${artist ? `

${artist}

` : ''} - ${album ? `

${album}

` : ''} +
+
+ ${track.image ? `${track.title}` : ''} +
+
+ +
+
+
+
+

${track.title}

+ ${track.artist ? `

${track.artist}

` : ''} + ${track.album ? `

${track.album}

` : ''}
- ${url ? `` : ''} ${genreTags.length > 0 ? `
${genreTags.map(t => `${t}`).join('')} @@ -253,6 +286,7 @@ function renderMusicTracks(tracks, containerId, randomize = false) { ` : ''} +
`; card.innerHTML = cardHTML; @@ -283,15 +317,16 @@ function handleLyricsToggle() { } // ============================================ -// 4. PICTURES RENDERER (UPDATED) +// 4. PICTURES RENDERER // ============================================ function renderRandomPictures(picturesData, containerId, randomize = false) { const container = document.getElementById(containerId); if (!container) return; - // Flatten all pictures from all events + // First, flatten all pictures from all events but keep track of which event they belong to let allPictures = []; + let allEvents = []; picturesData.forEach(event => { const imetaTags = []; @@ -302,6 +337,9 @@ function renderRandomPictures(picturesData, containerId, randomize = false) { }); if (imetaTags.length > 0) { + let firstImage = null; + let eventImages = []; + imetaTags.forEach(imetaTag => { let imageUrl = ''; let alt = event.content || ''; @@ -318,14 +356,28 @@ function renderRandomPictures(picturesData, containerId, randomize = false) { }); if (imageUrl) { - allPictures.push({ + const pictureData = { url: imageUrl, alt: alt, created_at: event.created_at, - pubkey: event.pubkey - }); + pubkey: event.pubkey, + event_id: event.id + }; + eventImages.push(pictureData); + allPictures.push(pictureData); + if (!firstImage) { + firstImage = pictureData; + } } }); + + if (firstImage) { + allEvents.push({ + event_id: event.id, + created_at: event.created_at, + firstImage: firstImage + }); + } } else { let imageUrl = ''; let alt = event.content || ''; @@ -341,40 +393,68 @@ function renderRandomPictures(picturesData, containerId, randomize = false) { }); if (imageUrl) { - allPictures.push({ + const pictureData = { url: imageUrl, alt: alt, created_at: event.created_at, - pubkey: event.pubkey + pubkey: event.pubkey, + event_id: event.id + }; + allPictures.push(pictureData); + allEvents.push({ + event_id: event.id, + created_at: event.created_at, + firstImage: pictureData }); } } }); - // Sort or shuffle - let sortedPictures; + // Store ALL pictures in the global array for the lightbox + allPicturesArray = allPictures; + + // Sort events by created_at (newest first) + const sortedEvents = [...allEvents].sort((a, b) => b.created_at - a.created_at); + + // Select which events to display (6 max) + let displayEvents; if (randomize) { - sortedPictures = shuffleArray(allPictures); + const shuffled = shuffleArray([...sortedEvents]); + displayEvents = shuffled.slice(0, 6); } else { - sortedPictures = [...allPictures].sort((a, b) => b.created_at - a.created_at); + displayEvents = sortedEvents.slice(0, 6); } - // Store all pictures globally for the lightbox - allPicturesArray = sortedPictures; - - // Show first 6, or all if less than 6 - const initialCount = Math.min(6, sortedPictures.length); - const selected = sortedPictures.slice(0, initialCount); - container.innerHTML = ''; - selected.forEach(picture => { - const item = createPictureElement(picture); + displayEvents.forEach((event, index) => { + const picture = event.firstImage; + if (!picture) return; + + const item = document.createElement('div'); + item.className = 'photo-item'; + item.dataset.image = picture.url; + item.dataset.alt = picture.alt; + item.dataset.index = index; + item.dataset.eventId = event.event_id; + + const date = new Date(picture.created_at * 1000); + const dateStr = date.toLocaleDateString('en-US', { + year: 'numeric', month: 'short', day: 'numeric' + }); + item.dataset.date = dateStr; + item.dataset.pubkey = picture.pubkey || ''; + + item.innerHTML = ` + ${picture.url ? `${picture.alt}` : ''} +
📅 ${dateStr}
+ `; + container.appendChild(item); }); - // Initialize lightbox - initLightbox(); + // Initialize photo lightbox + initPhotoLightbox(); } // ============================================ @@ -461,7 +541,10 @@ function renderRandomVideos(videosData, containerId, randomize = false) { // ============================================ function refreshMusic() { - if (window.allMusicData) renderMusicTracks(window.allMusicData, 'musicGrid', true); + if (window.allMusicData) { + window.musicPlaylist = []; + renderMusicTracks(window.allMusicData, 'musicGrid', true); + } } function refreshPictures() { @@ -473,7 +556,236 @@ function refreshVideos() { } // ============================================ -// 7. DOM CONTENT LOADED +// 7. MUSIC LIGHTBOX +// ============================================ + +let currentMusicIndex = 0; +let musicPlayer = null; + +// Open music lightbox +function openMusicLightbox(index) { + if (!window.musicPlaylist || window.musicPlaylist.length === 0) return; + + // Stop any existing playback + if (musicPlayer) { + musicPlayer.pause(); + musicPlayer.remove(); + musicPlayer = null; + } + + if (index < 0) index = window.musicPlaylist.length - 1; + if (index >= window.musicPlaylist.length) index = 0; + currentMusicIndex = index; + + const track = window.musicPlaylist[currentMusicIndex]; + if (!track) return; + + // Get elements + const lightbox = document.getElementById('musicLightbox'); + const bg = document.getElementById('musicLightboxBg'); + const img = document.getElementById('musicLightboxImage'); + const title = document.getElementById('musicLightboxTitle'); + const artist = document.getElementById('musicLightboxArtist'); + const album = document.getElementById('musicLightboxAlbum'); + const durationDisplay = document.getElementById('musicLightboxDuration'); + const currentTimeDisplay = document.getElementById('musicLightboxCurrentTime'); + const progressFill = document.getElementById('musicLightboxProgressFill'); + const playBtn2 = document.getElementById('musicLightboxPlayBtn2'); + const playIcon2 = document.getElementById('musicPlayIcon2'); + + // Set album art + const artUrl = track.image || '/images/default-album.jpg'; + img.src = artUrl; + bg.style.backgroundImage = `url(${artUrl})`; + + // Set info + title.textContent = track.title || 'Untitled'; + artist.textContent = track.artist || 'Unknown Artist'; + album.textContent = track.album || ''; + + // Reset progress + progressFill.style.width = '0%'; + currentTimeDisplay.textContent = '0:00'; + durationDisplay.textContent = track.duration ? formatTime(track.duration) : '0:00'; + + // Set play buttons to play state + playIcon2.textContent = '▶'; + + // Create audio player + musicPlayer = new Audio(track.url); + musicPlayer.preload = 'metadata'; + + // When metadata loaded, update duration + musicPlayer.addEventListener('loadedmetadata', function() { + durationDisplay.textContent = formatTime(this.duration); + }); + + // Track ended - go to next + musicPlayer.addEventListener('ended', function() { + nextMusicTrack(); + }); + + // Update progress + musicPlayer.addEventListener('timeupdate', function() { + const percent = (this.currentTime / this.duration) * 100; + progressFill.style.width = `${percent}%`; + currentTimeDisplay.textContent = formatTime(this.currentTime); + }); + + // Show lightbox + lightbox.classList.add('active'); + document.body.style.overflow = 'hidden'; + + // Auto-play + playMusic(); +} + +// Play music +function playMusic() { + if (!musicPlayer) return; + + musicPlayer.play() + .then(() => { + document.getElementById('musicPlayIcon2').textContent = '⏸'; + }) + .catch(e => { + console.log('Playback prevented:', e); + }); +} + +// Pause music +function pauseMusic() { + if (!musicPlayer) return; + musicPlayer.pause(); + document.getElementById('musicPlayIcon2').textContent = '▶'; +} + +// Toggle play/pause +function toggleMusic() { + if (!musicPlayer) return; + if (musicPlayer.paused) { + playMusic(); + } else { + pauseMusic(); + } +} + +// Next track +function nextMusicTrack() { + openMusicLightbox(currentMusicIndex + 1); +} + +// Previous track +function prevMusicTrack() { + openMusicLightbox(currentMusicIndex - 1); +} + +// Close music lightbox +function closeMusicLightbox() { + const lightbox = document.getElementById('musicLightbox'); + if (!lightbox) return; + + if (musicPlayer) { + musicPlayer.pause(); + musicPlayer.remove(); + musicPlayer = null; + } + + lightbox.classList.remove('active'); + document.body.style.overflow = ''; +} + +// Format time (seconds to MM:SS) +function formatTime(seconds) { + if (!seconds || isNaN(seconds)) return '0:00'; + const mins = Math.floor(seconds / 60); + const secs = Math.floor(seconds % 60); + return `${mins}:${secs.toString().padStart(2, '0')}`; +} + +// Initialize music lightbox event listeners +function initMusicLightbox() { + const lightbox = document.getElementById('musicLightbox'); + const closeBtn = document.getElementById('musicLightboxClose'); + const playBtn2 = document.getElementById('musicLightboxPlayBtn2'); + const prevBtn = document.getElementById('musicLightboxPrev'); + const nextBtn = document.getElementById('musicLightboxNext'); + const progressBar = document.getElementById('musicLightboxProgressBar'); + + if (!lightbox) return; + + // Remove old listeners by cloning + const newClose = closeBtn.cloneNode(true); + const newPlayBtn2 = playBtn2.cloneNode(true); + const newPrev = prevBtn.cloneNode(true); + const newNext = nextBtn.cloneNode(true); + const newProgressBar = progressBar.cloneNode(true); + + closeBtn.parentNode.replaceChild(newClose, closeBtn); + playBtn2.parentNode.replaceChild(newPlayBtn2, playBtn2); + prevBtn.parentNode.replaceChild(newPrev, prevBtn); + nextBtn.parentNode.replaceChild(newNext, nextBtn); + progressBar.parentNode.replaceChild(newProgressBar, progressBar); + + // Close button + newClose.addEventListener('click', closeMusicLightbox); + + // Click outside to close (on the background) + lightbox.addEventListener('click', function(e) { + if (e.target === lightbox) { + closeMusicLightbox(); + } + }); + + // Play button + newPlayBtn2.addEventListener('click', function(e) { + e.stopPropagation(); + toggleMusic(); + }); + + // Previous/Next + newPrev.addEventListener('click', function(e) { + e.stopPropagation(); + prevMusicTrack(); + }); + + newNext.addEventListener('click', function(e) { + e.stopPropagation(); + nextMusicTrack(); + }); + + // Progress bar click to seek + newProgressBar.addEventListener('click', function(e) { + if (!musicPlayer) return; + const rect = this.getBoundingClientRect(); + const x = e.clientX - rect.left; + const percent = x / rect.width; + musicPlayer.currentTime = percent * musicPlayer.duration; + }); + + // Keyboard controls + document.addEventListener('keydown', function(e) { + const lightbox = document.getElementById('musicLightbox'); + if (!lightbox || !lightbox.classList.contains('active')) return; + + if (e.key === 'Escape') { + e.preventDefault(); + closeMusicLightbox(); + } else if (e.key === ' ' || e.key === 'Space') { + e.preventDefault(); + toggleMusic(); + } else if (e.key === 'ArrowLeft') { + e.preventDefault(); + prevMusicTrack(); + } else if (e.key === 'ArrowRight') { + e.preventDefault(); + nextMusicTrack(); + } + }); +} + +// ============================================ +// 8. DOM CONTENT LOADED // ============================================ document.addEventListener('DOMContentLoaded', function() { @@ -520,7 +832,7 @@ document.addEventListener('DOMContentLoaded', function() { }); }); - // Smooth scrolling for navigation links + // Smooth scrolling for navigation links (both main nav and sticky nav) document.querySelectorAll('nav a').forEach(link => { link.addEventListener('click', function(e) { e.preventDefault(); @@ -545,14 +857,15 @@ document.addEventListener('DOMContentLoaded', function() { // Initialize Pictures (chronological, not randomized) if (window.allPicturesData && window.allPicturesData.length > 0) { renderRandomPictures(window.allPicturesData, 'photoGrid', false); - } else { - initLightbox(); } // Initialize Videos (chronological, not randomized) if (window.allVideosData && window.allVideosData.length > 0) { renderRandomVideos(window.allVideosData, 'videoGrid', false); } + + // Initialize music lightbox + initMusicLightbox(); }); console.log('✅ Site initialized successfully!'); diff --git a/themes/one-pager/layouts/index.html b/themes/one-pager/layouts/index.html index 6d27d91..fda64ef 100644 --- a/themes/one-pager/layouts/index.html +++ b/themes/one-pager/layouts/index.html @@ -51,6 +51,43 @@
1 / 1
+ +
+
+ + +
+
+ Album art +
+ + +
+

Title

+

Artist

+

Album

+ +
+ +
+ 0:00 +
+
+
+ 0:00 +
+ +
+ + + +
+
+
+
+ {{ $js := resources.Get "js/scripts.js" | resources.Minify | fingerprint }}