Spaces:
Sleeping
Sleeping
File size: 8,461 Bytes
1c9424e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | /**
* 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();
}
}
|