[Week 9, Continued] [David J. Malan - Harvard University] [This is CS50. - CS50.TV] This is CS50. This is the end of week 9. Thank you very much. Finally. Week 9. I got it. Today we continue our conversation about web programming with an eye toward the final project, not because you have to do something web-based for final projects but because either for final projects or after CS50 this is certainly the direction in which modern software is going. And yet it's not actually an easy thing. In fact, one of the hardest things to do is the aspect of design. For instance, by design we mean actually getting the user interface or the user experience right. I daresay--and we know from a recent problem set when a few of you aired your gripes about some piece of software or hardware that infuriates you, whether on campus or off-- there's a lot of sites out there, there's a lot of hardware out there, that kind of sucks. But the reality is that making things that are easy to use yet are nonetheless powerful is a very difficult challenge. So for today I asked Joseph and Tommy to join me up here so that we can have a conversation, both about design and what kinds of thought processes should start going through your head when you design your final projects, your future endeavors. And then with Tommy's help we'll look at some of the implementation details. How can you have some vision on paper or in your mind that you can then execute programmatically by using some of the technologies and techniques we've just started talking about, namely JavaScript and something even newer, namely AJAX, asynchronous JavaScript. That allows you to create all the more dynamic of a user interface by fetching more and more data progressively from a server. So we'll see some of those snippets as well today. As an aside, if you are interested in concentrating in computer science or minoring in computer science, know that this Friday at noon in Maxwell Dworkin 221 there will be a pizza event where you can learn a bit more about computer science. On your way out the door today you'll be able to pick up an unofficial guide to CS at Harvard. We'll put it on the trash cans outside at waist height so that if you'd like to grab this and learn a bit more about CS, that will be there for you as it was in week 0. Also if you would like to join us for CS50 lunch this Friday at 1:15pm, head to cs50.net/lunch. Without further ado, I give you teaching fellow Joseph Ong. Hi. [applause] Thanks. The first time I learned about design was in a class here called CS179. The professor at the time told us the story about another professor who had gone to a hotel and used the faucets. Can anyone tell me what the 2 knobs on the left and right do? [student] Hot and cold. >>Hot and cold. Good. What you normally expect, right? This professor after using the faucet wants to take a shower, and he proceeds to use this. He thinks the left and the right sides are for hot and cold, right? But can anyone tell me what these actually do? Any hands? [inaudible student response] >>One suggestion is? [inaudible student response] >>Temperature? So one of them controls temperature and the other controls? >>[student] Water pressure. Water pressure. Good. This professor walks into this and, thinking they are controlling hot and cold, turns the right one, which he thinks is for hot, all the way up because he wants to take a warm shower. Well, these don't really match up, so he gets this not very fun experience of being in a cold shower, and we all know what that feels like. This is an example of a design flaw. What I mean by that is his expectation from the faucet did not match what came out of the shower, which is kind of unfortunate for him. So this is an example of a design flaw that happens in real life. But we see all sorts of other ones as well. We're probably not fans of the MBTA system. This is a subway system actually in London, which says, "This button's not in use." Why is it even on there? Why do we even care? When I was a kid, being the tech savvy one in the house, whenever the computer would crash, my mom would come to me, showing me this screen and asking me what happened. Even I don't know what this means. [laughter] What? [laughter] Sometimes we feel like software developers are just trolling us. As users we're like, "What is going on? Someone tell us." This all comes down to an issue of design. Design, as we can see, is not purely about aesthetics, it's not about how things look. We see here that this little pop-up over here actually looks pretty nice. It has a drop shadow in the background, it has border radiuses going on. It's kind of pretty. It's not really well designed because it's not very user friendly. That little pop-up that comes up doesn't really give me any information about what's going on, it doesn't tell me anything as the user about how to recover from that error. We want to think about things that design is not. First, it's not aesthetics. It's also not stuffing your app with tons of unnecessary functionality. If you're a Thai restaurant, you probably don't want to be a dentist at the same time. And with Facebook Questions, not that many people used it and it wasn't really at the core of what they were building. And so it's nice to think about not so much the quantity of the things that you're putting to your application but the quality and how you're making that user experience better by actually improving upon what you already have. In a nutshell, design tells us what we should build. For example, if we're building something that let us search things up, like Google, for example, should we do things in a manner that requires the user to take lots of clicks to get to what they want, or should we do it in a way, for example, with Google Instant or autocomplete that lets us get to our results faster? Engineering involves, like Tommy will show you, actually building it. There are lots of types of design. For example, if you're building something to deploy something in a Third World country where there isn't much electricity or that much technology, you have to design what you're building in a way that easily gives access to the people there. But what sorts of other design decisions might there be or might be involved in something like this? Yeah. I see a hand. [inaudible student response] >>Right. Exactly. Accessibility is one thing. A lot of people don't think about, "What about my users?" like the extremes of either spectrum. I have users who might have disabilities that I'm not thinking about and I'm just thinking about designing for the general user. The Internet is accessible by everyone nowadays, and I should be designing for those people as well. What sorts of other design decisions might you make? Yes. >>[student] Cost. Cost. Very good. Another thing we might base our design decisions on are cost. If we're a business, you want to build something that doesn't take much cost to produce but can sell at a particularly high cost or can get us some profit. These are all different types of design, but when we're building something on the Internet or when we're building something that probably doesn't cost that much to build up now, like Internet applications--you don't have to throw much capital into it in order to make something that actually works-- what we're more worried about is the user experience. We call this user centered design. Essentially what user centered design involves is putting yourselves in the shoes of your users. If someone signs up for what I'm building, they've obviously come to my particular application with a goal in mind, with a task they want to complete. And your job is not only to help them complete that task but to help them complete that task in a manner that is efficient, intuitive, and, as some person said over there, accessible. What does efficiency mean? Efficiency means how quickly does my user complete the task given my interface. Does it take lots of clicks for them to get from one place to the other? Is it tedious? Do they have to perform lots of repetitive tasks? We want to make that process as efficient as possible so they don't have to do those sorts of things. As for intuitiveness, that is, for example, if a user looks up my interface, is it easy for them to get from place to place? Is it easy for them to figure out what they have to click in my interface in order for them to achieve the goal or task that they want to achieve? And finally, as one person said over there, accessibility is very important. [male speaker] It comes to accessibility for things like vision, like how do I actually design something for someone who is blind? Oh. For people who can't see at all, we have something called screen readers. What you should do is you should build your website in a way that, for example, particular technologies what we call-- There are lots of things now. I think there are screen readers called JAWS. A lot of these things rely on what we call area rules in order to read out to the user what is present on the page. For those people who can't see, you need to make sure that these screen readers can actually pick up the content on the page and can actually show your users, if you can't see, at least you can still understand the content on the page. Yeah. Okay. Enough talking about good design. Let's talk about bad design. These are things that you should not do. Can anyone tell me about their experiences with Craigslist and what they think is not so great about this design? Yes. >>[student] I think there's too many words in one area. Too many words, right? Completely overwhelming. You come to this page and you're greeted with a whole bunch of things up here that might not even matter to you. For example, you live in one state that does not begin with this letter. Let's say you live in Texas or something. You have to scroll all the way down the page to get to the location you are at. I'm from Boston, so let me look in Massachusetts. Where is Massachusetts? Oh, it's right here. Oh, it's Boston. Okay. Let's look at Boston. [laughter] Pretty overwhelming, right? Awkward things over there. [laughter] Let's say I'm looking for somewhere to live. How many people have actually used Craigslist? Tons of you. There are pretty bad ways to look at this, but let's look at this. What's the difference between img and pic? Can anyone tell me? There actually is no difference. They mean exactly the same thing, but they have different labels for them for some reason. If I click on Has Image, nothing happens on the page. I actually have to click Search again for something to happen. What might be a better design decision that could be done there? If I'm clicking on that filter, I probably want to filter by that particular action or that particular category. So instead of having to press Search again, I could just automatically do the filtering sort of Google style where they do it instantly. [Malan] But don't forms as we've seen them thus far have to be physically submitted by hitting Enter at least or clicking a button? As you've seen them so far, you actually have to click Submit to do those things. But as Tommy will show you in a second, there are actually ways for you such that when you click on that thing it can automatically send what we call an AJAX request and get data back and filter your results instantaneously. There are tons of things that are wrong with this interface. [Malan] Can you search for Cambridge? There's something slightly anomalous here where you care about Cambridge and yet you're getting Westford, Spring Hill, West Newton and the like. Probably not ideal. >>Probably not ideal. How might I be able to make the user's experience better on this particular page? Yes. >>[student] Instructions. Okay. Instructions in what sort of sense? [student] For example, a thing for first time users who don't even know what Craigslist is or you don't know what you're supposed to do. Right. So explaining what Craigslist is on this page is important. We can actually tell users what this page is actually for. If I'm just visiting this, I see a whole bunch of locations. I don't even know what they mean. But more importantly, just looking at this interface, remember I had to scroll down a ton of things to find a particular community that I actually cared about on this. What's a faster way I could do that? Yes. [student] Divide them up into east, west regions. >>Okay. I could divide them into more categories that could help me faster determine how to get to that particular location. [student] Put a drop-down list. >>Right. Okay. I could use a drop-down menu because we have a fixed set of things and we could show them in a drop-down menu. That way it doesn't take up so much space on the screen. But even better than that, what can we do? Yes. >>[inaudible student response] >>Can you say that again? >>[student] Search box. Yeah, a search box. That's great. What we can actually do is if we look back at the slides, search box. Autocomplete. Very easy way to search through results that you know are in a set. If I start typing B-O, just show me all the results that have B-O inside of them. That way I can very easily find the particular one I want to go to instead of having to scroll through this really big list. These are all sorts of really low-hanging fruit that someone who is implementing Craigslist can actually do to make the experience on the website a lot better for their particular user. Okay. Enough talking about bad websites. Let's talk about Facebook. When Facebook came out, and particularly Facebook photos, there were lots of other services at the time which could do exactly the same things. They could organize your photos into albums. What you could do is you could organize them into sets as well. You could organize them by date. You could do all these particular things. But does anyone know what made Facebook photos explode at the time it was released? Yes. >>[student] Tags. >>Tags. Exactly. We have Milo over here, who is our dog mascot with that CS50 bandana. You can see that we have this tagging feature in the middle. And what made Facebook photos so interesting from a usability standpoint is that it actually allowed people via this to involve their friends in their photos. For Facebook, since their website is particularly social, it's about building this sort of social atmosphere. That improved the experience of photos a lot more because they could actually start saying, "These are connections between people, and these are photos about people you actually care about." Part of it is also sort narcissism. People like to be tagged in photos and things like that. While that's not necessarily a good human trait, at the same time it's based on good design decisions because people actually care about things like this. So that's Facebook photos. But let's talk Facebook more generally. I'm sure lots of people here have opinions about Facebook, both good design decisions and bad design decisions. So let's vent or be happy. Come on. I know all of you use Facebook. Someone has to have something bad to say or something good to say about it. Yes. [student] In the news feed there's a lot of things I don't really care about. The news feed does show a lot of things you might not care about. You have friends on Facebook who you haven't met for 2 or 3 years and you see their news results popping up in your news feed and you don't really care about it. Facebook has actually made an effort to make this better, and they've actually tried to push relevant results to the top of the news feed as of late so you actually see things by friends which are relevant to you or your close friends. Anything else? Yes. [inaudible student response] >>Can you say that again? [student] The ads are relatively unobtrusive. >>In what sense? [inaudible student response] They don't have light on the screen, like banners. Okay. That's good. If you remember the Internet from the '90s-- >>[Malan] I was there. >>He was there. [laughter] You might remember flashing GIFs backgrounds, sparkly things, GeoCities style sort of things. That's really not an example of a good design because it's really distracting from the content. The Yale art website used to have animated GIFs as their background and you couldn't read anything on the page, but I guess someone actually talked to them and now it's a bit different. [Malan] It's much better now. >>It's much better now, as you can see. >>[Malan] Oh yeah. Just great, just-- Yeah. Okay. Part of it is also making your page possibly very minimalist and very understandable so things on the page flow in a way that is very logical and don't get in the way of each other. What sorts of other things are good about Facebook or bad about Facebook? Let's just have a design conversation here. Oh. Where? Yeah. [student] The new Timeline system allows you to search the person's profile about their past. Ooh, Timeline. Timeline is a great thing because it lets you stalk your friends back when they were in high school. Timeline is good because it lets you filter through content a lot faster, it lets you find things that would have otherwise taken you a really long time to find just scrolling up and down, up, up, up, up, up, like going back in time. But then there's also sort of a downside to that in terms of user experience. What might that be? Big word that starts with P-R. >>[student] Privacy. >>Privacy, right? Privacy is a huge user experience issue. This is one of the things I hate most about Facebook now. [laughter] [Malan] As do I now. David didn't realize this actually happened until yesterday. So now he knows that every time I chat him I know he's been ignoring me. [Malan] The awkward part was I was actually ignoring him, and I didn't know he knew I was ignoring him. [laughter] Privacy is a huge issue. Can anyone here tell me what might be bad about Facebook privacy besides the fact that they do things like this? What is it particularly hard to do with respect to Facebook privacy? That sort of is a leading question. Yes. >>[student] Hide your photos from certain people. Right. Exactly, to hide your photos from certain people. They have this small, little button in the upper right that lets you toggle the privacy of a photo. Their privacy options are very varied between different sorts of menus. They've gotten a lot better about it recently, but it used to be the case that whenever you wanted to prevent your friends from seeing photos, you would have to go through a very complicated 5-step process of being like, let me click this link, now let me click again, let me click again, let me specify which people can't see my photos. That is not particularly good on Facebook's part because so much about user experience is actually giving them the freedom to control what people can see. We call this user control and freedom. If you're not letting your users do that in a way that is efficient and intuitive, then your user experience isn't really that great at all. Would you guys like to say anything about Facebook? How do I turn this off? [Ong] You can't turn this off, and that is a huge usability flaw on the part of Facebook. This feature--I actually looked into it yesterday-- it's either that you can't do it or it's buried somewhere very, very deep in the recesses of Facebook because I can't figure out how to disable this functionality at all. [Malan] But sometimes these decisions aren't obvious because you guys have given us a lot of useful feedback on various CS50 applications and websites that the course uses. We have not implemented all of these requests and suggestions. Part of that is for getting so many requests that it's a function of time, but sometimes we just make a conscious decision like, "Thank you for the suggestion, but we disagree." So how do you actually decide what you should do if your users think you should do something even if you don't necessarily? It's a fine balance between actually listening to what your users say and actually having some sort of line where you say, "We're not going to do what these users say." And in particular, I think there was a quote by Henry Ford that sums this up pretty well. "If I had asked people what they wanted, they would have said they wanted faster horses." Can anyone sort of tease apart what that quote really means? It's not just that users know what they want, but it's more that-- [student] They don't know what's possible. In part they don't know what is possible. Tease that apart a little bit more. What do you mean by that? [inaudible student response] That's good. What I think we're trying to say here is that people know what they want. They want faster horses. What they really want is the ability to move faster, but they don't really know the medium by which to achieve that. When you come to your users and your users tell you something and they tell you, "We want these features and these features and these features," you don't want to necessarily think about, "Let me go ahead "and implement what they explicitly say," but what you want to think about is, "What sort of ideas can I get from that?" What do they actually want? And from there what you can do is design something that satisfies those requests but not necessarily in the way that the user expects it to be satisfied. So for something like final projects, in very real terms, what's a useful heuristic when it comes to making something better, especially if the designer has this arrogance about him whereby you sort of know what's best, you might take input from your users, but how do you actually go about getting that feedback? In final projects, very concretely, what produces optimal results here? What produces optimal results--and I will go over this in a second-- is this process of developing and then testing and then iterating. What I mean by testing is usually when you design something you think it's fairly good, like, "I'm such a great designer. Everyone is going to love this." And then you put it out there and people don't really like it for some reason. What you have to do is you have to take the parts of things that people do like and revamp the things that people don't like. It sounds like a very obvious process, but this process of constantly iterating on top of what you've already built is a process that helps you not only refine your own design skills but also helps you refine the design so that people actually appreciate your product even more than they did before. I'll go over more concrete examples of what you might actually do. As sort of a last example of a product, let's look at KAYAK. KAYAK when it came out was very, very popular. Can anyone guess why? What are the sorts of things you like about this if you have used it or what are the sorts of things you don't like? Yes. >>[inaudible student response] >>Okay. That's part of it is letting the user have a query that is more expansive than a very restrictive one like, "You have to pick your start date "and you have to pick your end date." In fact, it lets you be flexible about it and it gives you all of the flights in that range. Anything else? [student] They include the fees in the price. They do include the fees in the price. The taxes and things actually go straight into that price in the upper left so you're not tricked into thinking that you're actually paying for a $240 flight when it's really $330. Anything else? Yes. [inaudible student response] I'm not sure if they actually let you do that. I might be wrong. That might be an interesting thing if you want to put more weight on particular filters so that they push results related to that filter to the top. But can anyone tell me what's so special about this left side? How did you traditionally look up a flight on an Internet service before this? Yes. >>[inaudible student response] >>Can you say that-- [student] Each airline. >>Yeah. Each airline has its own website. This consolidates things. And? [student] You know exactly what time you're leaving. You do know exactly what time you're leaving, but related to the filters in particular. Let me pull up KAYAK. Oh God, pop-ups. Bad user experience. What happens when I move this slider? [student] Automatic updates. >>[Ong] Automatic updates. That's something that's very important. Before this, whenever you wanted to look up a flight, you had to put in your input location, your output location, press Search, it would process that and show your results. If you wanted to change your query, you would have to press back twice, enter in a new query from scratch, and then do it over and over again. The nice thing about something like this is it uses a very [unintelligible] thing in the middle. Whenever you do something like this, it shoots off a request and it returns you all the results immediately. This sort of immediate feedback is something that made KAYAK wildly popular because it's really easy for me to just change my query and to figure out the things that are around a particular range without having to go back and forth, back and forth, back and forth. So these are all sorts of things you want to think about when you're designing your website. How can I make it very efficient for my users to go through whatever they're working on and to get to their eventual goal as quickly as possible? [Malan] And to Joseph's point earlier about users not necessarily knowing what they want, based on what you guys now know about HTML and you have checkboxes, radio buttons, select menus, input fields and the like, how would you implement the notion of picking a start time for a flight? Which of those various UI mechanisms would you use? If you just know the amount of HTML that was taught before and you know the inputs are radio buttons, checkboxes, drop-downs, and input box, what would your natural choice have been for picking dates? [student] Input. >>Input. Or maybe even a drop-down with all of the dates, right? So with more complex UI mechanisms like this on the left side that you can implement, you can make this process much more intuitive with a slider because time is continuous, and people usually don't think of it in terms of discrete chunks. All right. Last thing. Ten usability heuristics. All the things we talked about probably fall under one of these categories. If you go to this link, which the sites will be posted online, you'll actually be able to, as you design your site, keep these heuristics in mind and these rules of thumb. For your projects, what I suggest you do in order to design your app better is to do paper prototyping first. When you're thinking about your application, very quickly sketch what you want it to look like and make sure all the boxes are arranged in a way that is very intuitive for the user to use and even show these paper prototypes to your friends and start focus groups. Just get 2 or 3 people together and ask them to just tap on these paper prototypes, and show them new screens to see if they actually understand what's going on. What you want to do is give them a task, motivate that task, and just give them the app and let them use it. Don't give them instructions beyond that. You want to actually let them interact with your app in a way that lets you see how they would use it if you weren't standing next to them. And that's very important. That will give you lots of insights as to are people getting around particular things in a way that I didn't intend them to? Are they using particular UI mechanisms on the screen in a way that is kind of hacky? I didn't intend for them to do it that way. And once you're done with that, what do you want to do? Your design rocks, right? What you want to do is you want to develop and then do that process over again. So show it to friends once you've developed it, test it, develop, test, develop, test, iterate, on and on and forward. Design is a very iterative process in this sense. You actually have to build something and then realize things about it that you didn't realize before and go back and improve from that. Now, as for the development part, that's what Tommy is going to show you after the break and how you might be able to implement something like autocomplete in a way that is fairly simple. [Malan] As Tommy sets up here, a question then. A lot of the earliest websites--and when Joseph said 1990s style website, it was implementations where if you wanted to select a start time and an end time, frankly, back in the day and even on some websites today, the way you do this is you pick an hour from a drop-down, you pick minutes from a drop-down, maybe you choose AM, PM, and then you do that 3 more times. And so with 6 clicks and maybe some scrolling your user can actually provide some kind of date and/or time range in this sense. So definitely suboptimal and yet thus far we've seen no expressive capabilities in any of the languages we've looked at to do something sexier like this slider of start time and end time. But if you think back to week 0 when we talked about Scratch, there too there were not widgets that just did certain things. You really just had these fundamentals like loops and conditions and the like. So kind of just thinking very abstractly now, independent of the particulars of HTML, what is really going on with something like this start time and end time slider? When I move my mouse and I click on that little carrot symbol on the left and start dragging, programmatically, what is it you want to be able to implement to make that happen? What questions, what Boolean expressions do you want to be able to ask? What's really going on? Sammy? [student] Where's the position of the cursor? >>Good. Where is the position of the cursor? This was something we needed to express back in Scratch, whether it was based on location or even color or the like. You might recall ever so briefly on Monday there were all of these things called events in the world of the Web, and so there's things like onclick and onkeypress and onkeyup and onmouseover and onmouseout. So realize that even these things we've been taking for granted on the Web with sites like Facebook and Gmail, even if you have no idea how you would possibly implement that because there's nothing even like it in lecture or Problem Set 7, realize that with these exact same fundamentals, with HTTP and parameters and GET and POST, with the basic HTML inputs that we've looked at thus far and in a moment with the programmatic mechanisms that Tommy's about to introduce can you start to express yourself just like you did in week 0 by very intuitively dragging and dropping. So with that said, Tommy MacWilliam and some new puzzle pieces for us for Web. All right. My name is Tommy and I'm going to be talking about JavaScript. Just a disclaimer: I am of the opinion that JavaScript is the best programming language in the whole entire world. There are lots of people who disagree with me, but it's just amazing. Once you go back to C, if you have to write C for another class or some other languages, it's just really frustrating in all the low-level details you have to get bogged down in. So if you're ever feeling sad about how annoying C is to write, just go back, write some JavaScript. It's nirvana. You'll feel much better about your bad day. A lot of the magic of JavaScript comes from its ability to manipulate things that are already on the page. When we wrote our PHP scripts, they were executed on the server, and eventually that PHP script probably output some HTML. That HTML was sent to the client, and then that was it. If PHP wanted to add a button to a page, for example, it can't really do that. It would have to render a whole new HTML file and send that to the browser. With JavaScript we know that we can update things while they're already on the page, and because of this we can provide much more instant feedback, which will really improve the user experience on our website. Just a quick recap of JavaScript selectors. We know that when we download an HTML page, that's going to be represented in the DOM. The DOM remember is just this big tree where elements are related in this large hierarchy. When we worked with databases in pset 7, one of the first things we needed to know how to do was query the database. We have this large users table, and sometimes we just want to say, "I only want some of these users that match some condition." Similarly, when we have the DOM we need some way of querying it. We need some way of saying, "I want all of the buttons that look like this "or all of the images on the page." And these selectors allow us to do that. So just a quick recap. This first one here, this #submit, what is that going to select? Does anyone remember? [inaudible student response] >>Yeah, exactly. This is going to select an element on the page that has an ID of submit. And so that hash tag says this selector is going to work with IDs. How about the second one, this .centered, what will that select? Yeah. >>[student] Class. >>Exactly. This is now going to select by class. The difference between ID and class here is generally the ID should be unique within whatever space you're searching over. So if you were searching over an entire web page, you really should only have 1 element with that certain ID, so in this case of submit. With classes, on the other hand, we can have more than 1 element on the same page with the same class. This could be useful for saying I want to select everything that's centered on the page rather than just 1 thing. And finally, this last one here is a little more complicated, but what is this going to select from the DOM? [inaudible student response] >>What's that? [student] Anything that's a tag. >>We have 2 parts here. The second part is going to say I want to select these tags with a tag of input, so any element that is an input tag. But I don't want to just select all of the inputs because something like a submit button could be an input and something like a text box could be an input. So with these square brackets I'm saying I only want to select those elements that are of type text. Somewhere in my HTML tag I have an attribute called type, and the value of that attribute has to be text. So how about this first part here? The first word of this selector is form then I have a space and then this input part. What does that do, putting the form in front of it? This is going to basically limit our query. It could be the case that we have some inputs on the page that aren't descendants of a form. What this will do is this will say I only want the input tags that have somewhere above them some parent element of a form. And so in this way we can make these more hierarchical queries so we don't just have to select everything matching a given selector. We can kind of limit the scope of that query to something else. So now that we know how to select elements on the page, let's talk a bit about AJAX. AJAX is a still very trendy acronym that stands for asynchronous JavaScript and XML. It just so happens that XML is just some way to represent data. That kind of lost popularity recently, so the X in AJAX isn't used all the time. Basically, what AJAX allows us to do is make HTTP requests from the context of JavaScript. When we're in our web browser and we're navigating around pages and we click a link, what our browser is going to do is make an HTTP request to whatever link we click. But that's not always ideal because if that's the case, then as David was saying, we always have to make users click a Submit button or click a link in order to make anything happen that's going to involve an HTTP request. So with AJAX we can make these requests on behalf of JavaScript. That means whenever the user interacts with the page or anything happens, we can actually make a programmatic request to some other PHP file on our website or anything else and retrieve the data that that file spits out. Let's take a look at an example of AJAX. This is our CS50 Finance page with which hopefully some of us are familiar. If we look at the HTML of this page, we see here that I've added a few things, one of which I've given this form an ID. I've said id="form-quote". I've done this just because it's going to make this a little bit easier to select from the DOM since I can just make a very simple query. What I want to do here is I want to fix some problem with CS50 Finance. So if we go to finance.cs50.net, every time I want to get a quote, I have to click this Get Quote button, and that Get Quote button then takes me to another whole page. And if I want another quote, I have to hit the Back button and then I type it in, I get a quote, and I hit the Back button. This really is not the best user experience. Who would really use the site if it's that slow to get stock prices? So what we want to do with AJAX is remove that step of going to a separate page in order to view the results. What we're really only asking for is that really small price, and that's just a really small amount of data. So there's no need for me to go another whole HTML page, download a whole new batch of HTML, maybe download some more images, some other CSS files just for me to answer that very simple question of how much does this stock cost. With AJAX we can make this a lot easier. We see down here that I'm linking in a JavaScript file called quote.js. Let's actually open up that file. Not there. All of my JavaScript files are going to be located in HTML so that the web browser can access it. Then we have a separate directory here for JavaScript, and now here is quote.js. At the top of this file this says here that I want to wait for the entire page to be loaded before I try to do anything. Why is that necessary? It turns out that the next thing I'm going to do here is start looking for an element that matches some selector. If this JavaScript is ever executed before this element is loaded on the page, then everything I try to do isn't going to work because I'm going to try to select something that isn't there yet. So this line up top says I want you to wait until everything is loaded so we're guaranteed that any elements I'm looking for are actually on the page. This dollar sign here means I'm using the library called jQuery. This jQuery library allows us to use these selectors that we just looked at. By saying $ then passing in as an argument this #form-quote, I'm now selecting that form that we just took a look at. Now I have a representation of that form in memory somehow. On this object now, this representation of the form, I'm now using a function called on. What this function does is it's going to attach an event handler. The event that we're going to listen for is the submit event. So when the user clicks that Submit button or presses Enter, this event is going to fire. By hooking into this, I can now override the default behavior of the form. Without this JavaScript, the form would submit to whatever PHP file we used in that action attribute. But instead, I'm now saying, wait, wait, wait, I don't want you to actually do that. I want this to happen before you go and try to submit to some PHP file. Now what do I want to do? At this point I want to use AJAX somehow to load in what the price of the stock is. The first thing I need to know is what stock the user is looking up. To do that I'm going to use another selector. This is the third selector we looked at before. This says that I want to start off this form element with an ID of form-quote. Then somewhere inside of that form there has to be an input element that has a name of symbol. If we look back at our HTML, we saw that we had an input[name=symbol]. That means that this is going to select that text box that the user is typing into. That's nice. We have the text box. Now we just need to know what's inside of it. To do that we can call this method here, this .val, and this says I know what text box you have. I want you to tell me what it is the user typed into that text box. Now we have a string called symbol that is equal to whatever the user typed in. That's nice. We can use that string now to make our request. This is a new function here, this $, except we're no longer going to be selecting elements, we're going to be calling a different function that's provided to us by jQuery. This AJAX function is what's actually going to make this HTTP request. So we have to tell it a few things. The first thing we have to tell this function is where I want the request to go. Somewhere in my project I have this file inside of the HTML directory called quote.php. I can access this file, we saw, just like this, if I go to localhost/quote.php. I want my JavaScript to make a request to that page. What type of request now? We saw before that the form has that method="post" attribute, and that means it's going to make a POST request, so it's not going to put anything in the URL, rather than a GET request, which would just be fired if we just accessed the page with the web browser, for example. Now we've said I want to make an HTTP POST request to a page located at quote.php. When we submit the form, remember we could access the input elements inside of that form with that $_POST variable. So far in the story we haven't actually sent along any data yet. We've just said we're making an AJAX request and here's the type of request we're making. Now we need to actually send some data to the page. To do that we can use this property called data. The value of this property is actually an associative array. The reason for this is it allows us to send more than just 1 piece of data. That's why we have these curly braces here nested inside of these other curly braces. The keys in these associative arrays are going to be the same thing as those name attributes in our form elements. That means that if I send along a key of symbol, that means my PHP page can access this data with $_POST[symbol] just like we did before when we were submitting a form. And now the actual data we want to send is going to be the value inside of this associative array. We stored this text in a variable called symbol, and so we're sending along now a key of symbol and a value of whatever the user typed in. Now we've made this HTTP request, our PHP file has executed, and it's going to send some data back now to the client that just made this request. Now we need to respond to whatever the server said to us. To do that we have this last property here called success. The value of this success key is actually going to be a function, and this is one of the really cool things you can do with JavaScript. Not only can you have ints or arrays as a value inside of an associative array, we can also have a function. So by saying success, this is my key. A colon says here comes the value, and now the value of this is actually a function. So we don't need to give this function a name per se. We can just say this is going to be some function. It's going to take 1 argument. The argument to this function is going to be whatever the server sent us back from the request. Just like when our browser makes a request, the server sends something back and the browser displays it, in the context of AJAX we just made a request, the server sent something back, and now we have that represented as a string. With that string I would just like to display that on the page. To do that I'm going to have one last selector. I want to select the element with the ID price. This is just an empty div that I've created on the page, and I want to set the contents of that div to be whatever the server sent us back. I've actually modified quote.php a bit. Rather than calling render and rendering some page, quote.php now is simply going to print out the value of the stock as a string. So if you were to actually visit the page, you would just see that small string of whatever the stock price is. One last thing we need to do here is just make sure this function returns false. What this says is that if I'm inside of an event handler and that event handler returns false instead of returning true, that means that I do not want the original event to fire. In this case, if we did not have any JavaScript and we submitted a form, our web browser is going to say, "I'm going to send that data along," and they're going to send you to another page. Because we're using AJAX now, there's no need to send the user to another page. We're just going to display the results dynamically on this same page. We really don't want them to go anywhere, and I want to stay on the same page. So by returning false, we ensure that the form doesn't do that for us. Let's take a look at what this actually looks like. Our quote page looks the same. Let me pull up the inspector down here so we can see what's going on. Make it a little less huge. Remember if we open up the Network tab, this is where we can see all of the HTTP requests that are happening on the page. For a symbol let me type in a-a-p-l and click Get Quote. Now we saw that a share of Apple costs some number of dollars just appeared on the page, but the URL didn't change at all. In fact, here is the HTTP request that we just made. We made a POST request to quote.php. That makes sense. This is what the server sent us back. It's no longer this gigantic HTML document with images and things like that, it's just a line of text, and then we just displayed the line of text. If we go back to the headers and see what we actually sent inside of this HTTP request, we can see down here that we sent along a key of symbol and a value of aapl, which is what the user typed in. This is nice, but it's still a little annoying. I still have to click this button to get the stock quote. We're busy people and we don't have time to click buttons. Google realized this a little while ago when they implemented Google Instant. What Google Instant does is as you're typing it just starts displaying results for you so you don't have to worry about even clicking Search. Actually, a fun story related to that. Once Google Instant came out, people were like, "Whoa, this is super amazing." "This is so cool." And a student down at Stanford who was 19 at the time made this site called YouTube Instant. All YouTube Instant does is effectively search YouTube instantly. So rather than having to go to YouTube.com and hit Search, when I start typing into YouTube Instant something like CS50, we could see here that it's attempting to on a slow Internet connection populate these results live. To do that we can actually make a very simple modification to our quote.js file. Right now we're attaching this event when the form is submitted. We don't really want to make the user submit that form anymore, so let's instead fire this event every time the user presses a key. To do that let's first change the event from submit to keyup. That means that rather than waiting for the form to submit, every time the key is pressed, something is going to happen. It no longer makes sense to attach this keyup event to the whole form. We really only care about that search box. To select that now, we can change this to be, rather than form-quote, form-quote and we'll have an input(type=text) or we could say (name=symbol)-- whatever we want. Now there's one last thing we have to do. Remember down here when we said return false we said we don't want that default event to fire. But it just so happens that if we disable that now, whatever we type in is not going to show up in the browser anymore because that would be the default behavior of typing into a text box. We no longer want to override that, so let's destroy this return false. If we save that and reload the page, now when I start typing a-a-p-l you'll see that the stock price at the bottom here is completing automatically. So here is CS50 Finance Instant. Actually a fun story about the YouTube Instant is that student just kind of wrote it as a 1-night project, and the next day he was offered a job by the YouTube CEO. So as simple as that, you CS50 students, your final projects can get you a job at YouTube. Something like that is a really cool idea for a final project, right? We had some existing functionality that we wanted to integrate with. We improve the user experience a little bit, and suddenly searching something on YouTube Instant might be a lot easier than searching for it on regular YouTube. So that's AJAX in a nutshell. In the examples that Joseph was showing, we saw a lot of autocompletes, and those autocompletes are really, really handy because we don't have to remember-- For example, if you don't remember the stock price for Apple and we just know it's a-a something, rather than just saying to me, "A share of this thing costs this much money," I'd kind of like to know what stocks start with aa. We can do that really nicely with the Bootstrap library that's already included inside of CS50 Finance. If you come up here to the JavaScript tag and scroll down to Typeahead, this is just a nice plugin that somebody already wrote for us, and we can easily use its functionality like this. I typed in an A and here is a list of some states that start with A. Let's say that I think this is really cool and it's time for me to include this on my page. It turns out that this is really, really simple. Let's jump over here to quote3.js. My file looks a little bit different. Down here all of my AJAX stuff is the same. I want to load the stock data without having to go to another page. But now I want to use this plugin. The Bootstrap documentation has great examples of how exactly I can do that. I want to say, "Here's the input that I want to autocomplete on," and I'm going to call this function called typeahead, and that's going to handle all of the Typeahead stuff for us. It will initialize the list, it will do all of our filtering. The only thing it needs to know is what data we're autocompleting on. So I found out this key just by reading the documentation and looking at the examples. If I give it a key of source, the value of this key is just some array of things I want to autocomplete on. This variable came from this other file. I open up symbols.js. This symbols.js is just this really, really big array containing strings of all of these stock symbols from the NASDAQ. If I want to jump back to the HTML, so jharvard, vhosts, globalhost, html, templates, quote_form. Since that's now called quote3.js, let me change the JavaScript file I'm including here. Now I have quote3.js, so I'm going to load in that separate JavaScript file, the one that has that Bootstrap autocomplete. Now when I jump back to the browser, reload the page, and I start typing a-a, there's my autocomplete. And it was really as simple as that. I had 1 line of code that just said, "Here are the things I want to autocomplete on," and suddenly I have this really, really nice functionality with not a whole lot of effort at all. As you're developing websites and particularly the front end side of things, you're going to find this is the case a lot. There are a lot, lot, lot of really cool free libraries out there that make it super easy to do things like this. Can anyone think of any drawbacks of simply autocompleting on this large list of symbols? What could be something that's not the best with this approach? Yeah. >>[student] Time, if you have a lot of [inaudible] Yeah. Right now we're downloading this huge JavaScript file and there's a lot of symbols. And so if we have a ton of stuff, this could kind of increase the latency of not only searching but also downloading the actual file. Great. Anything else? Right now there's no real sense of relevance. If I type in an A, the companies that show up here might not be the most popular companies that start with A. Before I get to Apple, it might take some more characters to find what I'm looking for. This autocomplete doesn't have this sense of relevance. It's just going to say, "Anything that matches I'm going to display." Instead of that, I'd like to somehow integrate some relevance into my searches. If I go over here to Yahoo! Finance, finance.yahoo.com, If I try to enter a symbol on Yahoo! Finance's page and I start typing g-o-o-g, I have this nice list of things. Clearly, it looks like Yahoo! Finance is doing something more clever here. They have some relevance and they also have additional information like the name of the stock. That's something that I can't really get with just my stock list of symbols. I want this and so I'm going to take it. To do that let's do a few things. Let's first open up the inspector on this page because we saw that this page is not reloading at all, so it's probably using AJAX somehow to be loading its data. We can find out what data it's loading. If I click on this Network tab, these are going to be all of the requests that start to be fired. Now if I type in g-o-o, we can see that I just got a new HTTP request. This is probably where that data is coming from. Sure enough, if I look at this URL, which is a bit strangely named, we can see that this is exactly where Yahoo is sending off its data from. I've created a separate file called suggest.php that's very similar in spirit to the lookup function. It's basically going to make a query to Yahoo's URL, get back some data, and send it back to me. Now, rather than using this big, huge list of symbols, I can use Yahoo's nice relevance things, and I don't have to download that massive JavaScript file. I'm only going to pull down the actually relevant stock symbols. Let's jump into that. So html, js. We're now in quote4. Now we're no longer using that big list of JavaScript files. But there's a small kind of design problem here. We've said that the A in AJAX is asynchronous. What that means is that when I make an AJAX request, so right here on line 8, this is where my AJAX request is actually fired. Let's say now I have some code down here that's going to do some stuff like alert the user or change something on the page. What's not going to happen is the browser is not going to wait for this request to continue before coming down and hitting this line. That's the asynchronous part. It's going to make this request and say, "Whenever you finish, "come back and call that function that I told you to call inside of success." That means we can't just download all the stocks beforehand. We need to make the request and wait for something to come back. That means that before, we could simply tell Bootstrap, "Here's the list of things I want you to autocomplete on." We can no longer do that anymore because we don't know what we want to actually autocomplete on. Luckily, Bootstrap thought of this because those are smart guys over there, and they actually gave us another way to load this Typeahead plugin. Before, the value of this source property was just this big array of things to autocomplete on. Now the source property is actually a function, and the purpose of this function is to figure out what the things to autocomplete on are. The way it's going to figure that out is it's going to ask Yahoo! Finance what the best things to autocomplete are. To do that I'm going to make a very similar AJAX request. I'm going to request this page at suggest.php. I want to send along the symbols still. And now my success, the Bootstrap documentation told me that in order to populate that list of things, all I need to do is pass in this array now to the callback function. But wait a minute. If this is supposed to be an array and AJAX is sending me back text, how is that possible? This introduces a new way of exchanging data called JSON. In this case we're not just sending back a simple string of text. Now we're dealing with this more complex list of stock symbols. These stock symbols can also include things like the company's name or the current prices. Just using a big long string that's not formatted in any predictable way isn't going to be the best way to get this data from Yahoo's server to me in a way that I can easily understand. JSON is a technology that takes advantage of how we create associative arrays in JavaScript. This looks a lot like a JavaScript associative array, and in fact, it's because it is. JSON stands for JavaScript Object Notation. This is basically an agreed upon format for transferring data back and forth. Here this JSON object or this JSON associative array is sending me some data about a course. The keys of this array are things like course that has a value of cs50, and down here we can see that I can have a value that is an array. I don't have to do things like parse out strings and look for commas and do crazy things like that. Because this is declared in this JSON format, JavaScript and jQuery already have functions to convert a string that looks like this JSON into an actual JavaScript associative array that we can work with. Doing that is as simple as saying that no longer is this file, suggest.php, sending me back simply a string of text, but I know it's going to be sending me back JSON. That means that that JSON can be converted into a JavaScript associative array. And so jQuery, I would like you to do that for me. That means that this response parameter here, this is no longer just a string. Because we've told jQuery that here comes some JSON, jQuery is going to be smart enough to say, "You wanted JSON?" "I'm going to convert that into an associative array for you." Let's actually take a look at the Network tab once we have quote4.js. We'll change this and reload the page. Now I'm going to type in a-a again. I've made a couple requests to suggest.php, but now this response, rather than just the string, it's JSON. So I have an open curly brace saying, "Here comes an associative array." The first and only key of this associative array is called symbols, and then here is an array of all of the relevant symbols coming now from Yahoo! Finance, not from that gigantic list. That's how I can simply populate this autocomplete plugin with some data that's not coming from a local file that's already predetermined but from something else. It turns out that we can actually take advantage of a technology called JSONP, or JSON with padding, that will eliminate this suggest.php middleman. But instead of doing that, let's instead take a look at how I can improve this even more. I really like Bootstrap's Typeahead. It's really nice. But we're getting good at JavaScript and we want to kind of do this ourselves, maybe take a look at what this plugin could be doing. Let's no longer use that Typeahead thing, and let's try to make this list of suggested stocks ourselves. Here in quote6.php we're going to start off the same way. Every time someone types something, we want to make an AJAX request. This is similar to our original CS50 Finance Instant. Rather than making a request to quote.php, we're now making a request to that same file as before, this suggest.php, which is just going to pull data from Yahoo! Finance. Again, we're still expecting JSON, but now since the Typeahead isn't doing this for us, we also need to send along the value that is inside of the current text box. Now we know what to ask Yahoo! Finance for, and so now here's the function that we want to execute once the request completes. We don't have the plugin to make the list for us, so here's where we're actually going to build a list of suggestions. To do that, much like in PHP we concatenated these big strings of HTML then we printed them, we can do the same exact thing in JavaScript. First we're going to start off this string called suggestions, and this string is just going to contain some HTML. We want it to be a list of things, so we're going to start off with this list tag, and now we're going to iterate over all of the symbols that were returned back to us. Remember, because we've said dataType: 'json', this is not a string. This is already an array for us. That's really cool. We can simply say, "I want you to append a list element." We'll put it inside an a element in side of that, we'll give it a class of suggestions so we know what it is, and now here is the symbol that we got back from Yahoo! Finance. Once we've created an element for each of the symbols we've gotten back, we just want to close off the list. So now suggestions represents this little HTML fragment that when put on a page is going to be the list of things we're looking for. Now let's actually put that on the page. To do that I've actually created another empty div and I've given it an ID of suggestions. Much like we set the contents of the div that would display the price of the stock data, we now just want to set the contents of this div to whatever this string is which contains these symbols. By using this HTML method, this suggestions variable, this string, is a string of HTML. I want you to take that HTML and put it inside of the div called suggestions. We've just appended something to the DOM now. We've added some new elements to the DOM that we can now display on the page. Let's see what this looks like. If we load in quote6 and now we come back, now when I start typing a-a-p-l, we no longer have that Bootstrap autocomplete, but we now have this list that we made ourselves. This is a little bit uglier than the Bootstrap Typeahead, for example, but it does allow us to do one other thing. When we were looking at that Bootstrap plugin, we saw that when we autocompleted, one of the autocomplete values was a-a-p-l. That might not be so helpful. As a user, I might not immediately recognize all of the stock symbols. What I'm probably more likely to recognize are the company's actual names. So wouldn't it be really helpful if rather than saying a-a-p-l this said something like Apple Inc. Because we've rolled this ourselves, we can really easily do that. Let's open up our last quote file here, so quote7. Same thing. I've just created another PHP file that will return to us more than just the symbols. It will also give us back the company's names. And so we're doing the same thing. We're making an AJAX request. Once the request has completed, we're going to execute this function here, and this function is going to build up a big string of elements. But the difference here is that the value of these lists is no longer just the symbol, it's now the name. So we have one small problem. When we use our lookup, we need to somehow pass it the symbol. We can't pass lookup something like Microsoft Corporation. We need to pass it MSFT. When we're writing HTML, we have lots of nice built-in attributes. An A might have associated with it an href or a class. But what we really need now is for each of these links to have a stock symbol associated with it. There's no built-in HTML attribute for stock symbol, but luckily, HTML5 allows us to create our own attributes to be whatever we want. By saying data-symbol, I've introduced a new attribute whose name I just made up, and this is okay because I prefaced it with this data. We're going to store inside of there the symbol from the stock now. What that means is that even though we're displaying the value of the company's name inside of our autocomplete, we're still remembering the symbol that is associated with each company. The way we're doing that is inside of this element itself. So that means we need to make one more change. When we click it now, we need to actually take advantage of the symbol attribute rather than just its value. If we back up, we attach an event handler to suggestions. Whenever one of these suggestions is clicked now, I want to do something. What I want to do is change the value of that input box. Now I want to set this same val function. So without any arguments this val function returns to you what's already in the text box, but if you give it a string, it's going to take that string and put it into the text box. I'm selecting its text box in the same way. It's name is symbol inside of form-quote. Now I'm sending it the value of the attribute data-symbol. This thing here is new, this $(this). What this refers to is the element that was clicked. We can see here that we're not attaching a click event to each element with a class of suggestion individually. Rather, we're approaching this a little differently. Instead we're saying whenever anything inside of this suggestions div, which remember is just the container for that list, if something inside of this div is clicked and it has a class of suggestion, I want this event to fire. Basically what this means we can do is we can reuse this same event handler for all of the things in the list. So we don't have to have one event handler for the first element and a different event handler for the second element. We can instead say, "I want the same event handler to apply to everything in my list." But we need to somehow know which element was clicked. This "this" keyword represents just that. This is the object that was just clicked by the user. If I just clicked the 3rd link, this represents the element of that 3rd link, which means that I can get its attribute, data-symbol, which we know has to contain the symbol that's associated with the company I just clicked. If we jump back to our finance page, we can see now that once I start typing something like m-s-f-t, we're no longer getting just the stock symbols, we're now getting the actual companies. But when I click on one of these companies, we can see that we're actually populating the text box not with the name of the company but with whatever was stored inside of those data attributes. And so if I actually inspect one of these elements by right clicking it and clicking Inspect Element, we can actually see what this looks like. Remember this is something that we created inside of that for loop when we were building up that string of HTML. We can see here that this data-symbol has the value of MSFT, which is great. That's what we were expecting. That's the symbol and that's how we got the value that we needed to use inside of this text box. That's enough for the quote form because that's kind of boring. Let's just make some quick enhancements to our portfolio page. If you've used CS50 Finance for a while and you start buying and selling a lot of stocks, eventually this table is going to get pretty big, and you're going to want a stock ticker, of course. Once the table is really, really big, it could be useful for the user to try to search over it. Inside of the search box if I start typing something like Disney and looking for my Mickey Mouse stock, we can see that the table is now filtering based on what I just typed in. This functionality looks super complicated, but it's really, really easy with jQuery and JavaScript. This portfolio.php file includes a JavaScript file called portfolio.js. Let's take a look at that. So html, js, portfolio. Here's where we're doing that searching on the table. The first thing I need to do is attach an event handler to that text box because we know that we want our filtering function to fire every time the user presses something because we don't have time for Search buttons. The first thing we need to do is figure out what the user is searching for, just like we did before. This keyword refers to the current element the user is interacting with. Because the user is interacting with the search box, $ this represents the search box, so this.val gives us what's inside of the search box the user is currently typing. So, now what we want to do is we want to iterate over all of the rows inside of our table. To select all of the rows in our table, I gave that table an ID of table portfolio, and each row is represented by a TR element, so this selector is going to return to me a big array of all the rows in my table. Now I want to iterate over that array. I could you a for loop, but jQuery actually provides us the nice function called "each." What each does is each takes one argument, and that argument is a function. What it's going to do is it's going to apply that function to every element inside of this list. This function takes one argument that's e, and when this function is executed, this e is going to be replaced with the first row, then the second row, and then the third row. By this way, this is the same thing as running a for loop and then figuring the current element based on the index inside of your for loop. At each iteration, for each of these elements in the table, I want to check if the text of the element--the text of the cell inside of the row-- matches what I'm searching for. This big long string of commands is how I could do that. First, again, this now refers to--because it's inside of a new function-- this is now the current row in the table. I want to take the current row in the table, and I want to get all of its children. Remember, the DOM is a hierarchical tree, which means that elements have a number of children. This .children function is going to return to me back an array of all of the elements that are the children of, in this case, a row in the table. This is just simply the cells inside of the row. I just want to search over the first cell. This .first function says give me the first element in that array. Then the text function says get me exactly what's inside of that cell since I want to search over that text. Finally, let's convert it to lowercase, so we can do text case insensitive queries. Finally, we want to see if that string inside of a table contains the string we're searching for. The indexOf function in JavaScript does just that. It tells us whether or not this string contains another string. If it's true that the cell contains what I'm searching for, then I want to make sure that it's shown. The show method will say, "Show the element." If this is not the case, then that means whatever I'm searching for is not contained within that row, and so I want to hide is from the user. That achieves that nice filtering effect where no longer we see the entire table. If you're interested in how to make this ticker as well, we'll post the source online. But it's really simple. JQuery has awesome methods for these animations and manipulating CSS properties. So, that's it for me. What then lies ahead? As you'll see in a few days, the final projects proposal is due. The final projects proposal will ask you a few questions, but among them will be three milestones-- one a "good" milestone, one a better milestone, and one a best. The idea being really to help you guys set your expectations so that minimally you will be happy with the output of your final project and it will be "good" so far as you are concerned. But then in the interest of getting you to reach just a little bit to something better or something best, we'll also sort of push you toward that as well. The CS50 Hack-a-thon, meanwhile, is in a few weeks. Typically, we do this on a lottery basis basis because of interest, but odds are we'll take a few hundred of us in shuttle buses from Harvard Square down to Kendall Square where Microsoft has a beautiful facility aptly called "N.E.R.D."-- the New England Research and Development Center. We'll get there around 8 p.m. We'll have some food. Around 1 a.m. we'll have some more food. Around 5 a.m. if you're still awake we'll head over to IHOP or take you back to campus. The objective there is to dive into final projects alongside of classmates and staff. Then a few days later is the CS50 Fair, which is really meant to be a opportunity for you guys to showcase your work and accomplishments for the semester while rubbing shoulders with each other and getting a sense of what everyone did. With that said, many thanks to Tommy and to Joseph, and we will see you on Monday. [applause]