Add splash page and improve user registration views.
This commit is contained in:
221
static/js/password-strength.js
Normal file
221
static/js/password-strength.js
Normal file
@@ -0,0 +1,221 @@
|
||||
// Password Strength Indicator
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Password strength rules
|
||||
const passwordRules = {
|
||||
minLength: 8,
|
||||
requireUppercase: true,
|
||||
requireLowercase: true,
|
||||
requireNumbers: true,
|
||||
requireSpecialChars: true,
|
||||
specialChars: '!@#$%^&*()_+-=[]{}|;:,.<>?'
|
||||
};
|
||||
|
||||
// Function to check password strength
|
||||
function checkPasswordStrength(password) {
|
||||
let strength = 0;
|
||||
const feedback = [];
|
||||
|
||||
// Check minimum length
|
||||
if (password.length >= passwordRules.minLength) {
|
||||
strength += 20;
|
||||
} else {
|
||||
feedback.push(`At least ${passwordRules.minLength} characters`);
|
||||
}
|
||||
|
||||
// Check for uppercase letters
|
||||
if (passwordRules.requireUppercase && /[A-Z]/.test(password)) {
|
||||
strength += 20;
|
||||
} else if (passwordRules.requireUppercase) {
|
||||
feedback.push('One uppercase letter');
|
||||
}
|
||||
|
||||
// Check for lowercase letters
|
||||
if (passwordRules.requireLowercase && /[a-z]/.test(password)) {
|
||||
strength += 20;
|
||||
} else if (passwordRules.requireLowercase) {
|
||||
feedback.push('One lowercase letter');
|
||||
}
|
||||
|
||||
// Check for numbers
|
||||
if (passwordRules.requireNumbers && /\d/.test(password)) {
|
||||
strength += 20;
|
||||
} else if (passwordRules.requireNumbers) {
|
||||
feedback.push('One number');
|
||||
}
|
||||
|
||||
// Check for special characters
|
||||
const specialCharRegex = new RegExp(`[${passwordRules.specialChars.replace(/[\[\]\\]/g, '\\$&')}]`);
|
||||
if (passwordRules.requireSpecialChars && specialCharRegex.test(password)) {
|
||||
strength += 20;
|
||||
} else if (passwordRules.requireSpecialChars) {
|
||||
feedback.push('One special character');
|
||||
}
|
||||
|
||||
// Bonus points for length
|
||||
if (password.length >= 12) {
|
||||
strength = Math.min(100, strength + 10);
|
||||
}
|
||||
if (password.length >= 16) {
|
||||
strength = Math.min(100, strength + 10);
|
||||
}
|
||||
|
||||
return {
|
||||
score: strength,
|
||||
feedback: feedback,
|
||||
isValid: strength >= 100
|
||||
};
|
||||
}
|
||||
|
||||
// Function to update the strength indicator UI
|
||||
function updateStrengthIndicator(input, result) {
|
||||
let container = input.parentElement.querySelector('.password-strength-container');
|
||||
|
||||
// Create container if it doesn't exist
|
||||
if (!container) {
|
||||
container = document.createElement('div');
|
||||
container.className = 'password-strength-container';
|
||||
|
||||
const indicator = document.createElement('div');
|
||||
indicator.className = 'password-strength-indicator';
|
||||
|
||||
const bar = document.createElement('div');
|
||||
bar.className = 'password-strength-bar';
|
||||
|
||||
const text = document.createElement('div');
|
||||
text.className = 'password-strength-text';
|
||||
|
||||
const requirements = document.createElement('ul');
|
||||
requirements.className = 'password-requirements';
|
||||
|
||||
indicator.appendChild(bar);
|
||||
container.appendChild(indicator);
|
||||
container.appendChild(text);
|
||||
container.appendChild(requirements);
|
||||
|
||||
input.parentElement.appendChild(container);
|
||||
}
|
||||
|
||||
const bar = container.querySelector('.password-strength-bar');
|
||||
const text = container.querySelector('.password-strength-text');
|
||||
const requirements = container.querySelector('.password-requirements');
|
||||
|
||||
// Update bar width and color
|
||||
bar.style.width = result.score + '%';
|
||||
|
||||
// Remove all strength classes
|
||||
bar.className = 'password-strength-bar';
|
||||
|
||||
// Add appropriate class based on score
|
||||
if (result.score < 40) {
|
||||
bar.classList.add('strength-weak');
|
||||
text.textContent = 'Weak';
|
||||
text.className = 'password-strength-text text-weak';
|
||||
} else if (result.score < 70) {
|
||||
bar.classList.add('strength-fair');
|
||||
text.textContent = 'Fair';
|
||||
text.className = 'password-strength-text text-fair';
|
||||
} else if (result.score < 100) {
|
||||
bar.classList.add('strength-good');
|
||||
text.textContent = 'Good';
|
||||
text.className = 'password-strength-text text-good';
|
||||
} else {
|
||||
bar.classList.add('strength-strong');
|
||||
text.textContent = 'Strong';
|
||||
text.className = 'password-strength-text text-strong';
|
||||
}
|
||||
|
||||
// Update requirements list
|
||||
requirements.innerHTML = '';
|
||||
if (result.feedback.length > 0) {
|
||||
requirements.innerHTML = '<li>' + result.feedback.join('</li><li>') + '</li>';
|
||||
}
|
||||
}
|
||||
|
||||
// Function to check if passwords match
|
||||
function checkPasswordMatch(password, confirmPassword) {
|
||||
const confirmInput = document.querySelector(confirmPassword);
|
||||
if (!confirmInput) return;
|
||||
|
||||
let matchIndicator = confirmInput.parentElement.querySelector('.password-match-indicator');
|
||||
|
||||
if (!matchIndicator) {
|
||||
matchIndicator = document.createElement('div');
|
||||
matchIndicator.className = 'password-match-indicator';
|
||||
confirmInput.parentElement.appendChild(matchIndicator);
|
||||
}
|
||||
|
||||
if (confirmInput.value === '') {
|
||||
matchIndicator.textContent = '';
|
||||
matchIndicator.className = 'password-match-indicator';
|
||||
} else if (password === confirmInput.value) {
|
||||
matchIndicator.textContent = '✓ Passwords match';
|
||||
matchIndicator.className = 'password-match-indicator match';
|
||||
} else {
|
||||
matchIndicator.textContent = '✗ Passwords do not match';
|
||||
matchIndicator.className = 'password-match-indicator no-match';
|
||||
}
|
||||
}
|
||||
|
||||
// Attach to all password inputs
|
||||
const passwordInputs = document.querySelectorAll('input[type="password"][name="password"], input[type="password"][name="new_password"]');
|
||||
|
||||
passwordInputs.forEach(input => {
|
||||
// Show initial requirements when focused
|
||||
input.addEventListener('focus', function() {
|
||||
if (this.value === '') {
|
||||
const result = checkPasswordStrength('');
|
||||
updateStrengthIndicator(this, result);
|
||||
}
|
||||
});
|
||||
|
||||
// Check strength on input
|
||||
input.addEventListener('input', function() {
|
||||
const result = checkPasswordStrength(this.value);
|
||||
updateStrengthIndicator(this, result);
|
||||
|
||||
// Check password match if there's a confirm field
|
||||
const formElement = this.closest('form');
|
||||
const confirmField = formElement.querySelector('input[name="confirm_password"], input[name="confirm_new_password"]');
|
||||
if (confirmField && confirmField.value) {
|
||||
checkPasswordMatch(this.value, '#' + confirmField.id);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Attach to confirm password inputs
|
||||
const confirmInputs = document.querySelectorAll('input[name="confirm_password"], input[name="confirm_new_password"]');
|
||||
|
||||
confirmInputs.forEach(input => {
|
||||
input.addEventListener('input', function() {
|
||||
const formElement = this.closest('form');
|
||||
const passwordField = formElement.querySelector('input[name="password"], input[name="new_password"]');
|
||||
if (passwordField) {
|
||||
checkPasswordMatch(passwordField.value, '#' + this.id);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Prevent form submission if password is not strong enough
|
||||
const forms = document.querySelectorAll('form');
|
||||
forms.forEach(form => {
|
||||
form.addEventListener('submit', function(e) {
|
||||
const passwordField = this.querySelector('input[name="password"], input[name="new_password"]');
|
||||
if (passwordField && passwordField.value) {
|
||||
const result = checkPasswordStrength(passwordField.value);
|
||||
if (!result.isValid) {
|
||||
e.preventDefault();
|
||||
alert('Please ensure your password meets all the requirements.');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check password match
|
||||
const confirmField = this.querySelector('input[name="confirm_password"], input[name="confirm_new_password"]');
|
||||
if (confirmField && confirmField.value !== passwordField.value) {
|
||||
e.preventDefault();
|
||||
alert('Passwords do not match.');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user