167 lines
No EOL
6.2 KiB
JavaScript
167 lines
No EOL
6.2 KiB
JavaScript
// ===============================
|
||
// PANNELLO INFO + MAPPA (toggle affidabile + auto-refresh su cambio foto)
|
||
// ===============================
|
||
|
||
const infoPanel = document.getElementById('infoPanel');
|
||
let infoMapInstance = null; // tieni traccia della mappa per pulizia
|
||
|
||
// -------------------------------
|
||
// Helpers UI / stato
|
||
// -------------------------------
|
||
function isPanelOpen() {
|
||
return infoPanel.classList.contains('open') ||
|
||
infoPanel.getAttribute('aria-hidden') === 'false' ||
|
||
infoPanel.getAttribute('data-open') === '1' ||
|
||
infoPanel.style.display === 'block';
|
||
}
|
||
|
||
function markButtonActive(active) {
|
||
const btn = document.getElementById('modalInfoBtn');
|
||
if (btn) btn.classList.toggle('active', !!active);
|
||
}
|
||
|
||
// -------------------------------
|
||
// Render contenuti + (ri)creazione mappa
|
||
// -------------------------------
|
||
function renderInfo(photo) {
|
||
if (!photo) return;
|
||
|
||
const gps = photo.gps || { lat: '-', lng: '-', alt: '-' };
|
||
const folder = photo.path?.split('/').slice(2, -1).join('/') || '-';
|
||
const loc = photo.location || {};
|
||
|
||
// Inietta contenuti
|
||
infoPanel.innerHTML = `
|
||
<h3>Informazioni</h3>
|
||
|
||
<div class="info-row"><b>Nome:</b> ${photo.name ?? '-'}</div>
|
||
<div class="info-row"><b>Data:</b> ${photo.taken_at ?? '-'}</div>
|
||
|
||
<div class="info-row"><b>Latitudine:</b> ${gps.lat ?? '-'}</div>
|
||
<div class="info-row"><b>Longitudine:</b> ${gps.lng ?? '-'}</div>
|
||
<div class="info-row"><b>Altitudine:</b> ${gps.alt ?? '-'} m</div>
|
||
|
||
<div class="info-row"><b>Dimensioni:</b> ${photo.width ?? '-'} × ${photo.height ?? '-'}</div>
|
||
<div class="info-row"><b>Peso:</b> ${photo.size_bytes ? (photo.size_bytes / 1024 / 1024).toFixed(2) + ' MB' : '-'}</div>
|
||
<div class="info-row"><b>Tipo:</b> ${photo.mime_type ?? '-'}</div>
|
||
|
||
<div class="info-row"><b>Cartella:</b> ${folder}</div>
|
||
|
||
<div class="info-spacer"></div>
|
||
|
||
<h3>Mappa</h3>
|
||
${gps.lat !== '-' && gps.lng !== '-' ? '<div id="infoMap" class="info-map"></div>' : ''}
|
||
|
||
<div class="info-spacer"></div>
|
||
|
||
<h3>Location</h3>
|
||
${loc.continent ? `<div class="info-row"><b>Continente:</b> ${loc.continent}</div>` : ''}
|
||
${loc.country ? `<div class="info-row"><b>Nazione:</b> ${loc.country}</div>` : ''}
|
||
${loc.region ? `<div class="info-row"><b>Regione:</b> ${loc.region}</div>` : ''}
|
||
${loc.city ? `<div class="info-row"><b>Città:</b> ${loc.city}</div>` : ''}
|
||
${loc.address ? `<div class="info-row"><b>Indirizzo:</b> ${loc.address}</div>` : ''}
|
||
${loc.postcode ? `<div class="info-row"><b>CAP:</b> ${loc.postcode}</div>` : ''}
|
||
${loc.county_code ? `<div class="info-row"><b>Provincia:</b> ${loc.county_code}</div>` : ''}
|
||
${loc.timezone ? `<div class="info-row"><b>Timezone:</b> ${loc.timezone}</div>` : ''}
|
||
${loc.time ? `<div class="info-row"><b>Offset:</b> ${loc.time}</div>` : ''}
|
||
`;
|
||
|
||
// (Ri)crea la mappa se ci sono coordinate
|
||
// 1) Pulisci istanza precedente (evita "Map container is already initialized")
|
||
try { infoMapInstance?.remove(); } catch {}
|
||
infoMapInstance = null;
|
||
|
||
if (gps.lat !== '-' && gps.lng !== '-') {
|
||
setTimeout(() => {
|
||
try {
|
||
infoMapInstance = L.map('infoMap', {
|
||
zoomControl: false,
|
||
attributionControl: false
|
||
}).setView([gps.lat, gps.lng], 13);
|
||
|
||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||
maxZoom: 19
|
||
}).addTo(infoMapInstance);
|
||
|
||
L.marker([gps.lat, gps.lng]).addTo(infoMapInstance);
|
||
} catch (err) {
|
||
console.warn('Errore creazione mappa info:', err);
|
||
}
|
||
}, 50);
|
||
}
|
||
}
|
||
|
||
// -------------------------------
|
||
// API pubbliche: apri / chiudi / toggle
|
||
// -------------------------------
|
||
window.openInfoPanel = function openInfoPanel(photo) {
|
||
renderInfo(photo || window.currentPhoto);
|
||
infoPanel.classList.add('open');
|
||
infoPanel.setAttribute('aria-hidden', 'false');
|
||
infoPanel.setAttribute('data-open', '1');
|
||
markButtonActive(true);
|
||
};
|
||
|
||
window.closeInfoPanel = function closeInfoPanel() {
|
||
infoPanel.classList.remove('open');
|
||
infoPanel.setAttribute('aria-hidden', 'true');
|
||
infoPanel.setAttribute('data-open', '0');
|
||
markButtonActive(false);
|
||
|
||
// pulizia mappa
|
||
try { infoMapInstance?.remove(); } catch {}
|
||
infoMapInstance = null;
|
||
};
|
||
|
||
window.toggleInfoPanel = function toggleInfoPanel(photo) {
|
||
if (isPanelOpen()) window.closeInfoPanel();
|
||
else window.openInfoPanel(photo || window.currentPhoto);
|
||
};
|
||
|
||
// -------------------------------
|
||
// Delegation: click su ℹ️ = TOGGLE vero
|
||
// -------------------------------
|
||
document.addEventListener('click', (e) => {
|
||
if (e.target.id !== 'modalInfoBtn') return;
|
||
e.stopPropagation(); // evita side-effects (es. navigazione ai bordi)
|
||
window.toggleInfoPanel(window.currentPhoto);
|
||
});
|
||
|
||
// Chiudi pannello cliccando FUORI (non su ℹ️)
|
||
document.addEventListener('click', (e) => {
|
||
if (!isPanelOpen()) return;
|
||
const inside = infoPanel.contains(e.target);
|
||
const isBtn = e.target.id === 'modalInfoBtn';
|
||
if (!inside && !isBtn) window.closeInfoPanel();
|
||
});
|
||
|
||
// -------------------------------
|
||
/* Auto-refresh: se cambia il media nel modal e l'info è aperto, aggiorna */
|
||
(() => {
|
||
const mediaContainer = document.getElementById('modalMediaContainer');
|
||
if (!mediaContainer) return;
|
||
|
||
const refreshIfOpen = () => {
|
||
if (!isPanelOpen()) return;
|
||
const photo = window.currentPhoto;
|
||
if (photo) renderInfo(photo);
|
||
};
|
||
|
||
// 1) Osserva la sostituzione del media (immagine/video) nel modal
|
||
const mo = new MutationObserver(() => {
|
||
// Debounce minimo per evitare doppi render durante il replace
|
||
setTimeout(refreshIfOpen, 0);
|
||
});
|
||
mo.observe(mediaContainer, { childList: true });
|
||
|
||
// 2) (Extra robustezza) ascolta le frecce se esistono
|
||
document.getElementById('modalPrev')?.addEventListener('click', () => setTimeout(refreshIfOpen, 0));
|
||
document.getElementById('modalNext')?.addEventListener('click', () => setTimeout(refreshIfOpen, 0));
|
||
|
||
// 3) (Extra) tastiera ←/→
|
||
document.addEventListener('keydown', (e) => {
|
||
if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
|
||
setTimeout(refreshIfOpen, 0);
|
||
}
|
||
});
|
||
})(); |