본문 바로가기
CodeIt_Sprint/JavaScript_중급

(11)JavaScript중급_4_이벤트 활용_KeyBoard_event

by 코잼민 2024. 11. 15.

#알아야 할 개념 :

● 개념_1 : 키보드 기본 이벤트 type, 프로퍼티

○ 정의 :Mouse 키 눌렀을 때, 떼었을 때, 관한 기본적인 event.type event.프로퍼티가 존재한다.

- event.type

  • 키보드를 누른 순간 (2가지) : 'keydown' || 'keypress'
  • 키보드를 뗀 순간 : 'keyup'

- event.프로퍼티

  • 키보드 입력된 값 : key
  • 키보드 입력된 물리적 위치 : code

Ex1_대문자 A, 소문자 a 눌렀을 시

  • event.key : 'A' , 'a'
  • event.code : Key A

Ex1_왼쪽 Shift , 오른쪽 Shift 누를 시

  • event.key : 'Shift'
  • event.code : ShiftLeft || ShiftRight

● 개념_2 : 키보드 이벤트 type 인 'keypress' 에 대하여,

keydown vs keypress

상황1_ 연속적으로 특정 키를 연타할 시,

  • keydown : 발생 o
  • keypress : 발생 x

상황2_ 한글입력시 ,

  • keydown : 발생 o
  • keypress : 발생 x

상황1_ space vs shift esc tab등의 기능적인 key 누를시 ,

space : //입력된 value값이 변하는 기능 key

  • keydown : 발생 o
  • keypress : 발생 o

space : //입력된 value값이 변하지않는 기능적인 key

  • keydown : 발생 o
  • keypress : 발생 x

 

※연습문제  :

 문제 조건 :

실습 설명

코드잇 우등생 규리는 최근에 공부한 HTML/CSS, 그리고 자바스크립트를 활용해서 웹으로 간단한 채팅 앱을 만들었습니다. textarea 태그에 메시지를 입력하고 오른편에 있는 send 버튼을 클릭하면 화면에 입력한 메시지가 나오죠.

규리가 만든 것처럼 text 타입의 input 태그나 textarea 태그를 자바스크립트로 선택한 다음에 해당 요소 노드의 value 프로퍼티를 활용하면 해당 태그에 입력된 값을 다룰 수 있습니다.

그런데 한 가지 아쉬운 점은 키보드로 메시지를 입력하고 나면, 마우스를 움직여서 send 버튼을 눌러야 한다는 겁니다.

아쉬운 규리를 위해서 textarea 태그에서 enter 키를 누르면 sendMyText 함수가 호출되는 코드를 추가해 주세요.

코드를 완성했을 때 아래 조건들이 지켜져야 합니다.

  • ①.  enter 키로 메시지를 전송하고 나면 textarea 태그는 초기화가 제대로 되어야 합니다.
  • ②.  shift+enter 일때는 줄바꿈이 일어나야 합니다.
  • ③.  keypress 타입으로 이벤트 핸들러가 등록되어야 합니다.

참고 사항

하나의 버튼에 하나의 값이 입력되는 영어와는 다르게, 한국어의 자음과 모음의 결합처럼 여러 버튼을 눌러서 하나의 입력 값을 만들 수 있는 언어들은 입력할 때 자세히 살펴보면, 화면에 입력중인 문자 바로 아래에 작은 밑줄이 나타나는 경우를 볼 수 있습니다. 만약 keyup, keydown 타입으로 이벤트 핸들러를 등록하고, 그 밑줄이 보이는 상황에서 enter나 esc, 혹은 방향키와 같은 키보드 버튼을 누를 경우 해당 버튼에 대한 이벤트가 2번 중복해서 반응하는 이슈가 있습니다. 왜냐하면 글자가 조합 중인지, 조합이 완료된 것인지 쉽게 파악하기 어렵기 때문인데요. 그래서 이렇게 특별한 상황에 따라서는 keypress가 필요할 수도 있다는 점. 참고해 두시면 좋을 것 같습니다!

● Default 코드 :

- html

<!DOCTYPE html>
<html lang="ko">

<head>
  <meta charset="UTF-8">
  <title>Codeit Messenger</title>
  <link rel="stylesheet" href="6.css">
</head>

<body>
  <img class="background" src="imgs/background.png">
  <div class="container">
    <div class="header">
      <button class="back-btn">
        <img src="imgs/left-arrow.png" width="30" height="30">
      </button>
      <img class="profile-pic" src="imgs/profile.png" width="40" height="40">
      <div class="info-block">
        <p class="username">썸남</p>
        <p class="status">1시간 전에 활동</p>
      </div>
      <div class="call-box">
        <button>
          <img src="imgs/phone-call.png" width="20" height="20">
        </button>
        <button>
          <img src="imgs/video-call.png" width="20" height="20">
        </button>
      </div>
    </div>

    <div id="chat-box">
      <div class=" bubble friend-bubble">
        자니?
      </div>
      <div class=" bubble friend-bubble">
        자나보네..ㅎ
      </div>
      <div class=" bubble friend-bubble">
        잘 자 :)
      </div>
    </div>

    <div class="footer">
      <textarea id="input" placeholder="메시지를 입력하세요..." autofocus="true"></textarea>
      <button id="send">
        <img src="imgs/send.png" width="24" height="24">
      </button>
    </div>
  </div>
  <script></script>
</body>

</html>

- Css

* {
  box-sizing: border-box;
}

button {
	border: none;
	background-color: transparent;
	cursor: pointer;
}

body {
	height: 100vh;
	display: flex;
	justify-content: center;
	align-items: center;
}

.background {
	width: 100%;
	max-width: 1200px;
	position: absolute;
	top: 0;
	left: 0;
}

.container {
	position: relative;
	width: 340px;
	height: 540px;
	border-radius: 15px;
	box-shadow: 1px 1px 10px #333333;
	background-color: #ffffff;
	overflow: hidden;
}

.header {
	display: flex;
	height: 60px;
	padding: 12px 5px 8px;
	align-items: center;
	box-shadow: 0 0 4px #999999;
}

.info-block {
	margin-left: 12px;
	margin-right: 95px;
}

.username {
	margin: 0 0 3px;
	font-size: 16px;
}

.status {
	margin: 0;
	font-size: 12px;
	color: #999999;
}

.call-box {
	display: flex;
	width: 60px;
	justify-content: space-between;
}

#chat-box {
	height: 400px;
	padding: 12px 10px;
	overflow: scroll;
}

.bubble {
	margin: 5px 0;
	display: inline-block;
	max-width: 300px;
	font-size: 14px;
	position: relative;
}

.friend-bubble {
	background-color: #f3f0f5;
	border-radius: 14px 14px 14px 0;
	padding: 7px 15px 7px 15px;
	float: left;
	clear: both;
	color: #8f00fe;
}

.my-bubble {
	background-color: #8f00fe;
	border-radius: 14px 14px 14px 0;
	padding: 7px 15px 7px 15px;
	float: right;
	clear: both;
	color: #ffffff;
}

.footer {
	display: flex;
	justify-content: space-between;
	align-items: flex-end;
	width: 100%;
	height: 80px;
	padding: 10px;
	position: absolute;
	bottom: 0;
}

#input {
	width: 90%;
	height: 100%;
	padding: 10px;
	background-color: #e8e8e8;
	border: none;
	border-radius: 10px;
	resize: none;
}

● 풀이과정 :

1_ 상대방과 나의 Message Box 확인하기

#chat-box {
	height: 400px;
	padding: 12px 10px;
	overflow: scroll;
}

.bubble {
	margin: 5px 0;
	display: inline-block;
	max-width: 300px;
	font-size: 14px;
	position: relative;
}

.friend-bubble {
	background-color: #f3f0f5;
	border-radius: 14px 14px 14px 0;
	padding: 7px 15px 7px 15px;
	float: left;
	clear: both;
	color: #8f00fe;
}

.my-bubble {
	background-color: #8f00fe;
	border-radius: 14px 14px 14px 0;
	padding: 7px 15px 7px 15px;
	float: right;
	clear: both;
	color: #ffffff;
}

- 상대방(썸남 스토커남 한남)의 메시지 박스의 CSS style 시트: chat-box bubble friend-bubble 에 해당

- 나의 메시지 박스의 CSS style 시트: chat-box bubble my-bubble 에 해당

2_ JavaScript로 나의 메시지 생성 핸들러 코드 작성 //sendMyText()

<div id="chat-box">
      <div class=" bubble friend-bubble">
        자니?
      </div>
      <div class=" bubble friend-bubble">
        자나보네..ㅎ
      </div>
      <div class=" bubble friend-bubble">
        잘 자 :)
      </div>
    </div>

위에는 채팅에 해당하는 div부분이고,

①. 그 해당 부분의 가장 부모 Box노드를 변수에 저장

const chatBox = document.querySelector('#chat-box');

②. 밑에 입력창에서 적힌 값을 갖고온다.

const messageText = 입력태그.value;

③. 입력값이 존재할 경우, => <div> 노드 생성 => class "bubble" + class " my-bubble " 추가 => 생성된 노드의 textContent에 newMessage 삽입

const messageBox = createElement('DIV');

messageBox.classList.add('bubble', ' my-bubble ');

message.textContent = messageText;

④ . ③에서 만들어진 노드를 부모Box인 chatBox 맨 마지막 자식에 삽입

 chatBox.append(messageBox);

⑤. message가 보내진 후, input안에 있는 값 비어있게 하기

input.value = "";

3★_ sendMyText핸들러를 button#send에 적용하기

const send = document.Selector('#send');

send.addEventListener('click',sendMyText); //send 버튼 누를 시 , 메시지 전송 됨

4_ input창에서 텍스트입력 시, 메시지 발송되도록 하기

①.  엔터 입력시 => 발송이 되는 메소드 코드 작성

const input = querySelector('#input');

function inputMessageSend(event)
{

if(event.key=='Enter' && !event.shiftKey) //엔터키를 누를시, 또는 shift키가 눌러지지 않는 상태일 시{

event.pretendDefault();//줄바꿈 방지

sendMyText(); //메시지가 보내지도록 한다.

}
}

②. input 태그에 ①에 작성한 핸들러 적용

input.addEventListener('keypress' , inputMessageSend ) //'keydown' X

● 정답 :

    const chatBox = document.querySelector('#chat-box');
    const input = document.querySelector('#input');
    const sendBtn = document.querySelector('#send');

    function sendMyText()
    {
      if(input.value)
    {
      let messageText = input.value;
      const messageBox = createElement('DIV');
      messageBox.classList.add('bubble', 'my-bubble');
      messageBox.textContent = messageText;

      chatBox.append(messageBox);

      //메시지 보낸 후, 텍스트 창의 텍스트 비어있게 하기
      input.value = "";
    }
    }

    sendBtn.addEventListener('click',sendMyText); //send 버튼을 왼쪽 마우스 클릭 시, 메시지 발송 구현

    //입력 창에 대한 세부 설정 => enter 입력시 , 줄바꿈 금지 + 메시지 전송 기능

    input.addEventListener('keydown',function(event){

      if(event.key==='Enter'&&!event.shiftKey)
    {
      sendMyText();
      event.preventDefault();
    }

    });