ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자바스크립트 계산기 만들기 1: 계산기 꾸미기, 계산식 입력
    자바스크립트 2020. 3. 30. 23:38

    css 그리드와 자바스크립트를 이용해서 계산기 만들기

     

    계산기 개발 순서

    1. 계산기 뼈대 만들기
    2. 계산기 꾸미기
    3. 버튼 클릭 시 input에 텍스트 추가
    4. AC 기능 구현
    5. 계산 기능 구현 (=버튼)
    6. 예외 처리

     

    결과 화면


     

    계산기 뼈대 만들기


    필요한 태그

    • 숫자, 연산자를 클릭할 수 있는 <button />

    • <button />에 그리드를 적용하기 위한 <div />

    • 버튼 클릭 시 값을 입력받을 <input />

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Calculator</title>
        <link rel="stylesheet" href="style.css">    
    </head>
    <body>
        <main>
            <input type="text" disabled>
            <div class="button-wrap">
                <button>AC</button>            
                <button>&divide;</button>
                <button>7</button>
                <button>8</button>
                <button>9</button>
                <button>&times;</button>
                <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>

     

     

     

    계산기 꾸미기


    그리드 레이아웃으로 버튼 정렬

    /* style.css */
    main {
        width: 300px;
    }
    .button-wrap {
        display: grid;
        /* 한 줄에 4개씩, 모두 동일한 비율 적용(1:1:1:1) */
        grid-template-columns: repeat(4, 1fr);
    }

     

    AC, 0 버튼 크기 조절

    <main>
        <input type="text" disabled>
        <div class="button-wrap">
            <!-- ac 클래스 추가 -->
            <button class="ac">AC</button>
            <button>&divide;</button>
            <button>7</button>
            <button>8</button>
            <button>9</button>
            <button>&times;</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>

    그리드 라인 참고

    ...
    .ac {
        /* 첫 번째 선부터 4번째 선까지 지정 */
        grid-column: 1/4;
    }
    .zero {
        /* 첫 번째 선부터 3번째 선까지 지정 */
        grid-column: 1/3;
    }

     

    input 태그 스타일 설정

    /* style.css */
    * {
        box-sizing: border-box;
        color: white;   
    }
    input, button {
        height: 70px;
        outline: none;
    }
    input {
        width: 100%;
        text-align: right;
        border: none;    
        background: #5B5B5D;
        padding-right: 1rem;
        font-size: 3rem;
    }

     

    버튼 태그 스타일 설정

    button {
        background: #828284;
        border: 1px solid #454448;
        font-size: 2rem;
    }
    /* nth-child(4n+2): 4번째 요소마다 스타일을 적용하는데 처음에만 두번째에 적용 */
    button:nth-child(4n+2), button:last-child  {
        background-color: orange;
    }
    button:hover {    
        opacity: .5;
    }
    .ac {
        grid-column: 1/4;
        background: #6A6A6C;
    }
    .zero {
        grid-column: 1/3;
    }

     

     


    버튼 클릭 시 input에 추가


    버튼 클릭 시 data-type에 따라 동작을 다르게 처리하기 위해 숫자 버튼을 제외하고 data-type 속성 추가

    • AC버튼 : data-type="ac"
    • 연산자 버튼 : data-type="operator"
    • = 버튼 : data-type="equals"
    <main>
        <input type="text" value="0" disabled>
        <div class="button-wrap">
            <button data-type="ac" class="ac">AC</button>
            <button data-type="operator">&divide;</button>
            <button>7</button>
            <button>8</button>
            <button>9</button>
            <button data-type="operator">&times;</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>
            <button class="zero">0</button>
            <button>.</button>
            <button data-type="equals" class="equals">=</button>
        </div>
    </main>

     

    script.js 파일을 만들고 버튼과 input 태그를 가져와서 변수에 담기

    const buttons = document.querySelectorAll('button')
    const displayElement = document.querySelector('input')

     

    html 파일에 script.js 연결

    <body>
        <main>
            <!-- ... -->            
        </main>
        <script src="script.js"></script>
    </body>
    

     

    Calculator 클래스 만들고 인스턴스 생성

    class Calculator {
        constructor(displayElement) { 
            this.displayElement = displayElement
            this.displayContent = ''
        }    
    }
    
    const buttons = document.querySelectorAll('button')
    const displayElement = document.querySelector('input')
    
    const calculator = new Calculator(displayElement)

     

    addEventListener로 모든 버튼에 클릭 이벤트를 연결하고 switch문으로 data-type에 따라 버튼 구분

    // ...
    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:
                    console.log('number')
                    break
            }
        })      
    })

     

    click 이벤트 연결 후 테스트

     

    숫자 버튼을 클릭할 때마다 displayContent 속성에 숫자가 추가되고 input에도 표시되도록 appendNumber, updateDisplay 메서드 추가

    switch문의 default에서 추가한 메서드 호출

    class Calculator {
        constructor(displayElement) { 
            this.displayElement = displayElement
            this.displayContent = ''
        }    
    
        appendNumber(number) {
            this.displayContent += number
        }
    
        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
            }
        })      
    })

     

     

    마찬가지로 클래스에 appendOperator 메서드 추가 후 연산자 버튼 클릭 시 호출되도록 연결

    class Calculator {
        constructor(displayElement) { 
            this.displayElement = displayElement
            this.displayContent = ''
        }    
    
        appendNumber(number) {
            this.displayContent += number
        }
    
        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)
    
    buttons.forEach(button => {
        button.addEventListener('click', () => {
            switch (button.dataset.type) {
                case 'operator':
                    calculator.appendOperator(button.innerText)
                    calculator.updateDisplay()
                    break
                //...
            }
        })      
    })

     

     

     

    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.clear()
        }    
    }

     

    html에서 input 태그의 value 속성은 더 이상 필요 없으니 제거

    <!--<input type="text" value="0" disabled>-->
    <input type="text" disabled>

     

     

     

     

    댓글

Designed by Tistory.