File manager - Edit - /home/webapp69.cm.in.th/u69319090004/Portfolio004/app.js
Back
document.addEventListener('DOMContentLoaded', () => { // ----------------------------------------- // 1. Dark Mode / Light Mode Management // ----------------------------------------- const themeToggleBtn = document.getElementById('theme-toggle'); const themeToggleIconDark = document.getElementById('theme-toggle-dark-icon'); const themeToggleIconLight = document.getElementById('theme-toggle-light-icon'); // Check system preference or localStorage const isDarkMode = localStorage.getItem('color-theme') === 'dark' || (!('color-theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches); function setTheme(dark) { if (dark) { document.documentElement.classList.add('dark'); themeToggleIconDark.classList.add('hidden'); themeToggleIconLight.classList.remove('hidden'); localStorage.setItem('color-theme', 'dark'); } else { document.documentElement.classList.remove('dark'); themeToggleIconLight.classList.add('hidden'); themeToggleIconDark.classList.remove('hidden'); localStorage.setItem('color-theme', 'light'); } } // Initialize Theme setTheme(isDarkMode); // Toggle Theme Click Event themeToggleBtn.addEventListener('click', () => { const darkActive = document.documentElement.classList.contains('dark'); setTheme(!darkActive); }); // ----------------------------------------- // 2. Mobile Hamburger Menu (Slide Drawer) // ----------------------------------------- const menuBtn = document.getElementById('menu-btn'); const closeBtn = document.getElementById('close-btn'); const mobileMenu = document.getElementById('mobile-menu'); const mobileMenuLinks = document.querySelectorAll('.mobile-menu-link'); function toggleMenu() { const isOpen = mobileMenu.classList.contains('translate-x-0'); if (isOpen) { mobileMenu.classList.remove('translate-x-0'); mobileMenu.classList.add('translate-x-full'); document.body.style.overflow = ''; // restore scrolling } else { mobileMenu.classList.remove('translate-x-full'); mobileMenu.classList.add('translate-x-0'); document.body.style.overflow = 'hidden'; // prevent scrolling behind menu } } menuBtn.addEventListener('click', toggleMenu); closeBtn.addEventListener('click', toggleMenu); // Close mobile menu when a link is clicked mobileMenuLinks.forEach(link => { link.addEventListener('click', () => { mobileMenu.classList.remove('translate-x-0'); mobileMenu.classList.add('translate-x-full'); document.body.style.overflow = ''; }); }); // ----------------------------------------- // 3. Contact Form Submission // ----------------------------------------- const contactForm = document.getElementById('contact-form'); const formFeedback = document.getElementById('form-feedback'); const submitBtn = contactForm.querySelector('button[type="submit"]'); contactForm.addEventListener('submit', (e) => { e.preventDefault(); // Show spinner / loading state submitBtn.disabled = true; const originalBtnText = submitBtn.innerHTML; submitBtn.innerHTML = ` <svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-white inline-block" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"> <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle> <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path> </svg> กำลังส่งข้อความ... `; // Simulate network delay setTimeout(() => { submitBtn.disabled = false; submitBtn.innerHTML = originalBtnText; // Show Success Alert formFeedback.classList.remove('hidden'); formFeedback.classList.add('flex'); // Clear inputs contactForm.reset(); // Auto-hide alert after 5 seconds setTimeout(() => { formFeedback.classList.add('hidden'); formFeedback.classList.remove('flex'); }, 5000); }, 1500); }); // ----------------------------------------- // 4. Smooth Fade-in on Scroll Animation // ----------------------------------------- const observerOptions = { root: null, rootMargin: '0px', threshold: 0.15 }; const fadeObserver = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.remove('opacity-0', 'translate-y-8'); entry.target.classList.add('opacity-100', 'translate-y-0'); observer.unobserve(entry.target); // stop observing once animated } }); }, observerOptions); // Apply observer to specific sections const scrollRevealElements = document.querySelectorAll('.scroll-reveal'); scrollRevealElements.forEach(el => { fadeObserver.observe(el); }); // ----------------------------------------- // 4.1. Active Section Navigation Highlighter // ----------------------------------------- const navSections = document.querySelectorAll('section[id]'); const desktopNavLinks = document.querySelectorAll('header nav a'); const bottomNavLinks = document.querySelectorAll('.bottom-nav-link'); const activeSectionObserver = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const id = entry.target.getAttribute('id'); // Highlight desktop links desktopNavLinks.forEach(link => { if (link.getAttribute('href') === `#${id}`) { link.classList.add('text-brand-600', 'dark:text-brand-400'); link.classList.remove('text-slate-600', 'dark:text-slate-300'); } else { link.classList.remove('text-brand-600', 'dark:text-brand-400'); link.classList.add('text-slate-600', 'dark:text-slate-300'); } }); // Highlight sticky bottom menu links bottomNavLinks.forEach(link => { if (link.getAttribute('href') === `#${id}`) { link.classList.add('text-brand-600', 'dark:text-brand-400'); link.classList.remove('text-slate-600', 'dark:text-slate-400'); } else { link.classList.remove('text-brand-600', 'dark:text-brand-400'); link.classList.add('text-slate-600', 'dark:text-slate-400'); } }); } }); }, { root: null, rootMargin: '-30% 0px -30% 0px' }); navSections.forEach(section => { activeSectionObserver.observe(section); }); // ----------------------------------------- // 5. Interactive Before/After Image Slider & Preset Filters // ----------------------------------------- const beforeAfterSlider = document.getElementById('before-after-slider'); const sliderOverlay = document.getElementById('slider-overlay'); const sliderLine = document.getElementById('slider-line'); const sliderAfterImg = document.getElementById('slider-after-img'); function updateSlider() { if (!beforeAfterSlider || !sliderOverlay || !sliderLine || !sliderAfterImg) return; const val = beforeAfterSlider.value; sliderOverlay.style.width = val + '%'; sliderLine.style.left = val + '%'; sliderAfterImg.style.width = beforeAfterSlider.parentElement.clientWidth + 'px'; } if (beforeAfterSlider) { beforeAfterSlider.addEventListener('input', updateSlider); window.addEventListener('resize', updateSlider); // Initialize with small delay to ensure container width is rendered setTimeout(updateSlider, 200); } const filterBtns = document.querySelectorAll('.filter-btn'); if (filterBtns.length > 0 && sliderAfterImg) { filterBtns.forEach(btn => { btn.addEventListener('click', () => { // Remove active classes filterBtns.forEach(b => { b.classList.remove('active', 'bg-slate-50', 'dark:bg-slate-800'); b.classList.add('text-slate-600', 'dark:text-slate-400'); }); // Add active classes btn.classList.add('active', 'bg-slate-50', 'dark:bg-slate-800'); btn.classList.remove('text-slate-600', 'dark:text-slate-400'); const filterType = btn.getAttribute('data-filter'); if (filterType === 'original') { sliderAfterImg.style.filter = 'none'; } else if (filterType === 'vivid') { sliderAfterImg.style.filter = 'saturate(1.5) contrast(1.1) brightness(1.05)'; } else if (filterType === 'vintage') { sliderAfterImg.style.filter = 'sepia(0.4) saturate(1.2) hue-rotate(-10deg) brightness(0.95)'; } else if (filterType === 'cinematic') { sliderAfterImg.style.filter = 'contrast(1.25) brightness(0.85) saturate(0.85) hue-rotate(15deg)'; } else if (filterType === 'cyberpunk') { sliderAfterImg.style.filter = 'hue-rotate(130deg) saturate(1.7) contrast(1.2) brightness(1.05)'; } }); }); } // ----------------------------------------- // 6. Interactive Cat Gallery // ----------------------------------------- const catGalleryImg = document.getElementById('cat-gallery-img'); const catThumbBtns = document.querySelectorAll('.cat-thumb-btn'); if (catGalleryImg && catThumbBtns.length > 0) { catThumbBtns.forEach(btn => { btn.addEventListener('click', () => { // Remove active styling from all buttons catThumbBtns.forEach(b => { b.classList.remove('active', 'border-white'); b.classList.add('border-transparent'); }); // Add active styling to clicked button btn.classList.add('active', 'border-white'); btn.classList.remove('border-transparent'); // Change main image with fade effect const targetImg = btn.getAttribute('data-img'); catGalleryImg.style.opacity = '0.3'; setTimeout(() => { catGalleryImg.src = targetImg; catGalleryImg.style.opacity = '1'; }, 150); }); }); } });
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Generation time: 0.33 |
proxy
|
phpinfo
|
Settings