Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trial
Kristian Woods
23,414 PointsHow to create a form that allows 3 separate users and allows 3 attempts to successfully log in
Hello, I'm trying to create a form field that allows for 3 separate users, and allows 3 attempts to successfully log in - otherwise, each form field is disabled.
So far, I have created an array that holds an object. The object contains information on each persons log in details e.g. username and password.
I have then looped through each object and stored that information into a few variables. I then check to see if the value held in the form field matches any of the log in information that is contained within the variables.
If the value doesn't match the information, a red alert pops up. If the log in is successful, then a green alert pops up.
Thats what i'd like to happen.... however, the only result i'm getting is a red alert pop up, never a green. Even when I enter the correct information
Hope anyone can help me,
Thank you
<!DOCTYPE html>
<html>
<head>
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>
<div id="main-alert-red">
</div>
<div id="main-alert-green">
</div>
<div id="div-1">
<form id="form">
<input type="text" placeholder="Enter Name" id="userName"><br>
<input type="password" placeholder="Enter Password" id="password"><br>
<span id="hint">password is 6 characters long</span>
<input type="submit" value="Submit" id="submit">
</form>
<img src="green-check.svg" id="greenCheck">
</div>
<script src="password-part-2.js"></script>
</body>
</html>
var attempts = 1;
var form = document.getElementById("form");
var greenCheck = document.getElementById("greenCheck");
var alertBoxRed = document.getElementById("main-alert-red");
var alertBoxGreen = document.getElementById("main-alert-green");
var submitBtn = document.getElementById("submit");
var userName = document.getElementById("userName");
var password = document.getElementById("password");
var users;
var logIn;
var userList = [
{
name: "anka",
password: "H2X835"
},
{
name: "bob",
password: "bob"
},
{
name: "jon",
password: "jon"
}
];
var submit = function(e) {
for (var i = 0; i < userList.length; i++) {
users = userList[i].name;
logIn = userList[i].password;
if(userName.value !== users && password.value !== logIn) {
e.preventDefault();
alertBoxRed.innerHTML = "<h3>You have entered the wrong information. Please try again " + "[" + attempts + " attempt[s]" + " out of 3 to log in]</h3>";
alertBoxRed.style.display = "block";
attempts += 1;
userName.value = "";
password.value = "";
if (attempts > 3) {
alertBoxRed.innerHTML = "<h3>Denied!</h3>";
userName.disabled = true;
password.disabled = true;
submitBtn.disabled = true;
}
} else {
e.preventDefault();
alertBoxGreen.innerHTML = "<h3>Welcome back, " + userName.value + "!</h3>";
alertBoxGreen.style.display = "block";
alertBoxRed.style.display = "none";
form.style.display = "none";
greenCheck.style.display = "inline-block";
userName.value = "";
password.value = "";
}
}
}
submitBtn.onclick = submit;
3 Answers
Matt Milburn
20,787 PointsHi Kristian, the problem is that as soon as your code finds a mismatch, it decides that the user has totally failed to login.
Let's rethink our approach here. We want to...
- Accept a
usernameand apasswordfrom the user. - Compare the given
usernameandpasswordto a list of stored logins. - If there are no matching logins found, display a warning message and increment the number of attempts by 1.
- If the user fails to provide a matching login after 3 attempts, they will be displayed an error message and won't be allowed to login.
- If the user provides a login that matches a stored login in the
userListarray, then display a success message.
To do this, we need to..
- Loop through
userListand compare login info until we have found a match or reached the end of the array. - Once we have found a match, we can exit out of the loop and display a success message.
- If we reach the end of the loop and still have no matches, we can display a warning or error message depending on the value of
attempts.
Here is your submit function revised with some comments explaining the changes I made for you. Let me know if this helps or if you have any other questions!
var submit = function(e) {
// No need to decide if or when to do this, it can go at the top of your function
e.preventDefault();
// Use `match` to store a matching login object if one is found, otherwise leave it undefined (literally)
var match;
// Loop through `userList` to check for matching logins
for (var i = 0; i < userList.length; i++) {
// Cache the `username` and `password` values provided in the form
// (I renamed your vars to use a simpler naming convention)
var user = userList[i].name;
var pass = userList[i].password;
// If the username and password are strictly equal to the current username and password in the loop,
// then we have found a match and we can exit this loop
if (user === userName.value && pass === password.value) {
match = userList[i];
break; // this will exit the loop early
}
// We won't do anything else to handle non-matching iterations.
// The fact that `match` remains `undefined` is enough for us to work with.
}
// Now that the loop is finished... did we find a matching login?
if (match) {
// Display "successful" message
alertBoxGreen.innerHTML = "<h3>Welcome back, " + userName.value + "!</h3>";
alertBoxGreen.style.display = "block";
alertBoxRed.style.display = "none";
form.style.display = "none";
greenCheck.style.display = "inline-block";
userName.value = "";
password.value = "";
// Reset `attempts` after a successful login
attempts = 0;
} else {
// If the user has attempted and failed to login 3 times already, totally deny them
if (attempts > 3) {
alertBoxRed.innerHTML = "<h3>Denied!</h3>";
userName.disabled = true;
password.disabled = true;
submitBtn.disabled = true;
// Otherwise, give them another chance
} else {
alertBoxRed.innerHTML = "<h3>You have entered the wrong information. Please try again " + "[" + attempts + " attempt[s]" + " out of 3 to log in]</h3>";
alertBoxRed.style.display = "block";
userName.value = "";
password.value = "";
// Increment `attempts`
attempts += 1;
}
}
}
miikis
44,957 PointsHey Kristian,
I had half an hour to kill so I cleaned it up for you — even added a CSS file lol But hey man, keep in mind that, in the real world, you would never, ever, ever, ever, EVER, EVER, EVER create a login form entirely in JavaScript like this. Like ever. Just don't do it. Anyway, the code's below; feel free to ask any questions you might have ;)
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Kristian's Form</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<section class="login">
<h1 class="login-header">Kristian's Form</h1>
<form class="form" method="post">
<div class="form-section">
<label class="form-label" for="username">Username</label>
<i class="form-hint is-hidden">Username cannot be empty!</i>
<input class="form-input" id="username" name="username" type="text" placeholder="Enter username..." autofocus autocomplete="off">
</div>
<div class="form-section">
<label class="form-label" for="password">Password</label>
<i class="form-hint is-hidden">Password must be 6 characters long!</i>
<input class="form-input" id="password" name="password" type="password" placeholder="Enter password...">
</div>
<button class="form-submit" type="submit">Submit!</button>
</form>
<footer class="feedback is-hidden">
<p class="feedback-msg"> </p>
</footer>
</section>
<script src="app.js" charset="utf-8"></script>
</body>
</html>
styles.css
*,
*::after,
*::before {
box-sizing: border-box; }
body,
h1,
p {
padding: 0;
margin: 0; }
body {
font-family: sans-serif;
font-size: 16px;
background: #c4f5f0; }
.login {
color: #13746a;
width: 600px;
margin: auto; }
.login-header {
text-align: center;
margin-bottom: 20px; }
.form {
width: 100%;
margin-bottom: 20px; }
.form-section {
width: 100%;
position: relative;
padding: 20px 0; }
.form-label {
float: left;
display: block;
width: 25%;
padding-bottom: 10px;
vertical-align: baseline; }
.form-hint {
display: block;
float: right;
width: 75%;
padding-top: 5px;
text-align: right; }
.form-input {
width: 100%;
font-size: 1.5em;
padding: 10px;
border: 2px solid turquoise;
outline: none;
border-radius: 5px;
background: #c4f5f0;
color: #13746a; }
.form-submit {
display: block;
width: 75%;
padding: 5px;
background: turquoise;
border: none;
margin: auto;
border-radius: 5px;
font-size: 2em;
color: #13746a;
transition: all 150ms ease-in;
cursor: pointer; }
.form-submit:hover {
border: 3px solid #13746a; }
.form-submit:active {
background: #21ccbb;
border: 1px solid #13746a; }
.feedback {
width: 100%;
height: 50px;
position: relative;
font-size: 1.25em; }
.feedback-msg {
position: absolute;
width: 100%;
padding: 10px 0;
text-align: center;
bottom: -100%;
transition: 300ms all ease-in-out;
color: white; }
.feedback-msg.is-success {
background: turquoise;
bottom: 0; }
.feedback-msg.is-success::before {
content: "\2713";
padding-right: 5px; }
.feedback-msg.is-error {
background: firebrick;
bottom: 0; }
.feedback-msg.is-error::before {
content: "\2A09 ";
padding-right: 5px; }
.is-hidden {
display: none; }
app.js
// I lengthened the passwords of bob and jon ...
// because you seemed like you wanted a valid password to be at least 6 characters
const USERS = [
{
name: "anka",
password: "H2X835"
}, {
name: "bob",
password: "bob123"
}, {
name: "jon",
password: "jon321"
}
]
var maxAttempts = 3
const $form = document.querySelector('.login .form')
const $username = $form.querySelector('#username')
const $password = $form.querySelector('#password')
const $usernameHint = $form.querySelectorAll('.form-hint')[0]
const $passwordHint = $form.querySelectorAll('.form-hint')[1]
const $feedback = document.querySelector('.feedback')
const $feedbackMsg = $feedback.querySelector('.feedback-msg')
$form.addEventListener('submit', function(event) {
event.preventDefault()
// A dirty, nasty, despicable way of denying access
if (maxAttempts <= 0) {
document.write('ACCESS DENIED!!!')
alert('WHOA! YOU\'VE MAXED OUT YOUR 3 ATTEMPTS!')
}
const username = $username.value.toLowerCase()
const password = $password.value.toLowerCase()
// Is username empty?
if (!username) {
$usernameHint.classList.remove('is-hidden')
maxAttempts--;
return false
} else {
$usernameHint.classList.add('is-hidden')
}
// Is password empty or less than six characters?
if (!password || password.length < 6) {
$passwordHint.classList.remove('is-hidden')
maxAttempts--;
return false
} else {
$passwordHint.classList.add('is-hidden')
}
// A more-inutitive method of filtering an array
const isValidUser = USERS.filter(function(user) {
return user.name === username && user.password === password
})
// Does a user by that username and password exist?
if (isValidUser.length) {
$feedback.classList.remove('is-hidden')
$feedbackMsg.classList.remove('is-error')
$feedbackMsg.classList.add('is-success')
$feedbackMsg.textContent = 'Login Successful! Welcome, ' + isValidUser[0].name.toUpperCase() + '!'
} else {
$feedback.classList.remove('is-hidden')
$feedbackMsg.classList.add('is-error')
$feedbackMsg.classList.remove('is-success')
$feedbackMsg.textContent = 'Sorry! There is no user named ' + username.toUpperCase() + ' with that password!'
maxAttempts--
}
})
Kristian Woods
23,414 PointsHey man, thank you for all the effort you put into this
miikis
44,957 PointsNah it's nothing. Did it help you out at all though? Lol I was gonna do it like Matt Milburn and just point out where you went wrong but I had time to kill and got carried away.
Vance Rivera
18,323 PointsThis is how I would go about solving this issue. Comments in code to help you understand. Let me know if you need any more help. Cheers!
var submit = function (e) {
e.preventDefault();
//Find the index of the User in user list by userName if it exist else return -1
var userIndex = userList.map(function (r)
{
//create an array with just user names from userList
return r.name.toLowerCase();
}) //return index of name or -1 if not found
.indexOf(userName.value.toLowerCase());
//if too many attempts disable controls
if (attempts > 3) {
alertBoxRed.innerHTML = "<h3>Denied!</h3>";
userName.disabled = true;
password.disabled = true;
submitBtn.disabled = true;
//Return from the call and do not continue any further
return;
}
//if userIndex is not found or the userIndex is found and password doesn't match
if (userIndex === -1 || (userIndex >= 0 && userList[userIndex].password !== password.value)) {
//increment attempts
attempts += 1;
alertBoxRed.innerHTML = "<h3>You have entered the wrong information. Please try again " + "[" + attempts + " attempt[s]" + " out of 3 to log in]</h3>";
alertBoxRed.style.display = "block";
userName.value = "";
password.value = "";
} else {
//user and password match WELCOME!!
//reset attempts
attempts = 0;
alertBoxGreen.innerHTML = "<h3>Welcome back, " + userName.value + "!</h3>";
alertBoxGreen.style.display = "block";
alertBoxRed.style.display = "none";
form.style.display = "none";
greenCheck.style.display = "inline-block";
userName.value = "";
password.value = "";
}
}
Matt Milburn
20,787 PointsYou're welcome! I tried not to overwhelm my example with too many changes for you. Glad it helped!
Kristian Woods
23,414 PointsKristian Woods
23,414 PointsHey, Matt, thank you so much, man. Your code worked and really helped me to understand a few concepts. I really appreciated the comments, too
Thanks again