3

I've created a password strength meter using zxcvbn.js. You can demo it here:

http://codepen.io/anon/pen/QEakxV

(UPDATE: Revised working pen: http://codepen.io/anon/pen/dXdGwE)

When I type in a password, it seems to work correctly, i.e. the meter grows and changes color appropriately for the password strength as determined by zxcvbn. The problem comes when backspacing - deleting characters from the password. It, too, works initially, until I reach the last one or two characters. At that point, the meter stops decreasing and remains partially visible, the equivalent of perhaps a password strength of 10%, even when the percentage strength is 0. (For verification, there is a console.log statement that outputs the current password strength percentage to the console.)

So, there is either something wrong with the way I am determining the value in the password input control or there is some quirk or different way I need to handle the key-up event, whether in general or specifically when the key that is involved is the backspace key (delete key on my Mac).

Any ideas? Thanks!

HTML

<form novalidate="novalidate" class="simple_form new_user" id="new_user" action="/users" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" />
  <div id="user-prefs-password-new-input-wrapper" class="form-group password optional user_password user-prefs-input-wrapper">
    <label class="password optional control-label" for="user-prefs-password-new-input">New Password</label>
    <input id="user-prefs-password-new-input" class="password optional user-prefs-input form-control" type="password" name="user[password]" />
  </div>
  <div id='user-prefs-password-new-strength-meter'></div>
  <div id='user-prefs-email-password-form-submit-btn-wrapper'>
    <input type="submit" name="commit" value="Update" id="user-prefs-email-password-form-submit-btn" class="btn-success btn-sm btn-submit" />
  </div>
</form>

JAVASCRIPT

$(document).ready(function() {

  var input = document.getElementById('user-prefs-password-new-input');
  var bar  = document.getElementById('user-prefs-password-new-strength-meter');

  input.addEventListener('keyup', function() {

    console.log('*** PASSWORD: ' + input.value)

    var analysis = zxcvbn(input.value);

    var strengthPercentage = Math.floor(Number((analysis.guesses_log10 / 12.0).toFixed(2).replace(/0+$/, '')) * 100.0);
    if (strengthPercentage > 100) {
      strengthPercentage = 100;
    };

    console.log('*** STRENGTH PERCENTAGE: ' + strengthPercentage.toString())
    if ($(input).val() === '') {
      bar.style.backgroundImage = 'linear-gradient(to right, #ffffff 100%)';
    } else {
      switch (analysis.score) {
        case 0:
          bar.style.backgroundImage = 'linear-gradient(to right, #d30202 ' + strengthPercentage + '%, #ffffff ' + (strengthPercentage + 1) + '%)';
          break;
        case 1:
          bar.style.backgroundImage = 'linear-gradient(to right, #d30202 25%, #f07906 ' + strengthPercentage + '%, #ffffff ' + (strengthPercentage + 1) + '%)';
          break;
        case 2:
          bar.style.backgroundImage = 'linear-gradient(to right, #d30202 25%, #f07906 50%, #f3f304 ' + strengthPercentage + '%, #ffffff ' + (strengthPercentage + 1) + '%)';
          break;
        case 3:
          bar.style.backgroundImage = 'linear-gradient(to right, #d30202 25%, #f07906 50%, #f3f304 66%, #5bb502 ' + strengthPercentage + '%, #ffffff ' + (strengthPercentage + 1) + '%)';
          break;
        case 4:
          if (strengthPercentage <= 99) {
            bar.style.backgroundImage = 'linear-gradient(to right, #d30202 25%, #f07906 50%, #f3f304 66%, #57ad02 83%, #02ad02 ' + strengthPercentage + '%, #ffffff ' + (strengthPercentage + 1) + '%)';
          } else {
            bar.style.backgroundImage = 'linear-gradient(to right, #d30202 25%, #f07906 50%, #f3f304 66%, #57ad02 83%, #02ad02 100%)';
          };
      };
    };

  });

});

CSS

#user-prefs-password-new-strength-meter {
  width: 100%;
  height: 1em;
  margin-bottom: 1em;
  background-color: #ffffff;
  border: 1px solid #cccccc;
  border-radius: 0.25rem;
}

form {
  width: 30%;
  margin: 1em auto;
}

3 Answers 3

1

Can you try just removing the backgroundImage completely, like this:

if ($(input).val() === '') {
  bar.style.backgroundImage = 'none';
} else {
  ...
}
Sign up to request clarification or add additional context in comments.

2 Comments

Genius. Thanks! Sheesh, I should have posted this question yesterday and saved myself a great deal of aggravation. It also solved the problem I was having with the meter not updating properly if you just hold down the backspace key to delete the whole password. What is the difference in what's happening between your solution and what I was doing? Why doesn't an all-white gradient accomplish the same thing?
Probably something to do with needing a clear rule in the css... but it seems easier to just remove the background.
1

Add if statement after switch case.

  case 4:
              if (strengthPercentage <= 99) {
                bar.style.backgroundImage = 'linear-gradient(to right, #d30202 25%, #f07906 50%, #f3f304 66%, #57ad02 83%, #02ad02 ' + strengthPercentage + '%, #ffffff ' + (strengthPercentage + 1) + '%)';
              } else {
                bar.style.backgroundImage = 'linear-gradient(to right, #d30202 25%, #f07906 50%, #f3f304 66%, #57ad02 83%, #02ad02 100%)';
              };
          };
        };
//Add this below if statement,
         if (strengthPercentage <= 10){
              bar.style.backgroundImage = "none"; 
         }
      });

2 Comments

This works, too! Robin's solution ended up solving another problem I was having with this that I didn't include as part of the question (see my comment to Robin's response). Thanks for responding so quickly with a working solution. Cheers!
Welcome @eggroll and it's good that you got solution for your problem.
0

Or, you could just fix the issue when the input is empty...

bar.style.backgroundImage = 'linear-gradient(to right, #ffffff 100%, #ffffff 100%)';

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.