The DOM (Document Object Model) is the browser's live model of your HTML page. JavaScript reads and changes it: document.querySelector(".css-selector") finds the first matching element and querySelectorAll finds all of them.
Change what users see with textContent (text), classList.add/remove/toggle (CSS classes) and attributes such as disabled. Create new elements with document.createElement and add them with append.
element.addEventListener("click", handler) runs your function whenever the user clicks. Most interactive pages follow this pattern: listen for an event → update data → update the page.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Attendance counter</title>
<style>
.full { color: #b5541e; font-weight: bold; }
</style>
<script src="app.js" defer></script>
</head>
<body>
<h1>Class attendance</h1>
<p>Present: <span id="count">0</span> / 5</p>
<button id="add">Mark present</button>
<button id="reset">Reset</button>
<ul id="log"></ul>
</body>
</html>const LIMIT = 5;
let present = 0;
const countEl = document.querySelector("#count");
const addBtn = document.querySelector("#add");
const resetBtn = document.querySelector("#reset");
const log = document.querySelector("#log");
function render() {
countEl.textContent = present;
countEl.classList.toggle("full", present === LIMIT);
addBtn.disabled = present === LIMIT;
}
addBtn.addEventListener("click", () => {
present++;
const item = document.createElement("li");
item.textContent = `Student ${present} arrived at ${new Date().toLocaleTimeString()}`;
log.append(item);
render();
});
resetBtn.addEventListener("click", () => {
present = 0;
log.replaceChildren(); // remove all list items
render();
});
render();Key points
querySelectorfinds elements with CSS selectors.- Use
textContentfor text andclassListfor styling changes. - Pattern: event → update your data → re-render the page from the data.
Exercise
Build a "tip calculator" page: an input for the bill amount, buttons for 5%, 10% and 15%, and a paragraph that shows the tip and total when a button is clicked. Show a message if the input is empty.
Show solution
Try the exercise yourself first — then compare your approach with this one.
One click handler, shared by all three buttons through data-percent attributes, reads the bill, checks it, and shows the tip and total. Using type="number" on the input gives a numeric keyboard on phones.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Tip calculator</title>
<script src="app.js" defer></script>
</head>
<body>
<h1>Tip calculator</h1>
<label>Bill (TSh) <input id="bill" type="number" min="0" /></label>
<p>
<button data-percent="5">5%</button>
<button data-percent="10">10%</button>
<button data-percent="15">15%</button>
</p>
<p id="result"></p>
</body>
</html>const billInput = document.querySelector("#bill");
const result = document.querySelector("#result");
for (const button of document.querySelectorAll("[data-percent]")) {
button.addEventListener("click", () => {
if (billInput.value === "") {
result.textContent = "Please enter the bill amount first.";
return;
}
const bill = Number(billInput.value);
const percent = Number(button.dataset.percent);
const tip = (bill * percent) / 100;
result.textContent = `Tip (${percent}%): ${tip.toLocaleString("en-US")} TSh. Total: ${(bill + tip).toLocaleString("en-US")} TSh`;
});
}