Project: Calculator
Table of Contents + −
In the previous lesson, we learned how throttling limits how often a function runs. Now let’s build our first project: a working calculator that brings together everything you know about the DOM, events, and strings.
🎯 What We’ll Build
We will build a calculator that runs in the browser. It has a display at the top and a grid of buttons below it: the digits 0 through 9, the four operators +, -, *, and /, an equals button =, and a clear button C.
When the user clicks a button, the calculator adds that character to the display. When the user clicks =, the calculator evaluates the expression and shows the answer. The C button clears everything and starts over.
This project ties together several JavaScript concepts you have already learned:
- The DOM to find the display and the buttons on the page.
- Event listeners with
addEventListenerto react to clicks. - Strings to build the expression one character at a time.
- Data attributes to tell which button was pressed.
🧱 The HTML
The HTML gives us a div for the display and a button for every key. Each button stores its value in a data-value attribute so the JavaScript can read it later. Here is the markup:
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" /> <title>Calculator</title> </head> <body> <div class="calculator"> <div class="display" id="display">0</div>
<div class="buttons"> <button data-value="C" class="clear">C</button> <button data-value="/">/</button> <button data-value="*">*</button> <button data-value="-">-</button>
<button data-value="7">7</button> <button data-value="8">8</button> <button data-value="9">9</button> <button data-value="+">+</button>
<button data-value="4">4</button> <button data-value="5">5</button> <button data-value="6">6</button>
<button data-value="1">1</button> <button data-value="2">2</button> <button data-value="3">3</button>
<button data-value="0">0</button> <button data-value="=" class="equals">=</button> </div> </div>
<script src="calculator.js"></script> </body></html>Let’s walk through the key parts of this markup:
<div class="display" id="display">0</div>is the screen at the top. Theid="display"lets us grab it quickly from JavaScript, and the0is what shows before the user types anything.<div class="buttons">wraps every key in one container so we can lay them out as a grid.data-valueon each button holds the exact character that button represents. We read this one attribute instead of checking the button’s text, which keeps the logic simple.data-value="C"is the clear key anddata-value="="is the equals key. We give these aclass(clearandequals) so they can be styled differently from the digits.<script src="calculator.js"></script>sits at the end of thebodyso the buttons exist on the page before our JavaScript runs.
⚙️ The JavaScript
The JavaScript listens for clicks, builds the expression as a string, and evaluates it when the user presses =. Here is the full logic:
const display = document.getElementById("display");const buttons = document.querySelectorAll("button");
let expression = "";
buttons.forEach((button) => { button.addEventListener("click", () => { const value = button.dataset.value;
if (value === "C") { // Clear everything and start over expression = ""; display.textContent = "0"; return; }
if (value === "=") { // Work out the answer const result = calculate(expression); display.textContent = result; expression = String(result); return; }
// Any digit or operator: add it to the expression expression += value; display.textContent = expression; });});
function calculate(text) { try { const answer = Function(`"use strict"; return (${text})`)(); if (!isFinite(answer)) { return "Error"; } return answer; } catch { return "Error"; }}Here is how it works, line by line:
const display = ...andconst buttons = ...grab the display withgetElementByIdand collect every button withquerySelectorAll.let expression = "";is a string that holds what the user has typed so far. It starts empty.buttons.forEach((button) => { ... })loops over the buttons and attaches a click listener to each one.const value = button.dataset.value;reads thedata-valueattribute, so we always know exactly which key was pressed.if (value === "C")resets the expression to an empty string and puts0back on the display.if (value === "=")callscalculateto evaluate the expression, shows the result, and stores it so the user can keep calculating from the answer.expression += value;handles everything else, a digit or an operator: we add the character toexpressionand update the display.function calculate(text)turns the expression text into a number. It uses theFunctionconstructor to evaluate the math, wraps the work in atry...catchso a broken expression like5++returns"Error"instead of crashing, and checksisFiniteso dividing by zero also shows"Error".
A note about evaluating math
This project uses the Function constructor to evaluate the expression, which
is simple but can run any code passed to it. That is fine here because the only
input comes from our own buttons. In a real app that accepts text from users,
parse and compute the math yourself instead of evaluating strings, so you never
run untrusted code.
🚀 Try It Yourself!
Get the basic calculator working first, then pick an enhancement to add.
- Save the HTML as
index.htmland the JavaScript ascalculator.jsin the same folder, then open the page in your browser. - Add keyboard support by listening for
keydownon the document. Map number and operator keys to the same logic,Enterto=, andEscapetoC. - Add a decimal point button with
data-value="."so users can type numbers like3.14. - Add a percentage button that divides the current number by
100when clicked.
Reuse your logic
When you add keyboard support, call the same code that the click listener already runs. Move the shared work into one function so the keyboard and the buttons stay in sync.
🧩 What You’ve Learned
- ✅ How to attach a click listener to many buttons with
forEachandaddEventListener - ✅ How to read a button’s
data-valueattribute withdataset - ✅ How to build an expression string and update the display as the user types
- ✅ How to evaluate the expression safely with
try...catchandisFinite - ✅ How a clear button resets the calculator to its starting state
🚀 What’s Next?
You have built your first interactive app. Next we will fetch real data from the internet and display it. Let’s build a Weather App.