오늘은 계산기 구현하기를 진행했다.
기능이 크게 없어서 간단하다고 생각했으나, 생각보다 로직을 짜기 어려웠다.
우선 계산기.html이다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaScript Calculator</title>
<link href="https://fonts.googleapis.com/css?family=Righteous" rel="stylesheet">
<link rel="stylesheet" href="./yourStyle.css">
</head>
<body>
<div class="container">
<div class="calculator">
<div class="calculator__display--bare">
<span class="calculator__operend--left">0</span>
<span class="calculator__operator">+</span>
<span class="calculator__operend--right">0</span>
<span class="calculator__equal">=</span>
<span class="calculator__result">0</span>
</div>
<div class="calculator__display--for-advanced">0</div>
<div class="calculator__buttons">
<div class="clear__and__enter">
<button class="clear">AC</button>
<button class="calculate">Enter</button>
</div>
<div class="button__row">
<button class="number">7</button>
<button class="number">8</button>
<button class="number">9</button>
<button class="operator">+</button>
</div>
<div class="button__row">
<button class="number">4</button>
<button class="number">5</button>
<button class="number">6</button>
<button class="operator">-</button>
</div>
<div class="button__row">
<button class="number">1</button>
<button class="number">2</button>
<button class="number">3</button>
<button class="operator">*</button>
</div>
<div class="button__row">
<button class="number double">0</button>
<button class="decimal">.</button>
<button class="operator">/</button>
</div>
</div>
</div>
<img class="logo" src="data/codestates-logo.png">
</div>
<script src='./script.js'></script>
</body>
</html>
그리고 계산기.css이다.
/* TODO : CSS파일을 편집하여 원하는 스타일의 계산기를 만들어보세요 :) */
/* global */
* {
margin: 0;
padding: 0;
border: 0px;
box-sizing: border-box;
font-family: "Righteous", cursive;
color: #000;
}
body {
background-image: url("./data/codestates-motif.png");
}
/*
Calculator styles
*/
.container {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.calculator {
background-color: #4000c7;
width: 350px;
height: 500px;
border-radius: 10px;
padding: 30px 20px;
}
.calculator__display--bare {
display: none;
background-color: #ffffff;
text-align: center;
vertical-align: middle;
height: 100px;
width: 100%;
border-radius: 10px;
font-size: 20px;
padding: 25px 15px;
overflow: hidden;
overflow-wrap: break-word;
}
.calculator__display--bare > span {
display: inline-block;
text-align: center;
background-color: #f3f0fc;
margin: 5px;
width: 40px;
height: 45px;
border-radius: 10px;
font-size: 20px;
padding: 10px 5px;
}
.calculator__display--for-advanced {
/* 이 줄을 모두 지우면 advanced 테스트를 하실 수 있습니다.*/
background-color: #ffffff;
height: 100px;
width: 100%;
border-radius: 10px;
font-size: 20px;
text-align: right;
vertical-align: middle;
padding: 25px 15px;
overflow: hidden;
overflow-wrap: break-word;
}
.calculator__buttons {
background-color: #ffffff;
width: 100%;
height: 330px;
margin-top: 10px;
padding: 10px;
border-radius: 10px;
}
.clear__and__enter {
height: 50px;
margin: 10px;
background-color: #f3f0fc;
}
.clear__and__enter > button {
border-radius: 10px;
width: 50px;
height: 40px;
margin: 0px 5px;
background-color: #00da75;
cursor: pointer;
outline: none;
}
.button__row {
height: 50px;
margin: 10px;
background-color: #f3f0fc;
}
.button__row > button {
width: 50px;
height: 40px;
border-radius: 10px;
cursor: pointer;
outline: none;
background-color: #ebebeb;
}
.button__row > .operator {
color: #ffffff;
background-color: #313132;
}
.button__row > .double {
width: 115px;
}
.button__row > .isPressed {
background-color: #00da75;
}
.logo {
position: fixed;
width: 204px;
padding: 30px;
bottom: 0px;
right: 0px;
}
마지막으로 계산기.js이다.
const calculator = document.querySelector(".calculator"); // calculator 엘리먼트와, 그 자식 엘리먼트의 정보를 모두 담고 있습니다.
const buttons = calculator.querySelector(".calculator__buttons"); // calculator__keys 엘리먼트와, 그 자식 엘리먼트의 정보를 모두 담고 있습니다.
const firstOperend = document.querySelector(".calculator__operend--left"); // calculator__operend--left 엘리먼트와, 그 자식 엘리먼트의 정보를 모두 담고 있습니다.
const operator = document.querySelector(".calculator__operator"); // calculator__operator 엘리먼트와, 그 자식 엘리먼트의 정보를 모두 담고 있습니다.
const secondOperend = document.querySelector(".calculator__operend--right"); // calculator__operend--right 엘리먼트와, 그 자식 엘리먼트의 정보를 모두 담고 있습니다.
const calculatedResult = document.querySelector(".calculator__result"); // calculator__result 엘리먼트와, 그 자식 엘리먼트의 정보를 모두 담고 있습니다.
function calculate(a, operator, b) {
console.log(a, operator, b);
let result = 0;
// TODO : n1과 n2를 operator에 따라 계산하는 함수를 만드세요.
// ex) 입력값이 n1 : '1', operator : '+', n2 : '2' 인 경우, 3이 리턴됩니다.
if (operator === "+") {
result = Number(a) + Number(b);
} else if (operator === "-") {
result = Number(a) - Number(b);
} else if (operator === "/") {
result = Number(a) / Number(b);
} else if (operator === "*") {
result = Number(a) * Number(b);
}
console.log(result);
return String(result);
}
buttons.addEventListener("click", function (event) {
// 버튼을 눌렀을 때 작동하는 함수입니다.
const target = event.target; // 클릭된 HTML 엘리먼트의 정보가 저장되어 있습니다.
const action = target.classList[0]; // 클릭된 HTML 엘리먼트에 클레스 정보를 가져옵니다.
const buttonContent = target.textContent; // 클릭된 HTML 엘리먼트의 텍스트 정보를 가져옵니다.
// ! 위 코드(Line 19 - 21)는 수정하지 마세요.
if (target.matches("button")) {
// TODO : 계산기가 작동할 수 있도록 아래 코드를 수정하세요. 작성되어 있는 조건문과 console.log를 활용하시면 쉽게 문제를 풀 수 있습니다.
// 클릭된 HTML 엘리먼트가 button이면
if (action === "number") {
// 그리고 버튼의 클레스가 number이면
// 아래 코드가 작동됩니다.
console.log("숫자 " + buttonContent + " 버튼");
if (firstOperend.textContent === "0") {
firstOperend.textContent = buttonContent;
} else if (firstOperend.textContent !== 0) {
secondOperend.textContent = buttonContent;
}
}
if (action === "operator") {
console.log("연산자 " + buttonContent + " 버튼");
operator.textContent = buttonContent;
}
if (action === "decimal") {
console.log("소수점 버튼");
}
if (action === "clear") {
console.log("초기화 버튼");
firstOperend.textContent = 0;
secondOperend.textContent = 0;
calculatedResult.textContent = 0;
}
if (action === "calculate") {
console.log("계산 버튼");
calculatedResult.textContent = calculate(
firstOperend.textContent,
operator.textContent,
secondOperend.textContent
);
}
}
});
// ! Advanced Challenge test와 Nightmare test를 위해서는 아래 주석을 해제하세요.
const display = document.querySelector(".calculator__display--for-advanced"); // calculator__display 엘리먼트와, 그 자식 엘리먼트의 정보를 모두 담고 있습니다.
let firstNum, operatorForAdvanced, previousKey, previousNum;
buttons.addEventListener("click", function (event) {
// 버튼을 눌렀을 때 작동하는 함수입니다.
const target = event.target; // 클릭된 HTML 엘리먼트의 정보가 저장되어 있습니다.
const action = target.classList[0]; // 클릭된 HTML 엘리먼트에 클레스 정보를 가져옵니다.
const buttonContent = target.textContent; // 클릭된 HTML 엘리먼트의 텍스트 정보를 가져옵니다.
// ! 위 코드는 수정하지 마세요.
// ! 여기서부터 Advanced Challenge & Nightmare 과제룰 풀어주세요.
if (target.matches("button")) {
if (action === "number") {
//화면이 0이고 연산자가 없을때, 클릭 시 화면 출력
if (display.textContent === "0" && operatorForAdvanced === undefined) {
display.textContent = buttonContent;
firstNum = display.textContent;
} else if (
display.textContent !== "0" &&
operatorForAdvanced === undefined
) {
display.textContent += buttonContent;
firstNum = display.textContent;
}
//화면이 0이고 연산자가 있을때, 클릭시 새로운 값으로 화면 출력하고 previousNum에 저장
else if (previousKey === "operator" && display.textContent !== "0") {
display.textContent = buttonContent;
previousNum = display.textContent;
} else {
display.textContent += buttonContent;
previousNum = display.textContent;
}
previousKey = "number";
}
if (action === "operator") {
// previousNum이 존재할 때
if (previousNum) {
firstNum = calculate(firstNum, operatorForAdvanced, previousNum);
operatorForAdvanced = buttonContent;
display.textContent = firstNum;
previousNum = undefined;
}
// firstNum이 0이 아니고, previousKey가 number
else if (firstNum !== "0" || previousKey === "number")
operatorForAdvanced = buttonContent;
previousKey = "operator";
}
if (action === "decimal") {
if (!display.textContent.includes(".") && previousKey !== "operator") {
display.textContent = display.textContent + ".";
} else if (previousKey === "operator") {
display.textContent = "0.";
previousNum = "0.";
}
previousKey = "decimal";
}
if (action === "clear") {
firstNum = undefined;
previousNum = undefined;
display.textContent = 0;
operatorForAdvanced = undefined;
previousKey = "clear";
}
if (action === "calculate") {
if (previousNum === undefined)
display.textContent = calculate(
display.textContent,
operatorForAdvanced,
display.textContent
);
else if (previousKey === "calculate")
display.textContent = calculate(
display.textContent,
operatorForAdvanced,
previousNum
);
else
display.textContent = calculate(
firstNum,
operatorForAdvanced,
previousNum
);
previousKey = "calculate";
}
}
});
기본적으로 첫번째 숫자, 연산자, 두번째 숫자가 차례대로 입력되면 간단하게 구현할 수 있다. 하지만 첫번째 숫자와 연산자만 입력되는 경우나 계속 결과값(=)을 입력하는 경우 다르게 알고리즘을 짜야된다는게 어려워서 오래걸렸다.