Files
gestoria-lp/assets/js/main.js
Gestoría LP 3f5ca4b2de feat: agregar selector de tema oscuro/claro
Toggle sol/luna en el navbar que permite cambiar entre tema oscuro (por
defecto) y tema claro. Preferencia guardada en localStorage. Incluye
overrides de CSS para todos los componentes con colores hardcodeados,
inversión de logo, y transición suave entre temas.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 08:25:34 +00:00

216 lines
7.6 KiB
JavaScript

/**
* Gestoría LP — Main JavaScript
* Handles: mobile menu, smooth scroll, navbar scroll effect, scroll animations
*/
document.addEventListener('DOMContentLoaded', function () {
// ---- DOM References ----
const navbar = document.getElementById('navbar');
const navToggle = document.getElementById('navToggle');
const navMenu = document.getElementById('navMenu');
const body = document.body;
// Create overlay element for mobile menu backdrop
const overlay = document.createElement('div');
overlay.classList.add('navbar__overlay');
document.body.appendChild(overlay);
// ================================================================
// 1. Mobile Hamburger Menu Toggle
// ================================================================
function openMenu() {
navToggle.classList.add('active');
navMenu.classList.add('active');
overlay.classList.add('active');
navToggle.setAttribute('aria-expanded', 'true');
body.style.overflow = 'hidden';
}
function closeMenu() {
navToggle.classList.remove('active');
navMenu.classList.remove('active');
overlay.classList.remove('active');
navToggle.setAttribute('aria-expanded', 'false');
body.style.overflow = '';
}
if (navToggle) {
navToggle.addEventListener('click', function () {
if (navMenu.classList.contains('active')) {
closeMenu();
} else {
openMenu();
}
});
}
// Close menu when clicking overlay
overlay.addEventListener('click', closeMenu);
// Close menu when pressing Escape
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape' && navMenu.classList.contains('active')) {
closeMenu();
}
});
// ================================================================
// 2. Dropdown Toggle (mobile + touch devices)
// ================================================================
var dropdownItems = document.querySelectorAll('.navbar__item--dropdown');
dropdownItems.forEach(function (item) {
var link = item.querySelector('.navbar__link--dropdown');
if (link) {
link.addEventListener('click', function (e) {
// Always prevent default on the dropdown parent link
e.preventDefault();
e.stopPropagation();
item.classList.toggle('active');
});
}
});
// Close dropdown when clicking outside (desktop)
document.addEventListener('click', function (e) {
dropdownItems.forEach(function (item) {
if (!item.contains(e.target)) {
item.classList.remove('active');
}
});
});
// ================================================================
// 3. Smooth Scroll for Anchor Links
// ================================================================
var anchorLinks = document.querySelectorAll('a[href^="#"]');
anchorLinks.forEach(function (link) {
// Skip dropdown toggle links — they have their own handler
if (link.classList.contains('navbar__link--dropdown')) return;
link.addEventListener('click', function (e) {
var targetId = this.getAttribute('href');
if (targetId === '#') return;
var target = document.querySelector(targetId);
if (target) {
e.preventDefault();
closeMenu();
var navHeight = navbar ? navbar.offsetHeight : 0;
var targetPos = target.getBoundingClientRect().top + window.pageYOffset - navHeight;
window.scrollTo({
top: targetPos,
behavior: 'smooth'
});
}
});
});
// ================================================================
// 4. Navbar Background/Shadow on Scroll
// ================================================================
var lastScrollY = 0;
function handleNavbarScroll() {
var scrollY = window.pageYOffset || document.documentElement.scrollTop;
if (scrollY > 20) {
navbar.classList.add('navbar--scrolled');
} else {
navbar.classList.remove('navbar--scrolled');
}
lastScrollY = scrollY;
}
if (navbar) {
window.addEventListener('scroll', handleNavbarScroll, { passive: true });
// Run once on load
handleNavbarScroll();
}
// ================================================================
// 5. Scroll Animations (Testimonials & fade-up elements)
// ================================================================
function animateOnScroll() {
// Testimonial cards
var testimonialCards = document.querySelectorAll('.testimonial-card:not(.animate-in)');
testimonialCards.forEach(function (card, index) {
var rect = card.getBoundingClientRect();
var windowHeight = window.innerHeight;
if (rect.top < windowHeight * 0.88) {
// Stagger the animation
setTimeout(function () {
card.classList.add('animate-in');
}, index * 120);
}
});
// Generic fade-up elements
var fadeElements = document.querySelectorAll('.fade-up:not(.visible)');
fadeElements.forEach(function (el) {
var rect = el.getBoundingClientRect();
var windowHeight = window.innerHeight;
if (rect.top < windowHeight * 0.88) {
el.classList.add('visible');
}
});
}
window.addEventListener('scroll', animateOnScroll, { passive: true });
// Run once on load to catch elements already in viewport
animateOnScroll();
// ================================================================
// 6. Close mobile dropdown on window resize to desktop
// ================================================================
window.addEventListener('resize', function () {
if (window.innerWidth > 768) {
closeMenu();
dropdownItems.forEach(function (item) {
item.classList.remove('active');
});
}
});
// ================================================================
// 7. Dark / Light Theme Toggle
// ================================================================
var themeToggle = document.getElementById('themeToggle');
var themeIcon = document.getElementById('themeIcon');
function setTheme(theme) {
document.documentElement.setAttribute('data-theme', theme);
localStorage.setItem('theme', theme);
if (themeIcon) {
themeIcon.className = theme === 'light' ? 'fas fa-sun' : 'fas fa-moon';
}
// Update theme-color meta tag
var metaTheme = document.querySelector('meta[name="theme-color"]');
if (metaTheme) {
metaTheme.setAttribute('content', theme === 'light' ? '#f5f5f5' : '#0a0a0a');
}
}
// Determine initial theme: localStorage > system preference > dark
var savedTheme = localStorage.getItem('theme');
if (savedTheme) {
setTheme(savedTheme);
} else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches) {
setTheme('light');
}
// else: default is dark (no data-theme attribute needed)
if (themeToggle) {
themeToggle.addEventListener('click', function () {
var current = document.documentElement.getAttribute('data-theme');
setTheme(current === 'light' ? 'dark' : 'light');
});
}
});