2

I have a password strength bar which which uses li items which are styled with different colours to indicate to the user how strong their password is, like so:

<input type="password" name="password" id="password" placeholder="Password">

<ul id="passwordStrength">
    <li class="point-reg"></li>
    <li class="point-reg"></li>
    <li class="point-reg"></li>
    <li class="point-reg"></li>
</ul>

When a regEx criteria has been met through a set of if statements, the counter is incremented and a switch statement then adds the necessary CSS background property to each li item depending on the counter value.

var password_li = $('#passwordStrength').find('li');

var counter = 0;

if(pw.match(/[A-Z]/) && pw.match(/[a-z]/)) {
    counter++;
}

//further regex if statements

switch(counter) { //patrick
    case 0:
    break;
    case 1:
        $(password_li[0]).css('background', '#e30613'); //first li

    break;
    case 2:
        $(password_li[0]).css('background', '#e30613'); //first li
        $(password_li[1]).css('background', '#f9b233'); //second li         

    break;
    case 3:
        $(password_li[0]).css('background', '#e30613'); //first li
        $(password_li[1]).css('background', '#f9b233'); //second li                 
        $(password_li[2]).css('background', '#53ab58'); //third li                  

    break;
    case 4:
        $(password_li[0]).css('background', '#e30613'); //first li
        $(password_li[1]).css('background', '#f9b233'); //second li             
        $(password_li[2]).css('background', '#53ab58'); //third li                                  
        $(password_li[3]).css('background', '#418746'); //fourth li 
    break;
}

This doesn't seem the most efficient way of styling the li items. Also, if the user then deletes the value they have entered, the li items remain the colour they have been assigned, rather than reverting back to their default colour of grey, which makes sense as there isn't a function in place to remove the styling. I can add grey to the li items depending on what case has been met in the switch statement like so:

case 1:
    $(password_li[0]).css('background', '#e30613');
    $(password_li[1]).css('background', '#dcdcdc');                 
    $(password_li[2]).css('background', '#dcdcdc');                 
    $(password_li[3]).css('background', '#dcdcdc');                             
break;

But again, this does not seem the most efficient apporach.

Question

How do I approach this functionality so the styling for the li elements can be dynamically added and removed?

Here is a JSFiddle

6
  • 1
    can you provide a working snippet ? It is better to work with css classes than properties (add class, remove class) Commented Dec 13, 2017 at 11:54
  • I'll get onto making one Commented Dec 13, 2017 at 11:55
  • 1
    The ideal way to do this would be to push the values to a data- attribute and then read them in CSS via attr(), but unfortunately I don't think any browser currently supports that :( Commented Dec 13, 2017 at 12:00
  • Added fiddle guys Commented Dec 13, 2017 at 12:02
  • 1
    @PatrickMcDermott no support at all right now (outside of using it with content in ::before and ::after). Commented Dec 13, 2017 at 12:07

3 Answers 3

2

First, there's actually a method to remove the styling. Simply set it to nothing:

$(password_li[0]).css({
    background: ""
});
// I guess that can be done inline too
$(password_li[0]).css("background", "");

But if you prefer to do it with less iterations, you can do it with CSS classes. Just set your parent element a class and the class will have a nth-child selector that will set the color of each child, individually, depending on their position.

<style>
    .list1 > li:nth-child(1) {
        background: #e30613;
    }
    .list2 > li:nth-child(2) {
        background: #f9b233;
    }
    .list3 > li:nth-child(3) {
        background: #53ab58;
    }
    .list4 > li:nth-child(4) {
        background: #418746;
    }
    .list5 > li:nth-child(5) {
        background: red;
    }
    .list6 > li:nth-child(6) {
        background: blue;
    }
</style>
<input type="password" name="password" id="password" placeholder="Password">

<ul id="passwordStrength">
    <li class="point-reg"></li>
    <li class="point-reg"></li>
    <li class="point-reg"></li>
    <li class="point-reg"></li>
</ul>

Then you can add the classes to the parent depending on the counter, like this

counter && $("#passwordStrength").addClass("list" + counter);

And remove them when not needed

while(counter) {
    $("#passwordStrength").removeClass("list" + counter--);
}

This way you can have the styles in other file, as recommended, instead of using inline styling, which is discouraged.

Fiddle: https://jsfiddle.net/b6jfgyvy/

Sign up to request clarification or add additional context in comments.

5 Comments

I am not sure this will work as expected. could you place the code in fiddle or here as a working snippet?
Are you saying place the counter && $("#passwordStrength").addClass("list" + counter); within the switch statement or remove the switch statement completely? I have tried your approach but no success I'm afraid
@PatrickMcDermott To remove the switch. Just add it after the counter is increased. Check the fiddle.
Thank @JorgeFuentesGonzález for your time and example. Didn't see the Fiddle
Nice Logic. +1 for your fiddle.
1

I would recommend adding/removing CSS classes rather than manipulating CSS rules.

You can persist which class to be add along with <li> element using custom data-* prefixed attribute.

Then you can target the elements on which classes needs to added using .filter() method and :lt() selector.

Fiddle

$(document).ready(function() {
  var password_li = $('#passwordStrength').find('li');
  $('#password').bind('keyup', function() {
    var counter = 0;
    var pw = $(this).val();

    if (pw.length >= 8) {
      counter++;
    }
    if (pw.match(/\d/)) { //match digit
      counter++;
    }
    if (pw.match(/[A-Z]/) && pw.match(/[a-z]/)) { //match digit
      counter++;
    }
    if (pw.match(/[$@$!%*#?&]/)) { //match digit
      counter++;
    }
    //Get all classes to remove
    var clssesToRemove = password_li.map(function() {
      return $(this).data('matched-class');
    }).get().join(' ');

    //Remove all class
    password_li.removeClass(clssesToRemove);

    //Filter and add class
    password_li.filter(':lt(' + counter + ')').each(function() {
      $(this).addClass($(this).data('matched-class'));
    });

  })
})
ul#strength {
  display: inline;
  list-style: none;
  padding: 0;
  vertical-align: 2px;
}

.point-reg {
  background: #DDD;
  border-radius: 2px;
  display: inline-block;
  height: 10px;
  margin-right: 2px;
  width: 30px;
}

.first {
  background-color: #e30613;
}

.second {
  background-color: #f9b233;
}

.third {
  background-color: #53ab58;
}

.fourth {
  background-color: #418746;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta/css/bootstrap.min.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<div class="row">
  <div class="col-xl-8 offset-xl-2">
    <div class="form-group row">
      <div class="col-md-12">
        <input type="password" name="password" class="form-control pill-radius font-body" id="password" placeholder="Password">
      </div>
      <div class="form-group row">
        <div class="col-md-12">
          <ul id="passwordStrength">
            <li class="point-reg" data-matched-class="first"></li>
            <li class="point-reg" data-matched-class="second"></li>
            <li class="point-reg" data-matched-class="third"></li>
            <li class="point-reg" data-matched-class="fourth"></li>
          </ul>
        </div>
      </div>
    </div>
  </div>
</div>

1 Comment

Thank you @Satpal. Would of never though to ever take this apporach. Have never been one to utilize custom data- attributes.
0

Maybe you can do something like this

colours = [
    '#e30613',
    '#f9b233',
    '#53ab58',
    '#53ab58'
];

for (i = 0; i < counter; i++) {
    $("password_li[" + i + "]").css('background', colours[i]);
}

You can reset all colours by:

$("password_li").css('background', '#dcdcdc');

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.