Types (Strings, Numbers, Arrays)
Conditionals, Loops, Functions
Modular JS Pattern
Basic Event Handlers with addEventListener
Basic HTML UI Elements
Today: Page Event Flow and Timers
When working with pages, anything you interact with on the page is an "object" (but not in the same definition as Java).
An object in JavaScript has a set of properties (e.g. innerText for DOM
objects) and built-in functions (e.g. addEventListener
. Some
objects have different properties/functions than others.
It is helpful to think of the following "types" of objects in JavaScript (this is informal, but can help you moving forward):
document
(which is a Global DOM object)What kinds of properties (information) do you think would be useful to have access to in an page event?
Every JavaScript program can refer to the following global objects:
method | description |
---|---|
document | current HTML page and its content |
history | list of pages the user has visited |
location | URL of the current HTML page |
navigator | info about the web browser you are using |
screen | info about the screen area occupied by the browser |
window | the browser window |
You will usually just use window
and document
.
document.getElementyById(...)
document.querySelector(...)
document.querySelectorAll(...)
document.createElement(...)
(introduced soon)For starters, the HTML attributes. This HTML:
<img src="images/puppy.png" alt="A fantastic puppy photo"/>
<p>A paragraph!</p>
Has two objects (let's call them puppyImg
and p
) with these properties:
puppyImg.src
-- set by the browser to images/puppy.png
puppyImg.alt
-- set by the browser to "A fantastic puppy photo"
p.innerText
-- set by the browser to "A paragraph!"
Contain properties about an event that occurred.
<html>
<head>
<script src="myfile.js"></script>
</head>
<body> ... </body>
</html>
let x = 3;
function f(n) { return n + 1; }
function g(n) { return n - 1; }
x = f(x);
Your file's JS code runs the moment the browser loads the script
tag
Important! At this point in time, the browser has not yet read your page's body
<html>
<head>
<script src="myfile.js" type="text/javascript"></script>
</head>
<body>
<div><button id="ok">OK</button></div>
(... more html ...)
let btn = document.getElementById("ok");
btn.onclick = okayClick; // this is bad: btn is null at this point
Problem: global JS code runs the moment the script is loaded
Script in head
is processed before page's body
has
loaded
No elements are available yet or can be accessed yet via the DOM
This problem is solved by attaching a function to the global window load event, which fires once everything in the page has been loaded.
There are different types of behaviors on a page. But when you're first learning JavaScript, it may seem like there are a ton of different things to keep track of, and connecting the dots can be tricky when staring at code.
But it's really not that complicated if you break it down before starting the code.
source.addEventListener("event", response);
function response() {
// response behavior with possible output/document elements changed
}
load
event, sometimes for various key events like keyPress
).
JS Implementation (with comments!)
CP2 External Requirements
this
this.fieldName // access field
this.fieldName = value; // modify field
this.functionName(parameters); // call method
All JavaScript code actually runs inside of an object
By default, code runs in the global window
object (so this === window
)
window
The this
keyword refers to the current object
For response functions atteched in addEventListener
,
this
refers to the source element of the event.
window.addEventListener("load", initialize);
function initialize() {
let msgP = document.getElementById("msgP");
msgP.addEventListener("mouseover", showMsg);
}
function showMsg() {
this.innerText = "You moved the mouse over me!";
// same as document.getElementById("msgP").innerText = "You moved the mouse over me!";
}
Event handlers attached unobtrusively are bound to the element
Inside the handler, that element becomes this
The functions we've seen so far to respond to events like click
have had the following format:
sourceEl.addEventListener("click", responseFunction);
function responseFunction() {
//
}
JavaScript gives us a really useful way to get more information about an event that fired the callback function by accepting an optional parameter to the attached function representing the event object.
Conventionally this event object is given the name "e" or "evt"
sourceEl.addEventListener("click", responseFunction);
function responseFunction(e) {
// each time this line is reached in response to a click, we have a new
// event object "e" with data about the event (time, location, etc.)
}
<button id="ok">OK</button> <!-- (1) -->
window.addEventListener("load", initialize); // (2)
// called when page loads (from event (2))
// sets up event handlers
function initialize() {
let ok = document.getElementById("ok"); // (3)
ok.addEventListener("click", okayClick);
}
function okayClick() {
alert("booyah"); // (4)
}
let clicks = 0;
window.addEventListener("load", main);
function main() {
let foo = document.getElementById("foo-btn");
let bar = document.getElementById("bar-btn");
foo.addEventListener("click", function() {
console.log("A button was clicked!");
clicks++;
});
bar.addEventListener("click", function() {
console.log("A button was clicked!");
clicks++;
});
}
Used to delay or set intervals for executing functions
method | description |
---|---|
setTimeout(function, delayMS) | arranges to call given function after given delay in ms |
setInterval(function, delayMS) | arranges to call function repeatedly every delayMS ms |
clearTimeout(timerID)
clearInterval(timerID) |
stops the given timer |
Both setTimeout
and setInterval
return an ID
representing the timer
clearTimeout
/Interval
later to
stop the timersetTimeout
Example<button id="demo-btn">Click me!</button>
<span id="output-text"></span>
window.addEventListener("load", function() {
document.getElementById("demo-btn").onclick = delayedMessage;
});
function delayedMessage() {
document.getElementById("output-text").innerText = "Wait for it...";
setTimeout(sayBooyah, 5000);
}
function sayBooyah() { // called when the timer goes off
document.getElementById("output-text").innerText = "BOOYAH!";
}
setInterval
Examplelet timer = null; // stores ID of interval timer
function delayMsg2() {
if (timer === null) {
timer = setInterval(sayHello, 1000);
} else {
clearInterval(timer);
timer = null;
}
}
function sayHello() {
document.getElementById("output-text").innerText += "Hello..."
}
function delayedMultiply() {
// 6 and 7 are passed to multiply when timer goes off
setTimeout(multiply, 2000, 6, 7);
}
function multiply(a, b) {
alert(a * b);
}
Any parameters after the delay are eventually passed to the timer function
Why not just write this?
setTimeout(multiply(6 * 7), 2000);
Many students mistakenly write ()
when passing the function
setTimeout(booyah(), 2000);
setTimeout(booyah, 2000);
setTimeout(multiply(num1 * num2), 2000);
setTimeout(multiply, 2000, num1, num2);
What does it actually do if you have the ()
?
JavaScript has evolved quite a bit since it was first created.
Why? It was the first real client-side programming language that allowed people to add interactivity to their HTML and CSS pages.
A ton of work has been done to improve standards between browsers and JavaScript, and adapt to an increasingly connected world with different devices and users browsing the web.
As a result, you may see different ways to accomplish something in JS. In this course, we focus on providing a foundational knowledge of JS to implement interactive web pages, while laying a foundation of best practices.
You may find some resources online helpful to explore different ways to implement UI's in JavaScript - there are a ton of things! But some are better than others (make sure you understand why these examples are poor use of JS).
For reference, here's a much better solution using what we've taught in this course to accomplish a mouseover demo given by W3Schools (view HTML source to get CSS/JS).
Understanding good code quality can be extremely valuable in navigating an overwhelming amount of resources on the web today.
We choose resources that best align with our code quality guidelines, while giving just enough "extra detail" into topics we cover in lecture/section/lab. That said, let us know if you're looking for recommendations on a specific resource!
We introduced addEventListener
as the way to give a
"listener" to a DOM element, mapping an action (event) to a response
(function).
Before addEventListener
was introduced in JS, events were most
often handled using "onevent" attributes. You will still see these
occassionally, but addEventListener
is the better choice.
onclick
let myBtn = document.getElementById("my-btn");
myBtn.onclick = function() {
console.log("You clicked a button!");
};
let myBtn = document.getElementById("my-btn");
myBtn.addEventListener("click", function() {
console.log("You clicked a button!");
});
This is fine to use if you are attaching an event to an element and don't need to ever remove the event listener. It's an older convention, but not necessarily a "bad" one for simple event handling.
window.onload
Recall that we need to set up our JS program with a listener for the window's
load
event in order to ensure access to DOM elements in our program
when the document has finished loading.
window.addEventListener("load", initialize);
You can achieve the same result using the onload
event attribute
for the window. You may see this in some examples, but
addEventListener
is preferred.
// initialize defined elsewhere
window.onload = initialize;
window.onload = function() {
// this is fine for short setup code, but it's common to factor
// your page setup into an "initialize" function as seen above
};
We can also easily remove events using removeEventListener
.
el.removeEventListener(event, responseFunction);
Note that this only works if responseFunction
is a named
function that has been added to the listener on el
for the
specified event (this is one motivation for preferring named functions over anonymous
functions to handle events).
function initialize() {
let box = document.getElementById("box");
box.addEventListener("mouseover", mouseOverResponse);
}
function mouseOverResponse() {
console.log("You moved the mouse over a box!");
}
function turnOffBox() {
let box = document.getElementById("box");
box.removeEventListener("mouseover", mouseOverResponse);
}