WEB/JAVASCRIPT

[JS] westagram login page (feat. 로그인 버튼 활성화&비활성화)

heeney 2021. 12. 7. 16:29
728x90

 

로그인 버튼 활성화&비활성화 (feat. westagram)

instagram을 클론코딩(westagram)하면서 과제로 주어졌던 로그인 버튼 활성화 & 비활성화 기능에 대한 내용을 정리했다.




 

과제 ➡️

  1. 로그인 페이지
    1-1. 로그인 페이지 레이아웃
    1-2. 로그인 페이지의 로그인 버튼 활성화 & 비활성화
  2. 메인 페이지
    2-1. 메인 페이지 레이아웃
    2-2. 메인 페이지 댓글 생성 기능

그 중 로그인 페이지를 먼저 작업하였다.
전체적인 westagram 레이아웃을 잡은 후 Javascript를 이용해 ID와 PassWord 입력란에 값이 모두 들어왔을 때만 로그인 버튼이 활성화 되도록 구현한다.

 

 

checkList ✅

  • ID와 PassWord 둘 다 입력이 들어왔을 때만 로그인 버튼이 활성화 되는가?
    => ID만 입력이 되거나 PW만 입력 되었을 때 로그인 버튼이 활성화 되면 안된다.
  • 입력 도중에 ID 값이나 PassWord 값을 지우면 로그인 버튼이 비활성화 되는가?
    => 실시간으로 사용자가 ID 값 혹은 PW를 재 입력하기 위해 지워서 값이 사라지면 로그인 버튼을 비활성화 해야한다.

 

 

완성된 화면 🙋🏻‍♀️

westagram login page

 

전체적인 너비, 높이, 색상 등의 기본적인 style은 인스타그램을 참고 하였다.
컨텐츠가 수평 및 수직 정렬 되도록 flex를 이용했다.
아직 flex의 내용이 익숙치 않아서 정렬할 때 어리숙하게 진행한 부분이 마음에 걸렸다.
flex 공부했는데 며칠만에 휘발해버렸다, 조만간 flex에 대한 총정리가 필요할 듯 싶다 😅

사용자가 입력 하기 전에는 default로 로그인 버튼이 비활성화 되어있다.
클릭(페이지 이동)도 안되고 cursor: pointer 기능도 없고 빈 깡통의 버튼이다.
그러나 사용자의 입력 값이 들어오면 로그인 버튼이 활성화 되어 클릭이 되도록 구현한다.

 

 

 

코드 💻

 

HTML
<div id="container" class="login_container">
    <main class="login_main">
        <article>
            <div class="wrap_box">
                <h1 id="logo">westagram</h1>
                <div class="login_form">
                    <form action="" method="post">
                        <ul>
                            <li>
                                <input id="login_id" type="text" placeholder="전화번호, 사용자 이름 또는 이메일">
                            </li>
                            <li>
                                <input id="login_pw" type="password" placeholder="비밀번호">
                            </li>
                            <li class="login_btn"><button id="login_btn">로그인</button></li>
                        </ul>
                        <div class="or_line"><i>또는</i></div>
                        <a href="#" class="forget_pw_link">비밀번호를 잊으셨나요?</a>
                    </form>
                </div>
            </div>
        </article>
    </main>
</div>

 

 

 

JS
21.12.07
const idInput = document.getElementById('login_id'),
    pwInput = document.getElementById('login_pw');
const loginBtn = document.getElementById('login_btn');


const isActiveLogin = () => {
    let idValue = idInput.value;
    let pwValue = pwInput.value;

    if(
        (idValue && pwValue) && (pwValue.length > 4)
    ) {
        loginBtn.classList.add('login_active');
    }
    else {
        loginBtn.classList.remove('login_active');
    }
}

idInput.addEventListener('keyup', isActiveLogin);
pwInput.addEventListener('keyup', isActiveLogin);

코드를 하나씩 살펴보면 id input, pw input, login button을 제어하기 위해 const 변수에 담았다.

check list에서 언급했듯이 아이디 및 비밀번호 둘 다 값이 들어와야만 로그인 버튼이 활성화 되어야 한다.
그리고 사용자가 갑자기 입력했던 값을 지운다면? 그 때도 함수가 작동되어 버튼을 빠르게 비활성화 해준다.

한번 함수가 실행되고 끝이 아니라 사용자가 event를 발생할 때 마다 함수 내에서 조건문에 따라 해당 기능을 해주어야 한다.
그래서 idInput과 pwInput 둘 다 addEventListener 메소드에서 첫 번째 인자에 *keyup 키워드를 주었다.
두 addEventListener는 check list 내용에 부합하도록 동일한 함수를 실행하므로 함수를 따로 만들어준다.

실행할 함수는 const로 선언한 isActiveLogin이라는 함수를 따로 만들어서 그 안에 기능을 넣었다.
사용자가 입력을 할 때와 입력하지 않을 때를 조건문으로 완성했다.

필자는 활성화&비활성화의 style을 *classList를 통해 class를 추가하고, 제거하였다.
style이 한개라면 직접 js 파일 내에서 style을 주었겠지만 해당 파일의 경우 style 속성이 두개였고 이후 더 추가될 경우가 있을 수도 있으니 편하게 css파일에서 컨트롤할 수 있게 class로 묶어서 관리하기로 했다.

 

 

21.12.10
'use strict';

const idInput = document.getElementById('login_id'),
  pwInput = document.getElementById('login_pw');
const loginBtn = document.getElementById('login_btn');


const isActiveLogin = () => {
  let idValue = idInput.value;
  let pwValue = pwInput.value;

  if(
      (idValue && pwValue) && 
      (pwValue.length >= 5) && 
      (idValue.includes('@') || idValue.length >= 5)
      ) {
      loginBtn.disabled = false;
      loginBtn.style.opacity = 1;
      loginBtn.style.cursor = 'pointer';
  }
  else {
      loginBtn.disabled = true;
      loginBtn.style.opacity = .3;
  }
}

const init = () => {
  idInput.addEventListener('input', isActiveLogin);
  pwInput.addEventListener('input', isActiveLogin);
  idInput.addEventListener('keyup', isActiveLogin);
  pwInput.addEventListener('keyup', isActiveLogin);
}

init();

리팩토링 했다. 변수는 다 그대로이다.

Add ➕

  1. 유효성 검사
    - 아이디에 '@' 문자가 포함 되어 있는지 확인
    - 비밀번호가 5글자 이상인지 확인
    - disabled로 버튼을 활성화 및 비활성화
  2. class를 추가하는 대신 style도 조금 변경해서 backgroundColor의 색을 변경하는 것이 아닌 한번에 opacity로 제어하도록 수정했고 style 코드가 줄었으니 자바스크립트에 직접 DOM에 접근하도록 했다.
  3. init 함수를 만들어서 기본적인 함수 실행을 init 함수 안에 정리했다.
  4. 'input'을 넣은 이유는 직접 키보드로 입력하지 않고 복붙해오는 경우가 있어서 추가했다.

 


 

💡 keyup, keydown, keypress event 정확히 짚고 가기

keyup

누른 키에서 손을 떼면 이벤트 실행

 

keydown

키보드를 눌렀을 때 한번 이벤트 실행
ctrl,alt, shift 등의 키 작동
이전에 누른 값의 정보를 갖고 있다.

 

keypress

키보드를 누르고 있는 동안 계속 이벤트 실행
ctrl,alt, shift 등의 키 작동 안됨
이전에 누른 값의 정보를 갖고 있지 않는다.

 

key event 동작 순서

'a' 키 누른다 -> keydown 이벤트(input에는 'a'텍스트 안나옴) -> 
'a'키 텍스트로 나온다. -> keypress 이벤트 ->
'a' 키에서 손을 뗀다 -> keyup 이벤트

 

내 구현 방식에서 keyup을 넣은 이유는 단순하다.
keydown이나 keypress처럼 ctrl, alt같은 키의 작동이 필요하지 않았고 키보드를 누르고 있는 동안 계속해서 이벤트를 실행할 필요가 없었다.
4글자 이상으로 조건을 걸어준 부분도 어차피 keyup 이벤트로 사용자가 누른 키를 손에서 떼면 이벤트가 발생하기 때문에 굳이 keypress가 필요하지도 않다.

 


 

💡 classList로 class 추가하기

classList

해당하는 클래스가 어떤게 있는지 확인할 수 있다.
ex) document.getElementById("wrap").classList = "one", two"

 

classList.add

element.classList.add('className');

class를 추가한다.
add(class1, class2 ...) 인자를 여러 개 받아서 한번에 여러 개의 class를 추가할 수도 있다.
그 외에 기존에 생성해둔 class도 그대로 존재한다.

 

classList.remove

element.classList.remove('className');

class를 제거한다.
remove(class1, class2 ...) 인자를 여러 개 받아서 한번에 여러 개의 class를 제거할 수도 있다.
그 외에 기존에 생성해둔 class는 그대로 존재한다.

 

 

+ 번외 + className으로 class 추가하기

className

class의 이름을 문자열로 리턴한다. (classList와 동일)

 

className class 설정 및 추가

element.className = 'className';

class를 인자 내용으로 변경한다.
classList와 다른 것이 이 부분인데 className은 기존에 있던 class들을 모두 초기화하고 추가한 인자 내용만 둔다.

 

className class 추가

element.className += ' className';

스페이스바도 추가해서 입력해야 한다. (class="default className")

 

 

이렇듯이 className으로도 class를 추가할 수 있지만 기존에 있던 class들이 초기화 될 수 있어서 classList를 사용했다.
오로지 내가 만든 class를 쉽게 제어할 수 있다는 게 장점이다.
그리고 추가로 else 문에서 class를 직접 삭제해주어야 하는데 이때 사용되는게 classList.remove라는 메소드가 있으므로 그냥 classList를 세트 개념으로(?) 사용하는 것이 더 좋을 것 같다는 판단이 들었다.

 

 

 

 

 

 

 

728x90