📂 FileMgr
📍
/home/sgssmau.org/public_html/assets/js
✏️ Edit File: /home/sgssmau.org/public_html/assets/js/main.js
⬅ Kembali
// NGO Website JavaScript document.addEventListener('DOMContentLoaded', function() { // Initialize all components initSmoothScrolling(); initAnimations(); initFormValidation(); initNavbarScroll(); initContactForm(); initCounterAnimation(); initGalleryModal(); }); // Counter Animation function initCounterAnimation() { const counters = document.querySelectorAll('.counter'); const observerOptions = { threshold: 0.5, rootMargin: '0px 0px -100px 0px' }; const counterObserver = new IntersectionObserver(function(entries) { entries.forEach(entry => { if (entry.isIntersecting) { const counter = entry.target; const target = parseInt(counter.getAttribute('data-target')); animateCounter(counter, target); counterObserver.unobserve(counter); } }); }, observerOptions); counters.forEach(counter => { counterObserver.observe(counter); }); } function animateCounter(element, target) { let current = 0; const increment = target / 100; const timer = setInterval(() => { current += increment; element.textContent = Math.floor(current); if (current >= target) { element.textContent = target; clearInterval(timer); } }, 20); } // Gallery Modal function initGalleryModal() { const galleryLinks = document.querySelectorAll('.gallery-link'); galleryLinks.forEach(link => { link.addEventListener('click', function(e) { e.preventDefault(); // Add gallery modal functionality here }); }); } // Smooth scrolling for navigation links function initSmoothScrolling() { const navLinks = document.querySelectorAll('a[href^="#"]'); navLinks.forEach(link => { link.addEventListener('click', function(e) { const targetId = this.getAttribute('href'); if (targetId === '#' || targetId === '') return; try { const targetSection = document.querySelector(targetId); if (targetSection) { e.preventDefault(); const offsetTop = targetSection.offsetTop - 80; // Account for fixed navbar window.scrollTo({ top: offsetTop, behavior: 'smooth' }); } } catch (err) { console.warn("Invalid smooth scroll selector:", targetId); } }); }); } // Fade in animations on scroll function initAnimations() { const observerOptions = { threshold: 0.1, rootMargin: '0px 0px -50px 0px' }; const observer = new IntersectionObserver(function(entries) { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('visible'); } }); }, observerOptions); // Add fade-in class to elements const animatedElements = document.querySelectorAll('.feature-card, .cause-card, .event-card, .testimonial-card'); animatedElements.forEach(el => { el.classList.add('fade-in'); observer.observe(el); }); } // Form validation function initFormValidation() { const forms = document.querySelectorAll('form'); forms.forEach(form => { form.addEventListener('submit', function(e) { if (!validateForm(this)) { e.preventDefault(); } }); // Real-time validation const inputs = form.querySelectorAll('input, textarea, select'); inputs.forEach(input => { input.addEventListener('blur', function() { validateField(this); }); }); }); } function validateForm(form) { let isValid = true; const inputs = form.querySelectorAll('input[required], textarea[required], select[required]'); inputs.forEach(input => { if (!validateField(input)) { isValid = false; } }); return isValid; } function validateField(field) { const value = field.value.trim(); const fieldType = field.type; let isValid = true; let errorMessage = ''; // Remove existing error styling field.classList.remove('is-invalid'); const existingError = field.parentNode.querySelector('.invalid-feedback'); if (existingError) { existingError.remove(); } // Required field validation if (field.hasAttribute('required') && !value) { isValid = false; errorMessage = 'This field is required'; } // Email validation else if (fieldType === 'email' && value) { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(value)) { isValid = false; errorMessage = 'Please enter a valid email address'; } } // Phone validation else if (field.name === 'phone' && value) { const phoneRegex = /^[\+]?[1-9][\d]{0,15}$/; if (!phoneRegex.test(value.replace(/[\s\-\(\)]/g, ''))) { isValid = false; errorMessage = 'Please enter a valid phone number'; } } // Password validation else if (fieldType === 'password' && value) { if (value.length < 8) { isValid = false; errorMessage = 'Password must be at least 8 characters long'; } } // Confirm password validation else if (field.name === 'confirm_password' && value) { const passwordField = field.form.querySelector('input[name="password"]'); if (passwordField && value !== passwordField.value) { isValid = false; errorMessage = 'Passwords do not match'; } } // Show error if validation failed if (!isValid) { field.classList.add('is-invalid'); const errorDiv = document.createElement('div'); errorDiv.className = 'invalid-feedback'; errorDiv.textContent = errorMessage; field.parentNode.appendChild(errorDiv); } return isValid; } // Navbar scroll effect function initNavbarScroll() { const navbar = document.querySelector('.navbar'); window.addEventListener('scroll', function() { if (window.scrollY > 50) { navbar.classList.add('scrolled'); } else { navbar.classList.remove('scrolled'); } }); } // Contact form handling function initContactForm() { const contactForm = document.querySelector('.contact-form'); if (contactForm) { contactForm.addEventListener('submit', function(e) { e.preventDefault(); const formData = new FormData(this); const submitBtn = this.querySelector('button[type="submit"]'); const originalText = submitBtn.innerHTML; // Show loading state submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Sending...'; submitBtn.disabled = true; // Simulate form submission (replace with actual AJAX call) setTimeout(() => { showNotification('Message sent successfully!', 'success'); this.reset(); // Reset button submitBtn.innerHTML = originalText; submitBtn.disabled = false; }, 2000); }); } } // Notification system function showNotification(message, type = 'info') { const notification = document.createElement('div'); notification.className = `alert alert-${type} alert-dismissible fade show position-fixed`; notification.style.cssText = 'top: 20px; right: 20px; z-index: 9999; min-width: 300px;'; notification.innerHTML = ` ${message} <button type="button" class="btn-close" data-bs-dismiss="alert"></button> `; document.body.appendChild(notification); // Auto remove after 5 seconds setTimeout(() => { if (notification.parentNode) { notification.remove(); } }, 5000); } // Utility functions function formatCurrency(amount, currency = 'USD') { return new Intl.NumberFormat('en-US', { style: 'currency', currency: currency }).format(amount); } function formatDate(date, options = { year: 'numeric', month: 'long', day: 'numeric' }) { return new Date(date).toLocaleDateString('en-US', options); } // AJAX helper function function makeRequest(url, options = {}) { const defaultOptions = { method: 'GET', headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest' } }; const config = { ...defaultOptions, ...options }; return fetch(url, config) .then(response => { if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response.json(); }) .catch(error => { console.error('Request failed:', error); showNotification('An error occurred. Please try again.', 'danger'); throw error; }); } // File upload preview function previewImage(input, previewElement) { if (input.files && input.files[0]) { const reader = new FileReader(); reader.onload = function(e) { previewElement.src = e.target.result; previewElement.style.display = 'block'; }; reader.readAsDataURL(input.files[0]); } } // Progress bar animation function animateProgressBar(element, targetWidth) { let currentWidth = 0; const increment = targetWidth / 50; const timer = setInterval(() => { currentWidth += increment; element.style.width = currentWidth + '%'; if (currentWidth >= targetWidth) { clearInterval(timer); element.style.width = targetWidth + '%'; } }, 20); } // Initialize progress bars when they come into view function initProgressBars() { const progressBars = document.querySelectorAll('.progress-bar'); const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const progressBar = entry.target; const targetWidth = parseInt(progressBar.style.width) || 0; progressBar.style.width = '0%'; setTimeout(() => { animateProgressBar(progressBar, targetWidth); }, 500); observer.unobserve(progressBar); } }); }); progressBars.forEach(bar => observer.observe(bar)); } // Initialize progress bars initProgressBars(); // Lazy loading for images function initLazyLoading() { const images = document.querySelectorAll('img[data-src]'); const imageObserver = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target; img.src = img.dataset.src; img.classList.remove('lazy'); imageObserver.unobserve(img); } }); }); images.forEach(img => imageObserver.observe(img)); } // Initialize lazy loading initLazyLoading();
💾 Simpan File
Batal
⬅ Naik ke assets
1 item
Nama
Tipe
Ukuran
Diubah
Aksi
📜
main.js
js
11.3 KB
2026-06-04 11:53
✏️ Edit
👁️ View
🗑 Hapus