script.js file.Exercises 1โ5: JavaScript Core
Exercise 1 โ Variables & Types
Create variables for: your name (string), age (number), whether you're a student (boolean), and a list of your top 3 programming languages (array). Log each one with its type using typeof.
Show Answer
const name = "Uzair";
const age = 25;
const isStudent = true;
const languages = ["Python", "JavaScript", "SQL"];
console.log(name, typeof name);
console.log(age, typeof age);
console.log(isStudent, typeof isStudent);
console.log(languages, typeof languages);Exercise 2 โ Functions
Write three versions of the same function (convert Celsius to Fahrenheit): as a function declaration, a function expression, and an arrow function. Test all three with 100ยฐC.
Show Answer
// Declaration
function toF1(c) { return c * 9/5 + 32; }
// Expression
const toF2 = function(c) { return c * 9/5 + 32; };
// Arrow
const toF3 = c => c * 9/5 + 32;
console.log(toF1(100)); // 212
console.log(toF2(100)); // 212
console.log(toF3(100)); // 212Exercise 3 โ Array Methods
Given const nums = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3], use array methods to: (a) get unique values only, (b) square all values, (c) filter values greater than 4, (d) get their sum. One line each.
Show Answer
const nums = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3];
// a) Unique
const unique = [...new Set(nums)];
// b) Squared
const squared = nums.map(n => n ** 2);
// c) Greater than 4
const big = nums.filter(n => n > 4);
// d) Sum
const sum = nums.reduce((acc, n) => acc + n, 0);
console.log(unique); // [3,1,4,5,9,2,6]
console.log(squared); // [9,1,16,1,25,81,4,36,25,9]
console.log(big); // [5,9,6,5]
console.log(sum); // 39Exercise 4 โ Object Destructuring
Given a user object, destructure it to extract: name, email, and the city from the nested address. Then use spread to create an updated copy with a different age.
Show Answer
const user = {
name: "Alice",
age: 25,
email: "alice@example.com",
address: { city: "London", postcode: "EC1A 1BB" }
};
const { name, email, address: { city } } = user;
console.log(name, email, city); // Alice alice@example.com London
const updated = { ...user, age: 26 };
console.log(updated.age); // 26
console.log(user.age); // 25 (original unchanged)Exercise 5 โ Error Handling
Write a function divide(a, b) that throws an error if b is 0. Wrap calls in try/catch and log a helpful message for each case. Test with valid and invalid inputs.
Show Answer
function divide(a, b) {
if (b === 0) throw new Error("Cannot divide by zero");
return a / b;
}
[{a:10,b:2}, {a:7,b:0}, {a:9,b:3}].forEach(({a, b}) => {
try {
console.log(`${a} / ${b} = ${divide(a, b)}`);
} catch (err) {
console.error(`Error for ${a}/${b}: ${err.message}`);
}
});Exercises 6โ10: DOM & Events
index.html with a linked script.js. Add elements as needed per exercise.Exercise 6 โ DOM Selection & Modification
Create a page with an <h1> and 3 <p> tags. Using JavaScript (not CSS): change the h1 colour to red, double the font-size of all paragraphs, add a CSS class "highlight" to the second paragraph.
Show Answer
// HTML setup:
// <h1 id="title">Hello</h1>
// <p>Para 1</p> <p>Para 2</p> <p>Para 3</p>
const title = document.querySelector("h1");
title.style.color = "red";
const paras = document.querySelectorAll("p");
paras.forEach(p => {
const current = parseFloat(getComputedStyle(p).fontSize);
p.style.fontSize = (current * 2) + "px";
});
paras[1].classList.add("highlight");Exercise 7 โ Live Input Counter
Create a textarea with a character counter below it (e.g., "42 / 280 characters"). The counter updates in real-time as the user types. Turn the text red when over 250 characters.
Show Answer
// HTML:
// <textarea id="msg" rows="4" maxlength="280"></textarea>
// <div id="counter">0 / 280</div>
const textarea = document.getElementById("msg");
const counter = document.getElementById("counter");
textarea.addEventListener("input", () => {
const len = textarea.value.length;
counter.textContent = `${len} / 280`;
counter.style.color = len > 250 ? "red" : "";
});Exercise 8 โ Show/Hide Toggle
Create a "Spoiler" button. When clicked it shows hidden content (a paragraph of text). When clicked again it hides it. Animate the transition smoothly.
Show Answer
// HTML:
// <button id="toggle">Show Spoiler</button>
// <p id="spoiler" style="display:none;transition:opacity 0.3s">
// The butler did it!
// </p>
const btn = document.getElementById("toggle");
const spoiler = document.getElementById("spoiler");
btn.addEventListener("click", () => {
const hidden = spoiler.style.display === "none";
spoiler.style.display = hidden ? "block" : "none";
spoiler.style.opacity = hidden ? "1" : "0";
btn.textContent = hidden ? "Hide Spoiler" : "Show Spoiler";
});Exercise 9 โ Form Validation
Create a sign-up form (username, email, password, confirm password). Validate on submit: username min 3 chars, valid email format, password min 8 chars with a number, passwords match. Show inline error messages.
Show Answer
document.getElementById("signupForm").addEventListener("submit", e => {
e.preventDefault();
const username = document.getElementById("username").value;
const email = document.getElementById("email").value;
const pass = document.getElementById("password").value;
const confirm = document.getElementById("confirm").value;
const errors = [];
if (username.length < 3)
errors.push("Username must be at least 3 characters");
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email))
errors.push("Enter a valid email address");
if (pass.length < 8 || !/\d/.test(pass))
errors.push("Password must be 8+ chars and contain a number");
if (pass !== confirm)
errors.push("Passwords do not match");
const errDiv = document.getElementById("errors");
if (errors.length) {
errDiv.innerHTML = errors.map(e => `<p style="color:red">${e}</p>`).join("");
} else {
errDiv.innerHTML = "<p style='color:green'>Success!</p>";
}
});Exercise 10 โ Keyboard Shortcut Handler
Listen for keyboard shortcuts: Ctrl+S โ log "Saved!", Ctrl+Z โ log "Undo!", Escape โ close any open modal. Prevent browser defaults where applicable.
Show Answer
document.addEventListener("keydown", e => {
if (e.ctrlKey && e.key === "s") {
e.preventDefault();
console.log("Saved!");
} else if (e.ctrlKey && e.key === "z") {
e.preventDefault();
console.log("Undo!");
} else if (e.key === "Escape") {
const modal = document.querySelector(".modal");
if (modal) modal.style.display = "none";
console.log("Modal closed (Escape)");
}
});Exercises 11โ15: Arrays, Logic & Async
Exercise 11 โ Sort & Search
Given an array of 10 people objects (name, age, city), write functions to: sort by age ascending, filter by city, find a person by name, and get the average age.
Show Answer
const people = [
{name:"Alice", age:25, city:"London"},
{name:"Bob", age:30, city:"Paris"},
{name:"Carol", age:22, city:"London"},
{name:"Dave", age:35, city:"Berlin"},
{name:"Eve", age:28, city:"London"},
];
const byAge = [...people].sort((a,b) => a.age - b.age);
const inLondon = people.filter(p => p.city === "London");
const findAlice = people.find(p => p.name === "Alice");
const avgAge = people.reduce((s,p) => s + p.age, 0) / people.length;
console.log("Sorted:", byAge.map(p => p.name));
console.log("London:", inLondon.map(p => p.name));
console.log("Found:", findAlice);
console.log("Avg age:", avgAge);Exercise 12 โ Debounce
Implement a debounce function that wraps another function and only calls it after the user stops typing for a specified delay. Test it on a search input that logs the query.
Show Answer
function debounce(fn, delay) {
let timer;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}
const search = debounce((query) => {
console.log("Searching for:", query);
}, 500);
// Attach to input:
document.getElementById("searchInput").addEventListener("input", e => {
search(e.target.value);
});Exercise 13 โ Local Storage
Build a preferences saver: let the user pick a theme (dark/light), font size (small/medium/large), and language. Save to localStorage. On page load, restore saved preferences automatically.
Show Answer
const defaults = { theme: "dark", fontSize: "medium", language: "en" };
function loadPrefs() {
const saved = JSON.parse(localStorage.getItem("prefs")) || defaults;
applyPrefs(saved);
document.getElementById("theme").value = saved.theme;
document.getElementById("fontSize").value = saved.fontSize;
document.getElementById("language").value = saved.language;
}
function applyPrefs(prefs) {
document.body.className = prefs.theme;
document.body.style.fontSize = { small:"14px", medium:"16px", large:"20px" }[prefs.fontSize];
console.log(`Language: ${prefs.language}`);
}
document.getElementById("saveBtn").addEventListener("click", () => {
const prefs = {
theme: document.getElementById("theme").value,
fontSize: document.getElementById("fontSize").value,
language: document.getElementById("language").value,
};
localStorage.setItem("prefs", JSON.stringify(prefs));
applyPrefs(prefs);
console.log("Saved:", prefs);
});
loadPrefs();Exercise 14 โ Fetch & Display
Fetch users from https://jsonplaceholder.typicode.com/users and display them as cards on the page. Each card shows: name, email, company name, and website. Add a loading spinner while fetching.
Show Answer
// HTML: <div id="loading">Loading...</div><div id="cards"></div>
async function loadUsers() {
const loading = document.getElementById("loading");
const cards = document.getElementById("cards");
loading.style.display = "block";
try {
const res = await fetch("https://jsonplaceholder.typicode.com/users");
const users = await res.json();
cards.innerHTML = users.map(u => `
<div style="border:1px solid #333;padding:16px;border-radius:8px;margin:12px 0">
<h3>${u.name}</h3>
<p>๐ง ${u.email}</p>
<p>๐ข ${u.company.name}</p>
<p>๐ ${u.website}</p>
</div>
`).join("");
} catch (err) {
cards.innerHTML = `<p style="color:red">Error: ${err.message}</p>`;
} finally {
loading.style.display = "none";
}
}
loadUsers();Exercise 15 โ Promise Chain
Write a function that simulates a multi-step process using Promises: step 1 validates input (1s delay), step 2 saves to "database" (2s delay), step 3 sends confirmation email (1s delay). Log progress at each step.
Show Answer
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
async function processSignup(username) {
console.log("Starting signup for:", username);
console.log("Step 1: Validating...");
await delay(1000);
if (username.length < 3) throw new Error("Username too short");
console.log("โ Validation passed");
console.log("Step 2: Saving to database...");
await delay(2000);
const userId = Math.floor(Math.random() * 10000);
console.log(`โ Saved with ID: ${userId}`);
console.log("Step 3: Sending confirmation email...");
await delay(1000);
console.log("โ Email sent!");
return { userId, username };
}
processSignup("Uzair")
.then(result => console.log("Done!", result))
.catch(err => console.error("Failed:", err.message));Exercises 16โ20: Mini Projects
Exercise 16 โ Countdown Timer
Build a countdown timer: user enters minutes, clicks Start. Timer counts down and shows MM:SS. Buttons: Start, Pause, Reset. When it hits 0, play an alert sound (or show an alert).
Show Answer
// HTML: <input id="mins" type="number" value="5"/>
// <div id="display">05:00</div>
// <button id="start">Start</button>
// <button id="pause">Pause</button>
// <button id="reset">Reset</button>
let total, timer, running = false;
function format(secs) {
const m = String(Math.floor(secs/60)).padStart(2,"0");
const s = String(secs%60).padStart(2,"0");
return `${m}:${s}`;
}
document.getElementById("start").addEventListener("click", () => {
if (!running) {
if (!total) total = parseInt(document.getElementById("mins").value) * 60;
running = true;
timer = setInterval(() => {
total--;
document.getElementById("display").textContent = format(total);
if (total <= 0) {
clearInterval(timer);
running = false;
alert("Time's up!");
}
}, 1000);
}
});
document.getElementById("pause").addEventListener("click", () => {
clearInterval(timer); running = false;
});
document.getElementById("reset").addEventListener("click", () => {
clearInterval(timer); running = false; total = 0;
document.getElementById("display").textContent = "00:00";
});Exercise 17 โ Quiz App
Build a 5-question quiz: show one question at a time with 4 options, track score, show result at end. Include a progress bar and allow restart.
Show Answer
const questions = [
{q:"What does HTML stand for?", options:["HyperText Markup Language","High Transfer Markup Language","HyperText Machine Language","None"],correct:0},
{q:"Which of these is NOT a JavaScript data type?", options:["String","Boolean","Float","Undefined"],correct:2},
{q:"What does CSS stand for?", options:["Cascading Style Sheets","Computer Style System","Creative Syntax Styles","None"],correct:0},
{q:"Which method adds an element to the end of an array?", options:["push()","pop()","shift()","append()"],correct:0},
{q:"What does SQL stand for?", options:["Structured Query Language","Simple Query Logic","Standard Question Language","None"],correct:0},
];
let current = 0, score = 0;
function showQuestion() {
const q = questions[current];
document.getElementById("question").textContent = q.q;
document.getElementById("progress").textContent = `Q${current+1}/${questions.length}`;
document.getElementById("options").innerHTML = q.options.map((opt,i) =>
`<button onclick="answer(${i})">${opt}</button>`
).join("");
}
function answer(i) {
if (i === questions[current].correct) score++;
current++;
if (current < questions.length) showQuestion();
else document.getElementById("app").innerHTML = `
<h2>Score: ${score}/${questions.length}</h2>
<button onclick="restart()">Restart</button>
`;
}
function restart() { current = 0; score = 0; showQuestion(); }
showQuestion();Exercise 18 โ Drag & Drop Kanban
Build a 3-column Kanban board (To Do, In Progress, Done) where tasks can be dragged between columns. Allow adding new tasks. Save state to localStorage.
draggable, ondragstart, ondrop). Stretch goal: add task priority colours.Exercise 19 โ Weather App
Build a weather app using the Open-Meteo API (free, no API key): fetch current weather for a city using its coordinates. Show temperature, wind speed, and weather code. Let the user enter a city name.
Show Answer
// Open-Meteo is free and needs lat/lon. Use Nominatim for geocoding.
async function getWeather(city) {
// Step 1: geocode city name to lat/lon
const geoRes = await fetch(`https://nominatim.openstreetmap.org/search?q=${city}&format=json&limit=1`);
const geoData = await geoRes.json();
if (!geoData.length) throw new Error("City not found");
const { lat, lon, display_name } = geoData[0];
// Step 2: get weather
const weatherRes = await fetch(
`https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}¤t_weather=true`
);
const weather = await weatherRes.json();
const cw = weather.current_weather;
document.getElementById("result").innerHTML = `
<h3>${display_name.split(",")[0]}</h3>
<p>๐ก๏ธ Temperature: ${cw.temperature}ยฐC</p>
<p>๐จ Wind speed: ${cw.windspeed} km/h</p>
<p>๐ Updated: ${cw.time}</p>
`;
}
document.getElementById("searchBtn").addEventListener("click", async () => {
const city = document.getElementById("cityInput").value;
try { await getWeather(city); }
catch(e) { document.getElementById("result").innerHTML = `Error: ${e.message}`; }
});Exercise 20 โ Full CRUD App
Build a full Notes CRUD app: Create notes (title + body), Read/list all notes, Update (click to edit), Delete. Store in localStorage. Add search/filter. Style it properly.