Files

355 lines
12 KiB
JavaScript
Raw Permalink Normal View History

2025-09-18 22:20:01 +02:00
// Voyage Layout JavaScript - Smooth, Interactive, Engaging
document.addEventListener('DOMContentLoaded', function() {
// Theme Switcher
const themeToggle = document.getElementById('themeToggle');
const themeDropdown = document.getElementById('themeDropdown');
const themeOptions = document.querySelectorAll('.theme-option');
if (themeToggle && themeDropdown) {
themeToggle.addEventListener('click', (e) => {
e.stopPropagation();
themeDropdown.classList.toggle('active');
});
themeOptions.forEach(option => {
option.addEventListener('click', () => {
const theme = option.dataset.theme;
document.body.className = theme === 'nautical' ? '' : `theme-${theme}`;
localStorage.setItem('selectedTheme', theme);
themeDropdown.classList.remove('active');
});
});
// Close dropdown when clicking outside
document.addEventListener('click', () => {
themeDropdown.classList.remove('active');
});
// Load saved theme
const savedTheme = localStorage.getItem('selectedTheme');
if (savedTheme && savedTheme !== 'nautical') {
document.body.className = `theme-${savedTheme}`;
}
}
// Navigation scroll effect
const nav = document.getElementById('voyageNav');
let lastScroll = 0;
window.addEventListener('scroll', () => {
const currentScroll = window.pageYOffset;
if (currentScroll > 50) {
nav.classList.add('scrolled');
} else {
nav.classList.remove('scrolled');
}
lastScroll = currentScroll;
});
// Smooth scroll for navigation links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function(e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
// Parallax effect for hero video
const heroSection = document.getElementById('heroSection');
const heroVideo = document.querySelector('.hero-video-container');
window.addEventListener('scroll', () => {
const scrolled = window.pageYOffset;
const rate = scrolled * 0.5;
if (heroVideo) {
heroVideo.style.transform = `translateY(${rate}px)`;
}
});
// Fleet Carousel
const yachtCards = document.querySelectorAll('.yacht-card');
const dots = document.querySelectorAll('.dot');
const prevBtn = document.querySelector('.fleet-prev');
const nextBtn = document.querySelector('.fleet-next');
let currentYacht = 0;
function showYacht(index) {
yachtCards.forEach(card => card.classList.remove('active'));
dots.forEach(dot => dot.classList.remove('active'));
yachtCards[index].classList.add('active');
dots[index].classList.add('active');
}
if (prevBtn && nextBtn) {
prevBtn.addEventListener('click', () => {
currentYacht = (currentYacht - 1 + yachtCards.length) % yachtCards.length;
showYacht(currentYacht);
});
nextBtn.addEventListener('click', () => {
currentYacht = (currentYacht + 1) % yachtCards.length;
showYacht(currentYacht);
});
}
dots.forEach((dot, index) => {
dot.addEventListener('click', () => {
currentYacht = index;
showYacht(currentYacht);
});
});
// Auto-rotate fleet carousel
setInterval(() => {
if (document.visibilityState === 'visible') {
currentYacht = (currentYacht + 1) % yachtCards.length;
showYacht(currentYacht);
}
}, 5000);
// CTA Button interactions
document.querySelectorAll('.btn-primary-warm, .btn-secondary-warm').forEach(btn => {
btn.addEventListener('click', function(e) {
// Create ripple effect
const ripple = document.createElement('span');
ripple.classList.add('ripple');
this.appendChild(ripple);
const rect = this.getBoundingClientRect();
const size = Math.max(rect.width, rect.height);
const x = e.clientX - rect.left - size / 2;
const y = e.clientY - rect.top - size / 2;
ripple.style.width = ripple.style.height = size + 'px';
ripple.style.left = x + 'px';
ripple.style.top = y + 'px';
setTimeout(() => ripple.remove(), 600);
});
});
// Add ripple styles
const style = document.createElement('style');
style.textContent = `
.ripple {
position: absolute;
border-radius: 50%;
background: rgba(255, 255, 255, 0.6);
transform: scale(0);
animation: ripple 0.6s ease-out;
pointer-events: none;
}
@keyframes ripple {
to {
transform: scale(4);
opacity: 0;
}
}
.btn-primary-warm,
.btn-secondary-warm {
position: relative;
overflow: hidden;
}
`;
document.head.appendChild(style);
// Animate elements on scroll
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -100px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}
});
}, observerOptions);
// Observe elements for animation
document.querySelectorAll('.welcome-content, .story-card, .booking-card').forEach(el => {
el.style.opacity = '0';
el.style.transform = 'translateY(30px)';
el.style.transition = 'all 0.6s ease';
observer.observe(el);
});
// Interactive booking cards
document.querySelectorAll('.booking-card').forEach(card => {
card.addEventListener('mouseenter', function() {
this.style.transform = 'translateY(-10px) scale(1.02)';
});
card.addEventListener('mouseleave', function() {
if (this.classList.contains('featured')) {
this.style.transform = 'scale(1.05)';
} else {
this.style.transform = 'translateY(0) scale(1)';
}
});
});
// Phone number click handler
document.querySelectorAll('.btn-booking.primary').forEach(btn => {
if (btn.textContent.includes('415')) {
btn.addEventListener('click', () => {
window.location.href = 'tel:4155550123';
});
}
});
// Video optimization - pause when not visible
const video = document.querySelector('.hero-video');
if (video) {
const videoObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
video.play();
} else {
video.pause();
}
});
}, { threshold: 0.25 });
videoObserver.observe(video);
}
// Story cards hover effect
document.querySelectorAll('.story-card').forEach(card => {
const img = card.querySelector('img');
card.addEventListener('mouseenter', () => {
if (img) {
img.style.transform = 'scale(1.1)';
img.style.transition = 'transform 0.6s ease';
}
});
card.addEventListener('mouseleave', () => {
if (img) {
img.style.transform = 'scale(1)';
}
});
});
// Dynamic trust badge counter - starts from 0
// Target the white text span specifically (the second span in trust-badge)
const trustBadge = document.querySelector('.trust-badge > span:last-child');
if (trustBadge) {
let count = 0;
const targetCount = 500;
const duration = 2000; // 2 seconds
const steps = 50;
const increment = targetCount / steps;
const stepDuration = duration / steps;
// Start with 0
trustBadge.textContent = `Trusted by 0+ adventurers`;
const counter = setInterval(() => {
count += increment;
if (count >= targetCount) {
count = targetCount;
clearInterval(counter);
trustBadge.textContent = `Trusted by 500+ adventurers`;
} else {
trustBadge.textContent = `Trusted by ${Math.floor(count)}+ adventurers`;
}
}, stepDuration);
}
// Remove any duplicate red text that might exist
const allSpans = document.querySelectorAll('.hero-content span');
allSpans.forEach(span => {
// Check if this is the red duplicate text (not inside trust-badge)
if (span.textContent.includes('Trusted by') &&
span.textContent.includes('adventurers') &&
!span.closest('.trust-badge')) {
span.style.display = 'none';
}
});
// Smooth hover for navigation links
document.querySelectorAll('.nav-link').forEach(link => {
link.addEventListener('mouseenter', function() {
this.style.transform = 'translateY(-2px)';
});
link.addEventListener('mouseleave', function() {
this.style.transform = 'translateY(0)';
});
});
// Mobile menu (would need to add hamburger menu for production)
const mobileMenuBtn = document.createElement('button');
mobileMenuBtn.className = 'mobile-menu-btn';
mobileMenuBtn.innerHTML = '<span></span><span></span><span></span>';
mobileMenuBtn.style.cssText = `
display: none;
flex-direction: column;
gap: 4px;
background: transparent;
border: none;
cursor: pointer;
padding: 0.5rem;
`;
// Add mobile menu styles
const mobileStyles = document.createElement('style');
mobileStyles.textContent = `
@media (max-width: 768px) {
.mobile-menu-btn {
display: flex !important;
}
.mobile-menu-btn span {
width: 24px;
height: 2px;
background: white;
transition: all 0.3s ease;
}
.voyage-nav.scrolled .mobile-menu-btn span {
background: var(--primary-blue);
}
}
`;
document.head.appendChild(mobileStyles);
// Add mobile menu button to nav
const navContainer = document.querySelector('.nav-container');
if (navContainer && window.innerWidth <= 768) {
navContainer.appendChild(mobileMenuBtn);
}
// Loading animation for images
document.querySelectorAll('img').forEach(img => {
// Check if image is already loaded
if (img.complete && img.naturalHeight !== 0) {
img.style.opacity = '1';
} else {
img.style.opacity = '0';
img.addEventListener('load', function() {
this.style.opacity = '1';
});
}
img.style.transition = 'opacity 0.6s ease';
});
console.log('Voyage layout initialized successfully!');
});