The DOM — Tree, Selectors & Traversal
প্রতিটি web page একটি গাছ — JS সেই গাছ পরিবর্তন করে
1. The Page Is a Tree
The browser parses HTML into a Document Object Model — a live tree of nodes that JavaScript can read, change, add to, or delete from. document is the root, window is the global.
2. Selectors
// Single element — first match
const el = document.querySelector("#title");
const btn = document.querySelector(".btn-primary");
// All matches — static NodeList
const items = document.querySelectorAll("li.todo");
items.forEach(li => console.log(li.textContent));
// Legacy
document.getElementById("title");
document.getElementsByClassName("btn"); // live HTMLCollection
document.getElementsByTagName("p");
querySelector CSS selector ব্যবহার করে — সবচেয়ে শক্তিশালী এবং পরিচিত। querySelectorAll static — পরে DOM বদলালেও list পরিবর্তন হবে না। getElementsByClassName live — DOM বদলে সাথে সাথে list update হয়।3. Traversal
// element-only navigation (skips text nodes)
el.parentElement
el.children // HTMLCollection
el.firstElementChild
el.lastElementChild
el.previousElementSibling
el.nextElementSibling
// Node-level (includes text nodes — usually you don't want these)
el.parentNode
el.childNodes
el.firstChild
// Climb the tree until a selector matches
el.closest(".card")
4. Reading & Writing Content
el.textContent = "হ্যালো"; // safe text
el.innerHTML = "<b>Hi</b>"; // parses HTML — XSS risk if untrusted
el.innerText // visible text only (slower)
el.value // for inputs
el.setAttribute("data-id", 42);
el.getAttribute("data-id");
el.dataset.id // = "42" — preferred for data-* attrs
el.classList.add("active");
el.classList.remove("hidden");
el.classList.toggle("dark");
el.style.color = "red";
innerHTML. Use textContent for text and createElement + appendChild for structure.
5. Creating & Inserting Elements
const li = document.createElement("li");
li.textContent = "নতুন item";
li.classList.add("todo");
document.querySelector("ul").appendChild(li);
// Modern alternative — accept strings or nodes
parent.append(li, "extra text", anotherNode);
parent.prepend(li);
sibling.before(li);
sibling.after(li);
// Remove
li.remove();
6. Sandbox-Safe DOM Mock
Our in-page runner has no real document. Below is a tiny mock so you can practice the API patterns inside the runner.
class MockEl {
constructor(tag) {
this.tag = tag;
this.children = [];
this.textContent = "";
this.classList = new Set();
}
append(child) { this.children.push(child); }
}
const ul = new MockEl("ul");
["কেনাকাটা", "পড়াশোনা", "ব্যায়াম"].forEach(t => {
const li = new MockEl("li");
li.textContent = t;
li.classList.add("todo");
ul.append(li);
});
console.log(`<ul> has ${ul.children.length} children:`);
ul.children.forEach(li => console.log("·", li.textContent));
7. Glossary (শব্দকোষ)
| Term | Meaning | বাংলায় |
|---|---|---|
| DOM | Document Object Model — live tree representing the page. | Page-এর live tree representation। |
document | The root of the DOM tree. | DOM tree-এর root। |
window | The browser's global object. | Browser-এর global object। |
querySelector | Returns the first element matching a CSS selector. | CSS selector-এর প্রথম মিল-যাওয়া element। |
| NodeList | Static list returned by querySelectorAll. | querySelectorAll-এর static list। |
| HTMLCollection | Live list returned by getElementsByClassName/TagName. | getElementsByClassName-এর live list। |
textContent | Plain-text content — XSS-safe. | Plain text — XSS-নিরাপদ। |
innerHTML | HTML markup — XSS-risky with user input. | HTML markup — user input দিলে XSS ঝুঁকি। |
closest | Climbs the tree until a selector matches. | Selector মিল না হওয়া পর্যন্ত উপরে যায়। |
dataset | Reads/writes data-* attributes as object properties. | data-* attribute-কে object-এর মতো access। |
querySelector দিয়ে খুঁজুন এবং textContent / classList / dataset দিয়ে নিরাপদে edit করুন। User-এর data কখনোই innerHTML-এ বসাবেন না — XSS-এর সরাসরি দরজা। DOM মূলত imperative API; React-এর মতো framework-এ এটিই declarative হয়ে যায়।
8. Practice Problems
- Write a CSS selector to grab all links inside a nav with class "main".
✨ Show Answer
document.querySelectorAll("nav.main a") - Set a heading's text to "হ্যালো!".
✨ Show Answer
document.querySelector("h1").textContent = "হ্যালো!"; - Toggle a "dark" class on the body when a button is clicked.
✨ Show Answer
btn.addEventListener("click", () => document.body.classList.toggle("dark")); - Build a runnable mock that lists 3 todo items as objects.
✨ Show Answer
a4.jsconst todos = [ { text: "কেনাকাটা", done: false }, { text: "পড়াশোনা", done: true }, { text: "ব্যায়াম", done: false }, ]; todos.forEach(t => console.log(`[${t.done ? "x" : " "}] ${t.text}`)); - What's the difference between
querySelectorAll(static) andgetElementsByClassName(live)?✨ Show Answer
Answer:
querySelectorAlltakes a snapshot — adding/removing elements after the call doesn't change the NodeList.getElementsByClassNamereturns a live HTMLCollection that automatically reflects DOM changes. Live collections are surprising in loops where you mutate the DOM. - Use
closestto find the nearest.cardancestor.✨ Show Answer
e.target.closest(".card").remove(); - Show why
innerHTML = userInputis a security risk.✨ Show Answer
If
userInputis<img src=x onerror="steal()">, the browser will parse and execute it. Always usetextContentor DOM-built nodes for user data. - Build an HTML table from a JS array (sketch).
✨ Show Answer
const tbody = document.querySelector("tbody"); data.forEach(row => { const tr = document.createElement("tr"); Object.values(row).forEach(v => { const td = document.createElement("td"); td.textContent = v; tr.appendChild(td); }); tbody.appendChild(tr); }); - Use
datasetto read a customdata-idattribute.✨ Show Answer
// <li data-id="42"> → li.dataset.id === "42" const id = el.dataset.id; - Demonstrate that adding to a live HTMLCollection inside a for loop misbehaves.
✨ Show Answer
If
list = document.getElementsByClassName("x")and you add a new element with class "x" inside a loop,list.lengthgrows during iteration — the loop never ends. Snapshot first:[...list].forEach(...). - Sketch a function that toggles dark mode based on system preference.
✨ Show Answer
const m = matchMedia("(prefers-color-scheme: dark)"); const sync = () => document.body.classList.toggle("dark", m.matches); sync(); m.addEventListener("change", sync); - Replace an element entirely with a new one (sketch).
✨ Show Answer
old.replaceWith(newEl); // or parent.replaceChild(newEl, old); - Show why setting
style.color = "red"overrides CSS — and how to avoid it.✨ Show Answer
Inline styles win over external stylesheets (except for
!important). Prefer toggling classes — it keeps style logic in CSS where it belongs. - Build a runnable "render todo list" simulation that converts an array to console.log lines.
✨ Show Answer
a14.jsconst render = todos => todos.map(t => `<li class="${t.done ? "done" : ""}">${t.text}</li>`); console.log(render([{ text: "কেনাকাটা", done: false }, { text: "পড়া", done: true }])); - Why is the DOM API often called "imperative"?
✨ Show Answer
Answer: You tell the browser the exact steps — "create this node, set this property, append it here." Frameworks like React invert that to declarative: you describe the UI as a function of state and the framework figures out the minimal DOM mutations.
- Show how to clear all children of a list.
✨ Show Answer
// Fast and clean ul.replaceChildren(); // or ul.innerHTML = "";
Summary — Module 25
The DOM is the live tree representing your page. Use querySelector/querySelectorAll to find nodes, textContent to read/write text safely, classList for styling, createElement + append to build new content, and closest for upward search. Avoid innerHTML with untrusted strings.