For Bootstrap 4 login form, see this codebank entry: https://www.vbforums.com/showthread....4-0-Login-Form
The code requires the following external files:
- Bootstrap 5 CSS - https://getbootstrap.com/
The code uses the following external files, but they are optional:
- Font-Awesome 6 - https://fontawesome.com/
HTML:
HTML Code:
<section class="position-relative py-4 py-xl-5">
<div class="container">
<div class="row mt-2 mb-3">
<div class="col-md-8 col-xl-6 text-center mx-auto">
<h2>Application Name</h2>
<p class="w-lg-50">Login</p>
</div>
</div>
<div class="row d-flex justify-content-center">
<div class="col-md-6 col-xl-4">
<div class="card mb-5">
<div class="card-body d-flex flex-column align-items-center">
<div class="my-4">
<!-- my logo () -->
</div>
<form method="post">
<div class="mb-3">
<label for="username">Username</label>
<div class="input-group input-group-extras">
<input id="username" class="form-control" name="email" placeholder="Username" autocomplete="username" required />
<button class="btn btn-outline-secondary clear-input d-none" type="button">
<span class="visually-hidden">Clear</span>
<i class="fa-solid fa-x"></i>
</button>
</div>
</div>
<div class="mb-3">
<label for="password">Password</label>
<div class="input-group input-group-extras">
<input type="password" id="password" class="form-control" name="password" placeholder="Password" required />
<button class="btn btn-outline-secondary show-password d-none" type="button">
<span class="visually-hidden">Show Password</span>
<i class="fa-solid fa-eye"></i>
</button>
<button class="btn btn-outline-secondary hide-password d-none" type="button">
<span class="visually-hidden">Hide Password</span>
<i class="fa-solid fa-eye-slash"></i>
</button>
<button class="btn btn-outline-secondary clear-input d-none" type="button">
<span class="visually-hidden">Clear</span>
<i class="fa-solid fa-x"></i>
</button>
</div>
</div>
<div class="mb-3 form-check text-start">
<input class="form-check-input" type="checkbox" id="specify-domain">
<label class="form-check-label" for="specify-domain">
Specify Domain?
</label>
</div>
<div class="mb-3">
<button class="btn btn-primary d-block w-100" type="submit">Login</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</section>
JavaScript:
Code:
// methods
const getSilblingElements = (element) => {
if (!element) {
return [];
}
const parentNode = element.parentNode;
if(!parentNode) {
return [];
}
const siblings = [];
let sibling = parentNode.firstChild;
while (sibling) {
if (sibling.nodeType === 1 && sibling !== element) {
siblings.push(sibling);
}
sibling = sibling.nextSibling;
}
return siblings;
}
const wireUpClearInput = () => {
const clearInputButtons = document.querySelectorAll('.clear-input');
for (const clearInputButton of clearInputButtons) {
const clearInputButtonSiblings = getSilblingElements(clearInputButton);
const firstInput = clearInputButtonSiblings.find(sibling => sibling.tagName === 'INPUT');
if (!firstInput) {
return;
}
clearInputButton.addEventListener('mousedown', clearInputButton_Click, false);
firstInput.addEventListener('input', clearableInput_Change, false);
firstInput.addEventListener('focusin', clearableInput_Change, false);
firstInput.addEventListener('focusout', clearableInput_Leave, false);
}
}
const wireUpHidePassword = () => {
const hidePasswordButtons = document.querySelectorAll('.hide-password');
for (const hidePasswordButton of hidePasswordButtons) {
const hidePasswordButtonSiblings = getSilblingElements(hidePasswordButton);
const firstInput = hidePasswordButtonSiblings.find(sibling => sibling.tagName === 'INPUT');
if (!firstInput) {
return;
}
hidePasswordButton.addEventListener('mousedown', hidePasswordButton_Click, false);
firstInput.addEventListener('input', hidePassword_Change, false);
firstInput.addEventListener('focusin', hidePassword_Change, false);
firstInput.addEventListener('focusout', hidePassword_Leave, false);
}
}
const wireUpShowPassword = () => {
const showPasswordButtons = document.querySelectorAll('.show-password');
for (const showPasswordButton of showPasswordButtons) {
const showPasswordButtonSiblings = getSilblingElements(showPasswordButton);
const firstInput = showPasswordButtonSiblings.find(sibling => sibling.tagName === 'INPUT');
if (!firstInput) {
return;
}
showPasswordButton.addEventListener('mousedown', showPasswordButton_Click, false);
firstInput.addEventListener('input', showPassword_Change, false);
firstInput.addEventListener('focusin', showPassword_Change, false);
firstInput.addEventListener('focusout', showPassword_Leave, false);
}
}
// event handlers
const window_Load = () => {
wireUpClearInput();
wireUpHidePassword();
wireUpShowPassword();
};
const clearableInput_Change = (e) => {
const element = e.currentTarget;
const triggeringEvent = element.getAttribute('data-triggering-event') || 'clear-input';
if (triggeringEvent !== 'clear-input') {
return;
}
element.setAttribute('data-triggering-event', '');
const siblings = getSilblingElements(element);
const clearInputDiv = siblings.find(sibling => sibling.classList.contains('clear-input'));
if (!clearInputDiv) {
return;
}
if (!clearInputDiv.classList.contains('d-none') && !(element.value || element.value.length)) {
clearInputDiv.classList.add('d-none');
} else if (clearInputDiv.classList.contains('d-none') && element.value && element.value.length) {
clearInputDiv.classList.remove('d-none');
}
};
const clearableInput_Leave = (e) => {
const element = e.currentTarget;
const siblings = getSilblingElements(element);
const clearInputDiv = siblings.find(sibling => sibling.classList.contains('clear-input'));
if (!clearInputDiv) {
return;
}
if (!clearInputDiv.classList.contains('d-none')) {
clearInputDiv.classList.add('d-none');
}
};
const clearInputButton_Click = (e) => {
const element = e.currentTarget;
element.setAttribute('data-triggering-event', 'clear-input');
const clearInputButtonSiblings = getSilblingElements(element);
const firstInput = clearInputButtonSiblings.find(sibling => sibling.tagName === 'INPUT');
if (!firstInput) {
return;
}
firstInput.value = '';
};
const hidePassword_Change = (e) => {
const element = e.currentTarget;
const triggeringEvent = element.getAttribute('data-triggering-event') || 'hide-password';
if (triggeringEvent !== 'hide-password') {
return;
}
element.setAttribute('data-triggering-event', '');
const siblings = getSilblingElements(element);
const hidePasswordDiv = siblings.find(sibling => sibling.classList.contains('hide-password'));
if (!hidePasswordDiv) {
return;
}
const elementType = element.getAttribute('type');
if (!hidePasswordDiv.classList.contains('d-none') && (!(element.value || element.value.length) || elementType === 'password')) {
hidePasswordDiv.classList.add('d-none');
} else if (hidePasswordDiv.classList.contains('d-none') && element.value && element.value.length && elementType !== 'password') {
hidePasswordDiv.classList.remove('d-none');
}
};
const hidePassword_Leave = (e) => {
const element = e.currentTarget;
const siblings = getSilblingElements(element);
const hidePasswordDiv = siblings.find(sibling => sibling.classList.contains('hide-password'));
if (!hidePasswordDiv) {
return;
}
if (!hidePasswordDiv.classList.contains('d-none')) {
hidePasswordDiv.classList.add('d-none');
}
if (element.getAttribute('type') !== 'password') {
element.setAttribute('type', 'password');
}
};
const hidePasswordButton_Click = (e) => {
const element = e.currentTarget;
element.setAttribute('data-triggering-event', 'hide-password');
const hidePasswordButtonSiblings = getSilblingElements(element);
const firstInput = hidePasswordButtonSiblings.find(sibling => sibling.tagName === 'INPUT');
if (!firstInput) {
return;
}
e.preventDefault();
firstInput.setAttribute('type', 'password');
firstInput.focus();
firstInput.dispatchEvent(new Event('input', { 'bubbles': true }));
};
const showPassword_Change = (e) => {
const element = e.currentTarget;
const triggeringEvent = element.getAttribute('data-triggering-event') || 'show-password';
if (triggeringEvent !== 'show-password') {
return;
}
element.setAttribute('data-triggering-event', '');
const siblings = getSilblingElements(element);
const showPasswordDiv = siblings.find(sibling => sibling.classList.contains('show-password'));
if (!showPasswordDiv) {
return;
}
const elementType = element.getAttribute('type');
if (!showPasswordDiv.classList.contains('d-none') && (!(element.value || element.value.length) || elementType === 'text')) {
showPasswordDiv.classList.add('d-none');
} else if (showPasswordDiv.classList.contains('d-none') && element.value && element.value.length && elementType !== 'text') {
showPasswordDiv.classList.remove('d-none');
}
};
const showPassword_Leave = (e) => {
const element = e.currentTarget;
const siblings = getSilblingElements(element);
const showPasswordDiv = siblings.find(sibling => sibling.classList.contains('show-password'));
if (!showPasswordDiv) {
return;
}
if (!showPasswordDiv.classList.contains('d-none')) {
showPasswordDiv.classList.add('d-none');
}
if (element.getAttribute('type') !== 'password') {
element.setAttribute('type', 'password');
}
};
const showPasswordButton_Click = (e) => {
const element = e.currentTarget;
element.setAttribute('data-triggering-event', 'show-password');
const showPasswordButtonSiblings = getSilblingElements(element);
const firstInput = showPasswordButtonSiblings.find(sibling => sibling.tagName === 'INPUT');
if (!firstInput) {
return;
}
e.preventDefault();
firstInput.setAttribute('type', 'text');
firstInput.focus();
firstInput.dispatchEvent(new Event('input', { 'bubbles': true }));
};
// window events
window.addEventListener('load', window_Load, false);
Fiddle: https://jsfiddle.net/2xdhuyk1/