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