字幕表 動画を再生する
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.