sprint - 계산기 구현

FeelSoo·2022년 4월 12일
0

CodeStates

목록 보기
2/43

Bare Minimum

Step 1 - CSS 마음껏 수정하여 예쁜 계산기 만들기

calculate.html 파일은 그대로 두고, yourStyle.css 파일을 수정합니다.
자신이 원하는 디자인으로 계산기를 꾸며보세요.

Step 2 - 버튼이 잘 동작하는지 확인하기

버튼을 클릭했을 때, 각 버튼이 잘 동작하는지 개발자 도구의 콘솔 탭에서 확인하세요.

Step 3 - 기본적인 계산 기능 구현하기

연산 시 script.js의 calculate 함수를 활용할 수 있도록 함수 calculate를 작성합니다.
처음 숫자 버튼을 클릭했을 때, 첫 번째 화면에 누른 숫자가 나타나야 합니다.
숫자 버튼과 연산자 버튼을 순서대로 클릭했을 때, 첫 번째 화면는 숫자, 두 번째 화면에는 연산자가 나타나야 합니다.
숫자 버튼, 연산자 버튼, 숫자 버튼을 순서대로 클릭했을 때, 화면에 숫자, 연산자, 순자가 순서대로 나타나야 합니다.
숫자 버튼, 연산자 버튼, 숫자 버튼, 엔터 버튼을 순서대로 클릭했을 때, 화면에 숫자, 연산자, 숫자, =, 연산 결과가 순서대로 나타나야 합니다.
AC 버튼을 클릭했을 때, 화면에 0, +, 0, =, 0 이 순서대로 나타나야 합니다.


Advanced Challenges

Step 2 - 숫자 버튼을 누르고 화면에 숫자를 입력하기

숫자 버튼을 눌렀을 때, 계산기의 화면에 숫자가 보여야 합니다.
숫자 버튼을 여러 번 눌렀을 때, 계산기 화면에 숫자가 이어붙여져야(concatenation) 합니다.
Step 3 - Enter 버튼을 눌러 계산하고, AC 버튼으로 초기화 시키기

연산자 버튼을 눌렀을 때, 계산기 화면에 보이는 숫자를 따로 저장하고 계산할 준비해야 합니다.
Enter 버튼을 눌렀을 때, 이전에 저장한 숫자와 계산기 화면에 보이는 숫자를 계산한 결과를 화면에 보여줘야 합니다.
두 정수의 사칙연산을 수행하는 calculate 함수를 작성합니다.
AC 버튼을 누르면 초기 상태로 돌아갈 수 있어야 합니다.
미리 작성된 SpecRunner.html 파일을 열고, Requirements을 전부 구현했는지 테스트를 돌려서 확인 합니다.

Yourstyle.css


* global */
* {
  margin: 0;
  padding: 0;
  border: 0px;
  box-sizing: border-box;
  font-family: 'Verdana', 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: #7556b9;
  width: 400px;
  height: 530px;
  border-radius: 20px;
  padding: 40px 20px;
  border: solid 6px #672fdf; 
  border-bottom: solid 6px #7c5ebd;
}

.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: 50px;
  height: 45px;
  border-radius: 10px;
  font-size: 20px;
  padding: 10px 5px;
}

.calculator__display--for-advanced {
  
  background-color: #ffffff;
  height: 100px;
  width: 100%;
  border-radius: 10px;
  font-size: 20px;
  text-align: center;
  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: 15px;
  width: 70px;
  height: 45px;
  margin: 0px 5px;
  background-color: #00ff88;
  cursor: pointer;
  outline: none;
  border-bottom: 3px solid #00c267;
}

.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;
  padding: 30px;
  bottom: 0px;
  right: 0px;
}

script.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(n1, operator, n2) {
  let result = 0;
  // TODO : n1과 n2를 operator에 따라 계산하는 함수를 만드세요.
  // ex) 입력값이 n1 : '1', operator : '+', n2 : '2' 인 경우, 3이 리턴됩니다.
  
  let a = +n1; // n1, n2 변수를 각각 선언하고 할당한다. +를 붙이면 숫자가 결합하는게 아닌 산수를 진행한다. 
  				//( 5 + 6 >> 56 이 아니고 11이 된다 )
  let b = +n2;
  if (operator === '+') result = a + b;
  else if (operator === '-') result = a - b; 
  else if (operator === '*') result = a * b;
  else if (operator === '/') result = a / b;
  //operator 가 +,-,*,/	일때 각각 조건을 주어 n1,n2변수에 각각 선언한다
  return String(result);
  //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')) {

    // 클릭된 HTML 엘리먼트가 button이면 그리고 버튼의 클레스가 number이면 코드 실행 
    if (action === 'number') { //숫자를 클릭했을때 화면상에 그숫자가 보이도록 한다
      if (firstOperend.textContent === '0') firstOperend.textContent = buttonContent;
      else if (firstOperend.textContent !== '0') secondOperend.textContent = buttonContent;
      console.log('숫자 ' + buttonContent + ' 버튼');
    }

    if (action === 'operator') {//기호를 클릭했을때 해당 기호가 화면상에 보이게 한다.
      operator.textContent = buttonContent;
      console.log('연산자 ' + buttonContent + ' 버튼');
    }

    if (action === 'decimal') {
      // console.log('소수점 버튼');
    }

    if (action === 'clear') {// 화면상에 보이는 숫자들을 초기화 한다.
      firstOperend.textContent = '0';
      secondOperend.textContent = '0';
      calculatedResult.textContent = '0';
      console.log('초기화 버튼');
    }

    if (action === 'calculate') {//최종 계산 값이 화면상에 나올 수 있도록 한다.
      calculatedResult.textContent = calculate(firstOperend.textContent, operator.textContent, secondOperend.textContent)
      console.log('계산 버튼');
    }
  }
});

// ! Advanced Challenge test와 Nightmare test를 위해서는 아래 주석을 해제하세요.

const display = document.querySelector('.calculator__display--for-advanced'); // calculator__display 엘리먼트와, 그 자식 엘리먼트의 정보를 모두 담고 있습니다.
let firstNum, operatorForAdvanced, previousKey, previousNum;


function calculate(n1, operator, n2) {
  let result = 0;
  // TODO : n1과 n2를 operator에 따라 계산하는 함수를 만드세요.
  // ex) 입력값이 n1 : '1', operator : '+', n2 : '2' 인 경우, 3이 리턴됩니다.
  
  let a = +n1; // n1, n2 변수를 각각 선언하고 할당한다.
  let b = +n2;
  if (operator === '+') result = a + b;
  else if (operator === '-') result = a - b; 
  else if (operator === '*') result = a * b;
  else if (operator === '/') result = a / b;
  //operator 가 +,-,*,/	일때 각각 조건을 주어 n1,n2변수에 각각 선언한다
  return String(result);
  //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 엘리먼트의 텍스트 정보를 가져옵니다.
  // ! 위 코드는 수정하지 마세요.

  // ! 여기서부터 Advanced Challenge & Nightmare 과제룰 풀어주세요.
  if (target.matches('button')) {
    if (action === 'number') {
      if (display.textContent === '0' && previousKey !== 'operator')
      {
        display.textContent = buttonContent;
        firstNum = display.textContent;
      }
      else if (display.textContent !== '0' && previousKey !== 'operator' && previousNum === undefined)
      {
        display.textContent += buttonContent;
        firstNum = display.textContent;
      }
      else if (previousKey === 'operator' && display.textContent !== '0')
      {
        display.textContent = 0;
        display.textContent = buttonContent;
        previousNum = display.textContent;
      }
      else
      {
        display.textContent += buttonContent;
        previousNum = display.textContent;
      }
      previousKey = 'number';
    }
    if (action === 'operator') {
      if (previousNum)
      {
        firstNum = calculate(firstNum, operatorForAdvanced, previousNum);
        operatorForAdvanced = buttonContent;
        display.textContent = firstNum;
        previousNum = undefined;
      }
      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') {
      previousKey = 'clear'
      previousNum = undefined
      firstNum = undefined
      operatorForAdvanced = undefined;
      display.textContent = 0;
    }
    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';
      console.log(firstNum, operatorForAdvanced, previousNum);
    }
  }
});

포인트는 DOM(JS에서 html요소에 접근하는 것)을 활용하기 위한 document.querySelector

profile
세상은 넓고 배울건 많다

0개의 댓글