Logic
Goal for this step
Part 3 brings MiniCalc to life. You will load app.js and teach the page how to respond when someone presses a key on the pad.
The calculator needs a small amount of memory: the number currently being typed, the previous number, the pending operator, and a flag that says whether the next digit should replace the display instead of appending to it.
When this part is done, mouse clicks alone should support everyday arithmetic, clearing, and backspacing. Keyboard support waits until Part 4.
What you should already know
You need the styled HTML from Part 2, including data-action attributes on every button. You should know that a script tag can load a JavaScript file at the end of the body.
If words like variable, function, and event feel new, read the paragraphs below slowly. The ideas are small. We are only storing a few strings and reacting to clicks.
Concepts in plain language
The DOM is the browser’s live tree of HTML elements. JavaScript can find nodes, read attributes, and change text. Our display updates by writing to display.textContent.
Event listeners wait for something to happen. When a click occurs inside the keys area, our listener figures out which button was pressed and what action that button represents.
Event delegation means we attach one listener to the keys container instead of one listener per button. Clicks bubble up from the button to the container. We ask the event for the nearest button and read its dataset. That pattern scales cleanly if you add more keys later.
A state machine sounds fancy, but here it only means: remember a few values, change them according to rules, then refresh the display. Digits append while typing; after an operator, the next digit starts a fresh number.
Track state, then update the display
Keep calculator memory in variables at the top of app.js. Store numbers as strings while the user is typing so leading zeros and decimals stay easy to manage. Convert to numbers only when you compute.
Write a single updateDisplay helper that copies current into the display element. Event handlers should change state, then call that helper. Scattering DOM writes in many places makes bugs hard to find.
let current = "0";
let previous = null;
let operator = null;
let fresh = false;
function updateDisplay() {
display.textContent = current;
}
Handle clicks and compute results
Listen on the keys container. Ignore clicks that did not land on a button. Read dataset.action and dataset.value, then branch with a switch or if/else chain for digit, operator, equals, clear, backspace, and decimal.
Digit handling should replace a lone leading zero, append after that, and respect the fresh flag after an operator or equals. Operator handling should store the pending operation and move the current value into previous when needed.
Put the four arithmetic operations in a small compute function. Round floating results slightly so values like 0.1 + 0.2 stay readable instead of showing a long binary artifact.
keys.addEventListener("click", (event) => {
const button = event.target.closest("button");
if (!button) return;
const action = button.dataset.action;
const value = button.dataset.value;
// switch on action: digit, operator, equals, clear, ...
updateDisplay();
});
function compute(a, op, b) {
switch (op) {
case "+": return a + b;
case "-": return a - b;
case "*": return a * b;
case "/": return a / b;
default: return b;
}
}
Run the snapshot and verify
Serve the Part 3 folder and try a few expressions by clicking only. Confirm that digit entry replaces a leading zero, that chained operations such as 2 + 3 + 4 work, and that clear resets everything to zero.
Also test backspace on a multi-digit number and a simple decimal entry. If something fails, log the state variables temporarily or compare your handlers to the snapshot file.
git clone https://github.com/michaeldunga1/fcc-js-calculator.git
cd fcc-js-calculator/03-Logic
python3 -m http.server 8000
# Then visit http://localhost:8000
Common mistakes and checklist
Loading the script in the head without defer can run code before the buttons exist. Place the script before </body> or use defer so the DOM is ready.
Forgetting to set fresh after an operator causes digits to glue onto the previous number. Forgetting to clear it after starting a new number causes the opposite bug.
Dividing by zero may show Infinity in this part. Part 4 will turn that into a friendly error. Focus on ordinary math paths here.
- Digit entry replaces a leading zero and appends after that
- Chained operations such as
2 + 3 + 4work - Clear resets everything to
0 - Backspace deletes the last digit of the current entry
- Equals computes using the pending operator and operands
Next: Polish
Comments
One comment per signed-in account. Comments are saved with this page’s URL.