[PIANO PLAYING] BRIAN YU: OK. Welcome back to CS50 Beyond. Hope everyone's doing all right
with the cold weather today. I know it's a bit chilly getting here. So for a bit of recap, what we've
been doing these past couple days is we started on day zero
with a look at HTML and CSS, just building web pages,
thinking about how to style them, how to make them more responsive. We then yesterday,
added a server to that, added a Flask-based web
server written in Python, whereby we could handle different
routes to be able to create more interesting, more dynamic web pages. And where we're going today is
a bit of a continuation of that, moving from the server side to
the client side, in particular, taking a closer look at
JavaScript, which we introduced and really scratched
the surface of CS50. But there's a lot more to JavaScript
than we were able to cover. So we'll go over a few more of those
details, look at some of the nuances, and look at some of the
details of more advanced-- of newer versions of JavaScript,
the latest version, including ES6, for instance, looking at the
features that that offers us and the types of
capabilities that it gives us in terms of the types of web
pages that we can design. So ultimately, what you
want to be thinking about as we think about JavaScript
is where the code is running. And you can think of
this as the distinction between the server and the client. The client is your computer, your web
browser that you are interacting with, you're clicking buttons
on, for instance. The server is hosted somewhere
else, code running elsewhere that you're talking to. Yesterday, when we were writing
Flask applications, all of that code is server code. Your web page was making the request
to some server, where that server might have been running on your own computer,
or maybe it was running on Heroku, and you had some server
running elsewhere, and it was communicating with that. But ultimately, you were
making requests to that server, and you were getting responses back. What JavaScript's
going to allow us to do is to actually run code
on the client side, run code inside of the
user's browser, which is going to give us
the ability to create a lot of really interesting features. So let's dive in, take a look
at what JavaScript has to offer. And so we'll start with
just a very simple HTML web page, same as what we've done before. I'll just call it hello.html
add in [INAUDIBLE] HTML, add a header that has a
title that's just Hello and a body that just says maybe Welcome. And so this is just HTML, plain
and simple, what we've seen before. But what we're going
to add today is we're going to add up in the header section
of the web page, a script tag. And in between these script tags,
we're going to have JavaScript code. So we can include JavaScript,
and our web browsers, all modern web browsers
understand JavaScript. And so we can write JavaScript
code here that's actually going to run inside of the web browser. And so the simplest thing
we could do is something like alert, which is the equivalent
of something like print in Python. But instead of printing to
the terminal window, which you can also do in JavaScript, and
we'll probably do a little bit later, alert is actually going to
display a graphical visual alert in the user's web browser. So we can say, alert
hello, for instance. And that is a very basic
JavaScript program. And so I'm going to go ahead
and open up hello.html. And we get this page says hello,
this alert that pops up on my screen. I'm going to press OK. And OK, it says welcome. And so this is the very basics of what
JavaScript is going to enable us to do. But JavaScript, of
course, has the same sort of notion of variables and
functions and loops and conditions that any other programming language,
like C or Python, does as well. And we can take advantage of that too. So in JavaScript, there are
a number of different ways to define variables, although the
two most common that we're generally going to use them are let and const. So if I wanted to find a variable,
let's say let x equal 28, for example, and then I can alert x just to
display an alert message that has the value of that variable there. If I go ahead and open up
hello.html again, this page says 28, displays that alert, as I might expect. And when I define a
variable with let, this is a mutable variable, in other
words, a variable that can change. So if later on down the road I wanted
to reset the value of that variable, set x 50, for example, and then
alert x, that's totally fine. When I refresh this page,
this page now says 50. So let is your standard
variable that is mutable. But JavaScript also has a
variable declaration called const. And if I define a variable with
const, const stands for constant. In other words, this variable's
value is not going to change. And so if I try to change it, that's
actually going to cause some errors. So if I try and run this page now,
where I first site const x equals 28 and then x equals 50, trying to
reset the value of the variable that I said would be constant,
if I run this, no alert happen. I see welcome, but I didn't get an
alert page when I refreshed the page. If I go into the Chrome
Inspector, or other web browsers have something similar, and go into
the console, what I'll see here is, all right, uncut type error
assignment to constant variable. In other words, this
actually threw an error and didn't let me make this
assignment to a constant variable because x was constant. I wasn't allowed to change it. And so this is a feature that
you can and probably should use in your JavaScript programs
whenever you have something whose value isn't going to change. If something's value
isn't going to change, it's often safest to define
it as a constant variable so that nobody could ever
accidentally change it, for instance, such that you always
know that that variable's value is going to be constant. Questions about anything so far? Yeah? AUDIENCE: Does the script
part always go in the head? BRIAN YU: Good question, does the
script section always go in the head? Not necessarily. You can put the script section
later on in the body, for instance. In the lower part of the body is where
some people will put their script tags. Ultimately, HTML is read from top to
bottom, much like most anything else. But we'll often put
the script in the head, in particular, once we start
separating code into separate files. When we start putting things inside of
scripts and inside of a JavaScript file and just including, the same
way we might include CSS files, it's often common to put that
code inside of a separate file. So for instance, I
might create a new file and call it, like,
hello.js, for example, which is just going to be a JavaScript file. And all this code-- or maybe I'll put the let x
equal 50 here and alert x. This code is just going to
go inside my JavaScript file. And then what I can do is in this file
say, script source equals hello.js to mean, all right, I'm not going to
include the JavaScript inside my HTML. I'm going to separate the
JavaScript into a separate file. And so this is very common, to put
a the script inside of the header, linking to some JavaScript
file that's located elsewhere. Whereby now if I refresh
the page, it still says 50 because it's pulling in
that JavaScript from the other file and then running it
inside of this web page. Good question. And I see a couple of people have
it open already and are responding. But feel free to go to the course
website, click on the Feedback button so that you can click on
the Smiley Face/Frowny Face throughout the lecture,
in case things make sense or in case you need
clarification on topics. So I see a couple of
yellow faces already. Questions, yeah? AUDIENCE: Kind of two
questions for this. BRIAN YU: Yep. AUDIENCE: One of your
imported multiples [INAUDIBLE] same variable name across
two different ones. Does that count as it trying to-- is
it, like, trying to [INAUDIBLE] error? BRIAN YU: Yeah, good question. So the question is, if you
have, like, maybe two scripts that are trying to define
the same variable name, that is something you need to be careful of. The name refers to the variable. So if you declare a variable once,
then try and declare it again, you run into problems there. AUDIENCE: And then the other
thing, for [INAUDIBLE] should you use it as something
that's only going to be constant within that particular script? Or should it be something
that's based on [INAUDIBLE] so that it's constant
for each [INAUDIBLE].. For instance, like a header-based
variable or something along those lines,
where you don't want it to change in the course of that session,
but it might be one for each user. BRIAN YU: Oh, good question. So the question is, does const mean
that it literally, across all users, anytime anyone is using
the page will never change? Not necessarily. It just means that once you define
what the variable's value is, it will not change from that point
forward while that script is running. But if that script is
running some other time, that constant value might take on
some other value, for instance. And that's totally OK. Good question. Yeah? AUDIENCE: Can you do a
[INAUDIBLE] JS file [INAUDIBLE].. Can you also, more like a
relation-type of word for CSS file, or do you just have to [INAUDIBLE]? BRIAN YU: Good question. All you need is script and then source. You don't need the rel equal style
sheet, the way you would in a CSS file, for example. Yeah, just this is sufficient. OK, we'll keep going in that case,
take a look at some other things. And I'll go ahead and just keep
working with hello.html and hello.js. But let's now actually take a look
at trying to manipulate the DOM. So the DOM is the Document Object Model. It refers to the general
structure of this web page. And what JavaScript is very good for
is actually manipulating the web page, changing the elements inside of the page
to be something different, for example. So for instance, right here I have a
header that says Welcome, for example. And maybe I want it to
do something different. I want it to change
under certain conditions. And so I might add some code to do that. So the first thing I'll
do is create an event. And so I'll create a button
that's going to trigger an event. And the button's just going to
say Click Here, for example. And so, OK, let me get rid of
everything in the JavaScript file. So I just have a Welcome heading
and a button that says Click Here. I refresh this page. And it says, Welcome. And there's a button underneath
that says Click Here. But of course, clicking here doesn't
really do anything, at least not yet. But I would like it to. So I'm going to say button on click,
give the button an on-click attribute. This is an event listener. In other words, I'm saying
when the button is clicked on, run this JavaScript code. And the code I'm going
to run is I'm going to call a function that's just called
hello, for example, so hello and then two parentheses, same as I would
call a function in C or in Python, for example, just the name of the
function and then two parentheses. But of course, I haven't yet
defined a function called hello. But I can do that in JavaScript, and
so simple as in my JavaScript file, hello.js, having a
function called hello. And then inside this function
I can do whatever I want. So for example, I could do alert hello,
just to display an alert message, for example. And so I'll go ahead and
refresh this page, hello.html. It just says Welcome. There's a button that says Click Here. And when I click on the
button, I get an alert. And that alert says, Hello. So why did that work? It's because I have a
function called hello. It displays the alert. And when I click on the button, that
triggers the hello function to run, and that displays the alert. So basics of event listeners there. And so now let's do
something a little more interesting inside this hello function. I'm going to write something like this,
document.queryselector H1 dot inner HTML equal-- it said welcome. We'll change it to hello. So I'll show you what
it does, and then we'll go back and tease apart what this
actually means and how this is working. We saw this briefly in CS50. But good to get a
refresher on it as well. So I refreshed the page. The heading says Welcome. And there's a button
that says Click Here. And now when I click the
button, the Click Here, the word Welcome changes to the word Hello. So I've been able to manipulate
the DOM, manipulate this page, change what's actually on the page. And how did that work? Well, document.queryselector
is a function. And that function takes as its argument
what's effectively a CSS selector, in the same way that I could specify a
tag, like H1, to mean select an H1 tag, for instance. Or I could say pound sign, and then
the name of some ID, for instance. Or I could have said dot followed
by the name of some class, like we saw when we were
doing CSS two days ago. You can do the same thing
in document.queryselector, to say select for me
something that is an H1 tag. And take that H1 element,
that heading element, and change its inner HTML, the HTML
contained within that HTML element, and change it to Hello. So what's going to happen
there is it's going to look throughout my page for an H1 element. And once it finds the first
H1 element in the page, it's going to go inside of it, go to
the inner HTML and change its value. It's going to change its
value to hello, in this case. And so we're seeing two
important concepts here. Concept number one, event listeners,
that when I click on a button, that triggers an event, the click event. And that's going to
run the hello function. And concept number two is
this idea of DOM manipulation, that I can select for part of
the page, get an element out of the page programmatically,
and update its value, change the thing on the page,
such that this enables us to now have these dynamic pages that
aren't just the same every time, but that can change in response
to events, in response to things that are happening and so forth. Yeah? AUDIENCE: Does this
change every single H1 tag throughout the page
or just the first one? BRIAN YU: Good question. Does this change every single
H1 tag or just the first one? It only changes the first one. So if I have another H1 that says
some other heading, for example, and I refresh the page, it says
Welcome and Some Other Heading. I click here. Welcome changes to Hello, but
Some Other Heading stays the same. And that's because query
selector will only select for the first thing that matches it. If I wanted to select for
all of the H1 elements, then I'd have to do something
like, document.queryselector all, which is another
function that instead of just selecting for
the first thing, selects for all of the things that match. But then you can't just say
inner HTML because query selector all doesn't return a single element. It returns an array of elements. So what am I do is say something
like, OK, const headings equals document.queryselector all H1. In other words, get me
all of the headings, and that's going to be
an array, and let's save that array inside of a
variable called headings. And now what I can do is I can
do what's effectively a for loop. And the for loop syntax in
JavaScript looks something like this. I would say for const
heading of headings. And I can say const here because when I
have the heading, like each heading is going to be called heading. But in the context of the for loop,
I'm never going to change the heading. Even though the heading
is going to change every time the next iteration
of the loop happens, within any one iteration of the
loop, the heading doesn't change. And now I'm just going to say
heading.inner HTML equals hello. We'll take a look at
what's actually happening and then look at why it works. So refresh the page. I get two headings, Welcome
and Some Other Heading. I click here, and they
both change to Hello. So again, why did that work? On line two, I query for all the
headings, store them in an array, save that inside of a
variable called headings. On line three, I create a for loop,
looping over each of those headings. We'll call each one just heading. And then for each of those
headings, I'm taking the inner HTML and setting that equal to hello. What questions do you have? Yeah? AUDIENCE: Does the JavaScript file to be
in a specific file for either the HTML [INAUDIBLE] function? BRIAN YU: Oh, good question. Does the JavaScript file need
to be in a specific place? In this case right here, where
I'm just opening the HTML file, the JavaScript file needs
to be in the same directory. And when you're building
web applications on the server, for
instance, with like Flask, you'll want to store the
JavaScript file probably inside of a directory called static. It's what we would
consider a static file. The JavaScript file
itself doesn't change. And Flask has a special
way of serving up static files that most
web servers do as well. Other things? How do we feel about this general
idea, these ideas of event listener is waiting for an event to happen and
then performing some action based on it and then manipulating the DOM, actually
changing things on the page in response to what's happening? All right, so mostly green,
but some yellow and some red. So happy to pause and take questions,
if there are more questions. Or I can just show another example,
if that would be helpful as well. All right, let's do another example. I'll create a new file. I'll call it counter.html. And I'll just copy what's
in hello.html for now. What I'm going to do is create a
JavaScript file called counter.js. What I'm going to do is
create an application that just allows me to keep a counter,
sort of like those click counters that you can use to keep tally of
attendance at something, for instance. I'm going to define an H1. And then I'm going to give it an ID,
just to make it easy to reference. And I'll give it an ID of counter. And it's going to start at zero. And I'm going to have a button. When I click on the button, we're
going to run the count function. And the button is going
to say Click Here. So I have a heading that's
going to display the number zero and a button that's just
going to say Click Here. And if I open counter.html,
here's what I see, right? I see the number zero, and I see a
button that says called Click Here. But if I click on it right
now, nothing's going to happen. I'm, in fact, going to
get an error because I haven't defined this count function. So let's define it. Inside of counter.js, here's
the code I'm going to include. I'm going to have a variable,
let counter equal 0. And then I'm going to have a
function, a function called count. And when the count function is
run, the first thing I want to do is take my counter variable and
increment it, increase it by one. And there are many ways to do this. I could do counter
equals counter plus 1. I could simplify that to
just counter plus equals 1. Or if I'm only incrementing by
one, the simplest way to say this is just counter plus plus,
increase the value of counter by 1. And then I'll say document.queryselector
pound counter, in other words, get the thing that has an ID of counter,
which was this H1 tag right over here, and set its inner HTML to be whatever
the current value of my counter variable is. So let's see what happens. I have zero. I click here. And the number now is one. I click again. Now it's two. And every time I click, the
value of the counter goes up, and the page updates to
reflect that counter. And so again, what's happening here? I'm defining a variable on
line one, let counter equal 0, using let not const because the
value of counter's going to change. I want to be able to update the value
of counter throughout this program. Then I have a function which is
going to actually do the counting. And it increments the
value of the variable and then manipulates the DOM, updates
the contents of the actual page to reflect whatever the
value of the variable is. Yeah? AUDIENCE: Should there be like a pop-up
window in JavaScript or [INAUDIBLE]?? BRIAN YU: Sorry. Repeat that. AUDIENCE: So isn't there
usually like a pop-up window for when you do JavaScript? How do you get it so that
doesn't show the pop-up? BRIAN YU: The pop-up window-- so I
was able to use the alert function, if that's what your referring to,
in order to create a pop-up window. But there's no alert function
being used in this code. And so we're not going
to get any pop-up when I'm trying to run the
JavaScript code, for instance. Yeah, can use JavaScript to create
alerts, but you don't need to. In fact, most of the
time manipulating the DOM is one of the primary use cases
the JavaScript can be good for. Yeah? AUDIENCE: This one, like,
just like the [INAUDIBLE],, that they would just change the
first one with [INAUDIBLE],, right? BRIAN YU: Good question. Yes, query selector is only
going to select the first thing. But in the case of IDs,
there should only ever be one thing because IDs are unique. And so when you select for
an ID, it would be a mistake if you had two things with the
same ID in the same HTML page. Is there question here? Yeah? AUDIENCE: Yeah. Can you explain again why you
use const for heading earlier? BRIAN YU: Oh, OK. So the question is why earlier
did I use const for headings when I had all of those different headings? It was because that array
of headings never changed. I was never going to add
something to that array, or I was never going to change it to
be a different array, for example. The real thing is I wasn't going to
change it to be a different array. Because it was always
going to be the same array, that's why I was able to use const. AUDIENCE: You could then change each
individual element inside the array? BRIAN YU: Good question. I was able to modify the
contents of the elements. But the array itself didn't change. So the contents, I was able to
update and manipulate their values. But these were still
the same two headings. I just changed what was inside of them. Yeah. Yeah? AUDIENCE: So [INAUDIBLE]? BRIAN YU: Oh, good question. So there also is a function
called document.getElementById that you can use to get
something by its ID as well. You can use that too. Query selector's a little bit
newer and is a little more robust, in that allows you to select by
different things, for instance. But you can definitely use
getElementById as well. We'll be using query selector
just for consistency. But getElementById will work, too. Often in JavaScript there are multiple
ways of achieving the same thing. All right, let's do another example. We'll add a little bit
of complexity here. So one thing that you'll notice
here is that right now we have button on click equals count,
meaning that inside of my HTML I have JavaScript code for what
happens when a button is clicked on. Oftentimes for design reasons we
want to separate out the JavaScript, sort of put it into its own
file, into the JavaScript file so that I don't have the
JavaScript and HTML commingling together inside of the same file. So what I might do is instead of
saying, button on click equals count, I can move this to the JavaScript
file, much in the same way that two days ago when we were looking
at CSS we were able to say, all right, instead of having inline CSS right
next to the element in a style attribute, we move the CSS either into
the header or into a separate file, for instance. And so I can do the
same thing here, too. What I would like to
be able to do is say document dot query selector
button on click equals count. I'd like to be able to
say something like that, select a button, and when you
click, when you get clicked, run the count function, just add
this sort of code to counter dot JS. And so now if I refresh
this page and click here-- OK, nothing's happening. Any thoughts as to why? This is a little bit subtle,
but there is a small bug that I've created, an error. So recall a moment ago, I said that
HTML pages are read from top to bottom. So my web browser is looking at
this HTML page from top to bottom. It's going through the
HTML header, title. OK, here's the script. And at the point that it hits the
script, it's going to run the script. And when it runs the script,
it's going to first run, all right, let's get the button. But at this point in time, the
page doesn't have a button yet. If I'm reading the
page from top to bottom and I hit document dot query
selector button on line five, well, the button isn't defined
until later on, on line nine. So the [INAUDIBLE] hasn't
fully been loaded yet because I'm only on line
five of this HTML file, and so there's no button to select. And so there's no way to say
when the button is clicked on, run the count function. Is that nuance clear as to
why this isn't quite working? All right. So how do we fix this? Yeah, question. AUDIENCE: If you put the script back
from the bottom, would that be helpful? BRIAN YU: Good question. We put the script tag at the bottom? Yes, that would certainly fix the issue. But we'd like to keep
the script in the header because that's often where
scripts are going to go. And so we can come up with other
ways of solving this problem as well, and probably the most common way
is to have something like this-- document dot ad event
listener DOM content loaded. And then put the event
listener inside of that. So this is a lot of sort
of strange looking syntax. We'll tease it apart. This is all in the lecture
source code examples, which are online now if you
want to take a look at them. But what's going on here? Document dot ad event listener is saying
let's take the document, this web page, and add an event listener to it. Let's listen for something. And what event am I listening for? I'm listening for a special
event called DOM content loaded. DOM, remember, is the
Document Object Model. And so when I say add event
listener DOM content loaded, what I'm saying is let's wait for all
of the DOM to finish loading, all of the buttons and the
headings and the forums and whatever else might be inside of my
HTML page, wait for all of the elements to finish loading. And when everything's done
loading, then run this function, the function that comes after it. So whereas before when I was
just reading top to bottom, the take the button and when it's
clicked on run the count function, that happened right away before
the DOM was done loading. Now I'm saying, all right, all
this code that I want to run, I only want it to run after
the DOM is done loading. And so that's what this beginning
part of the script is saying. Wait until the whole
page is done loading and then run the JavaScript code. So the syntax looks a little bit
funky, but with practice you'll find that this notion of passing
in functions as arguments to other functions is something you'll
see quite commonly in JavaScript. And yeah, question. AUDIENCE: Would you be
able to do the same thing if the button was dynamically
created or generated on the page? BRIAN YU: Good question. Would you be able to do the same
thing if the button were dynamically created or generated on the page? Yes, you could. The DOM content loaded just refers to
all the content initially on the page, so when all that is loaded
this function will run. But certainly, , as we'll soon se
when we get to this morning's project, we will be adding buttons to the page
dynamically and adding event listeners to those. And so you can do similar
things there, too. Yeah. AUDIENCE: Um, on the
second line [INAUDIBLE].. BRIAN YU: Oh, good question. Yeah, this is actually a really
interesting point about JavaScript. What am I passing in as
the value of on click? I'm passing in count. And what is count exactly? Count, defined here on
line seven, is a function. And so JavaScript does
something interesting which is it lets me treat
functions as values. I can take a function and set it
equal to some variable or some value, and you can treat functions
the same way that you treat integers or strings or
floating point numbers or arrays or any other type of
data in other languages. And this is a bit of a tricky concept
to wrap your mind around at first. This has to do with getting towards
this idea of functional programming, passing in functions
into other functions and using functions in this way. And this is quite powerful because if
I were to put parentheses after count, that would actually run the count
function right now on line two. It would run the count
function and set whatever its return value is equal to this. But I don't want to run
the count function now. I want to say, when the button is
clicked, then run the function. And so by just passing
and count, no parentheses, I'm not running the function. I'm just passing in the function
providing it as the value of on click, so that when the button is clicked,
then it's going to run the function. So this is a little bit tricky, but
this idea is that I can take a function and rather than run it, just
pass it around as a value and save it inside of
a variable, provide it as the value of on click, the on click
attribute of the button, for example, and use it in that way. Questions? Yeah. AUDIENCE: Why would you always
want to have event listener, have your Java scripts run
after the entire HTML page? BRIAN YU: Why would you-- AUDIENCE: Why wouldn't you always just
want to event listener for JavaScript? BRIAN YU: Why wouldn't
you always want to have an event listener for your JavaScript? Oftentimes you do just want to have
an event listener for your JavaScript, although your functions
can exist outside of that. So this function, count, for
example, none of that code is actually going to run until I
actually call the count function, a so it doesn't need
to be inside of this add event listener because it's
not going to run anyways until I call the count function, for example. Other things? I know this notion of
passing around functions is a little bit tricky, but hopefully
with a couple more examples it'll become a little clearer. Yeah? AUDIENCE: For DOM content load
[INAUDIBLE] once everything [INAUDIBLE] after a certain [INAUDIBLE]. BRIAN YU: So DOM content loaded
will wait until everything is done. There is no specific event
for after half of the page is loaded, for instance. But wherever you put
your script and that is where that script is going to run. And so if you were to add script tags
in other places throughout the page, you could get a script that runs
before all of the rest of the content has loaded for instance. And that's something that you could do. Is there a question over here? Yeah. AUDIENCE: So how is this better
than just adding on click is equal to [INAUDIBLE]? BRIAN YU: So the question is why is
this any better than just adding button on click equals something? Why should I do this programmatically? Doing it programmatically gives
us a little bit more flexibility in the sense that right now,
yeah, this is no different than if I just said
on click equals count. You can imagine a situation
where maybe on click-- I don't necessarily always
want to run the same function. Maybe I want to run one of a
couple of different functions and I want to programmatically be
able to decide which function to run. This ability to use
this variable account and pass it around as a value means
that I could do something like that, means that I could pick and choose, do
things programmatically, add some more logic to this program. And so doing it in the
JavaScript side of things just gives us a little bit
more flexibility in that sense. Yeah? AUDIENCE: If you want to
have multiple functions, say that the count function [INAUDIBLE]
different functions, at the very top, you have a document as a
[INAUDIBLE] have function, [INAUDIBLE] all the functions
in JavaScript or just-- BRIAN YU: Oh. So the question is, what
exactly is this function doing? This function is actually being provided
as an argument to add event listener. This is a function that
I'm saying, this is the function that should run
when the DOM content is loaded. And so I could have other
functions here like hello that get triggered on other buttons,
but this function itself, this is just a function
that's describing what code is going to run when
the DOM content is done loading. I could have separated this out
and said let's take this function and call this function start for what to
do when you start running the program. And I could have said, document dot add
event listener, when the DOM content is done loading, run the function start. And then so that's
what would happen then. When the DOM content is loaded,
we would run the function start, and here is that function. But oftentimes if all I'm
doing is naming a function so that I can provide it as the argument
to something like an event listener, for instance, it can be more succinct
just to take the whole function and plug it in as the argument to
add event listener, and in this case, not even bother to give it a name
because it doesn't need a name. This is what we call an anonymous
function, a function that just doesn't have a name. And I'm providing this function to
say, when the DOM content is loaded, this is the function that should run. Yeah, of course. Yeah? AUDIENCE: How is adding event listener
different from the [INAUDIBLE]?? BRIAN YU: So question is,
how is an event listener different from query selector? Query selector is going to look
throughout the page for an HTML element and pick it out for me, give me that
HTML element so that I can do something with it, so that I can modify it,
so that I can add properties to it, for example. Add event listener is
going to take some element and it's going to wait
for something to happen. And when something happens, then
it's going to run a function. In this case, I'm taking the
document-- my whole web page-- adding an event listener, saying
wait for all the content of this page to be done loading, and when it's
done loading, run this function. So that's the distinction there. Yeah? AUDIENCE: So kind of like the previous
question, if you have more functions, could you add them to the
same function line on one 2? BRIAN YU: Yeah. So line 2 doesn't need
to just be one line. I could add another
document dot query selector. I could do any arbitrary
logic in this function and make it as long
as you want it to be. Yeah? AUDIENCE: So is it [INAUDIBLE]
argument in the add event listener to the function, is that
unique to add an event listener or do you actually [INAUDIBLE]? BRIAN YU: OK. So question is, is this idea
of this anonymous function passing in a function, is that
unique to add event listener? No, you can do that anytime you want to
provide a function as the argument to-- as a value to anything. And in fact, I don't even need this
function called count necessarily. If I wanted to, I could
just say, all right. I don't need to name
this function count. Let me just create another
anonymous function inside of which is the contents of the count function. And I'll move the declaration
of counter up to the top here. But now what I'm saying is, all
right, when the DOM content is loaded, run this function. And this function is going to
say, when the button is clicked, then go ahead and run this function,
which is going to increment counter and update counter as in our HTML. This would be exactly the same thing. I've just gotten rid of another
function and just turned it into an anonymous function. Yeah? AUDIENCE: Is it preferable
to have [INAUDIBLE] that way? Or is it better to find [INAUDIBLE]? BRIAN YU: So is it preferable
to have fewer functions? It's going to depend a little
bit upon the type of program that you're creating. Generally, I'd go for cleanliness and
ease of reading as the top priority here. And so here I'd probably prefer
to actually separate count into a different function so
that it becomes very clear, here's what the function does. It counts. And I'm saying when
the button is clicked, then you should run the count function. And that just seems a little
bit clearer to me, at least, than putting everything in
without giving them names. Yeah? AUDIENCE: So the scope
of [INAUDIBLE],, but if it's outside of [INAUDIBLE] variable? BRIAN YU: Yeah. If this let counter is outside of
the curly braces of any function, then it'll be accessible from within the
count function or any other function, for example. OK. Let's take a look at
another example that will hopefully help to make some
of this a little clearer as well. So I'll go in here and we'll
take a look at color 0 dot HTML. So here is color 0 dot HTML. It's got hello in big letters and
it's got three buttons-- red, blue, and green. So what am I going to do here? If I click on the red button,
let's just observe what happens and then take a look at why it happens. I click on red and hello changes to red. I click blue, hello changes to blue. I click green and
hello changes to green. Why and how did that happen? Well, all right, let's take
a look at color 0 dot HTML. Let's take a look at the body. I have a heading that has an ID
of hello that just says hello. And then I have three buttons--
red, blue, and green-- that are just red, blue, and green. And they have IDs--
red, blue, and green. Let's take a look at the
JavaScript that's making this work. First, we add an event listener,
wait for the DOM content to load, and then run this function. Same as before, basically just saying,
wait for the page to finish loading. And then I'm saying, document
dot query selector red-- get the red button, the
thing that has ID red. When it's clicked-- on click-- run this function. What is the function doing? It's saying, all right, let
me select for the thing that has ID hello, that heading. And then I can actually
change its style. I can say dot style to get
at the style of that element. And what property do I want to change? What CSS property? Same as anything as this property. I want to change the color and I
want to change the color to red. And then I do the same thing for
blue and the same thing for green. So we have these nested
functions, these event listeners. There's a lot of JavaScript code here. Let's see if you can
glean, generally speaking, what it is that this code is doing. It's waiting for the
DOM to finish loading and then when a button is
clicked, we're changing the style of some HTML element. Yeah? AUDIENCE: Is it better to use
single quotes or double quotes? Or does it not matter? BRIAN YU: Oh. So is it better to use single
quotes or double quotes? I've been using them
sort of interchangeably. JavaScript doesn't really care. It's really a matter of
personal preference and style. You should just be consistent within a
file is probably the best thing to do. AUDIENCE: I know we had that one
advantage of using double quotes is that this side of it was [INAUDIBLE]. BRIAN YU: Yeah. Within double quotes,
you can use single quotes and just treat them as normal
single quotes, and vice versa. Within single quotes, you
can use double quotes, and those are just
plain old double quotes. So that can be a reason to make a
choice in certain situations, too. All right. Questions about anything so far? ? What seems poorly designed about this
example anything that strike you? Yeah? AUDIENCE: It's the same code. BRIAN YU: It's the same code. There's a lot of code
repeated multiple times and so this is probably not ideal. I'd like to do something about that in
order to make it a little bit better. So let's take a look
at colors one dot HTML. Colors one dot HTML is going
to do exactly the same thing-- hello, red, blue, and green. I click red, it turns red. Blue turns blue, green turns green. But how is this one working? Well, here's the body. I have a heading, hello. And then I have buttons,
but these buttons have a few other different attributes. These buttons, instead
of having an ID, have a class because I want this class
to refer to all three buttons. The class is called color change
so later I can say, all right, get the things with the class of color
change and do something with them. And they also have this data attribute. And this data attribute is something
that you can add to HTML elements if you want to store data
alongside those elements. And in particular, I want each of my
buttons to store data about what color they should change the heading
to when I click on that button. So here I'm saying, button
class equals color change. Data color equals red, in order to mean,
I want to store along with this button some information and the information
about what color it should turn, and it should turn the
heading red in this case. And I give the blue button the data
color of blue, green button data color of green. And so now here's the JavaScript
code that makes this all work. I have document dot add event
listener DOM content loaded. Wait for the whole
page to finish loading. And so what's the code that
I'm ultimately going to run? I'm going to say, document
dot query selector all for any-- select everything
that has a class of color change. And now I have an array of things. And now I can do use a
function called for each. And what for each is going to do is
it's basically going to take an array and apply a function for
each element in that array. So I've got this array
of buttons and I would like to do the same thing for each
of the buttons inside of this array. And so what am I going to
do each of these buttons? Well, I'm going to run this function. The function takes this
argument, the button itself, the element of the array. And what am I going to
do with that button? Well, when the button is clicked,
then go ahead and run this function. What is the function doing? Well, it's saying let's get the
hello heading, get its style, change the color property of the style. And what value do I
want to change it to? Well, I want to take the button and
I want to get at its data dash color attribute. And so how do I get at the data
information inside of an HTML element? In JavaScript you do this by
saying button dot data set, which gets you at all the data
information about that HTML element. And I want access the
color property of that. So button dot data
set dot color is a way of saying, all right, let's take
this button, get at the data elements within it, and extract
the color from it. There's a lot of new
syntax here and a lot of new syntax in a lot of the examples
that we're going to show today. Goal of this is not to have
you memorize all of this stuff. These examples are posted online. You can refer back to
them if you need it. But it's just to give you
a sense of the tool kit that JavaScript enables you to
use, this idea of associating data with elements such that later you
can go back and take an element and get it the data associated with it. It's a pretty valuable tool
that you might find useful as you go about building web
applications using JavaScript. Questions about what's
happening here and why it works? Yeah? AUDIENCE: Why is button passed
as the parameter to the function? BRIAN YU: All right. So the question is why is button passed
as the parameter to the function? This is part of the way
that for each works. What for each does is it takes
an array and applies a function to every element in that array. So I can actually demonstrate--
this is a good opportunity to talk a little bit about
functional programming, which is something that JavaScript really
enables, this idea of passing functions around as values of their own and
that you'll see in other classes. CS51 really emphasizes
functional programming as an idea and is very common in JavaScript
programming in general. So let's do this. Let's get an array. I'll zoom in here. And so let array be--
and right now I'm just using the console
inside of a web browser like Chrome, which
you can do just to run JavaScript code if you would like to. And I'm going to have this array be
1, 2, 3, 4, 5, so it's just an array. And now I'm going to
say array dot for each. And for each element in this array
I'm going to run some function. And that function is going to take as
its argument the element of the array. It's going to go for each element
in this array, and for each one we're going to run this function,
passing in that element as the argument to the function. And here I'm going to say,
console dot log element. Console dot log is the
equivalent of printf, just means print to the console. And I press Return. Missing parentheses after argument list. Oh, I didn't close the parentheses
after the end of for each, so we'll go ahead and close the
parentheses after the end of for each. And OK. What gets printed out? 1, 2, 3, 4, 5. The undefined is because the for each
itself is not returning anything, so you don't have to
worry too much about that. But what I got printed
out to the console is 1, 2, 3, 4, 5 because
for every element we just printed out that element. I could, instead, have said, console
dot log element times 2, for example. And that would have printed out-- oh,
I did the same problem mistake again. And that would have printed out 2,
4, 6, 8, 10 because for each element we're just going to go through each
element in the array, multiply it by 2, for example, in order to do that. Questions about that or how it worked? Yeah. AUDIENCE: I actually have a
question about the previous one. For the data set dot, or
button dot data set dot color, can we define and kind
of data attributes we want on, like, we do data
dash then make up our own name? Or does it have to be-- BRIAN YU: Yes, you can do
data dash anything you want, just some arbitrary name
for the data attribute. And then you can access it via the
data set property of the HTML element. So you can store arbitrary
data with your HTML elements if you would like to. One new feature of ES6, one of the
more recent versions of JavaScript, is a different way of
defining functions. You can have what are called arrow
functions, which is this idea that you can define a function instead
of using the word function, you can use this arrow syntax
to mean, take some input and then provide some output. And so I'll show you an example of that. What I could do is I could take the
array 1, 2 3, 4, 5, as I did before. And then I could say something like
for each, just take the element, and console dot log that element. And then what I get printed
out as the exact same thing-- 1, 2, 3, 4, 5, just
much more succinctly. This right here is a function
that takes as input the element. And what it does with that
element is just print out that element to the console. And that arrow is this idea
of element as the input to the function and the arrow is
the actual body of the function. After the arrow is what the
function should actually do with that individual element. And so functional programming gives
us a lot of interesting capabilities that we might not have
had before or that we can do more easily now with the
ability to have functional programming. And so I'll give you an example. In addition to having for
each, which takes an array and run some function
on each element in it, I also have this function called map. What map is going to do
is it's going to apply a function to every element in the array
and give me a new array as a result. So let me apply-- take the array 1, 2, 3, 4, 5,
and let me map over that array a function that takes the element and
returns element times 2, for example. I press Return and what I get is I
get a new array of five elements-- the parentheses 5 just means
five elements-- and that array is 2, 4, 6, 8, 10. I was able to take an array and generate
a brand new array by mapping over every element inside of that array. This is functional programming,
passing a function as arguments around in order to create
interesting behavior. Yeah? AUDIENCE: Is this different
than in C [INAUDIBLE] loop, and then within the for
loop [INAUDIBLE] function? BRIAN YU: In C you could
have replicated this idea by having a for loop that loops over it
and generates a new array, for example. You certainly could do that. Functional programming just
offers a slightly different way of achieving that same effect, yeah. Yep? AUDIENCE: Is elements an arbitrary name? BRIAN YU: Yeah, ELT
is an arbitrary name. It could've been anything
you want it to be. AUDIENCE: So in the previous example,
button was also an arbitrary name? BRIAN YU: Button is
also an arbitrary name. Yeah, any argument to the function
you can call whatever you want. We just tend to give it names
that are semantically meaningful. Yeah? AUDIENCE: How do arrow
functions distinguish the arbitrary name of an input
versus the name of the [INAUDIBLE]?? BRIAN YU: Good question. The arrow function itself
doesn't have a name. It's just an anonymous function
that doesn't have a name. So ELT in this case is
always just going to be the input variable to the function. AUDIENCE: But if you were
writing it in a script file, how would you name the arrow? BRIAN YU: How would you
name an arrow function? You would do something like-- let's open up hello dot
JS or counter dot JS. I could have instead of
this said const count equals or I could define a function
like const double equals a function that takes as input x
and returns x times 2, for instance. And so you could do something like that. Again, a lot of new syntax
here, but see if you can just grasp the general ideas
here and then we'll get some opportunity to actually
try this hands on so you can see how this actually works. Other questions? I'll show you one other example
of functional programming at work. You can also-- in addition to
a map to map over an array, you can also filter an array. So I could say, all right, 1, 2,
3, 4, 5, let me filter this array, take every element, and only return
the elements that are greater than 2, for instance. And that will take 1, 2,
3, 4, 5, and return for me a new array that's
just 3, 4, 5, that has only the elements of that array that
are greater than 2, for example. Yeah? AUDIENCE: Those filter mutate
the array, or it doesn't do it? BRIAN YU: Does filter mutate the array? No, it's just returning
to me a new array that is the result of doing that filtering. Other questions? Let me show you one other
or a couple other examples. Let's go to Tasks 0 dot HTML
and let's go to Task 0 dot HTML. Here's a simple JavaScript
application that just acts as a to-do list, a list
of things that you need to do. So you type a thing you need
to do, you press Submit, and it adds it to a
list of things to do. Here's another thing that I need to do. I press Submit, it adds it
to the list of things to do. And so this is an
interesting application that actually lets me interact with it. I type things, it
manipulates the DOM, it updates the contents
of the page in response to whatever it is that I'm doing. And so how exactly is this working? So inside of the body of the
page I have an unordered list called Tasks that's just going to
maintain that list of all of the tasks that I currently have. And then I have a form, a form where
I can actually type in a new task and press Submit in order to
submit that form to do something. The form has an ID. It's called New Task. And then I have an input field where
I can actually type something in. The place holder here is
new task, which is just the text it's going to be displayed
before I start typing something in. And then I have a Submit button
at the bottom of the form. And so that defines the
general structure of the page. I have an unordered list, I have
inform or I have an input field, and then a Submit button that's actually
going to let me submit this form to say I want to submit a new thing. What is the JavaScript code
that's making this work? Well, OK, I'm adding an event
listener for DOM content loaded, waiting for the
whole page to finish loading. And when it does, I'm
going to run this function. Again, I'm using an arrow function
here, which is just new ES6 syntax. It's just the same as any
old function, although it does behave in slightly different
ways, the nuances of which we won't touch on today. And so what am I doing in here? I'm saying query selector new task. What is ID new task? Well, that is down here. That's this form. So OK, I've selected the
thing called new task and on Submit, it's
saying, when I submit this form, what would I like to do? Well, what I'd like
to do is actually when I type in something
and press Submit, I'd like to add that to my list of tasks. I have this unordered list
and I want to add a new list item to that list to reflect
whatever it is that I just typed in. So const LI equals document
dot create element LI. Document dot create element
creates a brand new HTML element. So I've here said to create a new
list item element, and LI element, and just save it inside
this variable called LI. Then I say LI dot inner HTML,
meaning take that list item. I want to update the contents
of it, the inner HTML. And what do I want
that list item to say? Well, the input field
down here was called Task. It had an ID of Task, and that was where
I was actually typing something in. So this list item up here, it's inner
HTML should be whatever I typed in. And I can get at whatever I typed in it
by saying document doc query selector, get the thing with ID
task and get its value, get that inputs value,
which in this case is whatever it is that I actually
typed in into the task field. I then say document dot
query selector tasks append LI, meaning take this
element of all of the tasks and go ahead and add this
thing to the end of it. Add this new list item
that I have just created. And then the last step is
to clear the input field, document dot query, select
your task, change its value to just be empty so that I can type in
a new fresh task if I would like to. Let's just show you what all
that looks like in practice. I type in a thing to do. When I press Submit,
that triggers the event. I've submitted the form
and when it does that, it's going to create a new list item element,
take the contents of this input field, set that as the inner HTML of the list
item, add that list item to my list, and then it's also going to
clear out this input field. So just step by step describing the
behavior that I want to perform. You can imagine as programs start
to get a little bit larger, doing this all the time is going
to start to get annoying. In a couple days time,
we'll introduce React, which will actually
simplify a lot of this and make it easier to reason about more
complex, more sophisticated programs. But questions about this
for now and how this works? Yeah? AUDIENCE: Would this be [INAUDIBLE]
how can you append [INAUDIBLE]?? BRIAN YU: So LI is a const because when
I define this variable LI, at least in the context of this
function, I'm never changing it to a different list item. If I were to later try and set
LI equal to something else, that is when this constraint would break. So a const, you can define it. You can manipulate its properties. You just can't set that variable
name to be some new thing is the only constraint there. Yeah? AUDIENCE: Why'd you choose to stop the
form from submitting at the bottom? BRIAN YU: Why did I choose to
stop the form from submitting? Normally when you submit a form, it
will either submit to the same page and just submit the page again or take
you to some other route altogether, and I didn't want that to happen. I wanted the user to stay on the
same page without reloading anything. So return false just
stops that from happening. Yeah? AUDIENCE: Why is it not
a problem [INAUDIBLE]?? So why do we not replace [INAUDIBLE]? BRIAN YU: Yeah. So why is it-- why am I allowed to say that
LI is a const when every time I create a new task this LI is different? It has to do with what's called
variable scope, like where this variable is actually alive. And this variable only exists for this
iteration, this run of this function. And the next time that I create that I
run this function, I get a brand new LI and so it doesn't matter
that I had an LI previously. So I can use this const variable
so long as in the same function I never said LI to be
equal to something else. Yeah? AUDIENCE: So like, did you have
to define it as a constant? Or can you just take that out
and LI would work [INAUDIBLE]?? BRIAN YU: I could have just used
let here if I had wanted to. It's just a little bit unnecessary
because I'm never changing it, so you'll generally want to use
const if you're not actually going to expect to change
the value of a variable. Yeah? AUDIENCE: For line 7, [INAUDIBLE],,
why did you pass the [INAUDIBLE]?? BRIAN YU: On submit is the event
that happens when you submit a form. And so new task is the idea that
actually refers to this form. So when I submit the form, I want
to run the event, run the function, and the function is going
to look at the input field. And so I have the event listener on the
form that then looks at the input field is why they're different. There are a couple other examples
in the source code examples if you'd like to go through them, just
to get a better understanding of what's going on in JavaScript
and how to actually do these sorts of manipulations. What I'd like to do now is actually get
started with this morning's projects, sort of walk through it together. We'll go through it together. I'll post the distribution
code so you can look to it if you would like to as
well, but then we'll get started and I'll show you what
we're creating first. Before we get to that, any
questions about anything? What we're going to be
creating this morning is a quiz application,
basically a mini quiz online that allows you to have
questions and answer questions and keep track of how many
questions you've gotten correct. So we can have code that
looks something like this. It displays a question, it
displays some answer choices. What is the binary
representation of the number 28? Anyone know which of
these is correct offhand? Any guesses? I heard someone say 1 1 1 0 0. OK, great. 1 out of 1 questions correct. What type of loop will
always execute at least once? AUDIENCE: [INAUDIBLE]. BRIAN YU: Do while. OK, throwback to when we were learning
about C. Which of the following HTTP status codes means not found? AUDIENCE: 404. BRIAN YU: 404. Let's just try getting a question
wrong just for the sake of example. Let's say 500. OK, quiz complete. Questions correct, two out of three. What we're going to be doing is just
building a quiz application like this using HTML and JavaScript,
and CSS if you'd like to, that just displays some questions
that you can choose for yourself, or we use the questions
that I used as well, and then lets you answer those
questions, keeping track of your score as you go. Questions about what we're trying to do? And then we'll actually start
trying to build it together. All right. Let's give this a shot. I'll go to my desktop. I'll create a new directory called Quiz. We'll go into the Quiz directory
and we'll start working on this. So I'm going to create a new file. We'll call it quiz.html
and quiz.html, we're just going to start off as a same old HTML
page that we've been doing before, give it a header. The title will just
be quiz, for example. And we're probably going to want
to link in some other files, maybe a CSS file, maybe some
JavaScript files, so let's do that. Let me first create a styles.CSS
file where we can store any CSS code that we want to use here. And then I can say link
href=styles.css rel=stylesheet, and that's basically
me saying, all right, I'm going to link this styles.css file. It's my style sheet for this page,
so any CSS code I put in styles.css will reflect in quiz.html. And let me also create a
new file called scripts.js where I'm going to store all the
JavaScript code for this quiz application. And I'm going to say script
source equals scripts.js and that's going to be my way of saying,
I want to include some JavaScript here as well that I want to associate
with this particular page, and the JavaScript code
is going to go there. Questions about what we've done so far? All right. Now in the body of the page
what am I going to include? Well, at the top of the
page, I'm going to go ahead and say, all right, let's just call it
Quiz, give it a heading called Quiz. And underneath the quiz I would
like a place to display the question and display the answer choices. But the question and answer
choices are going to change, so ideally I'd like to
have the JavaScript take care of actually putting the question
and the answer into the page. But I need space on the page for the
question and the answer choices to go, so I'm going to go ahead
and say h2id=question. So the question is going to be a
heading as well, not as big as quiz, so each h2 for slightly smaller than h1. And it's going to have an ID of question
so that I can reference it later, so that I can find this place in the page. But for now it's going to be empty. I'm not actually going to
put a question on the page. I'm going to let the JavaScript do that. And we'll get to that in just a moment. Underneath that I need some place to put
it in the answer choices, the options that the user can actually select. So I'll say-- let's create a div,
just a vertical section of the page, ID=options End array. I don't know what the options are yet. Again, I'll let the
JavaScript handle that. But I need some space on the
page where those options can go. And so that's what I'm
doing here, creating a new div where I have those options. And finally, at the bottom
we'll do questions correct and then I need some space where we
can input the number of questions correct that I have. By default, it's probably
just going to be 0 out of 0, but I'm going to need to
update that frequently. So I'm going to put
this inside of a span. A span you can think of just as
an inline section of the page that I can later reference,
similar to div, but divs take up their own vertical space. But I would like 0 out of 0 or 1
out of 1 to be on the same line as questions correct, so I'm
going to put it inside of a span. Give it an ID called correct, just
as a way of referencing it later. And for now, we'll say 0--
or not 0 and 0, 0 of 0. And so that's it for the HTML. I'm just defining the
structure of the page-- a heading that says Quiz, a place
where I can put the question, a place where I can fill in with
each of the options that I have, and then a place where
I can say, OK, here's how many questions correct I've gotten. If I open up quiz.html right now,
here's what the page looks like. It just says quiz and
questions correct 0 out of 0. What questions go so far
about just the HTML here? Yeah? AUDIENCE: Why do you [INAUDIBLE]? BRIAN YU: Why do I need the span? I need the span because later
on when I get a question right, I want to be able to update this text. Instead of 0 out of 0 I want it to
be 1 out of 1 and then 1 out of 2 if I get one wrong. And to do that, in my
JavaScript I'm going to need to be able to reference
this particular part of the page. And so by wrapping it inside of
a span that I give a name to, an ID of correct, I can
later query select or try and grab the thing that has an ID of
correct, and then modify the contents. So I'm just thinking
ahead here, thinking that eventually I'm going to need
to edit that section of the page. So I'm giving it a name that makes
it easier for me to edit it later. Other things? All right. Let's actually go ahead and actually
try and write some JavaScript code. The first thing that I'm going to need
is I'm going to need some questions, so I'm going to define a
variable called questions. It's going to be constant because
the questions aren't going to change. I'm just going to define them once and
those are going to be the questions. And it's going to be an array. It's an array of one question
after another question after another question. And each question is going to be what
we'll call a JavaScript object, which you can think of a Python
dictionary that associates keys and values together. And the idea here is I want
to be able to have a question, and the question is going
to be some question. We'll do something simple for
now, like, what is 10 plus 10? And we're going to have options. So my options are what data
type makes sense for options? AUDIENCE: A list. BRIAN YU: A list or an
array in JavaScript, yeah. Same idea. So my options are going to be-- all
right, let's do 8 and 28 and 30. And I guess we should probably put
the correct answer in there, too-- 20. OK, so we've defined question, we
defined our possible answer options, and then we also should probably
define what the answer is. JavaScript needs to know what the
correct answer to the question is. And the correct answer
in this case is 20. And I'm making everything strings
just for ease of comparison later because not all my
answers are necessarily numeric, though you can imagine
a variant of this where you use numbers instead of strings. Let's do another question. Anyone have a question in mind? We'll do, what is
Athena's favorite animal? Anyone know the answer to this? AUDIENCE: Otters. BRIAN YU: Great. You're paying attention. All right. We'll say jellyfish and
penguins and otters. And the answer is going to be
otters, and that'll be good for now. You can feel free to add more questions. Add whatever you want to
the page if you'd like to. So we've got our questions. What other information, what
other variables do we need here? What do we need to keep track of? Yeah? AUDIENCE: The number of questions. BRIAN YU: The number of questions
we've gotten correct, yeah. So we'll set let correct
be 0, just a variable to stand in for how many
things we've gotten correct. Anything else we need to keep track of? Yeah? AUDIENCE: [INAUDIBLE] BRIAN YU: Yeah, what question
number you're currently on is probably something
that we should probably have a program keep keeping track of. So maybe say, let
question number equal 0. I'll go ahead and zero index this so
it's easy to index into the array, because the first thing in the
array is going to be element zero. So we'll start at question number zero. And let's write some code here. Document dot add event listener. We'll wait for DOM content loaded,
and when Dom content is loaded we'll go ahead and run a function. And what should this do? Well, we want to load a new question. We want to load the
question onto the page, but loading a question onto the page
is something we're going to do a lot. We're going to load a
question onto the page, and later on we're going to load
another question onto the page and so on and so forth. So rather than put the code
to load a question right here, it's probably going to make more
sense to create a function just called load question that we can call here,
that we can call later if we need to, so that it's just easy to reference. And so what's going to happen is as
soon as the page is done loading, let's go ahead and call
this load question function. Questions about what we've done
here so far and why we've done it? We've defined a variable
called questions that's going to keep track of an array
of all the questions we've got so far-- questions, options, what
the correct answer is. We're keeping track of the current
question number, how many questions we've gotten correct. And then as soon as
the pages done loading, we're going to call this
load question function. All right. So what's load question going to do? Well, how would I access
the current question, the question that I want to load? Let's think about for that a little bit. Yeah, idea? AUDIENCE: [INAUDIBLE] BRIAN YU: Great. So when we want to move
on to the next question, we can increment question number. But yeah, this question
number variable is the index of which question I want to get at. And so if I have a variable
called questions up here, how will I get at the current question? What code would I write? Yeah? AUDIENCE: Questions bracket
question number bracket question. BRIAN YU: Yeah, exactly. Questions is my variable that's
keeping track of this whole list, but I don't want all the questions. I just want the current question. So if I say questions square
bracket question number, that's going to get me
just the current question. But the current question
has three parts. It has a question, it has
options, and it has an answer. And so I want to get
at just the question property of this particular object. And so I'm going to say
question number dot question. You could also use the square
bracket notation, but for an object, often you'll reference these
properties just using the dot notation. So I'm going to say,
question square bracket question mark question
number dot question. And try and make sure you
understand why that works. Questions is our array of questions. Question number is the index
of the question we care about. And that's going to be an object
with three parts-- a question and options and an answer, and I
want just the question out of that. So this is our question. And what do I want to
do with that question? I've gotten the question now,
but where do I want to put it? AUDIENCE: [INAUDIBLE] BRIAN YU: Yeah, the
inner HTML of something. Inner HTML of what? Here's my HTML page. AUDIENCE: The h2 with ID question. BRIAN YU: Yeah, the h2 that has
ID of question, that's where I want to put the actual question. So it has an ID of question,
so how am I going to get it? What code will get the thing
that has an ID of question? Yeah? AUDIENCE: Document dot query
selector and then quotation marks hashtag question. BRIAN YU: Great. Document dot query
selector pound question is going to say get the thing
that has an ID of question. And I would like to set its inner
HTML to be equal to this question. And just for fun, I'm going to
swap the order of the questions so that we get this one up first. So now I open up quiz.html, refresh
the page, and immediately we see Quiz. And now we've been able
to programmatically take the first question and put it into
the page in the question spot. Questions about how we did that? All right, let's move on. Green smiley faces, great. Now I want to actually insert
the options into this page, like the options that
are going to allow me now to be able to choose among
the possible options. So how am I going to do that? Well, where are the options stored? If the question is stored in question
square bracket question number dot question , what would I use
to get at the answer options? AUDIENCE: [INAUDIBLE] BRIAN YU: Great. Questions square bracket question
number, get the current question, and get the possible options. I'll go ahead and store that. That's going to be all my options. And what I'd like to
do is I'd like to have some loop over all of
those options that's just going to get me one option at
a time and do something with it. So I'm going to say for const
option of all of these options. And now I've got a loop. I'm looping through all
the possible options because I want to do something
with each of those options. And if I want to, I can
do console dot log option. Just for now, let's print
out the option and make sure it's what we expect it to be,
taking things one piece at a time, slowly just making sure
that we're building this application the right way. I'll open up the console,
refresh the page, and we get, what is
Athena's favorite animal? And sure enough, if you look
over here at the options, we see that we have jellyfish,
penguins, and otters as the possible options for this. They show up in the console, but now
I'd like to actually make them buttons, for example. So what do I need to do here? Well, the first thing
I probably need to do is to get it where I want
to put the options where do I want to put the options? AUDIENCE: [INAUDIBLE] BRIAN YU: Someone say it? OK. The thing that would ID options, great. So we'll create a
variable, call it options, set it equal to document
dot query selector options. The thing that has ID options we're now
going to store inside of this variable called options. And the first thing I'm going
to do is just clear it out. In case there was something in it
before from a previous question, we'll say options dot inner HTML
is equal to the empty string. It should be nothing. Yeah? AUDIENCE: When you're doing this
over the options [INAUDIBLE],, so is that equivalent
to doing the for each? BRIAN YU: Yes. I could have also just
done for each here and that would have
worked just fine, too. I'm using a for loop here
just because it's probably what you're more familiar with from
other languages, but in practice you actually would probably end up
using the for each, tends to be more JavaScript paradigm. But yes, you could use a
for each here, for sure. So now what I'd like to do
is for each of these options, let's try this-- options dot
inner HTML plus equals option. I take all the options, get at the inner
HTML, and just add the option to it. This isn't going to be perfect,
but you'll see what it looks like. We'll go ahead and refresh the page. What is Athena's favorite animal? All right, here's what the page
looks like-- jellyfish, penguins, otters as the three possible
options, which is OK. But we'd like to do better than that. We'd like to actually make them buttons. And so rather than just add the
option to it, let's go ahead and add something more. Let's add-- and now I'm
going to use it backticks. This is JavaScript's way of doing
format strings, the equivalent of what was the F in front of
the string in Python, because I want to be able to substitute
some values into this string. And you'll see how I'm going
to do that in just a moment. We're going to have a button, and
just forward thinking a little bit, I'll give all these buttons a class. That class will be called
option, so that later I can say let's wait for when you click
on something that has a class of option, but we'll deal with that later. Button class equals option. And in order to plug in some value
in JavaScript into a format string, you use a dollar sign
and then curly braces. So going to plug in the value
of option and then we'll say slash button to end the button. So here's what I've done. I've taken all of the options
in that space in the HTML page. I'm going to update
the HTML out in order to add this button, a button whose class
is option, which doesn't do anything now but we can make do something later,
plugging in the option as the value that button, and then
that's it for the button. Let's go ahead and refresh this page. And all right, this is
starting to look pretty good. It asks the question, what
is Athena's favorite animal. It's giving me buttons for each
of the three possible answers. Now, of course, there are ways that
I could style this if I wanted to in order to make it a little bit nicer. I'll go into my CSS file and say, all
right, let's center it, take the body the page, text align center it in
order to match what I had before. This is a serif font. Maybe you'd like to use
sans serif for this quiz, just because I think it'll
look a little nicer for this. So I can say font family sans serif,
just to make it a sans serif font. And then I'd like these buttons
to be a little spaced out. I'd like them to be a
little bigger, for instance. I'd maybe like to
change the color of it. So let's take all these buttons. Let's give them a font size,
font size of 18 pixels maybe. I'd like there to be some padding
on the inside of the button, so that the button shows
up as a little bit bigger. We'll give each button 15
pixels' width worth of padding, though feel free to
mess with this as you like for whatever you think looks best. And I'd also like space
between the buttons. Right now all the buttons
are right next to each other. So I'd like at least a little bit
of space between all the buttons, so I'll give them all
a margin of 10 pixels. Remember, margin is on
this side of the border. It's space between different elements. And then I'm going to give
it a background color. And I'm just going to give it
a grayish background color, and I know that the color for
that happens to be E7E7E7, so I'm going to go with that. And if I go ahead and refresh
this page now, all right, great. This is starting to really look
like that quiz application. I've centered things,
made it sans serif, added some space around the buttons,
changed the color of the buttons. We've got a question,
we've got possible answers. Of course, not all of this
is quite working just yet. The buttons don't actually
do anything, and I'd like to make the buttons
actually do something. So all right, how do I do that? How do I make the buttons do something? Yeah? AUDIENCE: Is there like, on click? BRIAN YU: Yeah, on click. And I want to apply the
on click to what exactly? To each of the buttons. And so how am I going to
get all of the buttons? Any thoughts on how I can get all the
buttons so I can apply something to it? Yeah? AUDIENCE: Document dot
query selector dot options? BRIAN YU: OK, query
selector dot option, this will get me a thing that has
a class a name of option, which is great because this
button has a class name of option. What could go wrong here? This is a good start. Yeah? AUDIENCE: It only takes the first one. BRIAN YU: Yeah, query selector,
recall, only gets me one thing. It's only going to get me the first
thing that has the class of option, but I want all of them. So what I might do is document
dot query selector all to say, get me all of the possible options. And for each of them I would like
to do something with that option. Again, I'm using the arrow syntax
here where the option is the input. This is the option that I
want to do something with and here is the function. And what do I want to do with this? We'll say, option dot on click,
we're going to run some function. And for now, let me just say,
alert you clicked something. Just say, all right, you
clicked on an option, let's just make sure this code works. I'm trying to say, for each of these
options, when you click on them, something should happen and let's
make sure something happens. So refresh. If I click on a button, great. I get an alert. It says, you clicked on something. Let's try another button. I click on it, great. It says, you clicked on something. But now what I really care about
is what is it that I clicked on. And in order to do that,
if you have a button-- and you'd only know this by playing
around a JavaScript little bit more. But there is a property called
text content that refers to what does the button actually say. So if I say, option dot text
content, now let's play this game. What is Athena's favorite animal? If I click on otters, I get an
alert and that alert says otters. That is the button that I clicked on. Questions about what we've done so far? So this is the part where we're
actually going to set you free. Your project is to complete
working on this quiz application. I'll post the distribution
code that we just worked on together in
just a moment, in case you want to use that as a starting point. But here are the things to think about. We've gotten to the point where
when you click on a button, we know what button you've clicked on. So if the answer is guessed
and the answer is correct, you should increment the
score and ideally display that as such on the page. And when you answer a question, we
should move on to the next question. As soon as the answer is guessed,
whether it's right or wrong, you should update the score and then
show us what the next question is. And then once all the
questions are done, we should ideally show
a game over screen that might just say, quiz
complete, for instance, and also shows you your final score. You got two out of three
questions correct or whatnot. Questions about what the project is? We'll have about an
hour to work on this. We'll go until about 12:30, at
which point we'll break for lunch and reconvene back here at 2:00
PM for more look at JavaScript, more look at animation
in particular and how to create animations
using CSS in JavaScript to make our pages even more interactive. But this is going to be the goal for
the morning project, at least for now. Questions about anything? Yeah? AUDIENCE: Will you go back to the post? BRIAN YU: I will post
the distribution code on the website in just
a couple of minutes as soon as we break out into groups. All right. In that case, why don't I have
this group on the right-hand side go to room 136, and if I could have
the front half of the middle group go to room 212 and everyone
else will stay here. And we'll work until 12:30 and we'll
reconvene back here at 2:00 PM.