[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.