Author: | erekkles |
---|---|
Views Total: | 2,427 views |
Official Page: | Go to website |
Last Update: | November 9, 2021 |
License: | MIT |
Preview:

Description:
An iOS-like web calculator created using plain JavaScript and CSS.
- AC or C Clear the last input
- +/- Assign the additive inverse
- % Find the 1% of the last input
- ÷ Division operator
- x Multiplication operator
- – Minus operator
- + Plus operator
- = Equals operator
How to use it:
1. Build the HTML for the iOS calculator.
<div class="calculator"> <div class="screen"> 0 </div> <div class="keyboard"> <div class="row"> <div class="sub-col" data-button-type="operator" data-value="clear" id="clear_button">AC</div> <div class="sub-col" data-button-type="operator" data-value="+/-">+/-</div> <div class="sub-col" data-button-type="operator" data-value="%">%</div> <div class="sub-col" data-button-type="operator" data-value="/">÷</div> </div> <div class="row"> <div class="sub-col" data-button-type="digit" data-value="7">7</div> <div class="sub-col" data-button-type="digit" data-value="8">8</div> <div class="sub-col" data-button-type="digit" data-value="9">9</div> <div class="sub-col" data-button-type="operator" data-value="*">x</div> </div> <div class="row"> <div class="sub-col" data-button-type="digit" data-value="4">4</div> <div class="sub-col" data-button-type="digit" data-value="5">5</div> <div class="sub-col" data-button-type="digit" data-value="6">6</div> <div class="sub-col" data-button-type="operator" data-value="-">-</div> </div> <div class="row"> <div class="sub-col" data-button-type="digit" data-value="1">1</div> <div class="sub-col" data-button-type="digit" data-value="2">2</div> <div class="sub-col" data-button-type="digit" data-value="3">3</div> <div class="sub-col" data-button-type="operator" data-value="+">+</div> </div> <div class="row"> <div class="sub-col" data-button-type="digit" data-value="0">0</div> <div class="sub-col" data-button-type="digit" data-value=".">,</div> <div class="sub-col" data-button-type="operator" data-value="=">=</div> </div> </div> </div>
2. The required CSS styles.
.calculator { display: flex; flex-direction: column; min-height: 500px; min-width: 290px; font-size: 1.3rem; } .calculator .screen { display: flex; justify-content: end; align-items: flex-end; padding: 0 0 15px 0; font-size: 5.5rem; width: 290px; height: 150px; overflow-x: hidden; } .calculator .keyboard { width: 290px; height: 350px; } /* first row */ .keyboard .row:first-child .sub-col:not(:last-child) { background-color: var(--function-keys); color: var(--background-color); } .keyboard .row:first-child .sub-col:last-child { background-color: var(--operator-keys); color: #ffffff; } /* second row, third row, fourth row and fifth row */ .keyboard .row:nth-child(2) .sub-col:not(:last-child), .keyboard .row:nth-child(3) .sub-col:not(:last-child), .keyboard .row:nth-child(4) .sub-col:not(:last-child), .keyboard .row:nth-child(5) .sub-col:not(:last-child) { background-color: var(--digit-keys); color: #ffffff; } .keyboard .row:nth-child(2) .sub-col:last-child, .keyboard .row:nth-child(3) .sub-col:last-child, .keyboard .row:nth-child(4) .sub-col:last-child, .keyboard .row:nth-child(5) .sub-col:last-child { background-color: var(--operator-keys); color: #ffffff; } .selected_operation[data-value='clear'], .selected_operation[data-value='%'], .selected_operation[data-value='+/-'] { animation: background-anim-fn .8s ease-out; } .selected_operation[data-value='='] { animation: background-anim-equals .8s ease-out; } /* Select every operator button except clear, %, +/- and = */ .selected_operation[data-button-type='operator']:not(.selected_operation[data-value='clear']):not(.selected_operation[data-value='%']):not(.selected_operation[data-value='+/-']):not(.selected_operation[data-value='=']) { background-color: #d4d4d2; color: var(--operator-keys); transition: background-color, color .8s ease-out; } @keyframes background-anim-fn { 0% { background-color: var(--function-keys); } 50% { background-color: #fff; } 100% { background-color: var(--function-keys); } } @keyframes background-anim-equals { 0% { background-color: var(--operator-keys); } 50% { background-color: #fff; } 100% { background-color: var(--operator-keys); } } .flex-center { justify-content: center; align-items: center; } .sub-col { display: flex; justify-content: center; align-items: center; width: 21%; height: 86%; -webkit-box-flex: 0; -ms-flex: 0 0 21%; flex: 0 0 21%; max-width: 21%; border-radius: 50%; transition: background-color .8s ease-out; } .row:last-child > .sub-col:first-child { display: flex; justify-content: start; padding-left: 25px; width: 47%; -ms-flex: 0 0 47%; flex: 0 0 47%; max-width: 47%; border-radius: 100px 100px 100px 100px; transition: background-color .8s ease-out; } .keyboard .row { justify-content: space-between; height: 20%; } @media only screen and (min-width: 1500px) { .calculator { min-height: calc(500px / .7); min-width: calc(290px / .7); font-size: 1.7rem; } .calculator .screen { display: flex; justify-content: end; align-items: flex-end; padding: 0 0 15px 0; font-size: 7rem; width: calc(290px / .7); height: calc(150px / .7); overflow-x: hidden; } .calculator .keyboard { width: calc(290px / .7); height: calc(350px / .7); } }
3. The main script for the calculator logic.
let first_number = "0"; let second_number = "0"; let result = "0"; let current_operator; let evaluation = []; const screen = document.querySelector(".screen"); const keyboard = document.querySelector(".keyboard"); keyboard.addEventListener('click', function(e) { e.stopImmediatePropagation() onButtonPress(e); }); function onButtonPress (e) { switch(e.target.getAttribute('data-button-type')) { case "digit": AssignNumber(e) break; case "operator": AssignOperation(e) break; } Render(e); } function AssignNumber(e) { if(evaluation.length <= 1) { first_number = first_number == "0" ? e.target.getAttribute("data-value") : first_number + e.target.getAttribute("data-value") if(evaluation.length == 1) evaluation.shift(); evaluation.push(first_number) result = first_number; return; } if (evaluation.length >= 2) { second_number = second_number == "0" ? e.target.getAttribute("data-value") : second_number + e.target.getAttribute("data-value"); if(evaluation.length == 3) evaluation.pop(); evaluation.push(second_number); result = second_number; } } function AssignOperation(e) { current_operator = e.target.getAttribute('data-value'); // Exclusive operations that can be performed with one number, in the case of clear it can be executed even when the evaluation array is empty if(current_operator == "%" || current_operator == "+/-" || current_operator == "clear" || current_operator == "=") return Operate(); if(evaluation.length == 3) Operate(); if(evaluation.length == 2) evaluation.pop(); evaluation.splice(1, 1, current_operator); } function Operate() { if(current_operator == "%" && evaluation.length) { let number = parseInt(evaluation[evaluation.length - 1]) result = (number / 100).toString(); evaluation.splice(evaluation.length - 1, 1, result); return; } if(current_operator == "+/-" && evaluation.length) { result = (evaluation[evaluation.length - 1] * -1).toString(); evaluation.splice(evaluation.length - 1, 1, result); return; } if(current_operator == "clear") { if(evaluation.length <= 2) { first_number = "0"; evaluation = []; result = "0"; return; } if(evaluation.length == 3) { second_number = "0"; evaluation = [first_number.toString()] result = first_number.toString(); return; } } if(evaluation.length == 3) { result = (eval(evaluation.join().replace(/,/g, ""))).toString(); first_number = result; second_number = "0"; evaluation = [first_number] } } function Render(e) { const clear_button = document.querySelector('div[data-value="clear"]'); let new_operator_button = e.target; let last_operator_button = document.querySelector('.selected_operation'); last_operator_button ? last_operator_button.classList.remove('selected_operation') : null; new_operator_button ? new_operator_button.classList.add('selected_operation') : null; // change screen's font-size switch(result.toString().length) { case 7: screen.style.fontSize = "4.7rem" break; case 8: screen.style.fontSize = "4.1rem" break; case 9: screen.style.fontSize = "3.65rem" break } if(result.toString().length > 9) { screen.textContent = parseFloat(result).toPrecision(3); } else { screen.textContent = result; } evaluation.length == "0" ? clear_button.textContent = 'AC' : clear_button.textContent = 'C' }