SPEAKER 1: All right,
this is CS50, week 10. And you'll recall that
last time we introduced one of our additional languages in CS40,
that of SQL, Structured Query Language. And this, recall, was a language that
we used to query databases, insert data into databases, delete,
update, and more, so that we actually have
a way of persisting data once we built a web-based application,
or really any other application that we want to be able
to store data long-term. And we had such statements as create for
creating a database or a table, insert, select, update, delete,
and a few others as well. And with these relatively
few building blocks, we're able to start building
a back-end for a web service. And indeed weeks ago when we first
implemented a front-end for Google, simply by implementing that
web form, we didn't really have anything to do with the data
or anywhere to query for data. But now we actually do via our
own database in the form of SQLite and via this new language, SQL itself. But today we introduce really the
last of our formal languages in CS50. Recall that we began the
semester with Scratch, transitioning quickly thereafter to C
where we spent a lot of the semester. We have since pivoted
to Python of course, whose syntax is quite
different, but whose ideas are really fundamentally the same. Today we transition to JavaScript. And JavaScript you'll find is more
syntactically similar probably to C than it is to Python itself. So you'll see that a few
more parentheses are back, perhaps some semi-colons as well. But what's most important today is that
really the fundamentals of programming aren't changing. But rather the method via which we
actually execute or run this code. In particular, thus
far, when we've written C code, when we've written Python code,
all of that code has run on the server, so to speak, within CS50 IDE or
maybe on your own Mac or your own PC if you have some prior
programming experience. But today we introduce a language
that is generally, though not always, used within the client, the browser. Which is to say the code
that we start writing today-- and when you generally use JavaScript in
order create front-end user interfaces, you will find that the code
you write, like HTML or CSS, is actually sent to the user's
browser where it's executed, again client-side, on the Mac on the PC. It is not executed server-side. Now to be fair, JavaScript can be and
is increasingly used on the server-side as well via frameworks called
Node.js, if not others. But we'll focus predominantly
on client-side usage thereof. And you'll see that you can start
to do some pretty powerful things, because not only now do we have the
ability to have a dynamic back-end that serves up data and
searches things for us, but a front-end that gives us all the
better user interface and features still. So I was thinking back yesterday on
when I first started using JavaScript. And it was in a very, very
small isolated instance. But way back in the day-- and this
is thanks to the wayback machine, you may recall Frosh IMs was
something I did in college. Not so much in sports
but more the website. And this was essentially the layout--
apologies-- of the Frosh IMs website some years ago. Now this actually post-dates
me by a few years, since it seems the codebase actually
survived me by quite a few years, surprisingly. But early on, when you would hover
over these menu options at top right, those would have what are called
event listeners attached to them so that when you hover over
some of those menu options, the color would actually change. And I think they shifted
positions slightly. So [INAUDIBLE] ultimately took over
the site and took it further than that. But this was my first
taste of JavaScript. And it was just to give the
website a sense of dynamism and to give it a sense of interactivity
that wasn't possible, certainly not at the time, with HTML alone. So let's do a quick compare
and contrast of JavaScript with things we've seen in the past,
just to kind of bring ourselves up to speed on some of the syntax. But you'll find we need to
spend relatively little time on the syntax and the language
itself, because you'll find syntactically it's so similar. And so instead we'll focus more on
ideas and new features of the language itself. So as in C and in Python,
we have the ability to express functions in JavaScript. They look a little bit different,
at least at first glance. But fundamentally
they're really the same. In JavaScript, if we
want to function, we're going to use the
keyword function to say, hey browser, here comes a function
followed by the function's names, zero or more parameters,
and then between the curly braces a bit of code that
implements that function. So gone is the ability
to just indent your code and have the interpreter
know what you mean. Those curly braces are back as are more
parentheses for us here in JavaScript. But in terms of loops you should
find this fairly familiar. In JavaScript if you want to iterate
over something again and again and again, the do while
construct is actually back. So we have something very
similar here as we do in C. And what you use that loop for
can be any number of things. But we do have that capability again. Similarly, do we have while
or while true loop here, which would induce an infinite loop. And again, these are the kinds of things
that might trip you up unnecessarily at first, but quite reasonably. Like if you start
capitalizing true again, it's not going to work in JavaScript. So again, reasonable
people will disagree when it comes to designing these languages. And so the authors of JavaScript
decided to lower case true and false, where again in Python we've been
capitalizing recently, true and false. Meanwhile, if you want to declare a
loop using a for loop, that is back. But you'll notice perhaps
implicit in this example is the fact that JavaScript is,
like Python, not strongly typed. It does have the notion of data types. And you can access or
look at those data types. But you don't have to specify
them as the programmer when you're declaring variables. Rather, in the case
like this, when you're declaring a counter like I, which
should be an integer from 0 up to 50, you literally say, var, for variable,
than the name you want to declare and then just the rest of the
syntax is as we've seen before. Meanwhile, there's another handy
feature-- and you'll see this in use in various examples perhaps online-- is
the very easy ability, like in Python, to iterate over the keys in an object. So recall that an object,
at least in Python, is really just a collection
of key value pairs. But it's an object can also
have methods inside of it. But if we focus entirely
on data, keys, and values, this syntax here would allow you
to iterate over all of the keys and some value coming back. So maybe if you have a
stock object, you could iterate over its name and
its price and its symbol, simply by using syntax like this,
and an index into the object to get at that object's value. Meanwhile, variables are
fairly straightforward. To declare a variable like I, we would
say var I equals 0, and a semi-colon. Boolean expressions,
meanwhile, are with us still. And these are no different. I is less than 50 might
be expressed with this. X is less than y might
be expressed with this. So nothing new there. Meanwhile with conditions, we
have syntax identical to C. So again, the curly
braces are necessary, at least if you have multiple lines
that you intend to be associated with the if or the else if or the else. Again we're back to, else space
if, instead of L if in Python. But again, there's nothing really new
here in terms of content, really just syntax. So after practice and
after some trial and error, you'll generally find that
it becomes second nature. Meanwhile, we have arrays in JavaScript. So for instance, if we want to
declare an array called numbers, again we don't specify the type of
this array or the members therein. We simply say var, to
give us a variable, number shall be the
name of that variable. And then a list here of
arbitrary numbers themselves nested in between square brackets. So in JavaScript, as
we've seen in Python, we have the ability to express
lists or arrays specifically in JavaScript that simply use square
bracket notation to define them in a context like this. Meanwhile, speaking of
objects a moment ago, we have that same ability in
JavaScript to declare them. So for instance, if we wanted to declare
an object, and we'll call it quote, we use, as in Python, curly braces. And I say as in Python
because in Python really when I say object,
focusing entirely on data, I really mean a Python dictionary
or dict object, which again is this collection of key value pairs. We don't necessarily do
things quite the same way. But in this case here, var
quote is a way of porting, say, from a CS50 finance
example, a company's name and its price and its symbol. And worth noting here, that
as in Python, you actually have choice over the quotes that
you use, at least in this context. Single quotes are fine. Double quotes are fine. So long as you are
stylistically consistent, it's probably fair to say that many
people in the JavaScript community tend to use single quotes here. There's no functional
difference as there is in C. However, they do matter,
as you'll perhaps eventually see, when you're using not
JavaScript per se, but JSON notation. JavaScript Object Notation,
which is a simple data format not unlike CSV, but that allows
you to store a hierarchical data inside of an object. And the subtlety there is that when you
want to store data in this JSON format, you have to quote literally everything
with specifically double quotes on the left and on the right. So it's an annoying distinction. And don't fret too much about it now. But just realize any time
we're talking about JSON and a technology called AJAX--
more on that soon-- it's got to look like this
with the double quotes on both sides of the colon
for those key value pairs. Now with that said, let's start
to give ourselves some context. Let me introduce a few features that
we've kind of sort of seen in Python-- didn't necessarily
leverage, but are going to be really integral to the way
in which many people use JavaScript within browsers. So here, for instance, is
that old simple example of HTML, perhaps the simplest
web page that we can write, that quite simply says in its
title and its body, hello world. And recall that the indentation
here is functionally meaningless. The browser doesn't really care
how pretty your HTML looks, just nicer for us humans to see everything
nested and nicely indented, because it's just a lot easier to read. And it's also a lot easier to detect if
you type something wrong, if something doesn't really line up as you expect. But another way, recall, of
viewing this same piece of HTML is in the form of a data
structure like a tree, which we discussed way back
when in the context of C. And we might draw this
same example of HTML with a Dom, document object model,
which is a fancy way of saying tree. And that tree might look like this. It's got some special root node that
we'll just generically call document, because there might actually be
some other stuff like comments or whatever up there. But the root element of a
web page, recall, is HTML. The second thing you type
is open bracket HTML. The first thing you should type with
HTML5 is open bracket doc type HTML. So you can think of the doc type
as meaning this node essentially, and the open bracket HTML close
bracket meaning this root element. Of course this page here
has both a head and a body. That head a title, and that title
has a text value inside of it, or a text node so to speak as does
the body that happens to be identical. So what's nice about this mental model
is that if we tie everything together from weeks past, sort of
the markup language of HTML and the data structure of
trees and specifically this Dom here, it turns out that you have the
ability with JavaScript-- something we didn't have in C
really and didn't really have with Python-- but the ability
to change this tree in real time. After a browser has downloaded
some HTML from a server, typically that content has been static. You can open up Chrome's console in the
elements tab and futz with it manually, but those changes aren't persistent,
even though you see them. And certainly no user, or no typical
user is going to do or know to do that. But you the programmer,
if you want a user to be able to download some web
page, but then interact with it and have that content change--
very similar in spirit to something like Gmail, whereby
every time you get an email, a new row in your inbox
appears without the whole page having to reload and certainly
without you having to click Reload. Or something like Facebook Messenger,
where no matter the time of day if you have Facebook open in a tab,
it's just going to pop up a message and keep adding to that little
window-- another line, another line, another line of text. So there's this dynamism you get that
you can't get from HTML and CSS alone, but you can with JavaScript. If you think of it just
intuitively, if you have the ability to run code inside of
a user's browser, you could have essentially kind of a while
loop that's just constantly waiting. Did the server send me more data? Did the server send me more data? And if so, go ahead with an if condition
and write more text to the web page. Write another message in the
little Facebook chat message. Write another row to the Gmail inbox. And that's what we're going to
get and more with JavaScript. And it turns out, with JavaScript, can
we listen for a whole bunch of events so to speak. I eluded to an event, a
listener being attached earlier. And this is just a small
sample of the events that can be triggered within
the confines of a web page. So unlike our Python programming thus
far, and unlike our C programming, we have in JavaScript
this asynchronicity. Multiple things can kind of
sort of happen at the same time or really at unpredictable
times because users, of course, are interacting now with our web pages. And who knows when or where
a user is going to click. Who knows when he or she is
going to click and drag something across the screen or select some menu
option or click check some checkbox. So we can't really just write a
program top to bottom in JavaScript as we've done in the past per se. Rather, we have to start writing code
that says, if I hear a mouse click, or if the user drags their mouse,
or if the user checks a checkbox, do something. So kind of like if this then
that, if this then that. So a lot of conditions. But it turns out that
it's relatively simple to register functions--
that is, associate functions with these various events. And so for instance, when you check
a box in Gmail and all of a sudden the row becomes a
different color or whatnot, that's because there's an event
listener for the click event that Gmail is saying, as
soon as the user clicks this event go ahead and change the color
or change the interface in some way. Or if you click the little X in the top
right-hand corner of a Facebook chat window, the reason it goes
away is because there's a click event happening. And Facebook has written code
that listens for that click event. And as soon as they hear that
event, they close the window and remove it from the
web page altogether. So Google Maps, for
instance-- drag is an event. So if you've ever kind
of wondered, well, how do I click and drag in Google
Maps and they just know to show me more of the map, whatever
direction I'm clicking in, they're listening for the drag event. And so this is where things get really
interesting with GUI side programming-- graphical user interface programming. There's this whole event model, where
a bunch of events, a bunch of things can happen at any number of times. Or at any point in time. So let's offer a few general definitions
of terms and features of JavaScript. But let's actually discuss them
in the context of examples. So JavaScript supports and
really, really leverages, typically things called
anonymous functions, otherwise known as lambda functions. And these quite simply are
functions that have no name. And that seems a little strange. But we will see contexts in
which functions don't need names if you're only going to call
them once, or if you only need to refer to them really once. So we'll see how to declare and define
a function that doesn't actually have a name like foo or bar or whatever. Meanwhile, we're going to see a
methodology involving callbacks, which is very similar in spirit to
the events I rattled off a moment ago. Whereby a call back is
just a function that's supposed to get called
when something happens. So in other words, Google and
Facebook with those user interfaces, they are registering functions. Really, they're registering callbacks,
so that when the user clicks on an X or when the user clicks on a checkbox,
or when the user clicks and drags on a map, they have in advanced register
a function that gets called back. It's like leaving a message
for someone on voicemail. They call you back in
response to that voicemail. They call you back in
response to the beep that their phone makes
when they've received that. So it triggers some kind of
functionality, these callbacks. Callbacks are just
functions that have been configured to be called at a certain
point in time when something happens. Now meanwhile, and
lastly, we'll talk about AJAX, which isn't a
technology unto itself but a use of various existing
features within browsers that allow you to query
from a browser, a server to get more data even after the
original page has been loaded. Let me go ahead here and create a
file called, say, Dom 0 dot HTML. Document object 0 dot HTML just to
line up with some of the examples that we'll place online
for everyone to play with. I'm going to go ahead and
start my page as I usually do. And I'm going to go ahead and say HTML. And then in here I'm
going to have a head tag and in here I'm going
to have a title tag. And I'm just going to call
this Dom 0 for simplicity. Down here I'm going to a body tag. And in here I'm going to have a form. I'm going to give this
form, similar in spirit as we did in our discussions
of CSS, a unique ID, simply so that I can refer to it
as a demo, a demonstration. But let's come back to what more
I want to associate with that. First let me go ahead and give
it an input, an ID of names so that I can refer specifically
to this input field. Let me give it a placeholder of name. And let me say that
the type of this field is a text field to close that tag. And then input type equals submit. So a very, very simple web
page that looks like this. Now what could go wrong if I present
a user with a web page like this? Well, he or she might
not give me their name. They might just click
submit and this form is going to get
submitted to some server. Well that doesn't seem all that great,
because I don't have a chance to check, did they actually type in a name? I don't have a chance to do
something with it on the client. And indeed that's now the new
feature we get with JavaScript. Notice what I can actually do. Let me go into the
head of this web page, where thus far we've pretty
much only put the title tag. We've put the link tag for CSS. And you may have seen with
CS50 Finance that we also had a script tag that referenced
a library called Bootstrap, and another one called Jquery. More on those in a bit. But indeed, inside of the head of
a web page can go with script tag. And you know what,
inside of a script tag can go code, specifically JavaScript. And in here I can define
a function, literally. I'm going to call it, greet,
just to kind of say what it does. And inside of this function I'm
going to do the following-- alert, quote unquote, hello,
comma, world, semi-colon. So this is how in this example I've
defined a function called greet. I've put it inside script
tags, open and closed inside of the head of this web page. Now, nothing's going to
happen with that unless I tell the browser to do it on an event. So I'm going to go into my form
tag here and say on Submit, go ahead and execute the following code. Go ahead and call the greet
method and greet function, and just for good measure return false. But more on that in a moment. So again, my function's defined up top. But nothing happens. Again, when you define a
function, nothing automatically happens until you call it. So when am I going to call it? On the form tag here, I
have an on submit attribute, which is new today, that says, call the
greet function and then return false. But again, more on
that in just a moment. So what actually happens here? Let me go into another
window, open up DOM 0. And you'll see, if I now
zoom in on this form, will see that it's a very simple
HTML form with just a name field and a submit box. And if I go ahead now and type in
my name, David and click Submit, hello world. So it's not actually saying hello,
David, it's just saying hello world. But notice what happened. This is a very bad user interface
just using this built-in prompt. But it demonstrates the
built into JavaScript are a bunch of functions,
one of which is alert. And that function is
designed to do exactly this. The window will look a
little different if you're using Chrome or Edge or Firefox or
Safari or whatever other browser, but you'll see that it
simply says, hello world. And it's going to say whatever the
URL on your page happens to be. In my case it's just this local
IP address for lecture's sake. But this isn't all that interesting
to just hard code, hello world, especially when I have the
opportunity to take in a user's name. So if I instead go
back into my code here, and don't just print out,
hello world, but perhaps concatenate with
JavaScript's plus operator, the result of this method call,
document dot get element by ID, quote unquote name, then dot value. So that's a mouthful. Let's see what this does
before we explain what it does. Let me go ahead and reload the page. And now we see the same form again. But this time I'm going to
type in David and click Submit. And now it says, hello, David. So how does this work? Somehow or other, I wrote code that not
only alerts the user with this window, but it somehow grabs data
that he or she has typed in and embeds it in this message. Well here is where we can leverage
the DOM, the Document Object Model, and a bunch of functions
that come with JavaScript that allow you to programmatically get
elements and get data ultimately from a web page. Specifically notice we're doing this. We're calling alert, and
then open paren close paren because it's a function call. Quote unquote hello comma, with a space. And again, single quotes,
double quotes, doesn't matter so long as I'm consistent here. Plus, which is concatenation,
document doc get element by ID, quote unquote name, dot value. So it's kind of a mouthful
and it's definitely verbose. And we'll see before long slightly
more succinct ways of expressing this. But you can think of document as being
this special global variable that's just accessible to JavaScript
code that you write. And that really is that
uppermost node in our tree, that top-most node in our DOM. And associated with that
node, which is just an object, are a bunch of methods or functions,
that just come with JavaScript, and that your browser
just supports for you. One of those is called
get elements by ID. And recall, we've used
this jargon before. An element in a web
page is the combination of an open tag and a closed tag
and everything in between it. So get element by ID quote
unquote name means, hey browser, go get me this entire
element from start to finish. And this is an empty
element because we've closed it within the it's own tag. So that just means, go get me. Kind of a pointer to
that node in the tree. There's no pointers in JavaScript. So we should really call this
like a reference to this node. But it really just means that. Go get me somehow this node in the tree. And what do I care about
once I have that node? I care about its value. So dot value, you can think
of like syntax like a struct. That means, if you have this node now,
via get element by ID, go inside of it and look for the field with
a property called value. And that's going to line up, it turns
out, with exactly what the user types. So I can do this again to be clear. Let me go up here and for instance
type in Andy and click Submit. And voila, now it says hello, Andy. But now the browser-- and this
is perhaps a curse from 10 and 20 years ago when people started
to abuse JavaScript and give you hundreds of popovers so
to speak, hundreds of prompts if you visit a website
that's trying to mess with you. Chrome and other browsers will
let you check a box like this, prevent this page from
creating additional dialogs, just because it thinks that maybe the
page is buggy, maybe it's malicious, and it's really just pestering
you as these things are annoying. But at least during CS50
development for P-sets projects, don't check this because it'll only
confuse if the page no longer does as you tell it to do. Fortunately that doesn't come
up too often on actual websites. All right. So we seem then to have the
ability to not only get data from a web page programmatically
and display it dynamically. But can we design this
code a little better? Well it turns out that
we technically don't need to co-mingle our code and our HTML. And notice too there's one other line
of code here that's a little sloppy. I mean literally between
these double quotes do I have two statements--
greet, which is a function call, and then return false. The reason I had return false is that
if I didn't, after clicking Submit and submitting this form,
the only thing stopping this form from just being submitted
to the server is return false. This says, hey browser, even when the
user tries to submit this form, don't. Return false. The default is true. Otherwise, if I didn't have
return false and I click Submit, I would see that alert as expected,
but the moment I dismiss it, I'm going to be led to some other
web page, presumably wherever the form is going to be
submitted, which coincidentally happens to be the same page. But now that we're developing
client-side applications, client-side web apps,
we don't necessarily want forms to be
submitted to the server. We want to use them, for now, only
within the confines of a browser. Indeed there is no back-end,
there is no action attribute for this particular example. But this feels messy. Any time in CS50 when we've
introduced some new language like CSS in the context of HTML, or our HTML
in the context of Python via our Jinja templates, did we try to factor out
one language from another, so as not to blur these worlds and make the
code very messy, very unmaintainable. So how can we begin to remove,
from these quoted values, code, but still have this feature
of listening for a form submission? Well let me go ahead and propose
another variant of this program, that I'll go ahead and
call DOM 1 dot HTML. I'm going to start with
the code from before, but I'm going to make a few changes. Instead of putting it in the
head of my web page, for now, I'm actually going to put
it down here in the body. More on that soon. But instead of even
declaring this as a function, I'm going to instead simply do this. I'm going to get rid
of this event handler. So now all that remains up here,
to be clear, is just pure HTML. I still have those ID attributes
so that I can uniquely identify those forms and that
form and those inputs if I want, or that input if I want. But notice what I can do now. Document dot get element by ID
quote unquote demo, because that's the name of my form, dot on submit,
gets function open paren close paren. And then just for stylistic
purposes, let me go ahead and do this, which is what most
JavaScript programmers would do. So what am I doing now? Now I have pure HTML appear. But to be fair, I now have a
script tag inside of which is code. But at least I've removed the
code from like an attribute, which just looked or felt a little sloppy. And look at the code now, document
dot get element by ID demo. So this gives me essentially a
reference to the entire form, not just that name field. And it turns out that provided
that node in the tree is a form, and indeed it is, that has
associated with it a property by the definition of
HTML5 called on submit. This is a property, that if you
assign it the value of a function, that function will get called
when the form is submitted. And yet what function do I want to Call
Well, function open paren close paren seems to omit a key detail that
we've seen in Python and C, which is the name of the function. But here's an example where I don't
care what the name of this function is. I don't need to know the
name of this function. Because all I need is a function, a
chunk of code that will ultimately get executed when this form is submitted. And that line of code is
identical to what it was before. So just to be clear, this anonymous
function, so to speak that I'm using, is not strictly necessary. If I really wanted to, I
could do something like this. I could declare a function
called greet, just as before. And I'll format it
exactly as I did before. And I could declare this right up here. And then down here I could say, greet. In other words, the
on submit handler just wants to know what function to call. So fine. If I find a function call greet, I
can tell on submit to call greet. Notice, no parentheses here. I don't want to call the greet function
when that line of code is executed. Rather, I want to assign
that function, which you can think of as a variable unto
itself to this on submit handler. But why? This hasn't really gained me anything. Yes, it's nice that it's called greet. But I'm defining a function called
greet only to configure my browser to call that function one line later. The nice thing about anonymous
functions is that you can just kind of tighten things up. Why clutter your namespace so to speak? Why fill up your brain
with names of functions that you're never again going to need? And so more common and cleaner,
better design arguably, would be something like this. All right. And actually just for
good measure because this is all part of a
statement, in this example let me put that semi-colon there. So the example is going
to work exactly the same. Indeed if I go back to my
browser and go into DOM 1 dot HTML and type in something
like summer and click Submit. Hello, summer. And so it behaves exactly as before. And for good measure, let me go
ahead and change the title here to match the name of the file. But now let me go ahead
and open up an example I wrote in advance, like
many of these, called DOM 2 dot HTML, the code
for which admittedly is much more cryptic at first glance. And indeed the syntax will
take some getting used to. And you don't strictly
need to do things this way. But a super popular library in the
world of JavaScript today to this day is something called jQuery. And indeed the bootstrap
library with which you're now acquainted by
CS50 Finance actually uses, for some of its features,
the jQuery library. So let's introduce the syntax so that
you've seen it, so that you can use it. But realize, this is not giving
us any new functionality. It's just giving us a different syntax. And over time, you'll see that
jQuery, like certain other libraries, it tends to make it more pleasurable,
more efficient to write JavaScript, because you can do things
a little more succinctly. The price you pay is a
little bit of complexity. So let's take a look syntactically
at this library called jQuery. Notice, in DOM 2 dot HTML,
I have this URL up here. There's any number of places to get
the jQuery library and libraries more generally. But this one happens to be
hosted, for instance, at this URL. And it's the latest version thereof. And this attribute source
simply says, hey browser, go get the JavaScript code that I
want to have access to from this URL, and assume that it's equivalent to
my having written in this web page itself, like our other
script tags thus far. Meanwhile, after that, an
order is generally important when including things like this. Let me go ahead and do the following. Up here notice that I
have this line of code, which generally is a good
thing to have because it says the following to the browser. Hey, browser, when the
document is ready-- that is, when the whole
web page has been loaded, when all the bytes have
come back from the server, please go ahead and
execute the following code. And we'll see that this allows
us to ensure that things don't happen sooner than we actually expect. Specifically, let's do the following. When the document is ready I
want the browser to execute the following lines of code
that I've highlighted here-- dollar sign, quote unquote, hash demo. It's kind of a mouthful. But this is simply reminiscent
perhaps of the CSS syntax that you might be familiar, that
simply says, hey browser, go get me the element from the DOM, from
the tree representing this page, that has a unique ID of demo. So hashtag demo is just a
more succinct way of saying, document dot get element by ID. You can do this all in
just a few characters. And the dollar sign here
is a feature of jQuery. It's actually just a synonym for jQuery. Dollar signs can actually
be variable names. So dollar sign quote unquote
hash demo means, hey, browser, execute the equivalent of document dot
get element by ID, quote unquote demo. Just more succinct, even though it's
a little bit cryptic at first glance. Meanwhile, submit, not to be confused
with on submit submit-- submit is a function that per
jQuery's documentation says, hey, browser, register the following
event handler for the submit event. The way you do this is
you provide the library with an anonymous function, which in
this case I've just said function. It takes one argument. And I would only know this from
having read the documentation. Function takes an argument
that we'll call event. But we can call it call
it anything we want. And then inside of this
code, what do I want to do when the demo form is submitted? Well, I want to use alert. But I want to paste in this value. So again, just new syntax here. And it's fine if you prefer
the other syntax for now. Dollar sign quote
unquote hash name, means go get the element from the DOM
that has a unique ID of name, and go get its value
using this method call. So jQuery essentially does this. jQuery
wraps existing elements in a DOM. It goes ahead and adds like
another bigger rectangle around those smaller
rectangles that give you additional features,
among which is the ability to use these CSS-style selectors, among
whose features is to call like dot val and get the value without
having to do dot value, which isn't all that
compelling in this case. And then we're appending, in this case,
an exclamation point for good measure, just so to show that we can to continue
to concatenate beyond one string. And then lastly, is this, which
granted, more verbose-- event dot prevent default just
means, hey, browser, whatever your default behavior is
for handling forms, don't do it. Prevent it, because I want to
handle this form submission. So this is a really long way
of saying, this is another way to implement exactly the same
program that we did earlier, albeit with an added
exclamation point, which has nothing to do here with jQuery. So why is this a good thing overall? Well one, your code will
actually get shorter over time. But it's fine if you'd
rather not use this. But this first line was
actually rather important. If I instead were to implement this code
like this, there's actually a problem. And actually there's a problem
even if I were to do it this way. If I were to go back
to DOM 1, and I were to do something like this in this
example, and not use jQuery at all, but just, in my head tag, have a
script tag that has this code here, there's a problem of
the order of operations. On this first line, when I
say document dot get element by ID quote unquote demo dot on submit,
assign that listener this function, it's too soon. Because the browser at
this point in the story literally is reading the file
top to bottom, left to right. And the browser has not
got to the line of code, where in this form, and its
demo ID is actually defined. So this would actually be broken,
in so far as the browser's reading it top to bottom, left to right. But it sees this code and it says, hey,
browser, go get the element by ID demo. There is no element with
that ID at this moment, because it doesn't come until later. So a way of solving this
using just JavaScript, is you could do something
like the following. Window dot on load get function, and
then you could do something like this, albeit fairly verbosely. So that would work. Hey, browser, when the
whole window is loaded, then please call this
anonymous function. Or we can use jQuery
which frankly tends to be more common, at least when
using other libraries as well, which says that exact same thing. And in fact, a little bit more than
that via this line of code here. So just another way of doing
something, another form of syntax. But we won't necessarily assume
that or complicate things by using that library
syntax along the way. All right. So now that we have the ability to
access data inside of my web page, specifically in forms. And I have the ability
to alert the user, it would seem we can actually
create useful features, not silly little programs that just
say hello, world, or hello, David. What if I now started
updating past examples to do client-side form validation? In the past, a couple
of weeks back, when we did like the Frosh IMs
website, or really any website that submits data-- maybe CS50
Finance, if the user doesn't cooperate and doesn't give me a valid symbol
or doesn't type his or her name or password or the passwords don't
match in the case of registration, the data gets submitted
to the server nonetheless and then your Python code thus
far has been using an if condition or l if or whatever to check if the
user provided the data that you expect. And if not, you apologize
to them in some way by just printing out some
message to the screen. That's a lot of work. If you can anticipate
that something is wrong, why bother sending all of that
data or lack thereof to the server, letting the Python code
figure out what's wrong and then wait for this
response to get back, even though frankly, it happens pretty
fast on today's internet, certainly on campus. That's a lot of unnecessary
work if you have a programming language
like JavaScript that allows you to run code in the browser. Let's open up an example
that we did in the past wherein we just have a
form that asks for a user's name, their password,
their password again, and then has a checkbox
by which they can agree to some terms and then a Submit button. And you'll recall that in the
past we might have used something like this to have them register. And then we said, no, not really,
because we didn't actually have a back-end at that point. But a lot of things can go wrong when we
present the user with this many things to do. Now we know from Python,
we can catch these things, and we can apologize and display
an error message on the screen. So we have all of that
program added capability. But what if we could create
a better UX, user experience. A lot of websites do
fancy things these days like, they don't
actually submit the form and then show a big
erroneous message with a cat. Instead, they just show
the text box into which you were supposed to type a value into
in red, or green if you got it right. Or a little alert
message saying, you need to give us a longer password,
or your name, or your email, or your passwords don't match. But you can do all this
instantly on the client side, if we somehow can hook into this HTML. So all of these inputs can
be uniquely identified, especially if we go at our own IDs. So let's see if we can't
take things up a notch and actually write some code
that validates a form like this. I'm going to go ahead
and do the following. Inform 1 dot HTML, our next
version of this program. We'll start with where I
began, with just a simple form. But below this form, just for
now so we can get things started, I'm going to go ahead
and have a script tag. I'm going to declare a variable called
form and call document dot get element by ID quote unquote registration. Why? Well, I'm going to go ahead up here
and add an ID that equals registration. And again, here I'm using
double quotes in HTML, even though both single quotes
or double quotes are allowed. Down here I'm using
single quotes, mostly just to be conformant with convention. But you can certainly stylistically do
whatever you want with both of these. Now I'm going to do form,
which is just an HTML form, and say on submit, get function. So in other words, hey, browser,
when this form is submitted, call this anonymous function. But again, the fact that
the function is anonymous really is not an interesting detail. It just means it has no name. This is the chunk of code that will
be called when this form is submitted. All right. What do I want to do? How about this. If form, its e-mail field
has a value that equals equals quote unquote, that's a problem. Let me go ahead and just
alert the user, missing email. And because we don't indeed want the
form to be submitted, let me go ahead and return false. Else if, form dot password
equals equals nothing-- the so-called empty string--
then let me go ahead and alert the user that
we're missing their password. And then let we return false so
that the form does not go through because it's not ready to go through. How about else if form
dot password dot value. Oops, and up here I need value as well. Otherwise you get the
element from the DOM, you don't get the value
inside of that rectangle. Else if form dot password
dot value does not equal form dot confirmation dot value. And why confirmation? Well, if I look back at my HTML,
the first field was called e-mail. The second field was called password. The third was called
confirmation, even though it's also a password field, because that's
where I want the user's password again. But if those passwords don't
match, let me tell the user, passwords don't match
semi-colon return false. Now wait a minute, my color-- my
syntax highlighting is all messed up. Why? So this is a common gotcha. If I just want to use
English grammar in this case, don't is the right spelling there. But because I have quotes
just like in C or in Python when you've used double quotes
inside of double quotes, you're going to confuse
the program in this case. And so I need to escape this. But as in other languages, escaping a
back quote here is as simple as this. Or if you don't really
like that because it just looks a little ridiculous
and a little harder to read, we could switch to double quotes here. But again, just because I'm using
single quotes everywhere else, I'm going to stick with
single quotes and escape it. But again, you could make
an argument either way. Ouch. There's still that checkbox. And that checkbox, let's
see, was called agreement. So it turns out in JavaScript
you can express that as follows. Else if it is not the case that the
form's agreement checkbox is checked. So it turns out,
associated with checkboxes in JavaScript is a
property called checked that's going to be true or false. So if that's not checked, I'm just
going to tell the user as much. Checkbox unchecked,
and then return false. Otherwise, if none of these checks
fail, and I get all the way through all of these if's and else if's
and nothing seems to be wrong, you know what, the form is ready
for submission, return true. And so now it actually makes
a little more sense perhaps, to return false or return true,
because in all of these erroneous cases you want to return false. But if everything's OK, by default,
we're just going to return true. And the browser's default
behavior in that case is going to be to go ahead and
submit the form to the server. So let's try that. Let's go into form 1 dot HTML. Notice that if I zoom up here,
we have more fields than before. E-mail, password, password,
again I agree in register. So let's try this. Let me go ahead and
say, no, I'm not going to give you any of this information. So let me click Register. Missing email. All right, fine. I'll cooperate and give you at least
my e-mail, mail in at Harvard dot edu. Let me click register
now-- missing password. Now there's the
additional checkbox there because now Chrome, or
your browser more generally thinks that, maybe this
website's buggy or it's being malicious or annoying at best. Let me not check that box, otherwise
none of the rest of the demo will work. All right. I'll give you a password. Register. Passwords don't match, that's
because I didn't type it again. So let me type the same
password again over here. Nice. Ah, checkbox unchecked. All right. Agree, register. Ah, and it even wants to save
my password, but not really. So where did this actually go? Well just to show you what's
going on behind the scenes, notice that the action attribute
of the past couple of forms have been slash register. Well it turns out with today's examples,
I'm actually currently running Flask. And inside of there I
have a couple of routes. We're going to use one
of those in just a bit. For now I'm just using this one here. I have a route for slash
register, that calls a function register that simply renders
a template called register dot HTML. So where did that text come from? Again, this is just stuff
from a couple of weeks back. If I go into registered dot HTML in my
template's directory, it's just that. You are registered. Well not really. So we're not focusing on the back-end. We're not focusing on Python. We're not focusing on Flask. But I do have it running right
now, so that we can see what does happen if the form is submitted. But that could be any
server in the world. It could even be Google if we're
building that search engine again. I just need something running there. Let me go ahead and show you just an
alternative take on this form, version two, that does things using jQuery. Again we won't dwell as much on this. But do get familiar with the syntax,
because you'll see it everywhere online. This says, hey, browser,
when the document is ready, go ahead and associate
this anonymous function with the submit handler of
the form with this unique ID. And then here a slightly different
syntax by which you can select fields on the web page. Let me wave my hands at that for now. Because again, you can go with
the DOM-specific functions we've been using thus far. Or when the time comes,
just read a little more closely some of this code here. But this is the
equivalent code in jQuery, which is just a library that just gives
you different ways of expressing things in JavaScript. But this form is pretty ugly, right? Like, this is really not
something to write home about. This also does not
suggest the best error handling if every time
I do something wrong I just get this ugly looking alert. Can I make something prettier? Well we certainly could
with JavaScript alone. And I could certainly
write some HTML, some CSS, and a whole bunch of
JavaScript myself and get a much better UX, user experience. I could get a much better
aesthetic to the site, so that maybe we print some
red text or green text, depending on whether
the user is cooperating. But that's a whole lot of work. And honestly, there are millions
of websites out there these days. Surely someone else has had
to validate a form before, and he or she has done
it with JavaScript, and he or she has been nice
enough to make their code freely available as open source online
so that the rest of us making the other millions of websites
can stand on their shoulders and not reinvent that wheel. And indeed, just like in Python,
there's lots and lots of libraries, and lots and lots of frameworks, so
in JavaScript it's there the same. So it turns out, if I
go into form 3 dot HTML, I have a slightly prettier version
that is using the bootstrap library. There's no banner or
menu or anything like. I kept it pretty simple here. But just by adding a little bit of more
HTML markup, and a little more CSS, can I stylize my form to be much prettier. Indeed in CS50 Finance we had much nicer
forms than the previous few examples because we used Bootstrap,
though you could use most any other library that's
out there as well just to make the forms a little prettier. But I'm adding one additional library. This one that supports Bootstrap, so
that if the user doesn't cooperate with this version three, notice
they can't even click Register without the following happening. Red email, please fill out this field. Red password, please
fill out this field. And by the way, not long enough,
because it's not even any characters. Password again, please
fill out this field. Checkbox unchecked. So you can immediately give
much prettier output to the user without using that sort of a
lame prompt that's just going to pester the user again and again. And even though there's
still an opportunity, I think, to improve the aesthetics,
this is much more akin to web 2.0. So modern websites that are using these
and other libraries to just create better user experiences. So let's cooperate now. M-A-L-A-N. And notice, whoops. That's not even my email address. The error message now goes away
entirely because the field is not blank. All right password, 1, 2, 3, 4, 5. OK. It's now no longer telling
me to please fill it out, but it's still not long enough. All right. 1, 2, 3, 4, 5, 6, 7, 8. Eight characters seems to be enough. All right. Let me go ahead and type in foo bar baz. Passwords don't match. OK. 1, 2, 3, 4, 5, 6, 7, 8. That one now matches. And finally, I agree. So we get so much
functionality for free. We could implement all of that ourselves
using just the primitives we've looked at thus far, just our
understanding of where JavaScript has to go in the web page, just our
understanding of how to write functions and if conditions and for loops
and while loops or whatever. But it's not interesting work. If I'm trying to build a finance website
or a final project more generally, I don't really want to
focus on form validation. I want to focus on my own intellectual
property, my own ideas, my own project itself. And so in form 3 dot HTML
is a few additional things. Not only have I included the
Bootstrap library at the top, as you might have noticed in CS50
Finance, as well as the latest version of jQuery, and Bootstrap's
own JavaScript, I've also included-- and I found this just
by Googling around. A very nice person made his or
her code available at this URL. And there's documentation online. And he or she based it on
Bootstrap so that if you want to use Bootstrap and have
pretty error messages, that you don't want to think about creating yourself. You can use their library. And indeed, notice
how I changed my HTML. It's a little more verbose
to be fair, but you'll remember some of this from
maybe your log-in form or registration form from CS50 Finance. Most of this just comes from
Bootstrap and you're using the classes that they tell you to. But there's a few
fields here that control how this new library is
working for form validation. Notice, on my input, not only do
I have a Bootstrap class, which I just read from the documentation
and in the unique ID, I've got a required attribute. And by saying required, that's
a clue, not only to the browser, but also to this library
specifically that I should not be allowed to submit this form
until this field is filled out. Now notice down here, input
class equals form control, which is just a Bootstrap thing. Data dash min length equals 8. This is how that library knows that
I, the programmer of this page, wanted the user to type in a password
that's at least eight characters long. It turns out, in HTML5, you
can prefix, or rather you can invent your own attributes. Any attribute that starts
with data dash, and then some other sequence of characters
can be your own custom attribute that does not come with HTML itself. So a lot of libraries,
this one among them, use those data attributes in
order to configure themselves. In this case, it's configuring itself
to use a minimum length of eight. That's also required. Down here it's a little more advanced. But I just figured this out
by reading the documentation. Down here, notice, I've got that
confirmation text box that's also an input with a Bootstrap
class data dash match equals hashtag password. So this is-- and you'd only know this
from the documentation of the library-- this is how the author decided to let us
configure this text field in such a way that it must match this password field. And you know what, data match
error-- I would only know this too from its documentation. But the way the author designed his
or her library is if there is an error and the passwords don't
match, this is the read text that I want the library
to display on the screen. And though it's cut off,
this field too is required. And meanwhile the checkbox, if we
scroll to the last feature here, that too has been
prescribed as required. And notice, I've also added some divs
here and there, help block with errors. This is not some fundamental HTML thing. This is, again, just the
author of the library who's decided that wherever
you, the programmer, put a div with these classes,
the library will plop those read error messages. So they don't have to be right there. You could centralize them
at the top of the screen. You could put them in a banner at
the bottom or wherever you want. You have some programmatic control. And so this library is
implemented in JavaScript, though we haven't written any additional
JavaScript code because this author has been pretty clever and is
using special HTML attributes to configure his or her library. And it suffices, at the top of the
page, simply to include that library. And it has been written, probably with
a line of code like document on ready. Like when the document is ready,
search the HTML for those special tags and make sure that this form
shall be validated accordingly. So this is what's really exciting
about JavaScript and Python as well, and any of these higher level
languages is just how many features you get access to for free, without
having to implement them yourselves. How you use them is
going to totally differ. And indeed, part of the process
of making a final project or a web application or a mobile
application in general, is using a fundamental
understanding of programming and loops and conditions and functions
and so forth, but then googling around and looking up
documentation that empowers you to do other things
with that understanding, using other people's code. So again, the goal is not to
absorb all of this en masse, but rather to realize the fundamentals,
the ingredients by which we can configure and do things ourselves. Let me go ahead and
propose now this example. So back in my day, when I first
learned HTML, for better or for worse, mostly for worse, there was a blink tag. So someone back in the '90s
thought this was a good idea. Let's empower people to have blinking
text on their screen for everyone to see. There was even worse,
perhaps, or as bad, like a marquee, where you could
scroll text across the screen from left to right or right to left--
I forget which direction-- and that too felt like a good idea at the time
that has since been removed as well. But it invites an opportunity, I dare
say, to reimplement this feature, even though browsers do not
support the blink tag now. But I can figure out how to do this. Right. What's going on? There's some big text on the
screen, that's roughly centered. So I can probably use some CSS for that
to make it big and bold and centered. It's blinking on and off. Well what does it mean
to blink on and off? Again, reduce this to first principles. What capabilities does a browser have? Clearly to display text, also
to display colors, we have seen. So maybe the act of
blinking, hello, world, is really just a matter of hiding it,
showing it, hiding it, showing it. Maybe there's a way to do that. And indeed there is in CSS. Or maybe it's still there, it's just
going black to white to black to white to black to white. So it feels like, so long as I have the
ability to kind of sit-in a loop, maybe even an infinite loop if this just
keeps going, and every second or so, every half second go ahead and change
from black to white, to black to white, or hide show, hide show. I just need to kind of commingle these
capabilities of JavaScript and CSS. And right now I can't
stare at this anymore. So let's go ahead and open up blink dot
HTML and see how I implemented this. So here's a body tag. Here's a div tag that
has unique ID greeting. And then, hello, world as my text. So the HTML to this
page is super simple. If I scroll just a little bit, this is
why that text is now centered and big. So 96-point, I decided,
pretty arbitrarily, just to make big centered
text on the screen. What about the JavaScript code? It turns out with
JavaScript, just as you can gain access to data in the page, so
can you gain access to CSS in the page. And in fact, even though we
won't dive in underneath the hood of that library for Bootstrap
that made our text fields read, how did it make our text fields read? Well, if we really looked
underneath the hood, that library, upon seeing that you didn't type your
name or your passwords don't match, it changed underneath the
hood the CSS of my web page to go from default colors to
red or to green or to whatever. But how did it do that? Well, it turns out that browsers
have the following capability-- one, to declare functions. And we know that already. Two, to get elements by their ID. And we know that already. And here I'm just declaring
a variable called divs, so my code's a little more succinct. But it turns out that
elements on a web page, certainly divs, which are just big
rectangular divisions of the page, have a style property
associated with them. And a style property, in this case,
lines up with that div element, CSS properties, if any. And if I want to change the
visibility of this div style, and visibility happens to be a CSS
property that we haven't necessarily used, but if you googled around
you'd see an online reference of available CSS properties. If the visibility of this
element equals equals hidden, I'm going to make it visible. Else, I'm going to make it hidden. So if visibility is
hidden, make it visible. Else, if the visibility is
visible, make it hidden. For whatever reason, the opposite
of visible in CSS is not invisible. It is hidden, which makes
this a bit of a mouthful. But this if block here, this if else,
really is just saying, if visible, make it hidden. If hidden, make it visible. So just toggles the state, so
to speak, from one to the other. But why would this function
operate more than once? There's no loop. There's no for loop, no while
loop, no do while loop, nothing. Look at this last line of code. It turns out that in
JavaScript you have the ability to do things again and again with
a clock that's running inside of your computer, essentially. Window dot set interval is a function
you can call in JavaScript that says, hey, browser, call this
function every 500 milliseconds. So couldn't quite glean
it before visually. Every half a second, call this function,
call this function, call this function. And notice again, as before, when I'm
passing around a function by its name, I don't want to do this. If I said, blink open paren close paren,
that would call the blink function, and it's only going to call it once. I instead want to pass
this function by its name. In C we would call this
a function pointer. In JavaScript we call it by reference,
passing in the name of this function to set interval. So that set interval knows
later what function essentially to append parentheses to, so as
to call it every 500 milliseconds. Now how that's
implemented, I don't know. I don't care. It's abstracted away from me. But set interval is a function that
comes with the browser that probably has some kind of
infinite loop that knows to check every 500 milliseconds
what's going on underneath the hood. So this is to say, in JavaScript,
we have the ability to control CSS. And indeed, if we now
think back retrospectively, that must be how that bootstrap
library was doing the form validation and making my fields red
when I did something wrong. So you have another feature in
JavaScript called local storage. This is relatively newer,
but it's a way, on a website, of storing information for the
long term, in a user's browser. So in CS50 Finance, and in Web
Programming with Flask more generally, we had the ability to
store data in sessions. And that's fine. But sometimes it'd be nice to store data
locally inside of the user's browser so that you don't have to remember
states on the server side. So that you don't have to contact
the server to get that information. And so this is particularly
common in web applications that you kind of want to
be able to run offline. Right. It's increasingly convenient,
especially on mobile devices, to be able to run those web pages when
you're not connected to the internet, when you're underground or
on a plane, so long as you loaded the page in advance. So with local storage, you actually
have exactly that feature in HTML to store information locally. So let's take a look at
this page does and then we can deconstruct how it's doing that. If I open up storage dot HTML, notice
that it says in the top corner-- and I'll zoom in, just the number 0. If I reload, and reload, and reload--
and to be clear, all I'm doing is reloading by using my keyboard--
and reload, and reload, and reload, the counter is going up. But why is that happening? Well, let me go back into the IDE and
focus on these lines of code here. If it's not the case that
there is an item called counter in this special global variable called
local storage, then you know what, set an item called
counter equal to zero. So local storage is really just a
JavaScript dictionary-- an object that's accessible globally to you. Now we've not seen this before, and
it's not all that common to need, but I did it just so I could display
something dynamically in the web page. You can call it document dot
right, which is similar in spirit to prints in Python or print F
in C. But, again, we don't really print to the screen as
much as we change values or HTML as we've done in the past. So we won't really use this too often. But for now, I just want to write local
storage dot get items return value when I ask it for counter. But then, and this is the key detail. Every time I print or write
that value to the screen, I want to go ahead and reset
the item, called counter, to the result of calling
parse ent on local storage dot get item dot counter plus 1. So long story short, local storage is
going to store key value pairs for you, but as strings. And that's fine, because like quote
unquote one, quote unquote two is still useful, but parseInt is
a function built into JavaScript that's going to allow me to
parse this string that I get back and convert quote unquote
something to an actual integer so that I can then add
1 to it and set it back. So this example is only to
say, there is an ability to store data locally in the browser. And this is a fundamental alternative,
especially for offline mobile apps, to storing data in sessions
on the server side. But things get much cooler, quickly. In fact, let me go into
geolocation dot HTML, which creepily wants to know my location. Not my location in the
sense of the IP address. I'm seeing the IP address
of my computer here. You'll see something with CS50
dot IO or the like most likely. But this is standard prompt that
Chrome and Edge and other browsers will trigger if a browser is running
JavaScript code that is creepily trying to get your GPS coordinates. So it's a good thing that there's
privacy defenses in place. And you really see this
on Android and iOS, which don't let apps do anything
without your permission typically. But I'm going to go ahead
and let it know my location. I'm going to go ahead and click
Allow, and see what happens. It's taking a moment. The computer is thinking. I am apparently at GPS coordinate
42.38 comma negative 77.11. So that's my latitude and my longitude. Now that's not all that
interesting unto itself, but let me go to something
like maps.google.com. Turns out you can search
by latitude and longitude. OK. We didn't have to go very far to
triangulate my position there. There we are, roughly in the middle
of the building, Sanders Theater here in Cambridge. So that's kind of cool. This is all to say that a browser
can apparently infer your location. Now why is that useful? Well if you're building a website
that is designed to show maps to the user like Google Maps or
MapQuest or Yahoo Maps or Bing Maps or any number of tools,
it's kind of a nice feature to just let the user see where he
or she is in the world by default, rather than just showing
them the generic United States or the whole globe. It'd be kind of nice to at least
show them the general area. And indeed, that's exactly what
happened when I went to Maps.Google.com. It knew, within some range, where I was
already, even before I typed this in. If you're implementing Yelp
or some restaurant review site or something like that where you want
to be able to find something near you, it's nice to not have to have
me, the human, type in my GPS coordinates, which I
certainly would never know. And it's nice to not make me type in
Cambridge, Massachusetts or New Haven, Connecticut or whatnot,
which is in 06511. Rather just let the browser actually
figure out where I am, so long as I consent to actually doing that. I did get that right this time, right? OK. So why is this a useful thing? So this, of course, is useless. Like, who cares what
GPS coordinates I'm at? Not all that useful unless you want
to target me right now in a map. Rather, we can do
something more interesting. So we need the ability
to actually get a map. Thus far I have no ability to
pull down pictures of maps. But what if I could make a website,
that after downloading some HTML and CSS and JavaScript, what if, ala Google
Maps, I could go get maps of Cambridge, go get maps of New Haven or
wherever I am in the world and display them to the user. And better yet, what if I
could then use the drag event and actually get more of that
map-- whatever's off the screens above, to the left, to
the right, or below me, when that user clicks and drags. Drag being one of the
events we can listen for. Well it turns out, as mentioned
earlier, that browsers today support AJAX, which is formally called
asynchronous JavaScript in XML. But people don't really
use XML for this anymore. They use JSON, JavaScript
Object Notation. And this is ultimately referring to
the ability of modern browsers today, upon already having downloaded a
web page and CSS and JavaScript, to make additional HTTP
requests from browser to server, without having to reload the whole
page, and certainly without the user having to click Reload and then see
a big blank screen for a moment, after which they see content. It can all happen dynamically. So Facebook Messenger,
Google Maps, Google Gmail and so forth-- any
number of websites you use today, certainly the most modern
of them, all use this capability. So how do we go about using it? Let me go ahead and open up a
file called AJAX 0 dot HTML. And here is now where honestly you
want to use something like jQuery. It tends to still be super popular. There's other libraries
that can do this for you. But what you don't really want to do
is start writing native browser code, so to speak, that's specific
to Chrome or specific to Edge or specific to any number of browsers. One of the nicest features
about libraries today is that there are so many stupid
cross-browser incompatibilities whereby reasonable smart people can disagree,
and so different companies have implemented browsers ever so
differently in terms of JavaScript, in terms of HTML, in terms of CSS. So literally, you might build
a beautiful looking website. Spend hours and hours getting it to look
perfect on your Google Chrome browser, and you open it up in Internet
Explorer or Edge or Firefox or Safari, and damn it, it doesn't look right. Something's off aesthetically. It doesn't even work maybe. It doesn't even load. And so a lot of the process
of getting websites just right is certainly building
them in the first place, but then that last stretch
is really about making sure in testing that things
work on multiple browsers. So this is all to say, this is when
it gets really useful to use something like jQuery, because stuff like AJAX
does get relatively simpler as follows. Here is a web page that's including
the jQuery library up top. Inside of my own script tag now is
a commented function called quote, similar in spirit to what we
might have wanted in CS50 Finance if we were using
JavaScript at that point. Notice what I'm doing
in JavaScript though. Give me a variable called URL. Set it equal to quote unquote slash
quote, which looks like a route, question mark symbol
equals, closed quote, plus which is concatenation,
the value of the symbol field. Now what is this? Let me fast forward to the
HTML down here in AJAX 0. Pretty simple web form and
I'm doing it old school here. Form on submit, call the
quote function return false. And then have an input
whose ID is symbol of type-- and it's a little cut off-- is text. So what does this page look like? If I go over to AJAX
0, and open this here, it's a very simple web
page that simply has a text field with a
placeholder that says symbol, and then an HTML submit
button that says get quote. But I want this site
to do is the following. If I type in GOOG for
Google's stock ticker symbol, I want to know right now
that it's worth $772.02. If I type in something like
Microsoft, that's $59.705. So I'm getting another digit
of precision from Yahoo Finance as it turns out, as we'll see. Netflix, get quote, $123.3405. So in this case we're really
getting some additional precision. But all of that is
immaterial at the moment. What I really just care
about is how this is working. So again, when that form is submitted,
the quote function is called. And then it returns false. And that's just so that it doesn't
get submitted to a back-end, because there is no
back-end at the moment. Rather, I'm using JavaScript to
talk to my back-end as follows. Var URL gets this URL equals this value. And this value is whatever
the user just typed in. Me, like Google or Microsoft or Netflix. So this a way, notice, of constructing
your own path for an HTTP get request. If you think back to week
six, we know that you can contact websites ultimately
via this route, like slash quote. The question mark is what separates
the route from the HTTP query, or the request parameters, the HTTP
parameters that you're passing in, one of which I've
decided to call symbol. And now notice what the jQuery library
does for us, pretty straightforwardly. jQuery comes with a
method called get JSON. Now what is this weird syntax? Again, this is just JavaScript
being cool, or jQuery being cool. The dollar sign is literally
a synonym for an object called jQuery, a global
object that happens to exist because of this line of code. But the author of jQuery, some
time ago realized, dollar sign is actually a valid character
for a variable name, which is not the case in C. So you know what, I am just going to
call my library's global object dollar sign. Why? Well one, it kind of looks cool, but
two, it's just much shorter to type. You don't have to actually
write out the whole word. But that's all. There's nothing syntactically
interesting about this. It's just valid variable symbol. Get JSON does that. It contacts a server at
a certain URL and expects to get back a JSON object, which
we saw an example of a bit ago. And what does it do? It will call a function,
in this case anonymous, but that's an immaterial
detail at this point. And it will pass to that
function a reference to the data it gets
back from the server. So again, get JSON somehow
figures out underneath the hood, how to make an HTTP request to that URL
that's passed in as the first argument. And when the server finally replies,
this anonymous function is called. It's passed that data. And then we call alert
on data dot price. So what is inside of that object? Well I can actually simulate this. Right. If you understand HTTP, you
can do all of this yourself. My IP address happens to be on
my local machine, 127.0.0.1. And then I'm on port 80. Your URL might be
different, on CS50 IDE. But what I do know is I
can construct my own HTTP request by just doing slash quote
question mark symbol equals NFLX and Enter. And notice what comes back. If I zoom in on that, this is
JSON, JavaScript Object Notation. Why does it look like this? Well, the world just
decided, we need a way of standardizing how you get back data. It's useful to get back data
in terms of metadata keys, and the actual values you care about. So the world decided
that JSON data is going to start with a curly brace,
end with a curly brace. It's going to have a
whole bunch of key value pairs, which are separated by colons. Each of the values, each of
the keys rather, is quoted. Each of the values is
quoted if there are strings. Otherwise if it's a number you
can just write it like that. Commas are separating each
of those key value pairs. And again, you must use double
quotes in this context, which is a long way of saying, this is
what my slash quote route returns. This is not a web page. This is not my quote route from CS50
Finance, which was must prettier and it actually had CSS
and HTML and it said, a share of Netflix costs such and such. This is just raw data. And this is where AJAX gets compelling. AJAX is the use of raw data like
that, you have programmatically requested from browser to
server, after the original web page is already loaded, because you
want to get more data for the user, perhaps in response, as in
this case, to his or her input, like when I typed in Netflix
or Google or Microsoft. This web page isn't all that
pretty though, of course. Right. It's ending up just using that alert. And it probably is the case that we
can do things a little bit better. And indeed we can. Right now, again, I've
kind of regressed. I should not slip into this habit. It's fine for perhaps a
lecture demonstration, but let's clean this up right now. If I go into AJAX 1 dot HTML, notice
I've gone in and cleaned up my HTML. No longer do I have some hackish
call to a function semi-colon return false inside of the value
of an HTML attribute. It's just bad design to do that. It's fine to sort of get warmed up. But let's get rid of
that, clean up my HTML, and now relegate everything
to the top of a file. I'm still using jQuery, but I
need one additional line, recall. Now I need this line here. Because a browser reads
my code top to bottom, I want to make sure that this code is
not executed until the page is ready. Before, I didn't need to worry
about this, because by the time the browser got to my HTML, saw the on
click or on submit attribute, rather, and saw the code to execute, that's
fine because everything else had already been loaded. But in this case, I have my
code up front before the HTML. So I have to say, hey, browser, don't
do this, until you're actually ready. What do I want you to do? I want you to, as before,
register a submit handler, calling in this function,
calling get JSON as before, and then return false here. As an aside, let me
point out just one thing. It turns out that putting your
JavaScript code in your file, that too is not generally good design. Certainly as your
pages get more involved and your code gets more
complex, just like in CSS when we factored out
our CSS, we should be able to factor out our
JavaScript code too. So actually a better practice longer
term and certainly with projects would be to do something like this. To take all of this
code that I've written, save it in a file called whatever,
scripts dot js is perhaps common. And then in my HTML page, don't just
have this big open tag and closed tag. Instead, go ahead and say something
like this, scripts dot js. In other words, have
a URL or partial URL that says to my browser, hey, browser,
besides the page you're currently reading, go get this file as well. Execute any code in there and then
proceed to run whatever's inside. All right. But-- but, but, but, I bet
we can make this even cooler. It is pretty, pretty lame
to keep using these alerts. What if instead we had
this capability as well. In AJAX 2 we have this example here. Let me go ahead and zoom in. And let me go ahead and type in NFLX
for Netflix and click get quote. I don't want that damn alert
anymore, which is pretty hackish. And again, it's going to look ugly
and different on different browsers. Let me click, get quote. Woo, hoo, hoo. Very nice. So this time it seems to have embedded
the response in the web page itself. And that's going to change GOOG, get
quotes, aka Alphabet, or Microsoft, or whatever other company. Somehow we're changing the page. In other words, now we're not just
using this out of band alert function. We are changing our DOM. And in fact, let me do this. Let me reload the page to
get back to original state. Let me control or right click
on Chrome and go into Elements. As you may know here, notice
that here in my web page, apparently is a paragraph
that we can't see, because it's got no text inside of it. It's just an open tag and a closed tag. But notice the unique ID called quote. And notice what happens. I'll have to zoom out to see this. But notice what happens. If I type in like GOOG
and click, get quote. Don't watch the top. Watch the bottom. A triangle appeared, because now
there's something inside of that. So that sentence was
dynamically inserted. Let's try this again. Let me try with Microsoft click, get
quote, and my page's HTML is changing. And it's also flashing it
in purple just so Chrome can draw your attention to it. How about Netflix, get quote. So this is where we're really
now tying everything together. We have the ability with JavaScript
to get values from this field. We have the ability with JavaScript via
AJAX, which is just a use of JavaScript to get more data from the server. We have the ability with
JavaScript to change my DOM, my web page, which really just means change
the HTML in that page, not permanently. None of this is happening on
the server, these changes here. It's just in my own local browser. And indeed if I reload,
the changes go away. But if you think of this sentence here
as being like another row in your Gmail inbox, or another message in
your Facebook chat window, that's all that's happening. Now I might be just clobbering,
that is deleting and changing the previous sentence. But there's nothing
stopping me from just writing every individual message to
the screen again and again and again. I don't have to overwrite
it as I'm doing here. So how do we do this? So if I go ahead and open up now, AJAX 2
dot HTML, it's almost entirely the same as before, except I am
now embedding inside of my DOM via these method calls, the
actual data I want the user to see. Indeed, this is saying, hey,
browser, go get the HTML element whose unique idea is quote. Call a method associated
with that, called HTML, which we haven't seen before. But it just literally changes
the HTML of that element to be whatever I pass in as an argument. It's a long argument, but
that's just the concatenation of a bunch of strings-- A share
of, plus data dot name, costs, dollar sign data dot price, period. Now, what is data dot name? What is data dot price? Well data is just the argument
to the callback function, which was, again, the anonymous function
that I passed in the second argument to get JSON. Data dot name gives me the name therein. Data dot price gives
me the price therein. If I really wanted the
symbol again, I could do data dot symbol, based on what
we've seen inside of that object. But, just like in C, structures, we
just use the dot operator in JavaScript to get at the properties of
the data inside of an object. Now again, the only way I would
know how to do this with jQuery specifically is by looking
up its documentation. And I would know that if I want to get
JSON I called dollar sign dot get JSON. I give it a URL, which
I've constructed here. And it can be just the
relative path if I'm assuming that page is
on the same server, that route's on the same server. And then the second argument
should be a function. It can be anonymous, doesn't
have to be anonymous, doesn't matter so long as that
function, per jQuery's documentation takes at least this one argument,
which I could called data. I could call it anything else. But the documentation for jQuery says,
hey, user, I will pass to this function that I will call back as soon
as I have some data for you, whatever the server gives me. And the server has given me
a name, a symbol, and a price all inside of this object, this
JavaScript Object Notation. Finally, this last line is
just kind of nice to have. I realize, you know what, it'd be a
nice feature if after the user searches for a stock quote that
we not only see it but we also reset the
form to be a blank value. So notice that this symbol
refers to a unique element, the unique ID of an element that's
not a paragraph tag, as this one is. This is an input field. And input fields don't have HTML inside. They literally just have textual values. So I use dot val instead,
passing it in an empty string. But the net effects, notice, this
time with that line is the following. Once I've added that line,
I have, GOOG, get quote. And notice the field
clears itself this time. Once I have Yahoo here, get
quote, it clears itself this time. So by adding that kind of
line to this example, which just happens to be
using a bit more jQuery, I now have the ability to
reset the field as well. All right. Now where was that JSON
coming from though? Well recall in application dot pie, we
had a couple of routes, one of which was register, which was
not all that interesting. It just rendered a template
called registered dot HTML. But the other route, which we
only glanced at a moment ago, was slash quote. This one's a bit more involved. And I've actually omitted
some error checking to keep the code a little tight. You'll see more error checking
and more code inside of helpers dot pie from CS50 Finance. But long story short,
these five rows of code simply contact Yahoo Finance, passing
in that symbol that's been provided, get back the response in CSV, convert
the CSV to JSON, and return that JSON. And so this is the code
that responds to get requests of the slash quote route, which
is what my JavaScript code is using. So again to be clear, we
don't have new capabilities necessarily with rendering this
financial information that we didn't already have with Python. What has changed is, now I
am doing that HTTP request, and I am changing that
web page client-side. I'm contacting the server, yes,
but only for additional data, only to get that JSON data, only to get the
name, the symbol again, and the price. I am not asking the
server, hey, server, could you also give me a brand
new web page with HTML tags and a body tag and a head tag
and a title tag and all that. I'm not asking the server
for a whole darn new page as Jinja might have given me by using
a template in, say, CS50 Finance. All I'm asking the server for, is
please just give me a stock quote, and I'll take it from there. And so now we have, frankly, a
much more responsive interface, because I'm requesting
less data of the server. That's going to be a smaller
number of bytes, which means it's quicker to send it back to me. And I already know how to display it
so there's just a lot less work to do. So in this case, it would seem
that the introduction of JavaScript hasn't changed what I can do, but
certainly has changed how I can do it. But it's easy to be misled. In our previous examples, when
we did some form validation, recall that we could similarly
validate that the user typed in the right thing or the wrong
thing, client-side, without talking to the server. And the result was prettier for sure. We had a little red text and so forth. Though technically we could
do that server-side as well. It's just easier to do it client-side. But it was faster. I mean, we don't really notice
on the wonderful internet speeds we might have right here on campus. But certainly on mobile devices,
if I took out my own phone, it's going to feel slower, certainly
if you're on a slower connection it will certainly be slower. But it's not sufficient to just
get rid of the server altogether and only do client-side. In fact, it turns out, an adversary,
whether maliciously or just accidentally, could do
something like this. Recall that this form here
asked for my email, password, password again, and an agreement. And if I don't cooperate,
it yells at me-- missing email, missing
password, passwords don't match, checkbox unchecked, or whatever. But it turns out that hacking
JavaScript, turning it off, is as simple in Chrome or any other
browser, poking around your settings, as I'm doing here, scrolling
down to an option called, in this case, disable JavaScript. And now after simply
disabling JavaScript, woo. I am registered. Well, not really. But I am not registered. I did not give an email address. I did not give a password. I definitely didn't give
it the same password again. And I certainly didn't agree
to those terms and conditions. So JavaScript is really
just a client-side nicety. It gives us amazing new features. It gives us amazing responsiveness. It is not an alternative
to security checks, to validation of data on the server. All of those lines of code from CS50
Finance, all of the lines of code you might have on the server in
Python or whatever language that are validating user submissions to make
sure they're cooperating, apologizing or admonishing them accordingly, if they
don't cooperate are still necessary. So it's a little annoying
that in order to benefit from this client-side responsiveness,
this better user experience, you have to now pretty much
invent the wheel in two places. In the client-side in JavaScript, on the
server in Python or whatever language. But that's the way it is. If you want to achieve
the best of both worlds. The security that you get
by actually doing something as close to your database
as possible on the server, and the nicety that you get, the
user experience that you get, and the immediacy of responding to
the user by using JavaScript alone. So it turns out, there
are some libraries that allow you to, on the server,
specify what fields are valid. And you can let the
library on the server generate the requisite JavaScript
code with which to validate your form. So long story short,
thankfully, other people have helped us solve this
as well so that you only do need to write the code once
if using the right library. But it's the principle that's important. In fact, too often on
poorly written websites, is it possible to circumvent some silly
checkbox or some requirements that's not really a requirement. It's really just a JavaScript
imposed request for data, if they're not actually
validating as much on the server. So realize that that need
on the server remains. All right. Back to that map. We have the ability, recall, to get the
GPS coordinates of where someone is. We have the ability, with AJAX,
to get more data from the server. And though the data we've gotten
this far has been stock data, there's nothing stopping us from
getting images from the server-- more and more images as might
composer ultimately a map. And indeed, let me go ahead
and open up the following. In map dot HTML is a relatively short
page that has a few characteristics. The top of my page. I've got some CSS. To be cleaner I could factor
this out to a separate file but I wanted to keep the demo
in lecture pretty succinct. So everything's in this one page. HTML, body and hash map. So the commas in the CSS
declaration here just mean, apply the following properties to
the HTML tag and to the body tag and to whatever element
has this unique ID. I want to make sure all three of those
are 100%, because by default your web page has no height. Because if you have no
content there's no height. But I want to make sure that my web
page literally fills the browser. And I don't want any white
margin around the edges. I want everything flush up against
the sides and the top and the bottom. So that's all this does for me,
nothing more than those aesthetics. Down here, in the body
of the page, notice that I have quite simply a div
that has nothing inside of it, open tag close tag, but that
has unique ID called map. This is really a place-holder
where I want to put a map. Down here I have my script tag. And I could have put
this in the head page. Really what I've done is
mimic one of the getting started examples in some of
Google's online documentation, so that if you'd like
to play along further, you'll see that this lines up almost
perfectly with some of their getting started exercises. Indeed, even the function name I
have here, INET map mimics theirs. And you'll see too, even though in
Python, or rather not in Python, in C, we generally put these curly
braces on the same line. You'll see that stylistically,
probably more common in JavaScript certainly to do it on
the same line here, even though the closing
brace ends up over here. Again, all that matters is that
you are consistent with respect to your own code and nice and neat. So what's going on
inside of this INET map function, which I know to
implement because Google told me to by reading its documentation. Go ahead and declare
a variable called map. Go ahead and instantiats--
it turns out that JavaScript allows you to create or instantiate new
objects, much like you can in Python. And JavaScript though,
in this kind of context, you need to say new, which says to
the browser, kind of like malloc, hey, browser, give me memory
four-- although we're not managing memory like we do at
a low level in C for a map. And Google dot maps dot map, you can
think of as a class in JavaScript that represents a map. Like literally a world map. It's not technically a
class in this case here, all the newer versions of JavaScript
will introduce that and other features. But this is Google's way of allowing
me to specify hey, Google, I want to map at the location
identified by this unique ID. So document [INAUDIBLE]
gets me that div, because its ID was quote unquote map. And hey, Google, here's how I
want you to configure that div. I want you to center a
world map at this latitude and this longitude-- which
based on some googling is apparently roughly the middle
of the United States, arbitrarily. Zoom level is four. I want to be able to see a lot of
the country, not the whole world because then it won't fill the page. But I don't want to just see
some middle state for instance. I want to be zoomed up higher. And I would know what number
to use by trial and error or from the documentation. Then I want two markers. I want one marker, one little
red pushpin on Cambridge, one pushpin on New Haven. And from some googling, I found
that the latitude of Cambridge is roughly 42.3762 and the
longitude is negative 71. And New Haven's 41 and
negative 72, give or take. And the map I want those markers
to be positioned on is map. So map is the key,
per the documentation. Map is also the name of my variable. A little confusing, but it also keeps
things clean because I mean what I say. So with just these few
lines of code, I have implemented a function called
INET map, whose purpose in life is to instantiate a map-- create
a map, and put it in this div. Then with these chunks
of code, I'm saying give me a marker, a little
pushpin, at this position. Give me another marker at this position. That's pretty much it. The only other thing I'm doing
in this page, notice, is this. At the bottom of the
file I have a script tag whose source value is this long URL. It's got a key, which I
signed up for earlier. And indeed, if you want
to play with this example, you'll have to go to Google's
documentation for the JavaScript API-- Application Programming
Interface-- for Google Maps and sign up for your own key, paste
it in there so that it actually works. But what's key at the end of
this line is this call back. This is just Google's
way-- it's completely a design decision of their own. But they have configured their
documentation and their back-end code base to say this. Tell us the name of your function,
because as soon as the Google Maps server hears from you, we will
call this function of yours, as soon as the Google Maps API is ready. And I keep saying API. API is just application
programming interface. It's a generic way of saying, someone
else has written code that you can use, and the API describes how you use it. Indeed, when I keep saying,
I've read the documentation, I've read the
documentation, I really read their API or some human-friendly
version there of-- a user's manual. And for instance, their API
prescribes that this special object map it takes in a reference
to the elements in which you want to put the map. Then it takes in an object as implied
by the curly brace and the curly brace that takes at least these
keys, the center of the map, and a zoom level-- or at least those
are the two keys that I'm using. Meanwhile, the API for
Google's marker specifies that you should also pass in an object,
per the curly braces, that gives it a map on which to put that marker,
that pushpin, and a position at which to put it. And I'm just doing that twice. So application
programming interface will mean a little something
different in real terms depending on whether you're using
Google or Bing or any number of tools completely unrelated to Maps. But it just refers to features--
functionality that someone else has provided that you can then integrate
typically into your own program. So what if I now visit Map dot HTML? What do I get? I get a map of the Earth,
or of the United States in this case, centered roughly
around the middle of your country. And then I have a marker here for
Cambridge, a marker here for New Haven. But, notice, this map has so much
functionality built into it for free. I can click and drag. And notice-- and if you
look quickly-- well now we are literally over
the edge of the Earth. So let's go back. If you do this quickly, you'll see that
those rectangular gray spots appear. And that's because, at
that moment in time, Google has not yet downloaded
the images, the pings or whatever they are, PNGs
for that part of the world. But, notice, if we do this. If I go into my Chrome tools
and open up my Developer Tools and watch the Network tab, notice what
happens every time I click and drag. Each of those rows in this table at the
bottom represents another HTTP request. And a lot of them, notice, are pings. So really useful when
developing JavaScript code is to watch the network tab because you
can see your own data or someone else's data coming back and
forth for you that's then somehow being used by your
JavaScript code to update the map. We in our previous example
were updating a price and a name of a company on the screen. But in this case, Google is clearly
updating images on the screen after having initially
drawn these markers. And if I now go to the
Elements tab here in Chrome, you'll see that script
tag that I had before, and this other script tag, which
contains my own JavaScript code. But notice this. Div ID map, which was previously
empty-- let me zoom in. If I expand this triangle, apparently
inside of that div now is another div. Inside of there is another div. Inside of there is a
whole bunch of divs. And indeed, this is what
Google's Maps API has done. They have dynamically generated,
using JavaScript, all of this HTML. I didn't write any of that. All I gave them was an empty
div with a unique ID of ID, and the Google Maps API, upon
being told where to put this map, has filled in that blank so
to speak with a whole lot more content from its server thanks to
JavaScript and thanks to this technique known as AJAX. Meanwhile, we can zoom in
and out, because in addition to that drag handler that you see
there, there is the plus sign over here. There's the minus sign over here. There's the satellite map, where it's
going to re-download all of the tiles all together. So all of these features--
this is my website. Like, I made this. Well, I made this. All I had made was an
empty div and maybe a dozen or so lines of JavaScript code. But this is again where programming
gets really exciting and really fun, because you can start building things
on top of other people's work in a way that they've made available
so that you can do this. And if you think about
apps you might have in your pocket, Lyft
or Uber or the like, those apps have maps built in, right. And Uber probably didn't go around the
world with cars or other technologies, figuring out where all the roads are. Rather, they're probably using
Google Maps API or something like it, in order to show you those maps. And they built their
business on top of that API. And this is again where things get
really powerful, really quickly. Now there's another feature still. And just to show you that we're
only scratching the surface, let me open up something like this so
that we've at least filled in one gap. Earlier today we started
with the alert function, which really should never be used. If you ever see a website that
has that ugly alert pop up, that is cutting corners, just as I have
because I wanted to focus on the ideas, not on the printing of information. But this underwhelming
button at first glance, has actually been
implemented using Bootstrap. So that's why it doesn't
look like a default button. It's got more of a nicer
gray border around it, even though it's still there
in the top left-hand corner. But there's an event listener
on this button for on click. And when that button is clicked,
we're going to see an alert, but it's an alert that's a lot nicer. And maybe it's not perfectly
beautiful as you would have it, but it's being generated entirely
with JavaScript HTML and CSS. It's not the browsers built-in default. And indeed, notice what just happened. The back of my screen went kind of gray. There's this nice drop shadow here. There's a title. There's a body. There's a close. And for convenience there's
this little x up here. And that's because Bootstrap, the
library to which I've been referring, has bunches of other features-- not
only these things, called modals, which are fancier alerts. And indeed, notice what a modal does. It deliberately, by design, blocks
you from seeing other things until you dismiss it. Now it's dismissed itself and it's gone. But these are the kinds of
features you get with JavaScript. So form validation, maps,
interactivity like that. We're really just
scratching the surface. But at the end of the day, it
just boils down to a few features. And it's these libraries that take
advantage of features like that. jQuery, which you can take a look
at in a bit more detail here. Bootstrap, which again you'll
recall from CS50 Finance, but you can see more about it here. It doesn't just come with CSS. It comes now with
JavaScript capabilities. And then this is the URL of that other
library that uses Bootstrap and gives us form validation. So let's look at one last
example so that we can now tie together what we did
some weeks ago with what we're now doing in JavaScript. It turns out that in C
we of course manipulated images for forensics problems
and whodunit and so forth. But you can do this
in JavaScript as well. In fact, if you go to this
URL here, there's some fun, exercises if you will, from our same
friend Nick [INAUDIBLE] from Stanford, whom you may recall starred in
that binky claymation video. Well, what Nick has put together online
is a bunch of JavaScript examples that give us puzzles like this. So iron image puzzle. So here's something,
not just with red noise, but with red and green noise still. And no matter what angle I look at this
one, I really can't tell what it is. And it's not actually one
of those magic eye things where you just kind of stare
through it and something appears. Rather, there's a lot of noise here. And there's that image hidden. If we actually read
the information here, we'll see that it contains
an image of something famous. However, the image has been distorted. The famous object is in the red values. However, the red values
have been all divided by 10. So they are too small by a factor of 10. So it's like Nick turned
a knob and ratcheted down all the red by a factor of 10. The blue and green values are all
just meaningless random values, noise, added to obscure the real image. And Nick tells us, you must undo these
distortions to reveal the real image. First, set all the blue and green values
to zero, to get them out of the way. Look at the result. And then if you look
very carefully you may see the image, although it's very dark. So at which point we can
multiply the red values by 10. So let me go ahead and do this. This now is using a simple image
API that Nick has provided here. And I know this only from having
read through his documentation, poking around the source code
and understanding what exists. And I gleaned, by poking around
and reading his documentation, that there's at least
six functions or methods associated with this simple image API. This API doesn't get more
data from the server per se. It's just an API in the sense that it
provides me with a set of functions that I can call. So these functions include,
get red, get green, and get blue, and set red,
and set green, and set blue. And it turns out that
Nick's already given me some starter code here in JavaScript. And I can now add some additional
code inside of these nested for loops. Because much like your
own forensics piece set where you probably iterated
from left to right and top to bottom over your image's
scan lines and pixels, so can we do the same in
JavaScript as follows. So Nick suggests, and I'll take
that advice, that I should first set the green and blue to 0. So I'm going to do IM for image. And that's the variable
he's defined up there. And just for good measure you can
think of this identical as before. We'll make it just like we did
with our variables declarations. Image dot sets green
at location x, y to 0. So again, I know the syntax for this API
only by having read his documentation. Image dot set blue at
location x comma y to 0. And Nick has given me this
handy run save button. Let's do that. He is right. So this is another copy of
that blue and green image. And I definitely can't
really make out the image. I mean, it looks like-- there's
a little bit of red there. I can actually way up close
here-- and perhaps on your screen you can see the faintest of red. Let me enhance that. But the red is there. The information is there. I've set all of the green and blue
bytes to 0, but there's still some red. I just need to bump that up. Well let me go ahead and
do something like this. Var red equals image to
get red at location x,y. All right. So let me do, image dot set red at
location x,y, equal to red times 10, as Nick suggests. Click run save. Ho, ho. It's all very red, but now I can
clearly see the Eiffel Tower. So we're really just
scratching the surface now. I mean there's this whole
field of steganography, the art of hiding information
within images, for instance. And this is just an example--
a simple example at that. But notice the things that
we did in C are all the more possible now in Python, or are just
as possible if not more possible in JavaScript. But it's ultimately the mental
models that are important. There's no server interactivity here
once we've downloaded this page. We have been using today, JavaScript
entirely on the client side. Which is to say that even
once you've download an image, can you permute that image, in memory,
in the browser, to manipulate it here. Or we could have sent it to Python. You could do the exact same
kind of thing in Python. Use the appropriate library with extra
read, those pixels, and those RGB triples if you will,
and do it server-side. So it really just depends on
what problem you want to solve. It did JavaScript itself, by
a framework called node js can be written on the server-side too. You don't need to use Python or
PHP or Ruby or Java or anything. You can use JavaScript. And as an aside, JavaScript
has nothing to do with Java. It was really just a
marketing ploy at the time. But JavaScript is the
programming language that is typically used in the browser. It can be used on the server. And its syntax is exactly
what we've seen here today. But it's especially useful
in the context of web pages because it gives us a language with
which we can manipulate the DOM that we've seen, the tree structure. It gives us a language with
which you can change and add to and remove the HTML, and the
CSS, and really anything you see. And indeed, it's this trio
of HTML, CSS, and JavaScript, coupled with some back-end, Python or
Ruby or PHP or Java or C+ or anything else, that together
implement today's web apps. And so now with that,
have you the vocabulary, coupled with SQL and your
own database back-end to build most anything
you want in the world. This was week 10. SPEAKER 2: Like I said, I don't
know anything more than you do. SPEAKER 3: There must be something
from your grad school days. SPEAKER 4: Hey, man. Not going to the party? We really should get
started on that [INAUDIBLE]. It's a doozy.