사용자가 입력 중일 때 "사용자가 입력 중입니다."와 같은 특정 메시지를 출력하도록 하고자 한다.
<form id="messaging-form" action="">
<input type="text" id="my-message" placeholder="enter message" autocomplete="off" onkeyup="checkTyping()">
<button onclick="send()">Send</button>
<span class="notification"></span>
</form>
notification이 메시지를 출력할 공간이다. 주목할 점은 input 태그에 keyup 이벤트 발생 시 해당 이벤트 핸들러를 checkTyping 사용자 정의 함수로 지정했다.
const checkTyping = () => {
const messageInputForm = document.getElementById('messaging-form');
const input = document.getElementById('my-message').value;
messageInputForm.addEventListener('keyup', (event) => {
if (input) {
socket.emit('typing');
} else {
socket.emit('stop typing');
}
});
}
keyup 이벤트가 발생했을 때 input 폼에 데이터가 입력되어 있다면, typing 이벤트를, 아니라면 stop typing 이벤트를 서버로 전송한다.
const users = {};
const typers = {};
... 중략 ...
socket.on('typing', () => {
typers[socket.id] = true;
socket.broadcast.emit('typing', {
nickname: users[socket.id],
numOfTyper: Object.keys(typers).length
});
});
socket.on('stop typing', () => {
delete typers[socket.id];
socket.broadcast.emit('stop typing', Object.keys(typers).length);
});
사용자가 입력 중인 상황(typing 이벤트)에서는 typers 객체에 해당 사용자를 추가하고, 사용자의 닉네임과 현재 입력 중인 사용자의 수를 송신자를 제외한 클라이언트에게 전송한다.
반대로 사용자가 입력을 종료하면(stop typing 이벤트) typers 객체에서 사용자의 정보를 삭제하고, 현재 입력 중인 사용자의 수를 송신자를 제외한 클라이언트에게 전송한다.
사용자가 입력을 종료해도 다른 사람은 아직 입력 중일 수 있기 때문에 반드시 typer의 수를 전송해야 한다.
socket.on('typing', (data) => {
const notification = document.querySelector('.notification');
if (data.numOfTyper - 1) {
notification.innerHTML = `${data.numOfTypers - 1} besides ${data.nickname} are typing.`;
} else {
notification.innerHTML = `${data.nickname} is typing.`
}
});
socket.on('stop typing', (numOfTypers) => {
const notification = document.querySelector('.notification');
if (!numOfTypers) {
notification.innerHTML = '';
}
});
numOfTyper가 0명이라면 빈 문자열을, 1명이라면 "user is typing"을, 2명 이상이라면 "n besideds user are typing"의 형식으로 문자열을 출력할 수 있도록 한다.

다음과 같이 사용자가 입력 중일 때 화면에 메시지가 출력되는 것을 볼 수 있다.