Question

I have to make a password meter from scratch basically (can't use outside frameworks like jquery), and I'm having 2 problems.

I can't seem to find a way where when a user enters a certain character, it won't jump the meter to a huge length.

And I can't prevent that meter from getting to big, even by setting the width.

<input type="password" id="newPass" style="width:206px" onkeyup="strengthMeter()"/><br/><br/>
                <div style="width:100px;display:inline;"><div id="meter" style="background-color:red;width:10px;height:10px;"></div>
                    <span>Strength</span><span id="strength" style="float:right">Weak</span>
                </div>

function strengthMeter(){


    var password = $("newPass").value;
    var numEx = /\d/;
    var lcEx = new RegExp("[a-z]");
    var ucEx = new RegExp("[A-Z]");
    var symbols = ['/', '@', '#', '%', '&', '.', '!', '*', '+', '?', '|','(', ')', '[', ']', '{', '}', '\\'];
    var meterMult = 1;

    for(var k = 0; k < password.length; k++){
        if(numEx.test(password)){
            meterMult += 0.75;
            $("meter").style.width = " " + (10*meterMult) + "px";
        }

        if(ucEx.test(password)){
            meterMult += 1;
            $("meter").style.width = " " + (10*meterMult) + "px";
        }

        if(lcEx.test(password)){
            meterMult += 0.25;
            $("meter").style.width = " " + (10*meterMult) + "px";
        }

        for(var i = 0; i < symbols.length; i++){
            if(password.indexOf(symbols[i]) >= 0){
                meterMult += 1;
                $("meter").style.width = " " + (10*meterMult) + "px";
            }
            }
        if(meterMult >= 12){
            $("strength").innerHTML = "Strong";
            }
        else if(k >= 6){
            $("strength").innerHTML = "Medium";
        }
        else
            $("strength").innerHTML = "Weak";
        }

    }

The above has the div i am using to make the meter. basically, I am taking a div and expanding it within another div to make the meter, and that's that. Please help! Thanks in advance.

Était-ce utile?

La solution

I've reduced your code to a working jsFiddle. I see a couple funky things in the code that perhaps need to get sorted out first.

First, there appears to be no reason for this loop as all it's doing is running the same code over and over again password.length times:

for(var k = 0; k < password.length; k++){

Did you mean to be examining each character in the password, one at a time in that loop? If so, that's not what your code is doing.

As for the width, I would suggest that the easiest way is to set the width of the container to the max width you want and then set the width of the meter to be a percentage of the parent from 0 to 100.

Here's a new version of your code (working here in a jsFiddle), revised in a bunch of ways:

  1. Changed the width of the red bar to a percentage of it's parent and capped it at 100% so it will never go beyond the parent width.
  2. Check each char in the password individually
  3. Set the width of the password bar only once
  4. Change the layout of the bar to match the width of the input field

Here's the code from the new version:

function strengthMeter() {
    var password = $("newPass").value;
    var numEx = /\d/;
    var lcEx = /[a-z]/;
    var ucEx = /[A-Z]/;
    var symbols = ['/', '@', '#', '%', '&', '.', '!', '*', '+', '?', '|','(', ')', '[', ']', '{', '}', '\\'];
    var meterMult = 1;

    for (var k = 0; k < password.length; k++) {
        var pchar = password.charAt(k);
        if(numEx.test(pchar)){
            meterMult += 0.75;
        }

        if(ucEx.test(pchar)){
            meterMult += 1;
        }

        if(lcEx.test(pchar)){
            meterMult += 0.25;
        }
    }

    for (var i = 0; i < symbols.length; i++) {
        if(password.indexOf(symbols[i]) >= 0) {
            meterMult += 1;
        }
    }

    // assume that 100% is a meterMult of 15
    var fullStrength = 15;
    $("meter").style.width = ((Math.min(fullStrength, meterMult)/fullStrength )*100) + "%";

    if(meterMult >= 12) {
        $("strength").innerHTML = "Strong";
    }
    else if(password.length >= 6) {
        $("strength").innerHTML = "Medium";
    }
    else {
        $("strength").innerHTML = "Weak";
    }
}

Obviously, you may want to tweak the weighting as desired.

Autres conseils

Instead of basing the meter's length off the score you're calculating, do some simple batching:

if (score < 10) {
    size = weak
} else if (score < 30) {
    size = medium
} else {
    size = hard
}

and assign sizes to those batched scores instead. That way, no matter how strong the password gets, it'll never go past whatever size you specified 'hard' to be.

As far as preventing the meter from getting to grow too much, it is as easy as having a condition like:

 $("meter").style.width = " " + (10*meterMult>200?200:10*meterMult) + "px";

And it will basically restrict the meter to grow past 200px

You need to check that updating width of the meter won't go over your max desired width. Even though you set the width in the style element, your script alters the style element and the div can grow as wide as it wants without ever being limited by that initial style attribute. You can add a check like

var n = $("meter").style.width;
if(n>someValue)
{
   //set the meter to the MAX width that you want
   $("meter").style.width=100;

}

Add this after your updates and if a character ever sets the style wider than you want it, you can have it reverted to the max width that you want.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top