| Server IP : 52.202.253.110 / Your IP : 216.73.217.139 Web Server : Apache/2.4.56 (Amazon Linux) OpenSSL/3.0.8 System : Linux ip-172-32-10-67.ec2.internal 6.1.49-70.116.amzn2023.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Sep 6 22:13:07 UTC 2023 x86_64 User : ec2-user ( 1000) PHP Version : 8.2.9 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/vhosts/micheleleasurept_html/ |
Upload File : |
// Mobile Navigation Toggle
document.addEventListener('DOMContentLoaded', function() {
const hamburger = document.querySelector('.hamburger');
const navMenu = document.querySelector('.nav-menu');
const navLinks = document.querySelectorAll('.nav-link');
// Toggle mobile menu
hamburger.addEventListener('click', function() {
hamburger.classList.toggle('active');
navMenu.classList.toggle('active');
});
// Close mobile menu when clicking on a link
navLinks.forEach(link => {
link.addEventListener('click', function() {
hamburger.classList.remove('active');
navMenu.classList.remove('active');
});
});
// Close mobile menu when clicking outside
document.addEventListener('click', function(event) {
if (!hamburger.contains(event.target) && !navMenu.contains(event.target)) {
hamburger.classList.remove('active');
navMenu.classList.remove('active');
}
});
});
// Smooth Scrolling 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) {
const offsetTop = target.offsetTop - 80; // Account for fixed navbar
window.scrollTo({
top: offsetTop,
behavior: 'smooth'
});
}
});
});
// Navbar Background Change on Scroll
window.addEventListener('scroll', function() {
const navbar = document.querySelector('.navbar');
if (window.scrollY > 100) {
navbar.style.backgroundColor = 'rgba(255, 255, 255, 0.98)';
navbar.style.boxShadow = '0 4px 6px -1px rgb(0 0 0 / 0.1)';
} else {
navbar.style.backgroundColor = 'rgba(255, 255, 255, 0.95)';
navbar.style.boxShadow = '0 1px 2px 0 rgb(0 0 0 / 0.05)';
}
});
// Form Handling
document.querySelector('.form').addEventListener('submit', function(e) {
e.preventDefault();
// Get form data
const formData = new FormData(this);
const data = Object.fromEntries(formData);
// Basic validation
if (!data.name || !data.email || !data.phone || !data.service) {
showNotification('Please fill in all required fields.', 'error');
return;
}
// Email validation
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(data.email)) {
showNotification('Please enter a valid email address.', 'error');
return;
}
// Phone validation (basic)
const phoneRegex = /^[\+]?[1-9][\d]{0,15}$/;
if (!phoneRegex.test(data.phone.replace(/\D/g, ''))) {
showNotification('Please enter a valid phone number.', 'error');
return;
}
// Simulate form submission
const submitButton = this.querySelector('button[type="submit"]');
const originalText = submitButton.textContent;
submitButton.textContent = 'Sending...';
submitButton.disabled = true;
// Simulate API call
setTimeout(() => {
showNotification('Thank you! Your appointment request has been sent. We will contact you within 24 hours.', 'success');
this.reset();
submitButton.textContent = originalText;
submitButton.disabled = false;
}, 2000);
});
// Notification System
function showNotification(message, type = 'info') {
// Remove existing notifications
const existingNotifications = document.querySelectorAll('.notification');
existingNotifications.forEach(notification => notification.remove());
// Create notification element
const notification = document.createElement('div');
notification.className = `notification notification-${type}`;
notification.innerHTML = `
<div class="notification-content">
<span class="notification-message">${message}</span>
<button class="notification-close">×</button>
</div>
`;
// Add styles
notification.style.cssText = `
position: fixed;
top: 100px;
right: 20px;
background: ${type === 'success' ? '#10b981' : type === 'error' ? '#ef4444' : '#3b82f6'};
color: white;
padding: 1rem 1.5rem;
border-radius: 0.5rem;
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1);
z-index: 1001;
max-width: 400px;
animation: slideInRight 0.3s ease-out;
`;
// Add close functionality
const closeButton = notification.querySelector('.notification-close');
closeButton.style.cssText = `
background: none;
border: none;
color: white;
font-size: 1.5rem;
cursor: pointer;
margin-left: 1rem;
padding: 0;
`;
closeButton.addEventListener('click', () => {
notification.style.animation = 'slideOutRight 0.3s ease-out';
setTimeout(() => notification.remove(), 300);
});
// Add to page
document.body.appendChild(notification);
// Auto remove after 5 seconds
setTimeout(() => {
if (notification.parentNode) {
notification.style.animation = 'slideOutRight 0.3s ease-out';
setTimeout(() => notification.remove(), 300);
}
}, 5000);
}
// Add notification animations to CSS
const notificationStyles = document.createElement('style');
notificationStyles.textContent = `
@keyframes slideInRight {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
@keyframes slideOutRight {
from {
transform: translateX(0);
opacity: 1;
}
to {
transform: translateX(100%);
opacity: 0;
}
}
.notification-content {
display: flex;
align-items: center;
justify-content: space-between;
}
`;
document.head.appendChild(notificationStyles);
// Intersection Observer for Animations
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 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.addEventListener('DOMContentLoaded', function() {
const animatedElements = document.querySelectorAll('.service-card, .testimonial-card, .approach-point, .credential-item');
animatedElements.forEach(el => {
el.style.opacity = '0';
el.style.transform = 'translateY(30px)';
el.style.transition = 'opacity 0.6s ease-out, transform 0.6s ease-out';
observer.observe(el);
});
});
// Form Input Enhancement
document.addEventListener('DOMContentLoaded', function() {
const inputs = document.querySelectorAll('input, select, textarea');
inputs.forEach(input => {
// Add focus/blur effects
input.addEventListener('focus', function() {
this.parentNode.classList.add('focused');
});
input.addEventListener('blur', function() {
this.parentNode.classList.remove('focused');
if (this.value) {
this.parentNode.classList.add('filled');
} else {
this.parentNode.classList.remove('filled');
}
});
// Check if input has value on load
if (input.value) {
input.parentNode.classList.add('filled');
}
});
});
// Accessibility Enhancements
document.addEventListener('DOMContentLoaded', function() {
// Add keyboard navigation for mobile menu
hamburger.addEventListener('keydown', function(e) {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
this.click();
}
});
// Add ARIA labels for better accessibility
const hamburger = document.querySelector('.hamburger');
if (hamburger) {
hamburger.setAttribute('aria-label', 'Toggle navigation menu');
hamburger.setAttribute('role', 'button');
hamburger.setAttribute('tabindex', '0');
}
// Add skip link for keyboard users
const skipLink = document.createElement('a');
skipLink.href = '#main-content';
skipLink.textContent = 'Skip to main content';
skipLink.className = 'skip-link';
skipLink.style.cssText = `
position: absolute;
top: -40px;
left: 6px;
background: #000;
color: #fff;
padding: 8px;
text-decoration: none;
z-index: 1002;
border-radius: 4px;
`;
skipLink.addEventListener('focus', function() {
this.style.top = '6px';
});
skipLink.addEventListener('blur', function() {
this.style.top = '-40px';
});
document.body.insertBefore(skipLink, document.body.firstChild);
// Add main content ID
const heroSection = document.querySelector('.hero');
if (heroSection) {
heroSection.id = 'main-content';
}
});
// Performance Optimization - Lazy Loading for Images
document.addEventListener('DOMContentLoaded', function() {
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.remove('lazy');
imageObserver.unobserve(img);
}
});
});
const lazyImages = document.querySelectorAll('img[data-src]');
lazyImages.forEach(img => imageObserver.observe(img));
}
});
// Contact Form Phone Number Formatting
document.addEventListener('DOMContentLoaded', function() {
const phoneInput = document.querySelector('input[name="phone"]');
if (phoneInput) {
phoneInput.addEventListener('input', function(e) {
let value = e.target.value.replace(/\D/g, '');
if (value.length >= 6) {
value = value.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');
} else if (value.length >= 3) {
value = value.replace(/(\d{3})(\d{0,3})/, '($1) $2');
}
e.target.value = value;
});
}
});
// Scroll to Top Functionality
document.addEventListener('DOMContentLoaded', function() {
// Create scroll to top button
const scrollTopBtn = document.createElement('button');
scrollTopBtn.innerHTML = '↑';
scrollTopBtn.className = 'scroll-top-btn';
scrollTopBtn.setAttribute('aria-label', 'Scroll to top');
scrollTopBtn.style.cssText = `
position: fixed;
bottom: 20px;
right: 20px;
width: 50px;
height: 50px;
border-radius: 50%;
background: var(--primary-color);
color: white;
border: none;
font-size: 20px;
cursor: pointer;
opacity: 0;
visibility: hidden;
transition: all 0.3s ease;
z-index: 1000;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
`;
document.body.appendChild(scrollTopBtn);
// Show/hide scroll to top button
window.addEventListener('scroll', function() {
if (window.pageYOffset > 300) {
scrollTopBtn.style.opacity = '1';
scrollTopBtn.style.visibility = 'visible';
} else {
scrollTopBtn.style.opacity = '0';
scrollTopBtn.style.visibility = 'hidden';
}
});
// Scroll to top functionality
scrollTopBtn.addEventListener('click', function() {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
});
});
// Error Handling for External Resources
window.addEventListener('error', function(e) {
console.warn('Resource failed to load:', e.target.src || e.target.href);
}, true);
// Service Worker Registration (for future PWA capabilities)
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
// Uncomment when service worker is implemented
// navigator.serviceWorker.register('/sw.js')
// .then(registration => console.log('SW registered'))
// .catch(error => console.log('SW registration failed'));
});
}