CSS&JS/⚡Thinkers

[JS] 바닐라 자바스크립트로 간단한 계산기 만들어보기(2)

arancia_ 2022. 1. 3. 16:24

개선 사항 : 

  • 좀 더 단순화한 data object
  • +/- 음수 양수 변환 추가
  • 연산자로 이용한 연속계산과, = 버튼을 이용한 반복계산 오류 안 나게 개선
  • eval이 아닌 switch문으로 변경

 

 

See the Pen Caculator v1.2 by Oh Ikmyeong (@dpffpself) on CodePen.

 

HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<!DOCTYPE html>
<html lang="ko">
<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>계산기-myAnswer</title>
<link rel="stylesheet" type="text/css" href="./style/main.css"/>
<script src="./js/main.js" type="module"></script>
</head>
<body>
    
<section id="caculator">
    <article id="area-display">
        <div id="steps" class="off">0</div>
        <div id="display">0</div>
    </article><!-- area-display -->
    <article id="area-btn">
        <div class="nums">
            <button class="num" data-val="7">7</button> 
            <button class="num"data-val="8">8</button> 
            <button class="num"data-val="9">9</button>
            <button class="num" data-val="4">4</button> 
            <button class="num"data-val="5">5</button> 
            <button class="num"data-val="6">6</button>
            <button class="num" data-val="1">1</button> 
            <button class="num"data-val="2">2</button> 
            <button class="num"data-val="3">3</button>
            <button class="num" data-val="-1">+/-</button> 
            <button class="num" data-val="0">0</button> 
            <button class="num"data-val=".">.</button>
            <button id="btn_result">=</button>
        </div>
        <div class="ops">
            <button id="reset">C</button>
            <button class="op" data-val="/">÷</button>
            <button class="op" data-val="*">×</button>
            <button class="op" data-val="-">-</button>
            <button class="op" data-val="+">+</button>
        </div>
    </article>
</section><!-- caculator -->
 
</body>
</html>
cs

CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
@charset "utf-8";
*{margin:0;padding:0;box-sizing:border-box;}
html,body{
    display:flex;flex-flow:column nowrap;
    justify-content:center; align-items:center;
    width:100%;min-height:100vh;
    background:#202020;
    font-size:18px;
}
button{font-family:inherit;cursor:pointer;}
button:hover{filter:brightness(80%);}
button:focus{filter:brightness(60%);}
 
/* 계산기 */
#caculator{
    position:relative;
    width:95%; max-width:300px;
    background:rgba(255,255,255,.1);
    border-radius:4px;
    box-shadow:5px 5px 1rem rgba(0,0,0,.2);
}
 
/* 숫자 계산 화면 */
#area-display{
    position:relative;
    width:100%;
    background:rgba(255,255,255,.1);
    border-bottom:1px solid rgba(0,0,0,.3);
    text-align:right;
}
#steps{
    position:relative;
    width:100%;
    padding:1.5rem 1.25rem .5rem;
    font-size:14px; color:rgba(255,255,255,.4);
}
 
    #steps.off{opacity:0;}
#display{
    display:block;position:relative;
    width:100%; height:auto;
    white-space:normal;
    word-break:break-all;
    padding:0 1rem; padding-bottom:1.25rem;
    background:transparent;
    border:none;
    text-align:right;font-family:inherit;font-size:2rem; color:#fff;
}
 
/* 버튼 영역 */
#area-btn{
    position:relative;display:flex;flex-flow:row wrap;
    justify-content:space-between;align-items:flex-start;
}
 
/* 버튼 - 숫자 */
.nums{
    display:flex;flex-flow:row wrap;
    position:relative;
    width:75%;
 
}
.num{
    display:block;
    width:33.33%; aspect-ratio:1/1;
    border:1px solid rgba(0,0,0,.2);
    background:#707070;
    font-size:inherit; color:rgba(255,255,255,1);
}
/* .num[data-val="0"]{width:66.66%; aspect-ratio:0;} */
.num[data-val="-1"],
.num[data-val="."]{background:rgba(255,255,255,.1);}
 
/* 버튼 - 연산 */
.ops{
    position:relative;
    width:25%;
}
.op{
    display:block;
    width:100%; aspect-ratio:1/1;
    background:rgba(255,255,255,.1);
    border:1px solid rgba(0,0,0,.2);
    font-size:1.5rem; color:#fff;
}
#reset{
    display:block;
    width:100%;aspect-ratio:1/1;
    background:rgba(36, 55, 165, 0.1);
    border:1px solid rgba(0,0,0,.2);
    font-size:1rem; color:#fff;
}
 
/* = 버튼 */
#btn_result{
    display:block;
    width:100%; aspect-ratio:1/.33;
    background:rgba(93, 128, 241, 0.3);
    border:1px solid rgba(0,0,0,.2);
    font-size:2rem; font-weight:bold; color:#fff;
    mix-blend-mode:hard-light;
}
cs

JS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
const $steps = document.getElementById('steps');
const $display = document.getElementById('display');
const $area_btn = document.getElementById('area-btn');
 
const data = {
    prev : '',
    curr : '',
    operator:undefined,
    pressedResult : false
}
 
$area_btn.addEventListener('click',(e)=>{
    const target = e.target;
    if(target.tagName !== 'BUTTON'){return;}
 
    //리셋인 경우
    if(target.id == "reset"){
        reset_data();
        return;}
 
    //숫자인경우
    if(target.classList.contains('num')){
        on_num(data.operator, target);}
 
    //연산자인 경우
    if(target.classList.contains('op')){
        on_ops(target);}
 
    // = 인 경우
    if(target.id == 'btn_result'){
        show_result();}
 
    //-- 최종 : blur
    target.blur();
});
 
/* 숫자버튼을 눌렀을 경우 */
function on_num(bool,target){
    const val = target.dataset.val;
    const prevOrcurr = bool ? 'curr' : 'prev';
    if(val == "-1"){
        data[prevOrcurr] = Number(data[prevOrcurr]) * -1;
    }else{
        data[prevOrcurr] += val;
    }
    $display.textContent = data[prevOrcurr];
}//on_num
 
/* 연산자를 눌렀을 경우 */
function on_ops(target){
    $steps.classList.remove('off');
    const val_op = target.dataset.val;
    data.operator = val_op;
 
    if(data.prev == undefined){return;}
 
    if(!data.pressedResult && data.curr){show_result();}
 
    show_middleStep();
    data.curr = '';
    data.pressedResult = false;
}//on_ops
 
/* 결과 = 버튼인 경우 */
function show_result(){
    if(data.prev == undefined || data.curr == undefined || !data.operator){return;}
    data.pressedResult = true;
    
    show_finalStep();
 
    data.prev = caculSwitch();
    $display.textContent = data.prev;
}//show_result
 
/* switch로 계산 */
function caculSwitch(){
    const {prev,curr,operator} = data;
    switch(operator){
        case "+" :
            return Number(prev) + Number(curr);
        case "-" :
            return Number(prev) - Number(curr);
        case "*" :
            return Number(prev) * Number(curr);
        case "/" :
            return Number(prev) / Number(curr);
    }
}//caculSwitch
 
function operator_to_string(){
    const {operator} = data;
    switch(operator){
        case "+" :
            return "+";
        case "-" :
            return "-";
        case "*" :
            return "×";
        case "/" :
            return "÷";
    }
}//operator_to_string
 
function show_middleStep(){
    const step_str = `${data.prev} ${operator_to_string()}`;
    $steps.textContent = step_str;
}//show_middleStep
 
function show_finalStep(){
    const cacul_str = `${data.prev} ${operator_to_string()} ${data.curr}`;
    $steps.textContent = `${cacul_str} =`;
}//show_finalStep
 
/* 리셋 */
function reset_data(){
    data.prev = '';
    data.curr = '';
    $steps.textContent = '&nbsp';
    $steps.classList.add('off');
    $display.textContent = '0';
    data.operator = undefined;
    data.pressedResult = true;
}//reset_data
cs