JS 101
JavaScript is the third pillar of the web. HTML is the skeleton, CSS the skin, JavaScript the muscles. From your first line to an interactive page.
Styling first? CSS 101 comes before JS 101.
Chapter 01
Introduction & setup
What is JavaScript — and how do we include it?
The browser has a built-in JS engine. No server, no installation.
script.jsin the MyFirst Site folder<script>on all 4 pages, before </body>console.log() shows what is insideHTML is the skeleton, CSS the skin, JavaScript the muscles.
script.js<script src defer>- console with F12
JavaScript is the third pillar of the web. HTML is the skeleton, CSS the skin — and JavaScript the muscles. In this chapter you learn what JS can do, how to include it in your MyFirst Site, and you write your first line of JS.
- What JavaScript is and why it is the third pillar of the web
- Understanding the difference between HTML, CSS and JavaScript
- Including JavaScript in your MyFirst Site — the right way!
- Writing your first line of JS and testing it in the browser
- Getting to know the browser console, your most important tool
1.1 · What is JavaScript?
| Technology | Task | Example |
|---|---|---|
| HTML | Structure & content | <button>Click me</button> |
| CSS | Look & layout | button { background: blue; } |
| JavaScript | Behaviour & interaction | button.onclick = () => alert('Hello!'); |
1.2 · How does JavaScript "think"?
JS reads your code line by line, from top to bottom. Like a cook following a recipe — step by step.
// JS reads this first let name = "Mikey"; // Step 1: create a variable name = "Dante"; // Step 2: change the value console.log(name); // Step 3: print "Dante" // This will NOT print "Mikey" — name was changed!
1.3 · Including JavaScript — the right way
There are three ways to include JS — we learn all three, but we consistently use the best one.
<button onclick="alert('Hi')">Click</button> <!-- Works, but hard to maintain! -->
<head> <script src="script.js"></script> <!-- Problem: JS loads before the HTML is ready! --> </head>
<!-- Always include JS just before </body> --> <script src="script.js" defer></script> </body> </html>
defer do? It tells the browser: "Download the JS file now, but only run it once the whole HTML has finished loading." That way your JS finds all the HTML elements it needs.// ======================================== // MyFirst Site — script.js // JS 101 learning project // ======================================== // Our first "sign of life" console.log("✅ script.js loaded successfully!");
1.4 · The browser console
The console is like a direct phone line to JavaScript. Here you see what your code does — and where it goes wrong.
| Browser | Shortcut | Alternatively |
|---|---|---|
| Chrome / Edge | F12 or Ctrl+Shift+J | Right-click → "Inspect" → Console |
| Firefox | F12 or Ctrl+Shift+K | Right-click → "Inspect Element" → Console |
| Safari | Cmd+Option+C | Developer menu → JavaScript Console |
> 2 + 2 < 4 > console.log("Hello World!") < Hello World! > console.error("This is an error!") < ❌ This is an error! > console.warn("Careful!") < ⚠️ Careful!
console.log() calls. Visitors should not see your debug output.1.5 · Your first lines of JS
// The current date and time const now = new Date(); console.log("Page loaded on:", now.toLocaleString("en-GB")); // Read the page title console.log("Page title:", document.title); // Count how many links are on the page const allLinks = document.querySelectorAll("a"); console.log("Number of links:", allLinks.length);
What is happening here?
new Date()— JS asks the browser: "What time is it right now?"document.title— JS reads the<title>tag from the HTMLquerySelectorAll("a")— JS finds ALL links on the page
The word document is your gateway to the HTML — through document JS can read and change everything on the page. More on that in chapter 6!
- Include
script.jscorrectly in all four pages of your MyFirst Site - Open each page and check whether script.js loaded successfully! appears in the console
- Add your own
console.log()with your name - Type directly into the console:
document.body.style.background = "red"— what happens? Why is the change gone after reloading?
→ On to chapter 2: variables & data types
Chapter 02
Variables & data types
How JavaScript stores data — and which kinds there are.
A variable is a labelled container. It holds a value of a certain type.
let changeable, const fixed"Mikey"350truevar is old. Use let or const.
let consttypeof
Variables are containers for data. Everything your program needs to remember — numbers, text, states — lives in variables.
2.1 · let, const and var
| Keyword | Use | Changeable? |
|---|---|---|
| let | Default choice for values that change | ✅ Yes |
| const | For values that do not change | ❌ No |
| var | Old — please do not use any more | ⚠️ Problematic |
// ✅ let — can be changed let points = 0; points = 10; // OK // ✅ const — cannot be reassigned const name = "Mikey"; // name = "Dante"; // ❌ Error! const cannot be changed // ❌ var — avoid it var old = "do not use any more";
const — and only switch to let when you know the value will change. You never use var.2.2 · The 6 most important data types
| Type | Example | Description |
|---|---|---|
| String | "Hello" or 'World' | Text, always in quotation marks |
| Number | 42 or 3.14 | Numbers (whole or with decimals) |
| Boolean | true or false | True or false |
| null | null | Deliberately empty |
| undefined | undefined | Not assigned yet |
| Object | { name: 'Mikey' } | A collection of data |
const greeting = "Hello MyKeyZ!"; // String const points = 42; // Number const isLoggedIn = false; // Boolean const user = null; // null — no user yet let result; // undefined until a value is assigned const cave = { name: "Mikey’s Center", points: 100 }; // Object console.log(typeof greeting); // "string" console.log(typeof points); // "number" console.log(typeof null); // "object" ← well-known JS bug!
"object" — a historical bug in JS that was never fixed for compatibility reasons. null is not an object!2.3 · Template literals — strings with variables
const name = "Mikey"; const points = 42; // ❌ Old way — clumsy console.log("Hello " + name + "! You have " + points + " points."); // ✅ Template literal — clean and readable console.log(`Hello ${name}! You have ${points} points.`); // Expressions work too console.log(`Double: ${points * 2} points`); // Double: 84 points
Shift+^ then the space bar.2.4 · Type coercion
// Number + string = string (concatenation!) console.log(1 + "2"); // "12" not 3! // Other operators force a number console.log("5" - 2); // 3 console.log("5" * 2); // 10 // Convert explicitly — always better! const input = "42"; const num = Number(input); // 42 as a number const text = String(42); // "42" as text
- Create 5 variables in script.js — one for each main type
- Output all 5 with
console.log()andtypeof - Build a template literal that shows your name and the number of tutorials
- What does
console.log(typeof typeof 42)output? Why?
Chapter 03
Operators & conditions
Calculate, compare, decide — the tools of the logician.
A condition checks something. Depending on the answer, a different path runs.
pointsifIs it true?ifelseAlways === instead of ==. Three equals signs check type and value.
+ - * / %=== !== < >if else&& ||
3.1 · Arithmetic operators
| Operator | Meaning | Example | Result |
|---|---|---|---|
| + | Addition | 5 + 3 | 8 |
| - | Subtraction | 10 - 4 | 6 |
| * | Multiplication | 3 * 4 | 12 |
| / | Division | 15 / 3 | 5 |
| % | Modulo (remainder) | 10 % 3 | 1 |
| ** | Power | 2 ** 8 | 256 |
| ++ | Increment (+1) | i++ | i = i + 1 |
3.2 · Comparison operators — == vs ===
== converts types automatically and can lead to unexpected results. === (three equals signs) compares type AND value — always safe.| Operator | Meaning | Example | Result |
|---|---|---|---|
| == | Equal (with type conversion) | "5" == 5 | true ⚠️ |
| === | Strictly equal | "5" === 5 | false ✅ |
| !== | Strictly not equal | "5" !== 5 | true |
| < | Less than | 3 < 5 | true |
| >= | Greater than or equal | 5 >= 5 | true |
3.3 · Logical operators
// && (AND) — both must be true const canEnter = age >= 16 && hasAccount; // || (OR) — at least one must be true const hasAccess = isAdmin || hasPremium; // ! (NOT) — flips it const isGuest = !isLoggedIn; // ?? (Nullish Coalescing) — if null or undefined const displayName = username ?? "Guest";
3.4 · if / else if / else
const points = 75; if (points >= 90) { console.log("Excellent! 🏆"); } else if (points >= 70) { console.log("Well done! ✅"); } else if (points >= 50) { console.log("Passed 👍"); } else { console.log("Try again 💪"); } // Output: Well done! ✅
3.5 · Ternary operator
// Long form let status; if (isLoggedIn) { status = "Welcome!"; } else { status = "Please log in"; } // Short form (ternary) const status = isLoggedIn ? "Welcome!" : "Please log in"; const role = hasPremium ? "Premium Member" : "Free Member";
- Write an if/else chain that outputs "Good morning", "Good afternoon" or "Good night" depending on the time
- Use
new Date().getHours()for the current hour - Turn the if/else into a ternary operator
- What is the difference between
0 == falseand0 === false? Test it!
Chapter 04
Loops & arrays
Managing lists and repeating code — the most powerful duo.
An array is a list. A loop goes through it item by item.
for, forEachThe first item is [0], not [1].
[ ]push pop lengthfor forEachmap filter
4.1 · Arrays
const tutorials = ["HTML 101", "CSS 101", "JS 101"]; // Access by index (starts at 0!) console.log(tutorials[0]); // "HTML 101" console.log(tutorials.length); // 3 // Add / remove an element tutorials.push("Python 101"); // to the end const last = tutorials.pop(); // remove the last one
4.2 · The most important array methods
| Method | What it does | Returns |
|---|---|---|
| push(x) | Adds x to the end | New length |
| pop() | Removes the last element | The element |
| filter(fn) | Filters by a condition | New array |
| map(fn) | Transforms every element | New array |
| find(fn) | Finds the first matching element | The element |
| includes(x) | Checks whether x is included | true / false |
| join(sep) | Joins into a string | String |
const points = [45, 78, 92, 23, 88, 67]; // filter — only points above 70 const good = points.filter(p => p > 70); console.log(good); // [78, 92, 88] // map — double them all const doubled = points.map(p => p * 2); // find — first number above 80 const firstBest = points.find(p => p > 80); console.log(firstBest); // 92
4.3 · Loops
// Classic for loop for (let i = 0; i < 5; i++) { console.log(`Round ${i}`); } // for...of — elegantly through arrays const colours = ["Red", "Green", "Blue"]; for (const colour of colours) { console.log(colour); } // forEach — with index colours.forEach((colour, index) => { console.log(`${index}: ${colour}`); });
for...of or forEach — they run through automatically.- Create an array with 5 tutorial names and output each one with
for...of - Filter out all tutorials that have "101" in their name
- Write a loop that counts from 1–10 and outputs "even" for even numbers
- What does
[1, 2, 3].map(x => x ** 2)do? Work it out in your head first, then test it!
Chapter 05
Functions
Write code once — call it as often as you like.
A function takes something in, does its work and returns a result.
namegreet()the code block"Hello Mikey!"functionreturn() =>
Functions are reusable blocks of code. CheckMate consists of dozens of functions — here you learn the basis of everything.
5.1 · Declaring and calling
function greet(name) { return `Hello ${name}! Welcome to the Center.`; } console.log(greet("Mikey")); // Hello Mikey! Welcome to the Center. function calculateScore(correct, total) { const percent = (correct / total) * 100; return `${percent.toFixed(1)}%`; } console.log(calculateScore(7, 10)); // "70.0%"
5.2 · Arrow functions
// Classic function function double(n) { return n * 2; } // Arrow Function — same function, shorter const double = (n) => { return n * 2; }; // Even shorter — for a one-line return const double = n => n * 2; // All three do the same thing! console.log(double(21)); // 42
return, you can leave out the curly braces and return. const square = n => n * n; — neat!5.3 · Default parameters & scope
// Default Parameter function greet(name = 'Guest') { return `Hello ${name}!`; } greet('Mikey'); // 'Hello Mikey!' greet(); // 'Hello Guest!' — the default kicks in // Scope — global vs local variable const appName = "MyKeyZ"; // global — visible everywhere function showApp() { const internal = 'only here'; // local — only in this function console.log(appName); // ✅ } // console.log(internal); // ❌ Error!
5.4 · Callbacks
function process(num, operation) { return operation(num); } const double = n => n * 2; const square = n => n * n; console.log(process(5, double)); // 10 console.log(process(5, square)); // 25 // You already know callbacks! (from chapter 4) [1,2,3].map(n => n * 10); // map takes a callback function
- Write a function
calculateBMI(weight, height)that returns the BMI - Write the same function as an arrow function
- Build a function
rateBMI(bmi)that returns "Underweight", "Normal" or "Overweight" - Combine both:
rateBMI(calculateBMI(70, 1.75))— what comes out?
Chapter 06
DOM manipulation
JavaScript talks to your HTML — and can change everything.
The DOM is the bridge: find, change and add elements without reloading the page.
script.jsyour codeIf querySelector finds nothing, it returns null. Check the selector.
getElementById querySelectortextContent classListcreateElement
The DOM (Document Object Model) is the bridge between JS and HTML. With DOM manipulation you can read, change, add or remove any element — without reloading the page.
6.1 · Finding elements
| Method | Finds | Returns |
|---|---|---|
| getElementById('id') | One element by ID | Element or null |
| querySelector('css') | First matching element | Element or null |
| querySelectorAll('css') | All matching elements | NodeList |
// By ID — fastest method const cave = document.getElementById('cave'); // By CSS selector — most flexible method const title = document.querySelector('.title'); const firstLink = document.querySelector('nav a'); // All elements const allButtons = document.querySelectorAll('button'); allButtons.forEach(btn => console.log(btn.textContent));
6.2 · Reading and changing content
const title = document.querySelector('h1'); title.textContent = 'Hello Mikey!'; // change the text title.innerHTML = '<em>Italic</em> and normal'; // set HTML // Change CSS directly title.style.color = 'var(--coral)'; // Control classes const card = document.querySelector('.card'); card.classList.add('active'); card.classList.remove('hidden'); card.classList.toggle('darkmode'); // on/off
textContent for plain text — innerHTML only for your own HTML code. Never set user input directly as innerHTML (XSS risk)!6.3 · Creating and inserting elements
const newItem = document.createElement('li'); newItem.textContent = 'New tutorial'; newItem.classList.add('tutorial-item'); const list = document.querySelector('#tutorial-list'); list.appendChild(newItem); // to the end list.prepend(newItem); // to the start newItem.remove(); // remove
- Add a button:
<button id="magic">Click me!</button> - Write JS that sets the background to a random colour on click
- Tip:
document.body.style.backgroundandMath.random() - Show a message in the HTML (not alert!) — create a
<p id="message">
Chapter 07
Events & interactivity
Reacting to clicks, keys and mouse movements.
An event happens, a listener is waiting, a function answers.
click, input, keydownaddEventListenerlistensonclick = overwrites the previous handler. addEventListener does not.
addEventListenerclick input submit keydowne.target
7.1 · addEventListener
const btn = document.querySelector('#myButton'); // ❌ Not like this — overwrites earlier handlers btn.onclick = () => console.log("Click 1"); btn.onclick = () => console.log("Click 2"); // overwrites Click 1! // ✅ Like this — several handlers possible btn.addEventListener('click', () => console.log("Click 1")); btn.addEventListener('click', () => console.log("Click 2")); // both run!
7.2 · The most important events
| Event | When it fires | Element |
|---|---|---|
| click | Mouse click | button, a, div |
| input | On every input | input, textarea |
| change | When the field is left | input, select |
| submit | Submitting a form | form |
| keydown | Key pressed | document, input |
| mouseover | Mouse over it | div, img |
| DOMContentLoaded | HTML finished loading | document |
7.3 · The event object & a practical example
const searchField = document.querySelector('#search'); const list = document.querySelectorAll('.tutorial-item'); searchField.addEventListener('input', (e) => { const searchText = e.target.value.toLowerCase(); list.forEach(item => { const text = item.textContent.toLowerCase(); item.style.display = text.includes(searchText) ? '' : 'none'; }); }); // Type, type → filtered live!
7.4 · Event delegation
// ✅ Event delegation — one listener on the container document.querySelector('#container').addEventListener('click', (e) => { if (e.target.classList.contains('btn')) { handler(e.target); } }); // Also works for buttons added later!
- Build a character counter: show live how many characters have been typed into a text field
- Keyboard shortcut:
Ctrl+Kshould make an alert appear - Toggle: a button switches a
divbetween visible and invisible - 5 coloured buttons — a click changes the body background to that colour
Chapter 08
Objects & JSON
The most important data structure in JS — and the format of the internet.
An object groups related values. As JSON text it travels to storage and servers.
{ name, points }data.name{ }obj.key obj["key"]JSON.stringify JSON.parse
8.1 · Creating objects
const user = { name: "Mikey", points: 350, premium: true, cave: "Mikey’s Creative Lab", }; // Dot notation console.log(user.name); // 'Mikey' // Bracket notation (for dynamic keys) const field = "name"; console.log(user[field]); // 'Mikey' // Add a property user.badges = ['HTML Master', 'CSS Pro'];
8.2 · Methods, destructuring & spread
const cave = { name: "Mikey’s Center", visitors: 0, enter() { this.visitors++; return `Welcome to ${this.name}!`; } }; // Destructuring — unpack properties const { name, points } = user; // Spread — copy/extend an object const extended = { ...user, role: 'admin' };
8.3 · JSON
const user = { name: 'Mikey', points: 350 }; // JS object → JSON string const json = JSON.stringify(user); // '{"name":"Mikey","points":350}' // JSON string → JS object const data = JSON.parse('{"name":"Mikey","points":350}'); console.log(data.name); // 'Mikey' // Nicely formatted (for debugging) console.log(JSON.stringify(user, null, 2));
- Create an object for your Center with name, points, completed_tutorials (array) and premium
- Add two methods:
info()andcomplete_tutorial(name) - Serialise it with
JSON.stringify()and parse it back again - What happens when you use
JSON.stringify()on an object with a method?
Chapter 09
Fetch & async ⏳
Loading data from APIs — the web lives on it.
fetch asks an API. await waits for the answer while the page keeps running.
fetch(url)response.json()Without internet or on an error: try/catch catches it.
async awaitfetchtry catch
With fetch() you can load data from APIs — weather, exchange rates, user information. async/await makes it elegant.
9.1 · Synchronous vs. asynchronous
console.log('1'); setTimeout(() => console.log('2 (after 1 second)'), 1000); console.log('3'); // runs BEFORE the '2'! // Output: 1, 3, 2
9.2 · async / await — the clean way
async function loadWeather() { try { const response = await fetch( 'https://api.open-meteo.com/v1/forecast?latitude=47.42&longitude=9.37¤t_weather=true' ); const data = await response.json(); console.log('Temperature:', data.current_weather.temperature); } catch (error) { console.error('Error:', error); } } loadWeather();
What does await do?
awaitpauses execution inside the async function and waits for the promise- The rest of the page keeps running — no freezing!
asyncfunctions always return a promisetry/catchcatches errors — network errors, invalid JSON responses, etc.
9.3 · Showing API data on the page
async function showWeather() { const url = 'https://api.open-meteo.com/v1/forecast?latitude=47.42&longitude=9.37¤t_weather=true'; const display = document.querySelector('#weather'); display.textContent = 'Loading...'; try { const res = await fetch(url); const data = await res.json(); display.textContent = `St. Gallen: ${data.current_weather.temperature}°C`; } catch { display.textContent = "Error while loading"; } } document.querySelector('#loadBtn').addEventListener('click', showWeather);
- Call the Open-Meteo API for St. Gallen and show the temperature in the console
- Show the result on the page — in a
<div id="weather"> - Add a "Loading..." indicator while the request is running
- Recreate an error case — what happens with a wrong URL?
Chapter 10
localStorage & state
Storing data permanently — even after closing the tab.
localStorage stores text in the browser. It is still there after closing.
cavelocalStorageonly in this browser, text onlylocalStorage only stores strings. Convert objects with JSON first.
setItem getItem removeItemJSON.stringify JSON.parse
10.1 · localStorage basics
// Save — strings only! localStorage.setItem("username", "Mikey"); // Read const name = localStorage.getItem("username"); // Delete localStorage.removeItem("username"); // Objects with JSON const cave = { name: 'Mikey’s Center', points: 350 }; localStorage.setItem('cave', JSON.stringify(cave)); const loaded = JSON.parse(localStorage.getItem("cave")); console.log(loaded.name); // 'Mikey’s Center'
10.2 · State management pattern
// Load state (or default) let state = { count: JSON.parse(localStorage.getItem("count")) || 0 }; function render() { document.querySelector("#display").textContent = state.count; } function save() { localStorage.setItem("count", JSON.stringify(state.count)); } document.querySelector("#plus").addEventListener("click", () => { state.count++; render(); save(); }); render(); // Show initially
- Build a visitor counter: every time the page loads, the counter goes up
- Show the counter on the page
- Add a "Reset" button
- Also store the date of the last visit and show it
Chapter 11
JS in practice
Everything together — MyFirst Site becomes truly interactive.
Three functions make your MyFirst Site interactive.
script.jsone file for all pages- chapters 1 to 10
script.js
Now we bring everything together! In this chapter you make your MyFirst Site truly interactive — with everything you learnt in chapters 1–10.
11.1 · Dark mode toggle
// ── Darkmode ────────────────────────────────────── function initDarkmode() { const toggle = document.querySelector('#darkmode-toggle'); if (!toggle) return; const saved = localStorage.getItem("darkmode") === "true"; document.body.classList.toggle('dark', saved); toggle.addEventListener('click', () => { const isDark = document.body.classList.toggle('dark'); localStorage.setItem("darkmode", isDark); toggle.textContent = isDark ? '☀️ Lightmode' : '🌙 Darkmode'; }); } initDarkmode();
11.2 · Active navigation
// ── Active nav ──────────────────────────────────── function markActiveNavigation() { const currentPage = window.location.pathname.split('/').pop() || 'index.html'; document.querySelectorAll('nav a').forEach(link => { const linkTarget = link.getAttribute('href'); link.classList.toggle('active', linkTarget === currentPage); }); } markActiveNavigation();
11.3 · Live clock & smooth scroll
// ── Live clock ────────────────────────────────────── function startLiveClock() { const display = document.querySelector('#clock'); if (!display) return; function update() { display.textContent = new Date().toLocaleTimeString("en-GB"); } update(); setInterval(update, 1000); } startLiveClock(); // ── Smooth Scroll ───────────────────────────────── document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', (e) => { e.preventDefault(); const target = document.querySelector(anchor.getAttribute('href')); if (target) target.scrollIntoView({ behavior: "smooth" }); }); });
if (!toggle) return;). That way the same script.js can run on every page without errors.- Build all four functions into your MyFirst Site
- Add a
<button id="darkmode-toggle">🌙 Darkmode</button>to index.html - Insert a
<span id="clock">and test the live clock - Make the dark mode button change its emoji (/) depending on the current mode
Chapter 12
PWA basics
The final chapter — your site becomes an app.
A PWA is a website you can install and that also works offline.
This chapter unlocks when the Community Center starts.
Registration on mykeyz.ch is not open yet. As soon as the Community Center launches, this chapter will be unlocked.
What awaits you in chapter 12:
- What a PWA is and how it differs from a normal website
- Web app manifest — so your app can be installed
- Service worker — adding offline capability
- Push notifications — notifying users
- Building your own PWA project — based on CheckMate
This is no longer an exercise — this is real JavaScript!
- Including JavaScript in HTML — the right way!
- Variables, types and operators
- Arrays, loops and functions
- DOM manipulation and events
- Objects, JSON and APIs
- localStorage and state management
- MyFirst Site made fully interactive
PWA 101 — build your first real installable app with everything you have learnt!
→ PWA 101 is in preparation.