music can haz a lightbox too
This commit is contained in:
parent
18abdfb9e8
commit
bfc5289a7e
3 changed files with 848 additions and 137 deletions
|
|
@ -1571,5 +1571,366 @@ button {
|
||||||
letter-spacing: 2px;
|
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 ============ */
|
/* ============ END CYBERPUNK FOOTER ============ */
|
||||||
|
|
|
||||||
|
|
@ -31,37 +31,13 @@ function isAllowedArtist(artist) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// 2. CUSTOM LIGHTBOX (UPDATED)
|
// 2. PHOTO LIGHTBOX
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|
||||||
let allPicturesArray = [];
|
let allPicturesArray = [];
|
||||||
let currentPhotoIndex = 0;
|
let currentPhotoIndex = 0;
|
||||||
|
|
||||||
// Helper function to create a picture element
|
function openPhotoLightbox(index) {
|
||||||
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 ? `<img src="${picture.url}" alt="${picture.alt}" loading="lazy">` : ''}
|
|
||||||
<div class="photo-date"><span>📅 ${dateStr}</span></div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open lightbox
|
|
||||||
function openLightbox(index) {
|
|
||||||
const lightbox = document.getElementById('customLightbox');
|
const lightbox = document.getElementById('customLightbox');
|
||||||
const lightboxImage = document.getElementById('lightboxImage');
|
const lightboxImage = document.getElementById('lightboxImage');
|
||||||
const lightboxCaption = document.getElementById('lightboxCaption');
|
const lightboxCaption = document.getElementById('lightboxCaption');
|
||||||
|
|
@ -75,57 +51,46 @@ function openLightbox(index) {
|
||||||
currentPhotoIndex = index;
|
currentPhotoIndex = index;
|
||||||
|
|
||||||
const photo = allPicturesArray[currentPhotoIndex];
|
const photo = allPicturesArray[currentPhotoIndex];
|
||||||
|
|
||||||
lightboxImage.src = photo.url;
|
lightboxImage.src = photo.url;
|
||||||
lightboxImage.alt = photo.alt;
|
lightboxImage.alt = photo.alt;
|
||||||
lightboxCaption.textContent = photo.alt;
|
lightboxCaption.textContent = photo.alt;
|
||||||
|
|
||||||
|
let metaText = '';
|
||||||
const date = new Date(photo.created_at * 1000);
|
const date = new Date(photo.created_at * 1000);
|
||||||
const dateStr = date.toLocaleDateString('en-US', {
|
const dateStr = date.toLocaleDateString('en-US', {
|
||||||
year: 'numeric', month: 'short', day: 'numeric'
|
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 || '📅 No date available';
|
||||||
|
|
||||||
lightboxMeta.textContent = metaText;
|
|
||||||
|
|
||||||
lightboxCounter.textContent = `${currentPhotoIndex + 1} / ${allPicturesArray.length}`;
|
lightboxCounter.textContent = `${currentPhotoIndex + 1} / ${allPicturesArray.length}`;
|
||||||
|
|
||||||
lightbox.classList.add('active');
|
lightbox.classList.add('active');
|
||||||
document.body.style.overflow = 'hidden';
|
document.body.style.overflow = 'hidden';
|
||||||
|
|
||||||
// Preload next and previous images
|
|
||||||
preloadAdjacentImages(currentPhotoIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function preloadAdjacentImages(index) {
|
function closePhotoLightbox() {
|
||||||
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() {
|
|
||||||
const lightbox = document.getElementById('customLightbox');
|
const lightbox = document.getElementById('customLightbox');
|
||||||
if (!lightbox) return;
|
if (!lightbox) return;
|
||||||
lightbox.classList.remove('active');
|
lightbox.classList.remove('active');
|
||||||
document.body.style.overflow = '';
|
document.body.style.overflow = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Navigate
|
function prevPhoto() {
|
||||||
function prevPhoto() { openLightbox(currentPhotoIndex - 1); }
|
if (allPicturesArray.length === 0) return;
|
||||||
function nextPhoto() { openLightbox(currentPhotoIndex + 1); }
|
openPhotoLightbox(currentPhotoIndex - 1);
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize lightbox event listeners
|
function nextPhoto() {
|
||||||
function initLightbox() {
|
if (allPicturesArray.length === 0) return;
|
||||||
|
openPhotoLightbox(currentPhotoIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function initPhotoLightbox() {
|
||||||
const lightbox = document.getElementById('customLightbox');
|
const lightbox = document.getElementById('customLightbox');
|
||||||
const lightboxClose = document.getElementById('lightboxClose');
|
const lightboxClose = document.getElementById('lightboxClose');
|
||||||
const lightboxPrev = document.getElementById('lightboxPrev');
|
const lightboxPrev = document.getElementById('lightboxPrev');
|
||||||
|
|
@ -133,50 +98,62 @@ function initLightbox() {
|
||||||
|
|
||||||
if (!lightbox) return;
|
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) => {
|
document.querySelectorAll('.photo-item img').forEach((img) => {
|
||||||
img.removeEventListener('click', img._lightboxClick);
|
img.removeEventListener('click', img._photoClick);
|
||||||
img._lightboxClick = function(e) {
|
img._photoClick = function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const url = this.src;
|
const url = this.src;
|
||||||
const fullIndex = allPicturesArray.findIndex(p => p.url === url);
|
const fullIndex = allPicturesArray.findIndex(p => p.url === url);
|
||||||
if (fullIndex !== -1) {
|
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');
|
const lightbox = document.getElementById('customLightbox');
|
||||||
if (!lightbox || !lightbox.classList.contains('active')) return;
|
if (!lightbox || !lightbox.classList.contains('active')) return;
|
||||||
if (e.key === 'Escape') closeLightbox();
|
|
||||||
else if (e.key === 'ArrowLeft') prevPhoto();
|
if (e.key === 'Escape') {
|
||||||
else if (e.key === 'ArrowRight') nextPhoto();
|
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');
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let selected;
|
// Build playlist from ALL filtered tracks
|
||||||
if (randomize) {
|
window.musicPlaylist = [];
|
||||||
const shuffled = shuffleArray(filteredTracks);
|
filteredTracks.forEach(track => {
|
||||||
selected = shuffled.slice(0, 6);
|
let title = '', url = '', image = '', artist = '', album = '', duration = '';
|
||||||
} 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 = '';
|
|
||||||
|
|
||||||
if (track.tags) {
|
if (track.tags) {
|
||||||
track.tags.forEach(tag => {
|
track.tags.forEach(tag => {
|
||||||
const key = tag[0];
|
const key = tag[0];
|
||||||
const value = tag[1];
|
const value = tag[1];
|
||||||
|
|
||||||
if (key === 'title') title = value;
|
if (key === 'title') title = value;
|
||||||
else if (key === 'url') url = value;
|
else if (key === 'url') url = value;
|
||||||
else if (key === 'image') image = value;
|
else if (key === 'image') image = value;
|
||||||
else if (key === 'artist') artist = value;
|
else if (key === 'artist') artist = value;
|
||||||
else if (key === 'album') album = value;
|
else if (key === 'album') album = value;
|
||||||
else if (key === 't') genreTags.push(value);
|
else if (key === 'duration') duration = parseFloat(value);
|
||||||
else if (key === 'alt') alt = 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');
|
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 = `
|
let cardHTML = `
|
||||||
${image ? `<img src="${image}" alt="${title}" class="music-image" loading="lazy">` : ''}
|
<div class="music-card-inner">
|
||||||
<div class="music-info-header">
|
<div class="music-image-wrapper">
|
||||||
<h4>${title || 'Untitled'}</h4>
|
${track.image ? `<img src="${track.image}" alt="${track.title}" class="music-image" loading="lazy">` : ''}
|
||||||
${artist ? `<p class="music-artist">${artist}</p>` : ''}
|
<div class="music-play-overlay">
|
||||||
${album ? `<p class="music-album">${album}</p>` : ''}
|
<div class="music-play-circle">
|
||||||
|
<span>▶</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="music-info-header">
|
||||||
|
<h4>${track.title}</h4>
|
||||||
|
${track.artist ? `<p class="music-artist">${track.artist}</p>` : ''}
|
||||||
|
${track.album ? `<p class="music-album">${track.album}</p>` : ''}
|
||||||
</div>
|
</div>
|
||||||
${url ? `<audio controls preload="none"><source src="${url}" type="audio/mpeg">Your browser does not support the audio element.</audio>` : ''}
|
|
||||||
${genreTags.length > 0 ? `
|
${genreTags.length > 0 ? `
|
||||||
<div class="music-tags">
|
<div class="music-tags">
|
||||||
${genreTags.map(t => `<span class="tag"><span>${t}</span></span>`).join('')}
|
${genreTags.map(t => `<span class="tag"><span>${t}</span></span>`).join('')}
|
||||||
|
|
@ -253,6 +286,7 @@ function renderMusicTracks(tracks, containerId, randomize = false) {
|
||||||
<button class="lyrics-toggle"><span>Show Info</span></button>
|
<button class="lyrics-toggle"><span>Show Info</span></button>
|
||||||
<div class="lyrics" style="display: none;">${content.replace(/\n/g, '<br>')}</div>
|
<div class="lyrics" style="display: none;">${content.replace(/\n/g, '<br>')}</div>
|
||||||
` : ''}
|
` : ''}
|
||||||
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
card.innerHTML = cardHTML;
|
card.innerHTML = cardHTML;
|
||||||
|
|
@ -283,15 +317,16 @@ function handleLyricsToggle() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
// 4. PICTURES RENDERER (UPDATED)
|
// 4. PICTURES RENDERER
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|
||||||
function renderRandomPictures(picturesData, containerId, randomize = false) {
|
function renderRandomPictures(picturesData, containerId, randomize = false) {
|
||||||
const container = document.getElementById(containerId);
|
const container = document.getElementById(containerId);
|
||||||
if (!container) return;
|
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 allPictures = [];
|
||||||
|
let allEvents = [];
|
||||||
|
|
||||||
picturesData.forEach(event => {
|
picturesData.forEach(event => {
|
||||||
const imetaTags = [];
|
const imetaTags = [];
|
||||||
|
|
@ -302,6 +337,9 @@ function renderRandomPictures(picturesData, containerId, randomize = false) {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (imetaTags.length > 0) {
|
if (imetaTags.length > 0) {
|
||||||
|
let firstImage = null;
|
||||||
|
let eventImages = [];
|
||||||
|
|
||||||
imetaTags.forEach(imetaTag => {
|
imetaTags.forEach(imetaTag => {
|
||||||
let imageUrl = '';
|
let imageUrl = '';
|
||||||
let alt = event.content || '';
|
let alt = event.content || '';
|
||||||
|
|
@ -318,14 +356,28 @@ function renderRandomPictures(picturesData, containerId, randomize = false) {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (imageUrl) {
|
if (imageUrl) {
|
||||||
allPictures.push({
|
const pictureData = {
|
||||||
url: imageUrl,
|
url: imageUrl,
|
||||||
alt: alt,
|
alt: alt,
|
||||||
created_at: event.created_at,
|
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 {
|
} else {
|
||||||
let imageUrl = '';
|
let imageUrl = '';
|
||||||
let alt = event.content || '';
|
let alt = event.content || '';
|
||||||
|
|
@ -341,40 +393,68 @@ function renderRandomPictures(picturesData, containerId, randomize = false) {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (imageUrl) {
|
if (imageUrl) {
|
||||||
allPictures.push({
|
const pictureData = {
|
||||||
url: imageUrl,
|
url: imageUrl,
|
||||||
alt: alt,
|
alt: alt,
|
||||||
created_at: event.created_at,
|
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
|
// Store ALL pictures in the global array for the lightbox
|
||||||
let sortedPictures;
|
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) {
|
if (randomize) {
|
||||||
sortedPictures = shuffleArray(allPictures);
|
const shuffled = shuffleArray([...sortedEvents]);
|
||||||
|
displayEvents = shuffled.slice(0, 6);
|
||||||
} else {
|
} 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 = '';
|
container.innerHTML = '';
|
||||||
|
|
||||||
selected.forEach(picture => {
|
displayEvents.forEach((event, index) => {
|
||||||
const item = createPictureElement(picture);
|
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 ? `<img src="${picture.url}" alt="${picture.alt}" loading="lazy">` : ''}
|
||||||
|
<div class="photo-date"><span>📅 ${dateStr}</span></div>
|
||||||
|
`;
|
||||||
|
|
||||||
container.appendChild(item);
|
container.appendChild(item);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Initialize lightbox
|
// Initialize photo lightbox
|
||||||
initLightbox();
|
initPhotoLightbox();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|
@ -461,7 +541,10 @@ function renderRandomVideos(videosData, containerId, randomize = false) {
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|
||||||
function refreshMusic() {
|
function refreshMusic() {
|
||||||
if (window.allMusicData) renderMusicTracks(window.allMusicData, 'musicGrid', true);
|
if (window.allMusicData) {
|
||||||
|
window.musicPlaylist = [];
|
||||||
|
renderMusicTracks(window.allMusicData, 'musicGrid', true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function refreshPictures() {
|
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() {
|
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 => {
|
document.querySelectorAll('nav a').forEach(link => {
|
||||||
link.addEventListener('click', function(e) {
|
link.addEventListener('click', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
@ -545,14 +857,15 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
// Initialize Pictures (chronological, not randomized)
|
// Initialize Pictures (chronological, not randomized)
|
||||||
if (window.allPicturesData && window.allPicturesData.length > 0) {
|
if (window.allPicturesData && window.allPicturesData.length > 0) {
|
||||||
renderRandomPictures(window.allPicturesData, 'photoGrid', false);
|
renderRandomPictures(window.allPicturesData, 'photoGrid', false);
|
||||||
} else {
|
|
||||||
initLightbox();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize Videos (chronological, not randomized)
|
// Initialize Videos (chronological, not randomized)
|
||||||
if (window.allVideosData && window.allVideosData.length > 0) {
|
if (window.allVideosData && window.allVideosData.length > 0) {
|
||||||
renderRandomVideos(window.allVideosData, 'videoGrid', false);
|
renderRandomVideos(window.allVideosData, 'videoGrid', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize music lightbox
|
||||||
|
initMusicLightbox();
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('✅ Site initialized successfully!');
|
console.log('✅ Site initialized successfully!');
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,43 @@
|
||||||
<div class="custom-lightbox-counter" id="lightboxCounter">1 / 1</div>
|
<div class="custom-lightbox-counter" id="lightboxCounter">1 / 1</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Music Lightbox -->
|
||||||
|
<div class="music-lightbox" id="musicLightbox">
|
||||||
|
<div class="music-lightbox-background" id="musicLightboxBg"></div>
|
||||||
|
<button class="music-lightbox-close" id="musicLightboxClose">✕</button>
|
||||||
|
|
||||||
|
<div class="music-lightbox-content">
|
||||||
|
<div class="music-lightbox-album-art">
|
||||||
|
<img id="musicLightboxImage" src="" alt="Album art">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- In the info section -->
|
||||||
|
<div class="music-lightbox-info">
|
||||||
|
<h2 id="musicLightboxTitle">Title</h2>
|
||||||
|
<p class="music-lightbox-artist" id="musicLightboxArtist">Artist</p>
|
||||||
|
<p class="music-lightbox-album-name" id="musicLightboxAlbum">Album</p>
|
||||||
|
<!-- ... rest ... -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="music-lightbox-progress">
|
||||||
|
<span class="music-lightbox-time" id="musicLightboxCurrentTime">0:00</span>
|
||||||
|
<div class="music-lightbox-progress-bar" id="musicLightboxProgressBar">
|
||||||
|
<div class="music-lightbox-progress-fill" id="musicLightboxProgressFill"></div>
|
||||||
|
</div>
|
||||||
|
<span class="music-lightbox-time" id="musicLightboxDuration">0:00</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="music-lightbox-controls">
|
||||||
|
<button class="music-lightbox-control-btn" id="musicLightboxPrev">⏮</button>
|
||||||
|
<button class="music-lightbox-control-btn play-btn" id="musicLightboxPlayBtn2">
|
||||||
|
<span id="musicPlayIcon2">▶</span>
|
||||||
|
</button>
|
||||||
|
<button class="music-lightbox-control-btn" id="musicLightboxNext">⏭</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{{ $js := resources.Get "js/scripts.js" | resources.Minify | fingerprint }}
|
{{ $js := resources.Get "js/scripts.js" | resources.Minify | fingerprint }}
|
||||||
<script src="{{ $js.RelPermalink }}"></script>
|
<script src="{{ $js.RelPermalink }}"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue