169 lines
5.6 KiB
JavaScript
169 lines
5.6 KiB
JavaScript
|
|
/**
|
|||
|
|
* Shared Header Component for SYNTAXIS Branding Galleries
|
|||
|
|
* Handles navigation, dark mode, and palette modal
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
function initializeSharedHeader() {
|
|||
|
|
// Restore dark mode preference
|
|||
|
|
if (localStorage.getItem('darkMode') === 'true') {
|
|||
|
|
document.body.classList.add('dark-mode');
|
|||
|
|
}
|
|||
|
|
updateDarkModeText();
|
|||
|
|
|
|||
|
|
// Set active button based on current page
|
|||
|
|
updateActiveNavButton();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function toggleDarkMode() {
|
|||
|
|
document.body.classList.toggle('dark-mode');
|
|||
|
|
localStorage.setItem('darkMode', document.body.classList.contains('dark-mode'));
|
|||
|
|
updateDarkModeText();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function updateDarkModeText() {
|
|||
|
|
const isDarkMode = document.body.classList.contains('dark-mode');
|
|||
|
|
const toggleBtn = document.querySelector('[data-toggle="dark-mode"]');
|
|||
|
|
if (toggleBtn) {
|
|||
|
|
toggleBtn.textContent = isDarkMode ? '☀️ Light Mode' : '🌙 Dark Mode';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function updateActiveNavButton() {
|
|||
|
|
const currentPage = window.location.pathname.split('/').pop() || 'index.html';
|
|||
|
|
const navButtons = document.querySelectorAll('[data-nav-button]');
|
|||
|
|
|
|||
|
|
navButtons.forEach(btn => {
|
|||
|
|
const target = btn.getAttribute('data-nav-button');
|
|||
|
|
if (currentPage.includes(target) ||
|
|||
|
|
(currentPage === '' && target === 'branding') ||
|
|||
|
|
(currentPage.includes('branding') && target === 'branding') ||
|
|||
|
|
(currentPage.includes('animated') && target === 'animated')) {
|
|||
|
|
btn.classList.add('active');
|
|||
|
|
} else {
|
|||
|
|
btn.classList.remove('active');
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function openPaletteModal() {
|
|||
|
|
const modal = document.getElementById('palette-modal');
|
|||
|
|
if (modal) {
|
|||
|
|
modal.style.display = 'flex';
|
|||
|
|
document.body.style.overflow = 'hidden';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function closePaletteModal() {
|
|||
|
|
const modal = document.getElementById('palette-modal');
|
|||
|
|
if (modal) {
|
|||
|
|
modal.style.display = 'none';
|
|||
|
|
document.body.style.overflow = 'auto';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Close modal on escape key
|
|||
|
|
document.addEventListener('keydown', function(event) {
|
|||
|
|
if (event.key === 'Escape') {
|
|||
|
|
closePaletteModal();
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// Close modal on outside click
|
|||
|
|
document.addEventListener('click', function(event) {
|
|||
|
|
const modal = document.getElementById('palette-modal');
|
|||
|
|
if (modal && event.target === modal) {
|
|||
|
|
closePaletteModal();
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
function toggleInfoNote() {
|
|||
|
|
const note = document.getElementById('info-note');
|
|||
|
|
const btn = document.querySelector('.toggle-note-btn');
|
|||
|
|
if (note && btn) {
|
|||
|
|
note.classList.toggle('visible');
|
|||
|
|
const isVisible = note.classList.contains('visible');
|
|||
|
|
btn.textContent = isVisible ? '🔼 Hide Note' : '💡 Show Animation Note';
|
|||
|
|
localStorage.setItem('infoNoteVisible', isVisible);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function restoreInfoNoteState() {
|
|||
|
|
const note = document.getElementById('info-note');
|
|||
|
|
const btn = document.querySelector('.toggle-note-btn');
|
|||
|
|
if (note && btn) {
|
|||
|
|
const wasVisible = localStorage.getItem('infoNoteVisible') === 'true';
|
|||
|
|
if (wasVisible) {
|
|||
|
|
note.classList.add('visible');
|
|||
|
|
btn.textContent = '🔼 Hide Note';
|
|||
|
|
} else {
|
|||
|
|
btn.textContent = '💡 Show Animation Note';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function copyFilename(filename) {
|
|||
|
|
navigator.clipboard
|
|||
|
|
.writeText(filename)
|
|||
|
|
.then(() => {
|
|||
|
|
const toast = document.createElement("div");
|
|||
|
|
toast.className = "copy-toast";
|
|||
|
|
toast.textContent = `✓ ${filename} copied!`;
|
|||
|
|
document.body.appendChild(toast);
|
|||
|
|
setTimeout(() => toast.remove(), 3000);
|
|||
|
|
})
|
|||
|
|
.catch(() => {
|
|||
|
|
const toast = document.createElement("div");
|
|||
|
|
toast.className = "copy-toast";
|
|||
|
|
toast.style.background = "#EF4444";
|
|||
|
|
toast.textContent = "✗ Error copying";
|
|||
|
|
document.body.appendChild(toast);
|
|||
|
|
setTimeout(() => toast.remove(), 3000);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Initialize on DOM content loaded
|
|||
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|||
|
|
initializeSharedHeader();
|
|||
|
|
restoreInfoNoteState();
|
|||
|
|
|
|||
|
|
// Add click handlers to .main-logo-meta elements
|
|||
|
|
document.querySelectorAll('.main-logo-meta').forEach(element => {
|
|||
|
|
element.addEventListener('click', function() {
|
|||
|
|
// Try to get the filepath from the sibling object element
|
|||
|
|
const card = this.closest('.main-logo-card');
|
|||
|
|
let filepath = null;
|
|||
|
|
|
|||
|
|
if (card) {
|
|||
|
|
const objectElement = card.querySelector('object[data]');
|
|||
|
|
if (objectElement) {
|
|||
|
|
filepath = objectElement.getAttribute('data');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// If filepath not found, extract filename from the text (e.g., "syntax_logo.svg • 800×200px" -> "syntax_logo.svg")
|
|||
|
|
if (!filepath) {
|
|||
|
|
const text = this.textContent.trim();
|
|||
|
|
filepath = text.split(' •')[0].trim();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
copyFilename(filepath);
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// Add click handlers to .card-meta-filename elements
|
|||
|
|
document.querySelectorAll('.card-meta-filename').forEach(element => {
|
|||
|
|
element.addEventListener('click', function() {
|
|||
|
|
// Extract filepath from data attribute (e.g., "syntax_logos_anim/syntax_logo_a.svg")
|
|||
|
|
const filepath = this.getAttribute('data-filepath');
|
|||
|
|
if (filepath) {
|
|||
|
|
copyFilename(filepath);
|
|||
|
|
} else {
|
|||
|
|
// Fallback: extract filename from the text (e.g., "📄 syntax_logo_a.svg" -> "syntax_logo_a.svg")
|
|||
|
|
const text = this.textContent.trim();
|
|||
|
|
const filename = text.replace(/^[📄\s]+/, '').trim();
|
|||
|
|
copyFilename(filename);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
});
|