Project kakao Day2 HTML, CSS, JS 작성

김지원·2022년 6월 23일
0

WebDevelop

목록 보기
9/21

-> fontAwesome 링크 추가


scope

: - 스코프(Scope)라는 영어 단어 자체는 ‘범위’라는 의미를 가진다.

  • 컴퓨터 공학, 그리고 JavaScript 에서도 ‘범위’의 의미를 가지고 있다

전역 스코프(Global Scope)

: 말 그대로 전역에 선언되어있어 어느 곳에서든지 해당 변수에 접근 가능하다.

지역 스코프(Local Scope)

: 해당 지역에서만 접근할 수 있어 지역을 벗어난 곳에선 접근할 수 없다

자바스크립트에서 함수를 선언하면 함수를 선언할 때마다 새로운 스코프를 생성하게 된다. 그러므로 함수 몸체에 선언한 변수는 해당 함수 몸체 안에서만 접근할 수 있는데 이걸 함수 스코프(function-scoped)라고 한다. 함수 스코프가 바로 지역 스코프의 예라고 할 수 있다.

querySelector() , querySelectorAll() , matches() 또는 Element.closest() 와 같은 DOM API에서 사용하는 경우 :scope 는 메서드가 호출 된 요소와 일치한다.
:scope 의사 클래스가 유용한 것으로 입증 된 상황 은 이미 검색된 Element 의 직계 자손을 가져와야 할 때, 즉 직접적인 애들을 데려오는 것이다.

classList

:자바스크립트에서는 classList 함수를 사용하여 HTML 요소에 class 속성을 추가, 제거, 변경, 여부확인이 가능하다.

  • 클래스를 조작하는 다양한 메서드들을 쓸 수 있다.

.classList.add(String)

:해당 요소의 클래스 속성값을 추가, 같은 클래스명 있는 경우 무시

.classList.remove(String)

: 클래스의 속성값을 체크하여 제거한다. 없는 경우 무시

.classList.contains(String)

:해당 요소의 클래스의 유무를 확인하여 true 또는 false로 구분

.classList.toggle(String)

: 클래스값이 있는지 체크하고 없으면 더하고 있으면 제거


-> index.unsugned.js

<body class="unsigned">
<div class="cover"></div>
<div class="resolution">
    <div class="exc">!</div>
    <div class="message">화면 크기를 더 크게 조정 해주세요.</div>
</div>
<form class="login-form" rel="loginForm">
    <div class="logo-container">
        <img class="logo" alt="카카오톡" th:src="@{/resources/images/login-form.logo.png}">
    </div>
    <div class="input-wrapper">
        <label class="label">
            <span hidden>이메일</span>
            <input autofocus class="input" maxlength="50" name="email" placeholder="카카오계정 (이메일)" type="email">
        </label>
        <label class="label">
            <span hidden>비밀번호</span>
            <input maxlength="100" class="input" name="password" placeholder="비밀번호" type="password">
        </label>
    </div>
    <input class="login-button" disabled type="submit" value="로그인">
    <label class="auto-sign-container">
        <input class="checkbox" name="autoSign" type="checkbox">
        <span class="checker">
            <i class="icon fa-solid fa-check"></i>
        </span>
        <span class="text">잠금모드로 자동로그인</span>
    </label>
    <ul class="menu">
        <li class="item">
            <a class="link" href="#" data-logic="register">카카오계정 만들기</a>
        </li>
        <li class="line"></li>
        <li class="item">
            <a class="link" href="#" data-logic="recover">비밀번호 재설정</a>
        </li>
    </ul>
</form>
<form class="register-form visible" rel="registerForm">
    <div class="progress" rel="progress">
        <div class="value" rel="value"></div>
    </div>
    <div class="step-container">
        <div class="step terms visible">
            <span class="title">카카오계정<br>서비스 약관에 동의해 주세요.</span>
            <label class="check-label">
                <input class="checkbox" name="terms-agree-all" type="checkbox">
                <span class="checker">
                    <i class="icon fa-solid fa-check"></i>
                </span>
                <span class="text">모두 동의합니다.</span>
            </label>
            <span class="all-warning">전체 동의는 필수 및 선택정보에 대한 동의도 포함되어 있으며, 개별적으로도 동의를 선택하실 수 있습니다.<br>선택항목에 대한 동의를 거부하시는 경우에도 서비스는 이용이 가능합니다.</span>
            <label class="check-label">
                <input class="checkbox" name="terms-no-kid" type="checkbox">
                <span class="checker">
                    <i class="icon fa-solid fa-check"></i>
                </span>
                <span class="text">만 14세 이상입니다.</span>
            </label>
            <label class="check-label">
                <input class="checkbox" name="terms-term" type="checkbox">
                <span class="checker">
                    <i class="icon fa-solid fa-check"></i>
                </span>
                <span class="text">[필수] 카카오계정 약관</span>
            </label>
            <label class="check-label">
                <input class="checkbox" name="terms-privacy" type="checkbox">
                <span class="checker">
                    <i class="icon fa-solid fa-check"></i>
                </span>
                <span class="text">[필수] 개인정보 수집 및 이용 동의</span>
            </label>
            <label class="check-label">
                <input class="checkbox" name="terms-profile" type="checkbox">
                <span class="checker">
                    <i class="icon fa-solid fa-check"></i>
                </span>
                <span class="text">[선택] 프로필정보 추가 수집 동의</span>
            </label>
            <input class="button" disabled type="button" rel="termsNext" value="동의">
        </div>
    </div>
</form>
</body>

-> index.insigned.css

@charset "UTF-8";

body.unsigned {
    width: 100%;
    height: 100%;
    background-color: rgb(var(--common-color-yellow-5));
    position: absolute;
}

body.unsigned > .cover {
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 50%);
    position: fixed;
}

body.unsigned > .resolution {
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    align-items: center;
    background-color: rgb(var(--common-color-yellow-5));
    display: none;
    flex-direction: column;
    justify-content: center;
    position: fixed;
    z-index: 2;
}

body.unsigned > .resolution > .exc {
    color: rgb(var(--common-color-brown-5));
    cursor: default;
    font-size: 5rem;
    margin-bottom: 1rem;
    user-select: none;
}

body.unsigned > .login-form {
    top: 50%;
    left: 50%;
    width: 25rem;
    align-items: stretch;
    background-color: rgb(var(--common-color-yellow-5));
    border: 0.0625rem solid rgba(var(--common-color-yellow-5), 90%);
    border-radius: 0.25rem;
    box-shadow: 0 0 0.5rem 0.0625rem rgba(50, 50, 50, 50%);
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    opacity: 0;
    padding: 5rem 2.75rem;
    pointer-events: none;
    position: fixed;
    transform: translate(-50%, -50%);
    z-index: 1;
}

body.unsigned > .login-form.visible {
    opacity: 1;
    pointer-events: all;
}

body.unsigned > .login-form > .logo-container {
    align-items: center;
    display: flex;
    flex-direction: row;
    justify-content: center;
    margin-bottom: 3rem;
}

body.unsigned > .login-form > .logo-container > .logo {
    width: 7.5rem;
    user-select: none;
    -webkit-user-drag: none;
}

body.unsigned > .login-form > .input-wrapper {
    align-items: stretch;
    background-color: rgb(255, 255, 255);
    border: 0.0625rem solid rgb(var(--common-color-yellow-4));
    border-radius: 0.25rem;
    display: flex;
    flex-grow: 0;
    flex-shrink: 0;
    flex-direction: column;
    justify-content: flex-start;
    margin-bottom: 0.45rem;
    overflow: hidden;
}

body.unsigned > .login-form > .input-wrapper > .label {
    align-items: stretch;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
}

body.unsigned > .login-form > .input-wrapper > .label:not(:last-of-type) {
    border-bottom: 0.0625rem solid rgb(225, 225, 225);
}

body.unsigned > .login-form > .input-wrapper > .label > .input {
    background-color: rgb(255, 255, 255);
    padding: 0.7rem 1rem;
}

body.unsigned > .login-form > .login-button {
    background-color: rgb(var(--common-color-brown-5));
    border: 0.0625rem solid rgb(var(--common-color-yellow-4));
    border-radius: 0.25rem;
    color: rgb(255, 255, 255);
    cursor: pointer;
    margin-bottom: 0.4rem;
    padding: 0.7rem 0;
}

body.unsigned > .login-form > .login-button:hover {
    background-color: rgb(var(--common-color-brown-6));
}

body.unsigned > .login-form > .login-button:active {
    background-color: rgb(var(--common-color-brown-4));
}

body.unsigned > .login-form > .login-button:disabled {
    background-color: rgb(246, 246, 246);
    color: rgb(180, 180, 180);
    cursor: default;
}

body.unsigned > .login-form > .auto-sign-container {
    align-items: center;
    color: rgb(var(--common-text-color-9));
    cursor: pointer;
    display: flex;
    flex-direction: row;
    font-size: 0.9rem;
    justify-content: flex-start;
    user-select: none;
}

body.unsigned > .login-form > .auto-sign-container > .checkbox {
    display: none;
}

body.unsigned > .login-form > .auto-sign-container > .checker {
    width: 1rem;
    height: 1rem;
    background-color: rgb(255, 255, 255);
    border: 0.0625rem solid rgb(var(--common-color-yellow-4));
    border-radius: 0.15rem;
    margin-right: 0.5rem;
    position: relative;
}

body.unsigned > .login-form > .auto-sign-container > .checker > .icon {
    top: calc(50% + 0.0625rem);
    left: 50%;
    color: rgb(var(--common-color-brown-5));
    display: none;
    font-size: 0.8rem;
    position: absolute;
    transform: translate(-50%, -50%);
}

body.unsigned > .login-form > .auto-sign-container > .checkbox:checked + .checker > .icon {
    display: inline-block;
}

body.unsigned > .login-form > .menu {
    align-items: center;
    display: flex;
    flex-direction: row;
    font-size: 0.9rem;
    justify-content: center;
    margin-top: 8rem;
}

body.unsigned > .login-form > .menu > .item > .link {
    color: rgb(var(--common-text-color-9));
    text-decoration: none;
}

body.unsigned > .login-form > .menu > .item > .link:hover {
    text-decoration: underline;
}

body.unsigned > .login-form > .menu > .line {
    height: 1rem;
    border-right: 0.0625rem solid rgb(var(--common-color-yellow-4));
    margin: 0 0.75rem;
}

body.unsigned > .register-form {
    top: 50%;
    left: 50%;
    width: 25rem;
    background-color: rgb(255, 255, 255);
    border: 0.0625rem solid rgb(225, 225, 225);
    border-radius: 0.25rem;
    box-shadow: 0 0 0.5rem 0.0625rem rgba(50, 50, 50, 50%);
    box-sizing: border-box;
    opacity: 0;
    padding: 2rem;
    pointer-events: none;
    position: fixed;
    transform: translate(-50%, -50%);
    z-index: 1;
}

body.unsigned > .register-form.visible {
    opacity: 1;
    pointer-events: all;
}

body.unsigned > .register-form > .progress {
    width: 6.5rem;
    height: 0.25rem;
    background-color: rgb(225, 225, 225);
    margin-bottom: 2rem;
    position: relative;
}

body.unsigned > .register-form > .progress > .value {
    top: 0;
    left: 0;
    width: 50%;
    height: 100%;
    background-color: rgb(100, 100, 100);
    position: absolute;
}

body.unsigned > .register-form > .step-container > .step {
    align-items: stretch;
    display: none;
    flex-direction: column;
    justify-content: flex-start;
}

body.unsigned > .register-form > .step-container > .step.visible {
    display: flex;
}

body.unsigned > .register-form > .step-container > .step > .title {
    font-size: 1.375rem;
    font-weight: 500;
    margin-bottom: 2rem;
}

body.unsigned > .register-form > .step-container > .step > .check-label {
    align-items: center;
    cursor: pointer;
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
    margin-bottom: 0.75rem;
    user-select: none;
}

body.unsigned > .register-form > .step-container > .step > .check-label > .checkbox {
    display: none;
}

body.unsigned > .register-form > .step-container > .step > .check-label > .checker {
    width: 1.25rem;
    height: 1.25rem;
    border: 0.0625rem solid rgb(220, 220, 220);
    border-radius: 50%;
    margin-right: 0.625rem;
    position: relative;
}

body.unsigned > .register-form > .step-container > .step > .check-label > .checkbox:checked + .checker {
    background-color: rgb(var(--common-color-yellow-5));
    border: 0.0625rem solid rgb(var(--common-color-yellow-5));
}

body.unsigned > .register-form > .step-container > .step > .check-label > .checker > .icon {
    top: 50%;
    left: 50%;
    color: rgb(220, 220, 220);
    font-size: 0.9rem;
    position: absolute;
    transform: translate(-50%, -50%);
}

body.unsigned > .register-form > .step-container > .step > .check-label > .checkbox:checked + .checker > .icon {
    color: rgb(255, 255, 255);
}

body.unsigned > .register-form > .step-container > .step > .check-label > .text {
    font-size: 1.0625rem;
    font-weight: 500;
}

body.unsigned > .register-form > .step-container > .step > .all-warning {
    border-bottom: 0.0625rem solid rgb(220, 220, 220);
    color: rgb(150, 150, 150);
    font-size: 0.8rem;
    margin-bottom: 1rem;
    padding-bottom: 1rem;
    padding-left: 2.125rem;
    text-align: justify;
}

body.unsigned > .register-form > .step-container > .step > .button {
    background-color: rgb(var(--common-color-yellow-5));
    border-radius: 0.25rem;
    cursor: pointer;
    margin-top: 2rem;
    padding: 0.75rem 0;
}

body.unsigned > .register-form > .step-container > .step > .button:hover {
    background-color: rgb(var(--common-color-yellow-4));
}

body.unsigned > .register-form > .step-container > .step > .button:active {
    background-color: rgb(var(--common-color-yellow-3));
}

body.unsigned > .register-form > .step-container > .step > .button:disabled {
    background-color: rgb(236,236,236);
    color: rgb(180, 180, 180);
    cursor: default;
}

@media screen and (max-width: 35rem) {
    body.unsigned > .login-form.visible {
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        border-radius: 0;
        justify-content: center;
        transform: none;
    }
    
    body.unsigned > .register-form.visible {
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        border-radius: 0;
        transform: none;
    }
}

@media screen and (max-height: 45rem) {
    body.unsigned > .login-form > .logo-container {
        margin-bottom: 2rem;
    }

    body.unsigned > .login-form > .menu {
        margin-top: 2rem;
    }
}

@media screen and (max-height: 35rem) {
    body.unsigned > .login-form.visible {
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        border-radius: 0;
        justify-content: center;
        transform: none;
    }
}

@media screen and (max-height: 27.5rem) {
    body.unsigned > .resolution {
        display: flex;
    }

    body.unsigned > .login-form {
        display: none;
    }
    body.unsigned > .register-form {
        display: none;
    }
}

-> index.unsigned.js

const Element = {
    visibilityClassName: 'visible',
    LoginForm: {
        getElement: () => window.document.body.querySelector(':scope > [rel="loginForm"]'),
        hide: () => Element.LoginForm.getElement().classList.remove(Element.visibilityClassName),
        isShown: () => Element.LoginForm.getElement().classList.contains(Element.visibilityClassName),
        show: () => Element.LoginForm.getElement().classList.add(Element.visibilityClassName)
    },
    RegisterForm: {
        Progress: {
            Value: {
                getElement: () => Element.RegisterForm.Progress.getElement().querySelector(':scope > [rel="value"]')
            },
            getElement: () => Element.RegisterForm.getElement().querySelector(':scope > [rel="progress"]'),
            setValue: (percent) => Element.RegisterForm.Progress.Value.getElement().style.width = `${percent}%`
        },
        Step: { // 약관동의 절차
            Terms: { // 동의 버튼
                Next: {
                    getElement: () => Element.RegisterForm.Step.Terms.getElement().querySelector(':scope > [rel=termsNext]')
                },
                names: [ //names 배열생성
                    {name: 'terms-no-kid', required: true},
                    {name: 'terms-term', required: true},
                    {name: 'terms-privacy', required: true},
                    {name: 'terms-profile', required: false}
                ],
                getElement: () => Element.RegisterForm.Step.getContainer().querySelector(':scope > .step.terms'),
                // terms의 구성요소로써 hide, isShown, show
                hide: () => Element.RegisterForm.Step.Terms.getElement().classList.remove(Element.visibilityClassName),
                isShown: () => Element.RegisterForm.Step.Terms.getElement().classList.contains(Element.visibilityClassName),
                show: () => Element.RegisterForm.Step.Terms.getElement().classList.add(Element.visibilityClassName)
            },
            getContainer: () => Element.RegisterForm.getElement().querySelector(':scope > .step-container')
            // Step의 요소는 getContainer는 함수 : step-container 약관동의의 내용이 담긴 div를 가져온다.
        },
        getElement: () => window.document.body.querySelector(':scope > [rel="registerForm"]'),
        hide: () => Element.RegisterForm.getElement().classList.remove(Element.visibilityClassName),
        isShown: () => Element.RegisterForm.getElement().classList.contains(Element.visibilityClassName),
        show: () => Element.RegisterForm.getElement().classList.add(Element.visibilityClassName)
    }
};

const Logic = {
    register: () => {
        Element.LoginForm.hide();
        Element.RegisterForm.show();
    }
};

window.document.body.querySelectorAll('a[data-logic]').forEach(x => {
    x.addEventListener('click', e => {
        e.preventDefault();
        const dataLogic = x.dataset.logic;
        if (typeof (Logic[dataLogic]) === 'function') {
            Logic[dataLogic]();
        }
    });
});

// Element.RegisterForm.getElement()['terms-agree-all'].addEventListener('change', e => {
//     //alert(e.target.checked);
//     Element.RegisterForm.getElement()['terms-no-kid'].checked = e.target.checked;
//     Element.RegisterForm.getElement()['terms-term'].checked = e.target.checked;
//     Element.RegisterForm.getElement()['terms-privacy'].checked = e.target.checked;
//     Element.RegisterForm.getElement()['terms-profile'].checked = e.target.checked;
// });
//모두 동의합니다 체크시  4가지 모두 체크된다.

Element.RegisterForm.getElement()['terms-agree-all'].addEventListener('change', e => {
    Element.RegisterForm.Step.Terms.names.forEach(x => {
        Element.RegisterForm.getElement()[x.name].checked = e.target.checked;
    });
    if (e.target.checked) {
        Element.RegisterForm.Step.Terms.Next.getElement().removeAttribute('disabled');
    } else {
        Element.RegisterForm.Step.Terms.Next.getElement().setAttribute('disabled', 'disabled');
    }
});
//모두 동의합니다 체크시  4가지 모두 체크된다. 에 대한 활성화 비활성화 '동의'가

Element.RegisterForm.Step.Terms.names.forEach(x => {
    Element.RegisterForm.getElement()[x.name].addEventListener('change', e => {
        if (!e.target.checked && Element.RegisterForm.getElement()['terms-agree-all'].checked) {
            Element.RegisterForm.getElement()['terms-agree-all'].checked = false;
        }// 4개 체크에 하나라도 빠지면 모두 동의한다라는체크가 빠진다는 의미 체크를 풀겟다.
        if (Element.RegisterForm.Step.Terms.names
            .filter(x => x.required === true)
            .every(x => Element.RegisterForm.getElement()[x.name].checked)) { // 이 파트에 대한 설명
            Element.RegisterForm.Step.Terms.Next.getElement().removeAttribute('disabled');
        } else {
            Element.RegisterForm.Step.Terms.Next.getElement().setAttribute('disabled', 'disabled');
        }      /* name 오브젝트에서  x.required === true 에 부합하는 애들만 걸러낸다. every는 전부 참일 때 반환한다.
            x.name =  name: `terms-term`이다 */
    });
});

-> 현재까지 결과


  • 모두 동의합니다 클릭시 4개 다 선택되도록 구현.
  • 선택을 제외한 나머지를 다 선택시 동의버튼 활성화

0개의 댓글