오늘의 생각
유효성 검사부분 로직을 구현하며 계속해서 오류가 나는 난관을 겪었다 ㅠㅠ
계속해서 이 부분때문에 머리를 쥐어 뜯었지만.. 주말을 할애하여 결국!! 이 부분을 해결해서 날이 갈수록 코딩이 재밌어지고 있다 > < 아무래도 Javascript 쪽 공부는 막히는 부분이 많지만(^^) 하면 할수록 된다는 것을 깨닫게 되는 뿌듯한 언어인 것 같다.
오늘의 학습내용
코드스테이츠에서 마련해준 ID 입력란 / PW 입력란 / PW 확인란으로 이루어진 HTML 페이지에 나만의 스타일로 디자인을 입혔다. (턱시도냥 만만세 x_x)
ID/PW에 대한 유효성 검사는 Javascript로 적용하였다. 유효성 검사에는 크게 2가지로 ID(4글자 이상, 영문/숫자로만 조합)와 PW(패스워드&패스워드 확인란 일치 여부)에 대한 부분을 구현하였다.
처음 로직 구현 시, onkeyup 함수를 썼는데 ID input창에 글자수 제한/영문,숫자 조합 제한 2가지 유효성 검사를 넣으니 한가지만 구현이 되고 나머지는 적용이 안되는 오류가 계속 발생했다 ㅠㅠ..
대체 왜그런건지 이 문제로 거의 6시간을 코드를 잡고 씨름하다 빛과 소금같은 addEventListener를 발견했다. 알고보니 비교적 최근에 나온 addEventListener를 쓰면 이벤트를 동시에 여러개 적용할 수 있다고 한다.
더불어 기능별로 별도의 js파일로 모듈화를 하여 가독성을 높였고 변수나 함수는 따로 모아 코드를 작성하여 클린코드를 만들 수 있도록 수정하였다.
<!DOCTYPE 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>CAT WORLD</title>
<link rel="stylesheet" href="global-style.css" />
<link rel="stylesheet" href="style.css" />
<link
href="//spoqa.github.io/spoqa-han-sans/css/SpoqaHanSansNeo.css"
rel="stylesheet"
type="text/css"
/>
<!-- head 부분에 스크립트를 넣을때는 defer속성을 넣는것이 좋음. <script defer src = '파일명.js'></script> -->
<script defer src="script.js"></script>
<script defer src="validator.js"></script>
</head>
<body>
<h1>WELCOME to CATWORLD</h1>
<main>
<img
class="logo"
src="https://search.pstatic.net/sunny/?src=https%3A%2F%2Fi.pinimg.com%2F736x%2F7e%2F07%2F3e%2F7e073e87f3ae339819b1ce6a33e49b95.jpg&type=sc960_832"
alt="CODE_STATES_LOGO"
/>
<fieldset>
<input type="text" class="username" placeholder="NAME" />
</fieldset>
<div class="success-message hide">사용할 수 있는 아이디입니다</div>
<div class="failure-message hide">아이디는 네 글자 이상이어야 합니다</div>
<div class="validfailure-message hide">아이디는 영문 또는 숫자로만 이루어져야 합니다</div>
<fieldset>
<input type="password" id="password" placeholder="PASSWORD" />
</fieldset>
<fieldset>
<input
type="password"
id="password-retype"
placeholder="CONFIRM PASSWORD"
/>
</fieldset>
<div class="mismatch-message hide">비밀번호가 일치하지 않습니다</div>
<fieldset class="signup">
<button id="btn" disabled>JOIN</button>
</fieldset>
</main>
</body>
</html>
* {
box-sizing: border-box;
padding: 0;
margin: 0;
/* font-family: 'Spoqa Han Sans Neo', 'sans-serif'; */
font-family: 'Edu VIC WA NT Beginner', cursive;
color: var(--gray-900);
background-color: var(--white);
font-size: var(--default);
}
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
background-color: white;
/* background-image: url('https://png.pngtree.com/png-clipart/20190515/original/pngtree-small-green-fresh-tropical-leaf-plant-palm-leaf-rectangular-border-png-image_3793060.jpg'); */
}
main {
display: flex;
flex-direction: column;
align-items: center;
padding: 24px;
box-shadow: var(--big-box);
/* border: 1px solid var(--gray-10); */
border-radius: 4px;
}
h1 {
text-align: center;
font-size: 40px;
}
fieldset {
display: flex;
flex-direction: column;
border-radius: 4px;
border-color: var(--gray-10);
justify-content: center;
margin: 4px;
padding: 8px 12px;
}
fieldset > label {
display: inline-block;
width: 112px;
}
main > div {
color: var(--peach-600);
font-size: var(--t2);
padding-left: 20px;
}
.logo {
/* margin: 12px auto 36px; */
width: 250px;
}
button {
cursor: pointer;
border: none;
border-radius: 4px;
width: 12rem;
height: 2.25rem;
color: var(--white);
background-color: var(--black);
font-size: var(--t1);
transition: all 0.3s;
}
button:hover {
background-color: rgb(219, 125, 161);
}
input {
border: none;
width: 12rem;
font-size: var(--t1);
}
input:focus {
outline: none;
}
.hide {
display: none;
}
.signup {
border: none;
}
.btn {
font-family: 'Edu VIC WA NT Beginner', cursive;
}
.success-message {
color: blue;
}
// id 길이 = #username에 입력하는 값의 길이
// 메시지 출력은 class명의 hide 제거
// failureMessage.classList.add('hide')
// failureMessage.classList.remove('hide')
// addEventListener를 쓰는것이 더 용이(이벤트를 동시에 여러개 적용할 수 있음, 최근 매소드임)
let userName = document.querySelector('.username');
let password = document.querySelector('#password');
let passwordRetype = document.querySelector('#password-retype');
let mismatchMessage = document.querySelector('.mismatch-message');
let failureMessage = document.querySelector('.failure-message');
let successMessage = document.querySelector('.success-message');
let validfailureMessage = document.querySelector('.validfailure-message');
userName.addEventListener('keyup', () => {
// userName 길이가 0이면 메시지 다 숩기기
if (userName.value.length === 0) {
successMessage.classList.add('hide');
failureMessage.classList.add('hide');
validfailureMessage.classList.add('hide');
}
// isMoreThan4Length가 성립하면 성공메시지 띄우기
else if (isMoreThan4Length(userName.value)) {
successMessage.classList.remove('hide');
failureMessage.classList.add('hide');
validfailureMessage.classList.add('hide');
}
// isMoreThan4Length가 성립하지 않으면 실패메시지 띄우기
else if (!(isMoreThan4Length(userName.value))) {
failureMessage.classList.remove('hide');
successMessage.classList.add('hide');
validfailureMessage.classList.add('hide');
}
});
function isMoreThan4Length(value) {
return value.length >= 4;
}
passwordRetype.onkeyup = function () {
// isMatch의 리턴값이 false면 .mismatch-message를 띄운다
if (isMatch(password.value, passwordRetype.value) === false) {
mismatchMessage.classList.remove('hide');
// 비밀번호가 일치하면 join 버튼을 활성화하고 조건이 만족하지 못하면 join버튼을 비활성화한다.
submitBtn.setAttribute('disabled', null);
} else {
mismatchMessage.classList.add('hide');
submitBtn.removeAttribute('disabled');
}
}
// password1 과 password2가 일치하는지 확인
function isMatch(password1, password2) {
if (password1 === password2) {
return true;
} else {
return false;
}
}
// id에 영어, 숫자 외 글자를 입력하고 join버튼을 누르면 'ID는 영문/숫자로만 입력 가능합니다.' 메시지 띄우기
function onlyNumberAndEnglish(str) {
return /^[A-Za-z][A-Za-z0-9]*$/.test(str);
}
// [유효성 검증 함수]: 최소 8자 이상하면서, 알파벳과 숫자 및 특수문자(@$!%*#?&) 는 하나 이상 포함
function strongPassword(str) {
return /^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$/.test(str);
}
userName.addEventListener('keyup', () => {
if (userName.value.length === 0) {
successMessage.classList.add('hide');
failureMessage.classList.add('hide');
validfailureMessage.classList.add('hide');
}
// onlyNumberAndEnglish 값이 false면 validfailueMessage 띄우기
else if (onlyNumberAndEnglish(userName.value) === false) {
validfailureMessage.classList.remove('hide');
failureMessage.classList.add('hide');
successMessage.classList.add('hide');
}
})