Web Developer Tool 을 이용해서 CSS 를 지워보면 이런 HTML 구조가 나오는데, 이런 구조에 맞춰서 HTML 을 작성해보았다.
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Form Validator</title>
</head>
<body>
<div id="container">
<form id="form" class="form">
<h2>Register With Us</h2>
<div class="form-control">
<label for="Username">Username</label>
<input id="userName" type="text" placeholder="Enter username">
<small>Error Message</small>
</div>
<div class="form-control">
<label for="Email">Email</label>
<input id="email" type="email" placeholder="Enter email">
<small>Error Message</small>
</div>
<div class="form-control">
<label for="password">Password</label>
<input id="password" type="password" placeholder="Enter password">
<small>Error Message</small>
</div>
<div class="form-control">
<label for="Confirmpassword">Confrim Password</label>
<input id="confirmPassword" type="password" placeholder="Enter password again">
<small>Error Message</small>
</div>
<button>Submit</button>
</form>
</div>
</body>
HTML 에서 label 은 form 요소에서의 이름표라고 생각하면 된다.
form 안에서 input 칸들이 여러개 놓여져 있을때, 이 input 칸들을 각각 필요한 네이밍으로 나누어줌으로써
input 과의 연계성을 조금 더 유연하게 만든다.
예를 들어서 label 없이 input 창만 있다면
정확히 이 input 칸을 클릭해서 값을 입력해야하지만 label 을 사용해서 나누어 놨다면
저 Username 이 쓰여져있는 칸만 클릭해도 인풋칸이 클릭 되는걸 확인할 수 있다.
❗️ input 창의 id와 label for = ' ' 안에 들어가는 값이 같아야한다 ❗️
small 태그는 크기가 작은 텍스트를 나타낼때 쓰는 태그이다.
<p>일반 글자 크기</p>
<small>small 태그를 사용한 글자 크기</small>
:root{ /* 가상 선택자*/
--success-color : #2ecc71;
--error-color : #e74c3c;
}
*{
box-sizing: border-box; /* box의 사이즈를 테두리 기준으로 정한다 */
}
body{
font-family: 'Open Sans', sans-serif;
background-color: #f9fafb;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
}
.container{
background-color: #fff;
border-radius: 5px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
width: 400px
}
h2{
font-size: 24px;
text-align: center;
margin: 0 0 20px;
}
.form{
padding: 30px 40px;
}
.form-control{
margin-bottom: 10px;
padding-bottom: 20px;
position: relative;
}
.form-control label{
color: #777;
display: block;
margin-bottom: 5px;
}
.form-control input{
border: 2px solid #f0f0f0;
border-radius: 4px;
display: block; /* 해당 라인 다 차지 */
width: 100%;
padding: 10px;
font-size: 14px;
}
.form-control input:focus{ /* 인풋창에 값 입력하려 할때 */
outline: 0;
border-color: #777;
}
.form-control.success input{
border-color: var(--success-color);
}
.form-control.error input{
border-color: var(--error-color);
}
.form-control small{
color : var(--error-color);
position: relative;
bottom: 0;
left: 0;
visibility: hidden;
}
.form-control.error small{
visibility: visible;
}
.form button{
cursor: pointer; /* 마우스 커서 버튼에 가져다 댔을때 */
background-color: #3498db;
border: 2px solid #3498db;
border-radius: 4px;
color: #fff;
display: block;
font-size: 16px;
padding: 10px;
margin-top: 20px;
width: 100%;
}
CSS 내에서 변수를 설정해주는 방법인데, Validator 내에서 값을 잘못 입력했을때는 빨간색, 잘 입력했다면 초록색 테두리를 띄어줘야 하므로 그 색깔을 담은 변수를 설정해줌으로써 중복을 줄일 수 있다.
document.addEventListener('DOMContentLoaded', () => {
const form = document.querySelector('#form');
const userName = document.querySelector('#userName');
const email = document.querySelector('#email');
const password = document.querySelector('#password');
const confirmPassword = document.querySelector('#confirmPassword');
// 확인 함수
function checkRequired(inputArr){
inputArr.forEach((input) => {
if(input.value.trim() === ''){
showError(input, toUpperFirstStr(input) + ' is required');
} else{
showSuccess(input);
}
})
}
// 에러 띄울 함수
function showError(input, message){
const formControl = input.parentElement;
formControl.className ='form-control error';
const small = formControl.querySelector('small');
small.innerText = message;
}
//성공 했을때 만들어줄 함수
function showSuccess (input){
const formControl = input.parentElement;
formControl.className = 'form-control success';
}
// 이메일 확인 함수
function checkEmail(input){
const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
if(re.test(input.value.trim())){
showSuccess(input);
} else{
showError(input, 'Email is not valid');
}
}
// 패스워드 일치하는지 확인하는 함수
function checkPasswordsMatch(input1, input2){
if(input1.value !== input2.value){
showError(input2, 'Passwords do not match');
}
}
// 첫 글자 대문자 만드는 함수
function toUpperFirstStr(input){
return input.id.charAt(0).toUpperCase() + input.id.slice(1); // 리턴중요
}
//길이 확인 함수
function checkLength(input, min, max){
if(input.value.length < min){
showError(input, toUpperFirstStr(input) + ' must be at least ' + min + ' characters')
} else if(input.value.length > max){
showError(input, toUpperFirstStr(input)+ ' must be less than '+ max + ' characters')
} else{
showSuccess(input);
}
}
// 폼에서 submit 이벤트가 발생했을때
form.addEventListener('submit', (e) =>{
e.preventDefault();
checkRequired([userName, email, password, confirmPassword]);
checkEmail(email);
checkLength(userName, 3, 15);
checkLength(password, 6, 25);
checkPasswordsMatch(password, confirmPassword);
})
})