Download assets/JS/login.js from JSWAI/XENXOS: direct link, hf CLI and curl.
- Browser
- Download file 5.68 kB
-
https://huggingface.co/spaces/JSWAI/XENXOS/resolve/main/assets/JS/login.js
- Command line
-
hf download hf://spaces/JSWAI/XENXOS/assets/JS/login.js
-
curl -L -o login.js https://huggingface.co/spaces/JSWAI/XENXOS/resolve/main/assets/JS/login.js
5.68 kB
| /* ========================================================================== | |
| XENEX GLASS OS — Login Screen Behavior | |
| assets/JS/login.js | |
| This file handles UI behavior only: password visibility and client-side | |
| form validation. It does NOT authenticate anyone. There is no backend | |
| yet, so submitting the form cannot and does not log a user in — it only | |
| reports that sign-in isn't wired up yet. See the comment above | |
| handleSubmit() for where the real API call goes once it exists. | |
| ========================================================================== */ | |
| document.addEventListener('DOMContentLoaded', () => { | |
| initPasswordToggle(); | |
| initFormValidation(); | |
| }); | |
| /* ---- Password visibility toggle ---- */ | |
| function initPasswordToggle() { | |
| const toggleButton = document.querySelector('[data-password-toggle]'); | |
| const passwordInput = document.getElementById('password'); | |
| if (!toggleButton || !passwordInput) return; | |
| toggleButton.addEventListener('click', () => { | |
| const isHidden = passwordInput.type === 'password'; | |
| passwordInput.type = isHidden ? 'text' : 'password'; | |
| toggleButton.setAttribute('aria-pressed', String(isHidden)); | |
| toggleButton.setAttribute('aria-label', isHidden ? 'Hide password' : 'Show password'); | |
| const toggleText = toggleButton.querySelector('.login-field__toggle-text'); | |
| if (toggleText) { | |
| toggleText.textContent = isHidden ? 'Hide' : 'Show'; | |
| } | |
| }); | |
| } | |
| /* ---- Form validation + submit ---- */ | |
| function initFormValidation() { | |
| const form = document.querySelector('.login-form'); | |
| const emailInput = document.getElementById('email'); | |
| const passwordInput = document.getElementById('password'); | |
| if (!form || !emailInput || !passwordInput) return; | |
| const statusRegion = createStatusRegion(form); | |
| form.addEventListener('submit', (event) => { | |
| event.preventDefault(); | |
| clearFieldErrors(form); | |
| setStatus(statusRegion, '', null); | |
| const errors = validateFields(emailInput, passwordInput); | |
| if (errors.length > 0) { | |
| errors.forEach(({ input, message }) => showFieldError(input, message)); | |
| errors[0].input.focus(); | |
| return; | |
| } | |
| handleSubmit({ email: emailInput.value.trim() }); | |
| }); | |
| // Clear a field's error state as soon as the person edits it. | |
| [emailInput, passwordInput].forEach((input) => { | |
| input.addEventListener('input', () => clearFieldError(input)); | |
| }); | |
| } | |
| function validateFields(emailInput, passwordInput) { | |
| const errors = []; | |
| const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; | |
| if (emailInput.value.trim() === '') { | |
| errors.push({ input: emailInput, message: 'Enter your email address.' }); | |
| } else if (!emailPattern.test(emailInput.value.trim())) { | |
| errors.push({ input: emailInput, message: 'Enter a valid email address.' }); | |
| } | |
| if (passwordInput.value === '') { | |
| errors.push({ input: passwordInput, message: 'Enter your password.' }); | |
| } | |
| return errors; | |
| } | |
| /* | |
| * There is no backend yet. When one exists, this is where the real | |
| * request goes, e.g.: | |
| * | |
| * const response = await fetch('/auth/login', { | |
| * method: 'POST', | |
| * headers: { 'Content-Type': 'application/json' }, | |
| * body: JSON.stringify({ email, password }), | |
| * credentials: 'include' // secure HttpOnly session cookie, not a token in JS | |
| * }); | |
| * | |
| * Until that endpoint exists, do not simulate a response. Tell the person | |
| * plainly that sign-in isn't connected yet. | |
| */ | |
| function handleSubmit({ email }) { | |
| const form = document.querySelector('.login-form'); | |
| const statusRegion = form.querySelector('[data-login-status]'); | |
| const submitButton = document.querySelector('[data-login-submit]'); | |
| submitButton.disabled = true; | |
| setStatus( | |
| statusRegion, | |
| "Sign-in isn't connected to a server yet. This form will work once the Xenex backend is live.", | |
| 'info' | |
| ); | |
| console.info('[Xenex] Login form submitted with no backend configured.', { email }); | |
| submitButton.disabled = false; | |
| } | |
| /* ---- Field error helpers ---- */ | |
| function showFieldError(input, message) { | |
| const field = input.closest('.login-field'); | |
| if (!field) return; | |
| field.classList.add('login-field--error'); | |
| input.setAttribute('aria-invalid', 'true'); | |
| let errorEl = field.querySelector('.login-field__error'); | |
| if (!errorEl) { | |
| errorEl = document.createElement('p'); | |
| errorEl.className = 'login-field__error'; | |
| errorEl.id = `${input.id}-error`; | |
| field.appendChild(errorEl); | |
| } | |
| errorEl.textContent = message; | |
| input.setAttribute('aria-describedby', errorEl.id); | |
| } | |
| function clearFieldError(input) { | |
| const field = input.closest('.login-field'); | |
| if (!field) return; | |
| field.classList.remove('login-field--error'); | |
| input.removeAttribute('aria-invalid'); | |
| input.removeAttribute('aria-describedby'); | |
| const errorEl = field.querySelector('.login-field__error'); | |
| if (errorEl) errorEl.remove(); | |
| } | |
| function clearFieldErrors(form) { | |
| form.querySelectorAll('.login-field__input').forEach(clearFieldError); | |
| } | |
| /* ---- Status region (created once, announced to screen readers) ---- */ | |
| function createStatusRegion(form) { | |
| let region = form.querySelector('[data-login-status]'); | |
| if (region) return region; | |
| region = document.createElement('p'); | |
| region.setAttribute('data-login-status', ''); | |
| region.className = 'login-status'; | |
| region.setAttribute('role', 'status'); | |
| region.setAttribute('aria-live', 'polite'); | |
| form.appendChild(region); | |
| return region; | |
| } | |
| function setStatus(region, message, kind) { | |
| if (!region) return; | |
| region.textContent = message; | |
| region.classList.toggle('login-status--info', kind === 'info'); | |
| region.classList.toggle('login-status--error', kind === 'error'); | |
| } | |