# JavaScript & HTML

Your script in a file of its own, the window object, timers and the first click on a button.

Multimedia & Creative Technology · 2.1 Webcoding · Lesson 4 · version 1.0.1 · 2026-10-14

Tags: javascript, html

Slides: <https://slides.mctantwerp.be/en/webcoding/04-javascript-and-html>

Speaker notes: <https://slides.mctantwerp.be/en/webcoding/04-javascript-and-html.notes.md>

<!-- slide 2 -->

## Agenda

1. A file of its own
2. The window object
3. Dialogs
4. Timers
5. Location and navigator
6. Events
7. Exercises

<!-- slide 3 -->

## 1. A file of its own

<!-- slide 4 -->

### So far

#### In the page

```html
<body>
  <h1>My website</h1>

  <script>
    document.write('Hello world');
  </script>
</body>
```

#### In Node

*index.js*

```js
console.log('Hello world');
```

```console
$ node index.js
Hello world
```

<!-- slide 5 -->

### Where that goes wrong

- Twenty lines of JavaScript in a script tag are fine. Two hundred, in between your HTML, and nobody finds anything back.
- A second page needs the same code. Copy, paste, and from then on every bug gets fixed twice.
- The browser downloads that JavaScript again with every single page.
- Your CSS moved to a file of its own a long time ago, for exactly these reasons.

<!-- slide 6 -->

### Link it with src

#### index.html

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>My website</title>
</head>
<body>
  <h1>My website</h1>

  <script src="script.js"></script>
</body>
</html>
```

#### script.js

```js
// Only JavaScript in here, no script tags
document.write('Hello world');
console.log('Hello from script.js');
```

> [!NOTE]
> You will also meet `<script src="script.js" defer>` in the head. We switch to that one with the DOM.

<!-- slide 7 -->

### Separation of concerns

*my-website*

```text
my-website/
├── index.html
├── about.html
├── style.css
└── script.js
```

- **One job per file.** HTML says what is on the page, CSS how it looks, JavaScript what it does.
- Every page loads the same script.js. A bug gets fixed in one place.
- The browser keeps the file in its cache. The second page does not download it again.

<!-- slide 8 -->

### The path in src

| src | Where the browser looks |
| --- | --- |
| `script.js` | In the same folder as the HTML file |
| `js/script.js` | In a folder js, next to the HTML file |
| `../script.js` | One folder up |
| `/js/script.js` | From the root of the site, whatever page you are on |
| `https://...` | On another server |

> [!TIP]
> The same rules as the `href` of a stylesheet and the `src` of an image.

<!-- slide 9 -->

### Top to bottom

```html
<h1>Digital Nomads</h1>

<script>
  const city = 'Antwerp';

  function greet(name) {
    return `Hello ${name}, welcome to ${city}`;
  }
</script>

<script>
  document.write(greet('Sam'));
</script>
```

<!-- slide 10 -->

### From another server

```html
<body>
  <h1>My website</h1>

  <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
  <script src="script.js"></script>
</body>
```

> [!NOTE]
> The library first, your own code under it. script.js can use everything the first file brought along.

<!-- slide 11 -->

### When nothing happens

| What you wrote | What you get |
| --- | --- |
| `<script src="scirpt.js">` | A red 404 in the console. The page loads, the script never does. |
| `<script src="script.js" />` | A script tag cannot close itself. Everything under it is swallowed. |
| `<script src="script.js">alert('Hi')</script>` | With a src, the code between the tags is ignored. |
| `<script>` inside script.js | `SyntaxError: Unexpected token '<'` |

> [!TIP]
> A blank page or a button that does nothing: the console knows why.

<!-- slide 12 -->

### Task: Move it out

*10 minutes*

1. Take one of your exercises of last week, the one with a script tag in index.html
2. Move the JavaScript to `script.js` and link it with `<script src="script.js">`
3. Open it with Live Server and check that it still does what it did
4. Break it on purpose: rename the file, reload, and find the error in the console

<!-- slide 13 -->

### A script tag has a src, and also a console.log between its tags. What runs?

- A. The file first, then the code between the tags
- B. The code between the tags first, then the file
- C. Only the file
- D. Only the code between the tags

**Answer:** C. Only the file

A script tag with a src ignores whatever is between its tags. Code of your own next to an external file goes in a second script tag.

<!-- slide 14 -->

## 2. The window object

<!-- slide 15 -->

### The language and the browser

#### In the browser

```js
alert('Hello world');
```

The alert() dialog of the browser: "Hello world" and an OK button.

#### In Node

```js
alert('Hello world');
```

```console
$ node index.js
ReferenceError: alert is not defined
```

<!-- slide 16 -->

### The Browser Object Model

- **[window](https://developer.mozilla.org/en-US/docs/Web/API/Window)**: The tab your page lives in. Dialogs, timers, the size of the viewport. The other five hang under it.
- **[document](https://developer.mozilla.org/en-US/docs/Web/API/Document)**: The page itself. That is the DOM, the lesson after the practice session.
- **[location](https://developer.mozilla.org/en-US/docs/Web/API/Location)**: The address bar. Read the URL, or send the browser somewhere else.
- **[history](https://developer.mozilla.org/en-US/docs/Web/API/History)**: The back and forward buttons.
- **[navigator](https://developer.mozilla.org/en-US/docs/Web/API/Navigator)**: The browser and the device: which one, which language, online or not.
- **[screen](https://developer.mozilla.org/en-US/docs/Web/API/Screen)**: The monitor the browser is shown on.

<!-- slide 17 -->

### window is the global object

```js
window.console.log('With window in front');
console.log('Without');

console.log(window.alert === alert);
console.log(typeof window.setTimeout);
```

> [!NOTE]
> Whatever lives on `window` can be written without `window.` in front. Nearly everybody leaves it out.

<!-- slide 18 -->

## 3. Dialogs

<!-- slide 19 -->

### alert

```js
// Show a message
window.alert('Hello world');

// Same thing, without window
alert('Hello world again');
```

The alert() dialog of the browser: "Hello world" and an OK button.

One button. The script waits until it is clicked, and alert gives nothing back.

<!-- slide 20 -->

### prompt

```js
// Ask for input
const visitor = prompt('What is your name?');

// With a default value in the field
const guest = prompt('What is your name?', 'Joske');
```

The prompt() dialog of the browser: "What is your name?", a text field filled in with "Joske" and a Cancel and an OK button. OK gives 'Joske', Cancel gives null.

Always a string, also when the visitor types 42.

<!-- slide 21 -->

### confirm

```js
// A yes or no question
const likesKittens = confirm('Do you like kittens?');

console.log(likesKittens);
```

The confirm() dialog of the browser: "Do you like kittens?" and a Cancel and an OK button. OK gives true, Cancel gives false.

A boolean, so it fits straight into an if.

<!-- slide 22 -->

### A confirm in an if

```js
if (confirm('Do you like kittens?')) {
  document.write('Yes!');
} else {
  document.write('No!');
}
```

*confirm() → `true`*

*OK is clicked*

```js
if (confirm('Do you like kittens?')) {
  document.write('Yes!');
} else {
  document.write('No!');
}
```

*confirm() → `true`*

*Cancel is clicked*

```js
if (confirm('Do you like kittens?')) {
  document.write('Yes!');
} else {
  document.write('No!');
}
```

*confirm() → `false`*

<!-- slide 23 -->

### The script waits

```js
console.log('Before');

alert('Everything stops here');

console.log('After');
```

1. Runs right away.
2. The dialog opens and JavaScript stops. No next line, no clicks on the page, until somebody answers.
3. Only now.

<!-- slide 24 -->

### Not on a real site

- The dialog looks like the browser, never like your site. No colours, no logo, no font of your own.
- The whole tab is frozen while it is open.
- After a few dialogs in a row the browser offers a checkbox to block the rest.
- Visitors have learned to distrust them. "127.0.0.1:5500 says" reads like a scam.

> [!TIP]
> Real sites build the question into the page itself, as a modal. For that you need the DOM.

<!-- slide 25 -->

### The visitor clicks Cancel. What does confirm('Sure?') give back?

- A. null
- B. false
- C. undefined
- D. 'Cancel'

**Answer:** B. false

confirm always gives a boolean: true for OK, false for Cancel. null is what prompt gives on Cancel, because there you were waiting for a string.

<!-- slide 26 -->

## 4. Timers

<!-- slide 27 -->

### setTimeout

```js
console.log('Hello');

setTimeout(function () {
  console.log('World!');
}, 2000);

console.log('Goodbye');
```

> [!NOTE]
> The second argument is the delay in milliseconds. 2000 is two seconds.

<!-- slide 28 -->

### Three ways to hand it over

```js
function printWorld() {
  console.log('World!');
}

console.log('Hello');
setTimeout(printWorld, 2000);
console.log('Goodbye');
```

*named*

```js
function printWorld() {
  console.log('World!');
}

console.log('Hello');
setTimeout(printWorld, 2000);
console.log('Goodbye');
```

*anonymous*

```js
console.log('Hello');

setTimeout(function () {
  console.log('World!');
}, 2000);

console.log('Goodbye');
```

*arrow*

```js
console.log('Hello');

setTimeout(() => {
  console.log('World!');
}, 2000);

console.log('Goodbye');
```

<!-- slide 29 -->

### Hand it over, without brackets

```js
function printWorld() {
  console.log('World!');
}

console.log('Hello');
setTimeout(printWorld(), 2000);
console.log('Goodbye');
```

> [!WARNING]
> `printWorld()` runs the function right now. `printWorld` hands the function itself to the timer.

<!-- slide 30 -->

### setInterval

```js
let seconds = 5;

const timer = setInterval(function () {
  console.log(seconds);
  seconds--;

  if (seconds < 0) {
    clearInterval(timer);
    console.log('Lift off!');
  }
}, 1000);
```

<!-- slide 31 -->

### A script logs A, sets a timer of 0 milliseconds that logs B, and logs C. In which order do the letters show up?

- A. A, B, C
- B. A, C, B
- C. B, A, C
- D. A, C, and B never shows

**Answer:** B. A, C, B

Even with a delay of 0, the function is put aside until the script that is running has finished. A timer never cuts in between two of your lines.

<!-- slide 32 -->

## 5. Location and navigator

<!-- slide 33 -->

### location

```text
https://shop.example.com/products/shoes?size=42#reviews
```

| Property | Gives |
| --- | --- |
| `location.href` | The whole address |
| `location.hostname` | `shop.example.com` |
| `location.pathname` | `/products/shoes` |
| `location.search` | `?size=42` |
| `location.hash` | `#reviews` |

<!-- slide 34 -->

### Somewhere else

```js
location.href = 'https://www.kdg.be';

location.replace('https://www.kdg.be');

location.reload();
```

1. The browser goes to the new address. The back button brings the visitor back here.
2. The same trip, but this page drops out of the history. No way back.
3. Loads the current page again.

<!-- slide 35 -->

### window.open

```js
// A new tab
window.open('https://www.kdg.be', '_blank');

// With a size it becomes a separate little window
window.open('https://www.kdg.be', '_blank', 'width=400,height=400');
```

> [!WARNING]
> Browsers only allow this straight from a click. Anywhere else the popup blocker eats it, without an error.

> [!TIP]
> A link that opens in a new tab needs no JavaScript: `<a href="..." target="_blank">`

<!-- slide 36 -->

### navigator

```js
console.log(navigator.userAgent);
console.log(navigator.language);
console.log(navigator.onLine);
```

> [!NOTE]
> The user agent is a line of text the browser writes about itself. Every one starts with Mozilla/5.0, Chrome and Safari included.

<!-- slide 37 -->

### Which system

```js
const agent = navigator.userAgent;
let system = 'Something else';

if (agent.includes('Android')) {
  system = 'Android';
} else if (agent.includes('iPhone')) {
  system = 'iOS';
} else if (agent.includes('Windows')) {
  system = 'Windows';
} else if (agent.includes('Mac')) {
  system = 'Mac';
}
console.log(system);
```

<!-- slide 38 -->

### Viewport and screen

```js
document.write(`Viewport: ${innerWidth} x ${innerHeight}`);
document.write('<br>');
document.write(`Screen: ${screen.width} x ${screen.height}`);
```

> [!TIP]
> A layout that follows the size of the window is a job for CSS media queries. JavaScript needs these numbers for the odd calculation.

<!-- slide 39 -->

### The page is https://www.kdg.be/courses?year=2#top. What is location.pathname?

- A. '/courses'
- B. 'www.kdg.be'
- C. '?year=2'
- D. '/courses?year=2#top'

**Answer:** A. '/courses'

pathname is the part between the host and the question mark. www.kdg.be is the hostname, ?year=2 the search and #top the hash.

<!-- slide 40 -->

## 6. Events

<!-- slide 41 -->

### Events

An event is something that happens on the page. An HTML element can say which JavaScript runs when it does, in an attribute that starts with `on`.

| Attribute | Fires when |
| --- | --- |
| `onclick` | The visitor clicks the element |
| `onmouseover` | The mouse moves onto it |
| `onmouseleave` | The mouse moves off it again |
| `onkeydown` | A key goes down |
| `oncopy` | The visitor copies something from it |

[Every event there is, on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Events)

<!-- slide 42 -->

### onclick

```html
<button onclick="sayHello()">Click me</button>

<script>
  function sayHello() {
    alert('Hello!');
  }
</script>
```

<!-- slide 43 -->

**onclick in your HTML is old school.**

We just moved the JavaScript out of the HTML, and this puts a piece of it back in. In period 2 you get addEventListener. After that I never want to see an on attribute again. ☠️ Never.

<!-- slide 44 -->

### With an argument

```html
<button onclick="order('fries')">Fries</button>
<button onclick="order('waffle')">Waffle</button>
<button onclick="order('smoothie')">Smoothie</button>

<script>
  function order(snack) {
    console.log(`You ordered: ${snack}`);
  }
</script>
```

> [!NOTE]
> Double quotes around the attribute, single quotes inside it. A second pair of doubles ends the attribute too early.

<!-- slide 45 -->

### document.write wipes the page

```html
<h1>My page</h1>
<p>A paragraph that took hours to write.</p>

<button onclick="document.write('<h1>Gone</h1>')">
  Click me
</button>
```

> [!WARNING]
> Once the page has loaded, document.write starts a new, empty page. Until the DOM lesson, the result of a click goes in an alert or in the console.

<!-- slide 46 -->

### onmouseleave

```html
<button onclick="push()" onmouseleave="leave()">THE BUTTON</button>

<script>
  let clicked = false;
  function push() {
    clicked = true;
    alert('Oh no! You pushed my button!');
  }
  function leave() {
    if (!clicked) {
      alert('Y U NO WANT TO CLICK ME?');
    }
  }
</script>
```

<!-- slide 47 -->

### oncopy

```html
<p oncopy="alert('Thief!')">
  Secret recipe: flour, eggs, milk and salt.
</p>

<p oncontextmenu="return false">
  No right click on this paragraph.
</p>
```

> [!WARNING]
> Blocking a copy or a right click stops nobody who wants your text. It only annoys the visitors who did nothing wrong.

<!-- slide 48 -->

### No function needed

```html
<button onclick="history.back()">Back</button>

<button onclick="location.reload()">Again</button>

<button onclick="window.print()">Print this page</button>
```

1. One step back in the history of the tab, like the back button of the browser.
2. Loads the page again.
3. Opens the print dialog of the browser.

<!-- slide 49 -->

### Fun with windows

#### index.html

```html
<button onclick="moveWindow()">
  Click me
</button>

<script src="script.js"></script>
```

> [!WARNING]
> Opening a window only works from a click.

#### script.js

```js
function moveWindow() {
  const popup = window.open('', '', 'width=200,height=100');
  const sizes = [500, 1000, 100];

  for (let i = 0; i < 30; i++) {
    setTimeout(function () {
      const size = sizes[i % 3];
      popup.resizeTo(size, size);
    }, i * 1000);
  }
}
```

<!-- slide 50 -->

### A button has onclick="sayHello". A click does nothing. Why?

- A. The brackets are missing, so the function is named but never called
- B. onclick has to be written as onClick
- C. A button only works inside a form
- D. sayHello has to be an arrow function

**Answer:** A. The brackets are missing, so the function is named but never called

The attribute holds code that runs on a click. sayHello on its own is a line that does nothing, sayHello() calls the function. With setTimeout it is the other way around: there you hand over the function itself, without brackets.

<!-- slide 51 -->

## 7. Exercises

<!-- slide 52 -->

> Help will always be given at Hoboken to those who ask for it.
>
> Almost Dumbledore

<!-- slide 53 -->

### How it works

- One folder per exercise, with an `index.html` and a `script.js`. **No more code inside a script tag.**
- Opened with Live Server, with the console open. A typo shows up there first.
- A prompt always gives back text. `Number()` before you calculate with it.
- Stuck for more than ten minutes? Ask a classmate, ask on Discord, then look at the solution.

<!-- slide 54 -->

### Task: Dialogs

All of this runs while the page loads, so document.write still works here.

1. Ask whether the visitor wants cookies (make believe). OK: show that cookies are on their way. Cancel: show that there will be none.
2. Ask for two numbers, add them up and show the sum on the page.
3. Add a third prompt that takes plus or minus, and add or subtract depending on the answer. Anything else gets a message that the input is not valid.

> [!TIP]
> **Dialogs**
>
> *Cookies*
>
> *script.js*
>
> ```js
> if (confirm('Do you want cookies?')) {
>   document.write('Cookies are on their way');
> } else {
>   document.write('No cookies for you');
> }
> ```
>
> *Sum*
>
> Without Number() the plus glues the two answers together: 2 and 3 become 23.
>
> *script.js*
>
> ```js
> const a = Number(prompt('First number?'));
> const b = Number(prompt('Second number?'));
>
> document.write(`${a} + ${b} = ${a + b}`);
> ```
>
> *Plus or minus*
>
> *script.js*
>
> ```js
> const a = Number(prompt('First number?'));
> const b = Number(prompt('Second number?'));
> const operation = prompt('plus or minus?');
>
> if (operation === 'plus') {
>   document.write(`${a} + ${b} = ${a + b}`);
> } else if (operation === 'minus') {
>   document.write(`${a} - ${b} = ${a - b}`);
> } else {
>   document.write('That is not a valid input');
> }
> ```

<!-- slide 55 -->

### Task: Buttons

After a click, the result goes in an alert or in the console.

1. A button that shows a random number from 1 to 100 in an alert.
2. A button that counts: every click says how many times it has been clicked.
3. A calculator. Two prompts ask for two numbers when the page loads. Four buttons, `+` `-` `*` and `/`, each show the result of their own operation.

> [!TIP]
> **Buttons**
>
> *Random number*
>
> *index.html*
>
> ```html
> <button onclick="showRandom()">Random number</button>
>
> <script src="script.js"></script>
> ```
>
> *script.js*
>
> ```js
> function showRandom() {
>   const number = Math.floor(Math.random() * 100) + 1;
>   alert(number);
> }
> ```
>
> *Counter*
>
> The counter lives outside the function. Inside, it would start at 0 again on every click.
>
> *index.html*
>
> ```html
> <button onclick="count()">Count me</button>
>
> <script src="script.js"></script>
> ```
>
> *script.js*
>
> ```js
> let clicks = 0;
>
> function count() {
>   clicks++;
>   alert(`Clicked ${clicks} times`);
> }
> ```
>
> *Calculator*
>
> *index.html*
>
> ```html
> <button onclick="calculate('+')">+</button>
> <button onclick="calculate('-')">-</button>
> <button onclick="calculate('*')">*</button>
> <button onclick="calculate('/')">/</button>
>
> <script src="script.js"></script>
> ```
>
> *script.js*
>
> ```js
> const a = Number(prompt('First number?'));
> const b = Number(prompt('Second number?'));
>
> function calculate(operation) {
>   let result;
>
>   if (operation === '+') {
>     result = a + b;
>   } else if (operation === '-') {
>     result = a - b;
>   } else if (operation === '*') {
>     result = a * b;
>   } else {
>     result = a / b;
>   }
>
>   alert(`${a} ${operation} ${b} = ${result}`);
> }
> ```

<!-- slide 56 -->

### Task: Browser and timers

1. Show the user agent on the page, with a button under it. On Windows a click asks "Go to Microsoft?" and goes to [microsoft.com](https://www.microsoft.com) after an OK. On a Mac it asks "Go to Apple?" and goes to [apple.com](https://www.apple.com).
2. A page that shows a message of your choice after 3 seconds, and moves on to [this page](https://i.giphy.com/media/PgdWZV8Bb1fFqVcmtk/giphy.webp) after 4.
3. A countdown from 10 to 0 in the console, one number per second, with an alert at the end.

> [!TIP]
> **Browser and timers**
>
> *Microsoft or Apple*
>
> *index.html*
>
> ```html
> <button onclick="goHome()">Take me home</button>
>
> <script src="script.js"></script>
> ```
>
> *script.js*
>
> ```js
> const agent = navigator.userAgent;
> document.write(agent);
>
> function goHome() {
>   if (agent.includes('Windows')) {
>     if (confirm('Go to Microsoft?')) {
>       location.href = 'https://www.microsoft.com';
>     }
>   } else if (agent.includes('Mac')) {
>     if (confirm('Go to Apple?')) {
>       location.href = 'https://www.apple.com';
>     }
>   }
> }
> ```
>
> *Message and redirect*
>
> Two timers that start at the same moment. The alert blocks, so the redirect waits until the dialog is closed, even when the 4 seconds are long over.
>
> *script.js*
>
> ```js
> setTimeout(function () {
>   alert('Hang on, something is coming');
> }, 3000);
>
> setTimeout(function () {
>   location.href = 'https://i.giphy.com/media/PgdWZV8Bb1fFqVcmtk/giphy.webp';
> }, 4000);
> ```
>
> *Countdown*
>
> *script.js*
>
> ```js
> let seconds = 10;
>
> const timer = setInterval(function () {
>   console.log(seconds);
>
>   if (seconds === 0) {
>     clearInterval(timer);
>     alert('Happy new year!');
>   }
>
>   seconds--;
> }, 1000);
> ```

<!-- slide 57 -->

### Task: Your own thing

Something fun, creative, boring or useful, with what you know of JavaScript so far. A few ideas to start from:

1. A quiz: three prompts, and the score in an alert at the end.
2. An egg timer: ask for a number of seconds, and ring when they are over.
3. A button that is very hard to leave alone.
4. Or something nobody thought of yet.

<!-- slide 58 -->

### Next up

- **15/10** JavaScript & HTML: Today
- **22/10** Practice session: HO-A.01.36
- **29/10** DOM: The most important lesson of them all

## Glossary

- **External script**: JavaScript in a file of its own, loaded into the page with <script src="script.js"></script>. The file holds only JavaScript, no script tags. (slide 6)
- **Separation of concerns**: One job per file: HTML says what is on the page, CSS how it looks, JavaScript what it does. Every page can load the same files, and a bug gets fixed in one place. (slide 7)
- **BOM**: Browser Object Model. Everything the browser hands your script besides the language itself: window, document, location, history, navigator and screen. (slide 16)
- **window**: The tab your page lives in, and the global object of JavaScript in a browser. alert, setTimeout, console, document and location all live on it, so you can write them without window. in front. (slide 17)
- **alert()**: Opens a browser dialog with a message and an OK button. Gives nothing back. Fine for exercises, never on a real site. (slide 19)
- **confirm()**: Opens a browser dialog with a question, an OK and a Cancel button. Gives back true for OK and false for Cancel, so it fits straight into an if. (slide 21)
- **Blocking**: Code that makes everything else wait until it is done. alert, prompt and confirm block: no next line runs and the page does not react until the dialog is closed. (slide 23)
- **setTimeout**: Runs a function once, after a delay in milliseconds: setTimeout(printWorld, 2000). The script does not wait for it, the lines under it run first. (slide 27)
- **setInterval**: Runs a function again and again, with a fixed number of milliseconds in between. It gives back an id, and clearInterval(id) stops it. (slide 30)
- **location**: The address bar as an object. location.href is the whole URL, pathname, search and hash are its pieces. Assign a new href and the browser goes there. (slide 33)
- **Popup blocker**: The part of the browser that refuses window.open unless it comes straight from a click of the visitor. It does so without an error. (slide 35)
- **navigator**: Information about the browser and the device: the user agent, the language, whether there is a connection. (slide 36)
- **User agent**: A line of text in which the browser describes itself: browser, version, operating system. Readable through navigator.userAgent, and not to be trusted: an iPad says it is a Mac. (slide 36)
- **Viewport**: The part of the browser window your page gets. window.innerWidth and innerHeight give its size in pixels. screen.width and screen.height are about the whole monitor. (slide 38)
- **Event**: Something that happens on the page: a click, a key that goes down, the mouse leaving an element, a copy. JavaScript can run code when it does. (slide 40)
- **Inline event handler**: An HTML attribute that starts with on and holds JavaScript to run on that event: onclick="sayHello()". Old school. From period 2 on, addEventListener replaces it. (slide 42)
- **document.write**: While the page loads it adds to the page. Once the page has loaded it starts a new, empty document, so everything that was there is gone. (slide 45)

## Links and sources

### In the deck

- [Window](https://developer.mozilla.org/en-US/docs/Web/API/Window) (slide 16): Everything the tab offers: dialogs, timers, sizes
- [document](https://developer.mozilla.org/en-US/docs/Web/API/Document) (slide 16)
- [location](https://developer.mozilla.org/en-US/docs/Web/API/Location) (slide 16)
- [history](https://developer.mozilla.org/en-US/docs/Web/API/History) (slide 16)
- [navigator](https://developer.mozilla.org/en-US/docs/Web/API/Navigator) (slide 16)
- [screen](https://developer.mozilla.org/en-US/docs/Web/API/Screen) (slide 16)
- [Every event there is, on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Events) (slide 41)
- [microsoft.com](https://www.microsoft.com) (slide 56)
- [apple.com](https://www.apple.com) (slide 56)
- [this page](https://i.giphy.com/media/PgdWZV8Bb1fFqVcmtk/giphy.webp) (slide 56)
- [kdgmt.be/discord](https://kdgmt.be/discord) (slide 59)

### Sources

- [<script>: The Script element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/script)
- [Window: confirm() method](https://developer.mozilla.org/en-US/docs/Web/API/Window/confirm)
- [Window: setTimeout() method](https://developer.mozilla.org/en-US/docs/Web/API/Window/setTimeout)
- [Window: setInterval() method](https://developer.mozilla.org/en-US/docs/Web/API/Window/setInterval)
- [Window: open() method](https://developer.mozilla.org/en-US/docs/Web/API/Window/open): Which features still work, and when a popup is blocked
- [Navigator: userAgent property](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgent)
- [Browser detection using the user agent](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Browser_detection_using_the_user_agent): Why you should avoid it when you can
- [Document: write() method](https://developer.mozilla.org/en-US/docs/Web/API/Document/write)
