Search code examples
javascripthtmlformsvalidationpasswords

How to add a special character to A Password Validation Form


I'm trying to make a password validation in javascript, I found several questions here using the same example from W3Schools and I followed all the examples with results but it doesn't make sure you enter a special character. It does check if you have one and make a green checkmark but it does not require one. I am pretty sure nobody knows there is still a problem everyone is missing. I am sure it is only the html pattern. I don't know how to force at least 1 special character in the html pattern. here is the pattern I have so far: pattern="(?=.\d)(?=.[a-z])(?=.*[A-Z]).{8,}"

var myInput = document.getElementById("password");
var letter = document.getElementById("letter");
var capital = document.getElementById("capital");
var number = document.getElementById("number");
var length = document.getElementById("length");
var special = document.getElementById("special");

// When the user clicks on the password field, show the message box
myInput.onfocus = function() {
    document.getElementById("message").style.display = "block";
}

// When the user clicks outside of the password field, hide the message box
myInput.onblur = function() {
    document.getElementById("message").style.display = "none";
}

// When the user starts to type something inside the password field
myInput.onkeyup = function() {
// Validate lowercase letters
var lowerCaseLetters = /[a-z]/g;
if(myInput.value.match(lowerCaseLetters)) {  
letter.classList.remove("invalid");
letter.classList.add("valid");
} else {
letter.classList.remove("valid");
letter.classList.add("invalid");
}

// Validate capital letters
var upperCaseLetters = /[A-Z]/g;
if(myInput.value.match(upperCaseLetters)) {  
capital.classList.remove("invalid");
capital.classList.add("valid");
} else {
capital.classList.remove("valid");
capital.classList.add("invalid");
}

// Validate numbers
var numbers = /[0-9]/g;
if(myInput.value.match(numbers)) {  
number.classList.remove("invalid");
number.classList.add("valid");
} else {
number.classList.remove("valid");
number.classList.add("invalid");
}

// Validate length
if(myInput.value.length >= 8) {
length.classList.remove("invalid");
length.classList.add("valid");
} else {
length.classList.remove("valid");
length.classList.add("invalid");
}

// Validate special
var specialcharacters = /[`!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?~]/g;
if(myInput.value.match(specialcharacters)) {
special.classList.remove("invalid");
special.classList.add("valid");
} else {
special.classList.remove("valid");
special.classList.add("invalid");
}
}
<style>
#message {
display:none;
background: #EFEFEF;
color: #000;
position: relative;
margin-top: 0px;
text-align:left;
width:100%;
}
#message p {
padding: 2px 35px 2px 60px;
font-size: 18px;
}
/* Add a green text color and a checkmark when the requirements are right */
.valid {
color: green;
}
.valid:before {
position: relative;
left: -20px;
content: "✔";
}
/* Add a red text color and an "x" when the requirements are wrong */
.invalid {
color: red;
}
.invalid:before {
position: relative;
left: -20px;
content: "✖";
color: red;
}
</style>
<form>
<input type="password" name="password" placeholder="Password" id="password" required minlength="8" maxlength="32" pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}">
</form>

<div id="message">
<div style="padding-top:8px;"></div>
<h2 style="padding-left:40px;font-size:19px;text-decoration:underline;font-weight:650;color:#333;">Password Requirements:</h2>
<p id="letter" class="invalid"><span style="font-weight:600;font-size:17px;">A lowercase letter</span></p>
<p id="capital" class="invalid"><span style="font-weight:600;font-size:17px;">A capital letter</span></p>
<p id="number" class="invalid"><span style="font-weight:600;font-size:17px;">A number</span></p>
<p id="special" class="invalid"><span style="font-weight:600;font-size:17px;">A special character</span></p>
<p id="length" class="invalid"><span style="font-weight:600;font-size:17px;">A minimum of 8 characters</span></p>
</div>

Added (Edited) I narrowed it down to the html pattern. this pattern almost works: (?=.\W)(?=.\d)(?=.[ a-z])(?=.[A-Z]).{8,} the (?=.\W) forces every other special character except an underscore. It does allow a space which I like. Any idea how I can add an _ to the (?=.\W) or another way to do it please?


Solution

  • I figured out the right answer. Change the html regex pattern to:

    pattern="(?=.*[\W_])(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*?[0-9]).{8,28}"
    

    this \W includes all special characters even the space bar but excluding the underscore, so I added it in the pattern after the \W. You can block the space bar using javascript return false if you wish:

        function StopSpaces() {
        var key = event.keyCode || event.charCode || event.which ; 
            if(key == 32) {
                return false;}
            else {
        return key; 
        }
        }
    

    add this to the input to activate the StopSpaces function above:

    onKeyDown="return StopSpaces(event)"
    

    No other questions cover this, and there is several on this site using the same code, people probably did not even notice because the javascript works properly and tells you need a special character, but the html skips it unless the html pattern also requires a special character. I am unable to comment on those posts to explain.