Nobody
Nobody

Reputation: 9

Javascript password feedbacks

So I've been making a password validator that will display feedback on the password a user is making based on the criteria.

HTML:

password: <input type="password" id="password" name="password"> <br>

<input type="checkbox" id="passwordReveal">
<label for="passwordReveal">Show Password</label>

<p id="feedback"></p>

What I am currently stuck on is how to make all of the error messages display as those criterias are not met, instead of only one error message at a time until all criteria is met.

Upvotes: 1

Views: 96

Answers (2)

Bumhan Yu
Bumhan Yu

Reputation: 2297

I'd recommend you show password criteria explicitly and constantly show whether they're met, rather than providing feedback only when it's not met. See this Codepen link as a reference. Also, rather than use regex.test(string), I'd propose string.match(regex) here to avoid inaccurate toggling.

// Password criteria
const CRITERIA_LOWERCASE = /[a-z]/g;
const CRITERIA_UPPERCASE = /[A-Z]/g;
const CRITERIA_NUMBERS = /[0-9]/g;
const CRITERIA_SPECIALS = /[^A-z\s\d][\\\^]?/g;
const CRITERIA_LENGTH = 6;

// DOM elements: password feedback
const pwLength = document.querySelector('li.pw-length');
const pwLowercase = document.querySelector('li.pw-lowercase');
const pwUppercase = document.querySelector('li.pw-uppercase');
const pwNumber = document.querySelector('li.pw-number');
const pwSpecial = document.querySelector('li.pw-special');

// DOM elements: inputs
const toggle = document.querySelector('#toggle');
const passwordField = document.querySelector('#password');

toggle.addEventListener('change', () => {
  passwordField.type === 'password' ? passwordField.type = 'text' : passwordField.type = 'password'
})

passwordField.addEventListener('keyup', validatePassword);

function validatePassword() {
  const password = passwordField.value;
  password.length >= CRITERIA_LENGTH ? 
    pwLength.classList.add('pass') : 
    pwLength.classList.remove('pass');
  password.match(CRITERIA_LOWERCASE) ?
    pwLowercase.classList.add('pass') : 
    pwLowercase.classList.remove('pass');
  password.match(CRITERIA_UPPERCASE) ?
    pwUppercase.classList.add('pass') : 
    pwUppercase.classList.remove('pass');
  password.match(CRITERIA_NUMBERS) ?
    pwNumber.classList.add('pass') : 
    pwNumber.classList.remove('pass');
  password.match(CRITERIA_SPECIALS) ?
    pwSpecial.classList.add('pass') : 
    pwSpecial.classList.remove('pass');    
}
*, * > * {
  box-sizing: border-box;
}
body {
  display: flex;
  align-items: center;
  justify-content: center;
}
.wrapper {
  width: 300px;
  display: flex;
  flex-direction: column;
  align-items: center;
  font-family: sans-serif;
  box-shadow: 0 1px 10px rgba(0,0,0,.2);
}
.passwordBox {
  width: 100%;
  line-height: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 20px;
}
.feedback {
  font-size: small;
  padding: 20px;
  width: 100%;
  background-color: #eee;
}
.feedback ul {
  list-style: none;
  padding: 0;
  margin: 10px 0 0;
}
.feedback li::before {
  content: '🚫';
}
.feedback li.pass::before {
  content: '🟢';
}
<div class="wrapper">
  <div class="passwordBox">
    <label for="password">
      Password:
      <input type="password" id="password" name="password">
    </label>
    <label for="toggle">
      Show password
      <input type="checkbox" id="toggle" name="toggle">
    </label>
  </div>
  <div class="feedback">
    <strong>
      Password requirements
    </strong>
    <ul>
      <li class="pw-length">
        Minimum 6 characters
      </li>
      <li class="pw-lowercase">
        At least 1 lowercase letter
      </li>
      <li class="pw-uppercase">
        At least 1 uppercase letter
      </li>
      <li class="pw-number">
        At least 1 number
      </li>
      <li class="pw-special">
        At least 1 special character
      </li>
    </ul>
  </div>
</div>

Upvotes: 0

Alexis Wilke
Alexis Wilke

Reputation: 20731

Maybe something like the following where you cummulate the messages in a variable and save the results in the DOM at the end?

var feedback = ""
if (password.length < passwordLength) {
  feedback += "Password is too short<br/>";
} else if (!lowerCaseLetters.test(password)) {
  feedback += "Does not contain a lower case letter<br/>";
} else if (!upperCaseLetters.test(password)) {
  feedback += "Does not contain an upper case letter<br/>";
} else if (!numbers.test(password)) {
  feedback += "Does not contain a number<br/>";
} else if (!specials.test(password)) {
  feedback += "Does not contain a special character<br/>";
}
if(feedback.length == 0) {
  feedback = 'password is valid'
}
feedbackElement.innerHTML = feedback;

Upvotes: 1

Related Questions