55 lines
2.3 KiB
JavaScript
55 lines
2.3 KiB
JavaScript
// Show/hide ("eye") toggle for every <input type="password">, wrapped
|
|
// in a .password-field div in web/templates/auth.html (login, signup,
|
|
// reset_password — the only pages with password fields). Framework-free
|
|
// and loaded as an external file on purpose: the page's CSP is
|
|
// script-src 'self' only, so no inline <script> or onclick="" handlers.
|
|
(function () {
|
|
function eyeIcon() {
|
|
// Open eye — shown while the field is masked (click to reveal).
|
|
return (
|
|
'<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.8" ' +
|
|
'stroke-linecap="round" stroke-linejoin="round">' +
|
|
'<path d="M1.5 12S5 5 12 5s10.5 7 10.5 7-3.5 7-10.5 7S1.5 12 1.5 12Z"/>' +
|
|
'<circle cx="12" cy="12" r="3"/>' +
|
|
"</svg>"
|
|
);
|
|
}
|
|
|
|
function eyeOffIcon() {
|
|
// Crossed-out eye — shown while the field is revealed (click to mask).
|
|
return (
|
|
'<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.8" ' +
|
|
'stroke-linecap="round" stroke-linejoin="round">' +
|
|
'<path d="M17.94 17.94A10.94 10.94 0 0 1 12 19.5C5 19.5 1.5 12.5 1.5 12.5a19 19 0 0 1 4.22-5.06M9.9 4.74A10.6 10.6 0 0 1 12 4.5c7 0 10.5 7 10.5 7a18.9 18.9 0 0 1-2.16 3.19M14.12 14.12a3 3 0 1 1-4.24-4.24"/>' +
|
|
'<path d="M1 1l22 22"/>' +
|
|
"</svg>"
|
|
);
|
|
}
|
|
|
|
function addToggle(field) {
|
|
var input = field.querySelector('input[type="password"], input[type="text"]');
|
|
if (!input) return;
|
|
|
|
var btn = document.createElement("button");
|
|
btn.type = "button";
|
|
btn.className = "password-toggle";
|
|
btn.setAttribute("aria-label", "Show password");
|
|
btn.setAttribute("aria-pressed", "false");
|
|
btn.innerHTML = eyeIcon();
|
|
|
|
btn.addEventListener("click", function () {
|
|
var revealed = input.type === "text";
|
|
input.type = revealed ? "password" : "text";
|
|
btn.setAttribute("aria-pressed", String(!revealed));
|
|
btn.setAttribute("aria-label", revealed ? "Show password" : "Hide password");
|
|
btn.innerHTML = revealed ? eyeIcon() : eyeOffIcon();
|
|
// Keep focus (and the caret position) in the field itself, not the button.
|
|
input.focus({ preventScroll: true });
|
|
});
|
|
|
|
field.appendChild(btn);
|
|
}
|
|
|
|
document.querySelectorAll(".password-field").forEach(addToggle);
|
|
})();
|