Student_Record / static /js /script.js
ministerchief's picture
Upload 12 files
1c9424e verified
Raw
History Blame Contribute Delete
8.46 kB
/**
* StudentMS β€” script.js
* Client-side validation, modals, and UI helpers.
*/
/* ═══════════════════════════════════════════
1. AUTO-DISMISS FLASH MESSAGES
═══════════════════════════════════════════ */
document.addEventListener('DOMContentLoaded', () => {
const alerts = document.querySelectorAll('.alert');
alerts.forEach(alert => {
setTimeout(() => {
alert.style.transition = 'opacity .4s, transform .4s';
alert.style.opacity = '0';
alert.style.transform = 'translateX(40px)';
setTimeout(() => alert.remove(), 420);
}, 4500);
});
});
/* ═══════════════════════════════════════════
2. MOBILE NAVBAR TOGGLE
═══════════════════════════════════════════ */
const navToggle = document.getElementById('navToggle');
const navLinks = document.getElementById('navLinks');
if (navToggle && navLinks) {
navToggle.addEventListener('click', () => {
navLinks.classList.toggle('open');
});
// Close when clicking outside
document.addEventListener('click', (e) => {
if (!navToggle.contains(e.target) && !navLinks.contains(e.target)) {
navLinks.classList.remove('open');
}
});
}
/* ═══════════════════════════════════════════
3. PASSWORD TOGGLE
═══════════════════════════════════════════ */
function togglePassword(inputId, btn) {
const input = document.getElementById(inputId);
const icon = btn.querySelector('i');
if (input.type === 'password') {
input.type = 'text';
icon.classList.replace('fa-eye', 'fa-eye-slash');
} else {
input.type = 'password';
icon.classList.replace('fa-eye-slash', 'fa-eye');
}
}
/* ═══════════════════════════════════════════
4. LOGIN FORM VALIDATION
═══════════════════════════════════════════ */
const loginForm = document.getElementById('loginForm');
if (loginForm) {
loginForm.addEventListener('submit', (e) => {
let valid = true;
const username = document.getElementById('username');
const password = document.getElementById('password');
const errUser = document.getElementById('err-username');
const errPass = document.getElementById('err-password');
// Reset
[errUser, errPass].forEach(el => { if (el) el.textContent = ''; });
[username, password].forEach(el => el.classList.remove('is-invalid'));
if (!username.value.trim()) {
errUser.textContent = 'Username is required.';
username.classList.add('is-invalid');
valid = false;
}
if (!password.value.trim()) {
errPass.textContent = 'Password is required.';
password.classList.add('is-invalid');
valid = false;
}
if (!valid) e.preventDefault();
});
}
/* ═══════════════════════════════════════════
5. STUDENT FORM VALIDATION (add & edit)
═══════════════════════════════════════════ */
const studentForm = document.getElementById('studentForm');
if (studentForm) {
studentForm.addEventListener('submit', (e) => {
const errors = validateStudentForm();
if (errors > 0) e.preventDefault();
});
}
function validateStudentForm() {
let errorCount = 0;
// Helper: show error
function showErr(fieldName, msg) {
const errEl = document.getElementById(`err-${fieldName}`);
const input = studentForm.querySelector(`[name="${fieldName}"]`);
if (errEl) errEl.textContent = msg;
if (input) input.classList.add('is-invalid');
errorCount++;
}
// Helper: clear error
function clearErr(fieldName) {
const errEl = document.getElementById(`err-${fieldName}`);
const input = studentForm.querySelector(`[name="${fieldName}"]`);
if (errEl) errEl.textContent = '';
if (input) input.classList.remove('is-invalid');
}
// Fields to validate
const required = [
'student_id', 'full_name', 'father_name', 'mother_name',
'gender', 'dob', 'email', 'phone',
'course', 'branch', 'year_sem',
'address', 'city', 'state', 'pin_code'
];
required.forEach(name => clearErr(name));
// Required check
required.forEach(name => {
const el = studentForm.querySelector(`[name="${name}"]`);
if (!el) return;
if (!el.value.trim()) {
const label = name.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
showErr(name, `${label} is required.`);
}
});
// Email format
const emailEl = studentForm.querySelector('[name="email"]');
if (emailEl && emailEl.value.trim()) {
const re = /^[\w.+-]+@[\w-]+\.[a-zA-Z]{2,}$/;
if (!re.test(emailEl.value.trim())) {
showErr('email', 'Enter a valid email address.');
}
}
// Phone β€” 10 digits only
const phoneEl = studentForm.querySelector('[name="phone"]');
if (phoneEl && phoneEl.value.trim()) {
if (!/^\d{10}$/.test(phoneEl.value.trim())) {
showErr('phone', 'Phone must be exactly 10 digits.');
}
}
// Pin code β€” 6 digits only
const pinEl = studentForm.querySelector('[name="pin_code"]');
if (pinEl && pinEl.value.trim()) {
if (!/^\d{6}$/.test(pinEl.value.trim())) {
showErr('pin_code', 'Pin Code must be exactly 6 digits.');
}
}
// Date of birth β€” must not be in the future
const dobEl = studentForm.querySelector('[name="dob"]');
if (dobEl && dobEl.value) {
const dob = new Date(dobEl.value);
if (dob >= new Date()) {
showErr('dob', 'Date of Birth cannot be in the future.');
}
}
return errorCount;
}
// Live phone & pin – allow only digits
document.addEventListener('DOMContentLoaded', () => {
const phoneInput = document.querySelector('[name="phone"]');
const pinInput = document.querySelector('[name="pin_code"]');
if (phoneInput) {
phoneInput.addEventListener('input', () => {
phoneInput.value = phoneInput.value.replace(/\D/g, '').slice(0, 10);
});
}
if (pinInput) {
pinInput.addEventListener('input', () => {
pinInput.value = pinInput.value.replace(/\D/g, '').slice(0, 6);
});
}
});
/* ═══════════════════════════════════════════
6. DELETE MODAL
═══════════════════════════════════════════ */
let pendingDeleteId = null;
function confirmDelete(studentId, studentName) {
pendingDeleteId = studentId;
const modal = document.getElementById('deleteModal');
const nameEl = document.getElementById('deleteStudentName');
if (nameEl) nameEl.textContent = studentName;
if (modal) modal.style.display = 'flex';
}
function closeModal() {
const modal = document.getElementById('deleteModal');
if (modal) modal.style.display = 'none';
pendingDeleteId = null;
}
function submitDelete() {
if (!pendingDeleteId) return;
const form = document.getElementById('deleteForm');
if (form) {
form.action = `/delete_student/${pendingDeleteId}`;
form.submit();
}
}
// Close modal when clicking backdrop
document.addEventListener('click', (e) => {
const modal = document.getElementById('deleteModal');
if (modal && e.target === modal) closeModal();
});
// Close modal on Escape key
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') closeModal();
});
/* ═══════════════════════════════════════════
7. SEARCH – CLEAR
═══════════════════════════════════════════ */
function clearSearch() {
const input = document.getElementById('searchInput');
if (input) {
input.value = '';
document.getElementById('searchForm').submit();
}
}