Initial commit: konesaliturku.fi website
Colocation/datacenter service website with: - One-page main site (hero, services, pricing, contact form) - Technical specs page (power, cooling, connectivity, security) - Dark blue technical theme, fully responsive - PHP backend for contact form with rate limiting Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
126
script.js
Normal file
126
script.js
Normal file
@@ -0,0 +1,126 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
// === Mobile nav toggle ===
|
||||
const navToggle = document.getElementById('nav-toggle');
|
||||
const nav = document.getElementById('nav');
|
||||
|
||||
if (navToggle && nav) {
|
||||
navToggle.addEventListener('click', () => {
|
||||
nav.classList.toggle('open');
|
||||
navToggle.classList.toggle('open');
|
||||
});
|
||||
|
||||
// Close nav on link click
|
||||
nav.querySelectorAll('a').forEach(link => {
|
||||
link.addEventListener('click', () => {
|
||||
nav.classList.remove('open');
|
||||
navToggle.classList.remove('open');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// === Sticky header ===
|
||||
const header = document.getElementById('header');
|
||||
if (header) {
|
||||
window.addEventListener('scroll', () => {
|
||||
header.classList.toggle('scrolled', window.scrollY > 50);
|
||||
}, { passive: true });
|
||||
}
|
||||
|
||||
// === Scroll animations ===
|
||||
const observerOptions = {
|
||||
threshold: 0.1,
|
||||
rootMargin: '0px 0px -50px 0px'
|
||||
};
|
||||
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.classList.add('visible');
|
||||
observer.unobserve(entry.target);
|
||||
}
|
||||
});
|
||||
}, observerOptions);
|
||||
|
||||
// Add fade-in to sections
|
||||
document.querySelectorAll('.service-card, .feature, .pricing-card, .contact-form, .contact-info').forEach(el => {
|
||||
el.classList.add('fade-in');
|
||||
observer.observe(el);
|
||||
});
|
||||
|
||||
// === Contact form ===
|
||||
const form = document.getElementById('contact-form');
|
||||
const formStatus = document.getElementById('form-status');
|
||||
|
||||
if (form) {
|
||||
form.addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
const submitBtn = form.querySelector('.btn-submit');
|
||||
const originalText = submitBtn.textContent;
|
||||
submitBtn.textContent = 'Lähetetään...';
|
||||
submitBtn.disabled = true;
|
||||
|
||||
// Honeypot check
|
||||
const honeypot = form.querySelector('input[name="website"]');
|
||||
if (honeypot && honeypot.value) {
|
||||
formStatus.textContent = 'Kiitos viestistäsi!';
|
||||
formStatus.className = 'form-status success';
|
||||
form.reset();
|
||||
submitBtn.textContent = originalText;
|
||||
submitBtn.disabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = new FormData(form);
|
||||
|
||||
try {
|
||||
const response = await fetch('api.php?action=contact', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
formStatus.textContent = 'Kiitos viestistäsi! Otamme yhteyttä pian.';
|
||||
formStatus.className = 'form-status success';
|
||||
form.reset();
|
||||
} else {
|
||||
formStatus.textContent = data.error || 'Viestin lähetys epäonnistui. Yritä uudelleen.';
|
||||
formStatus.className = 'form-status error';
|
||||
}
|
||||
} catch {
|
||||
formStatus.textContent = 'Viestin lähetys epäonnistui. Yritä uudelleen.';
|
||||
formStatus.className = 'form-status error';
|
||||
}
|
||||
|
||||
submitBtn.textContent = originalText;
|
||||
submitBtn.disabled = false;
|
||||
});
|
||||
}
|
||||
|
||||
// === Active nav link on scroll ===
|
||||
const sections = document.querySelectorAll('section[id]');
|
||||
const navLinks = document.querySelectorAll('.nav a[href^="#"]');
|
||||
|
||||
if (sections.length && navLinks.length) {
|
||||
window.addEventListener('scroll', () => {
|
||||
let current = '';
|
||||
sections.forEach(section => {
|
||||
const top = section.offsetTop - 100;
|
||||
if (window.scrollY >= top) {
|
||||
current = section.getAttribute('id');
|
||||
}
|
||||
});
|
||||
|
||||
navLinks.forEach(link => {
|
||||
link.classList.remove('active');
|
||||
if (link.getAttribute('href') === '#' + current) {
|
||||
link.classList.add('active');
|
||||
}
|
||||
});
|
||||
}, { passive: true });
|
||||
}
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user