├── README.md ├── calculator.js ├── index.html └── style.css /README.md: -------------------------------------------------------------------------------- 1 | # Calculator (HTML/CSS/JS) 2 | 3 | [Tutorial Link](https://www.youtube.com/watch?v=j59qQ7YWLxw&list=PLZlA0Gpn_vH8DWL14Wud_m8NeNNbYKOkj&index=2) 4 | -------------------------------------------------------------------------------- /calculator.js: -------------------------------------------------------------------------------- 1 | class Calculator { 2 | previousOperand = ''; 3 | currentOperand = ''; 4 | operation = undefined; 5 | 6 | constructor(previousOperandTextElement, currentOperandTextElement) { 7 | this.previousOperandTextElement = previousOperandTextElement; 8 | this.currentOperandTextElement = currentOperandTextElement; 9 | } 10 | 11 | clear() { 12 | this.previousOperand = ''; 13 | this.currentOperand = ''; 14 | this.operation = undefined; 15 | } 16 | 17 | delete() { 18 | this.currentOperand = this.currentOperand.slice(0, -1); 19 | } 20 | 21 | appendNumber(number) { 22 | const operandAsString = this.currentOperand.toString(); 23 | if (number === '.' && operandAsString.includes('.')) return; 24 | this.currentOperand = operandAsString + number.toString(); 25 | } 26 | 27 | chooseOperation(operation) { 28 | if (this.currentOperand === '') return; 29 | if (this.previousOperand !== '') { 30 | this.compute(); 31 | } 32 | 33 | this.operation = operation; 34 | this.previousOperand = this.currentOperand; 35 | this.currentOperand = ''; 36 | } 37 | 38 | compute() { 39 | const prev = parseFloat(this.previousOperand); 40 | const current = parseFloat(this.currentOperand); 41 | if (isNaN(this.previousOperand) || isNaN(this.currentOperand)) return; 42 | 43 | switch (this.operation) { 44 | case '+': 45 | this.currentOperand = prev + current; 46 | break; 47 | case '-': 48 | this.currentOperand = prev - current; 49 | break; 50 | case '*': 51 | this.currentOperand = prev * current; 52 | break; 53 | case '/': 54 | this.currentOperand = prev / current; 55 | break; 56 | default: 57 | return; 58 | } 59 | 60 | this.operation = undefined; 61 | this.previousOperand = ''; 62 | } 63 | 64 | getDisplayNumber(number) { 65 | const stringNumber = number.toString(); 66 | const integerDigits = parseFloat(stringNumber.split('.')[0]); 67 | const decimalDigits = stringNumber.split('.')[1]; 68 | 69 | let integerDisplay; 70 | if (isNaN(integerDigits)) { 71 | integerDisplay = ''; 72 | } else { 73 | integerDisplay = integerDigits.toLocaleString('en', { 74 | maximumFractionDigits: 0, 75 | }); 76 | } 77 | 78 | if (decimalDigits != null) { 79 | return `${integerDisplay}.${decimalDigits}`; 80 | } 81 | 82 | return integerDisplay; 83 | } 84 | 85 | updateDisplay() { 86 | this.currentOperandTextElement.innerText = this.getDisplayNumber(this.currentOperand); 87 | if (this.operation != null) { 88 | this.previousOperandTextElement.innerText = `${this.getDisplayNumber(this.previousOperand)} ${this.operation}`; 89 | } else { 90 | this.previousOperandTextElement.innerText = ''; 91 | } 92 | } 93 | } 94 | 95 | const numberButtons = document.querySelectorAll('[data-number]'); 96 | const operationButtons = document.querySelectorAll('[data-operation]'); 97 | const equalsButton = document.querySelector('[data-equals]'); 98 | const deleteButton = document.querySelector('[data-delete]'); 99 | const allClearButton = document.querySelector('[data-all-clear]'); 100 | const previousOperandTextElement = document.querySelector('[data-previous-operand]'); 101 | const currentOperandTextElement = document.querySelector('[data-current-operand]'); 102 | 103 | const calculator = new Calculator(previousOperandTextElement, currentOperandTextElement); 104 | 105 | numberButtons.forEach((button) => { 106 | button.addEventListener('click', () => { 107 | calculator.appendNumber(button.innerText); 108 | calculator.updateDisplay(); 109 | }); 110 | }); 111 | 112 | operationButtons.forEach((button) => { 113 | button.addEventListener('click', () => { 114 | calculator.chooseOperation(button.innerText); 115 | calculator.updateDisplay(); 116 | }); 117 | }); 118 | 119 | equalsButton.addEventListener('click', () => { 120 | calculator.compute(); 121 | calculator.updateDisplay(); 122 | }); 123 | 124 | allClearButton.addEventListener('click', () => { 125 | calculator.clear(); 126 | calculator.updateDisplay(); 127 | }); 128 | 129 | deleteButton.addEventListener('click', () => { 130 | calculator.delete(); 131 | calculator.updateDisplay(); 132 | }); 133 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Calculator 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 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | *, 2 | *::before, 3 | *::after { 4 | box-sizing: border-box; 5 | font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 6 | 'Helvetica Neue', sans-serif; 7 | font-weight: normal; 8 | } 9 | 10 | body { 11 | padding: 0; 12 | margin: 0; 13 | background: linear-gradient(to right, #00aaff, #00ff6c); 14 | } 15 | 16 | .calculator-grid { 17 | display: grid; 18 | justify-content: center; 19 | align-content: center; 20 | min-height: 100vh; 21 | grid-template-columns: repeat(4, 100px); 22 | grid-template-rows: minmax(120px, auto) repeat(5, 100px); 23 | } 24 | 25 | .calculator-grid > button { 26 | cursor: pointer; 27 | font-size: 2rem; 28 | border: 1px solid white; 29 | outline: none; 30 | background-color: rgba(255, 255, 255, 0.75); 31 | } 32 | 33 | .calculator-grid > button:hover { 34 | background-color: rgba(255, 255, 255, 0.9); 35 | } 36 | 37 | .span-two { 38 | grid-column: span 2; 39 | } 40 | 41 | .output { 42 | grid-column: 1 / -1; 43 | background-color: rgba(0, 0, 0, 0.75); 44 | display: flex; 45 | align-items: flex-end; 46 | justify-content: space-around; 47 | flex-direction: column; 48 | padding: 10px; 49 | word-wrap: break-word; 50 | word-break: break-all; 51 | } 52 | 53 | .output .previous-operand { 54 | color: rgba(255, 255, 255, 0.75); 55 | font-size: 1.5rem; 56 | } 57 | 58 | .output .current-operand { 59 | color: white; 60 | font-size: 2.5rem; 61 | } 62 | --------------------------------------------------------------------------------