Files
Additional/public/js/script.js
T
twotalesanimation e8e9b1f03c relocating
2025-12-30 20:59:58 +02:00

216 lines
6.0 KiB
JavaScript

// ===== MOBILE MENU TOGGLE =====
document.addEventListener('DOMContentLoaded', function () {
const hamburger = document.querySelector('.hamburger');
const nav = document.querySelector('nav');
if (hamburger) {
hamburger.addEventListener('click', function () {
nav.classList.toggle('active');
});
// Close menu when a link is clicked
document.querySelectorAll('nav a').forEach(link => {
link.addEventListener('click', function () {
nav.classList.remove('active');
});
});
}
});
// ===== SMOOTH SCROLL FOR ANCHOR 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'
});
}
});
});
// ===== LAZY LOAD IMAGES =====
if ('IntersectionObserver' in window) {
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.add('loaded');
observer.unobserve(img);
}
});
});
document.querySelectorAll('img[data-src]').forEach(img => imageObserver.observe(img));
}
// ===== SCROLL ANIMATIONS =====
function observeElements() {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}
});
}, {
threshold: 0.1
});
document.querySelectorAll('.card, .section').forEach(el => {
el.style.opacity = '0';
el.style.transform = 'translateY(20px)';
el.style.transition = 'opacity 0.6s ease, transform 0.6s ease';
observer.observe(el);
});
}
observeElements();
// ===== CART FUNCTIONALITY (SESSION-BASED) =====
class Cart {
constructor() {
this.items = JSON.parse(localStorage.getItem('cart')) || [];
this.updateCartCount();
}
addItem(productId, productName, price, quantity = 1) {
const existingItem = this.items.find(item => item.productId === productId);
if (existingItem) {
existingItem.quantity += quantity;
} else {
this.items.push({
productId,
productName,
price,
quantity
});
}
this.save();
this.updateCartCount();
this.showNotification(`${productName} added to cart`);
}
removeItem(productId) {
this.items = this.items.filter(item => item.productId !== productId);
this.save();
this.updateCartCount();
}
updateQuantity(productId, quantity) {
const item = this.items.find(item => item.productId === productId);
if (item) {
item.quantity = Math.max(1, quantity);
this.save();
this.updateCartCount();
}
}
clear() {
this.items = [];
this.save();
this.updateCartCount();
}
getTotal() {
return this.items.reduce((total, item) => total + (item.price * item.quantity), 0);
}
save() {
localStorage.setItem('cart', JSON.stringify(this.items));
}
updateCartCount() {
const count = this.items.reduce((sum, item) => sum + item.quantity, 0);
const badge = document.querySelector('.cart-count');
if (badge) {
badge.textContent = count;
badge.style.display = count > 0 ? 'block' : 'none';
}
}
showNotification(message) {
const notification = document.createElement('div');
notification.textContent = message;
notification.style.cssText = `
position: fixed;
bottom: 20px;
right: 20px;
background-color: var(--accent-dark);
color: white;
padding: 12px 20px;
border-radius: 4px;
font-size: 14px;
z-index: 1000;
animation: slideIn 0.3s ease;
`;
document.body.appendChild(notification);
setTimeout(() => {
notification.style.animation = 'slideOut 0.3s ease';
setTimeout(() => notification.remove(), 300);
}, 2000);
}
}
const cart = new Cart();
// Add CSS animations
const style = document.createElement('style');
style.textContent = `
@keyframes slideIn {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
@keyframes slideOut {
from {
transform: translateX(0);
opacity: 1;
}
to {
transform: translateX(100%);
opacity: 0;
}
}
`;
document.head.appendChild(style);
// ===== FORM HANDLING =====
document.querySelectorAll('form').forEach(form => {
// Skip cart-related, order, custom order, payment, and logout forms (they handle submission themselves)
if (form.action.includes('/cart/') ||
form.action.includes('/orders/') ||
form.action.includes('/custom-orders') ||
form.action.includes('/payment/') ||
form.action.includes('/track-order') ||
form.action.includes('/logout')) {
return;
}
form.addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
const data = Object.fromEntries(formData);
// Here you would typically send to backend
console.log('Form submitted:', data);
// Form submission handled - no popup message
this.reset();
});
});