[MUSIC PLAYING] DAVID J. MALAN: All right. This is CS50 and this is lecture 11,
so the end is actually quite near. And among the goals for today, and
next time, and our final lecture time together, is to start to tie things
together as far back as week zero. And in that spirit, I thought we would
begin by reflecting on this clip here, which you may recall
from a few weeks ago, wherein we tried to look in
popular media at the perception that viewers might have of
technology, if they relied only on shows like this, and on CSI, and the
like, where what you see on the screen isn't really technically accurate. And this is wonderful to say, but
most recently did Stranger Things 2 come out, which most of you are
probably familiar, and probably finished, if you're like me, on
Saturday after it came out on Friday. And on the screen-- let me say this, not a spoiler-- but I was so proud of
this particular show. But before we get there,
allow us to tease you with CS50's own take on that same show. If we could dim the lights. [STRANGER THINGS THEME PLAYING] OK, so that was mostly just
a set up for the following, and if you haven't seen Stranger
Things, or at least all of the episodes, I really don't want to
alienate the entire internet, let alone everyone in this room,
just close your eyes briefly, this isn't really a spoiler, it's all
technical, doesn't spoil any plot, but no one is going to
care in a few weeks time, so we thought we'd reveal this. So now's the time to put
your fingers in your ears and close your eyes if you don't want
to know that, at some point in the show, there's this scene, here. And of course, in every show
out there like CSI and Law and Order and the like, if you kind
of zoom in and enhance the screen, it's just nonsense, like a crayon
type program, like we saw from CSI. But I was so proud to see that, if you
actually zoom in on this screen here, you see this code, in a
language called Visual Basic. And even though we don't
teach Visual Basic, nor do many people use
Visual Basic as much anymore, can you glean what this programmer
was doing on the screen? What seems to be going on? AUDIENCE: Is it like getting a
four digit password or cracking-- DAVID J. MALAN: Yeah, it
was a program with which to crack a four digit password. And if you glean all of the
various loops in this structure, you'll actually see that it's trying
to come up with a digit after digit after digit after digit,
trying all of them, until finally, when it finds that
value, something interesting happens. And so now, those of you who have
your eyes closed and can hear this, you can take your fingers out
of your ears and we'll proceed. But perhaps the first example
in media of an actual program that works on the screen. So now, today, we look
back on a model we've been introducing for some time, MVC,
model, view, controller, which is just a fancy way of describing a
type of programming that's really popular in the web these days,
whereby you have a controller, which is the code that you've
been writing, in Pset 6, and now Pset 7, in application.pi. The fact that it's called application.pi
is just a convention in flask, but that's where all of your logic goes. Like the code that actually
drives your website. In what folder or files
are your so-called views? Say again? AUDIENCE: HTML? DAVID J. MALAN: Yeah, the HTML file. So in the templates subdirectory,
which is a flask thing also, you have a bunch of
HTML files, which are the views, the aesthetics, or the
presentation of your program's information. And then last week, did we introduce,
finally, the model, the M in MVC, which represents your
data, your database. Maybe it's a CSV file, maybe it's
in API, for getting stock quotes, maybe it is a persistent database,
wherein you store your users and stock portfolios and more. And together, these
three entities compose a pretty interesting application,
whether it is a Pset 6 or Pset 7 or beyond. But today, what we'll do is introduce
one more piece and one more language. I know we've discovered quite
a few languages thus far, Scratch, and C, and Python, and
SQL, not to mention HTML and CSS. But today, we introduce the last of
our languages in CS50, JavaScript. And you'll see that JavaScript is the
last of the enabling technologies that will allow you to build features
and tools very familiar to you nowadays on your phones
and on your laptops. And so, before we do that,
let me go ahead and pull up one example, via which
we can bridge last week and this, a final look at the
Frosh IMs website from yesteryear. And let me go ahead and run
this program as follows. Flask: run. This is Fosh IMs 4, available
in today's distribution code. And if I go ahead and open up this
URL, it's a very simple program, that I'll zoom in on, that
allows the users the ability to register and to see who is
registered and to register themselves. And if I want to go
ahead here and register, I'm going to see a form like this,
and I can choose from the dropdown my Harvard dormitory, and then
actually register my name. And then in very first version of this,
weeks ago, this program did nothing. We just threw the information away. Then we did something a
little more interesting, whereby we saved the data
to someone's email inbox, by just sending them an email, then
we added CSV files, which weren't bad, but what are downsides of
using just CSV text files? AUDIENCE: They take a
long time to search. DAVID J. MALAN: Yeah, they could
take a long time to search, because, especially as they grow
longer and longer, the best you can do is linear. You have to search the whole
file just to find one value because there's no data
structure there, it really is just like an array of lines,
if you will, a list of text that you have to search over. So we also don't have features
like select and insert and delete, these verbs, or operators, that
we actually got from a database last week, which allows us to do more
work, more easily, without having to write as much code. We can literally just
execute a SQL command, like select or insert or
delete, update or the like. So, how might we go about
building a piece like this? Well, recall, that if we go into
the source code for Frosh IMs 4, we'd have some entry
point, like application.pi, and a few different routes. And this might be familiar if you've
dived already into CS50 finance, the first of these routes, up top
though, just renders index.HTML, and that's where I see the menu. And odds are, an index.HTML
is just that bulleted list of three options, each of which
links to a different route. Then the routes do start to
get a little more interesting. And on the screen here,
on line 13 downward, is the logic, my controller
code, so to speak, that allows me to insert
a user into my database. And how do I do this? Well, on lines 15 and
16, I ask the question. If the requests method that's
just come in is get, what do I do? In English? Put up the register template. So show the user
register.HTML, using the using the render template
function, which we've used before to spit out HTML files. Else, if the user has
used post, that is, he or she has clicked a button,
presumably, and posted to this same end point, let's just
distinguish the behavior. If they've submitted a form via post, then go ahead and
execute these five lines here. And this line here, 18, if not request,
or if not request of name and dorm, that was just a way of saying if the
user forgot to give us his or her dorm or name, then render a failure
message, such as that and failure.HTML. Otherwise, if he or she did
give us the information, we can use CS50's execute method on this
DV variable, which we declared up here, we can insert into the registrants a
name and dorm's, specifically these two values, and then recall that
this colon syntax was new. It's just a convention,
in a lot of the SQL world, when you want to plug-in
values, rather than use PercentS, back from our
C days, rather than use curly braces from our Python F
string days, you instead just pass on two values via
these names like name and dorm. And then what happens here, exactly? If I go into this web
site, and I register David from St. Matthews, and click
register, because the application is running with flask, I'm
told that I'm registered. And how can I prove as much? Well, let me go ahead and
open up another terminal and go into today's source code
Frosh IMs 4, and then if I type LS, notice that this is what
composes this application. One of these files is Frosh IMs.db, and
if I go ahead and run this command line tool, SQL light, 3 on
[? Frosh IMs ?] db. I just got a command line interface. And you might not be comfortable
with this approach, and that's fine, but it allows you to do very simple
things like show me my schema. And I can see, from this textual
interface, what the format is of that database, it's just got
one table, called registrants, and then if I wanted to
see who is registered, maybe besides me, what can I type
in this command line interface? What can I type here? Yeah? AUDIENCE: Select star from registrants. DAVID J. MALAN: Yeah, select
star from registrants, semi-colon, and I see
a very text-based table showing me who is in the database. And thus far, it's just me. And I could tinker with
this at the command line, I could update and delete, and so forth,
but the key takeaway from last time, was that once you're a little
bit comfortable with SQL, you can begin to use
statements in SQL, put them between double quotes in Python,
and have Python execute those SQL queries for you on your database. And meanwhile, let's glimpse
at one other feature here. Before I registered a moment
ago, I had this dropdown menu. And I could have hardcoded this,
and that would certainly be fine. But if I wanted to actually
delete a user and, actually, let me show you this here. If I go into, what files is that,
that's in my templates directory. And so if I go to
register.HTML, here, I hardcoded all of those dormitories that
are available to Harvard students to register from. But what about my unregister page? Let me actually go back
and click unregister, and you'll actually see here,
I see kind of a prettier menu that's got the person's name and their
dorm, if he or she is registered. And I somehow want to
unregister the user. Well, if I go ahead and submit
this form, what value might I want the browser to submit
from the browser to the server? David? Matthews? David from Matthews? Something else? What should your instincts be for
when you submit something from a form to a server, when you
want to act on that data, like here, like unregistering the user? What do you think? AUDIENCE: ID number? DAVID J. MALAN: Yeah,
maybe their ID number. So, why? I have this string, David
from Matthews, why not just submit the string, David from
Matthews, look for it in my database and then delete David from Matthews? AUDIENCE: There could be
other Davids in Matthews. DAVID J. MALAN: Yeah, there's
ambiguity, potentially. If there's a couple or
more Davids from Matthews, coincdentally, you might end
up unregistering all of them, or both of them, or
however many they have. And so you want something
primary to identify users. And primary is an allusion to primary
keys, which we said last time, is generally a number, such as the
number one, which we saw a moment ago. When I looked at the contents of
this database just a moment ago, notice that David did indeed have
the unique ID, one, or at least we would see that it's
unique if we keep adding more and more users to the database. And so how did I go
about generating this? Well, if I go to
unregister.HTML, notice that I do have to use a bit
of one other language, it's not a particularly
fancy language, but it's called Jinja, the templating language. And notice what I did here. This is the form, unregister.HTML,
that the user sees when I'm trying to unregister someone. I have a form whose action is
unregister, the method here is post, and then I have the select menu. Select Name equals
quote/unquote ID, because I want to make clear to the server
that the value it's going to receive is called ID, and it's going to be
a number, like one or two or three. And then this is how,
now, I iterate over what? What am I doing in line 6 and 8 and 9? What's going on there in
kind of English terms? AUDIENCE: Number of
registrants in your SQL. DAVID J. MALAN: Yeah, I'm iterating
over the number of registrants I have in my SQL database. Well, it looks like,
and I'm just inferring, it looks like I have access
to some registrants variable, more on that in just a moment,
for registering in registrants, the syntax we've seen
before in Python that just lets you iterate over things in a list. And even though this is technically
Jinja, it uses some similar syntax. And what do I want to do on
each iteration of 4 loop, as I iterate over David
and Maria and Brian and Rob and whoever else is registered for
Frosh IMs For each of those students, I want to output open bracket
option value equals quote/unquote, and this is a bit of a
mouthful, but this just says, output the current
registrant's ID number, and the double curly braces is Jinja's
way of saying, take that actual value and plug it in between those quotes. Meanwhile, recall that an
option in a dropdown menu has two parts, its value
and then the thing that's between its open tag and its closed tag. So what I want the user to see here
is quote/unquote registrant.name from, literally, regristrant.dorm. And that was just a design decision. And it's that reason, for that
reason, that the format of this list is exactly that. So and so from such and such a place. And so the key insight via
which you can make that happen in application.pi, realize, is this. When I visit "/unregister" via "get,"
which is the default if you just visit the URL, notice that
I'm executing a SELECT, just like you proposed a bit ago,
SELECT star FROM registrants. But this time, rather than
just seeing it on the screen, I want to do something with it. So I take these rows that are
returned from the execute method and I just pass them
in to this template. And I could call it anything I want. I could have called it
rows or x or y or z. But I called it, a
little more conceptually, registrants equals those rows. So I'm essentially handing to the
template every row from that database table. And in this way in Pset
7, if you haven't already, can you begin to construct
the most dynamic of databases and the most dynamic of websites,
taking input from the user, saving it, as we did when I registered,
even deleting it or updating it by programmatically generating content. And this is the difference
between a static website, where if you look at it,
every day it looks the same. Because someone literally typed it
out, hard coded, and saved it forever versus a dynamic website, like
Gmail and Facebook and the like, that are obviously continually
changing with more and more content. And so underneath the hood of
Facebook and Gmail and other apps are databases like something
SQL based, using languages like Python and/or JavaScript and more. And so we'll begin to see
what other features we can now add to these kinds of websites. But any questions at this point on that
sort of model for creating a web based application? Anything at all? Yeah. AUDIENCE: How again does a
program know whether a request was submitted via get or post? DAVID J. MALAN: Good question. How does the program, application.pi,
know whether a request came in via get or post? Where is that information
stored or available? Does someone recall? I keep forgetting to bring
one more of these props. But recall that virtual
envelope, oh, here's one more, so recall that when a
browser sends a request, we sort of played along
by saying, oh, well, it puts a request inside of this
envelope like get me the home page. Or here is a photo or here is my
name that I'm uploading to the site. There is literally a
message in here, an HTTP message that says the word "get" or
"post," literally as its first line. And so the moment the server sees that
message inside the so-called envelope does it know if it was get or post. And realize, this is just me
being a little sort of tidy. There is no reason that we couldn't
define two routes like this. We could, in Flask,
have one route called register_form whose sole purpose in life
is to show the user the register form. So literally, the only thing it would
do, is let's see, def register_form, and it could literally return
render_template("register.html") Right? It can just blindly assume that
if the user visits register form, he or she got there by
via get, the default. And then, we could have
that user submit elsewhere if the route is actually register. The method for which, because
you have to explicitly say post if it's not the default for you. And then I say def actually_register. Here, I could now have
all of my database code that assumes that only if the
user has hit this endpoint has he or she submitted the form. And then I put all of my
database related code there. I point out that I'm just kind of
being a little tidy or a little anal when it comes to designing this. Because I just don't
like the idea of having like this end point and this thing. It's just two separate
things to think about. And also what the user sees is
not pretty, as pretty of a URL. It's not just /register, which
makes a little more sense. And so intuitively, this way, can
we have the user stay constantly at /register. But the website behaves
a little differently. If the request comes in by a GET,
show the user something, else, if he or she has submitted a form,
go ahead and do the database thing. So that's all. It's just me kind of compacting
two separate routes into one just to keep things tighter. Good question. Other questions? All right, so let's now transition to
a new world altogether of JavaScript. And even though it might
feel a little overwhelming, to date, that we've looked at
yet another language already, realize that the important takeaways
today are actually relatively few. We're going to see some familiar syntax. But there's a lot of shared features
like functions and loops and conditions and variables. All of those are present
in the same language. And syntactically, it's very,
very similar to C and Python. So that's one takeaway. And two, it's going to
allow us to explore really a different type of programming. Because consider what
we've done thus far. When we wrote programs in C, we
just started writing like #include. And then we had int main and so forth. And we just wrote our
programs top to bottom. We compiled them. And then we ran them. And they executed, essentially,
top to bottom, so to speak. We started doing that in Python, too. In Pset six, you might recall the
compare program or the score program. Those, too, you just wrote
Python code, top to bottom, and then executed those programs. But then we started doing something
a little different with Flask. In Flask, application.pi, when you
run it indirectly by typing flask run, does it ever quit? No, I mean, you see some
funky output on the screen, like some IP addresses and all of
the requests that are coming in. But essentially you see a
prompt that never goes away. Because essentially, built into
Flask, like any web server, is really an infinite loop. It's not a bug. It's a feature whereby
the program, once running, is just constantly
listening for HTTP requests. And any time your application.pi
gets an HTTP request, how does it know what to do with it? There is no main function. So if it's just sitting there waiting
and waiting for requests to come in. How does application.pi
know what to do and when? Like what's been going on all this time? AUDIENCE: By comparing the endpoints. DAVID J. MALAN: Yeah, that's it,
just comparing the endpoints. So inside of this envelope
that I keep grabbing is a request for a certain page. It's get/register or
post/register or the like. So as soon as application.pi
or specifically, Flask, the framework we are building
our application on, notices, oh, I see /register. Let me see if the programmer has
defined a route for /register using our "at" syntax, @app.route. Then, oh, that's the function that he
or she presumably wants me to call, upon getting that specific request. And it satisfies it by
returning some value. But then it goes back to just
listening in this infinite loop. And so this is an example of what we
might call event based programming. You're not just writing a program top
to bottom that just starts and stops. You're writing a program that's just
now always running unless you forcibly kill it by hitting control-c
or restarting the IDE or something dramatic like that. Otherwise, it's just constantly running. But the events that might come
in are a receipt of messages or HTTP requests like these. And similarly, in a
browser, it turns out there are bunches of
different types of events that can happen, not on the internet
per se, but just locally, here. Like, every time I click my trackpad
or mouse, that's an event, click. Every time I touch the
trackpad or move my mouse, that's an event, a drag
event or a mouse move event. Anytime I click somewhere on
the screen or select something from a menu or type in keys to
my keyboard, that is an event. So what we're going to
start to do today is wrap up the last of our user interfaces. The past few weeks, we
focused on the server. Today and next week we'll focus
on the client, the browser. And together then you can
have two pieces of the puzzle finally talking to one another,
listening for user input on the browser and doing something with the
user's input on the server. So let's make that transition. We began with Scratch, of course. We transitioned to C and
then Python and then SQL, which was a little different
syntactically, certainly. But it did allow us to
get data and update data. But today we'll focus
on this JavaScript. What is the relationship, technically,
between JavaScript, today's focus, and the language some of you might have
learned in high school, especially, called Java? Yeah. AUDIENCE: It's like [INAUDIBLE] DAVID J. MALAN: It's like what? AUDIENCE: [INAUDIBLE]
It's totally different. DAVID J. MALAN: Totally
different, exactly. It was really just a marketing thing. Java was very much in vogue at the time. JavaScript was a new language. And hey, why don't we name our
language after something else that's already pretty popular and
kind of ride that wave. But they are not the same language. If you know Java, you know Java. If you know JavaScript,
you know JavaScript. Syntactically, they're similar. But there's no fundamental
linkage between the two languages. JavaScript is a language,
now, that has historically been used in the confines of a browser. Which is to say, your Mac or PC executes
this language in your Mac or PC. However, it can be used
and it's increasingly being used on the server, as
well in something called node.js. But we're going to focus today and here
on out on its use within the browser. So fortunately, it's not all that
different from Python or even C. Here is an excerpt from
a function in JavaScript. What's familiar? Well, we have the keyword
function, which we have in Python. We have some open parentheses,
which we have in Python. We have comma-separated
lists of arguments, which we have in Python
as well as in C. Curly braces, which we have in C, but not
so much in the same way in Python. And so it looks like it's kind of
an amalgam of some of the features we've seen thus far. Indentation doesn't strictly matter. So now you're sort of on your
own again, such that good style means that you have to be indenting
proactively and not waiting for the interpreter to yell at you. But notice this, this is also
legitimate in JavaScript. And what just happened? Before. After. What is this second
version apparently lacking? AUDIENCE: A name. DAVID J. MALAN: A name. And it turns out, in
JavaScript, you can have, and it's a very common thing to have,
anonymous functions, functions that have no name explicitly, otherwise
known fancily as lambda functions. And they, literally, just have no name. Now, why that's useful, we'll soon see. But just realize, that's going to
be a feature that's also present, technically, in Java and can be
implemented in other ways in C. But it's very much a common
paradigm in JavaScript. So getting comfortable just with the
idea of your functions having no name will be a takeaway for today, as well. Variables, you'll notice this. And you can perhaps infer what this
does in English, even if you've never seen JavaScript before right now. What does this probably do? Say again? AUDIENCE: It's defining a variable. DAVID J. MALAN: Yeah, it's
defining a variable called i assigning it equal to 0. And maybe for the first
time it reads nicely. Let i equals 0. That's kind of wonderfully
stated, because that's exactly what you want it to do. What is missing though, from this
line of code that we did have in C? Data types. So there's no mention of int or float
or strings or so forth, explicitly. JavaScript does have types. But it, too, is loosely
typed as is Python. Whereby, there are types, but you
don't have to explicitly mention them. It's very context sensitive. And the computer
essentially figures out what data type is what from its context. But we'll have Boolean
expressions again, such as asking the question is i
less than 50, or more generally, is x less than y, where each
of those might be variables. Here is the do while loop. If you've been missing that in
Python, well, it's back in JavaScript. And we can do something here. And another little thing to
notice, do you capitalize or not capitalize "true" in JavaScript? Apparently you don't,
based on for inference. And so it's these kinds
of little things that, honestly, early on, might trip you up. And it's fine to get frustrated over it. But don't get discouraged fundamentally
by those kinds of nuances. It's just like if you know two romance
languages or two Asian languages and you occasionally confuse
a character or a word. That will happen inevitably,
now, in programming as well. Here is a while loop, an infinite
while loop in JavaScript, as well. Here is a for loop. Notice that it's almost identical
to what we've seen in C, except the lack of a specific data type. I'm instead just declaring i
implicitly to be an int in this case. And this will get a
little more interesting. We have similar syntax in Python. And it's almost the same in JavaScript. If you want to iterate over
the values of an array, you can literally say let value, where
this can be a variable x or y or z, of a keyword you literally
hardcode in array. It's going to be some array in question. And we'll see, wherein
we have actual arrays. That allows you to iterate
over the values in an array. JavaScript also has something
called an object, though. And Python has these, too. And we've mentioned them a couple times. Like technically, when you
declare the db variable for using CS50's SQL
library, that is an object. It's a variable that is an object type. So we've seen these. But we're going to see them ever
more explicitly in JavaScript, exactly what an object is useful for. Meanwhile, we're going to have
some, thankfully, familiar syntax. And you're going to kind of
revert back to your C days. Because elif is not a thing in
JavaScript. else-if explicitly is. So there's that little nuance. There's a declaration of arrays
which look quite like Python lists. So if you want-- and actually,
let me fix this to be consistent. Var is technically a keyword, too. But it works a little
differently than let. So let's just define this
as let numbers equals square brackets these numbers here. Notice the square brackets
means it's an array. But in JavaScript arrays can be resized. They can grow and they can
shrink, quite like what in Python? AUDIENCE: List. DAVID J. MALAN: List. And quite unlike arrays in C. So again,
there's just kind of these trade-offs. And again, it's fine to Google
these kinds of things like, can you resize arrays in JavaScript,
if you forget these kinds of things. But these are the kinds
of differences, when learning new languages, that
will eventually sink in. So here is an example of what
we'll call an object a.k.a. a dictionary or dict in Python. A dictionary, or more generally,
a hash table has keys and values. And that's it. You can have fancier structure. But at the end of the day, it's
just a bunch of keys and values. Different languages use different
syntax for these, curly braces or colons or equal signs or arrows
or other funky things. But the idea is the same. And in JavaScript, if I
want to declare a quote, like a stock quote to be a data
structure, like a struct in C, with three keys-- name, price, and symbol. I literally enumerate them here
with colons after the names. And then I put the values in quotes,
if they're strings, or no quotes, if they're not strings,
on the right hand side. So in the context of CS50
finance, a web-based application for downloading stock
quotes and more, if you wanted to get a piece of data that
represents Netflix's current stock price, you might get back
from the server something that looks a little bit like this. But technically, and not to throw
too much at us at once, technically, it's probably something in what's
called JSON format, JavaScript Object Notation, JSON format, which just has
some additional quotes around things, as here. But we'll see that actually
in use before long. And besides that, besides that, that's
kind of the essence, syntactically, of JavaScript. We're going to now see it's more
powerful features and its programming paradigms. But if you know C and if you know
Python, you kind of sort of already know at least the basic
syntax of JavaScript. You just now need to know how
and when and where to use it. But syntactically, before we
forge ahead, any questions? No? OK. So let me go ahead and do this. Let me go into the IDE and go ahead
and whip up a little example, here, that I'm going to go
ahead and call dom0.html. And we saw this term
briefly some time ago. But DOM refers to document
object model, which is a fancy way of saying the
tree that represents a web page. A web page, of course, might look,
super simply, like this in HTML. The hierarchy is there because
of the open tags and close tags. The indentation there is just
because of me, the human, wanting to be able to read
it a little more prettily. But this structure here in HTML
could be implemented in memory in any language using this
kind of tree structure. This tree structure is called
the document object model. And it's the right mental model,
the way to think about what a web page is underneath the hood. So why is this useful? Well, it turns out all this time
when we've been writing web pages, for the most part, we've
written HTML or we've written in Python that generates HTML. Or that's what you're in
the midst of doing now. But what if you want to change
a web page after the HTML has been written or sent to the user? You run it writing Python
code, don't have the ability to run Python code on your users'
or your customers' computers. Because it's only used on the server. It sends out HTML and CSS and that's it. You lose control over
the user's experience. Unless, in addition to the HTML and
the CSS that you're sending the user, you also send them some
JavaScript, an additional program written in this new language
that runs, ultimately, on their Mac or PC after
it's left your server. So let's see what this might mean. Let me go ahead and whip up
a little example like this. So dom0.html. We're going to have our usual DOCTYPE
at the top that says, hey, here comes HTML 5. Here's the beginning of my web page. It's good to have a head up here
with a simple title like dom0. The body of this web page is
going to be pretty simple. I'm going to go ahead and define a form
that has a unique ID called demo, just for demonstration purposes. Inside of this form is
going to be an input whose ID is name, so I can access that
too, whose placeholder, which is just the fancy gray text,
is going to be name, and then whose type is going to be text. And then I'm going to give myself
an input type equals submit button. So here I have, once I've saved
that, a pretty simple web page that simply has a very simple HTML form. Let me go ahead and run this. I'm going to go ahead and
do this by simply serving. By right clicking or control clicking
on my workspace and clicking serve, I'm going to see a very simple, ugly
web server whose sole purpose in life is to serve the HTML files I've written. And I'm going to go ahead
and click on dom0.html. So this is the file that I
just whipped up super simply. If I type something in
and hit submit, what's going to happen with the information? Nothing really. I haven't wired it to anything. I didn't have an action or a
method attribute on the form. I haven't finished writing this program. So what do I want to do
here to make this happen? I'm going to go ahead and do this. First, I'm going to go into
the head of my web page and instead of just having a title, I'm
going to introduce a new script tag. And as the name implies,
here comes a script. A script is generally synonymous
with like short program. The programs in a web page
can be written, these days, pretty much only in JavaScript. Back in the day, you
could use other languages, especially in Microsoft browsers. But for the most part, the world only
uses JavaScript in this context now. So inside of the script,
I can start writing code. In particular, I can do something
like this, alert("hello,world"); It turns out, alert is a pretty lame,
but a functional function in JavaScript that's just going to print
out an annoying pop up. So let me go ahead and
save the page, go back to my browser, reload, and there we
go, my very first interactive kind of sort of web page. That, really ugly, does this. It just says, hello, world. And I say ugly because it's
showing my domain name and my port. And that's just kind of lame and messy. But at least I'm conveying
some information to the user. So it would seem that
what a browser is indeed doing when it receives an HTTP
request is it's sending this file. And then when your browser receives
that file, it reads it top to bottom, left to right, and executes or
interprets every line of code. So it doesn't just make things bold
faced and centered and the like. It actually will execute lines
of code inside of script tags. So let's make this, now,
a little more interactive. Instead of just calling alert like that,
let's actually put it in a function. And call it function greet. Here are my curly braces
back in our C days. And here let me go ahead and
just say, hello, world, now. If I go and reload this page, am I
going to see or not see the alert? AUDIENCE: Not see. DAVID J. MALAN: Probably not
see, unless, for whatever reason, the browser runs the greet
function automatically. And it doesn't. It doesn't. There's no equivalent
of main in JavaScript. And it certainly doesn't mean greet. So nothing happens. But it is there. So suppose I want to now
connect these things somehow. What could I actually do? Well in my form, you know what, instead
of submitting to some end point-- like the action shall be to go to
register or something like that-- let me actually say this. On submit go ahead and call
a function called greet; So it's a little messy. And we're going to clean this up. But I've introduced a new HTML attribute
that literally does what it says. On submission of this form, call
this code, execute this code. And that code, defined up above,
is going to greet the user. So let's see. Let me go to this web page. And as always, reload the page
so that you see the latest. Let me go ahead and type
in my name and submit. And there we go, hello, world. And then suddenly the page resets. It actually reloaded itself. So let me actually clean
this up a little bit. After calling greet, I'm
actually going to return false. Because technically, I don't have
anywhere for the users name to go. There is no server. So I want to make sure that I've
disabled the built-in functionality of this browser. So that now, when I type in
my name and click submit, it still works like before. But notice, the web page stays the same. It didn't reload. It didn't take me elsewhere. It just stayed put. So now, I'm using the HTML
form as a local application and not really connecting it
to anything on the server. But this is a little annoying. And you might have wondered
why this does this. Most browsers do this. This eventually will get a little messy. It's kind of compromising a
bit of your privacy in forms. How can I disable this functionality
so that users' names are not remembered in text boxes? Well, if you've never known, we
can simply do autocomplete="off". And you might have seen
this already in Pset 7, or elsewhere on the web,
that's how we do that. And also let me go here
and reload the page. Notice that, how do I
interact with this form? I can't type my name by
default when I visit the page. Why? And that probably wasn't
good for my keyboard. What would you do in this case
to solve this stupid problem? Yeah, like click over here. And this is now an
example, albeit a tiny one, of a good versus a bad
user experience or UX. If the sole purpose of your
web page is for the user to type in his or her name, then why
are you doubling the number of steps so that the user has to click
up here first in order, then, to type his or her name? Why not just automatically
focus on the text box? And indeed, that is an operation in a
browser, to give focus to a form field. So in fact, if I go back to
my code here and I also add autofocus and just as an attribute. It doesn't strictly need a value
in quotes or with an equal sign. Now, if I reload the page with
command r or control r, notice, now, the cursor is blinking. The text box is blue on Mac OS. And it's ready to take
my name right away. So start to think about two
of these little subtleties, not just technically how
they work or how to do them, but also why you would do this. Like my rant the other day
about why a website can't accept phone numbers in different formats. These are the little things that start
to distinguish good code from bad code. And focus has another detail too. So if I hit tab, it's very
common, especially in Mac OS, it's super obvious, where things
become highlighted in blue. So you can tab around a user interface. Especially important for accessibility. So if someone is using a screen reader
because he or she can't actually see the words on the screen,
let alone the interface, using tab and a screen reader can they
actually be told what is on the screen. And that highlighting,
that so-called focus, has very real functional
value, so that they know exactly what will happen if they
start interacting with the website. Will the button get clicked? Will text end up in the box? It depends on what has focus. And only one thing can have focus
at a time, per those blue boxes. All right, so with that said, this
is not all that elegant right now. I'm kind of not
practicing what we've long been preaching about combining
one language inside of another. We started to go down
this road some time ago. I started putting CSS
in my style attributes. And then I put it up here. And then finally, I got it out of
there and put it into a separate file. So we're going to be on that
same trajectory here, too. But let me go ahead now and do things
a little differently as follows. It turns out that just putting code
inside of script tags like this isn't necessarily the best practice. We can instead-- because
it requires doing this. This is the ugliest portion of code. And it might not be obvious now. But bad practice, do not put code
inside of double quotes in HTML. Because you have one language
again inside of the other. It's not obvious what
this page is going to do when you glance at it at first glance. If you're collaborating
with someone, maybe you're the front end user interface designer. You're really good with design and art. And so you're doing the interface. And someone else is actually
writing the code and the logic. Because they like to do more
of the back functionality. You can't both really work as
effectively if all of your work is commingled in the same file. So we want to get this out of there. So how do we take a step toward that? Well let me go ahead
and create a new file. I'll call this dom1.html. And I'll start in the same place. But I'm going to go ahead and do this. I'm going to get rid
of this event handler and stop using that
attribute altogether. And I'm also going to
go ahead and do this. I'm going to get rid of my greet code. I'm going to go ahead and get
rid of the script tag, here. And just for now,
temporarily, I I'm going to actually put the script at the bottom
of the page for reasons we'll soon see. So in the bottom of the page, now,
I could do alert, hello, world. But that, of course, recreates
the same problem as before. I don't want it to just happen always. I want it to happen only
when the form is submitted. So how can I do that if I am trying to
avoid this messiness, this commingling of code and HTML? Well, it turns out that there
is a way to tell the browser to do something when something happens. Specifically, I can do this, document. And document is now going to be
a special global variable that refers to my web page, the
document that I'm writing. document.getElementById,
which is a long function name. It exists in JavaScript. And notice the capitalization
of the E and the B and the I, but not the initial g. This is conventional. In a lot of languages,
you don't capitalize the first letter of
your function but you do capitalize every word thereafter. Something called camel case, where
it's kind of going up and down and up and down. Because it's a little more
readable than all lowercase and certainly all upper case. So what ID do I want to get? I'm going to go ahead
and get the ID, demo. And we'll see what
that means in a moment. And I'm going to register
an event handler as follows. So let's finish this
thought in a moment. Where does demo come from? Where did we see that before? Yeah, a few lines earlier. I just gave my form an arbitrary,
but very unique, ID of demo. I could have called it anything. And I could have done this
actually in different ways, too. But this is just super explicit. So here, even if you've
never seen JavaScript before, you can start to infer this is
saying, hey document, hey web page, get me the element ById("demo"). So somehow or other,
this is a function that's going to go grab from the browser's
memory the square or the rectangle that I drew earlier. The reason that the DOM or document
object model is interesting, theoretically, is that with
document.getElementById, you have the ability to go grab
one of these nodes in the tree or one of these data structures in
memory and do something with it. Now, what are we going to do? Well, we're about to see. When I have access,
now, to this form, it turns out that forms, per the
manual for HTML so to speak, there are different
event handlers on submit, maybe on click, maybe on
mouse move, mouse drag. It depends on the element. But forms can be, of course, submitted. So literally, by saying .onsubmit, I
can now say the equivalent of call this function. This is just pseudocode. I now need to give this a function. And so I can do this
in a couple of ways. I can do it like this. So function greet is a function
that simply does say, hello, world. And now, at this point in the story,
I've defined a function up here and given it a name. And then here I'm saying, on submission
of the demo form, call this function. But notice the difference. It's subtle. I didn't do this, which is the norm. I instead did this. Why, though subtle, is
it probably important that you omit the parentheses? How to think about this? AUDIENCE: Because it doesn't
accept any arguments. DAVID J. MALAN: It doesn't
accept any arguments. That's true, but it's not
the reason for doing this. Good thought, though. Yeah. AUDIENCE: So maybe nobody can change it. DAVID J. MALAN: So no one can
change it, not there, too. I think anyone who has access to the
file can certainly change my code. So it's not that. AUDIENCE: Because you're trying
to send it to the output? DAVID J. MALAN: Closer. I'm trying to send it to the output. Not quite, but I think
we're on the right track. AUDIENCE: So it doesn't
call it right away. DAVID J. MALAN: Yes. So that it doesn't call it right away. Ever since week one of CS50, any
time we have seen a function name followed by open paren, closed paren,
maybe with some arguments inside, that has meant call this function
and maybe pass in these inputs. But that's not what we
want at this line of code. At this line of code, we want the
browser to know which function to call, not to call it right then and there. So we don't want that
function to be called as soon as we get to this line of code. Because otherwise, we're going
to see the alert, no matter what, the moment the browser reads
that line of code on the screen. Instead, we just want to
tell the browser, hey, just so you know in the future,
when the form is submitted, here is the name of the
function only to call. But don't call it now. And so that stupid, simple difference
actually makes all the difference in this case, functionally. And so now let me get rid of this. And leave the program as follows. So now let me go ahead and go back to
the web page, reload, click submit. And we see, hello, world. So the functionality
hasn't really changed. But at least I've made some progress. But I haven't done quite
as much as would be ideal. It would be a lot nicer,
I think, to do two things. One, this is kind of lame. I have defined a function called greet. And then I'm using that
function's name in one place only. That suggests I never really needed
this word greet in the first place. You know, it's fine. It's clear. It's correct. But you know what, I
remember from earlier that JavaScript supports anonymous
functions that don't have names. So how could I do this? Well, it turns out we can just,
in one fell swoop, do this. Let me go ahead and cut and paste that
and get rid of the excess white space now, get rid of the function
name, and now just do this. And just for clarity, let me put
the curly brace on the same line, even though it doesn't strictly matter. But this would be
stylistically more common. What am I doing now? This is now saying, hey
JavaScript, get the element called demo or with an ID of
demo and when it is submitted, call this function. Now, it's a subtle difference, again. Open paren, close paren, here,
does not mean call the function. Because it's immediately followed by
the curly braces, which means here comes the code that should be
executed when this function is called. It ends with a semi-colon not
because functions themselves need to end with semi-colons, but
this is all one long line of code that I've just indented now. Because we're declaring a function
and assigning it from right to left all at once. So a huge mouthful there. But again, none of the ideas
are new except for the fact here that functions can
be anonymous with no name. And you can pass functions
around and call them later. Any questions on this? Yeah. AUDIENCE: So can you remove
functions and instead just put equals alert, hello, world? DAVID J. MALAN: Good question. Can I get rid of the
function and just do this? Short answer, no. Because if I do this, this
is going to, just like in C, call this function, which is
going to display that alert. And then it's going to assign the return
value of that function, which I don't think it has one at all, to onsubmit. So this calls the function,
assigns its return value, which is technically undefined, to this. So nothing will ever happen if
you click submit thereafter. It's going to get called prematurely. So the way to avoid this is,
again, to define a function and then pass it in by its name only. Or declare it anonymously,
so to speak, like this. So that you're really just
telling the browser, on submit, call this chunk of code in
between the curly braces. And that's it. OK. So this is still a stupid demo. Because it keeps saying, hello, world. And yet, I have a form with which
the user can type in their name. So how do I get at that value? Well it's actually pretty
straightforward here, potentially. Let me go ahead and do this. Hello, I want it to say, David, if
I'm the one who types in my name. But of course, I don't
want to hard-code that. I want to somehow get the
user's name and plug it in here. So how can I do that? I can say let name equals document dot-- and just so we see where this is
going, getElementById maybe name. Because I have another ID. Recall, I had the anticipation to
write that line of code earlier. So get the user's name. And then it turns out you'd only know
this by seeing it before, online, or in class, .value will get me the text
that the user has typed in, and then semi-colon. And now here, just like
in C and in Python, I'm not going to want to do this. Because that's literally
going to say, hello, name. I want to plug it in. And I can do this in a couple of ways. Perhaps the most blatant is like this. And those of you who did
take APCS or the like might know what plus means in Java. This is just a coincidence
that it also works here. What does plus sometimes mean
in languages besides addition? AUDIENCE: Concatenation. DAVID J. MALAN: Concatenation. So in C, this would have
been a pain in the neck. Like, in C, this is
where you got to whip out like malloc or some really
big array on the stack and actually like plug
one name into the other. In Python, you can just concatenate
things using pluses as well. Or you can use f-strings
or format strings. In JavaScript, we can
just do pluses like this. And this will concatenate "hello,"
to the word name and print that out. So let's actually see what happens. If I didn't make any mistakes, when I
reload this page and type in my name and click submit, hmm,
what did I do wrong? What's that? I forgot to refresh it. I also forgot to change the
URL, which I just now realized. So now we're in demo1.html. So let's reload now, David, submit. And there we have David. And just for good measure, let's
go ahead and type in Maria, submit. And it does seem to be
changing dynamically. So that's a nice improvement
in that it's now doing that. Do we strictly need this variable? No, but if we have this variable,
notice we can do this, too. Just so you've seen this, in
JavaScript, for better for worse, now we have things called backticks,
which is the key on a US keyboard that's usually on the top
left just below escape. And if I have back
ticks here, guess what? You can do this, which is
uglier than Python's f-strings, but does the exact same thing. And again, this is the
kind of stuff where you can start to roll your
eyes as aspiring programmers. Where if one language does something
slightly different and you just have to constantly remember,
it's the same idea. It's the exact same idea. It's just different syntax. So this would plug-in the
name into those backticks. And this is called a template
literal in JavaScript. All right. Any questions on that thus far? All right, let me introduce one
final teaser, here, as follows. Let me go ahead and go into
our distribution code for today and open up, let's say, in
source 11, this directory here. And in a moment we'll see
all of the files in here and show a couple of examples here. So one, it's very common, of
course, to have web-based forms where the user may or
may not actually give you what you want him or her to type in. And so it's nice to
validate their input, like we've been doing on the server. But if you validate the
user's input and make sure that they've given you an email and a
password and a password that's the same and checked your terms and
conditions check box and so forth, you can do all of that in Python. And we've seen how to do
that in application.pi. But it's a better user
experience, UX, if you actually give the user more immediate
feedback, maybe prettier feedback, by using some colors and
highlighting on the screen to draw their attention
to what's actually wrong. With JavaScript, we
have that capability. Moreover, in JavaScript, we have the
capability to do something like this. So if I now run the web server
in today's distribution code and open up this URL, I'm
going to see a listing again. But I'm going to go ahead now
and pull up say ajax1.html. And here, I have a very
simple web form, not unlike, in spirit, what you
have in CS50 finance. But if I want to see what the
stock price is of Netflix, I can type that get quote and I can
actually get it in the client alone. I don't need to send
them to another route. I don't need to use Python, it
seems, to actually render a template. I can just interact with the
form directly and do this. And then lastly, just a tease, we
can do something like this whereby, if I actually con-- damn it-- if I actually
configure things correctly, we can actually get ourselves a
full fledged map using JavaScript. So that in the end, we can
use JavaScript and start to make interactive
applications, like this one here, using Google Maps' API so that
the user can click and drag and can actually interact with it. As by clicking on say,
Stanford, California, and seeing what's going on in the news
in Stanford, California right now by, again, writing code that executes in
the browser, talks to some other server, gets the data back, and renders it. So we've just begun by
introducing JavaScript to see the syntax with which we can do this. Let's take our 5 minute
break here and then actually start building some of these
things to see how they interact. All right. All right, we're back. And recall that the form that we created
a moment ago just looks like this. It's pretty simple, ugly HTML. There's no CSS. We're focusing only
on functionality here. I did, at least, give
autofocus to the email field, so I could start logging in right away. But I want to achieve this behavior. You know what, I don't
really want to cooperate. I just want to register
and see what happens. I want to validate this form. So here's one way. I seem to be using the alert
method and saying missing email. I'm not letting the
user actually register. OK, so let me slightly cooperate,
malan@harvard.edu, register. Missing password, it now says. All right, so let me go
ahead and give it a password. One, two, three, four, five, register. Passwords don't match. Of course they don't. Because I didn't type it in. One, two, three, four, five, register. Passwords still don't match
because I accidentally typed six. Register, check box
unchecked, and so forth. And only once I check that
box and now click register do I actually want the form to
go through to the server. So how do we start to
impose that kind of logic? We could do what you're doing or
have done in CS50 Finance, whereby you check on the server and make
sure that the user has given you email, password,
confirmation, and a check box. And if not, you show
them grumpy cat and you complain that they haven't cooperated. And that's all cute
the first time around, but it's not the best user experience. Because now the user has
to click the back button and they have to refill out
the form and then do it again. It would be nice to just
get more immediate feedback like we're getting here. And not necessarily as
ugly as this feedback, because this alert is really just for
debugging purposes, I would argue. But at least it's quick. And it's not even bothering
talking to the server. So here is the HTML with which
we might create that form. For the most part,
this is cookie cutter, whereby I'm disabling autocomplete on,
I was overzealous with my autocomplete. It's not strictly
necessary for passwords. Because browsers won't
do that by default. So really, I just want it to look
like this, which is even smaller. So I have a field called
email of type text. I have another field called
password of type password. I have another field called
confirmation also of type password. And then I have an input of
type check box called agreement followed by the submit button. So that's it. So how do I begin implementing
some of the logic we just saw? Well, let me do this. Down here in the script
tag, eventually we're going to factor this
out to another file, but for here, I'm going to do this. I'm going to go ahead and declare
a variable called form and go ahead and get via
document.getElementById("registration"). Why that? Well, notice that I gave a
unique ID to my registration form just because I want to be able
to easily get at it, as here. Then, I know that forms have submission
handlers, so I can go ahead and say, hey browser, on submission of
this form, go ahead and call the following function,
albeit an anonymous function. So all that remains for me to do is
to implement this anonymous function. What do I want to do when the
user clicks the submit button? I want to validate
their input in some way. So let me go ahead and
do it sort of logically. If this form's email field
has a value from the user that just equals quote/unquote,
then let me go ahead and alert the user that you
are missing email, semi-colon, and I'm going to return false. Because that's it. I'm not going to return true. Return true would mean, let
the user submit the form. Return false means, stop
submitting the form. Let the user try again. And so let's do this now for passwords. So how about else if the form's password
field has a value that also equals quote unquote, then go
ahead and alert the user missing an s, missing password,
semi-colon, and also return false. Next one is a little more interesting. Because now I can say else
if form.password.value. What do I want to say logically here? AUDIENCE: Dot length. DAVID J. MALAN: Dot
length, I could do that. So that's not a track I
currently have in the UI we saw. AUDIENCE: Can you find
some sort of confirmation? DAVID J. MALAN: The confirmation, yes. So it turns out the syntax
is the same as in C, not equals form.confirmation.value. Then, I want to go ahead
and say, I think I said, password, what did I say,
passwords don't match, semi-colon, return false as well. And then the check box
is a little different. I can say else if it is not the case
that the form agreement box is checked. And that's a Boolean that's
associated with a check box. And you would only know this from
the documentation for JavaScript. But the not inverts it. So if it's not checked, then
go ahead and alert the user that the check box is
unchecked and return false. But if none of those
conditions apply and we make it through this gauntlet
of error checks, what do I probably want to do down here? What do I want to return? AUDIENCE: Return true. DAVID J. MALAN: Yeah, return true. And that just means, hey browser,
do what you want to do by default. I'm done error checking the user. So there's some opportunities
for refinement here. I could say, I don't really need to
compare against the empty string. I could say, if there's not a
value, which is a little tighter. And I can say, if
there's not a password, so I could clean it up that way. I could actually use the string
length, which is a thing, too. So I could say something, if I
really wanted to be nit picky, else if the form's password
value.length is less than 8 characters, I can say something like
alert, password too short, which would be a nice check,
as well, and return false. If I really want to be secure, I can
make sure the user has a pretty random looking password, maybe with some
numbers or some special characters or some of those somewhat annoying,
but probably good, constraints, at least if you're using
a password manager. And this is how websites
do exactly that. But there's still an opportunity for
improvement here in a couple of ways. This code is, again,
commingled with my HTML. But this is actually an easy fix. Let me go ahead and copy all of this
code or highlight all of this code that we just wrote, cut
it out, and indeed I'm going to get rid of the
script tag altogether. And instead in the head as my
web page, where previously we've only ever put titles and maybe
some style or length tags for CSS, I'm going to go ahead and say
script tag the source of which will be form1.js for JavaScript. And even though this
looks a little weird, this is indeed the right way to do it. It's an open tag and a close tag. It is not valid, for
silly reasons, to do this. So even though this kind of makes
no sense, do this nonetheless. That's the way the world is. So let me create another file,
paste that very code I just wrote. Let me go ahead and unindent
it just to keep things cleaner. Actually, it's not
quite indented properly. Now let's do this once more. Let me save this as, what
did I say, form1.js, save. And now I have a better version of this. And what is the browser going to do? Well, just like when we've used
images in our web pages before, like the cat, by referencing an
image source equals quote unquote, so do we have a script source
equals quote unquote something here. So now when a user visits
this page, form1.html, the browser is going to read it
top to bottom, left to right. It's not going to see
any actual JavaScript. So nothing's going to
execute right away. But it is going to see this other file. And it's going to
recursively, if you will, download that file so that the web page
has access to all of the code therein. So that would be one refinement. And now we're back to what, I
would argue, is a better design. But there is another way to do this. And let me open up a
premade version of this. It turns out that some things in
JavaScript can be pretty tedious. Because the language, early
on, was pretty immature. And people were trying to get it
to do things that just weren't very easy to do in the language. And so popular libraries arose,
as was the case in Python as well. And here we have an
example called form2.html that actually uses a
library that, for some time, was one of the largest and
most popular called jQuery. JQuery is not a language unto itself. It's literally just code
that a bunch of nice people wrote to make it easier to use
JavaScript for certain things. The price we pay for that ease of
use is that some things are actually a little more syntactically
weird looking. And so we won't dwell too
much on the syntax of jQuery. But jQuery is the library for
JavaScript that Bootstrap uses. And you might recall Bootstrap
from the past couple of weeks. Anytime we've made prettier websites
than I'm typically capable of, when they have nice forms and
everything is nicely color coded and they resize nicely,
that's because we're using the Bootstrap
CSS library that also comes with some JavaScript
interactive features that require that you have jQuery
linked in your web page, as well. So that's why we'll use it here,
as well as to see the following. Here, now, is another implementation
of the same program in between script tags, for now, inside of my head. But I've done a couple
of different things. This line of code is perhaps the
weirdest looking at first glance, in part, because of this dollar sign. And we saw a dollar sign a moment
ago inside of those strings with the backticks. This one means something different. As soon as I import this file, which
is the latest version of jQuery, so it's hosted elsewhere,
not on my own IDE, it turns out that gives you access
to a global variable called jQuery, spelled like that. Back in the day though,
the people who wrote jQuery decided that that's a little tedious
if every time the users in the world want to use our library, they have to
type out this kind of long word jQuery. So it turns out they just created
an alias for it called dollar sign. And weirdly, in JavaScript dollar
sign and a few other punctuation symbols are actually legitimate
characters to use in variable names. This is not true in C.
This is not true in Python. But it is true in JavaScript, that even
though this looks funky to all of us, at least relative to the letters of
the alphabet, it's a valid symbol. It could have been fu or bar or x or y. So jQuery just kind of got there
first and claimed for the world, we shall use dollar sign for
all of our functionality. That's all it means. So what does this
functionality do for us? This is a mouthful. But let's see if we can
parse what's going on. Document is what, in your
own words, anyone's words? Yeah. AUDIENCE: The web page. DAVID J. MALAN: The web page. It is a global variable referring to
the very web page we're looking at. That's the so-called document. This syntax here, dollar
sign open paren, close paren, is the way in jQuery to
wrap, literally, the document with some additional functionality. So the browser gives you this
global variable document. And it's got some functionality
built in, like getElementById. And there's other stuff too. But we won't look in detail at it. This dollar sign open paren close paren
around it, takes that global variable and stuffs even more
functionality into it just to make it even easier
for us humans to use. One of the pieces of functionality it
gives us is this function called ready. And ready, a little unusually,
but similar to what we just saw, takes an argument as its input. And that argument is a function. The function that should be
called when the document is ready. That's it. Because web pages can
be pretty big, right? You go to cnn.com or Google
News or Facebook or Gmail, it kind of takes some number of
milliseconds or sometimes even seconds for the whole page to
load until you finally see the entirety of the web page. That means the web page is ready,
once you see everything on it. So the way you can say,
programmatically, hey browser, only execute the following code
when the document is ready, is with the line of code like this. And it's fine if you have to copy-paste
that for now until it sinks in. But that's all it's saying. Add some functionality to the
document, like this ability to wait until the web page is ready. And then when it is ready, call
this anonymous function i.e. this chunk of code. So what's happening below that? Well, it turns out, there's
just alternative syntax in jQuery for doing the
same thing we just did. Though cryptic looking, this
dollar sign with the parentheses takes an argument here that's
different from document. If you pass in a string,
that kind of looks like CSS, recall that we've used
CSS selectors before, where you can either have a tagged
name in your CSS file or hashtag something, which is the ID,
the unique ID, in a file. Or dot, which meant
a CSS class, vaguely. So look back at some of your CSS
examples if you don't quite recall. But in CSS, those are selectors. And this one just means, grab the dom
node whose unique ID is registration. jQuery syntax for that
same expression is this. So this line of code is
essentially equivalent to
document.getElementById("registration") And the reason that jQuery exists
is that they say in about half as many characters what it just took me
twice as many characters to type out. That's all. It's not a new idea. It's just more succinct,
if more cryptic. And moreover, if we keep going,
in raw JavaScript, it's onsubmit. In jQuery, it's .submit. Just because, why do we need
those two extra characters? We don't really. So that's all we're seeing here. So what actually
happens, now the syntax, admittedly, gets a little funkier. So we won't spend too much time here. But if you did not have the foresight
or for whatever reason did not want to give unique identifiers to
all of your form fields, that's OK. Because you can use
CSS-like selectors, fancier ones than we've introduced
in the class, that say hey, go look in the web page for the element
whose unique ID is registration. Look inside of it, it's
children or descendants, for an element of type input. And then, only grab the value of
that input if its name is email. So again, we won't dwell on this. Because there are easier,
simpler ways to do this. But with jQuery, you get the
expressiveness that we're seeing here. And all the rest of
the code on the screen simply does the exact same
thing using another syntax. So use this more as a crutch
when experimenting with, say, for the next project or
final project, jQuery, if you want to see analogues
from no jQuery to yes jQuery, but it does nothing
fundamentally different. It's just a different syntax. But there is going to be a more powerful
feature that we now get from jQuery. It turns out that when
you do visit websites like maps.google.com like this. This is not the whole world. At the moment, it figured
out that I'm in Cambridge. And it's showing me just a
little snippet of Cambridge. And Google also, even though
I'm only looking at Cambridge, also did not proactively download
pictures of the rest of the world and store them in my browser's memory. That's be pretty stupid. Because I rarely need to go
very far away from where I am. And even so, if I want
to go to like New Haven, I don't really need all of the
cities and towns between me and New Haven to be in my browser. We can just jump straight there. And you can kind of see
this artifact, as follows. If I click and drag really
quickly, what do you see happening? I should have gone somewhere
where there is land. What do you see happening on
the left, as I do this quickly? AUDIENCE: There is a delay. DAVID J. MALAN: Yeah, there's a delay. You see these gray
tiles, like placeholders, until eventually, they're filled in. Now why is that happening? Well, you know what, I'm going to
go up to my browser's developer menu, developer tools, which should
be a habit you're increasingly getting into when you want to understand
something or solve some problem or just learn out of curiosity. Let me clear this temporarily. But every time I click, whoa. Just clicking and dragging
induced, as of now, 89-- whoops, there there's my screen saver-- 92 more HTTP requests. So what is it that's being requested, do
you think, every time I click and drag? More images, more tiles, as
they're called in Google Maps. And so what is the
feature of browsers that allows them to go get more and
more data like this on demand? This is a technology or
technique called AJAX. AJAX is just a fancy way of
saying a feature in browsers that lets them execute HTTP requests
after the first one is all done. Which is to say, when you first visit
Facebook or Gmail or Google Maps and you get back a response from the
server containing the map of Cambridge, the browser, thanks to AJAX,
which is a more modern technology over recent years, has the ability
to send more of these envelopes out onto the internet saying, I need
the tiles for the northeast corner. Or I need the tiles for
the southwest corner. Send them back to me. So constantly, we're now up
to 651 additional envelopes came back from Google in order
to fill in all of the blanks as I sort of rapidly clicked and
dragged to different locations. And it doesn't have to be
graphical in this nature. We saw stock quote a moment ago. And that's, perhaps, an
even simpler paradigm, if I just want to get some
slightly additional information. So let's do that, let me go
ahead and open up ajax.html. And I see this form here. And now let me go ahead, as should
be, again, increasing habit, go to my network tab. And notice, just for good
measure, also get into the habit of clicking preserve log. So that just in case the web
page redirects or goes elsewhere, it doesn't delete everything
you were looking at. You still see everything. Let me go ahead here and type
NFLX for Netflix and get a quote. And notice, we saw earlier, the
response come back from the server. As of this moment, it's $198.41,
but how do we know that? Let me dismiss the alert
and focus down here. After loading this page, apparently,
it sent one more HTTP request, which was successful. Why? Or how do I know? Yeah, 200 OK. So Chrome is showing me that, too. And you can do this in Edge
and in Firefox and Safari. But frankly, Chrome is sort of the go
to browser these days for development. So I would encourage you
to keep using it for this. If I click on this, I can now see what
the request was and the response was. Here are all those headers. There's some cookies involved,
which are a result of the IDE and not my own code. But it's the response I care about. Let me view the source. And notice, a few things came
back, some of which are familiar, some of which aren't. Among the headers is indeed
200 OK, so that's a good thing. Notice what type of
content came back, though. In the past it's been text/html. But what came back this time? Yeah, application/json. Application is a little weird. It's not an application. It's not a program. But it's a format used by
programs, you can think of it. JSON is JavaScript Object Notation. So probably, what came back is something
with some curly braces and colons and quotes. We'll see in a moment,
47 bytes worth, in fact, and then some other stuff came
back from the server as well. So let me click on response. And what do you know, in
the response from the server is not another web page. There's no HTML tag, body
tag, head tag, or anything. It's just this text, but
in an official format. Open curly brace, close curly brace
means here comes a JavaScript object. What is an object? It's a hash table or a
dictionary with keys and values. What are they? A key is name. Value is Netflix. Price is a key. 198.41 is a value. Symbol is a key. Netflix is a value. And so it's just a way of
getting back one or more pieces of useful information. So how do I now do this and how
do I get the information back? For that, we have to
look at the code itself. So in ajax0.html, we
have this code here. In HTML form, that, just like
our very first example today, just simply hard-coded inside
of an onsubmit attribute, a quote function call,
and then return false. That is, don't reload the page,
don't submit the form for real, just call the quote function. Where is the quote function defined? At the moment, a little lazily,
it's defined in the same file. But that's fine. Because this is our very first. Notice that I have two
things for JavaScript. One, is jQuery, that library I
mentioned earlier, it has to come first. Because just like in C, you
need to know that functions have been loaded before you use them later. Then here comes my own
script, my own JavaScript. And here's my quote function. It doesn't take any arguments. Because we're going to get
those in code from the browser. And the syntax here is a little funky. But we'll distill it in just a moment. Dollar sign is synonymous with what? AUDIENCE: JQuery. DAVID J. MALAN: JQuery. So this is just a prettier or
confusing way of saying this. JQuery.getJSON. GetJSON is a function, or a method,
so to speak, whose purpose in life is to do that, go get me some JSON data. From where should I get it? /quote, which we'll see in a moment, is
a super short route that I implemented in Python on the back end. Though, it could have been
implemented in any language. This looks a little cryptic, so we'll
come back to this in just a moment. So let me delete this temporarily
and just say the following. The getJSON function
that comes with jQuery takes at least two
arguments in this case. One is the URL, to get JSON from. And two is what, would you infer? AUDIENCE: An anonymous function. DAVID J. MALAN: A what? AUDIENCE: An anonymous function. DAVID J. MALAN: An anonymous function. That anonymous function, though,
unlike the ones we've seen before, actually takes input this time. So it doesn't have a name. And that's no big deal. But it does take one argument-- data. And this is an example of
using an anonymous function as what's properly called a callback. Because the internet can be slow. And if I am trying to get
a stock quote from /quote, maybe it comes back super fast. But maybe the server is overloaded. Maybe my internet connection is slow. Maybe I'm on my phone. And so it might take a second or
two seconds to get that response. And imagine if things waited in the
world of the web for data to come back, your experience, your user experience,
your UX could be pretty bad, right? The whole browser might hang or wait or
you get the stupid spinning beach ball while you wait for something to happen. Imagine that in Facebook,
like every time your friend is typing you see the dot, dot, dot. But maybe you can't do anything with
the website until he or she hits enter and you finally get the message. That would be blocking you
from doing real useful-- well, "real useful things" from
using Facebook in other ways. So how can you instead
tell the browser, go get me something more, more
tiles of the map, more messages from my friend, more stock
quotes from a server, but call me back when you have the data
so that I can actually keep doing work? Just like, I might be at my desk here. And actually, Brian, if you
wouldn't mind coming up. And Brian may be here is
in his little home office. And I am really curious as to
what Netflix's stock price is. So let me go ahead and
pull up Brian, here. BRIAN: Hello. DAVID J. MALAN: Hi, Brian? BRIAN: Hi. DAVID J. MALAN: Hi, this is David BRIAN: Hi, how are you doing? DAVID J. MALAN: Hi, I'm
really good, thank you. I need the current stock
price of Netflix, please. BRIAN: The current stock price
of Netflix, I'll work on that. But I'll have to call you back. It'll me a little while. DAVID J. MALAN: OK, thank you. BRIAN: No problem. finance.cs50.net. DAVID J. MALAN: Oh, hello? BRIAN: Hello? Hi. The current share of Netflix cost $198 DAVID J. MALAN: Wait a minute,
I'm getting a call from Colton. BRIAN: OK, and $0.35. DAVID J. MALAN: Hold on I got to
call you back Colton, once sec. Wait, hello? BRIAN: Hi. DAVID J. MALAN: Oh, hi Brian. BRIAN: A share of Netflix costs $198.35 DAVID J. MALAN: OK, thank
you very much, Brian. BRIAN: No problem. DAVID J. MALAN: Goodbye. OK, I just hung up on
Colton on the internet. So thank you. OK, so what was the point of that
unexpected surprise and how weird that he called me right at that moment? So the point is that
callbacks are something we're already familiar with, right,
in the real world where you actually want to get some information
back from someone. And maybe it's not as contrived as
hey, I need a stock quote quickly, get back to me. But you do wait for them to get
back to you with some information. How do you implement this in code? This is the exact same idea. So we have this special
function called getJSON. It's baked into this library called
jQuery, whose nickname is dollar sign. I then say, go get me some data
from /quote or, equivalently, Brian in the real world. And then, I tell getJSON, when you
are ready with this information, call me back, so to speak. How do you call me back? Well, you know what, I'm going to
write in advance some code that I want you to call, literally, but in a
computer sense, when the data is ready. So just as Brian verbally gave me
that stock quote, passing it verbally back over the phone, so
can this anonymous function receive as an argument a
data parameter or argument that I, then, can have access to. So I can use dot notation,
like in C, structures, and get at the name or the price
or the symbol, which were the three values that we saw in that JSON object. But meanwhile, this line
of code executes instantly. And it registers, if you will, a
callback function with getJSON. So it just knows whom to call back. And what this means in real terms
is that if my web page were far more interesting than this and is
Facebook or G-mail with lots and lots of other
features, I can get back to working on and using those features
and then get interrupted if and when the phone actually rings or the
message comes in from my friend or I get a new email or I get,
in this case, a stock quote back. So all that happens super quickly on
a fast internet connection, but not necessarily the case on a slower one. As we started seeing with Google Maps,
trying to get more and more titles. But how can I clean this up? So that was version 0. Let me go ahead and
open up version 1 here. And notice that this time, I'm doing
things a little bit differently. Oh, and actually, let me reveal one
last thing by way of this example here. So what are we actually
doing differently here? So in this case, I'm now attaching-- let
me open up the other one so we can go there and back-- in this first version, recall,
I did the sloppy kind of thing where I commingled my
HTML and my JavaScript. And that's bad design. Don't do that, even though that's
where we started the story. So how can I do this,
programmatically, in code? Well, if this is my form now, and
notice there's no mention of onsubmit. There's no mention of that attribute. I'm doing this entirely in code. How can I do that? Well, I can say, when
the document is ready, go ahead and register this
submit handler, if you will. Event handler would be the generic
term for all of these kinds of things. When that form is submitted,
call getJSON of /quote. Then call this number back, so
to speak, when the data is ready. And I deleted this,
temporarily, earlier. But let's tease apart what this is. It's a little cryptic looking. So let me clean that up as follows. Let me go ahead and say the
following, let my HTTP parameters be this JavaScript object
that has a symbol and whose value is this thing here. And this is a little cryptic, too. But we'll tease this
apart in just a second. So let me now replace
this with HTTP parameters. So what's going on here? I'm just being more verbose,
but it's no more correct. Here is a variable
called HTTP parameters. What type of variable is it? It's an object in JavaScript,
note the nomenclature, because of the curly braces. That's the clue. An object, recall, has keys
and values separated by colons. So here's a key symbol. And here is a value. This is a very funky way of writing it. But this is jQuery's
way of saying this-- document.getElementById("symbol").value. So again, the value, no pun intended,
of using jQuery in contexts like this is just fewer keystrokes. It's more cryptic. You kind of have to remember
the syntax over time. But it's fewer things to type. And that's all it's doing. It's getting the symbol's value
from whatever the user typed in, like an NFLX for Netflix, and then it's
storing it as the value of this key. And then to getJSON, It's
passing in those HTTP parameters to create the URL I expected. And what was the URL I expected,
expected in the sense of me being the programmer? Well, if I hover over
the URL in Chrome's log, I visited /quote question
mark, symbol equals NFLX. So it seems that what getJSON is
doing for me is actually constructing, dynamically, a GET request. Just baking into the URL the
parameters that I want to pass in. And so that example does,
fundamentally, just that in the end. So any questions, then, on AJAX or
any of the syntax with which we're doing this? Yeah? AUDIENCE: Why is the keyword
symbol not between quotes? DAVID J. MALAN: Good question. Why is the word symbol
not between quotes? It could be. This would be perfectly correct, too. It's not strictly necessary when you're
providing it as input, shall we say, in this context. It is necessary in the output. So for stupid reasons,
the JSON format that is meant to come back as the
response, everything must be quoted. But when you're actually writing
JavaScript code with objects and keys and values, you don't
strictly need to quote things. Just bad design in the language. Other questions? All right, so if then,
the take-aways thus far are JavaScript has functions
and anonymous functions, which is kind of interesting, loops
and conditions and variables and more, even though we've not really
used some of those features, like loops and conditions. Because we've kind of beaten
them to death with Python and C. They are in there. But more importantly,
there is this notion of callbacks, the ability
to call a line of code and then say when you're
ready with your return value, call me back by calling this function. This is an example of what's called
asynchronous code in contrast with synchronous. Up until now, almost everything we've
written and everything we wrote in C was synchronous, which means
if you run a line of code and that function takes
awhile to run, your code is going to hang there
for some amount of time. And God forbid you've
got an infinite loop, it's going to hang there
forever and block everything. We started to see
asynchronous code in Python, even though we didn't call it
this, just a week or two ago when we started using Flask. Because Flask is asynchronous in the
sense that you write your program, it registers all of those routes, and
then it just kind of waits for things to happen asynchronously, sort
of out of order, in any order. But now in JavaScript,
we really feel the power of asynchronous in the following way. The reason that I was able to sort of-- actually, I didn't really do
anything useful with my time. I just kind of twiddled my fingers here. But theoretically, I could
have made another call. I could have checked my email. I could have gotten a snack while
I wait for Brian to get back to me. I could have gotten real work done. Because if you allow
for asynchronicity, you can do stuff in between the starting
and the finishing of some goal. And that was just like
when Brian called me back, I could have used that time usefully,
just like my program or my website could do other things
while I wait for this data. So the value, then, of
asynchronicity is that we can be ready to do more things at once. And what are some of the
things we might want to do? Well, let me open up some remaining
examples, here, as follows. Let me go ahead, here,
and open up this one. So this is built-in functionality
that's actually kind of cool, even though it's a little verbose. If you've ever noticed,
web pages these days and certainly mobile applications
can know where you are. Frankly, Google knew where
I was when I pulled up Google Maps, even though I was not
logged in, which is a little creepy. But they had enough
information about me. How could you be as creepy
in your own web sites and figure out where the user is? Maybe, I shouldn't have
teed it up like that. Well, this is a mouthful. But the ideas are exactly the same. Here, it turns out, there
is another global variable that comes with browsers these days. It's not just document. There's also navigator. And navigator is like this
special global variable that's got geographic related
functionality built into it. One of those pieces of functionality
literally is navigator.geolocation. So this is like a feature inside
of this global navigator object. It comes with a
function, otherwise known as a method called current position. Which, literally, if you
read the documentation, is supposed to get the
user or technically the browser's current position in
the world, latitude, longitude, using GPS coordinates or the like. But that can take awhile to
figure out where the user is. If we were talking in a CSI sense,
it's got to triangulate the user and figure out where they
are and do all of this, sometimes talking to the server. Somehow their position is determined. And it could take a second, a
minute maybe, some amount of time. So that's a good opportunity for
an asynchronous implementation, to use a callback like
we did with Brian. So that when the browser
does figure out my location, let me know so that I don't see
some annoying beach ball spinning until that answer comes in. So how do I do this? I call getCurrentPosition. I pass in an anonymous function,
though it could have a name. But it doesn't need it. An anonymous function that
takes, per the documentation, one argument called position, which is
going to be a special object containing coordinates. When that function is called some
seconds or milliseconds later, this one line of code here is
going to execute, document.write, which we haven't seen. But this is just a way of writing
additional words to the document, like the web page, the body. position.coords for
coordinates, .latitude. And then concatenate a comma
just to keep it pretty. And then concatenate
position.coords longitude. So this is a huge mouthful
for saying, do the following. Let me go into the web page
called geolocation.html. And nothing seems to happen yet. But if I-- Why did nothing happen? Oh, no. OK. There we go. So it wasn't working because I
wasn't accessing today's demos by HTTPS, which isn't a big deal. Because they're just
public demos anyway. But the browser didn't like it. Because it wants the communication
of my GPS coordinates to be secure. So as soon as I change
to HTTPS, it says, hey, this domain name, my own on the
IDE, wants to know your location. Now, some of us might be in the
habit of just clicking block. Some of us might instead be in
the habit of just clicking allow. Some of us might be in the
habit of clicking enter and who knows what just happened. But if I do click allow and
wait, because it's asynchronous, Brian could be taking awhile
to figure out where I am. There are my incredibly precise,
using floating point values, location in the world, at
least with high probability. Now, I can check for this, I believe. This just happens to be
Cambridge, Massachusetts. If I go to Google Maps and
search for those GPS coordinates, indeed that is pretty darn scary. So that's pretty good. That is, in fact, where we are. So the takeaway is, how can we do this? Well, we can do this by
understanding what a callback is and what asynchronous code is. But again, the paradigm is changing. I'm not just calling
getCurrentPosition and then getting back a return value like we have
been getting for weeks in C and Python. Now, there is nothing
on the left hand side. I'm not waiting for a
return value, per se. I'm certainly not storing a return
value on the left hand side, as we've been doing for
ages with Python and C. Instead, I'm passing in a
function, functionality, like my telephone saying, call
me back when you have the answer. And that's the paradigm now that's
really starting to change for us. And there's a couple of other things
we can do along these lines, too. Let me open up one, which
is just a little silly. But it kind of brings me
back to my days of HTML. Back in the day, in HTML like 1.0,
there was this amazing tag called blink. Whereby, if you did open
bracket blink close bracket and then wrote some words
and then close the tag, it would just do this on the web page. And I'm pretty confident
this is how you were greeted when you visited my like freshman year
website or sophomore year website like, hello, welcome to my website. This is stupid. And eventually, the one good thing the
standards bodies did over the years was remove blink
functionality all together. There was also, as an aside, a marquee
tag, where, just like a stock ticker or like a Broadway show
marquee, it would just scroll text across your screen like
this, which is also pretty stupid. But we can bring back at least
the blink tag as follows. So here is a pretty simple web page
with just a single div and an ID of greeting, just so I have some
way of uniquely identifying it. And suppose I want to
make this text blink. Well, if you consider, now
that you have the ability to execute code on the
user's computer, we should be able to achieve this by like
turning CSS on and turning CSS off, on and off. And you might not have done this before. Because we've probably just used CSS
for like centering text or making it bold or a color or a
different size or the like. But you can also make it display or
not display, visible or invisible, too. So if we look at my script code,
here, for better or for worse, let me consider how I might do this. I'm going to go ahead and
define a function called blink that simply gets that div by its ID. We've seen that before. And then I just do this. If the div's style
property, and you would only know that this exists by seeing
it in class or reading in a manual or seeing it online, if this
div, which came from this line, has a style of visibility equal to
hidden, then use this line of code to change the visibility for that style
of that div to quote unquote "visible." Else, logically, if that div style is
visible change it to hidden instead. To this day, I do not know why the
opposite of visible is not invisible. It is hidden. But that is also a design
decision we're stuck with. So how does this work? This is just one function
that just changes the state. But something's not going
to blink unless you change and then change and then
change and then change. Well, another beautiful
feature of JavaScript that we're kind of using for evil
here is to do something repeatedly but asynchronously. I could easily make
something blink and blink and blink by just
making an infinite loop. But if I had an infinite
while loop or for loop, I would, by definition,
never get out of it. And therefore, the page
would blink forever, but the page would not do anything else. But with asynchronous code like this, I
can register a function with a browser and say browser, go ahead and call
this function every 500 milliseconds. And notice, this is one line of code. So when the browser executes
this code, it executes one line. And it just keeps going. But it remembers, every 500 milliseconds
remember to stop whatever it's doing, blink, then keep going,
then blink, then keep going. So in this way, can you have multiple
things happening on your web page. Because the way JavaScript
works is it itself, the language, built into
the browser, essentially, just itself has this infinite loop. And it's constantly listening
for users to click on things. It's constantly listening
for the mouse to move. It's constantly listening
for a timer to go off. And every time one of
these events happens, it dispatches the handler,
the function, that it was told to call in response to those events. So the end result here
with blink is this. If I go back to my directory index,
here, and open up blink.html, you see it doing exactly that. And I can tweak this
a little differently. If I want to do it every tenth
of a second, we can do this. And if we do this too fast
it's probably not healthy. So we'll just leave it at 50. So you know, this is how I learned
how to make the web years ago. So what more can we do
in a more compelling way? Let's look at one final example
that I fixed during the break, which is this here map. This is where the world starts to
get really, really interesting. Because there are so many
third party APIs out there, application programming interfaces. Like nice people and nice companies
who are trying to sell you services, they have features, code that they've
written that they make available on the internet for us to use
either by grabbing data from them, as in the case of CS50 Finance
pulling in stock quotes. Or in the case of Google Maps, actually
baking in additional functionality to your application, so you don't
have to implement it yourself. If anyone's ever used Lyft
or Uber on your phone, Lyft and Uber did not start
out by being map companies, sending cars all around the
world mapping the whole world. That would be insane for a
startup to try to do that. They wanted to build
a car sharing service on top of another feature that's
just kind of a necessary ingredient. So they used Google
or some other company, paid them some amount to build their
maps into their own application. And then they contribute to their
own intellectual property and ideas. So how can we do this? Well, it turns out if I have a
web page that's pretty simple, and let me go ahead and just
quickly delete this real fast, so that it just looks as follows. Here is a very simple web page
that's got a body and then a div inside of it whose ID is map. And then at the very
bottom of the file notice that there's this JavaScript
code that points specifically to Google API, application programming
interface, slash map slash something. And what I did during the break
was I downloaded a new API key, which allows me, David Malan,
to use their API so that all these requests are associated with me. Previously, I had an old key. So it just wasn't working. And that's why we got the error message. So I signed up now for a free API key. But how do I actually do
something with this map? Well, we can do a few
different things simply by following along with the
documentation online in the right way. Let me go ahead and open
up the following here. If I go ahead and load this page right
now, that I've deleted that code, and open up map.html,
there's nothing there. It's just a big white page. And that's because I haven't
added any of my own code. But if I go into the script tag here,
let me go ahead and do the following. Let me define a function called
initMap that takes no arguments. And then inside of this function,
let me go ahead and do this. Let me declare a variable called
map that takes on the value of a new google.maps.map of
document.getElementById("map") And then pass into that a special object. So we'll see what this
means in a moment. The syntax here is a little funky. But this line of code
I only knew by reading the documentation for Google Maps. Google Maps told me if you
want a new map, type this. And if you want to remember that map in
a return value or in a variable, sorry, I should have said let,
store it in map on the left. So the weird thing
here is the following. The two arguments are these. This is a line of code that we have
seen before that says, hey browser, go get me the HTML element from
the dom whose unique ID is map. What is that element? It's just this div. And it's empty. There's no map there now, obviously. There's nothing between that
close brace and open brace. So that's why there's no map. But this line of code
is what we're going to use to inform Google
where to put its map for me. It takes another argument
here, as per the curly brace and the close curly brace,
which is just an argument, which is to say the documentation told me
I have to pass in multiple key value pairs. I have to configure the map. So let me do that in just a moment. Let me go ahead, now, and reload the map
by going up to the browser and reload. And interesting, it's
not doing anything yet. But we did get progress, right? It's gray. But that suggests I just
haven't configured the map. So let me do that. And I would know this only
from the documentation that I need to provide a key of center. And that center needs a
latitude and longitude. And I can choose just to
be neutral here, 39.833 and a longitude of negative
98.583 close curly brace. And then a zoom key of 4. These mean nothing out
of the context of Google. I know this only from
reading the documentation. And Google's documentation told me
make sure you use a key called center. Have its argument after the colon
be another JavaScript object with two keys, lat and
long, each of which is exactly that, a float that
represents a latitude and a longitude. And then also tell me, the Google
API, what zoom level do you want. Do you want to see the
bird's eye view way up here? Or do you want to really
zoom down on the terrain? And 4 is roughly, it's at a
certain level that's useful. But we can tinker with that as well. Let me save that. Go back over here and reload
the page now and voila. I'm centered over what's roughly
the center of the United States at a certain zoom level. If I want to change one of
those values just to see, let's make this maybe 8, save. Reload. Now I'm really zoomed in on what
appears to be Kansas or Nebraska. So that's a different zoom level. I can really kind of poke
around the world, so to speak. So let's see, if I go to like 139,
let's see where that takes me. Reload. That might not be
geographically possible. Let's do 42, how about. Change that to 42, reload. Now we're over, OK, Sioux City there. Let's maybe go to 44. Anyhow, we're moving the map to
places that I don't know in advance. Now we're in South Dakota. In any case, all we have
done now is just configure the map to be in different places. But there's other
functionality in Google Maps. Let me revert this and let me go ahead
and declare a couple of other things. I can actually declare
a marker, as follows. Let me get myself a new Google
Maps marker, open paren and then close paren. And then notice I have a
curly brace in there, too. Because marker is another
feature of the Google Maps API that lets me specify on what
map I want to put the marker. So there's a key called map. And then coincidentally, there
is a variable called map, which I defined up here. And then it takes one other thing,
the position of this marker. Well, I'm going to put this
marker at latitude 42.3762 and a longitude of negative 71.1158. And then just for good measure,
let's do one more of these. And actually, I don't strictly
need the variable here. So I'm just going to get rid of that. And I'm going to do a
new Google Maps marker. Same syntax as before. The map is going to be the same. But the position of this marker is
going to be a latitude of 41.3104 and a longitude of negative
72.9289 close curly brace, save. And if I didn't screw up, which I did. And it's yelling at me. Unexpected token param--
oh, OK, forgot this. Save. Go away. Go away. Reload. Let's go and zoom out. And look at that. We have markers over what is
hopefully Harvard and Yale. And so where did all this come from? Well, literally Google Maps. And that's what I Googled
during the break, API key. Google Maps API. And if I go to this URL,
as you soon will too, you'll see under its
documentation that they have many different APIs, some of
which are for phones, some of which are for web pages such as
this, the JavaScript API. And you'll see that there's a very
rich interface for actually creating these kinds of maps. And the documentation, frankly, can be
a little overwhelming at first glance. But here they give you examples of
how to put a marker, for instance, over Australia. This is how I inferred how to put one
over Cambridge, Massachusetts and New Haven. There's other functionality, too. Like these things called info Windows. So with info Windows, if I
scroll down to this example here, you'll be able to add clickability. So if I register an event handler
that's not on submit but on click, I can do things like
this, just as Google has, whereby on clicking a marker, we
trigger something else to happen, in this case, an info window to
open, and thereby get functionality. And so to bring all of this together,
which you will do, ultimately, for CS50's mash-up problems
set, your very last, is to implement a user interface
using some of these building blocks. Here we are centered over
Stanford, California. And notice that the map is full screen. But you can zoom in and out down there. Notice that there's a text box,
which is a very simple HTML form at the very top. And notice, just as I did before, we
have configured the staff solution, as yours will soon do too, to
listen for clicks and on clicks, call a function that makes
an AJAX request to a server, get back some news articles, create
an unordered list out of them, and display them in one
of these info windows. And so if we actually look at
what's going on underneath the hood, let me go to my developer
menu, under developer tools. And as you should be in the habit,
again, watching your network tab, let me go ahead and do exactly this. Let me clear that, click
Palo Alto's news, California. And notice a few things just happened. One, my browser made a
request to an articles route, passing in the geography
of this zip code here. Notice that I got back some gifs here. And in fact, the internet here is so
fast, we didn't see the progress bar. But we would have seen a little spinning
indicator if the internet were slow. And that's how I then
got those news results. And if I click on the articles here,
notice what I'm getting back is-- OK, hello. Always check the day's
news before class. So what I see here is a big JSON object. And it's all in one line. So it's a little hard to see. But I'm sure you can
scroll through the news later and see actually what the
articles and the URLs thereof are. But there's one more
piece of functionality. All of us have seen auto-complete
work in our browsers, because it remembers usually
what you've previously typed. But it's more powerful
to autocomplete based not on just what the users typed in the
past, but what you think in the future they might be typing. So if I actually want
to search for 02138, notice I can narrow down the list of
all the cities in the US so that I can click on that autocomplete. And now we have a localized
map to the Cambridge area where I can get the
local news from our area. Or I don't have to
search just by zip code, I can type in New Haven, Connecticut
and get any of New Haven's zip codes and similarly teleport over there. So among the challenges ahead is to
download a pretty big file, a text file, called us.text, in which are
bunches of cities names and states and zip codes, import those
into your own SQL-like database, implement a few routes so that
you can ask your database what are the few cities within view and
what is the current news in this area, and then using JavaScript and today's
ideas, stitch all of this functionality together to mash up all of these
different ideas into an end result, your last. And that's it for today. I'll stick around for
questions one on one. Otherwise, we'll see you next time.