본문 바로가기

카테고리 없음

[html css js] 간단한 계산기 만들기

 

 

html css javascript를 이용해서 연습용으로 간단한 계산기를 구현해 보았다

 

코드

HTML
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>자바스크립트 계산기</title>
</head>

<body>
  <div class="container">
    <div class="calculator">
      <input type="text" id="display-result" readonly>
      <input type="text" id="display" placeholder="0">
      <div class="number-button">
        <button type="button" onclick="clearEntryDisplay()">CE</button>
        <button type="button" onclick="clearDisplay()">C</button>
        <button type="button" class="orange" onclick="backspace()"><=</button>
      </div>
      <div class="number-button">
        <button type="button" onclick="appendNumber('7')">7</button>
        <button type="button" onclick="appendNumber('8')">8</button>
        <button type="button" onclick="appendNumber('9')">9</button>
        <button type="button" class="orange" onclick="appendNumber('*')">X</button>
      </div>
      <div class="number-button">
        <button type="button" onclick="appendNumber('4')">4</button>
        <button type="button" onclick="appendNumber('5')">5</button>
        <button type="button" onclick="appendNumber('6')">6</button>
        <button type="button" class="orange" onclick="appendNumber('-')">-</button>
      </div>
      <div class="number-button">
        <button type="button" onclick="appendNumber('1')">1</button>
        <button type="button" onclick="appendNumber('2')">2</button>
        <button type="button" onclick="appendNumber('3')">3</button>
        <button type="button" class="orange" onclick="appendNumber('+')">+</button>
      </div>
      <div class="number-button">
        <button type="button" onclick="appendNumber('0')">0</button>
        <button type="button" onclick="appendNumber('.')">.</button>
        <button type="button" onclick="appendNumber('/')">÷</button>
        <button type="button" class="orange" onclick="calculate()">=</button>
      </div>

    </div>
  </div>

</body>

</html>

처음에 버튼을 <input type = "button">과 <button type ="button"> 중 무엇을 해야 할까 고민을 했었는데

input과 button의 차이점은 button은 스스로 닫지 않는 태그이고 input은 스스로 닫는 태그다.

따라서 <button> 태그는 하위 태그들을 추가할 수 있고 <input> 태그는 추가할 수 없다는 점이고 

이는 디자인적 측면에서 자유도가 더 높아지는 점과 이미지 같은 것을 넣을 때

<button>은 <img> 태그를 삽입 하면 되지만 <input>타입은 css로 삽입 해야 해서

검색엔진 최적화에 <input>보다 <button>이 더 도움이 된다는 것을 배웠다.

 

<button>은 submit, reset, button 3개의 타입이 있는데 

submit은 form을 제출하는 이벤트,

reset은 form에 작성된 내용을 초기화,

button은 클릭 이벤트와 연결시켜서 자바스크립트를 활용하는데 많이 사용된다.

 

CSS
* {
  box-sizing: border-box;
  
}

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

.calculator {
  width: 350px;
  height: 480px;
  background-color: black;   
  border-radius: 8px;  
  box-shadow: 5px 7px 20px rgba(0, 0, 0, 0.3);  
  border: 3px solid darkgray;    
}

#display-result {
  width: 300px;
  height: 50px;
  text-align: right;
  margin: 20px 20px 0px 20px;
  font-size: 48px;
}

#display {
  width: 300px;
  height: 50px;
  text-align: right;
  margin: 20px ;
  font-size: 48px;
}

button[type="button"] {
  width: 75px;    
  height: 50px;
  border-radius: 16px;  
  font-size: 24px;
}

.number-button {
  display: flex;
  justify-content: flex-end;
  margin-right: 20px;  
  padding: 5px;
}

.number-button .orange {
  background-color: rgb(255, 207, 119);
}

계산기는 스마트폰 계산기 이미지를 참고하고 윈도우 계산기처럼 현재 계산식과 결과값을 따로 나오게 했다.

 

let lastResult = '';

function appendNumber(value) {    // 버튼을 누르면 입력창에 value 추가
    document.getElementById('display').value += value;
}

function clearDisplay() {  // 입력창 결과창 모두 초기화
    document.getElementById('display').value = "";    
    document.getElementById('display-result').value = "";
    lastResult = '';
}

function clearEntryDisplay() { // CE 버튼 입력창만 초기화
    document.getElementById('display').value = "";
}

function backspace() { // backspace 기능 구현
    let displayValue = document.getElementById('display').value;
    document.getElementById('display').value = displayValue.slice(0, -1);
}

윈도우에 있는 계산기를 참고해서 지우기 버튼은 slice()메서드를 이용했다.

 

function calculate() {
    let input = document.getElementById('display').value;
    
    input = input.replace(/\s/g, ''); // 입력값에서 공백 제거 (1)
    
    if (!/^[0-9+\-*/.]+$/.test(input)) { // 숫자와 연산자 이외의 값 금지 (2)
        document.getElementById('display-result').value = 'Error';
        return;
    }
    try { // (3)
      if (lastResult !== '' && "+-*/".includes(input[0])) { // 이전 결과가 있는 경우와 처음에 연산자가 입력되었을 경우
        lastResult += input; // 이전 결과와 입력값을 이어서 계산
      } else { // 연산자가 입력되지 않았을 경우      // (4)
        lastResult = input; // 입력값을 결과로 지정
      }
      lastResult = new Function('return ' + lastResult)(); // (5)
      document.getElementById('display-result').value = lastResult;
      clearEntryDisplay(); // 입력창을 초기화하지 않고 결과 창만 초기화
    } catch(error) {
      document.getElementById('display-result').value = 'Error';
    }
}

계산기를 버튼만 클릭하는 것이 아닌 윈도우 계산기처럼 키보드를 입력해서도 결과가 나오게끔 만들고 싶어서

(1) 스페이스바를 눌렀을 때를 방지하기 위해 정규표현식과 replace메서드를 이용해서 공백을 제거했다

 

(2) 정규표현식을 활용해서 계산기에 숫자와 연산자 값이 입력될 경우 'Error' 표시

 

(3) try..catch를 이용해서 3 ++ 5, 3 +- 5와 같은 에러를 방지했다.

 

(4) 처음 계산 하는게 아니고 이전의 결과값에 추가적으로 계산을 할 경우를 위해 lastResult라는 변수를 전역변수로 지정하고 값이 비어있는게 아니면서 연산자로 시작하는 경우 이전 결과값에 입력값을 이어서 계산하게 했다.

 만약 연산자가 먼저 시작되지 않고 숫자를 입력한 경우 새로운 계산을 하게끔 인식 했다. 

 ex) 1 + 2 = 3  ➔ + 2 = 5, 1 + 2 = 3 ➔ 2 + 2 = 4

 

(5) 처음에는 document.getElementById('display').value로 입력받은 숫자가 문자열이기 때문에 계산을 위해

 eval()메서드를 사용하려고 했었는데 MDN에서 eval() 메서드에 대해서 아래와 같이 표시 된 것을 확인했다.

eval() 코드의 위험성

eval()은 인자로 받은 코드를 caller의 권한으로 수행하는 위험한 함수입니다.
악의적인 영향을 받았을 수 있는 문자열을 
eval()로 실행한다면,
당신의 웹페이지나 확장 프로그램의 권한으로 사용자의 기기에서
악의적인 코드를 수행하는 결과를 초래할 수 있습니다

eval()함수의 대체로 new Function() 문법을 이용해서 해결했다. 

new Function()은 문자열을 이용해 새로운 함수를 만들고 이를 실행하는 것도 가능했다.

 

document.getElementById('display').addEventListener('keypress', function(event) {
    if (event.key === 'Enter') {
      calculate();
    }
  });

마지막으로 윈도우 계산기처럼 엔터키를 눌렀을 때 계산이 되도록 구현하려고

처음에는 KeyboardEvent: keyCode 속성을 이용하려고 했었는데

MDN사이트에서 브라우저 표준이 아닌 이 기능을 권장하지 않고 언제든지 작동이 중지 될 수 있다고 나와있었고

사이트 안에서 권장하는 방법은 addEventListener를 이용해서 처리하라고 나와있었다.

 

 

마무리

기존에 알고 있던 문법들이었지만 구현을 하려고 하니깐 바로바로 생각이 나지 않았고

간단한 계산기라도 만들어 보는 것이 배우는 데 있어서 큰 도움이 되는 것을 느꼈다.

 

 

참고사이트

https://velog.io/@minukbak/904 

https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode

https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code