threadr.lostcave.ddnss.de/static/forms.js

213 lines
7.0 KiB
JavaScript

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);
}
});
});
}