✿∘˚˳°∘°

46일차 : [실습] 단계형 회원가입 만들기 본문

국비수업/JavaScript

46일차 : [실습] 단계형 회원가입 만들기

_HYE_ 2023. 2. 2. 10:49

20230201

<!DOCTYPE html>
<html lang="ko">
<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="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="css/join1.css">
</head>
<body>
    <div class="wrap">
        <ul class="tabs">
            <li class="active-tab">약관확인</li>
            <li>필수정보입력</li>
            <li>상세정보입력</li>
            <li>가입완료</li>
        </ul>
        <!-- 본문4개가 들어갈 부분 -->
        <div class="content">
            <div class="contentDetail active-content">
                <!-- 본문1. 약관확인컨텐츠 -->
                <h3 class="title">이용약관 확인 및 동의</h3>
                <div>
                    <input type="checkbox" id="allAgreement">
                    <label for="allAgreement">이용약관 전체체크</label>
                </div>
                <div class="agreebox">
                    <div>
                        <input type="checkbox" id="privacyAgreement" class="agreeCheck">
                        <label for="privacyAgreement">개인정보 수집 및 이용에 동의 <span class="fc-blue">(필수)</span></label>
                        <div class="agreeContent">
                            <ul>
                                <li>수집항목 : 이름, 휴대전화번호, 생년월일, 비밀번호</li>
                                <li>수집/이용목적 : 회원제 서비스 제공</li>
                                <li>보유 및 이용기간 : 회원탈퇴 시 까지</li>
                            </ul>
                        </div>
                    </div>
                </div>
                <div class="agreebox">
                    <div>
                        <input type="checkbox" id="optionalAgreement" class="agreeCheck">
                        <label for="optionalAgreement">개인정보 수집 및 이용에 동의 <span class="fc-blue">(선택)</span></label>
                        <div class="agreeContent">
                            <ul>
                                <li>수집항목 : 이름, 휴대전화번호, 생년월일, 비밀번호</li>
                                <li>수집/이용목적 : 회원제 서비스 제공</li>
                                <li>보유 및 이용기간 : 회원탈퇴 시 까지</li>
                            </ul>
                        </div>
                    </div>
                </div>
                <div class="btnBox">
                    <button class="nextBtn">다음</button>
                </div>
            </div>
            <div class="contentDetail">
                <!-- 본문2. 필수정보입력컨텐츠 -->
                <h3 class="title">필수정보입력</h3>
                <table class="inputTbl">
                    <tr>
                        <td><label for="id">아이디</label></td>
                        <td><input type="text" class="input" name="id" id="id"><span id="idChk"></span></td>
                    </tr>
                    <tr>
                        <td><label for="pw">비밀번호</label></td>
                        <td><input type="password" class="input" name="pw" id="pw"></td>
                    </tr>
                    <tr>
                        <td><label for="pwRe">비밀번호확인</label></td>
                        <td><input type="password" class="input" name="pwRe" id="pwRe"><span id="pwChk"</td>
                    </tr>
                    <tr>
                        <td><label for="name">이름</label></td>
                        <td><input type="text" class="input" name="name" id="name"></td>
                    </tr>
                </table>
                <div class="btnBox">
                    <button class="nextBtn">다음</button>
                </div>
            </div>
            <div class="contentDetail">
                <!-- 본문3. 상세정보입력컨텐츠 -->
                <h3 class="title">추가정보입력</h3>
                <table class="inputTbl">
                    <tr>
                        <td>이메일</td>
                        <td>
                            <input type="text" class="input short" name="email1">
                            @
                            <input type="text" class="input short" name="email2">
                            <select name="emailSelect" id="emailSelect">
                                <option value="">직접입력</option>
                                <option value="naver.com">네이버</option>
                                <option value="gmail.com">구글</option>
                                <option value="nate.com">네이트</option>
                            </select>
                        </td>
                    </tr>
                    <tr>
                        <td>성별</td>
                        <td>
                            <input type="radio" name="gender" value="남" id="m">
                            <label for="m">남자</label>
                            <input type="radio" name="gender" value="여" id="f">
                            <label for="f">여자</label>
                        </td>
                    </tr>
                    <tr>
                        <td>자기소개</td>
                        <td>
                            <!-- 주의점 : 공간을 넓게줬다 - 여러줄을 사용해야함
                            input태그는 여러줄을 인식하지 못하므로 사용X -->
                            <textarea id="introduce"></textarea>
                        </td>
                    </tr>
                </table>
                <div class="btnBox">
                    <button class="nextBtn">다음</button>
                </div>
            </div>
            <div class="contentDetail">
                <!-- 본문4 : 가입완료 컨텐츠 -->
                <h3 class="title">가입을 축하합니다.</h3>
                <button class="nextBtn">로그인하기</button>
                <div id="loginFrm">
                    <div class="inputDiv">
                        <label for="loginId">아이디</label>
                        <input type="text" name="loginId" id="loginId" class="input">
                    </div>
                    <div class="inputDiv">
                        <label for="loginPw">비밀번호</label>
                        <input type="password" name="loginPw" id="loginPw" class="input">
                    </div>
                    <div class="btnBox">
                        <input type="submit" value="로그인" class="nextBtn">
                        <input type="button" value="취소" class="nextBtn">
                    </div>
                </div>
            </div>
        </div>
    </div>
    <script src="js/join1.js"></script>
</body>
</html>
*{
    font-family: 'Noto Sans KR', sans-serif;
    color: #282828;
    margin: 0;
    padding: 0;
    outline: none;
}
.wrap{
    width: 1200px;
    margin: 100px auto;
}
/* div는 display:block설정이기 때문에 한줄에 다른 컨텐츠가 올 수 없음
div를 가운데 정렬해주기 위해 1200px이외의 남은부분의 margin을 반으로 나눠
양옆에 제공해주는 margin:0 auto를 사용*/

.tabs{
    /*원래 ul의 불릿기호는 기본적으로 padding과 margin을 가지고 있으므로 
    div내부에 생성됨 -> 전체 마진과 패딩을 날려줘서 div영역 밖에 있는 것 */
    list-style-type: none;
    /*float 시 부모요소는 높이를 찾지X overflow:hidden을 넣어줘야함*/
    overflow: hidden;
}

.tabs>li{
    float: left;
    width: calc(100%/4);
    height: 70px;
    text-align: center;
    line-height: 70px;
    font-size: 18px;
    border: 1px solid #d8d8d8;
    box-sizing: border-box;
    /*width를 전체로 잡아놨는데 border의 1px이 추가되므로
    칸을 넘어가게된다 -> box-sizing을 통해 border포함 width를 설정해야줘야함*/
}

.content{
    border: 1px solid #d8d8d8;
    padding: 30px;
    border-top: none;
}
.tabs>li.active-tab{
    color: #1f4787;
    border-top: 10px solid #1f4787;
    font-weight: bold;
    line-height: 60px;
    border-bottom: none;
}

.contentDetail{
    display: none;
}
/* 이 클래스명을 이용해서 컨텐츠를 숨기고 보이고 할 것 */
/*같은클래스명에 우선순위가 동일할 경우 나중에 작성된게 우선순위가 더 높다*/
.active-content{
    display: block;
}
.title{
    font-size: 30px;
    color: #1f4787;
    margin-top: 30px;
    margin-bottom: 30px;
}

/* 본문1. 약관동의 컨텐츠 */

.agreeContent{
    width: 98%;
    margin: 0 auto;
    border: 1px solid #1f1111;
    margin-top: 5px;
    padding: 10px;
}

.agreeContent>ul{
    list-style-position: inside;
    padding-left: 10px;
}

.agreebox{
    margin-top: 30px;
}

input[type=checkbox]+label{
    font-size: 20px;
}

.fc-blue{
    color: #1f4787;
}

.btnBox{
    text-align: center;
    padding-top: 20px;
}

.nextBtn{
    width: 200px;
    height: 50px;
    background-color: #1f4787;
    border: none;
    color: #fff;
    font-size: 20px;
    cursor: pointer;
}


/* 본문2. 필수정보 입력 컨텐츠 */
.inputTbl{
    width: 98%;
    border-top: 1px solid #1f4787;
    border-bottom: 1px solid #b3b3b3;
}

/*tbody를 빼면 디자인이 들어가지 않는다
코드상에서 tbody가 들어가지 않더라도 개발자 도구에서 확인해보면
tbody가 자동으로 들어가있다 - 반드시 넣어야함!*/
.inputTbl>tbody>tr>td{
    border-top: 1px solid #ebebeb;
    font-size: 20px;
}

.inputTbl>tbody>tr>td:first-child{
    /*첫번째 td만 넓이를 지정해주면 다음td는 알아서 설정이된다(남은전체)*/
    width: 25%;
    background-color: #fbfcfd;
    border-right: 1px solid #ebebeb;
    padding-left: 20px;
}

.input{
    height: 35px;
    border: 1px solid #d8d8d8;
    font-size: 20px;
    width: 400px;
    padding-left: 10px;
}

.short{
    width: 280px;
}

.input:focus{
    border-color : #0e77d9;
}

#emailSelect{
    height: 40px;
    border: 1px solid #d8d8d8;
    font-size: 20px;
    width: 200px;
}
input[name=gender]{
    display: none;
}
input[name=gender]+label{
    display: inline-block;
    height: 40px;
    line-height: 40px;
    width: 150px;
    text-align: center;
    border: 1px solid #1f4787;
    color: #1f4787;
    cursor: pointer;
}
input[name=gender]:checked+label{
    background-color: #1f4787;
    color: #fff
}

#introduce{
    width: 600px;
    height: 300px;
    border: 1px solid #d8d8d8;
    font-size: 20px;
    resize: none;
}

#introduce:focus{
    border: 1px solid #0e77d9;
}
#loginFrm{
    width: 50%;
    margin: 0 auto;
    margin-top: 100px;
    font-size: 20px;
    display: none;
}

.inputDiv>label{
    display: block;
    margin-bottom: 20px;
    margin-top: 20px;
}

#loginFrm input{
    width: 100%;
}
.btnBox>input{
    margin-bottom: 20px;
}
const allAgreement = document.querySelector("#allAgreement");
allAgreement.addEventListener("change", function(){
    const agreeCheck = document.querySelectorAll(".agreeCheck");
    //체크박스의 상태를 가져옴
    const status = allAgreement.checked;
    /*
    if(status){
        agreeCheck[0].checked = true;
        agreeCheck[1].checked = true;
    }else{
        agreeCheck[0].checked = false;
        agreeCheck[1].checked = false;
    }
    */
    /*
    agreeCheck[0].checked = status;
    agreeCheck[1].checked = status;
    */
   //체크항목이 여러개면 for문사용
    /*
    for(let i=0; i<agreeCheck.length; i++){
        agreeCheck[i].checked = status;
    }
    */
    agreeCheck.forEach(function(agree){
        agree.checked = status;
    });
});

const nextBtn = document.querySelectorAll(".nextBtn");
nextBtn[0].addEventListener("click", function(){
    const privacyAgreement = document.querySelector("#privacyAgreement");
    const status = privacyAgreement.checked;

    if(status){
        /*
        const tabs = document.querySelectorAll(".tabs>li");
        const contentDetail = document.querySelectorAll(".contentDetail");
        tabs[0].classList.remove("active-tab");
        tabs[1].classList.add("active-tab");

        contentDetail[0].classList.remove("active-content");
        contentDetail[1].classList.add("active-content");
        */
        nextTab(0);
    }else{
        alert("이용약관 동의를 체크해주세요");
    }
});

const memberArr = ['user01', 'user02', 'user03'];

const id = document.querySelector("#id");
const pw = document.querySelector("#pw");
const pwRe = document.querySelector("#pwRe");
const name = document.querySelector("#name");

//아이디와 비밀번호가 정상적으로 들어갔는지 체크할 전역변수
//주의점 : 한글자만 입력했을 경우에도 아이디의 경우 배열에 있는 값과
//다르기때문에 true로 변화
//겹쳤을때 false로 되돌리는 작업을 해줘야함
let idCheckResult = false;
let pwCheckResult = false;


id.addEventListener("keyup", function(){
    const inputId = this.value;
    const check = memberArr.indexOf(inputId);
    const idChk = document.querySelector("#idChk");
    if(check == -1){
        //사용가능한 아이디인 경우
        idChk.innerText = "사용가능한 아이디 입니다.";
        idChk.style.color = "#1f4787";
        this.style.border = "1px solid #1f4787";
        idCheckResult = true;
    }else{
        //중복인 경우
        idChk.innerText = "이미 사용중인 아이디 입니다."
        idChk.style.color = "red";
        this.style.border = "1px solid red";
        idCheckResult = false;
    }
});

pw.addEventListener("change", function(){
    //비밀번호 확인이 비어있지 않을 때만 동작
    const inputPwRe = pwRe.value;
    if(inputPwRe != ""){
        pwCheck();
    }
});
pwRe.addEventListener("change", function(){
    pwCheck();
});

function pwCheck(){
    const inputPw = pw.value;
    const inputPwRe = pwRe.value;
    const pwChk = document.querySelector("#pwChk");
    if(inputPw == inputPwRe){
        pwChk.innerText = "비밀번호가 일치합니다."
        pwChk.style.color = "#1f4787";
        pw.style.border = "1px solid #1f4787";
        pwRe.style.border = "1px solid #1f4787";
        pwCheckResult = true;
    }else{
        pwChk.innerText = "비밀번호가 일치하지 않습니다."
        pwChk.style.color = "red";
        pw.style.border = "1px solid red";
        pwRe.style.border = "1px solid red";
        pwCheckResult = false;
    }
}

nextBtn[1].addEventListener("click", function(){
    if(idCheckResult && pwCheckResult && name.value != ""){
        nextTab(1);
    }else{
        alert("입력값을 확인하세요");
    }
});

/*
//0번탭에서 1번탭으로 변경하는 코드
const tabs = document.querySelectorAll(".tabs>li");
const contentDetail = document.querySelectorAll(".contentDetail");
tabs[0].classList.remove("active-tab");
tabs[1].classList.add("active-tab");

contentDetail[0].classList.remove("active-content");
contentDetail[1].classList.add("active-content");

//1번탭에서 2번탭으로 변경하는 코드
const tabs = document.querySelectorAll(".tabs>li");
const contentDetail = document.querySelectorAll(".contentDetail");
tabs[1].classList.remove("active-tab");
tabs[2].classList.add("active-tab");

contentDetail[1].classList.remove("active-content");
contentDetail[2].classList.add("active-content");
*/
//반복됨 -> 함수로 따로빼서 사용

function nextTab(tabNo){
    const tabs = document.querySelectorAll(".tabs>li");
    const contentDetail = document.querySelectorAll(".contentDetail");
    tabs[tabNo].classList.remove("active-tab");
    tabs[tabNo+1].classList.add("active-tab");
    contentDetail[tabNo].classList.remove("active-content");
    contentDetail[tabNo+1].classList.add("active-content");
}

//이메일을 선택하면 email2에 자동으로 들어가는 이벤트
//select에 이벤트를 걸어줘야함(option에는 이벤트를 걸 수 없다)
//option을 선택하면 해당 option의 value가 select의 value로 바뀜

const emailSelect = document.querySelector("#emailSelect");
emailSelect.addEventListener("change", function(){
    const selectedValue = emailSelect.value;
    console.log(selectedValue);
    const emailInput = document.querySelector("[name=email2]");
    emailInput.value = selectedValue;
});

nextBtn[2].addEventListener("click", function(){
    if(confirm("회원가입을 하시겠습니까?")){
        nextTab(2);
    }
});

nextBtn[3].addEventListener("click", function(){
    const loginFrm = document.querySelector("#loginFrm");
    loginFrm.style.display = "block";
});

[ 후기 ]

너무너무어려웠지만 구동되는걸 확인했을 땐 뭔가 뿌듯하기도하고 재미있었다

다만 내가 코드를 짤때는 엄청길어지고 뭔가 조잡해지는데 강사님이 해답코드를 주시면 너무 완벽해서 눈물이난다..^.ㅠ

좀 더 공부해서 나도 깔끔한 코드를 치고싶다~!

'국비수업 > JavaScript' 카테고리의 다른 글

45일차 : [실습] 상품상세페이지만들기  (0) 2023.02.02
44일차 : EVENT  (0) 2023.01.30
43일차 : [실습]DOM / BOM  (0) 2023.01.30
42일차 : DOM  (0) 2023.01.26
41일차 : JavaScript의 기본  (0) 2023.01.25
Comments