Initial import of HarborSmith website
Some checks failed
build-website / build (push) Failing after 1m2s
Some checks failed
build-website / build (push) Failing after 1m2s
This commit is contained in:
375
website-mockups/js/bento-layout.js
Normal file
375
website-mockups/js/bento-layout.js
Normal file
@@ -0,0 +1,375 @@
|
||||
// Bento Grid Layout JavaScript
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Menu Toggle
|
||||
const menuToggle = document.getElementById('menuToggle');
|
||||
const menuOverlay = document.getElementById('menuOverlay');
|
||||
const menuClose = document.getElementById('menuClose');
|
||||
|
||||
menuToggle.addEventListener('click', () => {
|
||||
menuOverlay.classList.add('active');
|
||||
});
|
||||
|
||||
menuClose.addEventListener('click', () => {
|
||||
menuOverlay.classList.remove('active');
|
||||
});
|
||||
|
||||
// Filter Toggle
|
||||
const filterToggle = document.getElementById('filterToggle');
|
||||
const filterBar = document.getElementById('filterBar');
|
||||
|
||||
filterToggle.addEventListener('click', () => {
|
||||
filterBar.classList.toggle('active');
|
||||
});
|
||||
|
||||
// Filter Functionality
|
||||
const filterChips = document.querySelectorAll('.filter-chip');
|
||||
const bentoTiles = document.querySelectorAll('.bento-tile');
|
||||
|
||||
filterChips.forEach(chip => {
|
||||
chip.addEventListener('click', () => {
|
||||
// Update active state
|
||||
filterChips.forEach(c => c.classList.remove('active'));
|
||||
chip.classList.add('active');
|
||||
|
||||
const filter = chip.dataset.filter;
|
||||
|
||||
// Filter tiles
|
||||
bentoTiles.forEach(tile => {
|
||||
if (filter === 'all' || tile.dataset.category === filter) {
|
||||
tile.classList.remove('hiding');
|
||||
tile.classList.add('showing');
|
||||
} else {
|
||||
tile.classList.add('hiding');
|
||||
tile.classList.remove('showing');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// FAB Menu
|
||||
const fabBtn = document.getElementById('fabBtn');
|
||||
const fabMenu = document.getElementById('fabMenu');
|
||||
|
||||
fabBtn.addEventListener('click', () => {
|
||||
fabMenu.classList.toggle('active');
|
||||
});
|
||||
|
||||
// FAB Options
|
||||
const fabOptions = document.querySelectorAll('.fab-option');
|
||||
|
||||
fabOptions.forEach(option => {
|
||||
option.addEventListener('click', () => {
|
||||
const action = option.dataset.action;
|
||||
|
||||
switch(action) {
|
||||
case 'chat':
|
||||
alert('Opening chat...');
|
||||
break;
|
||||
case 'call':
|
||||
window.location.href = 'tel:4155550123';
|
||||
break;
|
||||
case 'book':
|
||||
window.location.href = 'charter.html';
|
||||
break;
|
||||
}
|
||||
|
||||
fabMenu.classList.remove('active');
|
||||
});
|
||||
});
|
||||
|
||||
// Quick View for Yachts
|
||||
const quickViewBtns = document.querySelectorAll('.quick-view-btn');
|
||||
|
||||
quickViewBtns.forEach(btn => {
|
||||
btn.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
const yachtTile = btn.closest('.tile-yacht');
|
||||
const yachtName = yachtTile.querySelector('.yacht-name').textContent;
|
||||
|
||||
// Create modal
|
||||
const modal = document.createElement('div');
|
||||
modal.className = 'yacht-modal';
|
||||
modal.innerHTML = `
|
||||
<div class="modal-content">
|
||||
<button class="modal-close">×</button>
|
||||
<h2>${yachtName}</h2>
|
||||
<div class="modal-gallery">
|
||||
<img src="${yachtTile.querySelector('img').src}" alt="${yachtName}">
|
||||
</div>
|
||||
<div class="modal-details">
|
||||
<h3>Specifications</h3>
|
||||
<ul>
|
||||
<li>Length: 120ft</li>
|
||||
<li>Capacity: 12 Guests</li>
|
||||
<li>Cabins: 5</li>
|
||||
<li>Crew: Full Professional Crew</li>
|
||||
<li>Amenities: Jacuzzi, Water Toys, Full Bar</li>
|
||||
</ul>
|
||||
<div class="modal-actions">
|
||||
<button class="btn-primary">Book Now</button>
|
||||
<button class="btn-secondary">Request Info</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.body.appendChild(modal);
|
||||
|
||||
// Add styles
|
||||
const modalStyles = `
|
||||
.yacht-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0,0,0,0.8);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 300;
|
||||
animation: fadeIn 0.3s ease;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background: white;
|
||||
border-radius: 20px;
|
||||
padding: 2rem;
|
||||
max-width: 600px;
|
||||
width: 90%;
|
||||
max-height: 90vh;
|
||||
overflow-y: auto;
|
||||
position: relative;
|
||||
animation: slideUp 0.3s ease;
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
background: transparent;
|
||||
border: none;
|
||||
font-size: 2rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.modal-gallery img {
|
||||
width: 100%;
|
||||
border-radius: 10px;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.modal-details h3 {
|
||||
margin: 1.5rem 0 1rem;
|
||||
}
|
||||
|
||||
.modal-details ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.modal-details li {
|
||||
padding: 0.5rem 0;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.modal-actions {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.modal-actions button {
|
||||
flex: 1;
|
||||
padding: 0.75rem;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes slideUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
if (!document.getElementById('modal-styles')) {
|
||||
const styleSheet = document.createElement('style');
|
||||
styleSheet.id = 'modal-styles';
|
||||
styleSheet.textContent = modalStyles;
|
||||
document.head.appendChild(styleSheet);
|
||||
}
|
||||
|
||||
// Close modal
|
||||
modal.querySelector('.modal-close').addEventListener('click', () => {
|
||||
modal.remove();
|
||||
});
|
||||
|
||||
modal.addEventListener('click', (e) => {
|
||||
if (e.target === modal) {
|
||||
modal.remove();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Wishlist functionality
|
||||
let wishlist = [];
|
||||
const wishlistSidebar = document.getElementById('wishlistSidebar');
|
||||
const wishlistContent = document.getElementById('wishlistContent');
|
||||
|
||||
// Add to wishlist buttons (would be added to tiles)
|
||||
bentoTiles.forEach(tile => {
|
||||
if (tile.classList.contains('tile-yacht') || tile.classList.contains('tile-experience')) {
|
||||
const wishlistBtn = document.createElement('button');
|
||||
wishlistBtn.className = 'wishlist-add';
|
||||
wishlistBtn.innerHTML = '♡';
|
||||
wishlistBtn.style.cssText = `
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
left: 1rem;
|
||||
background: white;
|
||||
border: none;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
font-size: 1.5rem;
|
||||
cursor: pointer;
|
||||
z-index: 10;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
`;
|
||||
|
||||
tile.appendChild(wishlistBtn);
|
||||
|
||||
wishlistBtn.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
const itemName = tile.querySelector('h3').textContent;
|
||||
|
||||
if (wishlistBtn.innerHTML === '♡') {
|
||||
wishlistBtn.innerHTML = '❤️';
|
||||
wishlist.push(itemName);
|
||||
updateWishlist();
|
||||
} else {
|
||||
wishlistBtn.innerHTML = '♡';
|
||||
wishlist = wishlist.filter(item => item !== itemName);
|
||||
updateWishlist();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function updateWishlist() {
|
||||
if (wishlist.length === 0) {
|
||||
wishlistContent.innerHTML = '<p class="wishlist-empty">Select yachts and experiences to build your dream charter</p>';
|
||||
} else {
|
||||
wishlistContent.innerHTML = `
|
||||
<h4>Selected Items (${wishlist.length})</h4>
|
||||
<ul style="list-style: none; padding: 0;">
|
||||
${wishlist.map(item => `
|
||||
<li style="padding: 0.75rem; background: #f8fafc; margin-bottom: 0.5rem; border-radius: 8px;">
|
||||
${item}
|
||||
</li>
|
||||
`).join('')}
|
||||
</ul>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
// Show wishlist
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'w' && e.ctrlKey) {
|
||||
e.preventDefault();
|
||||
wishlistSidebar.classList.toggle('active');
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('wishlistClose').addEventListener('click', () => {
|
||||
wishlistSidebar.classList.remove('active');
|
||||
});
|
||||
|
||||
// Parallax effect on scroll
|
||||
let ticking = false;
|
||||
|
||||
function updateParallax() {
|
||||
const scrolled = window.pageYOffset;
|
||||
const heroTile = document.querySelector('.tile-hero');
|
||||
|
||||
if (heroTile) {
|
||||
const heroVisual = heroTile.querySelector('.hero-visual');
|
||||
if (heroVisual) {
|
||||
heroVisual.style.transform = `translateY(${scrolled * 0.3}px)`;
|
||||
}
|
||||
}
|
||||
|
||||
ticking = false;
|
||||
}
|
||||
|
||||
function requestTick() {
|
||||
if (!ticking) {
|
||||
window.requestAnimationFrame(updateParallax);
|
||||
ticking = true;
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', requestTick);
|
||||
|
||||
// Auto-play/pause videos on visibility
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
const video = entry.target.querySelector('video');
|
||||
if (video) {
|
||||
if (entry.isIntersecting) {
|
||||
video.play();
|
||||
} else {
|
||||
video.pause();
|
||||
}
|
||||
}
|
||||
});
|
||||
}, { threshold: 0.5 });
|
||||
|
||||
document.querySelectorAll('.tile-video, .tile-hero').forEach(tile => {
|
||||
observer.observe(tile);
|
||||
});
|
||||
|
||||
// Tile click navigation
|
||||
bentoTiles.forEach(tile => {
|
||||
if (!tile.classList.contains('tile-yacht')) {
|
||||
tile.addEventListener('click', () => {
|
||||
if (tile.classList.contains('tile-service')) {
|
||||
window.location.href = 'maintenance.html';
|
||||
} else if (tile.classList.contains('tile-experience')) {
|
||||
window.location.href = 'charter.html';
|
||||
} else if (tile.classList.contains('tile-cta')) {
|
||||
window.location.href = 'charter.html';
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Smooth hover effects
|
||||
bentoTiles.forEach(tile => {
|
||||
tile.addEventListener('mouseenter', () => {
|
||||
tile.style.zIndex = '10';
|
||||
});
|
||||
|
||||
tile.addEventListener('mouseleave', () => {
|
||||
setTimeout(() => {
|
||||
tile.style.zIndex = '';
|
||||
}, 300);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user