Reputation: 63
This is a live demo of my calculator: https://kepplin.github.io/odin-calculator/
After the equals button is pressed and the calculation is displayed, if a number button is pressed, then instead of starting a new calculation, the calculator evaluates with the operator of the previous calculation.
I have 3 global variables: num1, num2, operator. As well as a previous display and current display.
Example of the problem (step-by-step):
12
console.log(num1) // 12
console.log(num2) //
console.log(operator) //
12 +
console.log(num1) //
console.log(num2) // 12
console.log(operator) // +
12 + 4
console.log(num1) // 4
console.log(num2) // 12
console.log(operator) // +
After the '=' button is pressed, the calculator displays:
16
console.log(num1) //
console.log(num2) // 16
console.log(operator) // +
The calculator immediately evaluates if there are values for num1, num2, and operator. The problem comes here, if the user wants to start a different calculation (e.g, 5 - 4):
5
console.log(num1) // 5
console.log(num2) // 16
console.log(operator) // +
5 -
console.log(num1) //
console.log(num2) // 21
console.log(operator) // -
The calculator did 5 + 16. I want the values of num1, num2 and operator to be reset back to ' ' if a number button is pressed after the calculator has evaluated (only for a number button not an operator button).
An example of the behaviour I want is this:
https://mike-monta.github.io/calculator-pro/
https://github.com/Mike-Monta/calculator-pro
Here's my code:
<!DOCTYPE html>
<html lang="en">
<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>Calculator</title>
<link rel="stylesheet" href="style.css">
<link rel="icon" type="image/x-icon" href="img/favicon.ico">
</head>
<body>
<div class="calcBody">
<div class="calcDisplay">
<div class="screenDisplay">
<div class="prevDisplay"></div>
<div class="currentDisplay">0</div>
</div>
</div>
<div class="buttonsBody">
<div class="numberButtons">
<!--Row 1-->
<button class="clearButton inputButton" data-all="AC"><span class="buttonsText">AC</span></button>
<button class="deleteButton inputButton" data-all="C"><span class="buttonsText">C</span></button>
<button class="percentButton inputButton" data-all="%" data-operator="%"><span class="buttonsText">%</span></button>
<button class="divideButton inputButton" data-all="÷" data-operator="÷"><span class="buttonsText">÷</span></button>
<!--Row 2-->
<button class="sevenButton inputButton" data-all="7" data-num="7"><span class="buttonsText">7</span></button>
<button class="eightButton inputButton" data-all="8" data-num="8"><span class="buttonsText">8</span></button>
<button class="nineButton inputButton" data-all="9" data-num="9"><span class="buttonsText">9</span></button>
<button class="multiplyButton inputButton" data-all="×" data-operator="×"><span class="buttonsText">×</span></button>
<!--Row 3-->
<button class="fourButton inputButton" data-all="4" data-num="4"><span class="buttonsText">4</span></button>
<button class="fiveButton inputButton" data-all="5" data-num="5"><span class="buttonsText">5</span></button>
<button class="sixButton inputButton" data-all="6" data-num="6"><span class="buttonsText">6</span></button>
<button class="minusButton inputButton" data-all="-" data-operator="-"><span class="buttonsText">-</span></button>
<!--Row 4-->
<button class="oneButton inputButton" data-all="1" data-num="1"><span class="buttonsText">1</span></button>
<button class="twoButton inputButton" data-all="2" data-num="2"><span class="buttonsText">2</span></button>
<button class="threeButton inputButton" data-all="3" data-num="3"><span class="buttonsText">3</span></button>
<button class="plusButton inputButton" data-all="+" data-operator="+"><span class="buttonsText">+</span></button>
<!--Row 5 -->
<button class="doubleZeroButton inputButton" data-all="00" data-num="00"><span class="buttonsText">00</span></button>
<button class="zeroButton inputButton" data-all="0" data-num="0"><span class="buttonsText">0</span></button>
<button class="decimalButton inputButton" data-all="."><span class="buttonsText">.</span></button>
<button class="equalsButton inputButton" data-all="="><span class="buttonsText">=</span></button>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
const prevDisplay = document.querySelector('.prevDisplay');
const currentDisplay = document.querySelector('.currentDisplay');
const inputButton = document.querySelectorAll('.inputButton');
const divideButton = document.querySelector('.divideButton');
const equalsButton = document.querySelector('.equalsButton');
const operatorButton = document.querySelectorAll('[data-operator]');
const numberButton = document.querySelectorAll('[data-num]');
const clearButton = document.querySelector('.clearButton');
const deleteButton = document.querySelector('.deleteButton');
const decimalButton = document.querySelector('.decimalButton')
//Global variables
let num1 = "";
let operator = "";
let num2 = "";
let removeDot;
//Current display
numberButton.forEach((btn) => {
btn.addEventListener('click', (e) => {
handleNumber(e.target.textContent);
})
}
)
function handleNumber(number){
if (num1.length <= 21){
num1 += number;
currentDisplay.textContent = num1;
}
}
//Previous display
operatorButton.forEach((btn) => {
btn.addEventListener('click', (e) => {
handleOperator(e.target.textContent);
})
})
function handleOperator(op){
if (num1 == '' && num2 == ''){
num1 = '0';
}
else if (operator == '' && num2 !== ''){
num2 = ''
}
else if (num2 === "") {
num2 = num1;
operatorCheck(op);
} else if (num1 === "") {
operatorCheck(op);
} else {
operate();
operator = op;
currentDisplay.textContent = "0";
prevDisplay.textContent = num2 + " " + operator;
}
}
function operatorCheck(text) {
operator = text;
prevDisplay.textContent = num2 + " " + operator;
currentDisplay.textContent = "0";
num1 = "";
}
//Clear button
function clearCalc(){
prevDisplay.textContent = '';
currentDisplay.textContent = '';
num1 = '';
num2 = '';
operator = '';
}
clearButton.addEventListener('click', clearCalc)
//Delete button
function deleteCalc(){
num1 = num1.slice(0, currentDisplay.textContent.length - 1)
currentDisplay.textContent = currentDisplay.textContent.slice(0, currentDisplay.textContent.length - 1)
}
deleteButton.addEventListener('click', deleteCalc)
//Equals button
function equalsCalc(){
if (num1 != '' && num2 != ''){
operate()
}
}
equalsButton.addEventListener('click', equalsCalc)
//Decimal button
function decimalCalc(){
if (num1.includes('.') == false){
currentDisplay.textContent = currentDisplay.textContent + '.'
num1 = num1 + '.'
}
}
decimalButton.addEventListener('click', decimalCalc)
//Doing the calculation
function calcPercent(num1, num2){
return (num2 / 100) * num1
}
function calcDivide(num1, num2){
return num2 / num1
}
function calcMultiply(num1, num2){
return num1 * num2
}
function calcSubtract(num1, num2){
return num2 - num1
}
function calcAdd(num1, num2){
return num1 + num2
}
function operate() {
num1 = Number(num1)
num2 = Number(num2)
switch (operator) {
case '+':
num2 = calcAdd(num1, num2)
break
case '-':
num2 = calcSubtract(num1, num2)
break
case '×':
num2 = calcMultiply(num1, num2)
break
case '%':
num2 = calcPercent(num1, num2)
break
case '÷':
num2 = num2.toString();
if (num1 == 0){
num2 = "Error, you can't divide by 0"
} else{
num2 = calcDivide(num1, num2);
}
break
}
num2 = roundNum(num2)
prevDisplay.textContent = "";
currentDisplay.textContent = num2;
num1 = '';
}
//Round Number
function roundNum(num){
return Math.round(num * 1000000) / 1000000;
}
//Event listeners for key presses
window.addEventListener('keydown', removeDot = function(e){
switch (e.key){
case "7":
handleNumber(7)
break
case "8":
handleNumber(8)
break
case "9":
handleNumber(9)
break
case "4":
handleNumber(4)
break
case "5":
handleNumber(5)
break
case "6":
handleNumber(6)
break
case "1":
handleNumber(1)
break
case "2":
handleNumber(2)
break
case "3":
handleNumber(3)
break
case "0":
handleNumber(0)
break
case ")":
handleNumber(00)
break
case "Delete":
clearCalc();
break
case "+":
handleOperator('+')
break
case "-":
handleOperator('-')
break
case "*":
handleOperator('×')
break
case "/":
handleOperator('÷')
break
case "%":
handleOperator('%')
break
case ".":
decimalCalc();
break
case "Backspace":
deleteCalc();
break
case "Enter":
e.preventDefault();
equalsCalc();
break
}
}, true)
Upvotes: 2
Views: 463
Reputation: 2340
I think I would generally have a different approach BUT...
A simple solution would be to capture the =
as an operator, and check for it's presence in the handleNumber
method. If it is the current operator, just clear num2
.
...
function handleNumber(number) {
if (num1.length <= 21) {
num1 += number;
currentDisplay.textContent = num1;
}
if (operator === '=') { // <-- Added
num2 = ''
}
}
...
function equalsCalc() {
if (num1 != '' && num2 != '') {
operate()
operator = '=' // <-- Added
}
}
...
const prevDisplay = document.querySelector('.prevDisplay');
const currentDisplay = document.querySelector('.currentDisplay');
const inputButton = document.querySelectorAll('.inputButton');
const divideButton = document.querySelector('.divideButton');
const equalsButton = document.querySelector('.equalsButton');
const operatorButton = document.querySelectorAll('[data-operator]');
const numberButton = document.querySelectorAll('[data-num]');
const clearButton = document.querySelector('.clearButton');
const deleteButton = document.querySelector('.deleteButton');
const decimalButton = document.querySelector('.decimalButton')
//Global variables
let num1 = "";
let operator = "";
let num2 = "";
let removeDot;
//Current display
numberButton.forEach((btn) => {
btn.addEventListener('click', (e) => {
handleNumber(e.target.textContent);
})
})
function handleNumber(number) {
console.log('handleNumber', num1, operator, num2, '->', number)
if (num1.length <= 21) {
num1 += number;
currentDisplay.textContent = num1;
}
if (operator === '=') {
num2 = ''
}
console.log('handleNumber END', num1, operator, num2)
}
//Previous display
operatorButton.forEach((btn) => {
btn.addEventListener('click', (e) => {
handleOperator(e.target.textContent);
})
})
function handleOperator(op) {
console.log('handleOperator', num1, operator, num2, '->', op)
if (num1 == '' && num2 == '') {
num1 = '';
} else if (operator == '' && num2 !== '') {
num2 = ''
} else if (num2 === "") {
num2 = num1;
operatorCheck(op);
} else if (num1 === "") {
operatorCheck(op);
} else {
operate();
operator = op;
currentDisplay.textContent = "0";
prevDisplay.textContent = num2 + " " + operator;
}
console.log('handleOperator END', num1, operator, num2)
}
function operatorCheck(text) {
operator = text;
prevDisplay.textContent = num2 + " " + operator;
currentDisplay.textContent = "0";
num1 = "";
}
//Clear button
function clearCalc() {
prevDisplay.textContent = '';
currentDisplay.textContent = '';
num1 = '';
num2 = '';
operator = '';
}
clearButton.addEventListener('click', clearCalc)
//Delete button
function deleteCalc() {
num1 = num1.slice(0, currentDisplay.textContent.length - 1)
currentDisplay.textContent = currentDisplay.textContent.slice(0, currentDisplay.textContent.length - 1)
}
deleteButton.addEventListener('click', deleteCalc)
//Equals button
function equalsCalc() {
if (num1 != '' && num2 != '') {
operate()
console.log('equalsCalc END', num1, operator, num2)
operator = '='
}
}
equalsButton.addEventListener('click', equalsCalc)
//Decimal button
function decimalCalc() {
if (num1.includes('.') == false) {
currentDisplay.textContent = currentDisplay.textContent + '.'
num1 = num1 + '.'
}
}
decimalButton.addEventListener('click', decimalCalc)
//Doing the calculation
function calcPercent(num1, num2) {
return (num2 / 100) * num1
}
function calcDivide(num1, num2) {
return num2 / num1
}
function calcMultiply(num1, num2) {
return num1 * num2
}
function calcSubtract(num1, num2) {
return num2 - num1
}
function calcAdd(num1, num2) {
return num1 + num2
}
function operate() {
num1 = Number(num1)
num2 = Number(num2)
switch (operator) {
case '+':
num2 = calcAdd(num1, num2)
break
case '-':
num2 = calcSubtract(num1, num2)
break
case '×':
num2 = calcMultiply(num1, num2)
break
case '%':
num2 = calcPercent(num1, num2)
break
case '÷':
num2 = num2.toString();
if (num1 == 0) {
num2 = "Error, you can't divide by 0"
} else {
num2 = calcDivide(num1, num2);
}
break
}
num2 = roundNum(num2)
prevDisplay.textContent = "";
currentDisplay.textContent = num2;
num1 = '';
}
//Round Number
function roundNum(num) {
return Math.round(num * 1000000) / 1000000;
}
//Event listeners for key presses
window.addEventListener('keydown', removeDot = function(e) {
switch (e.key) {
case "7":
handleNumber(7)
break
case "8":
handleNumber(8)
break
case "9":
handleNumber(9)
break
case "4":
handleNumber(4)
break
case "5":
handleNumber(5)
break
case "6":
handleNumber(6)
break
case "1":
handleNumber(1)
break
case "2":
handleNumber(2)
break
case "3":
handleNumber(3)
break
case "0":
handleNumber(0)
break
case ")":
handleNumber(00)
break
case "Delete":
clearCalc();
break
case "+":
handleOperator('+')
break
case "-":
handleOperator('-')
break
case "*":
handleOperator('×')
break
case "/":
handleOperator('÷')
break
case "%":
handleOperator('%')
break
case ".":
decimalCalc();
break
case "Backspace":
deleteCalc();
break
case "Enter":
e.preventDefault();
equalsCalc();
break
}
}, true)
html,
body {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
padding: 0;
margin: 0;
}
.calcBody {
display: flex;
background-color: rgb(160, 160, 160);
width: 500px;
height: 700px;
border: 2px solid black;
border-radius: 35px;
padding-bottom: 25px;
transform: scale(0.95, 1);
}
.calcDisplay {
display: flex;
height: 200px;
width: 500px;
position: absolute;
justify-content: center;
border-radius: 30px;
}
.screenDisplay {
display: flex;
align-self: center;
background-color: rgb(248, 248, 248);
width: 450px;
height: 150px;
justify-content: flex-end;
border-radius: 45px;
border: 2px solid black;
}
.prevDisplay {
display: flex;
justify-content: flex-end;
align-items: flex-start;
width: 85%;
height: 50px;
position: absolute;
margin-top: 50px;
margin-right: 25px;
font-family: Verdana, Geneva, Tahoma, sans-serif;
font-size: 20px;
margin-bottom: 20px;
}
.currentDisplay {
display: flex;
align-self: flex-end;
justify-self: end;
height: 50px;
width: 100%;
justify-content: flex-end;
margin-right: 25px;
font-family: Verdana, Geneva, Tahoma, sans-serif;
font-size: 30px;
margin-bottom: 20px;
}
.buttonsBody {
display: flex;
width: 100%;
height: 500px;
align-self: flex-end;
justify-content: center;
}
.numberButtons {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr 1fr 1fr;
width: 450px;
height: 500px;
gap: 5px;
}
.inputButton {
padding: 0px;
margin: 0px;
border: 2px solid black;
border-radius: 20px;
transition: 200ms;
background-color: rgb(231, 231, 231);
}
.buttonsText {
padding: 0;
margin: 0;
font-size: 20px;
font-family: Verdana, Geneva, Tahoma, sans-serif;
transition: 150ms;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
width: 100%;
}
.inputButton:hover {
background-color: darkgray;
cursor: pointer;
}
.buttonsText:hover {
font-size: 30px;
}
.clearButton,
.deleteButton {
background-color: rgb(223, 145, 145);
}
.equalsButton {
background-color: rgb(187, 238, 110);
}
<div class="calcBody">
<div class="calcDisplay">
<div class="screenDisplay">
<div class="prevDisplay"></div>
<div class="currentDisplay"></div>
</div>
</div>
<div class="buttonsBody">
<div class="numberButtons">
<!--Row 1-->
<button class="clearButton inputButton" data-all="AC"><span class="buttonsText">AC</span></button>
<button class="deleteButton inputButton" data-all="C"><span class="buttonsText">C</span></button>
<button class="percentButton inputButton" data-all="%" data-operator="%"><span class="buttonsText">%</span></button>
<button class="divideButton inputButton" data-all="÷" data-operator="÷"><span class="buttonsText">÷</span></button>
<!--Row 2-->
<button class="sevenButton inputButton" data-all="7" data-num="7"><span class="buttonsText">7</span></button>
<button class="eightButton inputButton" data-all="8" data-num="8"><span class="buttonsText">8</span></button>
<button class="nineButton inputButton" data-all="9" data-num="9"><span class="buttonsText">9</span></button>
<button class="multiplyButton inputButton" data-all="×" data-operator="×"><span class="buttonsText">×</span></button>
<!--Row 3-->
<button class="fourButton inputButton" data-all="4" data-num="4"><span class="buttonsText">4</span></button>
<button class="fiveButton inputButton" data-all="5" data-num="5"><span class="buttonsText">5</span></button>
<button class="sixButton inputButton" data-all="6" data-num="6"><span class="buttonsText">6</span></button>
<button class="minusButton inputButton" data-all="-" data-operator="-"><span class="buttonsText">-</span></button>
<!--Row 4-->
<button class="oneButton inputButton" data-all="1" data-num="1"><span class="buttonsText">1</span></button>
<button class="twoButton inputButton" data-all="2" data-num="2"><span class="buttonsText">2</span></button>
<button class="threeButton inputButton" data-all="3" data-num="3"><span class="buttonsText">3</span></button>
<button class="plusButton inputButton" data-all="+" data-operator="+"><span class="buttonsText">+</span></button>
<!--Row 5 -->
<button class="doubleZeroButton inputButton" data-all="00" data-num="00"><span class="buttonsText">00</span></button>
<button class="zeroButton inputButton" data-all="0" data-num="0"><span class="buttonsText">0</span></button>
<button class="decimalButton inputButton" data-all="."><span class="buttonsText">.</span></button>
<button class="equalsButton inputButton" data-all="="><span class="buttonsText">=</span></button>
</div>
</div>
</div>
Upvotes: 2
Reputation: 11
You can clear num2 after new number has been clicked. typeof num2 !== 'string'
checks if it was operated before.
function handleNumber(number) {
if (typeof num2 !== 'string' && operator === '') num2 = ''; // Add this line
if (num1.length <= 21) {
num1 += number;
currentDisplay.textContent = num1;
}
}
Upvotes: 0