앞에서 설명했던 여러 매서드들을 제외하고, 나머지 부분들은 if문으로 구현하였다. 제로초님의 강의에서 if문을 너무 깊게 내려가지 않게 사용하라고 하였는데 자세히 순서도를 그리지 않고 구현하다 보니 역시나 복잡해져 버렸다.
원래는 나누어서 설명을 하는게 맞겠으나, 전체 코드를 다 알아야 왜 이렇게 짰는지 설명이 될 듯 하다.
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>텐키리스 계산기</title>
<style>
body{font-size: 0px;}
*{box-sizing: border-box; margin: 0 0 0 0;}
span{display:inline-block;width: 30px; height: 30px; background-color: cornsilk;
text-align: center; font-size: 20px; margin:0 1px 0 0;}
#cal{width: 30px;height: 30px; text-align: center;}
#calOutput{width: 92px;height: 30px; margin-left: 1px;}
.keyIn{background-color: burlywood;}
.row{margin:1px 0 1px 0}
.explainRow{font-size: 10px;}
</style>
</head>
<body>
<div class="row">
<input readonly id="cal" />
<input readonly id="calOutput" />
</div>
<div class="row">
<span id="u">1</span>
<span id="i">2</span>
<span id="o">3</span>
<span id="p">+</span>
</div>
<div class="row">
<span id="j">4</span>
<span id="k">5</span>
<span id="l">6</span>
<span id="[">-</span>
</div>
<div class="row">
<span id="m">7</span>
<span id=",">8</span>
<span id=".">9</span>
<span id=";">*</span>
</div>
<div class="row">
<span id="/">0</span>
<span id="n">.</span>
<span id="'">/</span>
<span id="]">=</span>
</div>
</body>
<script>
//연산자, 계산값을 변수로 할당
//ammd = add multiply minus divide 줄임말
let firstNum =''
let secNum = ''
let result =''
let ammd = ''
const $cal = document.querySelector('#cal')
const $calOutput = document.querySelector('#calOutput')
//연산자는 따로 표시되도록 변수 할당
const howtoCal = ["p","[",";","'"];
//키 입력시의 효과 함수 지정(value 창에 뜨게 하기, 값 변수에 저장하기)
// function removeClass(key) {
// document.getElementById(key.key).classList.remove('keyIn')
// }
const thisKeydown = (e) =>{
const key = document.getElementById(e.key);
if(key && !(firstNum === '' && howtoCal.includes(e.key)))
{key.classList.add("keyIn")}
//첫 숫자가 없이 부호만 누르면
//애초에 keydown 이벤트인 classList.add 가 일어나지 않게 하기
if(firstNum === '' && howtoCal.includes(e.key)){
$cal.value = ''
ammd = ''
// removeClass(e)
//removeClass 함수가 안되는 이유? =>누를때의 이벤트이기 때문(뗄 때가 아니라)
alert("숫자를 먼저 입력해 주세요")
}else{
//나머지를 else로 분리해야 값이 초기화가 안되는 에러가 안생김
if(howtoCal.includes(e.key)){
$cal.value = document.querySelector('#'+'\\'+e.key).textContent
ammd = document.querySelector('#'+'\\'+e.key).textContent
$calOutput.value = ''
}else if(e.key !== ']'){
$calOutput.value +=document.querySelector('#'+'\\'+e.key).textContent
if(!ammd) {
firstNum = $calOutput.value
}if(firstNum && ammd){
secNum = $calOutput.value
}
}
//선택된 연산자에 따른 결과값 계산방법
if(e.key === ']' && secNum){
$cal.value = document.querySelector('#'+'\\'+e.key).textContent
if(ammd === "+"){
result = Number(firstNum) + Number(secNum)
}else if(ammd === "-"){
result = Number(firstNum) - Number(secNum)
}else if(ammd === "/"){
result = Number(firstNum)/Number(secNum)
}else if(ammd === "*"){
result = Number(firstNum)*Number(secNum)}
$calOutput.value = result
}
}
}
document.addEventListener('keydown', thisKeydown)
document.addEventListener("keyup", (e)=>{
const key = document.getElementById(e.key);
if(key) {key.classList.remove("keyIn")}
});
</script>
</html>
연산자가 여러가지인데 if문에서 일일이 다 대입해주기에는 불편하고 복잡하다.
이때 includes를 사용해 주면 한번에 비교가 가능하다.
첫 숫자를 입력하기 전에 연산자를 누르면 alert가 뜨게 하였는데, 문제는
처음 keydown 에서 함수에 classList.add()가 실행이 되어버리므로 css가 그대로 남게 되는 문제가 발생한다.
그래서 keydown에 remove함수도 같이 써서 시도를 해보았으나, 적용이 되지 않았다.
생각해 보니 keydown은 누를 때 발생하는 것이므로, 애초에 누르기 전에는 class 값이 아예 없기 때문에 제거할 수가 없다. 실제로 undefind를 제거할 수 없다고 나온다.
이 문제를 keyup에서 해결하기도 어려워서, 애초에 첫 숫자 없이 연산자를 누르면 애초에 class 값이 추가되지 못하도록 if문을 통해 구별해 주었다.
if문을 쓸 때 자주 실수하는 부분이다. 두 값이 같냐 다르냐를 비교할 때는 ===을 사용해 주어야 한다. 선택된 연산자에 따른 결과값 계산방법 부분에서 이 부분을 실수해 값이 제대로 나오지 않았다.
이 세가지를 언제 적용해야 하는지를 헷갈리는 경우가 많다. 그런데 이 프로젝트를 하며 보니 포함관계를 고려하면 쉽게 사용할 수 있을 것이라고 생각이 들었다.
if를 사용한 특정 상황을 제외하고 다른 모든 부분에 적용이 되어야 한다면 else를 쓰고, 그렇지 않고 또 다른 특정 상황을 고려해야 한다면 else if를 사용하여야 한다.
혹시나 else if를 사용하였는데 예상치 못한 결과(적용이 되거나, 되지 않거나)가 나타나게 된다면, 앞의 if문에서의 조건문 외에는 적용이 되지 않도록 else로 분리해 주면 해결될 수 있을 것이다.
두 번째 입력값을 받을 때, 첫 입력값이 초기화가 안되어서 계속 숫자가 이어지는 오류가 생겼는데
if(firstNum === '' && howtoCal.includes(e.key))
이 부분 뒤를 모두 else
로 묶어지니 그러한 오류가 사라졌다.
본인이 작성한 조건문의 적용 범위를 고려하여 if, else if, else를 사용한다면 오류를 없앨 수 있다.