eggroll eggroll - 4 months ago 23
Javascript Question

jQuery - Password strength meter using zxcvbn.js and backspace

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

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

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 keyup 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;
}

Answer

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

if ($(input).val() === '') {
  bar.style.backgroundImage = 'none';
} else {
  ...
}
Comments