// ============================================
// 1. UTILITY FUNCTIONS
// ============================================
// Function to shuffle array (Fisher-Yates)
function shuffleArray(array) {
const shuffled = [...array];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
return shuffled;
}
// Artist filter list
const allowedArtists = [
'εΎ Setto γ»γγ',
'Settoshi Tonami',
'Sethy Bowoy'
];
// Function to check if a track is by an allowed artist
function isAllowedArtist(artist) {
if (!artist) return false;
const normalizedArtist = artist.trim().toLowerCase();
return allowedArtists.some(allowed => {
const normalizedAllowed = allowed.trim().toLowerCase();
return normalizedArtist.includes(normalizedAllowed) ||
normalizedAllowed.includes(normalizedArtist);
});
}
// ============================================
// 2. PHOTO LIGHTBOX
// ============================================
let allPicturesArray = [];
let currentPhotoIndex = 0;
function openPhotoLightbox(index) {
const lightbox = document.getElementById('customLightbox');
const lightboxImage = document.getElementById('lightboxImage');
const lightboxCaption = document.getElementById('lightboxCaption');
const lightboxMeta = document.getElementById('lightboxMeta');
const lightboxCounter = document.getElementById('lightboxCounter');
if (!lightbox || !lightboxImage || allPicturesArray.length === 0) return;
if (index < 0) index = allPicturesArray.length - 1;
if (index >= allPicturesArray.length) index = 0;
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}`;
lightboxMeta.textContent = metaText || 'π
No date available';
lightboxCounter.textContent = `${currentPhotoIndex + 1} / ${allPicturesArray.length}`;
lightbox.classList.add('active');
document.body.style.overflow = 'hidden';
}
function closePhotoLightbox() {
const lightbox = document.getElementById('customLightbox');
if (!lightbox) return;
lightbox.classList.remove('active');
document.body.style.overflow = '';
}
function prevPhoto() {
if (allPicturesArray.length === 0) return;
openPhotoLightbox(currentPhotoIndex - 1);
}
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');
const lightboxNext = document.getElementById('lightboxNext');
if (!lightbox) return;
// 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._photoClick);
img._photoClick = function(e) {
e.preventDefault();
const url = this.src;
const fullIndex = allPicturesArray.findIndex(p => p.url === url);
if (fullIndex !== -1) {
openPhotoLightbox(fullIndex);
}
};
img.addEventListener('click', img._photoClick);
});
}
function handlePhotoKeydown(e) {
const lightbox = document.getElementById('customLightbox');
if (!lightbox || !lightbox.classList.contains('active')) return;
if (e.key === 'Escape') {
e.preventDefault();
closePhotoLightbox();
} else if (e.key === 'ArrowLeft') {
e.preventDefault();
prevPhoto();
} else if (e.key === 'ArrowRight') {
e.preventDefault();
nextPhoto();
}
}
function handlePhotoClick(e) {
const lightbox = document.getElementById('customLightbox');
if (e.target === lightbox) closePhotoLightbox();
}
// ============================================
// 3. MUSIC RENDERER
// ============================================
function renderMusicTracks(tracks, containerId, randomize = false) {
const container = document.getElementById(containerId);
if (!container) return;
const filteredTracks = tracks.filter(track => {
let artist = '';
if (track.tags) {
track.tags.forEach(tag => {
if (tag[0] === 'artist') artist = tag[1];
});
}
return isAllowedArtist(artist);
});
if (filteredTracks.length === 0) {
container.innerHTML = '
No tracks found for the selected artists.
';
return;
}
// Build playlist from ALL filtered tracks
window.musicPlaylist = [];
filteredTracks.forEach(track => {
let title = '', url = '', image = '', artist = '', album = '', duration = '';
// ADD THIS: Store the track ID
const trackId = track.id || '';
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 === 'duration') duration = parseFloat(value);
});
}
if (url) {
window.musicPlaylist.push({
id: trackId, // ADD THIS LINE
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 clickable';
card.dataset.playlistIndex = index;
// Click on card opens lightbox (except when clicking on info button)
card.addEventListener('click', function(e) {
// Don't trigger if clicking on lyrics-toggle or inside lyrics
if (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 || '';
}
// Build the card HTML
let cardHTML = `
${track.image ? `

` : ''}
βΆ
${genreTags.length > 0 ? `
${genreTags.map(t => `${t}`).join('')}
` : ''}
${content ? `
${content.replace(/\n/g, '
')}
` : ''}
`;
card.innerHTML = cardHTML;
container.appendChild(card);
});
initMusicEventListeners();
}
function initMusicEventListeners() {
document.querySelectorAll('.lyrics-toggle').forEach(button => {
button.removeEventListener('click', handleLyricsToggle);
button.addEventListener('click', handleLyricsToggle);
});
}
function handleLyricsToggle(e) {
// Stop the click from bubbling up to the card
e.stopPropagation();
const lyrics = this.nextElementSibling;
if (lyrics && lyrics.classList.contains('lyrics')) {
if (lyrics.style.display === 'none') {
lyrics.style.display = 'block';
this.innerHTML = 'Hide Info';
} else {
lyrics.style.display = 'none';
this.innerHTML = 'Show Info';
}
}
}
// ============================================
// 4. PICTURES RENDERER
// ============================================
function renderRandomPictures(picturesData, containerId, randomize = false) {
const container = document.getElementById(containerId);
if (!container) return;
// 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 = [];
event.tags.forEach(tag => {
if (tag[0] === 'imeta') {
imetaTags.push(tag);
}
});
if (imetaTags.length > 0) {
let firstImage = null;
let eventImages = [];
imetaTags.forEach(imetaTag => {
let imageUrl = '';
let alt = event.content || '';
imetaTag.forEach(item => {
if (typeof item === 'string') {
if (item.startsWith('url ')) {
imageUrl = item.replace('url ', '').trim();
}
if (item.startsWith('alt ')) {
alt = item.replace('alt ', '').trim();
}
}
});
if (imageUrl) {
const pictureData = {
url: imageUrl,
alt: alt,
created_at: event.created_at,
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 || '';
event.tags.forEach(tag => {
if (tag[0] === 'imeta') {
const imetaStr = tag[1];
const urlMatch = imetaStr.match(/url ([^\s]+)/);
if (urlMatch) imageUrl = urlMatch[1];
const altMatch = imetaStr.match(/alt ([^\s]+)/);
if (altMatch) alt = altMatch[1];
}
});
if (imageUrl) {
const pictureData = {
url: imageUrl,
alt: alt,
created_at: event.created_at,
pubkey: event.pubkey,
event_id: event.id
};
allPictures.push(pictureData);
allEvents.push({
event_id: event.id,
created_at: event.created_at,
firstImage: pictureData
});
}
}
});
// 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) {
const shuffled = shuffleArray([...sortedEvents]);
displayEvents = shuffled.slice(0, 6);
} else {
displayEvents = sortedEvents.slice(0, 6);
}
container.innerHTML = '';
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 ? `
` : ''}
π
${dateStr}
`;
container.appendChild(item);
});
// Initialize photo lightbox
initPhotoLightbox();
}
// ============================================
// 5. VIDEOS RENDERER
// ============================================
function renderRandomVideos(videosData, containerId, randomize = false) {
const container = document.getElementById(containerId);
if (!container) return;
let selected;
if (randomize) {
const shuffled = shuffleArray(videosData);
selected = shuffled.slice(0, 2);
} else {
const sorted = [...videosData].sort((a, b) => b.created_at - a.created_at);
selected = sorted.slice(0, 2);
}
container.innerHTML = '';
const posterImage = '/images/videoposter.png';
selected.forEach(video => {
let videoUrl = '', mimeType = 'video/mp4', alt = video.content || '', dim = '';
let isVertical = false;
if (video.tags) {
video.tags.forEach(tag => {
if (tag[0] === 'imeta') {
const imetaStr = tag[1];
const urlMatch = imetaStr.match(/url ([^\s]+)/);
if (urlMatch) videoUrl = urlMatch[1];
const mimeMatch = imetaStr.match(/m ([^\s]+)/);
if (mimeMatch) mimeType = mimeMatch[1];
const altMatch = imetaStr.match(/alt ([^\s]+)/);
if (altMatch) alt = altMatch[1];
const dimMatch = imetaStr.match(/dim ([^\s]+)/);
if (dimMatch) {
dim = dimMatch[1];
const [width, height] = dim.split('x').map(Number);
if (height > width) isVertical = true;
}
}
});
}
const date = new Date(video.created_at * 1000);
const dateStr = date.toLocaleDateString('en-US', {
year: 'numeric', month: 'long', day: 'numeric'
});
const wrapperStyle = isVertical
? 'style="position:relative;padding-bottom:177.78%;height:0;overflow:hidden;background:var(--accent-black);"'
: '';
const videoStyle = isVertical
? 'style="position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;"'
: 'style="width:100%;"';
const html = `
${videoUrl ? `
` : ''}
${alt}
π
${dateStr}
${dim ? `π ${dim}` : ''}
`;
container.insertAdjacentHTML('beforeend', html);
});
}
// ============================================
// 6. REFRESH FUNCTIONS
// ============================================
function refreshMusic() {
if (window.allMusicData) {
window.musicPlaylist = [];
renderMusicTracks(window.allMusicData, 'musicGrid', true);
}
}
function refreshPictures() {
if (window.allPicturesData) renderRandomPictures(window.allPicturesData, 'photoGrid', true);
}
function refreshVideos() {
if (window.allVideosData) renderRandomVideos(window.allVideosData, 'videoGrid', true);
}
// ============================================
// 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');
// Get the lyrics element
const lyricsDisplay = document.getElementById('musicLightboxLyrics');
// Share button - in its own row
const shareBtn = document.getElementById('musicShareBtn');
// Create feedback element if it doesn't exist
let feedbackEl = document.getElementById('shareFeedbackPopout');
if (!feedbackEl) {
feedbackEl = document.createElement('div');
feedbackEl.id = 'shareFeedbackPopout';
feedbackEl.className = 'share-feedback';
feedbackEl.innerHTML = 'β Copied!';
document.body.appendChild(feedbackEl);
}
if (shareBtn) {
shareBtn.onclick = function() {
if (!track.id) {
feedbackEl.textContent = 'β οΈ No ID';
feedbackEl.classList.add('visible');
setTimeout(() => {
feedbackEl.classList.remove('visible');
}, 2000);
return;
}
const shareUrl = `https://nostr.basspistol.org/notes/${track.id}`;
if (navigator.share) {
navigator.share({
title: track.title || 'Music Track',
text: `Check out "${track.title}" by ${track.artist || 'Unknown Artist'}`,
url: shareUrl
}).catch(err => {
console.log('Share cancelled or failed:', err);
});
} else {
navigator.clipboard.writeText(shareUrl).then(() => {
feedbackEl.innerHTML = 'β Copied!';
feedbackEl.classList.add('visible');
setTimeout(() => {
feedbackEl.classList.remove('visible');
}, 2000);
}).catch(err => {
console.error('Could not copy text: ', err);
const textArea = document.createElement('textarea');
textArea.value = shareUrl;
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
feedbackEl.innerHTML = 'β Copied!';
feedbackEl.classList.add('visible');
setTimeout(() => {
feedbackEl.classList.remove('visible');
}, 2000);
} catch (err) {
console.error('Fallback copy failed:', err);
feedbackEl.textContent = 'β οΈ Copy failed';
feedbackEl.classList.add('visible');
setTimeout(() => {
feedbackEl.classList.remove('visible');
}, 2000);
}
document.body.removeChild(textArea);
});
}
};
}
// 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 || '';
// Set lyrics - find the original track data to get content
let lyricsContent = '';
// Find the original track data
const originalTrack = window.allMusicData ? window.allMusicData.find(t => {
let url = '';
if (t.tags) {
t.tags.forEach(tag => {
if (tag[0] === 'url') url = tag[1];
});
}
return url === track.url;
}) : null;
if (originalTrack && originalTrack.content) {
lyricsContent = originalTrack.content;
}
// Display lyrics if they exist
if (lyricsContent) {
lyricsDisplay.innerHTML = lyricsContent.replace(/\n/g, '
');
lyricsDisplay.style.display = 'block';
} else {
lyricsDisplay.style.display = 'none';
}
// 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() {
// Sticky Navigation
const stickyNav = document.getElementById('stickyNav');
const mainHeader = document.querySelector('.main-header');
let lastScrollY = window.scrollY;
let ticking = false;
function updateStickyNav() {
const scrollY = window.scrollY;
const headerHeight = mainHeader ? mainHeader.offsetHeight : 400;
if (scrollY > headerHeight - 100) {
stickyNav.classList.add('visible');
} else {
stickyNav.classList.remove('visible');
}
lastScrollY = scrollY;
}
window.addEventListener('scroll', function() {
if (!ticking) {
window.requestAnimationFrame(function() {
updateStickyNav();
ticking = false;
});
ticking = true;
}
});
setTimeout(updateStickyNav, 100);
// Read More toggle for blog posts
document.querySelectorAll('.read-more-toggle').forEach(button => {
button.addEventListener('click', function() {
const content = this.nextElementSibling;
if (content.style.display === 'none') {
content.style.display = 'block';
this.innerHTML = 'Read Less';
} else {
content.style.display = 'none';
this.innerHTML = 'Read More';
}
});
});
// Smooth scrolling for navigation links (both main nav and sticky nav)
document.querySelectorAll('nav a').forEach(link => {
link.addEventListener('click', function(e) {
e.preventDefault();
const targetId = this.getAttribute('href');
const targetElement = document.querySelector(targetId);
if (targetElement) {
const navHeight = stickyNav.offsetHeight;
const targetPosition = targetElement.getBoundingClientRect().top + window.pageYOffset - navHeight - 20;
window.scrollTo({
top: targetPosition,
behavior: 'smooth'
});
}
});
});
// Initialize Music (chronological, not randomized)
if (window.allMusicData && window.allMusicData.length > 0) {
renderMusicTracks(window.allMusicData, 'musicGrid', false);
}
// Initialize Pictures (chronological, not randomized)
if (window.allPicturesData && window.allPicturesData.length > 0) {
renderRandomPictures(window.allPicturesData, 'photoGrid', false);
}
// 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!');