I have attempted to implement a delete button to my calculator that deletes the last digit that the user has typed. When I tested the button, it just added undefined
to the end of the equation.
This is my code:
deleteButton.addEventListener("click", () => {
if (calcString.length > 0) {
calcString = calcString.slice(0, -1);
resultText.textContent = calcString || "0";
display.textContent = calcString.slice(-1) || "0";
} else {
calcString = "";
resultText.textContent = "0";
display.textContent = "0";
}
});
My full code:
const display = document.getElementById("display");
const buttons = document.querySelectorAll(".btn");
const copyButton = document.getElementById("copy");
const resultText = document.getElementById("result");
const rootModal = document.getElementById("rootModal");
const closeModal = document.getElementById("closeModal");
const rootInput = document.getElementById("rootInput");
const submitRoot = document.getElementById("submitRoot");
const deleteButton = document.getElementById("delete");
let calcString = "";
let result = null;
let rootDegree = null;
buttons.forEach((button) => {
button.addEventListener("click", () => {
const value = button.dataset.value;
if (button.classList.contains("clear")) {
calcString = "";
rootDegree = null;
display.textContent = "0";
resultText.textContent = "0";
result = null;
} else if (button.classList.contains("equals")) {
try {
if (rootDegree !== null) {
const base = parseFloat(calcString.replace('√', ''));
result = Math.pow(base, 1 / rootDegree);
} else {
result = eval(calcString.replace(/^/g, "**"));
}
display.textContent = result;
resultText.textContent = `${calcString} =`;
calcString = result.toString();
rootDegree = null;
} catch (error) {
display.textContent = "Error";
resultText.textContent = "Invalid Input";
calcString = "";
result = null;
}
} else if (button.dataset.value === "nth-root") {
rootModal.style.display = "block";
} else {
calcString += value;
resultText.textContent = calcString;
display.textContent = value;
}
});
});
deleteButton.addEventListener("click", () => {
if (calcString.length > 0) {
calcString = calcString.slice(-1);
resultText.textContent = calcString || "0";
display.textContent = calcString.slice(-1) || "0";
} else {
calcString = "";
resultText.textContent = "0";
display.textContent = "0";
}
});
closeModal.addEventListener("click", () => {
rootModal.style.display = "none";
});
submitRoot.addEventListener("click", () => {
const enteredValue = parseFloat(rootInput.value);
if (isNaN(enteredValue) || enteredValue <= 0) {
alert("Please enter a valid root degree!");
} else {
rootDegree = enteredValue;
rootModal.style.display = "none";
rootInput.value = "";
calcString = `√${calcString}`;
resultText.textContent = calcString;
}
});
window.addEventListener("click", (event) => {
if (event.target === rootModal) {
rootModal.style.display = "none";
}
});
copyButton.addEventListener("click", () => {
if (result !== null && result !== "Error") {
navigator.clipboard.writeText(result)
.then(() => {
alert("Result copied to clipboard!");
})
.catch((err) => {
console.error("Error copying to clipboard: ", err);
});
} else {
alert("Nothing to copy!");
}
});
body {
font-family: Montserrat, sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background: #7C8483;
}
.container {
text-align: center;
}
.header {
font-size: 1.5rem;
font-weight: bold;
color: #fff;
margin-bottom: 15px;
}
.calculator {
width: 300px;
background-color: #ffffff;
border-radius: 10px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 3);
overflow: hidden;
}
.calculation {
font-size: 1.2rem;
padding: 10px;
text-align: right;
color: #666;
background-color: #f4f4f4;
border-bottom: 1px solid #e0e0e0;
font-style: italic;
}
.calculation text {
display: inline-block;
}
.display {
font-size: 2rem;
padding: 15px;
text-align: right;
background-color: #28262C;
color: #F1FFFA;
}
.buttons {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 0;
}
.btn {
padding: 20px;
font-size: 1.2rem;
border: 0.1px solid #222;
background-color: #28262C;
cursor: pointer;
transition: all 0.5s ease-in-out;
color: #F1FFFA;
}
.btn:hover {
background-color: #28263c;
}
.operator {
border: 0.1px solid #345;
background-color: #364156;
color: #F1FFFA;
}
.operator:hover {
background-color: #364166;
}
.clear {
background-color: #364156;
color: #F1FFFA;
}
.clear:hover {
background-color: firebrick;
}
.equals {
grid-column: span 2;
background-color: #28262C;
color: #F1FFFA;
}
.equals:hover {
background-color: #28263C;
}
.copy-result {
margin-top: 10px;
}
.copy {
text-decoration: none;
background-color: #f4f4f4;
border: none;
opacity: 50;
transition: 0.5s ease-in-out;
border-radius: 10px;
height: 30px;
width: 30px;
float: left;
}
.copy:hover {
cursor: pointer;
background-color: gainsboro;
}
/* modal */
.modal {
display: none; /* Hidden by default */
position: fixed;
z-index: 1000;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
}
.modal-content {
background-color: #fff;
margin: 15% auto;
padding: 20px;
border: 1px solid #888;
border-radius: 8px;
width: 300px;
text-align: center;
}
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
cursor: pointer;
transition: 0.5s;
}
.close:hover {
color: black;
}
#rootInput {
width: 90%;
padding: 10px;
margin-bottom: 10px;
}
#submitRoot {
padding: 10px 20px;
background-image: linear-gradient(to bottom right, #4CAF50, #4CEF50);
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
.filler:hover {
cursor: default;
color:white;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Calculator</title>
<link rel="stylesheet" href="styles.css">
<script src="main.js"></script>
</head>
<body>
<div id="rootModal" class="modal">
<div class="modal-content">
<span id="closeModal" class="close">×</span>
<h3>Enter the Root Degree</h3>
<input type="number" id="rootInput" placeholder="Enter root degree">
<button id="submitRoot">Submit</button>
</div>
</div>
<div class="calculator">
<div class="calculation" id="calculation">
<h1 class="calculation text" id="result">0</h1>
<button class="copy" id="copy"><i class="fa-regular fa-copy fa-xl"></i></button>
</div>
<div class="display" id="display">0</div>
<div class="buttons">
<button class="btn" data-value="7">7</button>
<button class="btn" data-value="8">8</button>
<button class="btn" data-value="9">9</button>
<button class="btn operator" data-value="/">÷</button>
<button class="btn" data-value="4">4</button>
<button class="btn" data-value="5">5</button>
<button class="btn" data-value="6">6</button>
<button class="btn operator" data-value="*">×</button>
<button class="btn" data-value="1">1</button>
<button class="btn" data-value="2">2</button>
<button class="btn" data-value="3">3</button>
<button class="btn operator" data-value="-">−</button>
<button class="btn" data-value="0">0</button>
<button class="btn" data-value=".">.</button>
<button class="btn clear" id="clear">AC</button>
<button class="btn operator" data-value="+">+</button>
<button class="btn equals" id="equals">=</button>
<button class="btn operator" data-value="^">^</button>
<button class="btn operator" data-value="nth-root">√</button>
<button class="btn delete operator" id="delete">DEL</button>
<button class="filler"></button>
<button class="btn operator" data-value="(">(</button>
<button class="btn operator" data-value=")">)</button>
</div>
</div>
</body>
</html>
I thought it might be it was slicing from calcString
so I tried:
calcString = calcString.slice(-1);
This just outputted d
, however:
How can I fix this?
2
Answers
The issue isn’t with your
deleteButton
event listener, but in the event listener you apply to each element with thebtn
class. When you loop through all the buttons, it adds that element’sdata-value
value to calcString:Currently, your delete button does not have that attribute, so a simple fix would just be to add
data-value=""
to your delete button, eg.This way it is not undefined. Another option would just be to check if it is undefined before adding it to the string:
The first issue arises from the assignment of the class ‘btn’ to the DEL button:
In your JavaScript, you are selecting the buttons using:
As a result, when you click the back button, so first buttons event is triggered, which assigns undefined, and then the deleteButton event is triggered. To resolve this, you should either remove the ‘btn’ class from the DEL button or use a different class name.
The second issue is within the deleteButton event listener, where the slice method is being used incorrectly. Here’s the corrected code: