2

I have custom password validation function in my form. On the same form I use HTML5 validation on all other fields. I'm wondering if there is a good way to include this function in HTML validation? Here is example of my custom password validation function:

$('#myaccount-password').keyup(checkPsw).focus(function() {
  $('#pswd_info').show();
}).blur(function() {
  $('#pswd_info').hide();
});

function checkPsw() {
  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');
  }
}
.password-container {
  position: relative;
}

#pswd_info {
  position: absolute;
  font-size: .875em;
}

#pswd_info::before {
  content: "\25B2";
  position: absolute;
  top: -12px;
  left: 45%;
  font-size: 14px;
  line-height: 12px;
  color: #337ab7;
  text-shadow: none;
  display: block;
}

#pswd_info ul {
  margin: 0;
  padding: 0;
}

#pswd_info li {
  list-style: none;
}

.invalid {
  color: #ec3f41;
}

.valid {
  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="myaccount-password" id="myaccount-password" placeholder="Enter Password" maxlength="64" required>
  <div id="pswd_info" class="panel panel-primary">
    <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>

and here is example of my function that is used to submit the form:

$('#frm-myForm').on('submit', function(e){
    e.preventDefault(); 
    var formData = $('#frm-myForm').serialize();

    $.ajax({
        type: 'POST',
        url: 'AjaxFunctions.cfc?method=myForm',
        data: formData,
        dataType: 'json'
    }).done(function(obj){
            console.log(obj);
    }).fail(function(jqXHR, textStatus, errorThrown){
        alert("Error: "+errorThrown);
    });
});

Function above will trigger HTML5 validation but that won't check if my password is valid or not. Is there a way to check if all password requirements are met before form submit is processed? Thanks in advance.

TylerH
  • 20,799
  • 66
  • 75
  • 101
espresso_coffee
  • 5,980
  • 11
  • 83
  • 193
  • 1
    Yes you can it's called constraint validation, take a look at this article everything is explained: https://www.html5rocks.com/en/tutorials/forms/constraintvalidation/ – t3__rry Mar 28 '18 at 14:17

2 Answers2

1

You ARE actually validating your password hence you do have a way to know if it is valid, so what if you do this inside your submit function:

$('#frm-myForm').on('submit', function(e){
    e.preventDefault(); 
    if(!$('#pswd_info').find('li.invalid').presence()){
    var formData = $('#frm-myForm').serialize();

    $.ajax({
        type: 'POST',
        url: 'AjaxFunctions.cfc?method=myForm',
        data: formData,
        dataType: 'json'
    }).done(function(obj){
            console.log(obj);
    }).fail(function(jqXHR, textStatus, errorThrown){
        alert("Error: "+errorThrown);
    });
    } else{
        alert('Password is not valid');
    }
});

//helper function
$.fn.presence = function() {
    return this.length !== 0 && this;
};
TylerH
  • 20,799
  • 66
  • 75
  • 101
Scaramouche
  • 3,188
  • 2
  • 20
  • 46
  • Your solution will prevent form submit if password requirements are not complete. The only piece that is missing is HTML5 message, how we can add message for example 'Password field is not valid' or something like this? – espresso_coffee Mar 28 '18 at 14:32
  • @espresso_coffee; the most basic way would be an alert() and be done with it, but there are lots more stylish ways to pop a message informing the user that his password is not valid, like a toast-like message plugin for javascript, I know I saw it somewhere but can't remember, I'll let you know if I do – Scaramouche Mar 28 '18 at 14:38
1

Your password validation is basically minimun 8 charcaters, one small letter, one capital letter, one number and one of the three special characters @!?

for this you can use in built pattern attribute on the password input with pattern as

^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[?!@])[A-Za-z\d@!?]{8,}$

this way you don't have to write complex validation conditions

<input type="password" class="form-control" name="myaccount-password"
id="myaccount-password" placeholder="Enter Password" maxlength="64"
pattern="^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[?!@])[A-Za-z\d@!?]{8,}$" required>

The browser support for pattern attribute is here

For custom error messages on pattern mismatch you can use title attribute

<input type="password" class="form-control" name="myaccount-password"
id="myaccount-password" placeholder="Enter Password" maxlength="64"\
title="Password must be minimum 8 characters length with at least one small, one capital letter, one number and a special character"
pattern="^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[?!@])[A-Za-z\d@!?]{8,}$" required>

Regex101

Abdul Hameed
  • 1,025
  • 12
  • 27
  • I have tried this with some added special characters and didn't accept any of added special characters `pattern="^(?=.*[A-Za-z])(?=.*\d)(?=.*[?!@#$%^&*-])[A-Za-z\d@!?]{8,}$"` , I'm not sure if I did add special characters in the right spot. – espresso_coffee Mar 28 '18 at 14:42
  • you should add the special characters in both lookahead and match – Abdul Hameed Mar 28 '18 at 14:45
  • 1
    like `^(?=.*[A-Za-z])(?=.*\d)(?=.*[?!@#$%^&*-])[A-Za-z\d?!@#$%^&*-]{8,}$` – Abdul Hameed Mar 28 '18 at 14:45
  • Works just fine now! Only confusing part is why I have to include same thing twice in regex? (Like special characters included in () and then on the end in []) – espresso_coffee Mar 28 '18 at 14:53
  • `(?=)` denotes positive look ahead which implements the *at least once* part of the pattern validation – Abdul Hameed Mar 28 '18 at 14:58
  • `[]` checks if any other invalid character are present – Abdul Hameed Mar 28 '18 at 14:59
  • @espresso_coffee i have updated the pattern.. earlier pattern considered *atleast one capital or small letter* new pattern should consider *atleast one capital AND one small letter* – Abdul Hameed Mar 28 '18 at 15:06