Build Interactive Calculator (JavaScript Project)

JavaScript... Lesson 4 of 5 15 min

JavaScript DOM Manipulation

Day 4: Build an Interactive Calculator – Make Your Webpage Come Alive

Welcome to Day 4

In Days 1–3, you learned variables, functions, and control flow — JavaScript "thinking" behind the scenes. Today you connect that thinking to the actual webpage the user sees. This is called DOM Manipulation, and it's what makes websites truly interactive.

By the end of today, you'll have built a fully working calculator in pure JavaScript — no page reloads, no frameworks, just HTML, CSS, and JS working together.

Today's Goal: Understand how JavaScript reads from and writes to a webpage. Then apply all of it in one real project — an interactive calculator with add, subtract, multiply, and divide operations.

What You'll Build Today

Step 1 – Learn the DOM
Understand the "Document Object Model" — how JavaScript sees your HTML page
Step 2 – Select Elements
Use document.querySelector() to grab buttons, inputs, and divs
Step 3 – Listen for Events
Detect button clicks and user interactions with addEventListener()
Step 4 – Read & Update the Page
Get input values and display results without refreshing
Step 5 – Build the Calculator
Put it all together in one real, working project

What is the DOM?

When a browser loads your HTML page, it doesn't just display it — it also builds a tree-like map of every element on the page. This map is called the DOM (Document Object Model).

Think of it this way: your HTML file is like a blueprint. The DOM is the actual building that gets constructed from that blueprint. JavaScript can then walk through that building, open doors (read content), paint walls (change styles), or even knock walls down (remove elements).

Your HTML file:


  
    

Hello

Welcome!

How the DOM sees it (as a tree):

📄 document
🌐
📦
┌──────────────┼──────────────┐
🔠


id="title"

📝


class="description"

🔘

JavaScript can grab any of these nodes by their tag, id, or class — then read or change them.

Key Idea: The DOM is JavaScript's view of your HTML. Every HTML element becomes a JavaScript object that you can access and modify. This is what makes web pages dynamic.

The document Object

In JavaScript, document is your entry point into the DOM. It represents the entire webpage and has built-in methods to find elements.

// The document object represents the whole page
console.log(document);           // the entire page
console.log(document.title);     // the page title
console.log(document.body);      // the  element

document.querySelector() — Selecting Elements

document.querySelector() is how you tell "Go find this specific element on the page and give it to me."

It uses the same selectors as CSS — so if you know how to target elements with CSS, you already know how to use querySelector.

Selecting by ID (most common — use #)

// HTML: 

Hello World

let titleElement = document.querySelector('#title'); // Now titleElement IS the

element // You can read its content: console.log(titleElement.textContent); // "Hello World"

Selecting by Class (use .)

// HTML: 

Welcome!

let desc = document.querySelector('.description'); console.log(desc.textContent); // "Welcome!"

Selecting by Tag Name

// Selects the FIRST 

Visual: querySelector in Action

HTML (what the user sees):

id="num1" type="number">

id="result">Result appears here

JavaScript (selecting those elements):

let num1Input = document.querySelector('#num1');
let addButton = document.querySelector('#addBtn');
let resultDiv = document.querySelector('#result');
num1Input
Points to the input box — you can read what the user typed
addButton
Points to the button — you can listen for clicks
resultDiv
Points to the result area — you can write output here

querySelectorAll — Selecting Multiple Elements

When you need all matching elements (not just the first), use querySelectorAll(). It returns a list.

// Select ALL buttons on the page
let allButtons = document.querySelectorAll('button');

// Loop through them
allButtons.forEach(function(btn) {
    console.log(btn.textContent);
});
// Prints: "Add", "Subtract", "Multiply", "Divide"
Quick Reference:
'#myId' → selects element with id="myId"
'.myClass' → selects element with class="myClass"
'button' → selects a

Event Listeners — Responding to User Actions

An event is anything that happens on a webpage — a click, a keypress, a mouse hover, a form submission. An event listener is code that waits and watches for a specific event, then runs a function when it happens.

The Syntax:

element.addEventListener('eventType', function() {
    // code to run when the event happens
});
element
The HTML element to watch (e.g., a button)
'click'
The event to listen for
function() { }
Code to run when it happens

Click Events

Simple button click:

// HTML: 

let greetBtn = document.querySelector('#greetBtn');

greetBtn.addEventListener('click', function() {
    console.log("Button was clicked!");
    alert("Hello, World!");
});

What happens step by step:

Step 1
Page loads → event listener is set up and waits silently
Step 2
User clicks the button → browser fires a "click" event
Step 3
addEventListener catches it → runs the function inside
Step 4
Function executes → console.log and alert run

Common Event Types

// 'click' — user clicks an element
button.addEventListener('click', function() { ... });

// 'input' — user types into an input field
inputField.addEventListener('input', function() { ... });

// 'mouseover' — mouse hovers over element
div.addEventListener('mouseover', function() { ... });

// 'keydown' — user presses any key
document.addEventListener('keydown', function(event) {
    console.log("Key pressed:", event.key);
});
Pro Tip: The function inside addEventListener is called a callback function. It runs automatically when the event occurs — you don't call it yourself. JavaScript calls it for you!

Getting Input Values

When users type into an input field, you retrieve what they typed using the .value property.

// HTML: 

let nameInput = document.querySelector('#nameInput');

// User typed "Alice" into the input
let typedValue = nameInput.value;
console.log(typedValue);  // "Alice"

⚠️ Critical: Input Values Are Always Strings!

This is one of the most common beginner mistakes. Even when a user types a number like 42 into an input, JavaScript sees it as the text "42", not the number 42. You must convert it!

❌ The Problem (without conversion):

// User typed 10 and 5 in two input fields
let num1 = document.querySelector('#num1').value;  // "10" (string!)
let num2 = document.querySelector('#num2').value;  // "5" (string!)

let result = num1 + num2;
console.log(result);  // "105" ← WRONG! It joined the strings!

✅ The Fix (with Number() conversion):

// Convert strings to actual numbers using Number()
let num1 = Number(document.querySelector('#num1').value);  // 10 ✓
let num2 = Number(document.querySelector('#num2').value);  // 5 ✓

let result = num1 + num2;
console.log(result);  // 15 ← Correct!

Visual: String vs Number

String "10" + String "5"

"10"
+
"5"
=
"105"

Concatenation (gluing text)

Number(10) + Number(5)

10
+
5
=
15

Addition (math)

Three Ways to Convert to Number:
Number("42") → 42   ← Most clear and recommended
parseInt("42") → 42   ← For whole numbers only
parseFloat("42.5") → 42.5   ← For decimals

Updating the DOM — Displaying Results

Once you have a result, you need to show it on the page. The main properties for updating elements are textContent and innerHTML.

textContent — Change plain text:

// HTML: 
Waiting...
let resultDiv = document.querySelector('#result'); resultDiv.textContent = "The answer is 42!"; // The div now shows: The answer is 42!

innerHTML — Change content including HTML tags:

// You can insert HTML tags too
resultDiv.innerHTML = "Result: 42";
// Shows: Result: 42  (with "Result:" in bold)

Changing styles:

// Change CSS styles with JavaScript
resultDiv.style.color = "green";
resultDiv.style.fontWeight = "bold";
resultDiv.style.backgroundColor = "#d4edda";

Visual: Read Input → Process → Update Page

📥 Input
User types "10"
.value
⚙️ Convert
Number("10") = 10
Number()
🧮 Calculate
10 + 5 = 15
arithmetic
📤 Display
Shows "15" on page
.textContent

🛠 Project: Build an Interactive Calculator

Now we apply everything. We'll build a calculator with two number inputs, four operation buttons, and a result display — all updating live without any page reload.

Calculator Requirements:
✓ Two input fields for numbers
✓ Four buttons: Add, Subtract, Multiply, Divide
✓ Result displays on the page (no alert, no refresh)
✓ Error handling for division by zero
✓ Error handling for invalid (empty/non-number) inputs

Step 1: The Logic Flow (Before Any Code)

Calculator Logic Flow

🖱 User clicks a button (e.g., "Add")
📖 Read num1.value and num2.value
🔢 Convert to numbers with Number()
❓ Are inputs valid numbers?
NO
Show "Please enter valid numbers"
YES
Perform the math operation
📺 Display result with .textContent

Step 2: The HTML Structure (index.html)




    
    
    JavaScript Calculator
    



    

JavaScript Calculator

Enter two numbers and choose an operation
Notice the IDs: Every interactive element has a unique ID so JavaScript can find it. We have #num1, #num2, #addBtn, #subtractBtn, #multiplyBtn, #divideBtn, and #result.

Step 3: The CSS (style.css)

/* style.css */

* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

body {
    font-family: Arial, sans-serif;
    background: #f0f4f8;
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 100vh;
}

.calculator {
    background: white;
    padding: 30px;
    border-radius: 12px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
    max-width: 400px;
    width: 100%;
    text-align: center;
}

h1 {
    font-size: 1.5em;
    color: #2c3e50;
    margin-bottom: 20px;
}

.inputs {
    display: flex;
    gap: 10px;
    margin-bottom: 20px;
}

input[type="number"] {
    flex: 1;
    padding: 12px;
    font-size: 1.1em;
    border: 2px solid #ddd;
    border-radius: 8px;
    text-align: center;
    outline: none;
    transition: border-color 0.2s;
}

input[type="number"]:focus {
    border-color: #3498db;
}

.buttons {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    margin-bottom: 20px;
}

button {
    padding: 12px;
    font-size: 1em;
    font-weight: bold;
    border: none;
    border-radius: 8px;
    cursor: pointer;
    transition: background 0.2s, transform 0.1s;
}

button:active {
    transform: scale(0.97);
}

#addBtn      { background: #2ecc71; color: white; }
#subtractBtn { background: #e74c3c; color: white; }
#multiplyBtn { background: #3498db; color: white; }
#divideBtn   { background: #9b59b6; color: white; }

#addBtn:hover      { background: #27ae60; }
#subtractBtn:hover { background: #c0392b; }
#multiplyBtn:hover { background: #2980b9; }
#divideBtn:hover   { background: #8e44ad; }

#result {
    padding: 20px;
    background: #f8f9fa;
    border-radius: 8px;
    font-size: 1.2em;
    color: #555;
    min-height: 60px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px solid #eee;
    transition: all 0.3s;
}

#result.success {
    background: #d4edda;
    border-color: #2ecc71;
    color: #1a6b38;
    font-weight: bold;
}

#result.error {
    background: #f8d7da;
    border-color: #e74c3c;
    color: #721c24;
}

Step 4: The JavaScript — Building It Step by Step

We'll build script.js in stages, explaining each part before writing it.

Part A: Select All Elements

First, we grab every element we'll need using querySelector. Do this once at the top of your file.

// ===================================
// Part A: Select Elements from the DOM
// ===================================

// Input fields - we'll read .value from these
const num1Input = document.querySelector('#num1');
const num2Input = document.querySelector('#num2');

// Buttons - we'll add click listeners to these
const addBtn      = document.querySelector('#addBtn');
const subtractBtn = document.querySelector('#subtractBtn');
const multiplyBtn = document.querySelector('#multiplyBtn');
const divideBtn   = document.querySelector('#divideBtn');

// Result display - we'll write .textContent to this
const resultDiv = document.querySelector('#result');

Part B: Write a Helper Function

We'll write a reusable function to get both numbers and check if they're valid. This avoids repeating the same code four times.

// ===================================
// Part B: Helper Functions
// ===================================

// This function shows a result on the page
function showResult(message, isError) {
    resultDiv.textContent = message;

    // Change styling based on success or error
    if (isError) {
        resultDiv.className = 'error';   // red styling
    } else {
        resultDiv.className = 'success'; // green styling
    }
}

// This function gets the numbers from inputs
// Returns the numbers, or null if inputs are invalid
function getNumbers() {
    let num1 = Number(num1Input.value);
    let num2 = Number(num2Input.value);

    // Check if inputs are empty
    if (num1Input.value === '' || num2Input.value === '') {
        showResult("⚠️ Please fill in both number fields!", true);
        return null;  // Stop — invalid input
    }

    // Check if inputs are actual numbers (NaN = Not a Number)
    if (isNaN(num1) || isNaN(num2)) {
        showResult("⚠️ Please enter valid numbers!", true);
        return null;  // Stop — invalid input
    }

    // All good! Return the numbers as an object
    return { num1, num2 };
}
What is isNaN()?
isNaN() stands for "is Not a Number." It returns true if something is not a valid number.

isNaN(42) → false (42 IS a number)
isNaN("hello") → true ("hello" is NOT a number)

Part C: Add Event Listeners for Each Button

// ===================================
// Part C: Button Event Listeners
// ===================================

// --- ADD BUTTON ---
addBtn.addEventListener('click', function() {
    let numbers = getNumbers();
    if (numbers === null) return;  // Stop if inputs invalid

    let result = numbers.num1 + numbers.num2;
    showResult(`${numbers.num1} + ${numbers.num2} = ${result}`, false);
});

// --- SUBTRACT BUTTON ---
subtractBtn.addEventListener('click', function() {
    let numbers = getNumbers();
    if (numbers === null) return;

    let result = numbers.num1 - numbers.num2;
    showResult(`${numbers.num1} - ${numbers.num2} = ${result}`, false);
});

// --- MULTIPLY BUTTON ---
multiplyBtn.addEventListener('click', function() {
    let numbers = getNumbers();
    if (numbers === null) return;

    let result = numbers.num1 * numbers.num2;
    showResult(`${numbers.num1} × ${numbers.num2} = ${result}`, false);
});

// --- DIVIDE BUTTON ---
divideBtn.addEventListener('click', function() {
    let numbers = getNumbers();
    if (numbers === null) return;

    // Special check: can't divide by zero!
    if (numbers.num2 === 0) {
        showResult("⚠️ Cannot divide by zero!", true);
        return;
    }

    let result = numbers.num1 / numbers.num2;
    // Round to 4 decimal places to keep it clean
    let roundedResult = Math.round(result * 10000) / 10000;
    showResult(`${numbers.num1} ÷ ${numbers.num2} = ${roundedResult}`, false);
});

The Complete script.js File

Here is the complete, ready-to-use JavaScript file. Every part explained above combined:

// ============================================
// JavaScript Day 4: Interactive Calculator
// ============================================

// PART A: Select DOM Elements
// ============================================
const num1Input   = document.querySelector('#num1');
const num2Input   = document.querySelector('#num2');
const addBtn      = document.querySelector('#addBtn');
const subtractBtn = document.querySelector('#subtractBtn');
const multiplyBtn = document.querySelector('#multiplyBtn');
const divideBtn   = document.querySelector('#divideBtn');
const resultDiv   = document.querySelector('#result');


// PART B: Helper Functions
// ============================================

// Display result with correct styling
function showResult(message, isError) {
    resultDiv.textContent = message;
    resultDiv.className = isError ? 'error' : 'success';
}

// Get and validate the two input numbers
function getNumbers() {
    if (num1Input.value === '' || num2Input.value === '') {
        showResult("⚠️ Please fill in both number fields!", true);
        return null;
    }

    let num1 = Number(num1Input.value);
    let num2 = Number(num2Input.value);

    if (isNaN(num1) || isNaN(num2)) {
        showResult("⚠️ Please enter valid numbers!", true);
        return null;
    }

    return { num1, num2 };
}


// PART C: Event Listeners
// ============================================

addBtn.addEventListener('click', function() {
    let numbers = getNumbers();
    if (numbers === null) return;

    let result = numbers.num1 + numbers.num2;
    showResult(`${numbers.num1} + ${numbers.num2} = ${result}`, false);
});

subtractBtn.addEventListener('click', function() {
    let numbers = getNumbers();
    if (numbers === null) return;

    let result = numbers.num1 - numbers.num2;
    showResult(`${numbers.num1} - ${numbers.num2} = ${result}`, false);
});

multiplyBtn.addEventListener('click', function() {
    let numbers = getNumbers();
    if (numbers === null) return;

    let result = numbers.num1 * numbers.num2;
    showResult(`${numbers.num1} × ${numbers.num2} = ${result}`, false);
});

divideBtn.addEventListener('click', function() {
    let numbers = getNumbers();
    if (numbers === null) return;

    if (numbers.num2 === 0) {
        showResult("⚠️ Cannot divide by zero!", true);
        return;
    }

    let result = Math.round((numbers.num1 / numbers.num2) * 10000) / 10000;
    showResult(`${numbers.num1} ÷ ${numbers.num2} = ${result}`, false);
});

Step 5: Test Every Scenario

✅ Test 1 — Normal addition:
Enter 10 and 5, click Add → Should show "10 + 5 = 15"
✅ Test 2 — Decimal division:
Enter 10 and 3, click Divide → Should show "10 ÷ 3 = 3.3333"
✅ Test 3 — Divide by zero:
Enter 5 and 0, click Divide → Should show error "Cannot divide by zero!"
✅ Test 4 — Empty fields:
Leave fields empty, click any button → Should show "Please fill in both fields"
✅ Test 5 — Negative numbers:
Enter -5 and 3, click Multiply → Should show "-5 × 3 = -15"

🔍 Interactive Demo — Try It Now

Here's the calculator running live right in this lesson. Try it yourself!

🧮 Interactive Calculator Demo

Enter two numbers and choose an operation

Exercises: Extend Your Calculator

Once your calculator works, challenge yourself with these extensions to reinforce your understanding.

Exercise 1: Add a Clear Button

Task: Add a "Clear" button that empties both inputs and resets the result message.

HTML to add (inside .buttons div):

JavaScript to add:

const clearBtn = document.querySelector('#clearBtn');

clearBtn.addEventListener('click', function() {
    num1Input.value = '';   // Empty first input
    num2Input.value = '';   // Empty second input
    resultDiv.textContent = 'Enter two numbers and choose an operation';
    resultDiv.className = ''; // Remove success/error styling
});

Exercise 2: Add a Power Button (Bonus)

Task: Add a "Power" button that raises the first number to the power of the second (e.g., 2^8 = 256).

Hint:

// JavaScript has a built-in power operator
let result = Math.pow(2, 8);  // 256
// Or use ** operator:
let result2 = 2 ** 8;          // 256 (same thing)

Exercise 3: Show Calculation History

Task: Keep a list of the last 5 calculations and display them below the result.

Starter code structure:

// Add to your HTML:
// 
let history = []; // An array to store past calculations const historyDiv = document.querySelector('#history'); function addToHistory(calculation) { history.unshift(calculation); // Add to front of array if (history.length > 5) history.pop(); // Keep only last 5 // Display history historyDiv.innerHTML = 'History:
' + history.join('
'); } // Then in each button listener, call: // addToHistory(`${num1} + ${num2} = ${result}`);

File Structure Summary

📁 calculator-project/
├── 📄 index.html    ← The structure (inputs, buttons, result div)
├── 🎨 style.css     ← The styling (layout, colors, transitions)
└── ⚡ script.js     ← The logic (querySelector, addEventListener, values)

Testing Your Calculator Checklist

Step 1: Create the folder calculator-project/
Step 2: Create index.html and paste the HTML code
Step 3: Create style.css and paste the CSS code
Step 4: Create script.js and paste the JavaScript code
Step 5: Open index.html in your browser
Step 6: Open DevTools (F12) → Console tab to check for errors
Step 7: Test all 5 scenarios: normal math, decimals, divide by zero, empty fields, negatives

Key Concepts Quick Reference

// SELECT an element
let el = document.querySelector('#myId');

// READ text content
let text = el.textContent;

// WRITE text content
el.textContent = "New text!";

// READ an input value
let val = inputEl.value;  // Always a string!

// CONVERT string to number
let num = Number(val);

// LISTEN for a click
el.addEventListener('click', function() {
    // runs when clicked
});

// CHANGE a style
el.style.color = 'green';
el.style.backgroundColor = '#d4edda';

Complete this lesson

Mark as complete to track your progress