I am creating a calculator app using HTML, CSS, and JS as my stack.
When the user attempts to inputs a number, the behavior of the calculator is fine with single-digit arithmetic. However, as soon as the user attempts to input any number longer than two digits, the calculator drops all of the digits except for the first of both numbers and then proceeds to execute the arithmetic.
// Initializing all variables
const currentDisplay = document.querySelector(".current");
const previousDisplay = document.querySelector(".previous");
const numberButtons = document.querySelectorAll('[data-number]');
const operationButtons = document.querySelectorAll('[data-operation]');
const clearButton = document.querySelector(".clear");
const deleteButton = document.querySelector(".delete");
const enterButton = document.querySelector(".enter");
const pointButton = document.querySelector(".point");
let firstNumber;
let secondNumber;
let operand;
let answer;
// Adding event listeners to all buttons
clearButton.addEventListener('click', clearAll);
enterButton.addEventListener('click', enter);
numberButtons.forEach(button =>
button.addEventListener('click', () => {
/*
Checks if firstNumber is assigned yet.
If firstNumber & operand is undefined, just assign value of button to firstNumber.
If firstNumber has a value assigned and the operand is undefined, that means they pressed a number button already, append and reassign to firstNumber.
If secondNumber and operand is defined, then we know the user is appending to the secondNumber
Else they are just beginning to type their secondNumber.
*/
if (isUndefined(firstNumber) && isUndefined(operand)) {
firstNumber = parseFloat(button.textContent);
currentDisplay.textContent = firstNumber;
console.log("Case 1: firstNumber: " + firstNumber);
} else if (!isUndefined(firstNumber) && isUndefined(operand)) {
appendToCurrent(button.textContent);
firstNumber = parseFloat(currentDisplay.textContent);
console.log("Case 2: firstNumber: " + firstNumber);
} else if (!isUndefined(secondNumber) && !isUndefined(operand)) {
appendToCurrent(button.textContent);
secondNumber = parseFloat(currentDisplay.textContent);
console.log("Case 1: secondNumber: " + secondNumber);
} else {
secondNumber = parseFloat(button.textContent);
currentDisplay.textContent = secondNumber;
console.log("Case 2: secondNumber: " + secondNumber);
}
}));
operationButtons.forEach(button =>
button.addEventListener('click', () => {
/*
Checks if there is the operand & firstNumber has been assigned yet.
If both the operand and firstNumber is undefined, then they are trying to do some sort of arithemtic with zero (aka the starting value).
If the operand is undefined but the firstNumber isn't, that means the user has finished inputting their number and are moving onto an arithmetic operation.
*/
if (isUndefined(operand) && !isUndefined(firstNumber)) {
operand = button.textContent;
appendToPrevious(button.textContent);
}
if (isUndefined(operand) && isUndefined(firstNumber)) {
operand = button.textContent;
appendToPrevious(button.textContent);
}
}));
function appendToCurrent(number) {
currentDisplay.textContent += number
}
function appendToPrevious(op) {
/*
Takes in a button (which contains the operand) and assigns it to the 'operand' variable. Moves currentDisplay to previousDisplay while appending the operand to it. Afterwards, clear the currentDisplay readying it for new user input.
*/
previousDisplay.textContent = currentDisplay.textContent;
previousDisplay.textContent += op;
clear(currentDisplay);
}
function isUndefined(variable) {
return variable === undefined;
}
function del() {
}
function enter() {
console.log(operand + (typeof operand));
switch (operand.trim()) {
case "+":
console.log("Case: Addition");
answer = add(firstNumber, secondNumber);
previousDisplay.textContent = firstNumber + operand + secondNumber;
currentDisplay.textContent = answer;
break;
case "-":
console.log("Case: Subtraction");
previousDisplay.textContent = firstNumber + operand + secondNumber;
answer = subtract(firstNumber, secondNumber);
currentDisplay.textContent = answer;
break;
case "/":
console.log("Case: Division");
previousDisplay.textContent = firstNumber + operand + secondNumber;
answer = divide(firstNumber, secondNumber);
currentDisplay.textContent = answer;
break;
case "*":
console.log("Case: Multiplication");
previousDisplay.textContent = firstNumber + operand + secondNumber;
answer = multiply(firstNumber, secondNumber);
currentDisplay.textContent = answer;
break;
default:
console.log("Case: Default");
previousDisplay.textContent = firstNumber + operand + secondNumber;
break;
}
}
function clearAll() {
currentDisplay.textContent = 0;
previousDisplay.textContent = ' ';
firstNumber = undefined;
secondNumber = undefined;
operand = undefined;
console.clear();
}
function clear(display) {
display.textContent = ' ';
}
function add(x, y) {
return x + y;
}
function subtract(x, y) {
return x - y;
}
function multiply(x, y) {
return x * y;
}
function divide (x, y) {
return x / y;
}
/* #EEC61F */
* {
padding: 0;
margin: 0;
font-family: 'Fira Code';
}
head {
display: none;
}
body {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: lightgray;
}
/* Main app */
.app {
display: flex;
align-items: center;
justify-content: center;
height: 500px;
padding: 20px;
}
.calculator {
width: 400px;
border: 2px solid black;
border-radius: 10px;
padding: 20px;
background-color: gray;
}
.display {
background-color: whitesmoke;
text-align: right;
word-break: break-all;
padding: 10px 20px;
margin-bottom: 30px;
border: 1.5px solid black;
border-radius: 10px;
}
.current {
padding: 10px;
font-size: 2em;
}
.previous {
padding: 10px;
font-size: 1em;
}
.buttons {
display: grid;
grid-template-columns: repeat(4, 2fr);
gap: 20px;
}
#button {
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
border: 1px solid black;
border-radius: 3px;
background-color: whitesmoke;
}
.zero {
grid-column-start: 1;
grid-column-end: 3;
grid-row-start: 5;
grid-row-end: 5;
}
.enter {
grid-column-start: 4;
grid-column-end: 4;
grid-row-start: 4;
grid-row-end: 6;
}
<!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">
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="https://fonts.google.com/specimen/Fira+Code?vfquery=fira">
<script src="script.js" defer></script>
<title>Calculator</title>
</head>
<body>
<div class="app">
<div class="calculator">
<div class="display">
<div class="previous"></div>
<div class="current">0</div>
</div>
<div class="buttons">
<button id="button" class="clear">
<h3> CLEAR </h3>
</button>
<button id="button" data-operation>
<h3> / </h3>
</button>
<button id="button" data-operation>
<h3> * </h3>
</button>
<button id="button" class="delete">
<h3> ⌫ </h3>
</button>
<button id="button" data-number>
<h3> 7 </h3>
</button>
<button id="button" data-number>
<h3> 8 </h3>
</button>
<button id="button" data-number>
<h3> 9 </h3>
</button>
<button id="button" data-operation="">
<h3> - </h3>
</button>
<button id="button" data-number>
<h3> 4 </h3>
</button>
<button id="button" data-number>
<h3> 5 </h3>
</button>
<button id="button" data-number>
<h3> 6 </h3>
</button>
<button id="button" data-operation>
<h3> + </h3>
</button>
<button id="button" data-number>
<h3> 1 </h3>
</button>
<button id="button" data-number>
<h3> 2 </h2>
</button>
<button id="button" data-number>
<h3> 3 </h3>
</button>
<button id="button" class="enter">
<h3> ENTER </h3>
</button>
<button id="button" class="zero" data-number>
<h3> 0 </h3>
</button>
<button id="button" class="point">
<h3> . </h3>
</button>
</div>
</div>
</div>
</body>
</html>
Your issue appears to be in the appendToCurrent() function. You need to trim the number parameter before you add it to the current number:
function appendToCurrent(number)
{
const newNumber = currentDisplay.textContent += number.trim()
return newNumber
}
// Initializing all variables
const currentDisplay = document.querySelector(".current");
const previousDisplay = document.querySelector(".previous");
const numberButtons = document.querySelectorAll('[data-number]');
const operationButtons = document.querySelectorAll('[data-operation]');
const clearButton = document.querySelector(".clear");
const deleteButton = document.querySelector(".delete");
const enterButton = document.querySelector(".enter");
const pointButton = document.querySelector(".point");
let firstNumber;
let secondNumber;
let operand;
let answer;
// Adding event listeners to all buttons
clearButton.addEventListener('click', clearAll);
enterButton.addEventListener('click', enter);
numberButtons.forEach(button =>
{
button.addEventListener('click', () =>
{
/*
Checks if firstNumber is assigned yet.
If firstNumber & operand is undefined, just assign value of button to firstNumber.
If firstNumber has a value assigned and the operand is undefined, that means they pressed a number button already, append and reassign to firstNumber.
If secondNumber and operand is defined, then we know the user is appending to the secondNumber
Else they are just beginning to type their secondNumber.
*/
if (isUndefined(firstNumber) && isUndefined(operand))
{
firstNumber = parseFloat(button.textContent);
currentDisplay.textContent = firstNumber;
}
else if (!isUndefined(firstNumber) && isUndefined(operand))
{
appendToCurrent(button.textContent);
firstNumber = parseFloat(currentDisplay.textContent);
}
else if (!isUndefined(secondNumber) && !isUndefined(operand))
{
appendToCurrent(button.textContent);
secondNumber = parseFloat(currentDisplay.textContent);
}
else
{
secondNumber = parseFloat(button.textContent);
currentDisplay.textContent = secondNumber;
}
})
})
operationButtons.forEach(button =>
button.addEventListener('click', () => {
/*
Checks if there is the operand & firstNumber has been assigned yet.
If both the operand and firstNumber is undefined, then they are trying to do some sort of arithemtic with zero (aka the starting value).
If the operand is undefined but the firstNumber isn't, that means the user has finished inputting their number and are moving onto an arithmetic operation.
*/
if (isUndefined(operand) && !isUndefined(firstNumber)) {
operand = button.textContent;
appendToPrevious(button.textContent);
}
if (isUndefined(operand) && isUndefined(firstNumber)) {
operand = button.textContent;
appendToPrevious(button.textContent);
}
}));
function appendToCurrent(number)
{
const newNumber = currentDisplay.textContent += number.trim()
return newNumber
}
function appendToPrevious(op) {
/*
Takes in a button (which contains the operand) and assigns it to the 'operand' variable. Moves currentDisplay to previousDisplay while appending the operand to it. Afterwards, clear the currentDisplay readying it for new user input.
*/
previousDisplay.textContent = currentDisplay.textContent;
previousDisplay.textContent += op;
clear(currentDisplay);
}
function isUndefined(variable) {
return variable === undefined;
}
function del() {
}
function enter() {
switch (operand.trim()) {
case "+":
answer = add(firstNumber, secondNumber);
previousDisplay.textContent = firstNumber + operand + secondNumber;
currentDisplay.textContent = answer;
break;
case "-":
previousDisplay.textContent = firstNumber + operand + secondNumber;
answer = subtract(firstNumber, secondNumber);
currentDisplay.textContent = answer;
break;
case "/":
previousDisplay.textContent = firstNumber + operand + secondNumber;
answer = divide(firstNumber, secondNumber);
currentDisplay.textContent = answer;
break;
case "*":
previousDisplay.textContent = firstNumber + operand + secondNumber;
answer = multiply(firstNumber, secondNumber);
currentDisplay.textContent = answer;
break;
default:
previousDisplay.textContent = firstNumber + operand + secondNumber;
break;
}
}
function clearAll() {
currentDisplay.textContent = 0;
previousDisplay.textContent = ' ';
firstNumber = undefined;
secondNumber = undefined;
operand = undefined;
console.clear();
}
function clear(display) {
display.textContent = ' ';
}
function add(x, y) {
return x + y;
}
function subtract(x, y) {
return x - y;
}
function multiply(x, y) {
return x * y;
}
function divide(x, y) {
return x / y;
}
/* #EEC61F */
* {
padding: 0;
margin: 0;
font-family: 'Fira Code';
}
head {
display: none;
}
body {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: lightgray;
}
/* Main app */
.app {
display: flex;
align-items: center;
justify-content: center;
height: 500px;
padding: 20px;
}
.calculator {
width: 400px;
border: 2px solid black;
border-radius: 10px;
padding: 20px;
background-color: gray;
}
.display {
background-color: whitesmoke;
text-align: right;
word-break: break-all;
padding: 10px 20px;
margin-bottom: 30px;
border: 1.5px solid black;
border-radius: 10px;
}
.current {
padding: 10px;
font-size: 2em;
}
.previous {
padding: 10px;
font-size: 1em;
}
.buttons {
display: grid;
grid-template-columns: repeat(4, 2fr);
gap: 20px;
}
#button {
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
border: 1px solid black;
border-radius: 3px;
background-color: whitesmoke;
}
.zero {
grid-column-start: 1;
grid-column-end: 3;
grid-row-start: 5;
grid-row-end: 5;
}
.enter {
grid-column-start: 4;
grid-column-end: 4;
grid-row-start: 4;
grid-row-end: 6;
}
<div class="app">
<div class="calculator">
<div class="display">
<div class="previous"></div>
<div class="current">0</div>
</div>
<div class="buttons">
<button id="button" class="clear">
<h3> CLEAR </h3>
</button>
<button id="button" data-operation>
<h3> / </h3>
</button>
<button id="button" data-operation>
<h3> * </h3>
</button>
<button id="button" class="delete">
<h3> ⌫ </h3>
</button>
<button id="button" data-number>
<h3> 7 </h3>
</button>
<button id="button" data-number>
<h3> 8 </h3>
</button>
<button id="button" data-number>
<h3> 9 </h3>
</button>
<button id="button" data-operation="">
<h3> - </h3>
</button>
<button id="button" data-number>
<h3> 4 </h3>
</button>
<button id="button" data-number>
<h3> 5 </h3>
</button>
<button id="button" data-number>
<h3> 6 </h3>
</button>
<button id="button" data-operation>
<h3> + </h3>
</button>
<button id="button" data-number>
<h3> 1 </h3>
</button>
<button id="button" data-number>
<h3> 2 </h2>
</button>
<button id="button" data-number>
<h3> 3 </h3>
</button>
<button id="button" class="enter">
<h3> ENTER </h3>
</button>
<button id="button" class="zero" data-number>
<h3> 0 </h3>
</button>
<button id="button" class="point">
<h3> . </h3>
</button>
</div>
</div>
</div>
Related
let operator = "";
let currentValue = "";
let previousValue = "";
document.addEventListener("DOMContentLoaded", () => {
let clear = document.querySelector("#clear-btn");
let equal = document.querySelector(".equal");
let decimal = document.querySelector(".decimal");
let numbers = document.querySelectorAll(".number");
let operators = document.querySelectorAll(".operator");
let previousScreen = document.querySelector(".previous");
let currentScreen = document.querySelector(".current");
numbers.forEach((number) => {
number.addEventListener("click", (e) => {
handleNumber(e.target.textContent);
currentScreen.textContent = currentValue;
});
});
operators.forEach((op) => {
op.addEventListener("click", (e) => {
handleOperator(e.target.textContent);
previousScreen.textContent = previousValue + " " + operator;
currentScreen.textContent = currentValue;
});
});
clear.addEventListener("click", () => {
operator = "";
currentValue = "";
previousValue = "";
previousScreen.textContent = currentValue;
currentScreen.textContent = currentValue;
});
equal.addEventListener("click", () => {
if (currentValue != "" && previousValue != "") {
calculate();
previousScreen.textContent = "";
if (previousValue.length <= 5) {
currentScreen.textContent = previousValue;
} else {
currentScreen.textContent = previousValue.slice(0, 5) + "...";
}
}
});
decimal.addEventListener("click", () => {
addDecimal();
});
});
function handleNumber(num) {
if (currentValue.length <= 5) {
currentValue += num;
}
}
function handleOperator(op) {
operator = op;
previousValue = currentValue;
currentValue = "";
}
function calculate() {
previousValue = Number(previousValue);
currentValue = Number(currentValue);
if (operator === "+") {
previousValue += currentValue;
} else if (operator === "-") {
previousValue -= currentValue;
} else if (operator === "x") {
previousValue *= currentValue;
} else if (operator === "/") {
previousValue /= currentValue;
}
previousValue = roundNum(previousValue);
previousValue = previousValue.toString();
currentValue = previousValue.toString();
}
function roundNum(num) {
return Math.round(num * 1000) / 1000;
}
function addDecimal() {
if (!currentValue.includes(".")) {
currentValue += ".";
}
}
window.onkeydown = function(e) {
let x = e.key;
let choice;
switch (x) {
case "1":
choice = document.querySelector(".one");
choice.click();
break;
case "2":
choice = document.querySelector(".two");
choice.click();
break;
case "3":
choice = document.querySelector(".three");
choice.click();
break;
case "4":
choice = document.querySelector(".four");
choice.click();
break;
case "5":
choice = document.querySelector(".five");
choice.click();
break;
case "6":
choice = document.querySelector(".six");
choice.click();
break;
case "7":
choice = document.querySelector(".seven");
choice.click();
break;
case "8":
choice = document.querySelector(".eight");
choice.click();
break;
case "9":
choice = document.querySelector(".nine");
choice.click();
break;
case "0":
choice = document.querySelector(".zero");
choice.click();
break;
case "/":
choice = document.querySelector(".division");
choice.click();
break;
case "*":
choice = document.querySelector(".multiply");
choice.click();
break;
case "-":
choice = document.querySelector(".minus");
choice.click();
break;
case "+":
choice = document.querySelector(".plus");
choice.click();
break;
case ".":
choice = document.querySelector(".decimal");
choice.click();
break;
case "Enter":
choice = document.querySelector(".equal");
choice.click();
break;
case "Backspace":
choice = document.querySelector("#clear-btn");
choice.click();
break;
}
};
body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100vw;
height: 100vh;
}
.btn {
height: 75px;
width: 75px;
margin: 15px;
font-size: 40px;
}
.number {
border: 1px solid yellowgreen;
border-radius: 10px;
}
.number:hover {
background-color: palegreen;
}
.operator {
border: 1px solid steelblue;
border-radius: 10px;
}
.operator:hover {
background-color: paleturquoise;
}
.decimal {
border: 1px solid gold;
border-radius: 10px;
}
.decimal:hover {
background-color: palegoldenrod;
}
.equal {
border: 1px solid pink;
border-radius: 10px;
}
.equal:hover {
background-color: plum;
}
#clear-btn {
border: 1px solid violet;
border-radius: 10px;
}
#clear-btn:hover {
background-color: palevioletred;
}
.first-row {
display: flex;
justify-content: center;
align-items: center;
flex-direction: row;
}
#screen {
width: 300px;
border: 1px solid salmon;
height: 75px;
margin: 15px;
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: flex-end;
}
.previous {
font-size: 20px;
}
.current {
font-size: 30px;
}
<!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>Document</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous" />
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<h1>Calculator</h1>
<div class="calculator">
<div class="first-row">
<div id="screen">
<div class="previous"></div>
<div class="current"></div>
</div>
<button id="clear-btn" class="btn">C</button>
</div>
<div class="other-rows">
<button class="btn number seven">7</button>
<button class="btn number eight">8</button>
<button class="btn number nine">9</button>
<button class="btn operator division">/</button>
</div>
<div class="other-rows">
<button class="btn number four">4</button>
<button class="btn number five">5</button>
<button class="btn number six">6</button>
<button class="btn operator multiply">x</button>
</div>
<div class="other-rows">
<button class="btn number one">1</button>
<button class="btn number two">2</button>
<button class="btn number three">3</button>
<button class="btn operator minus">-</button>
</div>
<div class="other-rows">
<button class="btn decimal">.</button>
<button class="btn number zero">0</button>
<button class="btn equal">=</button>
<button class="btn operator plus">+</button>
</div>
</div>
</body>
</html>
I'm not sure if my code is best practice but when trying to implement both on click and keydown functions my application does not work. For example, type 5*5 and press Enter (the answer shows). Then proceed to CLICK the C to clear and type 5*5 and press Enter again. This time the answer will not be shown. I'm not sure what the error is. Is there a better way to implement both click and keydown functions?
Your general approach is fine. The problem is that the Enter key has a default action of clicking on the active button. Since the last button you clicked on was C, Enter is clicking on this again, which is clearing the result after it's displayed.
Call e.preventDefault() in the keydown listener to stop this.
let operator = "";
let currentValue = "";
let previousValue = "";
document.addEventListener("DOMContentLoaded", () => {
let clear = document.querySelector("#clear-btn");
let equal = document.querySelector(".equal");
let decimal = document.querySelector(".decimal");
let numbers = document.querySelectorAll(".number");
let operators = document.querySelectorAll(".operator");
let previousScreen = document.querySelector(".previous");
let currentScreen = document.querySelector(".current");
numbers.forEach((number) => {
number.addEventListener("click", (e) => {
handleNumber(e.target.textContent);
currentScreen.textContent = currentValue;
});
});
operators.forEach((op) => {
op.addEventListener("click", (e) => {
handleOperator(e.target.textContent);
previousScreen.textContent = previousValue + " " + operator;
currentScreen.textContent = currentValue;
});
});
clear.addEventListener("click", () => {
operator = "";
currentValue = "";
previousValue = "";
previousScreen.textContent = currentValue;
currentScreen.textContent = currentValue;
});
equal.addEventListener("click", () => {
if (currentValue != "" && previousValue != "") {
calculate();
previousScreen.textContent = "";
if (previousValue.length <= 5) {
currentScreen.textContent = previousValue;
} else {
currentScreen.textContent = previousValue.slice(0, 5) + "...";
}
}
});
decimal.addEventListener("click", () => {
addDecimal();
});
});
function handleNumber(num) {
if (currentValue.length <= 5) {
currentValue += num;
}
}
function handleOperator(op) {
operator = op;
previousValue = currentValue;
currentValue = "";
}
function calculate() {
previousValue = Number(previousValue);
currentValue = Number(currentValue);
if (operator === "+") {
previousValue += currentValue;
} else if (operator === "-") {
previousValue -= currentValue;
} else if (operator === "x") {
previousValue *= currentValue;
} else if (operator === "/") {
previousValue /= currentValue;
}
previousValue = roundNum(previousValue);
previousValue = previousValue.toString();
currentValue = previousValue.toString();
}
function roundNum(num) {
return Math.round(num * 1000) / 1000;
}
function addDecimal() {
if (!currentValue.includes(".")) {
currentValue += ".";
}
}
window.onkeydown = function(e) {
e.preventDefault();
let x = e.key;
let choice;
switch (x) {
case "1":
choice = document.querySelector(".one");
choice.click();
break;
case "2":
choice = document.querySelector(".two");
choice.click();
break;
case "3":
choice = document.querySelector(".three");
choice.click();
break;
case "4":
choice = document.querySelector(".four");
choice.click();
break;
case "5":
choice = document.querySelector(".five");
choice.click();
break;
case "6":
choice = document.querySelector(".six");
choice.click();
break;
case "7":
choice = document.querySelector(".seven");
choice.click();
break;
case "8":
choice = document.querySelector(".eight");
choice.click();
break;
case "9":
choice = document.querySelector(".nine");
choice.click();
break;
case "0":
choice = document.querySelector(".zero");
choice.click();
break;
case "/":
choice = document.querySelector(".division");
choice.click();
break;
case "*":
choice = document.querySelector(".multiply");
choice.click();
break;
case "-":
choice = document.querySelector(".minus");
choice.click();
break;
case "+":
choice = document.querySelector(".plus");
choice.click();
break;
case ".":
choice = document.querySelector(".decimal");
choice.click();
break;
case "Enter":
choice = document.querySelector(".equal");
choice.click();
break;
case "Backspace":
choice = document.querySelector("#clear-btn");
choice.click();
break;
}
};
body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100vw;
height: 100vh;
}
.btn {
height: 75px;
width: 75px;
margin: 15px;
font-size: 40px;
}
.number {
border: 1px solid yellowgreen;
border-radius: 10px;
}
.number:hover {
background-color: palegreen;
}
.operator {
border: 1px solid steelblue;
border-radius: 10px;
}
.operator:hover {
background-color: paleturquoise;
}
.decimal {
border: 1px solid gold;
border-radius: 10px;
}
.decimal:hover {
background-color: palegoldenrod;
}
.equal {
border: 1px solid pink;
border-radius: 10px;
}
.equal:hover {
background-color: plum;
}
#clear-btn {
border: 1px solid violet;
border-radius: 10px;
}
#clear-btn:hover {
background-color: palevioletred;
}
.first-row {
display: flex;
justify-content: center;
align-items: center;
flex-direction: row;
}
#screen {
width: 300px;
border: 1px solid salmon;
height: 75px;
margin: 15px;
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: flex-end;
}
.previous {
font-size: 20px;
}
.current {
font-size: 30px;
}
<!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>Document</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous" />
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<h1>Calculator</h1>
<div class="calculator">
<div class="first-row">
<div id="screen">
<div class="previous"></div>
<div class="current"></div>
</div>
<button id="clear-btn" class="btn">C</button>
</div>
<div class="other-rows">
<button class="btn number seven">7</button>
<button class="btn number eight">8</button>
<button class="btn number nine">9</button>
<button class="btn operator division">/</button>
</div>
<div class="other-rows">
<button class="btn number four">4</button>
<button class="btn number five">5</button>
<button class="btn number six">6</button>
<button class="btn operator multiply">x</button>
</div>
<div class="other-rows">
<button class="btn number one">1</button>
<button class="btn number two">2</button>
<button class="btn number three">3</button>
<button class="btn operator minus">-</button>
</div>
<div class="other-rows">
<button class="btn decimal">.</button>
<button class="btn number zero">0</button>
<button class="btn equal">=</button>
<button class="btn operator plus">+</button>
</div>
</div>
</body>
</html>
<!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="https://cdn.jsdelivr.net/npm/bootstrap#4.6.2/dist/css/bootstrap.min.css"
integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N"
crossorigin="anonymous"
/>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<h1>Calculator</h1>
<div class="calculator">
<div class="first-row">
<div id="screen">
<div class="previous"></div>
<div class="current"></div>
</div>
<button id="clear-btn" class="btn">C</button>
</div>
<div class="other-rows">
<button class="btn number seven">7</button>
<button class="btn number eight">8</button>
<button class="btn number nine">9</button>
<button class="btn operator division">/</button>
</div>
<div class="other-rows">
<button class="btn number four">4</button>
<button class="btn number five">5</button>
<button class="btn number six">6</button>
<button class="btn operator multiply">x</button>
</div>
<div class="other-rows">
<button class="btn number one">1</button>
<button class="btn number two">2</button>
<button class="btn number three">3</button>
<button class="btn operator minus">-</button>
</div>
<div class="other-rows">
<button class="btn decimal">.</button>
<button class="btn number zero">0</button>
<button class="btn equal">=</button>
<button class="btn operator plus">+</button>
</div>
</div>
</body>
</html>
body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
width: 100vw;
}
.btn {
height: 75px;
width: 75px;
margin: 15px;
font-size: 40px;
}
.number {
border: 1px solid blue;
border-radius: 10px;
}
.number:hover {
background-color: lightblue;
}
.operator {
border: 1px solid red;
border-radius: 10px;
}
.operator:hover {
background-color: lightcoral;
}
.decimal {
border: 1px solid peru;
border-radius: 10px;
}
.decimal:hover {
background-color: peachpuff;
}
.equal {
border: 1px solid green;
border-radius: 10px;
}
.equal:hover {
background-color: lightgreen;
}
#clear-btn {
border: 1px solid violet;
border-radius: 10px;
}
#clear-btn:hover {
background-color: lavender;
}
.first-row {
display: flex;
justify-content: center;
align-items: center;
flex-direction: row;
}
#screen {
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: flex-end;
width: 300px;
border: 3px solid rosybrown;
height: 75px;
margin: 15px;
}
.previous {
font-size: 20px;
}
.current {
font-size: 30px;
}
h1 {
font-family: cursive;
font-size: 80px;
color: salmon;
}
body {
background-color: lightyellow;
}
.calculator {
border: 1px solid black;
}
let operator = "";
let previousValue = "";
let currentValue = "";
document.addEventListener("DOMContentLoaded", () => {
let decimal = document.querySelector(".decimal");
let equal = document.querySelector(".equal");
let clear = document.querySelector("#clear-btn");
let operators = document.querySelectorAll(".operator");
let numbers = document.querySelectorAll(".number");
let previousScreen = document.querySelector(".previous");
let currentScreen = document.querySelector(".current");
numbers.forEach((number) => {
number.addEventListener("click", (e) => {
handleNumber(e.target.textContent);
currentScreen.textContent = currentValue;
});
});
operators.forEach((op) =>
op.addEventListener("click", function (e) {
handleOperator(e.target.textContent);
previousScreen.textContent = previousValue + " " + operator;
currentScreen.textContent = currentValue;
})
);
clear.addEventListener("click", () => {
previousValue = "";
currentValue = "";
operator = "";
previousScreen.textContent = currentValue;
currentScreen.textContent = currentValue;
});
equal.addEventListener("click", () => {
if (currentValue != "" && previousValue != "") {
calculate();
previousScreen.textContent = "";
if (previousValue.length <= 5) {
currentScreen.textContent = previousValue;
} else {
currentScreen.textContent = previousValue.slice(0, 5) + "...";
}
}
});
decimal.addEventListener("click", () => {
addDecimal();
});
});
function handleNumber(num) {
if (currentValue.length <= 5) {
currentValue += num;
}
}
function handleOperator(op) {
operator = op;
previousValue = currentValue;
currentValue = "";
}
function calculate() {
previousValue = Number(previousValue);
currentValue = Number(currentValue);
if (operator === "+") {
previousValue += currentValue;
} else if (operator === "-") {
previousValue -= currentValue;
} else if (operator === "x") {
previousValue *= currentValue;
} else if (operator === "/") {
previousValue /= currentValue;
}
previousValue = roundNum(previousValue);
previousValue = previousValue.toString();
currentValue = previousValue.toString();
}
function roundNum(num) {
return Math.round(num * 1000) / 1000;
}
function addDecimal() {
if (!currentValue.includes(".")) {
currentValue += ".";
}
}
window.onkeydown = function (e) {
e.preventDefault();
let x = e.key;
let choice;
let currentScreen = document.querySelector(".current");
switch (x) {
case "1":
choice = document.querySelector(".one");
choice.click();
break;
case "2":
choice = document.querySelector(".two");
choice.click();
break;
case "3":
choice = document.querySelector(".three");
choice.click();
break;
case "4":
choice = document.querySelector(".four");
choice.click();
break;
case "5":
choice = document.querySelector(".five");
choice.click();
break;
case "6":
choice = document.querySelector(".six");
choice.click();
break;
case "7":
choice = document.querySelector(".seven");
choice.click();
break;
case "8":
choice = document.querySelector(".eight");
choice.click();
break;
case "9":
choice = document.querySelector(".nine");
choice.click();
break;
case "0":
choice = document.querySelector(".zero");
choice.click();
break;
case "/":
choice = document.querySelector(".division");
choice.click();
break;
case "*":
choice = document.querySelector(".multiply");
choice.click();
break;
case "-":
choice = document.querySelector(".minus");
choice.click();
break;
case "+":
choice = document.querySelector(".plus");
choice.click();
break;
case ".":
choice = document.querySelector(".decimal");
choice.click();
break;
case "Enter":
choice = document.querySelector(".equal");
choice.click();
break;
case "Backspace":
currentScreen.textContent = currentScreen.textContent
.toString()
.slice(0, -1);
break;
}
};
The current screen in my calculator function responds to the keyboard input of backspace and removes the last value but when I input another value it shows up again. It seems to only temporarily remove it. Is this issue due to it being stored in memory ? I tried to use slicing but it does seem to work in case "Backspace".
In your switch case "Backspace", you only edit the text value on the HTML, but don't update the currentValue. When you press the other actions, it uses the currentValue, so your previous change gets overwritten.
case "Backspace":
currentValue = currentScreen.textContent
.toString()
.slice(0, -1);
currentScreen.textContent = currentValue;
break;
I added a working solution as well, so you can test it out.
let operator = "";
let previousValue = "";
let currentValue = "";
document.addEventListener("DOMContentLoaded", () => {
let decimal = document.querySelector(".decimal");
let equal = document.querySelector(".equal");
let clear = document.querySelector("#clear-btn");
let operators = document.querySelectorAll(".operator");
let numbers = document.querySelectorAll(".number");
let previousScreen = document.querySelector(".previous");
let currentScreen = document.querySelector(".current");
numbers.forEach((number) => {
number.addEventListener("click", (e) => {
handleNumber(e.target.textContent);
currentScreen.textContent = currentValue;
});
});
operators.forEach((op) =>
op.addEventListener("click", function (e) {
handleOperator(e.target.textContent);
previousScreen.textContent = previousValue + " " + operator;
currentScreen.textContent = currentValue;
})
);
clear.addEventListener("click", () => {
previousValue = "";
currentValue = "";
operator = "";
previousScreen.textContent = currentValue;
currentScreen.textContent = currentValue;
});
equal.addEventListener("click", () => {
if (currentValue != "" && previousValue != "") {
calculate();
previousScreen.textContent = "";
if (previousValue.length <= 5) {
currentScreen.textContent = previousValue;
} else {
currentScreen.textContent = previousValue.slice(0, 5) + "...";
}
}
});
decimal.addEventListener("click", () => {
addDecimal();
});
});
function handleNumber(num) {
if (currentValue.length <= 5) {
currentValue += num;
}
}
function handleOperator(op) {
operator = op;
previousValue = currentValue;
currentValue = "";
}
function calculate() {
previousValue = Number(previousValue);
currentValue = Number(currentValue);
if (operator === "+") {
previousValue += currentValue;
} else if (operator === "-") {
previousValue -= currentValue;
} else if (operator === "x") {
previousValue *= currentValue;
} else if (operator === "/") {
previousValue /= currentValue;
}
previousValue = roundNum(previousValue);
previousValue = previousValue.toString();
currentValue = previousValue.toString();
}
function roundNum(num) {
return Math.round(num * 1000) / 1000;
}
function addDecimal() {
if (!currentValue.includes(".")) {
currentValue += ".";
}
}
window.onkeydown = function (e) {
e.preventDefault();
let x = e.key;
let choice;
let currentScreen = document.querySelector(".current");
switch (x) {
case "1":
choice = document.querySelector(".one");
choice.click();
break;
case "2":
choice = document.querySelector(".two");
choice.click();
break;
case "3":
choice = document.querySelector(".three");
choice.click();
break;
case "4":
choice = document.querySelector(".four");
choice.click();
break;
case "5":
choice = document.querySelector(".five");
choice.click();
break;
case "6":
choice = document.querySelector(".six");
choice.click();
break;
case "7":
choice = document.querySelector(".seven");
choice.click();
break;
case "8":
choice = document.querySelector(".eight");
choice.click();
break;
case "9":
choice = document.querySelector(".nine");
choice.click();
break;
case "0":
choice = document.querySelector(".zero");
choice.click();
break;
case "/":
choice = document.querySelector(".division");
choice.click();
break;
case "*":
choice = document.querySelector(".multiply");
choice.click();
break;
case "-":
choice = document.querySelector(".minus");
choice.click();
break;
case "+":
choice = document.querySelector(".plus");
choice.click();
break;
case ".":
choice = document.querySelector(".decimal");
choice.click();
break;
case "Enter":
choice = document.querySelector(".equal");
choice.click();
break;
case "Backspace":
currentValue = currentScreen.textContent
.toString()
.slice(0, -1);
currentScreen.textContent = currentValue;
break;
}
};
body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
width: 100vw;
}
.btn {
height: 75px;
width: 75px;
margin: 15px;
font-size: 40px;
}
.number {
border: 1px solid blue;
border-radius: 10px;
}
.number:hover {
background-color: lightblue;
}
.operator {
border: 1px solid red;
border-radius: 10px;
}
.operator:hover {
background-color: lightcoral;
}
.decimal {
border: 1px solid peru;
border-radius: 10px;
}
.decimal:hover {
background-color: peachpuff;
}
.equal {
border: 1px solid green;
border-radius: 10px;
}
.equal:hover {
background-color: lightgreen;
}
#clear-btn {
border: 1px solid violet;
border-radius: 10px;
}
#clear-btn:hover {
background-color: lavender;
}
.first-row {
display: flex;
justify-content: center;
align-items: center;
flex-direction: row;
}
#screen {
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: flex-end;
width: 300px;
border: 3px solid rosybrown;
height: 75px;
margin: 15px;
}
.previous {
font-size: 20px;
}
.current {
font-size: 30px;
}
h1 {
font-family: cursive;
font-size: 80px;
color: salmon;
}
body {
background-color: lightyellow;
}
.calculator {
border: 1px solid black;
}
<!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="https://cdn.jsdelivr.net/npm/bootstrap#4.6.2/dist/css/bootstrap.min.css"
integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N"
crossorigin="anonymous"
/>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<h1>Calculator</h1>
<div class="calculator">
<div class="first-row">
<div id="screen">
<div class="previous"></div>
<div class="current"></div>
</div>
<button id="clear-btn" class="btn">C</button>
</div>
<div class="other-rows">
<button class="btn number seven">7</button>
<button class="btn number eight">8</button>
<button class="btn number nine">9</button>
<button class="btn operator division">/</button>
</div>
<div class="other-rows">
<button class="btn number four">4</button>
<button class="btn number five">5</button>
<button class="btn number six">6</button>
<button class="btn operator multiply">x</button>
</div>
<div class="other-rows">
<button class="btn number one">1</button>
<button class="btn number two">2</button>
<button class="btn number three">3</button>
<button class="btn operator minus">-</button>
</div>
<div class="other-rows">
<button class="btn decimal">.</button>
<button class="btn number zero">0</button>
<button class="btn equal">=</button>
<button class="btn operator plus">+</button>
</div>
</div>
</body>
</html>
I've added a back button to my calculator with the idea that when someone presses it they can undo if they clicked the wrong number.
I've tried to solve using substr within an if statement in my calculate function but nothing seems to be happening it's as if it's not recording when the user clicks the button. To be honest I'm not sure this is the correct approach!
//Create variable to hold display value, create variable of display area and populate.
let toShow = 0;
let displayValue = 0;
let displayArea = document.getElementById('result-display');
let dataType = document.querySelectorAll('[data-type]');
let operator = "";
let firstNumber = 0;
let secondNumber = 0;
let operatorPressed = false;
let secondNumberCounter = false;
let firstNumberCounter = false;
let buttonNumber = 0;
let decimalCounter = 0;
displayArea.innerHTML = 0;
/* displayArea.innerHTML += displayValue; */
//Basic math functions
add = (firstNumber, secondNumber) => firstNumber + secondNumber;
subtract = (firstNumber, secondNumber) => firstNumber - secondNumber;
multiply = (firstNumber, secondNumber) => firstNumber * secondNumber;
divide = (firstNumber, secondNumber) => firstNumber / secondNumber;
//Take an operator and two numbers and call a math function
operate = (operator, firstNumber, secondNumber) => {
toShow = operator(firstNumber, secondNumber);
return Math.round(toShow * 100) / 100;
};
//Update display with button clicked
const button = document.querySelectorAll('.item');
addEventListener('click', e => {
calculate(e);
});
let calculate = (e) => {
if (e.target.id === "equals" && secondNumber === 0) {
displayArea.innerHTML = "OH HELL NO!";
} else if (e.target.id === "equals") {
decimalCounter = 0;
switch (operator) {
case "add":
secondNumberCounter = false;
return firstNumber = displayArea.innerHTML = operate(add, firstNumber, secondNumber);
case "multiply":
secondNumberCounter = false;
return firstNumber = displayArea.innerHTML = operate(multiply, firstNumber, secondNumber);
case "divide":
secondNumberCounter = false;
return firstNumber = displayArea.innerHTML = operate(divide, firstNumber, secondNumber);
case "subtract":
secondNumberCounter = false;
return firstNumber = displayArea.innerHTML = operate(subtract, firstNumber, secondNumber);
}
}
if (operatorPressed === true && e.target.dataset.type === "number") {
if (secondNumberCounter === false) {
displayArea.innerHTML = null;
}
if (decimalCounter === 0) {
let secondButtonNumber = e.target.innerText;
displayValue = secondButtonNumber;
displayArea.innerHTML += displayValue;
secondNumber = Number(displayArea.innerHTML);
secondNumberCounter = true;
}
} else if (e.target.dataset.type === "nonNumber") {
decimalCounter = 0;
operator = e.target.id;
firstNumber = Number(displayArea.innerText);
operatorPressed = true;
} else {
if (e.target.id === "decimal" && decimalCounter === 0) {
++decimalCounter;
buttonNumber = e.target.innerText;
displayValue = buttonNumber;
displayArea.innerHTML += displayValue;
console.log(buttonNumber);
} else {
buttonNumber = Number(e.target.innerText);
displayValue = buttonNumber;
displayArea.innerHTML += displayValue;
displayArea.innerHTML = Number(displayArea.innerHTML);
}
}
if (e.target.id === "AC") {
secondNumberCounter = false;
operatorPressed = false;
firstNumber = 0;
secondNumber = 0;
buttonNumber = 0;
decimalCounter = 0;
displayArea.innerHTML = 0;
}
}
body {
display: flex;
align-items: center;
justify-content: center;
border: 1px solid black;
flex-direction: row;
width: 100%;
height: 100vh;
}
.container {
display: flex;
align-items: center;
justify-content: center;
background-color: gray;
width: 275px;
height: 450px;
border: 1px solid black;
}
.sub-container {
display: flex;
flex-direction: column;
align-items: center;
height: 95%;
width: 800%;
}
.display {
display: flex;
align-items: center;
justify-content: flex-end;
border: 1px solid white;
width: 80%;
height: 10%;
margin: 5% 0 5% 0;
color: white;
}
#result-display {
margin-right: 8%;
}
.button-grid {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
height: 100%;
width: 80%;
}
.item {
width: 50px;
height: 50px;
border: 1px solid white;
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
color: black;
}
button {
width: 100%;
height: 100%;
}
footer {
width: 100%;
background-color: gray;
}
Make the calculator work! You’ll need to store the first number that is input into the calculator when a user presses an operator,
and also save which operation has been chosen and then operate() on them when the user presses the “=” key.
<div class="container">
<div class="sub-container">
<div class="display">
<p id="result-display">
</p>
</div>
<div class="button-grid">
<div>
<button class="item" id="7" data-type="number">
7
</button>
</div>
<div>
<button class="item" id="8" data-type="number">
8
</button>
</div>
<div>
<button class="item" id="9" data-type="number">
9
</button>
</div>
<div>
<button class="item" id="divide" data-type="nonNumber">
*/*
</button>
</div>
<div>
<button class="item" id="4" data-type="number">
4
</button>
</div>
<div>
<button class="item" id="5" data-type="number">
5
</button>
</div>
<div>
<button class="item" id="6" data-type="number">
6
</button>
</div>
<div>
<button class="item" id="multiply" data-type="nonNumber">
X
</button>
</div>
<div>
<button class="item" id="1" data-type="number">
1
</button>
</div>
<div>
<button class="item" id="2" data-type="number">
2
</button>
</div>
<div>
<button class="item" id="3" data-type="number">
3
</button>
</div>
<div>
<button class="item" id="subtract" data-type="nonNumber">
-
</button>
</div>
<div>
<button class="item" id="0" data-type="number">
0
</button>
</div>
<div>
<button class="item" id="decimal" data-type="number">
.
</button>
</div>
<div>
<button class="item" id="AC" data-type="nonNumber">
AC
</button>
</div>
<div>
<button class="item" id="add" data-type="nonNumber">
+
</button>
</div>
<div>
<button class="item" id="equals" data-type="nonNumber">
=
</button>
</div>
<div>
<button class="item" id="back" data-type="nonNumber">
<
</button>
</div>
</div>
</div>
</div>
<div>
<!-- User presses back button
preprend displayValue
displayValue remove one
displayArea.innerHTML remove one
let str = 'Mozilla';
let smallStr = str.substr(0, str.length - 1);-->
You can use either The Memento Pattern or The Command Pattern explained here:
How to make a undo/redo function
I ended up solving this using substring. Basically I look for the length of the string in my calculators display then remove the last character.
Code used in an IF Statement:
if (e.target.id === "back") {
displayArea.innerHTML = displayArea.innerHTML.substring(0, displayArea.innerHTML.length - 1);
}
I would like to make the default display value '0' before inputting numbers into the calculator.
Also I would like to add the functionality to use the keyboard to input numbers and operations.
Here's a link to the Codepen
I've tried updating the this.currentOperand value to '0' but that hasn't worked.
I can only use vanilla JS
Thank you for taking a look.
HTML
<!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="styles.css">
<script src="script.js" defer></script>
</head>
<body>
<div class="calculator-grid">
<div class="output">
<!-- Using the data attribute for js selection to save confusion with css if I used class -->
<div data-previous-operand class="previous-operand"></div>
<div data-current-operand class="current-operand"></div>
</div>
<button data-all-clear id='clear' class="span-two">AC</button>
<button data-delete id='delete'>DEL</button>
<button data-operation id='divide'>÷</button>
<button data-number id='one'>1</button>
<button data-number id='two'>2</button>
<button data-number id='three'>3</button>
<button data-operation id='multiply'>x</button>
<button data-number id='four'>4</button>
<button data-number id='five'>5</button>
<button data-number id='six'>6</button>
<button data-operation id='add'>+</button>
<button data-number id='seven'>7</button>
<button data-number id='eight'>8</button>
<button data-number id='nine'>9</button>
<button data-operation id='subtract'>-</button>
<button data-number id='decimal'>.</button>
<button data-number id='zero'>0</button>
<button data-equals id='equals' class="span-two">=</button>
</div>
</body>
</html>
Javascript
class Calculator {
constructor( previousOperandTextElement, currentOperandTextElement){
this.previousOperandTextElement = previousOperandTextElement;
this.currentOperandTextElement = currentOperandTextElement;
// Call the clear function to start with a clear display
this.clear();
}
clear(){
this.previousOperand = '';
this.currentOperand = '';
this.operation = '';
}
delete(){
this.currentOperand = this.currentOperand.slice(0, -1)
}
appendNumber(number) {
// If there is a '.' in the number and the currentOperand already contains a '.', end the function by returning. I.E do not append a '.'
if (number === '.' && this.currentOperand.includes('.')) return;
// Coverting the numbers to a string as JS will try to add the numbers together instead of appending ie putting onto the end
this.currentOperand = this.currentOperand.toString() + number.toString();
}
chooseOperation(operation) {
if (this.currentOperand === '') return;
// This will compute the equation berofe appling another operation such as +, etc
if (this.currentOperand !== ''){
this.compute()
}
this.operation = operation;
this.previousOperand = this.currentOperand;
this.currentOperand = ''
}
compute() {
let computation;
// parseFloat() converts the string into a number, until it reaches a value that is not a number
const prev = parseFloat(this.previousOperand);
const current = parseFloat(this.currentOperand);
if (isNaN(prev) || isNaN(current)) return;
// Switch statement for the calculation programming
switch (this.operation) {
case '+':
computation = prev + current;
break;
case '-':
computation = prev - current;
break;
case 'x':
computation = prev * current;
break;
case '÷':
computation = prev / current;
break;
default:
return;
}
this.currentOperand = computation;
this.operation = undefined;
this.previousOperand = '';
}
updateDisplay() {
// Displays text in the previous-operand div that is equal to currentOperand
this.currentOperandTextElement.innerText = this.currentOperand;
if (this.operation != null){
// Displays a concatenation of previous operand and the operation symbol
this.previousOperandTextElement.innerText = `${this.previousOperand} ${this.operation}`;
}
}
}
// Data attribute needs to be inside []
const numberButtons = document.querySelectorAll('[data-number]');
const operationButtons = document.querySelectorAll('[data-operation]');
const deleteButton = document.querySelector('[data-delete]');
const equalsButton = document.querySelector('[data-equals]');
const allClearButton = document.querySelector('[data-all-clear]');
const previousOperandTextElement = document.querySelector('[data-previous-operand]');
const currentOperandTextElement = document.querySelector('[data-current-operand]');
// Defining a new Calculator class. Function declaration?
const calculator = new Calculator(previousOperandTextElement, currentOperandTextElement);
numberButtons.forEach(button => {
button.addEventListener('click', () => {
calculator.appendNumber(button.innerText)
calculator.updateDisplay()
})
})
operationButtons.forEach(button => {
button.addEventListener('click', () => {
calculator.chooseOperation(button.innerText)
calculator.updateDisplay()
})
})
equalsButton.addEventListener('click', button => {
calculator.compute();
calculator.updateDisplay();
})
allClearButton.addEventListener('click', button => {
calculator.clear();
calculator.updateDisplay();
})
deleteButton.addEventListener('click', button => {
calculator.delete();
calculator.updateDisplay();
})
CSS
*, *::before, *::after {
box-sizing: border-box;
font-family: Arial, Helvetica, sans-serif;
font-weight: normal;
}
body {
padding: 0;
margin: 0;
background: linear-gradient(to right, #7262B3, #CF98B6);
}
.calculator-grid {
display: grid;
justify-content: center;
align-content: center;
min-height: 100vh;
grid-template-columns: repeat(4, 100px);
grid-template-rows: minmax(120px, auto) repeat(5, 100px);
}
.calculator-grid > button {
cursor: pointer;
font-size: 2rem;
border: solid 1px #CF98B6;
/* border-radius: 10px; */
outline: none;
background-color: rgba(255,255,255, .75);
}
.calculator-grid > button:hover {
background-color: rgba(255,255,255, .91);
}
/* This causes any button within the span-two class to span over two squares */
.span-two {
grid-column: span 2;
}
.output {
/* This spans the output from the 1st column (1) to the last column (-1) */
grid-column: 1 / -1;
background-color: rgba(0, 0, 0, .75);
display: flex;
align-items: flex-end;
justify-content: space-around;
flex-direction: column;
padding: 10px;
word-wrap: break-word;
word-break: break-all;
}
.output .previous-operand {
color: rgba(255,255,255, .75);
font-size: 1.5rem;
}
.output .current-operand {
color: white;
font-size: 2.5rem;
}
The way I solved this was by using an if statement to reset to calculator to 0 and then setting the string to empty once the 0 condition had been met.
if (this.currentOperand === '0') {
this.currentOperand = '';
}
I have just started learning JavaScript and doing my first project by following Frontend Masters tutorial. Calculator is working perfectly fine except a problem. When i press any mathematical operator button (after passing the first number) the screen shows 0. I want it to show the last pressed number and not 0.
I just want to display the last entered number on screen when someone press any of maths operators like addition, subtraction.
let runningTotal = 0;
let bufferNumber = '0';
let previousOperator;
const display = document.querySelector('.display')
//initializing function to execute when a button is clicked
document
.querySelector(".calc-buttons")
.addEventListener("click", function(event) {
clickButton(event.target.innerText);
});
//This function checks if selected value is number or symbol
function clickButton(value) {
if (isNaN(parseInt(value))) {
handleSymbol(value);
} else {
handleNumber(value);
}
rerender()
}
//This function handles the display of number
//this is where initia displayed 0 will be handled
function handleNumber(value) {
if (bufferNumber === '0') {
bufferNumber = value;
} else {
bufferNumber += value;
}
console.log('buffer number is ', bufferNumber);
}
//This function executes different symbols.
function handleSymbol(value) {
switch(value) {
case 'C':
bufferNumber = "0";
runningTotal = 0;
previousOperator =null;
break;
case '←':
if (bufferNumber.length === 1) {
bufferNumber = "0";
} else {
bufferNumber = bufferNumber.substring(0, bufferNumber.length-1);
}
break;
case '=':
console.log('= operator displaying result')
if (previousOperator === null) {
return;
}
flushOperation(parseInt(bufferNumber));
previousOperator = null
bufferNumber = "" + runningTotal;
runningTotal = 0;
break;
default:
console.log('default');
handleMath(value);
break;
}
}
//handles DMAS
// We need to convert strings to integers before doing maths calculations on it
function handleMath(value) {
console.log('handle math function')
const intBuffer = parseInt(bufferNumber);
if (runningTotal === 0) {
runningTotal = intBuffer;
} else {
flushOperation(intBuffer);
}
previousOperator = value;
console.log('previous operator is', previousOperator)
bufferNumber = "0";
}
function flushOperation(intBuffer){
console.log('flush operation')
if (previousOperator === "+"){
runningTotal += intBuffer;
} else if (previousOperator === "−"){
runningTotal -= intBuffer;
} else if (previousOperator === "×"){
runningTotal *= intBuffer;
} else {
runningTotal /= intBuffer;
}
}
function rerender() {
display.innerText = bufferNumber;
}
* {
box-sizing: border-box;
}
body {
margin-left: 30%;
padding: 0;
}
.calc {
width: 400px;
background-color: black;
color: white;
}
.display {
font-family: 'Courier New', Courier, monospace;
font-size: 40px;
text-align: right;
padding: 20px 5px;
}
.calc-button {
background-color: rgb(206, 203, 203);
color: black;
height: 100px;
width: 24.5%;
border: none;
font-size: 40px;
cursor: pointer;
}
.calc-button:hover {
background-color: rgb(252, 249, 249);
}
.calc-button:active {
background-color: gray;
}
.calc-button:last-child {
background-color: rgb(209, 158, 62);
}
.calc-button:last-child:hover {
background-color: rgb(228, 189, 118);
}
.calc-button:last-child:active {
background-color:white;
}
.double {
width: 49.7%;
}
.triple {
width: 74.9%;
}
.calc-rows {
display: flex;
align-content: stretch;
justify-content: space-between;
margin-bottom: 0.5%;
}
<!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="styles.css">
</head>
<body>
<!-- container for overall calculator-->
<div class='calc'>
<section class="display">
0
</section>
<section class="calc-buttons">
<div class="calc-rows">
<button class="double calc-button">C</button>
<button class="calc-button">←</button>
<button class="calc-button">÷</button>
</div>
<div class="calc-rows">
<button class="calc-button">7</button>
<button class="calc-button">8</button>
<button class="calc-button">9</button>
<button class="calc-button">×</button>
</div>
<div class="calc-rows">
<button class="calc-button">4</button>
<button class="calc-button">5</button>
<button class="calc-button">6</button>
<button class="calc-button">−</button>
</div>
<div class="calc-rows">
<button class="calc-button">1</button>
<button class="calc-button">2</button>
<button class="calc-button">3</button>
<button class="calc-button">+</button>
</div>
<div class="calc-rows">
<button class="calc-button triple">0</button>
<button class="calc-button">=</button>
</div>
</section>
</div>
<script src="script.js"></script>
</body>
</html>
I have solved this problem by changing a few things.
when clicking on any of the operator buttons the screen was showing 0 because when the operator was clicked handleSymbol() was called and then handleMath() get called from the default case and the handleMath() function assigned the bufferNumber value of 0.
Removing bufferNumber = "0"; in handleNumber() creates another problem which is bufferNumber is concatenating two numbers into one. for e.g, if we do 5 + 6, the bufferNumber would become 56
the bufferNumber should store only one number which is the number before clicking the operator and there must be another variable to store another number. I have named this var as newBufferNumber
in handleSymbol() function I have added these lines to make the calculator keep working if the calculation continues without clicking the = button.
const ifAnySymbolSelected = value == '÷' ||
value == '×' ||
value == '+' ||
value == '−';
if(bufferNumber && newBufferNumber && ifAnySymbolSelected ) {
console.log(value, bufferNumber, newBufferNumber)
flushOperation(parseInt(bufferNumber), parseInt(newBufferNumber));
}
handleNumber() function contains few changes
Replacing the line
if (bufferNumber === '0') {
bufferNumber = value;
}
with
if(symbolSelected) {
newBufferNumber = newBufferNumber + value
}
to store another digit which the number we click, after clicking calculating operators.
On the screen, I am displaying both numbers including the operator. you can always control what you want to show on the screen.
these are the major things I changed. I want you to go through all of it and observe.
hope this helps.
Working fiddle:
let runningTotal = 0;
let bufferNumber = '';
let newBufferNumber = '';
let previousOperator;
const display = document.querySelector('.display')
//initializing function to execute when a button is clicked
document
.querySelector(".calc-buttons")
.addEventListener("click", function(event) {
clickButton(event.target.innerText);
});
//This function checks if selected value is number or symbol
function clickButton(value) {
if (isNaN(parseInt(value))) {
handleSymbol(value);
}
else {
handleNumber(value);
}
rerender()
}
//This function handles the display of number
//this is where initia displayed 0 will be handled
let symbolSelected ;
function handleNumber(value) {
if(symbolSelected) {
newBufferNumber = newBufferNumber + value
}
else {
bufferNumber += value;
}
console.log(bufferNumber,newBufferNumber)
}
//This function executes different symbols.
function handleSymbol(value) {
// if calculation goes regularly without clicking '=' operator
const ifAnySymbolSelected = value == '÷' ||
value == '×' ||
value == '+' ||
value == '−';
if(bufferNumber && newBufferNumber && ifAnySymbolSelected ) {
console.log(value, bufferNumber, newBufferNumber)
flushOperation(parseInt(bufferNumber), parseInt(newBufferNumber));
}
if (ifAnySymbolSelected) {
symbolSelected = true;
newBufferNumber = ''
}
else{
symbolSelected = false;
}
switch (value) {
case 'C':
bufferNumber = "0";
runningTotal = 0;
previousOperator = null;
previousOperator = null;
break;
case '←':
if (bufferNumber.length === 1) {
bufferNumber = "0";
} else {
bufferNumber = bufferNumber.substring(0, bufferNumber.length - 1);
}
break;
case '=':
if (previousOperator === null) {
return;
}
flushOperation(parseInt(bufferNumber), parseInt(newBufferNumber));
previousOperator = null
bufferNumber = runningTotal;
break;
default: handleMath(value); break;
}
}
// handles DMAS
// We need to convert strings to integers before doing maths calculations on it
function handleMath(value) {
const intBuffer = parseInt(bufferNumber);
if (runningTotal === 0) {
runningTotal = intBuffer;
}
previousOperator = value;
}
function flushOperation(intBuffer,newBufferNumber){
console.log('flush operation')
if (previousOperator === "+"){
runningTotal = intBuffer + newBufferNumber;
} else if (previousOperator === "−"){
runningTotal = intBuffer - newBufferNumber;
} else if (previousOperator === "×"){
runningTotal = intBuffer * newBufferNumber;
} else {
runningTotal = intBuffer / newBufferNumber;
}
bufferNumber = runningTotal;
}
function rerender() {
const displayText = `${bufferNumber} ${previousOperator ? previousOperator : ''} ${ previousOperator ? newBufferNumber : ''}`
display.innerText = displayText;
}
* {
box-sizing: border-box;
}
body {
margin-left: 30%;
padding: 0;
}
.calc {
width: 400px;
background-color: black;
color: white;
}
.display {
font-family: 'Courier New', Courier, monospace;
font-size: 40px;
text-align: right;
padding: 20px 5px;
}
.calc-button {
background-color: rgb(206, 203, 203);
color: black;
height: 100px;
width: 24.5%;
border: none;
font-size: 40px;
cursor: pointer;
}
.calc-button:hover {
background-color: rgb(252, 249, 249);
}
.calc-button:active {
background-color: gray;
}
.calc-button:last-child {
background-color: rgb(209, 158, 62);
}
.calc-button:last-child:hover {
background-color: rgb(228, 189, 118);
}
.calc-button:last-child:active {
background-color:white;
}
.double {
width: 49.7%;
}
.triple {
width: 74.9%;
}
.calc-rows {
display: flex;
align-content: stretch;
justify-content: space-between;
margin-bottom: 0.5%;
}
.as-console-wrapper{display: none!important;}
<!-- container for overall calculator-->
<div class='calc'>
<section class="display">
</section>
<section class="calc-buttons">
<div class="calc-rows">
<button class="double calc-button">C</button>
<button class="calc-button">←</button>
<button class="calc-button">÷</button>
</div>
<div class="calc-rows">
<button class="calc-button">7</button>
<button class="calc-button">8</button>
<button class="calc-button">9</button>
<button class="calc-button">×</button>
</div>
<div class="calc-rows">
<button class="calc-button">4</button>
<button class="calc-button">5</button>
<button class="calc-button">6</button>
<button class="calc-button">−</button>
</div>
<div class="calc-rows">
<button class="calc-button">1</button>
<button class="calc-button">2</button>
<button class="calc-button">3</button>
<button class="calc-button">+</button>
</div>
<div class="calc-rows">
<button class="calc-button triple">0</button>
<button class="calc-button">=</button>
</div>
</section>
</div>