[자바스크립트 계산기 만들어서 티스토리 블로그에 올리기]
See the Pen SimpleCalculator by YYYSYYY (@SayYoung) on CodePen.
아래 사이트 참고하여, 티스토리 블로그에 자바스크립트를 이용하여 계산기 만드는 과정을 배웠음
아래 내용은 위 블로그의 글과 거의 흡사하고, 중간중간 의문가는 사항이나 이해하는 과정에서의 코멘트를 파란 글씨로 추가했음.
1. 태그 배우기
- <button/> 태그를 통해 유저가 숫자나 연산자를 클릭할 수 있게 한다
- <button/> 을 격자로 표현하기 위해 <div/>를 사용한다.
- 사용자로부터 값을 입력받을 <input/>
2. 뼈대 만들기
아래와 같이 폴더와 html파일을 만든다.
html 코드 작성
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--위 태그는 html파일의 인코딩을 알려주는 태그다.
브라우저에게 text를 어떻게 그려달라는 것인지 말해주는 것으로,
위 태그가 없으면 특수문자 등이 제대로 표시되지 않을 수 있다-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--viewport란 화면상의 표시 영역을 말함. contnet=device-width로 하면
장치 크기에 맞게 표시되므로 추천.
initial-scale은 뷰포트의 초기 배율을 뜻하며 보이는 영역에서 웹페이지에 맞추기 위해 계산됨-->
<title>Calculator</title>
<link rel="stylesheet" href=“style.css">
<!--링크 태그에 달리는 링크가 현재 페이지와 어떤 관계를 갖는지 설명하는 attribute다.
현재 페이지의 스타일을 꾸미는 데 사용되는 스타일시트인 "style.css"를 불러오라는 것이다.
현재 html페이지와의 관계(rel)은 stylesheet, 그 스타일시트를 어디서 가져오냐면
"style.css"에서 가져오라는 것이다.-->
</head>
<body>
<main>
<input type="text" disabled>
<!--"text"타입의 요소는 사용자가 클릭할 수 없고 사용할 수 없음.-->
<div class="button-wrap">
<!--"button-wrap"이라는 class를 생성하고, 버튼을 만들어 준다.-->
<button>AC</button>
<button>÷</button>
<!--÷는 나눗셈 표시를 위한 html 토큰이다.-->
<button>7</button>
<button>8</button>
<button>9</button>
<button>×</button>
<!--×는 곱셈 표시를 위한 html 토큰이다.-->
<button>4</button>
<button>5</button>
<button>6</button>
<button>-</button>
<button>1</button>
<button>2</button>
<button>3</button>
<button>+</button>
<button>0</button>
<button>.</button>
<button>=</button>
</div>
</main>
</body>
</html>
* 여기까지 결과 화면
이걸 계산기 모양대로 바꿔줘야 한다. css파일을 이용한다.
3. css파일 만들기
*css 문법 이해
css의 문법은 선택자와 선언부로 구성됨.
선택자는 css 적용을 위한 html요소를 가리킨다. 선언부는 하나 이상의 세미콜론으로 구분하여 포함 가능하며
중괄호로 전체를 둘러싼다.
(출처: http://tcpschool.com/css/css_intro_syntax)
*css 선택자는 다음과 같다
- Html 요소 선택자
h2 { color: teal; text-decoration: underline; }
- Id 요소 선택자
#heading { color: teal; text-decoration: line-through; }
Class 선택자
.headings { color: lime; text-decoration: overline; }
html요소는 특수문자 없이 선택하면 되고, id요소는 #기호, Class요소는 .기호를 앞에 붙여서 선택하는 것을 알 수 있다.
Group 선택자(위의 여러 선택자를 같이 사용하고자 할 때)
h1 { color: navy; }
h1, h2 { text-align: center; }
h1, h2, p { background-color: lightgray; }
*css 코드
/* style.css */
/* main이라는 엘리먼트의 너비를 150으로 고정함 */
/*main 이라는 html요소를 선택자로 하고 넓이를 150픽셀로 설정*/
main {
width: 150px;
}
/*button-wrap이라는 class 요소를 선택자로 하고, grid 디스플레이 적용,
repeat(반복횟수, 반복값)
*/
.button-wrap {
display: grid;
/* 한 줄에 4개씩, 모두 동일한 비율 적용(1:1:1:1) */
grid-template-columns: repeat(4, 1fr);
}
* 여기까지 결과화면
4. 별로 예쁘지 않으니까 버튼 크기 등을 조절해 준다
아래처럼 바꿔주려 한다.
css에서 조정해 줘야 하는데, a버튼과 0버튼은 다른 버튼과 크기가 다르다.
Html 코드에서 class 를 추가하여 css에서 다룰 수 있게 해 준다.
- html 코드 수정
<main>
<!--"text"타입의 요소는 사용자가 클릭할 수 없고 사용할 수 없음.-->
<input type="text" disabled>
<!--"button-wrap"이라는 class를 생성하고, 버튼을 만들어 준다.-->
<div class="button-wrap">
<!-- ac 클래스 추가 -->
<button class="ac">AC</button>
<!--÷는 나눗셈 표시를 위한 html 토큰이다.-->
<button>÷</button>
<button>7</button>
<button>8</button>
<button>9</button>
<!--×는 곱셈 표시를 위한 html 토큰이다.-->
<button>×</button>
<button>4</button>
<button>5</button>
<button>6</button>
<button>-</button>
<button>1</button>
<button>2</button>
<button>3</button>
<button>+</button>
<!-- zero 클래스 추가 -->
<button class="zero">0</button>
<button>.</button>
<button>=</button>
</div>
</main>
-css 코드 추가
/*ac버튼 크기 조정*/
.ac {
/*4등분하여 나온 5개의 선 중에서 첫번째 선부터 4번째 선까지 지정*/
grid-column: 1/4;
}
/*0버튼 크기 조정*/
.zero {
/*4등분하여 나온 5개의 선 중에서 첫번째 선부터 3번째 선까지 지정*/
grid-column: 1/3;
}
*여기까지 결과화면
5. input 태그 스타일 설정(꾸미기)
여긴 색칠하고 그런거니까.. 복붙 하고 넘어가고 나중에 공부하기로 하자. 우선 기능을 만들어 보자
- css파일에 아래와 같이 추가해 준다.
* {
box-sizing: border-box;
color: white;
}
input, button {
height: 35px;
outline: none;
}
input {
width: 100%;
text-align: right;
border: none;
background: #5B5B5D;
padding-right: 1rem;
font-size: 2rem;
}
6. 버튼 태그 스타일 설정(꾸미기)
여기도 마찬가지로 복붙하고 넘어간다.
- css 코드 수정
button {
background: #828284;
border: 1px solid #454448;
font-size: 1rem;
}
/* nth-child(4n+2): 4번째 요소마다 스타일을 적용하는데 처음에만 두번째에 적용 */
button:nth-child(4n+2), button:last-child {
background-color: orange;
}
button:hover {
opacity: .5;
}
/*ac버튼 크기 조정*/
.ac {
/*4등분하여 나온 5개의 선 중에서 첫번째 선부터 4번째 선까지 지정*/
grid-column: 1/4;
background: #6A6A6C;
}
/*0버튼 크기 조정*/
.zero {
/*4등분하여 나온 5개의 선 중에서 첫번째 선부터 3번째 선까지 지정*/
grid-column: 1/3;
}
*여기까지 결과화면
7. 버튼 클릭 시 input에 추가
버튼을 클릭하면 값이 입력되도록 하는 작업이다. data-type에 따라 동작을 다르게 처리하기 위해, 숫자 버튼을 제외하고 data-type 속성을 추가해 준다
- ac버튼 : data-type=“ac”
- 연산자 버튼 : data-type=“operator”
- = 버튼 : data-tyle =“equals”
- html 코드 수정
<main>
<!--"text"타입의 요소는 사용자가 클릭할 수 없고 사용할 수 없음.-->
<input type="text" disabled>
<!--"button-wrap"이라는 class를 생성하고, 버튼을 만들어 준다.-->
<div class="button-wrap">
<!-- ac 클래스 추가 -->
<button data-type="ac" class="ac">AC</button>
<!--÷는 나눗셈 표시를 위한 html 토큰이다.-->
<button data-type="operator">÷</button>
<button>7</button>
<button>8</button>
<button>9</button>
<!--×는 곱셈 표시를 위한 html 토큰이다.-->
<button data-type="operator">×</button>
<button>4</button>
<button>5</button>
<button>6</button>
<button data-type="operator">-</button>
<button>1</button>
<button>2</button>
<button>3</button>
<button data-type="operator">+</button>
<!-- zero 클래스 추가 -->
<button class="zero">0</button>
<button>.</button>
<button data-type="equals" class="equals">=</button>
</div>
</main>
*자바스크립트 파일을 만든다(파일명:script.js)
8. 버튼과 input 태그를 가져와서 변수에 담는다
- javascript 코드
const buttons = document.querySelectorAll('button')
//자바스크립트 코드에 ‘buttons’ 라는 변수를 선언한다. css 문서 내의 ‘button’이라는 선택자에 해당하는 모든 요소를 리스트 타입으로 반환한다. 계산기에서 각 버튼들을 의미한다.
const displayElement = document.querySelector('input')
//자바스크립트 코드에 ‘displayElemnet’ 라는 변수를 선언한다. css 문서 내의 ‘input’이라는 선택자에 해당하는 모든 요소를 리스트 타입으로 반환한다. 계산기에서 입력된 내용을 보여주는 부분이다.
querySelector()
document.querySelector() 는 입력한 선택자와 일치하는 문서 내의 첫 번째 element를 반환한다. 일치하는 요소가 없다면 null을 반환한다. 괄호 안에 들어가는 매개변수는 유효한 CSS 선택자여야한다.
querySelectorAll()
querySelector()가 한 개의 요소를 반환했다면, querySelectorAll()은 주어진 CSS 선택자와 일치하는 모든 요소를 반환한다. 이때, 반환 타입은 리스트 타입이다. 따라서 인덱스를 통해 조작할 수 있다.
9. html 파일에 script.js 연결
<body>
<main>
<!-- ... -->
</main>
<script src="script.js"></script>
</body>
10. Calculator 클래스 만들고 인스턴스 생성
무슨말인지 모르겠다. 클래스는 뭐고 인스턴스는 뭘까.
예를 들면 이런 거라고 한다.
붕어빵틀 = class
붕어빵 = object
각각의 붕어빵 = instance
붕어빵을 굽다 = 인스턴스(instance)화 하다
생성자(constructor) =
클래스를 생성할 때 생성자는 반드시 존재해야 한다
생성자를 선언할 때 클래스의 이름과 생성자의 이름은 반드시 같아야 한다.
constructor 매서드(작업)는 class 내에서 객체를 생성하고 초기화하기 위한 특별한 메서드다.
내가 하는 작업에 적용해 보자면, “계산기”는 “붕어빵틀, class”이다. 무언가를 만들기 위한 기본 뼈대다. 이 도구를 통해서 입력값을 받아서 “결과값”을 내놓을 것이다. 이 “결과값”이 “붕어빵,instance”이라고 이해하면 될 것 같다. instance는 구체적인 상태(variable, 변수)와 행위(method, 기능)의 집합이다.
생성자의 개념은 잘 와 닿지 않는다. 비유하자면 생성자(constructor)는 업무를 하기 전에 하는 책상정리와 비슷하다고 한다(초기화).
(참조: https://whatisthenext.tistory.com/1)
class Calculator {
//class를 선언한다
constructor(displayElement) {
//생성자 함수를 통해 displatElement의 초기상태를 지정하기 위한 책상정리를 한다.
this.displayElement = displayElement
//this는 인스턴스 자신을 가리키는 참조변수다.
//Calculator클래스의 안에 있는 인스턴스 변수 displayElement에 displayElement를 담는다
this.displayContent = ''
//Calculator클래스의 안에 있는 인스턴스 변수 displayContent에 빈 문자열을 담는다
}
}
const buttons = document.querySelectorAll('button')
const displayElement = document.querySelector('input')
const calculator = new Calculator(displayElement)
//new 함수를 통해 Calculator라는 객체를 만든다. 이 객체에는 위에서 정의한 것과 같이 displayElement와 displayContent가 세팅되어 있다.
11. addEventListener로 모든 버튼에 클릭 이벤트를 연결하고 switch문으로 data-type에 따라 버튼 구분하기
event란 '사용자가 어떤 결과를 유발시킬만한 행동을 하는 것'이다. 사용자가 클릭을 한다거나 페이지를 넘긴다거나 하는 것을 말한다.
자바스크립트에서는 특정 이벤트가 발생했을 시 특정 함수를 실행할 수 있게 해주는 addEventListener라는 기능이 존재한다.
▶ addEventListener 등으로 등록할 수 있는 이벤트 중 자주 쓰이는 이벤트 목록
(출처: https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=qbxlvnf11&logNo=220877806711)
이벤트 명 | 설명 |
change | 변동이 있을 때 발생 |
click | 클릭시 발생 |
focus | 포커스를 얻었을 때 발생 |
keydown | 키를 눌렀을 때 발생 |
keyup | 키에서 손을 땟을 때 발생 |
load | 로드가 완료 되었을 때 발생 |
mousedown | 마우스를 클릭 했을 때 발생 |
mouseout | 마우스가 특정 객체 밖으로 나갔을 때 발생 |
mouseover | 마우스가 특정 객체 위로 올려졌을 때 발생 |
mousemove | 마우스가 움직였을 때 발생 |
mouseup | 마우스에서 손을 땟을 때 발생 |
select | option 태그 등에서 선택을 햇을 때 발생 |
// ...
const buttons = document.querySelectorAll('button')
const displayElement = document.querySelector('input')
const calculator = new Calculator(displayElement)
//arrow함수 forEach문은 다음과 같다.
//리스트.forEach(원소=>함수(원소));
//리스트 내의 각 원소를 함소 안에 차례로 넣는다.
buttons.forEach(button => {
<<!--대상객체.addEventListener('이벤트명', fuction 함수명(event){}) = ‘이벤트만들기’)
화살표 함수는 function 키워드 대신 화살표를 사용하여 간략하게 함수를 선언하는 것이다
매개변수가 없는 경우
()=>{…}
처럼 사용할 수 있다.-->
button.addEventListener('click', () => {
<!-- data-type은 html코드에서 요소별로 부여했다. button.dataset.type 부분은 button의 데이터타입을 가져오는 것이고,
케이스별로 분류하여 'operator', 'ac', 'equals'와 비교하여 일치여부 판단하고 콘솔 로그에 표시한다.-->
switch (button.dataset.type) {
case 'operator':
console.log('operator')
break
case 'ac':
console.log('ac')
break
case 'equals':
console.log('equals')
break
default:
console.log('number')
break
}
})
})
12. 숫자 버튼을 클릭할 때마다 displayContent 속성에 숫자가 추가되고 input에도 표시되도록 appendNumber, updateDisplay 메서드 추가 switch문의 default에서 추가한 메서드 호출
class Calculator {
constructor(displayElement) {
this.displayElement = displayElement
//this.displaycontent='' 라고 표시했다. 따옴표 표시했으므로 자료형은 문자열이다.
this.displayContent = ''
}
//appendNumber 메서드(작업) 추가.
appendNumber(number) {
//+= 는 복합대입연산자인데, this.displayContent = this.displayContent + number와 같은 의미를 가진다. 문자열(String)에 +기호를 쓴 경우 덧셈을 하라는 것이 아니라 문자열을 잇는다는 것이다. ex) 10 + 1 = 101
this.displayContent += number
}
//updateDisplay 메서드(작업)추가.
//this.displayElemnet의 값(value)에 this.displayContent를 담는다.
updateDisplay() {
this.displayElement.value = this.displayContent
}
}
const buttons = document.querySelectorAll('button')
const displayElement = document.querySelector('input')
const calculator = new Calculator(displayElement)
buttons.forEach(button => {
button.addEventListener('click', () => {
switch (button.dataset.type) {
case 'operator':
console.log('operator')
break
case 'ac':
console.log('ac')
break
case 'equals':
console.log('equals')
break
default:
calculator.appendNumber(button.innerText)
calculator.updateDisplay()
break
}
})
})
13. 마찬가지로 클래스에 appendOperator 메서드 추가 후 연산자 버튼 클릭 시 호출되도록 연결
class Calculator {
constructor(displayElement) {
this.displayElement = displayElement
this.displayContent = ''
}
appendNumber(number) {
this.displayContent += number
}
//this.displayContent = this.displayContent + operator 의 의미다.
appendOperator(operator) {
this.displayContent += operator
}
updateDisplay() {
this.displayElement.value = this.displayContent
}
}
const buttons = document.querySelectorAll('button')
const displayElement = document.querySelector('input')
const calculator = new Calculator(displayElement)
//클릭한 버튼이 연산자이면, calculator 클래스의 appendOperator 메서드를 추가한다.
//element.innerText;는 자바스크립트에 내장된 기능이다. HTML element 안의 텍스트를 가져온다.
buttons.forEach(button => {
button.addEventListener('click', () => {
switch (button.dataset.type) {
case 'operator':
calculator.appendOperator(button.innerText)
calculator.updateDisplay()
break
//...
}
})
})
14. AC 기능 구현
* ac버튼을 누르면 모든 입력이 초기화되도록 클래스에 clear 메서드 추가 후 ac버튼과 연결
class Calculator {
// ...
clear() {
this.displayContent = ''
this.displayElement.value = 0
}
}
const buttons = document.querySelectorAll('button')
const displayElement = document.querySelector('input')
const calculator = new Calculator(displayElement)
buttons.forEach(button => {
button.addEventListener('click', () => {
switch (button.dataset.type) {
case 'ac':
calculator.clear()
break
//...
}
})
})
* constructor에서도 clear 메서드를 호출하도록 수정
class Calculator {
constructor(displayElement) {
this.displayElement = displayElement
this.displayContent = ''
this.clear()
}
* 여기까지 결과화면
15. 계산 기능 구현
*eval() 함수.
자바스크립트에서 사칙연산과 관련된 산술 연산자는 +, -, *, /이다.
자바스크립트의 eval 함수를 사용하면 계산 기능을 쉽게 구현할 수 있다.
eval()은 문자로 표현된 JavaScript 코드를 실행하는 함수이다.
간단한 예로 a 변수에 2 + 3 * 5 연산식을 저장하고 eval 함수에 인자로 a를 넣고 실행하면 식이 계산된다.
let a = '2 + 3 * 5'
eval(a) // 17
class Calculator {
//...
compute() {
this.displayContent = eval(this.displayContent)
}
}
* 계속해서 클래스에 compute 메서드를 추가하고 eval() 함수를 사용해서 계산 기능 구현
class Calculator {
//...
compute() {
this.displayContent = eval(this.displayContent)
}
}
* "=" 버튼 클릭 시 compute 메서드를 호출하도록 연결
buttons.forEach(button => {
button.addEventListener('click', () => {
switch (button.dataset.type) {
// ...
case 'equals':
calculator.compute()
calculator.updateDisplay()
break
default:
calculator.appendNumber(button.innerText)
calculator.updateDisplay()
break
}
})
})
더하기와 빼기는 잘 되지만 곱하기와 나누기는 에러가 발생. 자바스크립트에서는 곱하기와 나누기가 ×, ÷가 아닌 *, / 를 사용하므로
replace를 사용하여 × -> *로, ÷ -> / 로 변경해준 후 계산
class Calculator {
// ...
compute() {
this.displayContent = eval(this.displayContent
//"\u00D7" 는 ×, "\u00F7"는 ÷를 의미한다.
.replace('\u00D7', '*')
.replace('\u00F7', '/')
)
}
}
* 여기까지 결과화면. 기본적인 기능을 한다.
'코딩 > 뭔가 만들어 보기' 카테고리의 다른 글
[Python] Selenium과 python selenium bot을 이용하여 취소표 빈자리 알림 보내기 (1) | 2022.09.29 |
---|---|
[Python] 특정 페이지에 새 글이 올라오면 알림을 보내는 코드 (0) | 2022.09.14 |
근로소득 구간별 세금 부담 비율 (0) | 2021.09.29 |
내 연봉, 근로소득자 중 상위 몇 퍼센트일까?(+ 세금은 얼마나 내고 있을까?) (0) | 2021.09.07 |
연말정산 계산기 만들어보기(1) (1) | 2021.08.29 |
댓글