this.#keyboardEl.addEventListener("mousedown", this.#onMouseDown);
document.addEventListener("mouseup", this.#onMouseUp);
마우스를 누를 때(mousedown)은 키보드 요소에서 eventListener를 걸지만, 마우스를 뗄 때는(mouseup) 눌렀던 그 자리에서만 떼는 것이 아닌 키보드 밖으로 나가서 어디에서든 뗄 수 있기 때문에 document에 eventListener를 건다.
주어진 선택자와 일치하는 요소를 찾을 때까지 자기 자신을 포함한 위쪽(부모 방향, root까지)으로 문서 트리를 순회하여 찾아낸다.
가장 가까운 조상 element, 또는 자기 자신을 반환하거나 없으면 null.
#onMouseDown(e) {
e.target.closest("div.key")?.classList.add("active");
}
#onMouseUp() {
this.#keyboardEl.querySelector(".active")?.classList.remove("active");
}
이번에도 optional chaining을 사용하여 코드를 간결하게 작성했다.
mousedown
target의 가장 가까운 div.key를 찾아 배경색이 어두워지는 .active
를 추가한다.
mouseup
마우스를 떼는 순간 .active
를 가지고 있는 요소에게서 .active
class 이름을 제거한다.
마우스가 떼지는 순간 input이 입력되게 하기 위해서 mouseup
이벤트 리스너에 input 작업을 한다.
const keyEl = e.target.closest("div.key");
const isActive = !!keyEl?.classList.contains("active");
const val = keyEl?.dataset.val;
keyEl
div.key
가진 요소
isActive
mouseup 될 때 active한 키보드 요소
val
키보드 요소에서 data-val이 존재하는지 판별하기 위한 변수 (없는 값도 있어서)
* !!변수
에서 느낌표 두 개 처리를 해주는 것은 undefined
나 null
값이 확실하게 false
로 처리하기 위함이다. (확실한 type casting)
if (isActive && !!val && val !== "Space" && val !== "Backspace") {
this.#inputEl.value += val;
}
if (isActive && val === "Space") {
this.#inputEl.value += " ";
}
if (isActive && val === "Backspace") {
this.#inputEl.value = this.#inputEl.value.slice(0, -1);
}
키보드가 active한 상태이고 값이 있어야지 동작하게 한다.
input 요소에 지금 클릭된 요소의 data-val을 추가한다. 원래 있던 값에 이어서 보여주기 위해 +=
Space
공백 한 칸 추가
Backspace
배열에서 맨 뒤의 값 삭제
강의에서는 동시에 입력되지 못하게 하는 처리를 해주었는데, 키보드 입력은 input 커서에서 벗어나면 입력되지 않고 마우스 입력을 하면 커서에서 벗어나져서 해당 처리를 해주지 않았다.