🦁 멋사 2번째 ν™œλ™

황닀은·2023λ…„ 3μ›” 26일
1

멋사 2μ£Όμ°¨ ν•™μŠ΅μœΌλ‘œ 넀이버 νšŒμ›κ°€μž… νŽ˜μ΄μ§€μ˜ μ½”λ“œλ₯Ό μ°Έκ³ ν•œ 클둠 코딩을 μ§„ν–‰ν–ˆλ‹€.

μ‹œμž‘ 전에 κ³ λͺ…이 사진 보고 νžλ§ν•˜κΈ°....



λ¨Όμ € 과제 인증 사진!

클둠 코딩은 기쑴에 μžˆλŠ” μ„œλΉ„μŠ€λ₯Ό λ³΅μ œν•˜λ“― λ‹€μ‹œ λ§Œλ“€λ©° ν•™μŠ΅ν•˜λŠ” 개발 ν•™μŠ΅ 방법둠이닀.
Django와 APIλ₯Ό 배운 후에 이 νšŒμ›κ°€μž… 창을 μ‘μš©ν•  수 μžˆμ„λ“―ν•΄μ„œ 넀이버 νšŒμ›κ°€μž… νŽ˜μ΄μ§€λ‘œ 클둠 코딩을 μ§„ν–‰ν–ˆλŠ”λ° 였λ₯˜κ°€ 뜨긴 ν–ˆμ§€λ§Œ 개인적으둠... μž¬λ°Œμ—ˆλ‹€.1μ£Όμ°¨μ—μ„œ κ°•μ˜λ₯Ό λ“€μœΌλ©° ν•™μŠ΅ν•œ λ‚΄μš©μ„ ν† λŒ€λ‘œ html의 전체적인 ꡬ쑰와 각 νƒœκ·Έμ˜ μ—­ν• , 속성값에 따라 cssκ°€ μ–΄λ–»κ²Œ μ μš©λ˜λŠ”μ§€ μ „λ°˜μ μΈ 과정을 μ‹€μŠ΅μ„ 톡해 λ³΅μŠ΅ν•  수 μžˆμ–΄μ„œ μ’‹μ•˜λ‹€.

html μ½”λ“œ

<!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>Naver : νšŒμ›κ°€μž…</title>
    <link rel="stylesheet" href="join.css">
</head>
<body>
    <!-- header -->
    <div id="header">
        <a href="https://nid.naver.com/user2/V2Join.nhn?m=agree#agreeBottom" target="_parent" title="넀이버 νšŒμ›κ°€μž… νŽ˜μ΄μ§€ λ³΄λŸ¬κ°€κΈ°">
            <img src="NAVER_CI_Green.png" id="logo">
        </a>
    </div>
    <!-- wrapper -->
    <div id="wrapper">
        <!-- content -->
        <div id="content">
            <!-- ID -->
            <div>
                <!-- h3νƒœκ·ΈλŠ” μ˜λ―Έμƒ ꡬ뢄 λ‹¨μœ„(μž…λ ₯폼의 제λͺ©)
                h3 νƒœκ·Έλ₯Ό λͺ¨μ•„μ„œ ν•œλ²ˆμ— μŠ€νƒ€μΌμ„ μ μš©ν•˜κΈ° μœ„ν•΄ μ‚¬μš© -->
                <h3 class="join_title">
                    <!-- label νƒœκ·ΈλŠ” "아이디" κΈ€μž ν΄λ¦­μ‹œ μž…λ ₯폼에 ν¬μ»€μŠ€κ°€ λ˜λŠ” κΈ°λŠ₯ 
                    νƒœκ·Έ ν΄λ¦­μ‹œ λ™μΌν•œ ID값을 가진 inputνƒœκ·Έλ‘œ μžλ™ ν¬μ»€μŠ€λ˜κΈ°λ•Œλ¬Έμ— 
                    label νƒœκ·Έμ˜ 아이디값을 "id"둜 μ„€μ •-->
                    <label for="id">아이디</label>
                </h3>
                <!-- spanνƒœκ·ΈλŠ” μž…λ ₯폼 전체λ₯Ό λ¬Άμ—ˆλ‹€λŠ” 의미둜 클래슀 box둜 μ„€μ • -->
                <span class="box info_id">
                    <!-- class="info"둜 λΉ„λ²ˆ, 이름 λ“± λͺ¨λ“  μž…λ ₯폼에 곡톡 μŠ€νƒ€μΌ 지정을 μœ„ν•¨
                    κΈ€μžμˆ˜ 20μ œν•œ -->
                    <input type="text" id="id" class="info" maxlength="20">
                    <span class="auto_url">@naver.com</span>
                </span>
                <!-- IDκ°’ 잘λͺ» μž…λ ₯μ‹œ μž…λ ₯ 폼 μ•„λž˜μ— μ—λŸ¬λ©”μ‹œμ§€ ν‘œκΈ° λΆ€λΆ„ λ‚˜νƒ€λ‚΄κΈ° μœ„ν•¨ -->
                <span class="error_next_box"></span>
            </div>

            <!-- PW1 -->
            <div>
                <h3 class="join_title">
                    <label for="pw1">λΉ„λ°€λ²ˆν˜Έ</label>
                </h3>
                <span class="box state_pass">
                    <input type="text" id="pw1" class="info" maxlength="20">
                    <span id="alertTxt">μ‚¬μš©λΆˆκ°€</span>
                    <img src="m_icon_pass.png" id="pw1_img1" class="pwImg">
                </span>
                <!-- js pwMsg 등둝 -->
                <span class="error_next_box" id="pwMsg"></span>
            </div>

            <!-- PW2  -->
            <div>
                <h3 class="join_title">
                    <label for="pw2">λΉ„λ°€λ²ˆν˜Έ μž¬ν™•μΈ</label>
                </h3>
                <span class="box state_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 name">
                    <input type="text" id="name" class="info" maxlength="20">
                </span>
                <span class="error_next_box"></span>
            </div>

            <!-- BIRTH -->
            <div>
                <h3 class="join_title">
                    <label for="yy">생년월일</label>
                </h3>
                <div id="bir_wrap">
                    <!-- BIRTH_YY -->
                    <div id="bir_yy">
                        <span class="box">
                            <input type="text" id="yy" class="info" maxlength="4" placeholder="λ…„(4자)">
                        </span>
                    </div>
                    
                    <!-- BIRTH_MM -->
                    <div id="bir_mm">
                        <span class="box">
                            <select id="mm" class="sel">
                                <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>

                    <!-- BIRTH_DD -->
                    <div id="bir_dd">
                        <span class="box">
                            <input type="text" id="dd" class="info" maxlength="2" placeholder="일">
                        </span>
                    </div>
                </div>
                <span class="error_next_box"></span>
            </div>

            <!-- GENDER -->
            <div>
                <h3 class="join_title">
                    <label for="gender">성별</label>
                </h3>
                <span class="box gender">
                    <select id="gender" class="sel">
                        <option value selected>성별</option>
                        <option value="M">λ‚¨μž</option>
                        <option value="F">μ—¬μž</option>
                        <option value="U">μ„ νƒμ•ˆν•¨</option>
                    </select>
                </span>
            </div>

            <!-- EMAIL -->
            <!-- <div>
                <h3 class="join_title">
                    <label for="email">본인 확인 이메일
                        <span class="optional">(선택)</span>
                    </label>
                </h3>
                <span class="box email">
                    <input type="text" id="email" class="info" maxlength="100" placeholder="μ„ νƒμž…λ ₯">
                </span>
                <span class="error_next_box"></span>
            </div> -->

            <!-- MOBILE -->
            <div>
                <h3 class="join_title">
                    <label for="phoneNum">νœ΄λŒ€μ „ν™”</label>
                </h3>
                <span class="box mobile">
                    <input type="text" id="mobile" class="info" maxlength="16" placeholder="μ „ν™”λ²ˆν˜Έ μž…λ ₯">
                </span>
                <span class="error_next_box"></span>
            </div>

            <!-- JOIN_BTN -->
            <div class="btn_area">
                <button type="button" id="btnJoin">
                    <span>κ°€μž…ν•˜κΈ°</span>
                </button>
            </div>
        </div>
        <!-- content -->
    </div>
    <!-- wrapper -->
    <script src="join.js"></script>
</body>
</html>


css μ½”λ“œ

html {
    height: 100%;
}

body {
    margin: 0;
    height: 100%;
    background: #f3f6f7;
    font-family: Dotum, '돋움', Helvetica, sans-serif;
}

#logo {
    width: 240px;
    height: 44px;
}

#header {
    padding-top: 62px;
    padding-bottom: 20px;
    text-align: center;
}

#wrapper {
    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: 70px;
}

.box {
    display: block;
    width: 100%;
    height: 51px;
    border: solid 1px #dadada;
    padding: 10px 14px 10px 14px;
    background: #fff;
    box-sizing: border-box;
    position: relative;
}

.info {
    display: block;
    position: relative;
    width: 100%;
    height: 20px;
    border: none;
    background: #fff;
    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-block;
    position: absolute;
    top: 50%;
    right: 16px;
    margin-top: -10px;
    cursor: pointer;
}

#bir_wrap {
    display: table;
    width: 100px;
}

#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: 10px;
}

.sel {
    width: 100px;
    height: 29px;
    font-size: 15px;
    line-height: 18px;
    color: #000;
    background: #fff url("sel_arr_2x.gif") 100% 50% no-repeat;
    wepkit-appearance: none;
    display: inline-block;
    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: 30px 0 91px;
}

#btnJoin {
    display: block;
    width: 100px;
    padding: 15px 0 10px;
    border: solid 1px rgb (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: white;
}


js(javaScript) μ½”λ“œ

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";
    }

    
}

μ§€κΈˆμ€ μž₯κ³ λ₯Ό 배우기 μœ„ν•œ 기초적인 html ꡬ쑰λ₯Ό 읡히기 μœ„ν•΄ κ°„λ‹¨ν•˜κ²Œ htmlκ³Ό cssλ₯Ό ν•™μŠ΅ν–ˆλ‹€. jsλŠ” μž₯κ³ λ₯Ό 배운 후에 ν–‘μŠ΅ν•  μ˜ˆμ •μ΄λ‹€.

0개의 λŒ“κΈ€