I am working on a signup form and I am having trouble with this last section. I need the input border to turn from red to green once all the correct keys have been put in. I mean it to happen at the time of typing and not after submitting. So it is red to begin but it turns green once you have pressed all the keys needed.
const form = document.getElementById("signup-form");
const password = document.getElementById('password').value;
const passwordField = document.getElementById('password');
const confirmPassword = document.getElementById('confirm_password').value;
const confirmPasswordField = document.getElementById('confirm_password');
function formValidation(){
// Password Field
passwordField.style.borderColor = "red";
passwordField.classList.add("invalid");
if(password === ""){
passwordField.style.borderColor = "red";
passwordField.classList.add("invalid");
return false;
}else{
passwordField.style.borderColor = "green";
passwordField.classList.remove("invalid");
passwordField.classList.add("valid");
}
}
function passwordFieldValidations() {
var letter = document.getElementById("letter");
var capital = document.getElementById("capital");
var number = document.getElementById("number");
var length = document.getElementById("length");
// When the user clicks on the password field, show the message box
passwordField.onclick = function() {
document.getElementById("message").style.display = "block";
}
// When the user clicks outside of the password field, hide the message box
passwordField.onblur = function() {
document.getElementById("message").style.display = "none";
}
passwordField.onkeyup = function() {
// Validate lowercase letters
var lowerCaseLetters = /[a-z]/g;
if(passwordField.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(passwordField.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(passwordField.value.match(numbers)) {
number.classList.remove("invalid");
number.classList.add("valid");
} else {
number.classList.remove("valid");
number.classList.add("invalid");
}
// Validate length
if(passwordField.value.length >= 8) {
length.classList.remove("invalid");
length.classList.add("valid");
} else {
length.classList.remove("valid");
length.classList.add("invalid");
}
if (letter.classList.contains(valid) && capital.classList.contains(valid)
&& number.classList.contains(valid) && length.classList.contains(valid)) {
passwordField.style.borderColor = "green";
passwordField.classList.remove("invalid");
passwordField.classList.add("valid");
}
}
}
form.addEventListener("submit", (e) => {
var password1 = passwordField.value;
var password2 = confirmPasswordField.value;
if(password1 !== password2) {
e.preventDefault()
confirmPasswordField.style.borderColor = "red";
confirmPasswordField.classList.add("invalid");
} else {
confirmPasswordField.style.borderColor = "green";
confirmPasswordField.classList.remove("invalid");
confirmPasswordField.classList.add("valid");
}
});
document.getElementById("submit-form").addEventListener("click", formValidation);
body { margin: 0; padding: 0; }
h1, h2 { font-family: 'Poppins', sans-serif; color: #fff; }
p, label, button { font-family: Roboto, sans-serif; }
#wrapper { width: 1200px; margin: 0 auto; }
#content { background-color: #272224; height: 600px; padding: 20px 0 0; }
#signup-info { margin: 0 auto; }
#signup-form { width: 400px; margin: 0 auto; }
#signup-info h2 img { width: 40px; vertical-align: middle; }
#signup-info h1 { margin-bottom: 0; }
.no-top-margin { margin-top: 0; }
#signup-info p { color: #FFE4CF; }
label { display: block; color: #fff; font-weight: bold; }
input { margin-bottom: 15px; border: none; border-bottom: 1px #555 solid;
background-color: transparent; padding: 10px 0; width: 100%;
color: #FFE4CF; font-weight: bold;
}
::placeholder { font-weight: normal; }
button { border: none; background-color: #FFE4CF; width: 100%; padding: 15px; font-weight: bold; }
#signup-info a { color: #fff; }
input.valid { background-image: url(images/check.png); background-position: right;
background-size: 10%; background-repeat: no-repeat; }
input.invalid { background-image: url(images/cross.png); background-position: right;
background-size: 10%; background-repeat: no-repeat; }
#message p { margin: 5px 0 5px 40px; }
#message h3 { margin: 0 0 5px 0; }
#message .valid { color: green; }
#message .valid:before { position: relative; left: -35px; content: "✔"; }
/* Add a red text color and an "x" when the requirements are wrong */
#message .invalid { color: red; }
#message .invalid:before { position: relative; left: -35px; content: "✖"; }
#message { display: none; background-color: #fff; padding: 10px; }
input.valid:focus { outline: none !important; border:1px solid green; }
::-ms-reveal { filter: invert(100%); }
<div id="wrapper">
<div id="content">
<div id="signup-info">
<form name="signup-form" id="signup-form" action="#" method="post">
<div>
<label for="password">Password:</label>
<input type="password" name="password" id="password" placeholder="Enter a password"
pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}"
title="Must contain at least one number and one uppercase and lowercase letter, and at least 8 or more characters" required onfocus="passwordFieldValidations()">
</div>
<div>
<label for="confirm_password">Confirm Password:</label>
<input type="password" name="confirm_password" id="confirm_password" placeholder="Retype password"
title="Password must match" required onkeyup="matchPasswords()">
</div>
<button type="submit" id="submit-form">Create account</button>
<div id="message">
<h3>Password must contain the following:</h3>
<p id="letter" class="invalid">A <b>lowercase</b> letter</p>
<p id="capital" class="invalid">A <b>capital (uppercase)</b> letter</p>
<p id="number" class="invalid">A <b>number</b></p>
<p id="length" class="invalid">Minimum <b>8 characters</b></p>
</div>
</form>
</div>
</div>
</div>
You are actually pretty close. :)
You accidentally used valid
as an identifier instead of a string in the classList.contains(valid)
expression near the end of the password verification section:
// contains(valid) should be contains("valid") in all this calls:
if (letter.classList.contains(valid) && capital.classList.contains(valid)
&& number.classList.contains(valid) && length.classList.contains(valid)) {
passwordField.style.borderColor = "green";
passwordField.classList.remove("invalid");
passwordField.classList.add("valid");
} else {
// You also need to add an else here, change the borderColor to "red", add "invalid", remove "valid", and you're done!
}
Tip: Always have the browser console open when working with JavaScript in order to detect any errors and warnings early on an fix them.
Another trick that you can use (which leads to cleaner and more maintainable code) is to define a variable hasErrors
at the beginning of the onkeyup event handler, assign the value false, and then set the value to true once any
of the following checks fails.
Here's the basic logic behind this:
var hasErrors = false;
// Validate numbers
var numbers = /[0-9]/g;
if(passwordField.value.match(numbers)) {
...
} else {
hasErrors = true;
...
}
// Validate length
if(passwordField.value.length >= 8) {
...
} else {
hasErrors = true;
...
}
if ( hasErrors ) {
// Handle error case (e.g. red border)
} else {
// Handle success (e.g. green border)
}
Also, as Scott Marcus
mentioned, it's better to use the addEventListener("keyup")
form instead of the onkeyup
. Here's a nice extensive SO answer that explains the benefits of using the former.