이번 과제는 동아리 활동 때 했던 네이버 회원가입 창 클론코딩에 이어서
html과 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>네이버 : 회원가입</title>
<link rel="stylesheet" href="join.css">
</head>
<body>
<div id="header">
<a href="https://nid.naver.com/user2/V2Join.nhn?m=agree#agreeBottom" target="_blank" title="네이버 회원가입 페이지 바로가기">
<img id="logo" src="NAVER_CI_Green.png">
</a>
</div>
<div id="rapper">
<div id="content">
<!-- id -->
<div>
<h3 class="join_title">
<label for="id">아이디</label>
</h3>
<span class="box info_id">
<input type="text" id="id" class="info" maxlength="20">
<span class="auto_url">@naver.com</span>
</span>
<span class="error_next_box"></span>
</div>
<!-- pw -->
<div>
<h3 class="join_title">
<label for="pw1">비밀번호</label>
</h3>
<span class="box info_pw">
<input type="password" id="pw1" class="info" maxlength="20">
<img src="m_icon_pass.png" id="pw1_img1" class="pwImg">
</span>
<span class="error_next_box"></span>
</div>
<!-- pw_check -->
<div>
<h3 class="join_title">
<label for="pw2">비밀번호 재확인</label>
</h3>
<span class="box info_pw_check">
<input type="password" id="pw2" class="info" maxlength="20">
<img src="m_icon_check_disable.png" id="pw2_img1" class="pwImg">
</span>
<span class="error_next_box"></span>
</div>
<!-- name -->
<div>
<h3 class="join_title">
<label for="name">이름</label>
</h3>
<span class="box info_name">
<input type="text" id="name" class="info" maxlength="20">
</span>
<span class="error_next_box"></span>
</div>
<!-- birth yy -->
<div>
<h3 class="join_title">
<label for="yy">생년월일</label>
</h3>
<div id="bir_wrap">
<div id="bir_yy">
<span class="box">
<input type="text" id="yy" class="info" maxlength="4" placeholder="년(4자)">
</span>
</div>
<!-- dirth mm -->
<div id="bir_mm">
<span class="box">
<select id="mm" class="set">
<option>월</option>
<option value="01">1</option>
<option value="02">2</option>
<option value="03">3</option>
<option value="04">4</option>
<option value="05">5</option>
<option value="06">6</option>
<option value="07">7</option>
<option value="08">8</option>
<option value="09">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
</select>
</span>
</div>
<!-- dirth day -->
<div id="bir_dd">
<span class="box">
<input type="text" id="dd" class="info" maxlength="2" placeholder="일">
</span>
</div>
</div>
</div>
<!-- gender -->
<div>
<h3 class="join_title">
<label for="gender">성별</label>
</h3>
<span class="box info_gender">
<select id="gender" class="set">
<option>성별</option>
<option value="F">여자</option>
<option value="M">남자</option>
<option value="U">선택 안함</option>
</select>
</span>
</div>
<!-- phone-number -->
<div>
<h3 class="join_title">
<label for="mobile">휴대전화</label>
</h3>
<span class="box info_mobile">
<input type="text" id="mobile" class="info" maxlength="18" placeholder="전화번호 입력">
</span>
<span class="error_next_box"></span>
</div>
<!-- join-button -->
<div class="btn_area">
<button type="button" id="button">
<span>가입하기</span>
</button>
</div>
</div>
</div>
<script type="text/javascript" src="join.js"></script>
</body>
</html>
html {
height: 100%;
}
body {
margin: 0;
height: 100%;
background: #f3f6f7;
font-family: Dotum, '돋움', Arial, Helvetica, sans-serif;
}
#logo {
width: 240px;
height: 44px;
}
#header {
padding-top: 60px;
padding-bottom: 20px;
text-align: center;
}
#rapper {
position: relative;
height: 100%;
}
#content {
position: absolute;
left: 50%;
transform: translate(-50%);
width: 460px;
}
label {
cursor: pointer;
}
input:focus {
outline: none;
}
h3 {
margin: 19px 0 8px;
font-size: 14px;
font-weight: 700;
}
.box {
display: block;
width: 100%;
height: 51px;
border: solid 1px #dadada;
padding: 10px 14px 10px 14px;
background: #ffffff;
box-sizing: border-box;
/* 테두리 포함 */
position: relative;
}
.info {
display: block;
position: relative;
width: 100%;
height: 29px;
border: none;
background-color: #ffffff;
font-size: 15px;
}
input {
font-family: Dotum, '돋움', Helvetica, sans-serif;
}
.box.info_id {
padding-right: 110px;
}
.box.info_pw {
padding-right: 40px;
}
.box.info_pw_check {
padding-right: 40px;
}
.auto_url {
position: absolute;
top: 16px;
right: 13px;
font-size: 15px;
color: #8e8e8e;
}
.pwImg {
width: 18px;
height: 20px;
display: inline;
position: absolute;
top: 50%;
right: 16px;
margin-top: -10px;
cursor: pointer;
}
#bir_wrap {
display: table;
width: 100%;
}
#bir_yy {
display: table-cell;
width: 147px;
}
#bir_mm {
display: table-cell;
width: 147px;
vertical-align: middle;
}
#bir_dd {
display: table-cell;
width: 147px;
}
#bir_mm,
#bir_dd {
padding-left: 10px;
}
.set {
width: 100%;
height: 29px;
font-size: 15px;
line-height: 18px;
color: #000;
background: #ffffff url("sel_arr_2x.gif") 100% 50% no-repeat;
-webkit-appearance: none;
display: inline;
text-align: start;
border: none;
cursor: default;
font-family: Dotum, '돋움', Helvetica, sans-serif;
}
.error_next_box {
margin-top: 9px;
font-size: 9px;
color: red;
}
.btn_area {
margin: 3px 0 9px;
}
#button {
display: block;
width: 100%;
padding: 15px 0 15px;
border: solid 1px rgba(0, 0, 0, .08);
cursor: pointer;
background-color: #03c75a;
font-size: 18px;
text-align: center;
font-weight: 700;
box-sizing: border-box;
font-family: Dotum, '돋움', Helvetica, sans-serif;
color: #fff;
}
var id = document.querySelector('#id');
var pw1 = document.querySelector('#pw1');
var pwMsg = document.querySelector('#alertTxt');
var pwImg1 = document.querySelector('#pw1_img1');
var pw2 = document.querySelector('#pw2');
var pwImg2 = document.querySelector('#pw2_img1');
var pwMsgArea = document.querySelector('.state_pass');
var userName = document.querySelector('#name');
var yy = document.querySelector('#yy');
var mm = document.querySelector('#mm');
var dd = document.querySelector('#dd');
var gender = document.querySelector('#gender');
var email = document.querySelector('#email');
var mobile = document.querySelector('#mobile');
var error = document.querySelectorAll('.error_next_box');
/*이벤트 핸들러 연결*/
id.addEventListener("focusout", checkId);
pw1.addEventListener("focusout", checkPw);
pw2.addEventListener("focusout", comparePw);
userName.addEventListener("focusout", checkName);
yy.addEventListener("focusout", isBirthCompleted);
mm.addEventListener("focusout", isBirthCompleted);
dd.addEventListener("focusout", isBirthCompleted);
gender.addEventListener("focusout", function() {
if(gender.value === "성별") {
error[5].style.display = "block";
} else {
error[5].style.display = "none";
}
})
email.addEventListener("focusout", isEmailCorrect);
mobile.addEventListener("focusout", checkPhoneNum);
/*콜백 함수*/
function checkId() {
var idPattern = /[a-zA-Z0-9_-]{5,20}/;
if(id.value === "") {
error[0].innerHTML = "필수 정보입니다.";
error[0].style.display = "block";
} else if(!idPattern.test(id.value)) {
error[0].innerHTML = "5~20자의 영문 소문자, 숫자와 특수기호(_),(-)만 사용 가능합니다.";
error[0].style.display = "block";
} else {
error[0].innerHTML = "멋진 아이디네요!";
error[0].style.color = "#08A600";
error[0].style.display = "block";
}
}
function checkPw() {
var pwPattern = /[a-zA-Z0-9~!@#$%^&*()_+|<>?:{}]{8,16}/;
if(pw1.value === "") {
error[1].innerHTML = "필수 정보입니다.";
error[1].style.display = "block";
} else if(!pwPattern.test(pw1.value)) {
error[1].innerHTML = "8~16자 영문 대 소문자, 숫자, 특수문자를 사용하세요.";
pwMsg.innerHTML = "사용불가";
pwMsgArea.style.paddingRight = "93px";
error[1].style.display = "block";
pwMsg.style.display = "block";
pwImg1.src = "m_icon_not_use.png";
} else {
error[1].style.display = "none";
pwMsg.innerHTML = "안전";
pwMsg.style.display = "block";
pwMsg.style.color = "#03c75a";
pwImg1.src = "m_icon_safe.png";
}
}
function comparePw() {
if(pw2.value === pw1.value && pw2.value != "") {
pwImg2.src = "m_icon_check_enable.png";
error[2].style.display = "none";
} else if(pw2.value !== pw1.value) {
pwImg2.src = "m_icon_check_disable.png";
error[2].innerHTML = "비밀번호가 일치하지 않습니다.";
error[2].style.display = "block";
}
if(pw2.value === "") {
error[2].innerHTML = "필수 정보입니다.";
error[2].style.display = "block";
}
}
function checkName() {
var namePattern = /[a-zA-Z가-힣]/;
if(userName.value === "") {
error[3].innerHTML = "필수 정보입니다.";
error[3].style.display = "block";
} else if(!namePattern.test(userName.value) || userName.value.indexOf(" ") > -1) {
error[3].innerHTML = "한글과 영문 대 소문자를 사용하세요. (특수기호, 공백 사용 불가)";
error[3].style.display = "block";
} else {
error[3].style.display = "none";
}
}
function isBirthCompleted() {
var yearPattern = /[0-9]{4}/;
if(!yearPattern.test(yy.value)) {
error[4].innerHTML = "태어난 년도 4자리를 정확하게 입력하세요.";
error[4].style.display = "block";
} else {
isMonthSelected();
}
function isMonthSelected() {
if(mm.value === "월") {
error[4].innerHTML = "태어난 월을 선택하세요.";
} else {
isDateCompleted();
}
}
function isDateCompleted() {
if(dd.value === "") {
error[4].innerHTML = "태어난 일(날짜) 2자리를 정확하게 입력하세요.";
} else {
isBirthRight();
}
}
}
function isBirthRight() {
var datePattern = /\d{1,2}/;
if(!datePattern.test(dd.value) || Number(dd.value)<1 || Number(dd.value)>31) {
error[4].innerHTML = "생년월일을 다시 확인해주세요.";
} else {
checkAge();
}
}
function checkAge() {
if(Number(yy.value) < 1920) {
error[4].innerHTML = "정말이세요?";
error[4].style.display = "block";
} else if(Number(yy.value) > 2024) {
error[4].innerHTML = "미래에서 오셨군요. ^^";
error[4].style.display = "block";
} else if(Number(yy.value) > 2008) {
error[4].innerHTML = "만 14세 미만의 어린이는 보호자 동의가 필요합니다.";
error[4].style.display = "block";
} else {
error[4].style.display = "none";
}
}
function isEmailCorrect() {
var emailPattern = /[a-z0-9]{2,}@[a-z0-9-]{2,}\.[a-z0-9]{2,}/;
if(email.value === ""){
error[6].style.display = "none";
} else if(!emailPattern.test(email.value)) {
error[6].style.display = "block";
} else {
error[6].style.display = "none";
}
}
function checkPhoneNum() {
var isPhoneNum = /([01]{2})([01679]{1})([0-9]{3,4})([0-9]{4})/;
if(mobile.value === "") {
error[7].innerHTML = "필수 정보입니다.";
error[7].style.display = "block";
} else if(!isPhoneNum.test(mobile.value)) {
error[7].innerHTML = "형식에 맞지 않는 번호입니다.";
error[7].style.display = "block";
} else {
error[7].style.display = "none";
}
}
생각보다 간단하다!
body 태그 안에 script 태그를 추가하여 js파일을 연결하면 된다!
<script type="text/javascript" src="join.js"></script>
이미지 추가할 때를 생각하면 된다!
이때 body 태그 맨 아래에 적어주는 게 좋다고 한다.
그러한 이유는 컴파일 처리 순서때문이다.
마지막으로 나의 오류에 대해 설명을 하자면
동아리 활동했을 때 css까지 모든 작성을 마친 뒤 아이디, 비밀번호, 비밀번호 재확인, 이름, 생년월일까지의 체크 박스는 제대로 잘 나왔는데...
성별, 휴대전화의 체크박스가 css에서 설정한 값처럼 안 나오는 거였다 ㅠㅠ
html 안에서 div 태그의 위치들도 잘 맞았고, <>도 빠짐없이 작성했는데
왜 오류가 날까? 생각하다 발견한 오류는...
html 에서의 클래스명과 css의 클래스명이 일치하지 않아서였다...!
진짜 혹시나...? 하고 확인했는데
<span class="box_info_mobile">
.box{
display: block;
width: 100%;
height: 51px;
border: solid 1px #dadada;
padding: 10px 14px 10px 14px;
background: #ffffff;
box-sizing: border-box; /* 테두리 포함 */
position: relative;
}
당시 내가 html에 쓴 클래스 명은 'box_info_mobile' 인데
css에 쓴 명은 .box인 것...
그렇다 'box info_mobile'이라 작성해야 .box의 속성을 따로 지정할 수 있는 것인데 중간에 내가 홀로 언더바를 작성하는 바람에 속성 적용이 안 되고 있던 거다 ㅋㅋ...
(동아리 활동 중 혼자 코드를 작성해보겠다고 혼자 클래스 명을 다르게 써서...)
클래스 명을 box info_mobile로 변경하니 아주 깔끔하게 css가 적용된 창을 볼 수 있었다 ^^
오류는 생각보다 기본적인 곳에서 많이 나니
오타, 클래스 명의 일치, 태그가 잘 닫혔는지, 태그의 정렬이 잘 됐는지를 먼저 확인하자!!!