File manager - Edit - /home/webapp69.cm.in.th/u69319090003/portfolio/script.js
Back
/* ========================================================================== PORTFOLIO LOGIC Features: Responsive Mobile Menu, Active Scroll Indicators, Sticky Navbar, and Contact Form handling. Author: Kasama ========================================================================== */ document.addEventListener('DOMContentLoaded', () => { // --- 1. Sticky Navbar & Header Glow --- const navbar = document.getElementById('navbar'); window.addEventListener('scroll', () => { if (window.scrollY > 50) { navbar.classList.add('scrolled'); } else { navbar.classList.remove('scrolled'); } }); // --- 2. Mobile Menu (Hamburger Toggle) --- const hamburgerToggle = document.getElementById('hamburgerToggle'); const navMenu = document.getElementById('navMenu'); const navLinks = document.querySelectorAll('.nav-link'); const toggleMenu = () => { hamburgerToggle.classList.toggle('active'); navMenu.classList.toggle('active'); // Prevent background scrolling when menu is active document.body.style.overflow = navMenu.classList.contains('active') ? 'hidden' : 'auto'; }; const closeMenu = () => { hamburgerToggle.classList.remove('active'); navMenu.classList.remove('active'); document.body.style.overflow = 'auto'; }; hamburgerToggle.addEventListener('click', toggleMenu); // Close menu when clicking on any nav link navLinks.forEach(link => { link.addEventListener('click', closeMenu); }); // Close mobile menu if clicked outside document.addEventListener('click', (e) => { if (navMenu.classList.contains('active') && !navMenu.contains(e.target) && !hamburgerToggle.contains(e.target)) { closeMenu(); } }); // --- 3. Scroll Active Link Indicator --- const sections = document.querySelectorAll('section'); const observerOptions = { root: null, rootMargin: '-20% 0px -60% 0px', // Trigger when section occupies the middle of screen threshold: 0 }; const observerCallback = (entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const id = entry.target.getAttribute('id'); // Remove active class from all links navLinks.forEach(link => { link.classList.remove('active'); if (link.getAttribute('href') === `#${id}`) { link.classList.add('active'); } }); } }); }; const observer = new IntersectionObserver(observerCallback, observerOptions); sections.forEach(section => observer.observe(section)); // --- 4. Interactive Contact Form Handler --- const contactForm = document.getElementById('contactForm'); const btnSubmit = document.getElementById('btnSubmit'); const btnText = btnSubmit.querySelector('.btn-text'); const btnLoader = btnSubmit.querySelector('.btn-loader'); const formStatus = document.getElementById('formStatus'); contactForm.addEventListener('submit', (e) => { e.preventDefault(); // Stop page reload // Form field data retrieval (ready for real back-end hookup) const formData = { name: document.getElementById('name').value, email: document.getElementById('email').value, message: document.getElementById('message').value }; console.log('Sending message:', formData); // Enter loading/sending state btnSubmit.disabled = true; btnText.classList.add('hidden'); btnLoader.classList.remove('hidden'); formStatus.classList.add('hidden'); // Simulate modern API network lag setTimeout(() => { // Success response state btnSubmit.disabled = false; btnText.classList.remove('hidden'); btnLoader.classList.add('hidden'); // Reveal success state status formStatus.classList.remove('hidden'); // Reset form input values contactForm.reset(); // Auto-hide success message after 5 seconds setTimeout(() => { formStatus.classList.add('hidden'); }, 5000); }, 1500); // 1.5 seconds mock latency }); // --- 5. Micro-Animations on Scroll --- // Smooth fade in animation wrapper (optional feature to wow the user) const fadeElements = document.querySelectorAll('.project-card, .channel-card, .skill-badge'); const fadeObserver = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.style.opacity = '1'; entry.target.style.transform = 'translateY(0)'; } }); }, { threshold: 0.1 }); fadeElements.forEach(el => { el.style.opacity = '0'; el.style.transform = 'translateY(20px)'; el.style.transition = 'all 0.6s cubic-bezier(0.16, 1, 0.3, 1)'; fadeObserver.observe(el); }); });
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Generation time: 0.33 |
proxy
|
phpinfo
|
Settings