2

I have function that checks password. This function should check if password values contains at least one of the special charters that I listed in the description. Here is example:

$('input[type=password]').keyup(function() {
  var pswd = $(this).val();

  //validate the length
  if (pswd.length < 8) {
    $('#length').removeClass('valid').addClass('invalid');
  } else {
    $('#length').removeClass('invalid').addClass('valid');
  }

  //validate letter
  if (pswd.match(/[a-z]/)) {
    $('#letter').removeClass('invalid').addClass('valid');
  } else {
    $('#letter').removeClass('valid').addClass('invalid');
  }

  //validate capital letter
  if (pswd.match(/[A-Z]/)) {
    $('#capital').removeClass('invalid').addClass('valid');
  } else {
    $('#capital').removeClass('valid').addClass('invalid');
  }

  //validate special character
  if (pswd.match(/[!"#$%&'()*+,-.:;<=>?@[\]^_`{|}~]/)) {
    $('#character').removeClass('invalid').addClass('valid');
  } else {
    $('#character').removeClass('valid').addClass('invalid');
  }

  //validate number
  if (pswd.match(/\d/)) {
    $('#number').removeClass('invalid').addClass('valid');
  } else {
    $('#number').removeClass('valid').addClass('invalid');
  }
}).focus(function() {
  $('#pswd_info').show();
}).blur(function() {
  $('#pswd_info').hide();
});
.form-group.required .control-label:after {
   content: "*";
   color: red;
}
.password-container {
 position: relative;
}
#pswd_info {
    position:absolute;
    width:250px;
    font-size:.875em;
}
#pswd_info::before {
    content: "\25B2";
    position:absolute;
    top:-12px;
    left:45%;
    font-size:14px;
    line-height:14px;
    color:#ddd;
    text-shadow:none;
    display:block;
}
#pswd_info ul {
 margin: 0;
 padding: 0;
}
#pswd_info li {
 list-style: none;
}
.invalid {
    padding-left: 22px;
    line-height: 24px;
    color: #ec3f41;
}
.valid {
    padding-left: 22px;
    line-height: 24px;
    color: #3a7d34;
}
#pswd_info {
    display:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="form-group required password-container">
  <label class="control-label" for="password">Password</label>
  <input type="password" class="form-control" name="temp_password" id="temp_password" placeholder="Enter Password" maxlength="64" required>
  <small id="passwordHelp" class="form-text text-muted">Special characters allowed:  <span class="text-danger">!"#$%&'()*+,-.:;<=>?@[\]^_`{|}~</span></small>
  <div id="pswd_info" class="panel panel-default">
    <div class="panel-heading">
      <h5>Password requirements:</h5>
    </div>
    <div class="panel-body">
      <ul>
        <li id="letter" class="invalid">At least <strong>one letter</strong></li>
        <li id="capital" class="invalid">At least <strong>one capital letter</strong></li>
        <li id="number" class="invalid">At least <strong>one number</strong></li>
        <li id="character" class="invalid">At least <strong>one special character</strong></li>
        <li id="length" class="invalid">Be at least <strong>8 characters</strong></li>
      </ul>
    </div>
  </div>
</div>

As you can see in the code above there is if statement that looking for the match for one of the special characters. i found the problem. My regular expression works until I enter \ , regex doesn't recognize backslash. Also If I enter any of the characters after backslash I see that li with id letter turns green. That is a bug and I'm not sure why that would be set to valid. I guess that my regex is breaking because of the \ and I'm not sure what is the correct way to check for back and forward slash in JavaScript?

espresso_coffee
  • 5,980
  • 11
  • 83
  • 193

1 Answers1

2

You can vastly simplify your expression with lookaheads:

^
(?=[^A-Z]*[A-Z])
(?=[^!"#$%&'()*+,-.:;<=>?@[\]^_`{|}~]*[!"#$%&'()*+,-.:;<=>?@[\]^_`{|}~])
(?=\D*\d).{8,}
$

Without verbose mode:

^(?=[^A-Z]*[A-Z])(?=[^!"#$%&'()*+,-.:;<=>?@[\]^_`{|}~]*[!"#$%&'()*+,-.:;<=>?@[\]^_`{|}~])(?=\D*\d).{8,}$

This makes use of the principle of contrasts.
Please also note that [A-z] matches more characters than you think.


This is what I mean:
$('input[type=password]').keyup(function() {
  var pswd = $(this).val();
  if (pwsd.match(/^(?=[^A-Z]*[A-Z])(?=[^!"#$%&'()*+,-.:;<=>?@[\]^_`{|}~]*[!"#$%&'()*+,-.:;<=>?@[\]^_`{|}~])(?=\D*\d).{8,}$/)) {
     // now, it is valid
  } else {
     // invalid
  }
}).focus(function() {
  $('#pswd_info').show();
}).blur(function() {
  $('#pswd_info').hide();
});
Jan
  • 42,290
  • 8
  • 54
  • 79