Short intro/talk...

Short live intro on these topics. After that you will work through the page on your own. (There is a lab handout at the bottom but you'll have to go through each check points. It's not meant to be hard, it's meant to have you understand. Often the answer is in the slides. Let me know if it's unclear/hard).

  1. Last class, variables.
  2. Go over idea of events (something happening) and responding to it.
    • Google Search, YouTube, gmail are full of events. You rarely reload/refresh the page but things happen!

      Google Search homepage

      • Type in the box: suggestions update per keystroke (input)
      • Press Enter: search runs (keydown / submit)
      • Hover over "I'm Feeling Lucky": the button text spins to something else (mouseover)
      • Click the microphone or the apps grid: a panel opens (click)

      YouTube video page

      • Hover over a thumbnail: preview plays (mouseover)
      • Press space or k: play/pause (keydown)
      • Press f: fullscreen (keydown)
      • Click and drag the progress bar (mousedown, mousemove, mouseup)
      • Scroll down: more comments load (scroll)
      • Video ends: next one autoplays (ended, an event with no user action)
  3. Functions: it's a way to reduce repeating the same code over and over again. It's also a way to access code that you have not written yourself. (You did not write the code that actually does the work in alert()... it opens a window, .. prints out text...)
Notes

Where We Are

So far every line of Javascript you have written ran once, top to bottom, the moment the page loaded. You have used variables, arithmetic, string concatenation, prompt(), alert() and document.write().

Today we add two more ideas:

Events: a click fires onclick and the code runs. Functions: code written once under a name and called many times.
Notes

Capturing Mouse Events: onclick

In Javascript, an event handler is code that runs when a specific event occurs. Common mouse events:

Event When it fires
onclick user clicks the element
onmouseover mouse pointer moves onto the element
onmouseout mouse pointer leaves the element

For a full list: w3schools, DOM events


Before we go to events, lets go over a HTML tag we did not cover before. <input> tag and <button> tag.

Two button elements in HTML. Both work, <button> is more flexible:

  <input type="button" value="Click Me" />
  <button>Click Me</button>

Nothing happens above. That is why we did not cover it before. We needed a way to react to the button click and that can be doen with "events" using javascript



The simplest way to attach an event handler is to add it as an HTML attribute, named after the event, with Javascript directly inside the quotes:

<!DOCTYPE html>
<html>
<head><title>onclick Demo</title></head>
  <body>

<button onclick="alert('Ouch, you clicked my button!');">Click Me (button)</button>

<div onclick="alert('you clicked my div!');"> click here (div) </div>

</body>
</html>

Try it right here on the slide:

click here (div)

[sample file]

The onclick attribute can be applied to nearly any HTML element, not just buttons.

Notes

Checkpoint 1: Two Clickable Things

Try it: create a new file called events.html. You will add to it in Checkpoint 2.
  1. Add one <button> and one <p> with some text in it.
  2. Give each one an onclick attribute with its own alert() message.
  3. Open the file in browser and click both.
It is working when: clicking the button and clicking the div each show a different message.
Nothing happens? Check your quotes: double quotes around the attribute, single quotes around the text inside alert().
Notes

onmouseover and onmouseout

These two events fire as the mouse enters or leaves an element. They are how hover effects are built.

<!DOCTYPE html>
<html>
<body>

  <img src="tick01.jpg"
       onmouseover="alert('You entered the image!');" />

</body>
</html>

[sample file]

Demo 1
Hover over the image. It will generate a onmouseover event.
<img src="tick01.jpg" onmouseover="alert('You entered the image!');" />


Dismiss the alert and hover again. It fires every single time you re-enter. An alert is a blunt way to see an event, it stops the whole page until you click OK. The next demo shows the same two events without interrupting anything.
Demo 2
Move the mouse in and out of the dashed box. Enter and then exit.

hover in and out of me
waiting for the mouse...


Here is the psuedo-code for the dashed box. Notice that we have one element <div> with two event attributes (onmouseover and onmouseout):
<div onmouseover="...javascript code to log onmouseover with time...";
     onmouseout="...javascript code to log onmouseover with time...">
  hover in and out of me
</div>
Each attribute runs a code of Javascript when its event fires.

The box also changes color when you hover. it is a CSS :hover rule. If all you want is a style change, CSS can already do it. Javascript events are for when you need to do something more than restyle, or when you need to know that it happened.
Quotes inside HTML attributes. This matters when you hand code, and your AI can fix it when you do not.

HTML attributes use double quotes:
<img onmouseover=" ... " />

Inside HTML, Javascript strings also need quotes. This creates a situation where HTML cannot tell when the double quote starts and ends. So, you cannot use double quotes again, they would close the attribute early. Use single quotes instead:
<img onmouseover="alert('hello');" />   correct
<img onmouseover="alert("hello");" />   breaks the HTML
Single and double quotes are interchangeable in Javascript. Use whichever is not already in use by the surrounding HTML.
Notes

A Useful Shortcut: this

To build a hover effect, the handler needs to change the element it is attached to. There is a one word shortcut for that.

Inside an event attribute, the word this means the element the attribute is sitting on.

this.src is that element's src.
this.style.color is its CSS text color. If you assign color to them the color changes on the page.

What this means in Javascript is complicated, it changes depending on where the word appears, and it is one of the most argued about aspect of the language. Soon you will learn document.getElementById(), which is the general way to reach any element on the page, and that is the tool you will actually use most of the time.

Image rollover. Swap the picture on hover:

<img src="tick01.jpg"
     onmouseover="this.src='tick02.jpg';"
     onmouseout="this.src='tick01.jpg';" />

[sample file]

Demo of the above code.
Hover on and off the image. The src attribute in html is changing based on the event:



Right click the image and choose inspect. Then hover it while you watch the HTML. You will see the src attribute change in place. Notice the source code changing without reloading.
To visualize what it is doing....

Color change. You can use the same technique to change a property. The CSS style of the <div> is being changed

<div onmouseover="this.style.background='yellow';"
     onmouseout="this.style.background='white';">
  Hover over me
</div>

<p onmouseover="this.style.color='red';"
   onmouseout="this.style.color='black';">
  Now hover over me
</p>

Hover over each one:

Hover over me

Now hover over me

this.style.background is reaching the same CSS property you would write as div { background: yellow; } in a stylesheet. The style rule is now being set from Javascript as a result of an event. The only difference is how multi-word property names are spelled. CSS uses a hyphen, as in font-size. Javascript cannot use a hyphen in a name (it would be read as a minus sign), so it removes the hyphen and capitalizes the next word instead: this.style.fontSize.

Notes

Checkpoint 2: A Hover Effect

Try it: in events.html, add one of these using the this recipe:
  • an image rollover: two images of your own, swapped with this.src, or
  • a color hover: a <div> or <p> that changes this.style.background or this.style.color.
Use both onmouseover and onmouseout.
It is working when: the element changes when the mouse enters and goes back to how it started when the mouse leaves. Right click it, choose Inspect, and watch the attribute change as you hover.
Notes

Functions: Packaging Code Under a Name

A function is a named block of code. You define it once, then call it by name as many times as you need.



To see why you would want a function... Here is a page that asks for a name and three scores, calculates the average, and reports it.

<!DOCTYPE html>
<html>
<body>

<button onclick="
  let name = prompt('What is your name?');
  let score1 = Number(prompt('Enter score 1:'));
  let score2 = Number(prompt('Enter score 2:'));
  let score3 = Number(prompt('Enter score 3:'));
  let average = (score1 + score2 + score3) / 3;
  alert(name + ', your average is ' + average);
">Student A</button>

<button onclick="
  let name = prompt('What is your name?');
  let score1 = Number(prompt('Enter score 1:'));
  let score2 = Number(prompt('Enter score 2:'));
  let score3 = Number(prompt('Enter score 3:'));
  let average = (score1 + score2 + score3) / 3;
  alert(name + ', your average is ' + average);
">Student B</button>

<button onclick="
  let name = prompt('What is your name?');
  let score1 = Number(prompt('Enter score 1:'));
  let score2 = Number(prompt('Enter score 2:'));
  let score3 = Number(prompt('Enter score 3:'));
  let average = (score1 + score2 + score3) / 3;
  alert(name + ', your average is ' + average);
">Student C</button>

</body>
</html>

The red part seems redundant. It's repeating the same thing over and over.

It can be a source of a bug if you accidently change one but not the other part.

Here is the same idea using a function. Much cleaner no?

<!DOCTYPE html>
<html>
<head>
<script>
  function showReport() {
    let name    = prompt("What is your name?");
    let score1  = Number(prompt("Enter score 1:"));
    let score2  = Number(prompt("Enter score 2:"));
    let score3  = Number(prompt("Enter score 3:"));
    let average = (score1 + score2 + score3) / 3;
    alert(name + ", your average is " + average);
  }
</script>
</head>
<body>

  <button onclick="showReport();">Student A</button>
  <button onclick="showReport();">Student B</button>
  <button onclick="showReport();">Student C</button>

</body>
</html>

The red block appears exactly once now. It is the same six lines, in the same order, doing the same thing. The difference is that there is one copy of it instead of three, and the three buttons point at it by name. We say the button is "calling" the function showReport()

In this example, one function is "called" (used) three times. This solves two problems:

The syntax:

Notes

Function Arguments: Passing Data In

A function can receive data when it is called. The values you pass in are called arguments. The names that receive them inside the function are called parameters.

<!DOCTYPE html>
<html>
<head>
<script>
  function greet(name) {
    alert("Hello, " + name + "!");
  }
</script>
</head>
<body>

<script>
  greet("Alice");
</script>

</body>
</html>

The same function now produces different output depending on what you pass in:

  greet("Alice");   gives   Hello, Alice!
  greet("Bob");     gives   Hello, Bob!
  greet("class");   gives   Hello, class!

The syntax:

You can pass numbers too. This is the key idea for Checkpoint 3:

<!DOCTYPE html>
<html>
<head>
<script>
  function showNumber(n) {
    alert("You picked: " + n);
  }
</script>
</head>
<body>

  <button onclick="showNumber(1)">Button 1</button>
  <button onclick="showNumber(2)">Button 2</button>
  <button onclick="showNumber(3)">Button 3</button>

</body>
</html>

[sample file] [sample file 2]

If you call showNumber(99), what would show up in the alert panel? What about showNumber("hello")? Remember what you learned about + and strings.
Notes

Checkpoint 3: One Function, Many Messages

The button passes a message, the function writes it into the document. In a new file called buttons.html, type this in and run it. Only Button 1 is wired up:

<!DOCTYPE html>
<html>
<head>
<script>
  function showMessage(message) {
    document.write("<h1>" + message + "</h1>");
  }
</script>
</head>
<body>

  <button onclick="showMessage('Hello from Button 1');">Button 1</button>
  <button>Button 2</button>
  <button>Button 3</button>
  <button>Button 4</button>

</body>
</html>
Try it:
  1. Click Button 1. The message is written into the document.
  2. Reload the page to get the buttons back. When document.write() runs after the page has finished loading, it replaces the whole page. In future class you will learn a way to change only one part of the page
  3. Make Button 2 and Button 3 work. Each one calls showMessage() and passes its own message. Do not write a second function.
  4. Now add the current time. Add one line inside showMessage(), below the first document.write():
    document.write("<p>" + Date() + "</p>");
    
    Date() is a built-in function, like alert(). Somebody else wrote it, and it hands back the current date and time as text. Do not touch the buttons.
  5. Leave Button 4 alone. You will use it in the Lab.
It is working when: Buttons 1, 2 and 3 each write a different message into the document followed by the current time, and there is still only one function in your file.
Nothing happens? Check your quotes: double quotes around the attribute, single quotes around the message.
Notes

Big Picture

IdeaIn one sentence
EventSomething the user did. A click, a hover.
Event handlerThe attribute that says what to run when it happens.
thisInside a handler, a shortcut for the element it is attached to.
FunctionA block of code with a name, so it can be called from anywhere.
ArgumentA value you hand to a function when you call it.
You have now written your own fuctions. You have been calling functions all along: alert(), prompt(), Number(). Anything with parentheses is a funciton. The ony difference is that somebody else wrote the code inside the function.
Notes

Lab: Button 4

Make two copies of your buttons.html from Checkpoint 3. Leave showMessage() and Buttons 1 through 3 exactly as they are. In the first copy, you will ask the agent to create a new function. Button 4 gets its own, second function, something too "fun and complicated" to build by hand in the next five minutes. This time you are not writing the code, you are writing the request. Open your AI's edit or agent mode on this file and try it twice.

Attempt 1. Step 1
Give it a vague instruction below.
Type this in, run it, see what you get:

When button 4 is clicked, do something fun and complicated: open a new window,
play a sound, and change the page's background color to go along with the sound.

Look closely at what comes back. Note what the AI decided for you: what size the window is, what kind of sound it picked, how the color changes, how long any of it lasts, whether the page goes back to normal afterward.

Attempt 1 Step 2
Once you are happy with the result, ask your agent to comment at the top of your file what it is doing and to add descriptive comments on what each function is doing. Read it carefully.




Attempt 2 Step 1.
Using the second copy, give it the precise instruction below:

Add one new function called wildButton(), attached only to Button 4's onclick.
Do not change showMessage() or Buttons 1 through 3. When wildButton() runs:

1. Open a new browser window, 300px by 200px, showing the text "Surprise!".
2. Play a one second tone using the Web Audio API (AudioContext and
   OscillatorNode). Do not load an external sound file.
3. While the tone plays, smoothly slide a rainbow-colored gradient across
   the page background (for example, animate a CSS linear-gradient's
   background-position), so the colors blend continuously rather than
   switching abruptly.
4. When the tone ends, set the background color back to what it was
   before the button was clicked.

Add no other functions.

Run it.

Attempt 2 Step 2
Once you are happy with the result, ask your agent to comment at the top of your file what it is doing and to add descriptive comments on what each function is doing. Read it carefully.

Notes

What to Submit

Create a folder on your Reed server:
~myname/ILCP/JS03/
Put these four files in it:
  1. events.html: Checkpoints 1 and 2 in one file (the button and div with onclick, plus the hover effect using onmouseover, onmouseout and this)
  2. buttons.html: Checkpoint 3, Buttons 1, 2 and 3 each passing their own message to showMessage()
  3. buttons_vague.html: the Lab, Attempt 1. The first copy of buttons.html, with what the AI built from the vague instruction and the comments it added
  4. buttons_precise.html: the Lab, Attempt 2. The second copy, with wildButton() built from the precise instruction and the comments the AI added
Submit URL here [here].

Check before you submit: open each file from your Reed server URL in a browser (for example https://people.reed.edu/~myname/ILCP/JS03/events.html) and make sure it runs with no red errors in the console.
Notes