JavaScript Programming Labs

Master JavaScript through hands-on coding challenges. Write real code, get instant feedback, and build practical web development skills.

DOM Manipulation, Events & Classes - Module 4

Learn to interact with web pages and build object-oriented JavaScript applications.

Lab 10: DOM Manipulation
Intermediate
Coding Challenge
Your Task: Learn to manipulate the Document Object Model (DOM) - the programming interface for HTML documents. DOM manipulation is essential for creating interactive web pages.

Detailed Requirements:

1. Select elements using document.getElementById() - The most common and fastest way to select a single element by its unique ID attribute.
const element = document.getElementById("myId"); // Returns the element with id="myId" or null if not found
2. Select elements using document.querySelector() - Uses CSS selector syntax to select the FIRST matching element. Very flexible!
const element = document.querySelector(".className"); // By class const element = document.querySelector("#myId"); // By ID const element = document.querySelector("div > p"); // CSS selector const element = document.querySelector("[data-id]"); // By attribute
3. Select multiple elements using querySelectorAll() - Returns a NodeList of ALL matching elements (use forEach to iterate).
const elements = document.querySelectorAll(".item"); elements.forEach(el => console.log(el.textContent)); // Or convert to array: [...elements] or Array.from(elements)
4. Modify element content with textContent and innerHTML
element.textContent = "Plain text (safe, escapes HTML)"; element.innerHTML = "HTML content (can be XSS risk!)"; // textContent is faster and safer for plain text
5. Modify element styles and classes
// Inline styles (camelCase properties) element.style.backgroundColor = "blue"; element.style.fontSize = "20px"; // Class manipulation (preferred for styling) element.classList.add("active"); element.classList.remove("hidden"); element.classList.toggle("visible"); element.classList.contains("active"); // returns true/false
6. Create and append new elements
const newDiv = document.createElement("div"); newDiv.textContent = "New element!"; newDiv.className = "my-class"; document.body.appendChild(newDiv); // Or insert at specific position parent.insertBefore(newDiv, referenceElement); parent.append(newDiv); // Appends to end parent.prepend(newDiv); // Prepends to beginning
💡 Pro Tips:
getElementById is fastest, but querySelector is more flexible
• Use textContent over innerHTML when possible (security + performance)
• Prefer classList methods over directly manipulating className
• Cache DOM references in variables to avoid repeated lookups
• Use dataset property to access data-* attributes: element.dataset.userId

⚠️ Common Mistakes to Avoid:
• Using innerHTML with user input (XSS vulnerability)
• Forgetting that querySelectorAll returns NodeList, not Array
• Not checking if element exists before accessing properties (null reference error)

Expected Output:
Selected element by ID: <div id="demo"> Selected element by class: <p class="intro"> All items: NodeList(3) [li, li, li] Text content changed! New element created and appended!

Requirements Checklist

Use document.getElementById() to select an element
Use document.querySelector() with CSS selector
Use querySelectorAll() to select multiple elements
Modify textContent or innerHTML
Use classList methods (add/remove/toggle)
Create and append a new element
Console Output
// Click "Run Code" to execute your JavaScript // Your console.log() output will appear here
Hints & Tips
• By ID: document.getElementById("myId")
• By selector: document.querySelector(".class")
• Multiple: document.querySelectorAll("li")
• Content: element.textContent = "text"
• Classes: element.classList.add("class")
• Create: document.createElement("div")
Progress: 0/6
Score: 0/100
0%

Lab Results

Review feedback below

Lab 11: Event Handling
Intermediate
Coding Challenge
Your Task: Learn to handle user interactions using JavaScript events. Events are actions that happen in the browser (clicks, key presses, form submissions, etc.).

Detailed Requirements:

1. Add click event listener using addEventListener() - The modern, preferred way to attach event handlers.
const button = document.querySelector("#myButton"); button.addEventListener("click", function(event) { console.log("Button clicked!"); console.log("Event target:", event.target); }); // Arrow function version: button.addEventListener("click", (e) => { console.log("Clicked!", e.target); });
2. Handle keyboard events - Listen for keydown, keyup, or keypress events.
document.addEventListener("keydown", (event) => { console.log("Key pressed:", event.key); // "Enter", "a", etc. console.log("Key code:", event.code); // "Enter", "KeyA", etc. console.log("Ctrl held?", event.ctrlKey); // true/false if (event.key === "Enter") { console.log("Enter was pressed!"); } });
3. Handle form events - Prevent default behavior and handle form data.
const form = document.querySelector("form"); form.addEventListener("submit", (event) => { event.preventDefault(); // Stop form from submitting/reloading const formData = new FormData(form); const name = formData.get("name"); // Or: const name = document.querySelector("#name").value; console.log("Form submitted with name:", name); });
4. Use the event object - Contains useful information about the event.
element.addEventListener("click", (event) => { event.target; // Element that triggered the event event.currentTarget; // Element listener is attached to event.type; // "click", "keydown", etc. event.preventDefault(); // Stop default behavior event.stopPropagation(); // Stop event bubbling });
5. Event delegation - Attach listener to parent, handle children efficiently.
// Instead of adding listener to each button: document.querySelector("#buttonContainer").addEventListener("click", (e) => { if (e.target.matches("button")) { console.log("Button clicked:", e.target.textContent); } });
6. Remove event listeners - Clean up when no longer needed.
const handleClick = () => console.log("Clicked!"); button.addEventListener("click", handleClick); // Later... button.removeEventListener("click", handleClick);
💡 Pro Tips:
• Always use addEventListener over onclick attributes
• Use event delegation for dynamically added elements
event.preventDefault() for links/forms you want to handle with JS
• Arrow functions can't be used with removeEventListener (no reference)
• Use { once: true } option for one-time listeners

⚠️ Common Mistakes to Avoid:
• Calling function instead of passing reference: addEventListener("click", fn())
• Forgetting event.preventDefault() for form submissions
• Not removing event listeners (memory leaks in SPAs)

Expected Output:
Event listener added! Button clicked! Key pressed: Enter Form submitted - Name: John Event delegation working!

Requirements Checklist

Add a click event listener using addEventListener()
Handle a keyboard event (keydown/keyup)
Handle a form submit event with preventDefault()
Access event.target in an event handler
Implement event delegation
Define a named function for event handling
Console Output
// Click "Run Code" to execute your JavaScript
Hints & Tips
• Click: element.addEventListener("click", handler)
• Keyboard: document.addEventListener("keydown", handler)
• Form: form.addEventListener("submit", handler)
• Prevent default: event.preventDefault()
• Event target: event.target gives clicked element
• Delegation: if (event.target.matches("selector"))
Progress: 0/6
Score: 0/100
0%

Lab Results

Review feedback below

Lab 12: Classes & Object-Oriented Programming
Advanced
Coding Challenge
Your Task: Learn ES6 classes and object-oriented programming concepts in JavaScript. Classes provide a cleaner syntax for creating objects and implementing inheritance.

Detailed Requirements:

1. Create a class with constructor - The constructor method is called when creating new instances.
class Person { constructor(name, age) { this.name = name; // Instance property this.age = age; } } const person = new Person("Alice", 25);
2. Add instance methods - Methods that operate on instance data using this.
class Person { constructor(name, age) { this.name = name; this.age = age; } greet() { return `Hello, I'm ${this.name}`; } haveBirthday() { this.age++; return `Happy birthday! Now ${this.age} years old.`; } }
3. Add static methods - Methods called on the class itself, not instances.
class MathUtils { static add(a, b) { return a + b; } static PI = 3.14159; // Static property } MathUtils.add(5, 3); // 8 (called on class) MathUtils.PI; // 3.14159
4. Add getters and setters - Control access to properties.
class Circle { constructor(radius) { this._radius = radius; // Convention: _ for private } get radius() { return this._radius; } set radius(value) { if (value > 0) this._radius = value; } get area() { return Math.PI * this._radius ** 2; } }
5. Implement inheritance with extends - Create child classes that inherit from parent classes.
class Animal { constructor(name) { this.name = name; } speak() { return `${this.name} makes a sound`; } } class Dog extends Animal { constructor(name, breed) { super(name); // MUST call super() first! this.breed = breed; } speak() { return `${this.name} barks!`; // Override parent method } }
6. Use super to call parent methods
class Cat extends Animal { speak() { const parentSound = super.speak(); // Call parent method return `${parentSound}... actually, ${this.name} meows!`; } }
💡 Pro Tips:
• Classes are "syntactic sugar" over JavaScript's prototype-based inheritance
• Use # prefix for truly private fields: #privateField
instanceof checks if object is instance of a class
• Classes are not hoisted like function declarations
• Methods are automatically in "strict mode"

⚠️ Common Mistakes to Avoid:
• Forgetting new keyword when creating instances
• Not calling super() in child constructor
• Using arrow functions for methods (they don't bind this)

Expected Output:
Created: Person { name: 'Alice', age: 25 } Greeting: Hello, I'm Alice Static method: 8 Circle area: 78.54 Dog says: Buddy barks!

Requirements Checklist

Create a class with a constructor
Add instance methods to the class
Add a static method
Add a getter or setter
Create a child class using extends
Use super() to call parent constructor/methods
Console Output
// Click "Run Code" to execute your JavaScript
Hints & Tips
• Class syntax: class ClassName { constructor() {} }
• Constructor: constructor(params) { this.prop = params; }
• Instance method: methodName() { return this.prop; }
• Static method: static methodName() { }
• Getter: get propName() { return this._prop; }
• Inheritance: class Child extends Parent { }
Progress: 0/6
Score: 0/100
0%

Lab Results

Review feedback below