function showNotification(message, type = 'info', duration = 3000) { const notification = document.createElement('div'); notification.className = `notification ${type}`; notification.textContent = message; document.body.appendChild(notification); setTimeout(() => { notification.classList.add('hiding'); setTimeout(() => { document.body.removeChild(notification); }, 300); }, duration); } function handleFormSubmit(form, button) { if (button) { button.disabled = true; button.classList.add('loading'); } const submitButtons = form.querySelectorAll('input[type="submit"], button[type="submit"]'); submitButtons.forEach(btn => { btn.disabled = true; btn.classList.add('loading'); }); } function removeLoadingState(form) { const submitButtons = form.querySelectorAll('input[type="submit"], button[type="submit"]'); submitButtons.forEach(btn => { btn.disabled = false; btn.classList.remove('loading'); }); } function enableEnterToSubmit(input, form) { input.addEventListener('keydown', (e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); form.requestSubmit(); } }); } function autoResizeTextarea(textarea) { textarea.style.height = 'auto'; textarea.style.height = textarea.scrollHeight + 'px'; } function addCharacterCounter(textarea, maxLength) { const counter = document.createElement('div'); counter.className = 'char-counter'; textarea.parentNode.insertBefore(counter, textarea.nextSibling); const updateCounter = () => { const length = textarea.value.length; counter.textContent = `${length}/${maxLength}`; if (length > maxLength * 0.9) { counter.classList.add('warning'); } else { counter.classList.remove('warning'); } }; textarea.addEventListener('input', updateCounter); updateCounter(); } function initFormHandling() { document.querySelectorAll('form').forEach(form => { form.addEventListener('submit', () => { const submitButton = form.querySelector('input[type="submit"], button[type="submit"]'); handleFormSubmit(form, submitButton); }); }); document.querySelectorAll('textarea').forEach(textarea => { textarea.addEventListener('input', () => autoResizeTextarea(textarea)); if (textarea.id === 'content' || textarea.name === 'content') { addCharacterCounter(textarea, 10000); } if (textarea.id === 'bio' || textarea.name === 'bio') { addCharacterCounter(textarea, 500); } }); const loginForm = document.querySelector('form[action*="login"]'); if (loginForm) { const passwordInput = loginForm.querySelector('input[type="password"]'); if (passwordInput) { enableEnterToSubmit(passwordInput, loginForm); } } const loginUsername = document.querySelector('input[name="username"]'); const loginPassword = document.querySelector('input[name="password"]'); if (loginUsername && loginPassword) { loginUsername.addEventListener('blur', () => { const error = validateRequired(loginUsername.value, 'Username'); if (error) { showFieldError(loginUsername, error); } else { clearFieldError(loginUsername); } }); loginPassword.addEventListener('blur', () => { const error = validateRequired(loginPassword.value, 'Password'); if (error) { showFieldError(loginPassword, error); } else { clearFieldError(loginPassword); } }); } const signupForm = document.querySelector('form[action*="signup"]'); if (signupForm) { const usernameInput = signupForm.querySelector('input[name="username"]'); const passwordInput = signupForm.querySelector('input[name="password"]'); const confirmInput = signupForm.querySelector('input[name="password_confirm"]'); if (usernameInput) { usernameInput.addEventListener('blur', () => { const error = validateUsername(usernameInput.value); if (error) { showFieldError(usernameInput, error); } else { clearFieldError(usernameInput); } }); } if (passwordInput) { passwordInput.addEventListener('blur', () => { const error = validatePassword(passwordInput.value); if (error) { showFieldError(passwordInput, error); } else { clearFieldError(passwordInput); } }); } if (confirmInput && passwordInput) { confirmInput.addEventListener('blur', () => { if (confirmInput.value !== passwordInput.value) { showFieldError(confirmInput, 'Passwords do not match'); } else { clearFieldError(confirmInput); } }); } signupForm.addEventListener('submit', (e) => { let hasError = false; if (usernameInput) { const error = validateUsername(usernameInput.value); if (error) { showFieldError(usernameInput, error); hasError = true; } } if (passwordInput) { const error = validatePassword(passwordInput.value); if (error) { showFieldError(passwordInput, error); hasError = true; } } if (confirmInput && passwordInput && confirmInput.value !== passwordInput.value) { showFieldError(confirmInput, 'Passwords do not match'); hasError = true; } if (hasError) { e.preventDefault(); removeLoadingState(signupForm); showNotification('Please fix the errors before submitting', 'error'); } }); } document.querySelectorAll('input[name="title"]').forEach(input => { input.addEventListener('blur', () => { const error = validateRequired(input.value, 'Title'); if (error) { showFieldError(input, error); } else if (input.value.length > 255) { showFieldError(input, 'Title is too long (max 255 characters)'); } else { clearFieldError(input); } }); }); document.querySelectorAll('textarea[name="content"]').forEach(textarea => { textarea.addEventListener('blur', () => { const error = validateRequired(textarea.value, 'Content'); if (error) { showFieldError(textarea, error); } else { clearFieldError(textarea); } }); }); }