1 00:00:00,000 --> 00:00:02,700 [Week 9, Continued] 2 00:00:02,700 --> 00:00:05,160 [David J. Malan - Harvard University] 3 00:00:05,160 --> 00:00:07,020 [This is CS50. - CS50.TV] 4 00:00:07,940 --> 00:00:13,340 >> This is CS50. This is the end of week 9. Thank you very much. 5 00:00:13,340 --> 00:00:15,310 Finally. Week 9. I got it. 6 00:00:15,310 --> 00:00:18,590 Today we continue our conversation about web programming 7 00:00:18,590 --> 00:00:21,660 with an eye toward the final project, not because you have to do something web-based 8 00:00:21,660 --> 00:00:25,610 for final projects but because either for final projects or after CS50 9 00:00:25,610 --> 00:00:29,000 this is certainly the direction in which modern software is going. 10 00:00:29,000 --> 00:00:31,770 And yet it's not actually an easy thing. 11 00:00:31,770 --> 00:00:35,040 In fact, one of the hardest things to do is the aspect of design. 12 00:00:35,040 --> 00:00:38,600 >> For instance, by design we mean actually getting the user interface 13 00:00:38,600 --> 00:00:40,420 or the user experience right. 14 00:00:40,420 --> 00:00:43,200 I daresay--and we know from a recent problem set 15 00:00:43,200 --> 00:00:45,960 when a few of you aired your gripes about some piece of software 16 00:00:45,960 --> 00:00:49,000 or hardware that infuriates you, whether on campus or off-- 17 00:00:49,000 --> 00:00:51,930 there's a lot of sites out there, there's a lot of hardware out there, 18 00:00:51,930 --> 00:00:53,900 that kind of sucks. 19 00:00:53,900 --> 00:00:58,730 But the reality is that making things that are easy to use yet are nonetheless powerful 20 00:00:58,730 --> 00:01:00,550 is a very difficult challenge. 21 00:01:00,550 --> 00:01:03,680 So for today I asked Joseph and Tommy to join me up here 22 00:01:03,680 --> 00:01:06,680 so that we can have a conversation, both about design 23 00:01:06,680 --> 00:01:09,090 and what kinds of thought processes should start going through your head 24 00:01:09,090 --> 00:01:12,040 when you design your final projects, your future endeavors. 25 00:01:12,040 --> 00:01:15,040 And then with Tommy's help we'll look at some of the implementation details. 26 00:01:15,040 --> 00:01:18,440 How can you have some vision on paper or in your mind 27 00:01:18,440 --> 00:01:20,760 that you can then execute programmatically 28 00:01:20,760 --> 00:01:24,030 by using some of the technologies and techniques we've just started talking about, 29 00:01:24,030 --> 00:01:29,080 namely JavaScript and something even newer, namely AJAX, asynchronous JavaScript. 30 00:01:29,080 --> 00:01:32,950 That allows you to create all the more dynamic of a user interface 31 00:01:32,950 --> 00:01:35,780 by fetching more and more data progressively from a server. 32 00:01:35,780 --> 00:01:38,560 So we'll see some of those snippets as well today. 33 00:01:38,560 --> 00:01:41,800 As an aside, if you are interested in concentrating in computer science 34 00:01:41,800 --> 00:01:45,010 or minoring in computer science, know that this Friday at noon 35 00:01:45,010 --> 00:01:48,750 in Maxwell Dworkin 221 there will be a pizza event 36 00:01:48,750 --> 00:01:50,780 where you can learn a bit more about computer science. 37 00:01:50,780 --> 00:01:54,860 On your way out the door today you'll be able to pick up an unofficial guide to CS at Harvard. 38 00:01:54,860 --> 00:01:57,290 We'll put it on the trash cans outside at waist height 39 00:01:57,290 --> 00:01:59,750 so that if you'd like to grab this and learn a bit more about CS, 40 00:01:59,750 --> 00:02:02,480 that will be there for you as it was in week 0. 41 00:02:02,480 --> 00:02:06,500 Also if you would like to join us for CS50 lunch this Friday at 1:15pm, 42 00:02:06,500 --> 00:02:09,800 head to cs50.net/lunch. 43 00:02:09,800 --> 00:02:13,260 Without further ado, I give you teaching fellow Joseph Ong. 44 00:02:13,260 --> 00:02:19,190 Hi. [applause] 45 00:02:19,190 --> 00:02:20,770 Thanks. 46 00:02:20,770 --> 00:02:24,780 The first time I learned about design was in a class here called CS179. 47 00:02:24,780 --> 00:02:28,040 >> The professor at the time told us the story about another professor 48 00:02:28,040 --> 00:02:31,640 who had gone to a hotel and used the faucets. 49 00:02:31,640 --> 00:02:35,630 Can anyone tell me what the 2 knobs on the left and right do? 50 00:02:35,630 --> 00:02:39,080 [student] Hot and cold. >>Hot and cold. Good. 51 00:02:39,080 --> 00:02:41,430 What you normally expect, right? 52 00:02:41,430 --> 00:02:46,960 This professor after using the faucet wants to take a shower, and he proceeds to use this. 53 00:02:46,960 --> 00:02:51,310 He thinks the left and the right sides are for hot and cold, right? 54 00:02:51,310 --> 00:02:55,470 But can anyone tell me what these actually do? 55 00:02:55,470 --> 00:02:58,060 Any hands? 56 00:02:58,060 --> 00:03:01,740 [inaudible student response] >>One suggestion is? 57 00:03:01,740 --> 00:03:05,860 [inaudible student response] >>Temperature? 58 00:03:05,860 --> 00:03:10,460 So one of them controls temperature and the other controls? >>[student] Water pressure. 59 00:03:10,460 --> 00:03:12,350 Water pressure. Good. 60 00:03:12,350 --> 00:03:15,100 This professor walks into this and, thinking they are controlling hot and cold, 61 00:03:15,100 --> 00:03:21,470 turns the right one, which he thinks is for hot, all the way up 62 00:03:21,470 --> 00:03:23,560 because he wants to take a warm shower. 63 00:03:23,560 --> 00:03:28,100 Well, these don't really match up, so he gets this not very fun experience 64 00:03:28,100 --> 00:03:31,110 of being in a cold shower, and we all know what that feels like. 65 00:03:31,110 --> 00:03:33,620 This is an example of a design flaw. 66 00:03:33,620 --> 00:03:37,040 What I mean by that is his expectation from the faucet 67 00:03:37,040 --> 00:03:39,420 did not match what came out of the shower, 68 00:03:39,420 --> 00:03:41,780 which is kind of unfortunate for him. 69 00:03:41,780 --> 00:03:44,990 So this is an example of a design flaw that happens in real life. 70 00:03:44,990 --> 00:03:48,020 But we see all sorts of other ones as well. 71 00:03:48,020 --> 00:03:50,390 We're probably not fans of the MBTA system. 72 00:03:50,390 --> 00:03:55,560 This is a subway system actually in London, which says, "This button's not in use." 73 00:03:55,560 --> 00:04:00,220 Why is it even on there? Why do we even care? 74 00:04:00,220 --> 00:04:02,810 When I was a kid, being the tech savvy one in the house, 75 00:04:02,810 --> 00:04:05,050 whenever the computer would crash, my mom would come to me, 76 00:04:05,050 --> 00:04:07,060 showing me this screen and asking me what happened. 77 00:04:07,060 --> 00:04:09,210 >> Even I don't know what this means. 78 00:04:11,890 --> 00:04:14,700 [laughter] What? 79 00:04:16,950 --> 00:04:18,019 [laughter] 80 00:04:18,720 --> 00:04:23,050 Sometimes we feel like software developers are just trolling us. 81 00:04:23,050 --> 00:04:28,460 As users we're like, "What is going on? Someone tell us." 82 00:04:28,460 --> 00:04:32,140 This all comes down to an issue of design. 83 00:04:32,140 --> 00:04:34,650 Design, as we can see, is not purely about aesthetics, 84 00:04:34,650 --> 00:04:37,230 it's not about how things look. 85 00:04:37,230 --> 00:04:41,720 We see here that this little pop-up over here actually looks pretty nice. 86 00:04:41,720 --> 00:04:45,290 It has a drop shadow in the background, it has border radiuses going on. 87 00:04:45,290 --> 00:04:47,550 It's kind of pretty. 88 00:04:47,550 --> 00:04:51,480 It's not really well designed because it's not very user friendly. 89 00:04:51,480 --> 00:04:54,920 That little pop-up that comes up doesn't really give me any information 90 00:04:54,920 --> 00:04:58,450 about what's going on, it doesn't tell me anything as the user 91 00:04:58,450 --> 00:05:01,400 about how to recover from that error. 92 00:05:01,400 --> 00:05:05,190 We want to think about things that design is not. 93 00:05:05,190 --> 00:05:06,670 First, it's not aesthetics. 94 00:05:06,670 --> 00:05:10,800 It's also not stuffing your app with tons of unnecessary functionality. 95 00:05:10,800 --> 00:05:14,890 If you're a Thai restaurant, you probably don't want to be a dentist at the same time. 96 00:05:14,890 --> 00:05:17,720 And with Facebook Questions, not that many people used it 97 00:05:17,720 --> 00:05:21,130 and it wasn't really at the core of what they were building. 98 00:05:21,130 --> 00:05:24,200 And so it's nice to think about not so much the quantity of the things 99 00:05:24,200 --> 00:05:26,390 that you're putting to your application but the quality 100 00:05:26,390 --> 00:05:28,910 and how you're making that user experience better 101 00:05:28,910 --> 00:05:32,540 by actually improving upon what you already have. 102 00:05:32,540 --> 00:05:37,040 >> In a nutshell, design tells us what we should build. 103 00:05:37,040 --> 00:05:41,950 For example, if we're building something that let us search things up, 104 00:05:41,950 --> 00:05:45,970 like Google, for example, should we do things in a manner 105 00:05:45,970 --> 00:05:48,950 that requires the user to take lots of clicks to get to what they want, 106 00:05:48,950 --> 00:05:52,580 or should we do it in a way, for example, with Google Instant or autocomplete 107 00:05:52,580 --> 00:05:54,970 that lets us get to our results faster? 108 00:05:54,970 --> 00:05:58,740 Engineering involves, like Tommy will show you, actually building it. 109 00:05:58,740 --> 00:06:01,890 There are lots of types of design. 110 00:06:01,890 --> 00:06:06,070 For example, if you're building something to deploy something 111 00:06:06,070 --> 00:06:09,770 in a Third World country where there isn't much electricity or that much technology, 112 00:06:09,770 --> 00:06:11,440 you have to design what you're building 113 00:06:11,440 --> 00:06:14,210 in a way that easily gives access to the people there. 114 00:06:14,210 --> 00:06:18,290 But what sorts of other design decisions might there be 115 00:06:18,290 --> 00:06:21,850 or might be involved in something like this? 116 00:06:23,690 --> 00:06:25,660 Yeah. I see a hand. 117 00:06:25,660 --> 00:06:37,200 [inaudible student response] >>Right. Exactly. Accessibility is one thing. 118 00:06:37,200 --> 00:06:40,870 A lot of people don't think about, "What about my users?" 119 00:06:40,870 --> 00:06:43,160 like the extremes of either spectrum. 120 00:06:43,160 --> 00:06:47,770 I have users who might have disabilities that I'm not thinking about 121 00:06:47,770 --> 00:06:50,590 and I'm just thinking about designing for the general user. 122 00:06:50,590 --> 00:06:52,630 The Internet is accessible by everyone nowadays, 123 00:06:52,630 --> 00:06:54,870 and I should be designing for those people as well. 124 00:06:54,870 --> 00:06:58,620 What sorts of other design decisions might you make? 125 00:06:58,620 --> 00:07:00,690 Yes. >>[student] Cost. 126 00:07:00,690 --> 00:07:02,680 Cost. Very good. 127 00:07:02,680 --> 00:07:08,060 Another thing we might base our design decisions on are cost. 128 00:07:08,060 --> 00:07:13,130 If we're a business, you want to build something that doesn't take much cost to produce 129 00:07:13,130 --> 00:07:17,720 but can sell at a particularly high cost or can get us some profit. 130 00:07:17,720 --> 00:07:21,540 >> These are all different types of design, but when we're building something on the Internet 131 00:07:21,540 --> 00:07:25,120 or when we're building something that probably doesn't cost that much to build up now, 132 00:07:25,120 --> 00:07:28,630 like Internet applications--you don't have to throw much capital into it 133 00:07:28,630 --> 00:07:30,900 in order to make something that actually works-- 134 00:07:30,900 --> 00:07:33,490 what we're more worried about is the user experience. 135 00:07:33,490 --> 00:07:36,390 We call this user centered design. 136 00:07:36,390 --> 00:07:41,550 Essentially what user centered design involves is putting yourselves in the shoes of your users. 137 00:07:41,550 --> 00:07:44,870 If someone signs up for what I'm building, 138 00:07:44,870 --> 00:07:48,250 they've obviously come to my particular application with a goal in mind, 139 00:07:48,250 --> 00:07:50,280 with a task they want to complete. 140 00:07:50,280 --> 00:07:53,650 And your job is not only to help them complete that task 141 00:07:53,650 --> 00:07:57,930 but to help them complete that task in a manner that is efficient, intuitive, 142 00:07:57,930 --> 00:08:01,900 and, as some person said over there, accessible. 143 00:08:01,900 --> 00:08:03,750 What does efficiency mean? 144 00:08:03,750 --> 00:08:08,050 Efficiency means how quickly does my user complete the task given my interface. 145 00:08:08,050 --> 00:08:11,650 Does it take lots of clicks for them to get from one place to the other? 146 00:08:11,650 --> 00:08:14,630 Is it tedious? Do they have to perform lots of repetitive tasks? 147 00:08:14,630 --> 00:08:17,140 We want to make that process as efficient as possible 148 00:08:17,140 --> 00:08:20,070 so they don't have to do those sorts of things. 149 00:08:20,070 --> 00:08:24,230 As for intuitiveness, that is, for example, if a user looks up my interface, 150 00:08:24,230 --> 00:08:27,240 is it easy for them to get from place to place? 151 00:08:27,240 --> 00:08:30,390 Is it easy for them to figure out what they have to click in my interface 152 00:08:30,390 --> 00:08:33,770 in order for them to achieve the goal or task that they want to achieve? 153 00:08:33,770 --> 00:08:37,520 >> And finally, as one person said over there, accessibility is very important. 154 00:08:37,520 --> 00:08:39,640 [male speaker] It comes to accessibility for things like vision, 155 00:08:39,640 --> 00:08:42,740 like how do I actually design something for someone who is blind? 156 00:08:42,740 --> 00:08:46,460 Oh. For people who can't see at all, we have something called screen readers. 157 00:08:46,460 --> 00:08:49,070 What you should do is you should build your website in a way 158 00:08:49,070 --> 00:08:52,020 that, for example, particular technologies what we call-- 159 00:08:52,020 --> 00:08:53,590 There are lots of things now. 160 00:08:53,590 --> 00:08:55,660 I think there are screen readers called JAWS. 161 00:08:55,660 --> 00:08:58,410 A lot of these things rely on what we call area rules 162 00:08:58,410 --> 00:09:02,010 in order to read out to the user what is present on the page. 163 00:09:02,010 --> 00:09:05,480 For those people who can't see, you need to make sure that these screen readers 164 00:09:05,480 --> 00:09:09,130 can actually pick up the content on the page and can actually show your users, 165 00:09:09,130 --> 00:09:13,630 if you can't see, at least you can still understand the content on the page. 166 00:09:13,630 --> 00:09:16,190 Yeah. Okay. 167 00:09:16,190 --> 00:09:23,410 Enough talking about good design. Let's talk about bad design. 168 00:09:23,410 --> 00:09:25,220 These are things that you should not do. 169 00:09:25,220 --> 00:09:27,890 Can anyone tell me about their experiences with Craigslist 170 00:09:27,890 --> 00:09:32,190 and what they think is not so great about this design? 171 00:09:33,690 --> 00:09:36,430 Yes. >>[student] I think there's too many words in one area. 172 00:09:36,430 --> 00:09:39,350 Too many words, right? Completely overwhelming. 173 00:09:39,350 --> 00:09:42,400 You come to this page and you're greeted with a whole bunch of things up here 174 00:09:42,400 --> 00:09:43,860 that might not even matter to you. 175 00:09:43,860 --> 00:09:47,010 For example, you live in one state that does not begin with this letter. 176 00:09:47,010 --> 00:09:48,690 Let's say you live in Texas or something. 177 00:09:48,690 --> 00:09:53,790 >> You have to scroll all the way down the page to get to the location you are at. 178 00:09:53,790 --> 00:10:00,320 I'm from Boston, so let me look in Massachusetts. Where is Massachusetts? 179 00:10:00,320 --> 00:10:03,270 Oh, it's right here. Oh, it's Boston. Okay. 180 00:10:03,270 --> 00:10:09,070 Let's look at Boston. [laughter] 181 00:10:09,070 --> 00:10:12,250 Pretty overwhelming, right? 182 00:10:12,250 --> 00:10:16,400 Awkward things over there. [laughter] 183 00:10:17,320 --> 00:10:19,470 Let's say I'm looking for somewhere to live. 184 00:10:19,470 --> 00:10:24,130 How many people have actually used Craigslist? Tons of you. 185 00:10:24,130 --> 00:10:30,960 There are pretty bad ways to look at this, but let's look at this. 186 00:10:35,130 --> 00:10:38,970 What's the difference between img and pic? Can anyone tell me? 187 00:10:41,350 --> 00:10:42,830 There actually is no difference. 188 00:10:42,830 --> 00:10:47,710 They mean exactly the same thing, but they have different labels for them for some reason. 189 00:10:48,980 --> 00:10:53,560 If I click on Has Image, nothing happens on the page. 190 00:10:53,560 --> 00:10:57,490 I actually have to click Search again for something to happen. 191 00:10:57,490 --> 00:11:02,430 What might be a better design decision that could be done there? 192 00:11:03,820 --> 00:11:08,030 If I'm clicking on that filter, I probably want to filter by that particular action 193 00:11:08,030 --> 00:11:09,970 or that particular category. 194 00:11:09,970 --> 00:11:14,450 So instead of having to press Search again, I could just automatically do the filtering 195 00:11:14,450 --> 00:11:17,060 sort of Google style where they do it instantly. 196 00:11:17,060 --> 00:11:20,440 [Malan] But don't forms as we've seen them thus far have to be physically submitted 197 00:11:20,440 --> 00:11:23,170 by hitting Enter at least or clicking a button? 198 00:11:23,170 --> 00:11:26,830 As you've seen them so far, you actually have to click Submit to do those things. 199 00:11:26,830 --> 00:11:30,090 >> But as Tommy will show you in a second, there are actually ways for you 200 00:11:30,090 --> 00:11:33,010 such that when you click on that thing it can automatically send 201 00:11:33,010 --> 00:11:38,840 what we call an AJAX request and get data back and filter your results instantaneously. 202 00:11:38,840 --> 00:11:41,340 There are tons of things that are wrong with this interface. 203 00:11:41,340 --> 00:11:43,530 [Malan] Can you search for Cambridge? 204 00:11:43,530 --> 00:11:47,030 There's something slightly anomalous here where you care about Cambridge 205 00:11:47,030 --> 00:11:54,790 and yet you're getting Westford, Spring Hill, West Newton and the like. 206 00:11:54,790 --> 00:11:57,930 Probably not ideal. >>Probably not ideal. 207 00:11:57,930 --> 00:12:03,900 How might I be able to make the user's experience better on this particular page? 208 00:12:03,900 --> 00:12:07,340 Yes. >>[student] Instructions. 209 00:12:07,340 --> 00:12:09,500 Okay. Instructions in what sort of sense? 210 00:12:09,500 --> 00:12:14,630 [student] For example, a thing for first time users who don't even know what Craigslist is 211 00:12:14,630 --> 00:12:17,320 or you don't know what you're supposed to do. 212 00:12:17,320 --> 00:12:20,150 Right. So explaining what Craigslist is on this page is important. 213 00:12:20,150 --> 00:12:23,490 We can actually tell users what this page is actually for. 214 00:12:23,490 --> 00:12:27,090 If I'm just visiting this, I see a whole bunch of locations. I don't even know what they mean. 215 00:12:27,090 --> 00:12:29,730 But more importantly, just looking at this interface, 216 00:12:29,730 --> 00:12:35,530 remember I had to scroll down a ton of things to find a particular community 217 00:12:35,530 --> 00:12:37,560 that I actually cared about on this. 218 00:12:37,560 --> 00:12:39,820 What's a faster way I could do that? Yes. 219 00:12:39,820 --> 00:12:43,290 [student] Divide them up into east, west regions. >>Okay. 220 00:12:43,290 --> 00:12:47,460 I could divide them into more categories that could help me faster determine 221 00:12:47,460 --> 00:12:49,820 how to get to that particular location. 222 00:12:49,820 --> 00:12:54,510 [student] Put a drop-down list. >>Right. Okay. 223 00:12:54,510 --> 00:12:58,240 I could use a drop-down menu because we have a fixed set of things 224 00:12:58,240 --> 00:13:00,100 and we could show them in a drop-down menu. 225 00:13:00,100 --> 00:13:02,240 That way it doesn't take up so much space on the screen. 226 00:13:02,240 --> 00:13:05,630 But even better than that, what can we do? 227 00:13:05,630 --> 00:13:09,220 Yes. >>[inaudible student response] >>Can you say that again? >>[student] Search box. 228 00:13:09,220 --> 00:13:11,260 Yeah, a search box. That's great. 229 00:13:11,260 --> 00:13:16,430 What we can actually do is if we look back at the slides, search box. 230 00:13:16,430 --> 00:13:21,520 Autocomplete. Very easy way to search through results that you know are in a set. 231 00:13:21,520 --> 00:13:25,980 If I start typing B-O, just show me all the results that have B-O inside of them. 232 00:13:25,980 --> 00:13:29,030 That way I can very easily find the particular one I want to go to 233 00:13:29,030 --> 00:13:32,390 instead of having to scroll through this really big list. 234 00:13:32,390 --> 00:13:37,450 >> These are all sorts of really low-hanging fruit that someone who is implementing Craigslist 235 00:13:37,450 --> 00:13:42,500 can actually do to make the experience on the website a lot better for their particular user. 236 00:13:42,500 --> 00:13:46,370 Okay. Enough talking about bad websites. 237 00:13:46,370 --> 00:13:49,410 Let's talk about Facebook. 238 00:13:50,880 --> 00:13:54,390 When Facebook came out, and particularly Facebook photos, 239 00:13:54,390 --> 00:13:57,870 there were lots of other services at the time which could do exactly the same things. 240 00:13:57,870 --> 00:14:00,740 They could organize your photos into albums. 241 00:14:00,740 --> 00:14:03,360 What you could do is you could organize them into sets as well. 242 00:14:03,360 --> 00:14:06,070 You could organize them by date. You could do all these particular things. 243 00:14:06,070 --> 00:14:11,710 But does anyone know what made Facebook photos explode at the time it was released? 244 00:14:11,710 --> 00:14:15,080 Yes. >>[student] Tags. >>Tags. Exactly. 245 00:14:15,080 --> 00:14:21,300 We have Milo over here, who is our dog mascot with that CS50 bandana. 246 00:14:21,300 --> 00:14:24,810 You can see that we have this tagging feature in the middle. 247 00:14:24,810 --> 00:14:28,240 And what made Facebook photos so interesting from a usability standpoint 248 00:14:28,240 --> 00:14:34,130 is that it actually allowed people via this to involve their friends in their photos. 249 00:14:34,130 --> 00:14:37,680 For Facebook, since their website is particularly social, 250 00:14:37,680 --> 00:14:40,750 it's about building this sort of social atmosphere. 251 00:14:40,750 --> 00:14:42,620 That improved the experience of photos a lot more 252 00:14:42,620 --> 00:14:46,390 because they could actually start saying, "These are connections between people, 253 00:14:46,390 --> 00:14:49,220 and these are photos about people you actually care about." 254 00:14:49,220 --> 00:14:52,200 Part of it is also sort narcissism. 255 00:14:52,200 --> 00:14:54,980 People like to be tagged in photos and things like that. 256 00:14:54,980 --> 00:14:58,510 While that's not necessarily a good human trait, 257 00:14:58,510 --> 00:15:01,910 at the same time it's based on good design decisions 258 00:15:01,910 --> 00:15:04,860 because people actually care about things like this. 259 00:15:04,860 --> 00:15:07,190 So that's Facebook photos. 260 00:15:07,190 --> 00:15:09,800 >> But let's talk Facebook more generally. 261 00:15:09,800 --> 00:15:13,400 I'm sure lots of people here have opinions about Facebook, 262 00:15:13,400 --> 00:15:16,430 both good design decisions and bad design decisions. 263 00:15:16,430 --> 00:15:20,270 So let's vent or be happy. 264 00:15:23,480 --> 00:15:26,450 Come on. I know all of you use Facebook. 265 00:15:26,450 --> 00:15:30,970 Someone has to have something bad to say or something good to say about it. Yes. 266 00:15:30,970 --> 00:15:35,060 [student] In the news feed there's a lot of things I don't really care about. 267 00:15:35,060 --> 00:15:37,740 The news feed does show a lot of things you might not care about. 268 00:15:37,740 --> 00:15:41,660 You have friends on Facebook who you haven't met for 2 or 3 years 269 00:15:41,660 --> 00:15:43,860 and you see their news results popping up in your news feed 270 00:15:43,860 --> 00:15:45,870 and you don't really care about it. 271 00:15:45,870 --> 00:15:48,700 Facebook has actually made an effort to make this better, 272 00:15:48,700 --> 00:15:53,150 and they've actually tried to push relevant results to the top of the news feed as of late 273 00:15:53,150 --> 00:15:58,300 so you actually see things by friends which are relevant to you or your close friends. 274 00:15:58,300 --> 00:16:01,110 Anything else? Yes. 275 00:16:01,110 --> 00:16:06,400 [inaudible student response] >>Can you say that again? 276 00:16:06,400 --> 00:16:10,140 [student] The ads are relatively unobtrusive. >>In what sense? 277 00:16:10,140 --> 00:16:16,370 [inaudible student response] They don't have light on the screen, like banners. 278 00:16:16,370 --> 00:16:17,760 Okay. That's good. 279 00:16:17,760 --> 00:16:25,030 If you remember the Internet from the '90s-- >>[Malan] I was there. >>He was there. [laughter] 280 00:16:25,030 --> 00:16:29,210 You might remember flashing GIFs backgrounds, sparkly things, 281 00:16:29,210 --> 00:16:31,570 GeoCities style sort of things. 282 00:16:31,570 --> 00:16:34,080 That's really not an example of a good design 283 00:16:34,080 --> 00:16:36,690 because it's really distracting from the content. 284 00:16:36,690 --> 00:16:39,590 The Yale art website used to have animated GIFs as their background 285 00:16:39,590 --> 00:16:41,800 and you couldn't read anything on the page, 286 00:16:41,800 --> 00:16:44,870 but I guess someone actually talked to them and now it's a bit different. 287 00:16:44,870 --> 00:16:48,940 [Malan] It's much better now. >>It's much better now, as you can see. >>[Malan] Oh yeah. 288 00:16:48,940 --> 00:16:56,020 Just great, just-- Yeah. Okay. 289 00:16:56,020 --> 00:17:00,560 >> Part of it is also making your page possibly very minimalist and very understandable 290 00:17:00,560 --> 00:17:05,690 so things on the page flow in a way that is very logical and don't get in the way of each other. 291 00:17:05,690 --> 00:17:11,849 What sorts of other things are good about Facebook or bad about Facebook? 292 00:17:11,849 --> 00:17:15,730 Let's just have a design conversation here. 293 00:17:19,470 --> 00:17:21,339 Oh. Where? Yeah. 294 00:17:21,339 --> 00:17:25,640 [student] The new Timeline system allows you to search the person's profile about their past. 295 00:17:25,640 --> 00:17:28,119 Ooh, Timeline. 296 00:17:28,119 --> 00:17:30,280 Timeline is a great thing because it lets you stalk your friends 297 00:17:30,280 --> 00:17:33,300 back when they were in high school. 298 00:17:35,160 --> 00:17:38,060 Timeline is good because it lets you filter through content a lot faster, 299 00:17:38,060 --> 00:17:41,500 it lets you find things that would have otherwise taken you a really long time to find 300 00:17:41,500 --> 00:17:45,840 just scrolling up and down, up, up, up, up, up, like going back in time. 301 00:17:45,840 --> 00:17:48,910 But then there's also sort of a downside to that in terms of user experience. 302 00:17:48,910 --> 00:17:51,190 What might that be? 303 00:17:51,190 --> 00:17:56,780 Big word that starts with P-R. >>[student] Privacy. >>Privacy, right? 304 00:17:56,780 --> 00:17:59,970 Privacy is a huge user experience issue. 305 00:17:59,970 --> 00:18:07,190 This is one of the things I hate most about Facebook now. [laughter] 306 00:18:07,190 --> 00:18:09,000 [Malan] As do I now. 307 00:18:09,000 --> 00:18:11,380 David didn't realize this actually happened until yesterday. 308 00:18:11,380 --> 00:18:14,560 So now he knows that every time I chat him I know he's been ignoring me. 309 00:18:14,560 --> 00:18:16,880 [Malan] The awkward part was I was actually ignoring him, 310 00:18:16,880 --> 00:18:21,040 and I didn't know he knew I was ignoring him. [laughter] 311 00:18:21,040 --> 00:18:24,030 Privacy is a huge issue. 312 00:18:24,030 --> 00:18:28,670 Can anyone here tell me what might be bad about Facebook privacy 313 00:18:28,670 --> 00:18:32,270 besides the fact that they do things like this? 314 00:18:32,270 --> 00:18:37,240 What is it particularly hard to do with respect to Facebook privacy? 315 00:18:37,240 --> 00:18:40,340 That sort of is a leading question. 316 00:18:41,680 --> 00:18:43,930 Yes. >>[student] Hide your photos from certain people. 317 00:18:43,930 --> 00:18:46,170 Right. Exactly, to hide your photos from certain people. 318 00:18:46,170 --> 00:18:51,290 They have this small, little button in the upper right that lets you toggle the privacy of a photo. 319 00:18:51,290 --> 00:18:56,360 Their privacy options are very varied between different sorts of menus. 320 00:18:56,360 --> 00:18:59,510 >> They've gotten a lot better about it recently, but it used to be the case 321 00:18:59,510 --> 00:19:04,870 that whenever you wanted to prevent your friends from seeing photos, 322 00:19:04,870 --> 00:19:08,280 you would have to go through a very complicated 5-step process of being like, 323 00:19:08,280 --> 00:19:11,150 let me click this link, now let me click again, let me click again, 324 00:19:11,150 --> 00:19:13,420 let me specify which people can't see my photos. 325 00:19:13,420 --> 00:19:17,250 That is not particularly good on Facebook's part 326 00:19:17,250 --> 00:19:20,530 because so much about user experience is actually giving them the freedom 327 00:19:20,530 --> 00:19:22,460 to control what people can see. 328 00:19:22,460 --> 00:19:25,550 We call this user control and freedom. 329 00:19:25,550 --> 00:19:31,090 If you're not letting your users do that in a way that is efficient and intuitive, 330 00:19:31,090 --> 00:19:34,570 then your user experience isn't really that great at all. 331 00:19:34,570 --> 00:19:38,200 Would you guys like to say anything about Facebook? 332 00:19:38,700 --> 00:19:41,420 How do I turn this off? 333 00:19:41,420 --> 00:19:46,290 [Ong] You can't turn this off, and that is a huge usability flaw on the part of Facebook. 334 00:19:46,290 --> 00:19:49,410 This feature--I actually looked into it yesterday-- 335 00:19:49,410 --> 00:19:53,940 it's either that you can't do it or it's buried somewhere very, very deep 336 00:19:53,940 --> 00:19:58,050 in the recesses of Facebook because I can't figure out how to disable this functionality at all. 337 00:19:58,050 --> 00:20:00,400 [Malan] But sometimes these decisions aren't obvious 338 00:20:00,400 --> 00:20:03,890 because you guys have given us a lot of useful feedback on various CS50 applications 339 00:20:03,890 --> 00:20:05,710 and websites that the course uses. 340 00:20:05,710 --> 00:20:10,260 We have not implemented all of these requests and suggestions. 341 00:20:10,260 --> 00:20:14,550 >> Part of that is for getting so many requests that it's a function of time, 342 00:20:14,550 --> 00:20:17,070 but sometimes we just make a conscious decision like, 343 00:20:17,070 --> 00:20:19,830 "Thank you for the suggestion, but we disagree." 344 00:20:19,830 --> 00:20:24,350 So how do you actually decide what you should do if your users think you should do something 345 00:20:24,350 --> 00:20:28,110 even if you don't necessarily? 346 00:20:28,110 --> 00:20:32,360 It's a fine balance between actually listening to what your users say 347 00:20:32,360 --> 00:20:35,840 and actually having some sort of line where you say, 348 00:20:35,840 --> 00:20:37,750 "We're not going to do what these users say." 349 00:20:37,750 --> 00:20:42,520 And in particular, I think there was a quote by Henry Ford that sums this up pretty well. 350 00:20:42,520 --> 00:20:47,130 "If I had asked people what they wanted, they would have said they wanted faster horses." 351 00:20:47,130 --> 00:20:51,840 Can anyone sort of tease apart what that quote really means? 352 00:20:51,840 --> 00:20:56,060 It's not just that users know what they want, 353 00:20:56,060 --> 00:20:59,180 but it's more that-- 354 00:20:59,180 --> 00:21:02,720 [student] They don't know what's possible. 355 00:21:02,720 --> 00:21:06,140 In part they don't know what is possible. 356 00:21:07,880 --> 00:21:11,440 Tease that apart a little bit more. What do you mean by that? 357 00:21:11,440 --> 00:21:21,340 [inaudible student response] 358 00:21:21,340 --> 00:21:25,770 That's good. What I think we're trying to say here is that people know what they want. 359 00:21:25,770 --> 00:21:28,050 They want faster horses. 360 00:21:28,050 --> 00:21:29,840 What they really want is the ability to move faster, 361 00:21:29,840 --> 00:21:32,310 but they don't really know the medium by which to achieve that. 362 00:21:32,310 --> 00:21:36,330 When you come to your users and your users tell you something 363 00:21:36,330 --> 00:21:39,700 and they tell you, "We want these features and these features and these features," 364 00:21:39,700 --> 00:21:42,650 you don't want to necessarily think about, "Let me go ahead 365 00:21:42,650 --> 00:21:44,720 "and implement what they explicitly say," 366 00:21:44,720 --> 00:21:48,610 but what you want to think about is, "What sort of ideas can I get from that?" 367 00:21:48,610 --> 00:21:50,450 What do they actually want? 368 00:21:50,450 --> 00:21:55,560 >> And from there what you can do is design something that satisfies those requests 369 00:21:55,560 --> 00:22:00,340 but not necessarily in the way that the user expects it to be satisfied. 370 00:22:00,340 --> 00:22:03,830 So for something like final projects, in very real terms, 371 00:22:03,830 --> 00:22:07,900 what's a useful heuristic when it comes to making something better, 372 00:22:07,900 --> 00:22:10,630 especially if the designer has this arrogance about him 373 00:22:10,630 --> 00:22:14,360 whereby you sort of know what's best, you might take input from your users, 374 00:22:14,360 --> 00:22:16,580 but how do you actually go about getting that feedback? 375 00:22:16,580 --> 00:22:21,610 In final projects, very concretely, what produces optimal results here? 376 00:22:21,610 --> 00:22:25,030 What produces optimal results--and I will go over this in a second-- 377 00:22:25,030 --> 00:22:29,190 is this process of developing and then testing and then iterating. 378 00:22:29,190 --> 00:22:32,020 What I mean by testing is usually when you design something 379 00:22:32,020 --> 00:22:36,970 you think it's fairly good, like, "I'm such a great designer. Everyone is going to love this." 380 00:22:36,970 --> 00:22:41,600 And then you put it out there and people don't really like it for some reason. 381 00:22:41,600 --> 00:22:46,820 What you have to do is you have to take the parts of things that people do like 382 00:22:46,820 --> 00:22:49,180 and revamp the things that people don't like. 383 00:22:49,180 --> 00:22:53,080 It sounds like a very obvious process, but this process of constantly iterating 384 00:22:53,080 --> 00:22:55,980 on top of what you've already built is a process that helps you 385 00:22:55,980 --> 00:22:59,730 not only refine your own design skills but also helps you refine the design 386 00:22:59,730 --> 00:23:03,790 so that people actually appreciate your product even more than they did before. 387 00:23:03,790 --> 00:23:07,390 >> I'll go over more concrete examples of what you might actually do. 388 00:23:07,390 --> 00:23:11,390 As sort of a last example of a product, let's look at KAYAK. 389 00:23:11,390 --> 00:23:14,970 KAYAK when it came out was very, very popular. 390 00:23:14,970 --> 00:23:18,760 Can anyone guess why? 391 00:23:18,760 --> 00:23:20,950 What are the sorts of things you like about this if you have used it 392 00:23:20,950 --> 00:23:23,990 or what are the sorts of things you don't like? 393 00:23:23,990 --> 00:23:31,590 Yes. >>[inaudible student response] >>Okay. 394 00:23:31,590 --> 00:23:34,730 That's part of it is letting the user have a query that is more expansive 395 00:23:34,730 --> 00:23:38,150 than a very restrictive one like, "You have to pick your start date 396 00:23:38,150 --> 00:23:39,810 "and you have to pick your end date." 397 00:23:39,810 --> 00:23:44,910 In fact, it lets you be flexible about it and it gives you all of the flights in that range. 398 00:23:44,910 --> 00:23:46,730 Anything else? 399 00:23:46,730 --> 00:23:50,530 [student] They include the fees in the price. 400 00:23:50,530 --> 00:23:53,330 They do include the fees in the price. 401 00:23:53,330 --> 00:23:56,720 The taxes and things actually go straight into that price in the upper left 402 00:23:56,720 --> 00:24:00,710 so you're not tricked into thinking that you're actually paying for a $240 flight 403 00:24:00,710 --> 00:24:03,280 when it's really $330. 404 00:24:03,280 --> 00:24:06,200 Anything else? Yes. 405 00:24:06,200 --> 00:24:10,140 [inaudible student response] 406 00:24:10,140 --> 00:24:14,610 I'm not sure if they actually let you do that. 407 00:24:14,610 --> 00:24:18,310 I might be wrong. 408 00:24:18,310 --> 00:24:23,360 That might be an interesting thing if you want to put more weight on particular filters 409 00:24:23,360 --> 00:24:27,000 so that they push results related to that filter to the top. 410 00:24:27,000 --> 00:24:31,920 But can anyone tell me what's so special about this left side? 411 00:24:31,920 --> 00:24:39,540 How did you traditionally look up a flight on an Internet service before this? 412 00:24:41,600 --> 00:24:44,650 >> Yes. >>[inaudible student response] >>Can you say that-- 413 00:24:44,650 --> 00:24:47,530 [student] Each airline. >>Yeah. Each airline has its own website. 414 00:24:47,530 --> 00:24:50,110 This consolidates things. And? 415 00:24:50,110 --> 00:24:52,190 [student] You know exactly what time you're leaving. 416 00:24:52,190 --> 00:24:54,460 You do know exactly what time you're leaving, 417 00:24:54,460 --> 00:24:59,380 but related to the filters in particular. 418 00:25:00,710 --> 00:25:03,540 Let me pull up KAYAK. 419 00:25:11,490 --> 00:25:14,020 Oh God, pop-ups. Bad user experience. 420 00:25:14,020 --> 00:25:17,230 What happens when I move this slider? 421 00:25:17,230 --> 00:25:21,010 [student] Automatic updates. >>[Ong] Automatic updates. 422 00:25:21,010 --> 00:25:23,440 That's something that's very important. 423 00:25:23,440 --> 00:25:25,380 Before this, whenever you wanted to look up a flight, 424 00:25:25,380 --> 00:25:28,410 you had to put in your input location, your output location, press Search, 425 00:25:28,410 --> 00:25:31,190 it would process that and show your results. 426 00:25:31,190 --> 00:25:34,120 If you wanted to change your query, you would have to press back twice, 427 00:25:34,120 --> 00:25:39,770 enter in a new query from scratch, and then do it over and over again. 428 00:25:39,770 --> 00:25:43,910 The nice thing about something like this is it uses a very [unintelligible] thing in the middle. 429 00:25:43,910 --> 00:25:46,230 Whenever you do something like this, it shoots off a request 430 00:25:46,230 --> 00:25:48,420 and it returns you all the results immediately. 431 00:25:48,420 --> 00:25:51,680 This sort of immediate feedback is something that made KAYAK wildly popular 432 00:25:51,680 --> 00:25:55,910 because it's really easy for me to just change my query 433 00:25:55,910 --> 00:25:58,890 and to figure out the things that are around a particular range 434 00:25:58,890 --> 00:26:01,950 without having to go back and forth, back and forth, back and forth. 435 00:26:01,950 --> 00:26:05,200 So these are all sorts of things you want to think about when you're designing your website. 436 00:26:05,200 --> 00:26:08,930 How can I make it very efficient for my users to go through whatever they're working on 437 00:26:08,930 --> 00:26:13,010 and to get to their eventual goal as quickly as possible? 438 00:26:13,010 --> 00:26:16,430 [Malan] And to Joseph's point earlier about users not necessarily knowing what they want, 439 00:26:16,430 --> 00:26:18,640 based on what you guys now know about HTML 440 00:26:18,640 --> 00:26:22,780 and you have checkboxes, radio buttons, select menus, input fields and the like, 441 00:26:22,780 --> 00:26:26,140 how would you implement the notion of picking a start time for a flight? 442 00:26:26,140 --> 00:26:30,030 >> Which of those various UI mechanisms would you use? 443 00:26:30,030 --> 00:26:34,100 If you just know the amount of HTML that was taught before 444 00:26:34,100 --> 00:26:39,070 and you know the inputs are radio buttons, checkboxes, drop-downs, and input box, 445 00:26:39,070 --> 00:26:43,320 what would your natural choice have been for picking dates? 446 00:26:43,320 --> 00:26:48,670 [student] Input. >>Input. Or maybe even a drop-down with all of the dates, right? 447 00:26:48,670 --> 00:26:53,170 So with more complex UI mechanisms like this on the left side that you can implement, 448 00:26:53,170 --> 00:26:55,500 you can make this process much more intuitive with a slider 449 00:26:55,500 --> 00:27:01,020 because time is continuous, and people usually don't think of it in terms of discrete chunks. 450 00:27:01,020 --> 00:27:04,950 All right. Last thing. 451 00:27:04,950 --> 00:27:07,370 Ten usability heuristics. 452 00:27:07,370 --> 00:27:10,820 All the things we talked about probably fall under one of these categories. 453 00:27:10,820 --> 00:27:14,420 If you go to this link, which the sites will be posted online, 454 00:27:14,420 --> 00:27:18,900 you'll actually be able to, as you design your site, keep these heuristics in mind 455 00:27:18,900 --> 00:27:21,330 and these rules of thumb. 456 00:27:21,330 --> 00:27:26,610 For your projects, what I suggest you do in order to design your app better 457 00:27:26,610 --> 00:27:28,850 is to do paper prototyping first. 458 00:27:28,850 --> 00:27:32,150 When you're thinking about your application, very quickly sketch what you want it to look like 459 00:27:32,150 --> 00:27:36,230 and make sure all the boxes are arranged in a way that is very intuitive for the user to use 460 00:27:36,230 --> 00:27:39,820 and even show these paper prototypes to your friends and start focus groups. 461 00:27:39,820 --> 00:27:44,230 Just get 2 or 3 people together and ask them to just tap on these paper prototypes, 462 00:27:44,230 --> 00:27:47,650 and show them new screens to see if they actually understand what's going on. 463 00:27:47,650 --> 00:27:50,680 >> What you want to do is give them a task, motivate that task, 464 00:27:50,680 --> 00:27:53,270 and just give them the app and let them use it. 465 00:27:53,270 --> 00:27:56,530 Don't give them instructions beyond that. 466 00:27:56,530 --> 00:28:00,920 You want to actually let them interact with your app in a way that lets you see 467 00:28:00,920 --> 00:28:03,870 how they would use it if you weren't standing next to them. 468 00:28:03,870 --> 00:28:05,250 And that's very important. 469 00:28:05,250 --> 00:28:08,780 That will give you lots of insights as to are people getting around particular things 470 00:28:08,780 --> 00:28:10,560 in a way that I didn't intend them to? 471 00:28:10,560 --> 00:28:14,680 Are they using particular UI mechanisms on the screen 472 00:28:14,680 --> 00:28:17,490 in a way that is kind of hacky? 473 00:28:17,490 --> 00:28:22,020 I didn't intend for them to do it that way. 474 00:28:22,020 --> 00:28:23,940 And once you're done with that, what do you want to do? 475 00:28:23,940 --> 00:28:26,010 Your design rocks, right? 476 00:28:26,010 --> 00:28:29,600 What you want to do is you want to develop and then do that process over again. 477 00:28:29,600 --> 00:28:32,110 So show it to friends once you've developed it, test it, 478 00:28:32,110 --> 00:28:36,630 develop, test, develop, test, iterate, on and on and forward. 479 00:28:36,630 --> 00:28:39,720 Design is a very iterative process in this sense. 480 00:28:39,720 --> 00:28:43,280 You actually have to build something and then realize things about it 481 00:28:43,280 --> 00:28:46,520 that you didn't realize before and go back and improve from that. 482 00:28:46,520 --> 00:28:50,890 Now, as for the development part, that's what Tommy is going to show you after the break 483 00:28:50,890 --> 00:28:53,220 and how you might be able to implement something like autocomplete 484 00:28:53,220 --> 00:28:56,610 in a way that is fairly simple. 485 00:28:57,440 --> 00:28:59,550 [Malan] As Tommy sets up here, a question then. 486 00:28:59,550 --> 00:29:03,780 A lot of the earliest websites--and when Joseph said 1990s style website, 487 00:29:03,780 --> 00:29:07,640 it was implementations where if you wanted to select a start time and an end time, 488 00:29:07,640 --> 00:29:10,380 frankly, back in the day and even on some websites today, 489 00:29:10,380 --> 00:29:13,220 the way you do this is you pick an hour from a drop-down, 490 00:29:13,220 --> 00:29:15,910 you pick minutes from a drop-down, maybe you choose AM, PM, 491 00:29:15,910 --> 00:29:17,440 and then you do that 3 more times. 492 00:29:17,440 --> 00:29:19,920 And so with 6 clicks and maybe some scrolling 493 00:29:19,920 --> 00:29:24,000 your user can actually provide some kind of date and/or time range in this sense. 494 00:29:24,000 --> 00:29:27,920 >> So definitely suboptimal and yet thus far we've seen no expressive capabilities 495 00:29:27,920 --> 00:29:30,330 in any of the languages we've looked at to do something sexier 496 00:29:30,330 --> 00:29:32,620 like this slider of start time and end time. 497 00:29:32,620 --> 00:29:36,290 But if you think back to week 0 when we talked about Scratch, 498 00:29:36,290 --> 00:29:39,080 there too there were not widgets that just did certain things. 499 00:29:39,080 --> 00:29:42,700 You really just had these fundamentals like loops and conditions and the like. 500 00:29:42,700 --> 00:29:46,910 So kind of just thinking very abstractly now, independent of the particulars of HTML, 501 00:29:46,910 --> 00:29:51,260 what is really going on with something like this start time and end time slider? 502 00:29:51,260 --> 00:29:54,960 When I move my mouse and I click on that little carrot symbol on the left 503 00:29:54,960 --> 00:29:59,220 and start dragging, programmatically, what is it you want to be able to implement 504 00:29:59,220 --> 00:30:01,000 to make that happen? 505 00:30:01,000 --> 00:30:04,920 What questions, what Boolean expressions do you want to be able to ask? 506 00:30:04,920 --> 00:30:06,930 What's really going on? Sammy? 507 00:30:06,930 --> 00:30:10,080 [student] Where's the position of the cursor? >>Good. Where is the position of the cursor? 508 00:30:10,080 --> 00:30:11,970 This was something we needed to express back in Scratch, 509 00:30:11,970 --> 00:30:14,690 whether it was based on location or even color or the like. 510 00:30:14,690 --> 00:30:18,410 You might recall ever so briefly on Monday there were all of these things called events 511 00:30:18,410 --> 00:30:22,370 in the world of the Web, and so there's things like onclick and onkeypress 512 00:30:22,370 --> 00:30:25,960 and onkeyup and onmouseover and onmouseout. 513 00:30:25,960 --> 00:30:29,130 So realize that even these things we've been taking for granted on the Web 514 00:30:29,130 --> 00:30:32,190 with sites like Facebook and Gmail, even if you have no idea 515 00:30:32,190 --> 00:30:34,890 how you would possibly implement that because there's nothing even like it in lecture 516 00:30:34,890 --> 00:30:38,570 or Problem Set 7, realize that with these exact same fundamentals, 517 00:30:38,570 --> 00:30:41,090 with HTTP and parameters and GET and POST, 518 00:30:41,090 --> 00:30:44,010 with the basic HTML inputs that we've looked at thus far 519 00:30:44,010 --> 00:30:47,690 and in a moment with the programmatic mechanisms that Tommy's about to introduce 520 00:30:47,690 --> 00:30:51,300 can you start to express yourself just like you did in week 0 521 00:30:51,300 --> 00:30:53,800 by very intuitively dragging and dropping. 522 00:30:53,800 --> 00:30:58,950 >> So with that said, Tommy MacWilliam and some new puzzle pieces for us for Web. 523 00:30:58,950 --> 00:31:03,450 All right. My name is Tommy and I'm going to be talking about JavaScript. 524 00:31:03,450 --> 00:31:07,150 Just a disclaimer: I am of the opinion that JavaScript is the best programming language 525 00:31:07,150 --> 00:31:09,010 in the whole entire world. 526 00:31:09,010 --> 00:31:11,940 There are lots of people who disagree with me, but it's just amazing. 527 00:31:11,940 --> 00:31:16,330 Once you go back to C, if you have to write C for another class or some other languages, 528 00:31:16,330 --> 00:31:19,780 it's just really frustrating in all the low-level details you have to get bogged down in. 529 00:31:19,780 --> 00:31:23,050 So if you're ever feeling sad about how annoying C is to write, 530 00:31:23,050 --> 00:31:25,130 just go back, write some JavaScript. It's nirvana. 531 00:31:25,130 --> 00:31:27,980 You'll feel much better about your bad day. 532 00:31:27,980 --> 00:31:31,900 A lot of the magic of JavaScript comes from its ability to manipulate things 533 00:31:31,900 --> 00:31:33,730 that are already on the page. 534 00:31:33,730 --> 00:31:38,520 When we wrote our PHP scripts, they were executed on the server, 535 00:31:38,520 --> 00:31:42,270 and eventually that PHP script probably output some HTML. 536 00:31:42,270 --> 00:31:45,860 That HTML was sent to the client, and then that was it. 537 00:31:45,860 --> 00:31:50,180 If PHP wanted to add a button to a page, for example, it can't really do that. 538 00:31:50,180 --> 00:31:54,350 It would have to render a whole new HTML file and send that to the browser. 539 00:31:54,350 --> 00:31:57,840 With JavaScript we know that we can update things while they're already on the page, 540 00:31:57,840 --> 00:32:00,840 and because of this we can provide much more instant feedback, 541 00:32:00,840 --> 00:32:06,150 which will really improve the user experience on our website. 542 00:32:06,150 --> 00:32:09,330 Just a quick recap of JavaScript selectors. 543 00:32:09,330 --> 00:32:11,590 We know that when we download an HTML page, 544 00:32:11,590 --> 00:32:13,890 that's going to be represented in the DOM. 545 00:32:13,890 --> 00:32:19,340 >> The DOM remember is just this big tree where elements are related in this large hierarchy. 546 00:32:19,340 --> 00:32:21,810 When we worked with databases in pset 7, 547 00:32:21,810 --> 00:32:26,280 one of the first things we needed to know how to do was query the database. 548 00:32:26,280 --> 00:32:29,060 We have this large users table, and sometimes we just want to say, 549 00:32:29,060 --> 00:32:33,260 "I only want some of these users that match some condition." 550 00:32:33,260 --> 00:32:36,020 Similarly, when we have the DOM we need some way of querying it. 551 00:32:36,020 --> 00:32:39,490 We need some way of saying, "I want all of the buttons that look like this 552 00:32:39,490 --> 00:32:41,860 "or all of the images on the page." 553 00:32:41,860 --> 00:32:44,330 And these selectors allow us to do that. 554 00:32:44,330 --> 00:32:45,690 So just a quick recap. 555 00:32:45,690 --> 00:32:50,770 This first one here, this #submit, what is that going to select? Does anyone remember? 556 00:32:50,770 --> 00:32:54,880 [inaudible student response] >>Yeah, exactly. 557 00:32:54,880 --> 00:32:59,510 This is going to select an element on the page that has an ID of submit. 558 00:32:59,510 --> 00:33:03,470 And so that hash tag says this selector is going to work with IDs. 559 00:33:03,470 --> 00:33:07,630 How about the second one, this .centered, what will that select? 560 00:33:11,360 --> 00:33:15,180 Yeah. >>[student] Class. >>Exactly. This is now going to select by class. 561 00:33:15,180 --> 00:33:18,840 The difference between ID and class here is generally the ID should be unique 562 00:33:18,840 --> 00:33:20,820 within whatever space you're searching over. 563 00:33:20,820 --> 00:33:23,080 So if you were searching over an entire web page, 564 00:33:23,080 --> 00:33:27,740 you really should only have 1 element with that certain ID, so in this case of submit. 565 00:33:27,740 --> 00:33:31,330 With classes, on the other hand, we can have more than 1 element on the same page 566 00:33:31,330 --> 00:33:33,130 with the same class. 567 00:33:33,130 --> 00:33:36,580 This could be useful for saying I want to select everything that's centered on the page 568 00:33:36,580 --> 00:33:38,450 rather than just 1 thing. 569 00:33:38,450 --> 00:33:40,310 >> And finally, this last one here is a little more complicated, 570 00:33:40,310 --> 00:33:43,890 but what is this going to select from the DOM? 571 00:33:46,650 --> 00:33:48,810 [inaudible student response] >>What's that? 572 00:33:48,810 --> 00:33:53,250 [student] Anything that's a tag. >>We have 2 parts here. 573 00:33:53,250 --> 00:33:58,070 The second part is going to say I want to select these tags with a tag of input, 574 00:33:58,070 --> 00:34:00,730 so any element that is an input tag. 575 00:34:00,730 --> 00:34:03,080 But I don't want to just select all of the inputs 576 00:34:03,080 --> 00:34:05,170 because something like a submit button could be an input 577 00:34:05,170 --> 00:34:08,409 and something like a text box could be an input. 578 00:34:08,409 --> 00:34:11,909 So with these square brackets I'm saying I only want to select those elements 579 00:34:11,909 --> 00:34:14,110 that are of type text. 580 00:34:14,110 --> 00:34:17,400 Somewhere in my HTML tag I have an attribute called type, 581 00:34:17,400 --> 00:34:19,750 and the value of that attribute has to be text. 582 00:34:19,750 --> 00:34:21,340 So how about this first part here? 583 00:34:21,340 --> 00:34:25,489 The first word of this selector is form then I have a space and then this input part. 584 00:34:25,489 --> 00:34:29,620 What does that do, putting the form in front of it? 585 00:34:33,409 --> 00:34:35,860 This is going to basically limit our query. 586 00:34:35,860 --> 00:34:38,510 It could be the case that we have some inputs on the page 587 00:34:38,510 --> 00:34:41,080 that aren't descendants of a form. 588 00:34:41,080 --> 00:34:46,150 What this will do is this will say I only want the input tags that have somewhere above them 589 00:34:46,150 --> 00:34:49,030 some parent element of a form. 590 00:34:49,030 --> 00:34:52,100 And so in this way we can make these more hierarchical queries 591 00:34:52,100 --> 00:34:55,000 so we don't just have to select everything matching a given selector. 592 00:34:55,000 --> 00:35:00,760 We can kind of limit the scope of that query to something else. 593 00:35:00,760 --> 00:35:04,000 So now that we know how to select elements on the page, 594 00:35:04,000 --> 00:35:06,780 let's talk a bit about AJAX. 595 00:35:06,780 --> 00:35:12,270 AJAX is a still very trendy acronym that stands for asynchronous JavaScript and XML. 596 00:35:12,270 --> 00:35:15,640 It just so happens that XML is just some way to represent data. 597 00:35:15,640 --> 00:35:20,920 >> That kind of lost popularity recently, so the X in AJAX isn't used all the time. 598 00:35:20,920 --> 00:35:26,220 Basically, what AJAX allows us to do is make HTTP requests 599 00:35:26,220 --> 00:35:28,620 from the context of JavaScript. 600 00:35:28,620 --> 00:35:32,310 When we're in our web browser and we're navigating around pages and we click a link, 601 00:35:32,310 --> 00:35:37,790 what our browser is going to do is make an HTTP request to whatever link we click. 602 00:35:37,790 --> 00:35:41,670 But that's not always ideal because if that's the case, then as David was saying, 603 00:35:41,670 --> 00:35:45,220 we always have to make users click a Submit button or click a link 604 00:35:45,220 --> 00:35:50,380 in order to make anything happen that's going to involve an HTTP request. 605 00:35:50,380 --> 00:35:54,160 So with AJAX we can make these requests on behalf of JavaScript. 606 00:35:54,160 --> 00:35:57,020 That means whenever the user interacts with the page or anything happens, 607 00:35:57,020 --> 00:36:01,780 we can actually make a programmatic request to some other PHP file on our website 608 00:36:01,780 --> 00:36:06,280 or anything else and retrieve the data that that file spits out. 609 00:36:06,280 --> 00:36:09,860 Let's take a look at an example of AJAX. 610 00:36:09,860 --> 00:36:16,140 This is our CS50 Finance page with which hopefully some of us are familiar. 611 00:36:16,140 --> 00:36:21,790 If we look at the HTML of this page, we see here that I've added a few things, 612 00:36:21,790 --> 00:36:23,820 one of which I've given this form an ID. 613 00:36:23,820 --> 00:36:26,480 I've said id="form-quote". 614 00:36:26,480 --> 00:36:31,910 I've done this just because it's going to make this a little bit easier to select from the DOM 615 00:36:31,910 --> 00:36:35,090 since I can just make a very simple query. 616 00:36:35,090 --> 00:36:38,960 What I want to do here is I want to fix some problem with CS50 Finance. 617 00:36:38,960 --> 00:36:41,550 So if we go to finance.cs50.net, 618 00:36:41,550 --> 00:36:45,700 every time I want to get a quote, I have to click this Get Quote button, 619 00:36:45,700 --> 00:36:48,960 and that Get Quote button then takes me to another whole page. 620 00:36:48,960 --> 00:36:52,400 And if I want another quote, I have to hit the Back button and then I type it in, 621 00:36:52,400 --> 00:36:54,480 I get a quote, and I hit the Back button. 622 00:36:54,480 --> 00:36:56,840 This really is not the best user experience. 623 00:36:56,840 --> 00:37:01,570 Who would really use the site if it's that slow to get stock prices? 624 00:37:01,570 --> 00:37:05,630 So what we want to do with AJAX is remove that step of going to a separate page 625 00:37:05,630 --> 00:37:08,410 in order to view the results. 626 00:37:08,410 --> 00:37:11,240 >> What we're really only asking for is that really small price, 627 00:37:11,240 --> 00:37:14,240 and that's just a really small amount of data. 628 00:37:14,240 --> 00:37:17,400 So there's no need for me to go another whole HTML page, 629 00:37:17,400 --> 00:37:20,670 download a whole new batch of HTML, maybe download some more images, 630 00:37:20,670 --> 00:37:24,410 some other CSS files just for me to answer that very simple question 631 00:37:24,410 --> 00:37:27,810 of how much does this stock cost. 632 00:37:27,810 --> 00:37:31,000 With AJAX we can make this a lot easier. 633 00:37:31,000 --> 00:37:36,400 We see down here that I'm linking in a JavaScript file called quote.js. 634 00:37:36,400 --> 00:37:40,140 Let's actually open up that file. Not there. 635 00:37:42,610 --> 00:37:45,860 All of my JavaScript files are going to be located in HTML 636 00:37:45,860 --> 00:37:47,630 so that the web browser can access it. 637 00:37:47,630 --> 00:37:50,330 Then we have a separate directory here for JavaScript, 638 00:37:50,330 --> 00:37:54,340 and now here is quote.js. 639 00:37:54,340 --> 00:38:00,930 At the top of this file this says here that I want to wait for the entire page to be loaded 640 00:38:00,930 --> 00:38:04,830 before I try to do anything. Why is that necessary? 641 00:38:04,830 --> 00:38:08,650 It turns out that the next thing I'm going to do here is start looking for an element 642 00:38:08,650 --> 00:38:10,810 that matches some selector. 643 00:38:10,810 --> 00:38:15,600 If this JavaScript is ever executed before this element is loaded on the page, 644 00:38:15,600 --> 00:38:17,820 then everything I try to do isn't going to work 645 00:38:17,820 --> 00:38:20,580 because I'm going to try to select something that isn't there yet. 646 00:38:20,580 --> 00:38:23,780 So this line up top says I want you to wait until everything is loaded 647 00:38:23,780 --> 00:38:28,030 so we're guaranteed that any elements I'm looking for are actually on the page. 648 00:38:29,730 --> 00:38:34,310 This dollar sign here means I'm using the library called jQuery. 649 00:38:34,310 --> 00:38:38,570 This jQuery library allows us to use these selectors that we just looked at. 650 00:38:38,570 --> 00:38:44,010 By saying $ then passing in as an argument this #form-quote, 651 00:38:44,010 --> 00:38:47,910 I'm now selecting that form that we just took a look at. 652 00:38:47,910 --> 00:38:52,290 Now I have a representation of that form in memory somehow. 653 00:38:52,290 --> 00:38:56,760 >> On this object now, this representation of the form, 654 00:38:56,760 --> 00:38:58,890 I'm now using a function called on. 655 00:38:58,890 --> 00:39:02,710 What this function does is it's going to attach an event handler. 656 00:39:02,710 --> 00:39:06,310 The event that we're going to listen for is the submit event. 657 00:39:06,310 --> 00:39:08,890 So when the user clicks that Submit button or presses Enter, 658 00:39:08,890 --> 00:39:11,730 this event is going to fire. 659 00:39:11,730 --> 00:39:16,390 By hooking into this, I can now override the default behavior of the form. 660 00:39:16,390 --> 00:39:19,770 Without this JavaScript, the form would submit to whatever PHP file 661 00:39:19,770 --> 00:39:22,110 we used in that action attribute. 662 00:39:22,110 --> 00:39:25,440 But instead, I'm now saying, wait, wait, wait, I don't want you to actually do that. 663 00:39:25,440 --> 00:39:31,140 I want this to happen before you go and try to submit to some PHP file. 664 00:39:31,140 --> 00:39:32,870 Now what do I want to do? 665 00:39:32,870 --> 00:39:39,270 At this point I want to use AJAX somehow to load in what the price of the stock is. 666 00:39:39,270 --> 00:39:44,170 The first thing I need to know is what stock the user is looking up. 667 00:39:44,170 --> 00:39:46,760 To do that I'm going to use another selector. 668 00:39:46,760 --> 00:39:49,020 This is the third selector we looked at before. 669 00:39:49,020 --> 00:39:54,460 This says that I want to start off this form element with an ID of form-quote. 670 00:39:54,460 --> 00:39:58,440 Then somewhere inside of that form there has to be an input element 671 00:39:58,440 --> 00:40:01,270 that has a name of symbol. 672 00:40:01,270 --> 00:40:05,460 If we look back at our HTML, we saw that we had an input[name=symbol]. 673 00:40:05,460 --> 00:40:12,380 That means that this is going to select that text box that the user is typing into. 674 00:40:12,380 --> 00:40:13,870 That's nice. We have the text box. 675 00:40:13,870 --> 00:40:17,360 Now we just need to know what's inside of it. 676 00:40:17,360 --> 00:40:20,290 To do that we can call this method here, this .val, 677 00:40:20,290 --> 00:40:23,240 and this says I know what text box you have. 678 00:40:23,240 --> 00:40:28,160 I want you to tell me what it is the user typed into that text box. 679 00:40:28,160 --> 00:40:34,440 Now we have a string called symbol that is equal to whatever the user typed in. 680 00:40:34,440 --> 00:40:39,820 That's nice. We can use that string now to make our request. 681 00:40:39,820 --> 00:40:42,450 This is a new function here, this $, 682 00:40:42,450 --> 00:40:44,900 except we're no longer going to be selecting elements, 683 00:40:44,900 --> 00:40:48,910 we're going to be calling a different function that's provided to us by jQuery. 684 00:40:48,910 --> 00:40:54,810 This AJAX function is what's actually going to make this HTTP request. 685 00:40:54,810 --> 00:40:57,000 So we have to tell it a few things. 686 00:40:57,000 --> 00:41:01,410 The first thing we have to tell this function is where I want the request to go. 687 00:41:01,410 --> 00:41:08,910 Somewhere in my project I have this file inside of the HTML directory called quote.php. 688 00:41:08,910 --> 00:41:15,150 I can access this file, we saw, just like this, if I go to localhost/quote.php. 689 00:41:15,150 --> 00:41:20,450 >> I want my JavaScript to make a request to that page. 690 00:41:20,450 --> 00:41:22,920 What type of request now? 691 00:41:22,920 --> 00:41:27,210 We saw before that the form has that method="post" attribute, 692 00:41:27,210 --> 00:41:29,270 and that means it's going to make a POST request, 693 00:41:29,270 --> 00:41:32,630 so it's not going to put anything in the URL, rather than a GET request, 694 00:41:32,630 --> 00:41:36,860 which would just be fired if we just accessed the page with the web browser, for example. 695 00:41:36,860 --> 00:41:41,260 Now we've said I want to make an HTTP POST request 696 00:41:41,260 --> 00:41:44,840 to a page located at quote.php. 697 00:41:44,840 --> 00:41:51,490 When we submit the form, remember we could access the input elements inside of that form 698 00:41:51,490 --> 00:41:54,430 with that $_POST variable. 699 00:41:54,430 --> 00:41:58,710 So far in the story we haven't actually sent along any data yet. 700 00:41:58,710 --> 00:42:00,640 We've just said we're making an AJAX request 701 00:42:00,640 --> 00:42:03,200 and here's the type of request we're making. 702 00:42:03,200 --> 00:42:07,090 Now we need to actually send some data to the page. 703 00:42:07,090 --> 00:42:10,930 To do that we can use this property called data. 704 00:42:10,930 --> 00:42:14,950 The value of this property is actually an associative array. 705 00:42:14,950 --> 00:42:19,390 The reason for this is it allows us to send more than just 1 piece of data. 706 00:42:19,390 --> 00:42:24,750 That's why we have these curly braces here nested inside of these other curly braces. 707 00:42:24,750 --> 00:42:29,680 The keys in these associative arrays are going to be the same thing 708 00:42:29,680 --> 00:42:32,630 as those name attributes in our form elements. 709 00:42:32,630 --> 00:42:35,740 That means that if I send along a key of symbol, 710 00:42:35,740 --> 00:42:41,870 that means my PHP page can access this data with $_POST[symbol] 711 00:42:41,870 --> 00:42:44,640 just like we did before when we were submitting a form. 712 00:42:44,640 --> 00:42:47,090 And now the actual data we want to send 713 00:42:47,090 --> 00:42:50,790 is going to be the value inside of this associative array. 714 00:42:50,790 --> 00:42:54,070 >> We stored this text in a variable called symbol, 715 00:42:54,070 --> 00:42:57,380 and so we're sending along now a key of symbol 716 00:42:57,380 --> 00:43:01,380 and a value of whatever the user typed in. 717 00:43:01,380 --> 00:43:06,270 Now we've made this HTTP request, our PHP file has executed, 718 00:43:06,270 --> 00:43:11,480 and it's going to send some data back now to the client that just made this request. 719 00:43:11,480 --> 00:43:15,220 Now we need to respond to whatever the server said to us. 720 00:43:15,220 --> 00:43:20,180 To do that we have this last property here called success. 721 00:43:20,180 --> 00:43:24,240 The value of this success key is actually going to be a function, 722 00:43:24,240 --> 00:43:26,910 and this is one of the really cool things you can do with JavaScript. 723 00:43:26,910 --> 00:43:31,720 Not only can you have ints or arrays as a value inside of an associative array, 724 00:43:31,720 --> 00:43:34,170 we can also have a function. 725 00:43:34,170 --> 00:43:36,380 So by saying success, this is my key. 726 00:43:36,380 --> 00:43:38,830 A colon says here comes the value, 727 00:43:38,830 --> 00:43:41,810 and now the value of this is actually a function. 728 00:43:41,810 --> 00:43:44,460 So we don't need to give this function a name per se. 729 00:43:44,460 --> 00:43:48,820 We can just say this is going to be some function. It's going to take 1 argument. 730 00:43:48,820 --> 00:43:51,190 The argument to this function is going to be 731 00:43:51,190 --> 00:43:54,460 whatever the server sent us back from the request. 732 00:43:54,460 --> 00:43:57,750 Just like when our browser makes a request, the server sends something back 733 00:43:57,750 --> 00:43:59,060 and the browser displays it, 734 00:43:59,060 --> 00:44:03,030 in the context of AJAX we just made a request, the server sent something back, 735 00:44:03,030 --> 00:44:07,110 and now we have that represented as a string. 736 00:44:07,110 --> 00:44:11,280 With that string I would just like to display that on the page. 737 00:44:11,280 --> 00:44:14,040 To do that I'm going to have one last selector. 738 00:44:14,040 --> 00:44:17,570 I want to select the element with the ID price. 739 00:44:17,570 --> 00:44:20,710 This is just an empty div that I've created on the page, 740 00:44:20,710 --> 00:44:26,640 and I want to set the contents of that div to be whatever the server sent us back. 741 00:44:26,640 --> 00:44:30,280 I've actually modified quote.php a bit. 742 00:44:30,280 --> 00:44:33,460 >> Rather than calling render and rendering some page, 743 00:44:33,460 --> 00:44:38,100 quote.php now is simply going to print out the value of the stock as a string. 744 00:44:38,100 --> 00:44:41,880 So if you were to actually visit the page, you would just see that small string 745 00:44:41,880 --> 00:44:45,030 of whatever the stock price is. 746 00:44:45,030 --> 00:44:50,170 One last thing we need to do here is just make sure this function returns false. 747 00:44:50,170 --> 00:44:53,560 What this says is that if I'm inside of an event handler 748 00:44:53,560 --> 00:44:57,300 and that event handler returns false instead of returning true, 749 00:44:57,300 --> 00:45:01,510 that means that I do not want the original event to fire. 750 00:45:01,510 --> 00:45:05,270 In this case, if we did not have any JavaScript and we submitted a form, 751 00:45:05,270 --> 00:45:08,280 our web browser is going to say, "I'm going to send that data along," 752 00:45:08,280 --> 00:45:10,130 and they're going to send you to another page. 753 00:45:10,130 --> 00:45:14,360 Because we're using AJAX now, there's no need to send the user to another page. 754 00:45:14,360 --> 00:45:17,920 We're just going to display the results dynamically on this same page. 755 00:45:17,920 --> 00:45:21,460 We really don't want them to go anywhere, and I want to stay on the same page. 756 00:45:21,460 --> 00:45:27,060 So by returning false, we ensure that the form doesn't do that for us. 757 00:45:27,060 --> 00:45:31,170 Let's take a look at what this actually looks like. 758 00:45:31,170 --> 00:45:34,180 Our quote page looks the same. 759 00:45:34,180 --> 00:45:37,240 Let me pull up the inspector down here so we can see what's going on. 760 00:45:37,240 --> 00:45:40,270 Make it a little less huge. 761 00:45:40,270 --> 00:45:44,590 Remember if we open up the Network tab, this is where we can see all of the HTTP requests 762 00:45:44,590 --> 00:45:47,570 that are happening on the page. 763 00:45:47,570 --> 00:45:52,890 >> For a symbol let me type in a-a-p-l and click Get Quote. 764 00:45:52,890 --> 00:45:56,720 Now we saw that a share of Apple costs some number of dollars 765 00:45:56,720 --> 00:46:00,410 just appeared on the page, but the URL didn't change at all. 766 00:46:00,410 --> 00:46:04,570 In fact, here is the HTTP request that we just made. 767 00:46:04,570 --> 00:46:09,980 We made a POST request to quote.php. That makes sense. 768 00:46:09,980 --> 00:46:12,800 This is what the server sent us back. 769 00:46:12,800 --> 00:46:16,320 It's no longer this gigantic HTML document with images and things like that, 770 00:46:16,320 --> 00:46:20,920 it's just a line of text, and then we just displayed the line of text. 771 00:46:20,920 --> 00:46:26,290 If we go back to the headers and see what we actually sent inside of this HTTP request, 772 00:46:26,290 --> 00:46:33,950 we can see down here that we sent along a key of symbol and a value of aapl, 773 00:46:33,950 --> 00:46:36,430 which is what the user typed in. 774 00:46:36,430 --> 00:46:39,230 This is nice, but it's still a little annoying. 775 00:46:39,230 --> 00:46:42,490 I still have to click this button to get the stock quote. 776 00:46:42,490 --> 00:46:45,880 We're busy people and we don't have time to click buttons. 777 00:46:45,880 --> 00:46:49,910 Google realized this a little while ago when they implemented Google Instant. 778 00:46:49,910 --> 00:46:53,590 What Google Instant does is as you're typing it just starts displaying results for you 779 00:46:53,590 --> 00:46:56,520 so you don't have to worry about even clicking Search. 780 00:46:56,520 --> 00:46:58,730 Actually, a fun story related to that. 781 00:46:58,730 --> 00:47:01,100 Once Google Instant came out, people were like, "Whoa, this is super amazing." 782 00:47:01,100 --> 00:47:02,540 "This is so cool." 783 00:47:02,540 --> 00:47:05,950 And a student down at Stanford who was 19 at the time 784 00:47:05,950 --> 00:47:09,000 made this site called YouTube Instant. 785 00:47:09,000 --> 00:47:13,170 All YouTube Instant does is effectively search YouTube instantly. 786 00:47:13,170 --> 00:47:17,020 So rather than having to go to YouTube.com and hit Search, 787 00:47:17,020 --> 00:47:21,650 when I start typing into YouTube Instant something like CS50, 788 00:47:21,650 --> 00:47:25,320 we could see here that it's attempting to on a slow Internet connection 789 00:47:25,320 --> 00:47:28,500 populate these results live. 790 00:47:28,500 --> 00:47:35,590 To do that we can actually make a very simple modification to our quote.js file. 791 00:47:35,590 --> 00:47:40,900 Right now we're attaching this event when the form is submitted. 792 00:47:40,900 --> 00:47:43,760 We don't really want to make the user submit that form anymore, 793 00:47:43,760 --> 00:47:48,570 so let's instead fire this event every time the user presses a key. 794 00:47:48,570 --> 00:47:53,200 To do that let's first change the event from submit to keyup. 795 00:47:53,200 --> 00:47:55,740 That means that rather than waiting for the form to submit, 796 00:47:55,740 --> 00:47:58,490 every time the key is pressed, something is going to happen. 797 00:47:58,490 --> 00:48:02,030 It no longer makes sense to attach this keyup event to the whole form. 798 00:48:02,030 --> 00:48:05,080 We really only care about that search box. 799 00:48:05,080 --> 00:48:09,320 >> To select that now, we can change this to be, rather than form-quote, 800 00:48:09,320 --> 00:48:14,220 form-quote and we'll have an input(type=text) or we could say (name=symbol)-- 801 00:48:14,220 --> 00:48:16,420 whatever we want. 802 00:48:16,420 --> 00:48:18,650 Now there's one last thing we have to do. 803 00:48:18,650 --> 00:48:21,190 Remember down here when we said return false 804 00:48:21,190 --> 00:48:24,370 we said we don't want that default event to fire. 805 00:48:24,370 --> 00:48:26,390 But it just so happens that if we disable that now, 806 00:48:26,390 --> 00:48:29,660 whatever we type in is not going to show up in the browser anymore 807 00:48:29,660 --> 00:48:33,000 because that would be the default behavior of typing into a text box. 808 00:48:33,000 --> 00:48:38,660 We no longer want to override that, so let's destroy this return false. 809 00:48:38,660 --> 00:48:44,800 If we save that and reload the page, now when I start typing a-a-p-l 810 00:48:44,800 --> 00:48:50,160 you'll see that the stock price at the bottom here is completing automatically. 811 00:48:50,160 --> 00:48:53,150 So here is CS50 Finance Instant. 812 00:48:53,150 --> 00:48:55,860 Actually a fun story about the YouTube Instant 813 00:48:55,860 --> 00:48:59,420 is that student just kind of wrote it as a 1-night project, 814 00:48:59,420 --> 00:49:03,800 and the next day he was offered a job by the YouTube CEO. 815 00:49:03,800 --> 00:49:10,610 So as simple as that, you CS50 students, your final projects can get you a job at YouTube. 816 00:49:10,610 --> 00:49:14,720 Something like that is a really cool idea for a final project, right? 817 00:49:14,720 --> 00:49:18,170 We had some existing functionality that we wanted to integrate with. 818 00:49:18,170 --> 00:49:20,330 We improve the user experience a little bit, 819 00:49:20,330 --> 00:49:24,340 and suddenly searching something on YouTube Instant might be a lot easier 820 00:49:24,340 --> 00:49:27,290 than searching for it on regular YouTube. 821 00:49:27,290 --> 00:49:30,790 So that's AJAX in a nutshell. 822 00:49:30,790 --> 00:49:34,860 >> In the examples that Joseph was showing, we saw a lot of autocompletes, 823 00:49:34,860 --> 00:49:39,250 and those autocompletes are really, really handy because we don't have to remember-- 824 00:49:39,250 --> 00:49:41,770 For example, if you don't remember the stock price for Apple 825 00:49:41,770 --> 00:49:45,110 and we just know it's a-a something, rather than just saying to me, 826 00:49:45,110 --> 00:49:48,740 "A share of this thing costs this much money," 827 00:49:48,740 --> 00:49:52,540 I'd kind of like to know what stocks start with aa. 828 00:49:52,540 --> 00:49:58,340 We can do that really nicely with the Bootstrap library that's already included 829 00:49:58,340 --> 00:50:01,380 inside of CS50 Finance. 830 00:50:01,380 --> 00:50:09,390 If you come up here to the JavaScript tag and scroll down to Typeahead, 831 00:50:09,390 --> 00:50:13,730 this is just a nice plugin that somebody already wrote for us, 832 00:50:13,730 --> 00:50:16,980 and we can easily use its functionality like this. 833 00:50:16,980 --> 00:50:21,410 I typed in an A and here is a list of some states that start with A. 834 00:50:21,410 --> 00:50:25,360 Let's say that I think this is really cool and it's time for me to include this on my page. 835 00:50:25,360 --> 00:50:28,300 It turns out that this is really, really simple. 836 00:50:28,300 --> 00:50:32,810 Let's jump over here to quote3.js. 837 00:50:34,890 --> 00:50:37,380 My file looks a little bit different. 838 00:50:37,380 --> 00:50:39,700 Down here all of my AJAX stuff is the same. 839 00:50:39,700 --> 00:50:43,170 I want to load the stock data without having to go to another page. 840 00:50:43,170 --> 00:50:46,220 But now I want to use this plugin. 841 00:50:46,220 --> 00:50:51,020 The Bootstrap documentation has great examples of how exactly I can do that. 842 00:50:51,020 --> 00:50:54,350 I want to say, "Here's the input that I want to autocomplete on," 843 00:50:54,350 --> 00:50:56,640 and I'm going to call this function called typeahead, 844 00:50:56,640 --> 00:50:59,730 and that's going to handle all of the Typeahead stuff for us. 845 00:50:59,730 --> 00:51:02,090 It will initialize the list, it will do all of our filtering. 846 00:51:02,090 --> 00:51:06,680 The only thing it needs to know is what data we're autocompleting on. 847 00:51:06,680 --> 00:51:10,480 So I found out this key just by reading the documentation and looking at the examples. 848 00:51:10,480 --> 00:51:14,150 If I give it a key of source, the value of this key 849 00:51:14,150 --> 00:51:17,770 is just some array of things I want to autocomplete on. 850 00:51:17,770 --> 00:51:20,180 This variable came from this other file. 851 00:51:20,180 --> 00:51:23,400 I open up symbols.js. 852 00:51:23,400 --> 00:51:27,980 >> This symbols.js is just this really, really big array containing strings 853 00:51:27,980 --> 00:51:32,080 of all of these stock symbols from the NASDAQ. 854 00:51:32,080 --> 00:51:42,190 If I want to jump back to the HTML, so jharvard, vhosts, globalhost, html, templates, 855 00:51:42,190 --> 00:51:45,820 quote_form. 856 00:51:45,820 --> 00:51:50,910 Since that's now called quote3.js, let me change the JavaScript file I'm including here. 857 00:51:50,910 --> 00:51:55,110 Now I have quote3.js, so I'm going to load in that separate JavaScript file, 858 00:51:55,110 --> 00:51:57,910 the one that has that Bootstrap autocomplete. 859 00:51:57,910 --> 00:52:04,430 Now when I jump back to the browser, reload the page, and I start typing a-a, 860 00:52:04,430 --> 00:52:06,880 there's my autocomplete. And it was really as simple as that. 861 00:52:06,880 --> 00:52:11,400 I had 1 line of code that just said, "Here are the things I want to autocomplete on," 862 00:52:11,400 --> 00:52:16,590 and suddenly I have this really, really nice functionality with not a whole lot of effort at all. 863 00:52:16,590 --> 00:52:19,810 As you're developing websites and particularly the front end side of things, 864 00:52:19,810 --> 00:52:21,840 you're going to find this is the case a lot. 865 00:52:21,840 --> 00:52:25,700 There are a lot, lot, lot of really cool free libraries out there 866 00:52:25,700 --> 00:52:30,190 that make it super easy to do things like this. 867 00:52:30,190 --> 00:52:37,230 Can anyone think of any drawbacks of simply autocompleting on this large list of symbols? 868 00:52:37,230 --> 00:52:41,580 What could be something that's not the best with this approach? 869 00:52:42,790 --> 00:52:45,960 Yeah. >>[student] Time, if you have a lot of [inaudible] 870 00:52:45,960 --> 00:52:50,420 Yeah. Right now we're downloading this huge JavaScript file and there's a lot of symbols. 871 00:52:50,420 --> 00:52:54,360 And so if we have a ton of stuff, this could kind of increase the latency of not only searching 872 00:52:54,360 --> 00:52:56,600 but also downloading the actual file. 873 00:52:56,600 --> 00:52:58,670 Great. Anything else? 874 00:53:01,950 --> 00:53:05,280 Right now there's no real sense of relevance. 875 00:53:05,280 --> 00:53:08,190 If I type in an A, the companies that show up here 876 00:53:08,190 --> 00:53:11,220 might not be the most popular companies that start with A. 877 00:53:11,220 --> 00:53:17,130 >> Before I get to Apple, it might take some more characters to find what I'm looking for. 878 00:53:17,130 --> 00:53:20,420 This autocomplete doesn't have this sense of relevance. 879 00:53:20,420 --> 00:53:24,400 It's just going to say, "Anything that matches I'm going to display." 880 00:53:24,400 --> 00:53:30,510 Instead of that, I'd like to somehow integrate some relevance into my searches. 881 00:53:30,510 --> 00:53:36,440 If I go over here to Yahoo! Finance, finance.yahoo.com, 882 00:53:36,440 --> 00:53:42,100 If I try to enter a symbol on Yahoo! Finance's page 883 00:53:42,100 --> 00:53:52,310 and I start typing g-o-o-g, I have this nice list of things. 884 00:53:52,310 --> 00:53:57,100 Clearly, it looks like Yahoo! Finance is doing something more clever here. 885 00:53:57,100 --> 00:53:59,790 They have some relevance and they also have additional information 886 00:53:59,790 --> 00:54:01,430 like the name of the stock. 887 00:54:01,430 --> 00:54:05,850 That's something that I can't really get with just my stock list of symbols. 888 00:54:05,850 --> 00:54:09,520 I want this and so I'm going to take it. 889 00:54:09,520 --> 00:54:11,790 To do that let's do a few things. 890 00:54:11,790 --> 00:54:15,580 Let's first open up the inspector on this page 891 00:54:15,580 --> 00:54:18,100 because we saw that this page is not reloading at all, 892 00:54:18,100 --> 00:54:21,960 so it's probably using AJAX somehow to be loading its data. 893 00:54:21,960 --> 00:54:23,920 We can find out what data it's loading. 894 00:54:23,920 --> 00:54:28,390 If I click on this Network tab, these are going to be all of the requests that start to be fired. 895 00:54:28,390 --> 00:54:34,020 Now if I type in g-o-o, we can see that I just got a new HTTP request. 896 00:54:34,020 --> 00:54:37,490 This is probably where that data is coming from. 897 00:54:37,490 --> 00:54:41,990 Sure enough, if I look at this URL, which is a bit strangely named, 898 00:54:41,990 --> 00:54:46,930 we can see that this is exactly where Yahoo is sending off its data from. 899 00:54:46,930 --> 00:54:53,400 >> I've created a separate file called suggest.php that's very similar in spirit to the lookup function. 900 00:54:53,400 --> 00:54:57,730 It's basically going to make a query to Yahoo's URL, get back some data, 901 00:54:57,730 --> 00:54:59,750 and send it back to me. 902 00:54:59,750 --> 00:55:02,570 Now, rather than using this big, huge list of symbols, 903 00:55:02,570 --> 00:55:05,280 I can use Yahoo's nice relevance things, 904 00:55:05,280 --> 00:55:08,150 and I don't have to download that massive JavaScript file. 905 00:55:08,150 --> 00:55:12,040 I'm only going to pull down the actually relevant stock symbols. 906 00:55:12,040 --> 00:55:13,960 Let's jump into that. 907 00:55:13,960 --> 00:55:17,360 So html, js. We're now in quote4. 908 00:55:17,360 --> 00:55:22,120 Now we're no longer using that big list of JavaScript files. 909 00:55:22,120 --> 00:55:24,430 But there's a small kind of design problem here. 910 00:55:24,430 --> 00:55:28,200 We've said that the A in AJAX is asynchronous. 911 00:55:28,200 --> 00:55:31,000 What that means is that when I make an AJAX request, 912 00:55:31,000 --> 00:55:36,490 so right here on line 8, this is where my AJAX request is actually fired. 913 00:55:36,490 --> 00:55:40,370 Let's say now I have some code down here that's going to do some stuff 914 00:55:40,370 --> 00:55:43,930 like alert the user or change something on the page. 915 00:55:43,930 --> 00:55:49,830 What's not going to happen is the browser is not going to wait for this request to continue 916 00:55:49,830 --> 00:55:53,480 before coming down and hitting this line. 917 00:55:53,480 --> 00:55:55,900 That's the asynchronous part. 918 00:55:55,900 --> 00:55:58,400 It's going to make this request and say, "Whenever you finish, 919 00:55:58,400 --> 00:56:03,080 "come back and call that function that I told you to call inside of success." 920 00:56:03,080 --> 00:56:07,300 That means we can't just download all the stocks beforehand. 921 00:56:07,300 --> 00:56:10,300 We need to make the request and wait for something to come back. 922 00:56:10,300 --> 00:56:13,330 That means that before, we could simply tell Bootstrap, 923 00:56:13,330 --> 00:56:15,580 "Here's the list of things I want you to autocomplete on." 924 00:56:15,580 --> 00:56:18,950 We can no longer do that anymore because we don't know 925 00:56:18,950 --> 00:56:21,780 what we want to actually autocomplete on. 926 00:56:21,780 --> 00:56:25,190 Luckily, Bootstrap thought of this because those are smart guys over there, 927 00:56:25,190 --> 00:56:30,160 and they actually gave us another way to load this Typeahead plugin. 928 00:56:30,160 --> 00:56:35,630 Before, the value of this source property was just this big array of things to autocomplete on. 929 00:56:35,630 --> 00:56:39,580 >> Now the source property is actually a function, 930 00:56:39,580 --> 00:56:44,580 and the purpose of this function is to figure out what the things to autocomplete on are. 931 00:56:44,580 --> 00:56:48,730 The way it's going to figure that out is it's going to ask Yahoo! Finance 932 00:56:48,730 --> 00:56:51,750 what the best things to autocomplete are. 933 00:56:51,750 --> 00:56:54,500 To do that I'm going to make a very similar AJAX request. 934 00:56:54,500 --> 00:56:59,010 I'm going to request this page at suggest.php. 935 00:56:59,010 --> 00:57:01,360 I want to send along the symbols still. 936 00:57:01,360 --> 00:57:05,570 And now my success, the Bootstrap documentation told me 937 00:57:05,570 --> 00:57:09,130 that in order to populate that list of things, 938 00:57:09,130 --> 00:57:14,370 all I need to do is pass in this array now to the callback function. 939 00:57:14,370 --> 00:57:15,660 But wait a minute. 940 00:57:15,660 --> 00:57:20,240 If this is supposed to be an array and AJAX is sending me back text, 941 00:57:20,240 --> 00:57:22,720 how is that possible? 942 00:57:22,720 --> 00:57:27,910 This introduces a new way of exchanging data called JSON. 943 00:57:27,910 --> 00:57:33,000 In this case we're not just sending back a simple string of text. 944 00:57:33,000 --> 00:57:37,670 Now we're dealing with this more complex list of stock symbols. 945 00:57:37,670 --> 00:57:41,730 These stock symbols can also include things like the company's name or the current prices. 946 00:57:41,730 --> 00:57:47,550 Just using a big long string that's not formatted in any predictable way 947 00:57:47,550 --> 00:57:51,970 isn't going to be the best way to get this data from Yahoo's server to me 948 00:57:51,970 --> 00:57:54,540 in a way that I can easily understand. 949 00:57:54,540 --> 00:58:01,280 JSON is a technology that takes advantage of how we create associative arrays in JavaScript. 950 00:58:01,280 --> 00:58:04,510 This looks a lot like a JavaScript associative array, 951 00:58:04,510 --> 00:58:06,600 and in fact, it's because it is. 952 00:58:06,600 --> 00:58:09,710 JSON stands for JavaScript Object Notation. 953 00:58:09,710 --> 00:58:15,020 This is basically an agreed upon format for transferring data back and forth. 954 00:58:15,020 --> 00:58:18,280 Here this JSON object or this JSON associative array 955 00:58:18,280 --> 00:58:21,010 is sending me some data about a course. 956 00:58:21,010 --> 00:58:25,110 >> The keys of this array are things like course that has a value of cs50, 957 00:58:25,110 --> 00:58:29,140 and down here we can see that I can have a value that is an array. 958 00:58:29,140 --> 00:58:32,730 I don't have to do things like parse out strings and look for commas 959 00:58:32,730 --> 00:58:35,330 and do crazy things like that. 960 00:58:35,330 --> 00:58:38,820 Because this is declared in this JSON format, 961 00:58:38,820 --> 00:58:43,510 JavaScript and jQuery already have functions to convert a string 962 00:58:43,510 --> 00:58:48,140 that looks like this JSON into an actual JavaScript associative array 963 00:58:48,140 --> 00:58:50,440 that we can work with. 964 00:58:50,440 --> 00:58:56,660 Doing that is as simple as saying that no longer is this file, suggest.php, 965 00:58:56,660 --> 00:58:59,040 sending me back simply a string of text, 966 00:58:59,040 --> 00:59:01,950 but I know it's going to be sending me back JSON. 967 00:59:01,950 --> 00:59:06,760 That means that that JSON can be converted into a JavaScript associative array. 968 00:59:06,760 --> 00:59:10,830 And so jQuery, I would like you to do that for me. 969 00:59:10,830 --> 00:59:13,990 That means that this response parameter here, 970 00:59:13,990 --> 00:59:16,070 this is no longer just a string. 971 00:59:16,070 --> 00:59:19,860 Because we've told jQuery that here comes some JSON, 972 00:59:19,860 --> 00:59:22,950 jQuery is going to be smart enough to say, "You wanted JSON?" 973 00:59:22,950 --> 00:59:26,890 "I'm going to convert that into an associative array for you." 974 00:59:26,890 --> 00:59:32,100 Let's actually take a look at the Network tab once we have quote4.js. 975 00:59:32,100 --> 00:59:35,400 We'll change this and reload the page. 976 00:59:37,150 --> 00:59:41,250 Now I'm going to type in a-a again. 977 00:59:41,250 --> 00:59:45,600 I've made a couple requests to suggest.php, but now this response, 978 00:59:45,600 --> 00:59:48,670 rather than just the string, it's JSON. 979 00:59:48,670 --> 00:59:52,580 So I have an open curly brace saying, "Here comes an associative array." 980 00:59:52,580 --> 00:59:56,830 >> The first and only key of this associative array is called symbols, 981 00:59:56,830 --> 01:00:00,240 and then here is an array of all of the relevant symbols 982 01:00:00,240 --> 01:00:04,820 coming now from Yahoo! Finance, not from that gigantic list. 983 01:00:06,110 --> 01:00:10,630 That's how I can simply populate this autocomplete plugin 984 01:00:10,630 --> 01:00:14,280 with some data that's not coming from a local file that's already predetermined 985 01:00:14,280 --> 01:00:17,490 but from something else. 986 01:00:17,490 --> 01:00:21,160 It turns out that we can actually take advantage of a technology called JSONP, 987 01:00:21,160 --> 01:00:27,420 or JSON with padding, that will eliminate this suggest.php middleman. 988 01:00:27,420 --> 01:00:34,010 But instead of doing that, let's instead take a look at how I can improve this even more. 989 01:00:34,010 --> 01:00:36,040 I really like Bootstrap's Typeahead. It's really nice. 990 01:00:36,040 --> 01:00:39,570 But we're getting good at JavaScript and we want to kind of do this ourselves, 991 01:00:39,570 --> 01:00:43,870 maybe take a look at what this plugin could be doing. 992 01:00:43,870 --> 01:00:46,500 Let's no longer use that Typeahead thing, 993 01:00:46,500 --> 01:00:50,550 and let's try to make this list of suggested stocks ourselves. 994 01:00:50,550 --> 01:00:53,790 Here in quote6.php we're going to start off the same way. 995 01:00:53,790 --> 01:00:58,050 Every time someone types something, we want to make an AJAX request. 996 01:00:58,050 --> 01:01:01,590 This is similar to our original CS50 Finance Instant. 997 01:01:01,590 --> 01:01:05,020 Rather than making a request to quote.php, 998 01:01:05,020 --> 01:01:08,530 we're now making a request to that same file as before, this suggest.php, 999 01:01:08,530 --> 01:01:12,460 which is just going to pull data from Yahoo! Finance. 1000 01:01:12,460 --> 01:01:19,480 >> Again, we're still expecting JSON, but now since the Typeahead isn't doing this for us, 1001 01:01:19,480 --> 01:01:24,850 we also need to send along the value that is inside of the current text box. 1002 01:01:24,850 --> 01:01:28,120 Now we know what to ask Yahoo! Finance for, 1003 01:01:28,120 --> 01:01:34,160 and so now here's the function that we want to execute once the request completes. 1004 01:01:34,160 --> 01:01:36,520 We don't have the plugin to make the list for us, 1005 01:01:36,520 --> 01:01:40,630 so here's where we're actually going to build a list of suggestions. 1006 01:01:40,630 --> 01:01:44,850 To do that, much like in PHP we concatenated these big strings of HTML 1007 01:01:44,850 --> 01:01:48,170 then we printed them, we can do the same exact thing in JavaScript. 1008 01:01:48,170 --> 01:01:51,850 First we're going to start off this string called suggestions, 1009 01:01:51,850 --> 01:01:54,590 and this string is just going to contain some HTML. 1010 01:01:54,590 --> 01:01:58,320 We want it to be a list of things, so we're going to start off with this list tag, 1011 01:01:58,320 --> 01:02:03,340 and now we're going to iterate over all of the symbols that were returned back to us. 1012 01:02:03,340 --> 01:02:06,500 Remember, because we've said dataType: 'json', this is not a string. 1013 01:02:06,500 --> 01:02:09,500 This is already an array for us. That's really cool. 1014 01:02:09,500 --> 01:02:13,790 We can simply say, "I want you to append a list element." 1015 01:02:13,790 --> 01:02:16,000 We'll put it inside an a element in side of that, 1016 01:02:16,000 --> 01:02:19,030 we'll give it a class of suggestions so we know what it is, 1017 01:02:19,030 --> 01:02:23,880 and now here is the symbol that we got back from Yahoo! Finance. 1018 01:02:23,880 --> 01:02:27,230 >> Once we've created an element for each of the symbols we've gotten back, 1019 01:02:27,230 --> 01:02:30,100 we just want to close off the list. 1020 01:02:30,100 --> 01:02:33,040 So now suggestions represents this little HTML fragment 1021 01:02:33,040 --> 01:02:37,860 that when put on a page is going to be the list of things we're looking for. 1022 01:02:37,860 --> 01:02:41,070 Now let's actually put that on the page. 1023 01:02:41,070 --> 01:02:46,390 To do that I've actually created another empty div and I've given it an ID of suggestions. 1024 01:02:46,390 --> 01:02:52,520 Much like we set the contents of the div that would display the price of the stock data, 1025 01:02:52,520 --> 01:02:58,600 we now just want to set the contents of this div to whatever this string is 1026 01:02:58,600 --> 01:03:00,290 which contains these symbols. 1027 01:03:00,290 --> 01:03:07,650 By using this HTML method, this suggestions variable, this string, is a string of HTML. 1028 01:03:07,650 --> 01:03:13,490 I want you to take that HTML and put it inside of the div called suggestions. 1029 01:03:13,490 --> 01:03:15,680 We've just appended something to the DOM now. 1030 01:03:15,680 --> 01:03:20,360 We've added some new elements to the DOM that we can now display on the page. 1031 01:03:20,360 --> 01:03:22,540 Let's see what this looks like. 1032 01:03:22,540 --> 01:03:29,110 If we load in quote6 and now we come back, 1033 01:03:29,110 --> 01:03:34,480 now when I start typing a-a-p-l, we no longer have that Bootstrap autocomplete, 1034 01:03:34,480 --> 01:03:38,470 but we now have this list that we made ourselves. 1035 01:03:38,470 --> 01:03:43,230 This is a little bit uglier than the Bootstrap Typeahead, for example, 1036 01:03:43,230 --> 01:03:45,580 but it does allow us to do one other thing. 1037 01:03:45,580 --> 01:03:48,660 When we were looking at that Bootstrap plugin, 1038 01:03:48,660 --> 01:03:52,590 we saw that when we autocompleted, one of the autocomplete values was a-a-p-l. 1039 01:03:52,590 --> 01:03:54,820 That might not be so helpful. 1040 01:03:54,820 --> 01:03:59,100 As a user, I might not immediately recognize all of the stock symbols. 1041 01:03:59,100 --> 01:04:02,370 What I'm probably more likely to recognize are the company's actual names. 1042 01:04:02,370 --> 01:04:05,310 So wouldn't it be really helpful if rather than saying a-a-p-l 1043 01:04:05,310 --> 01:04:07,970 this said something like Apple Inc. 1044 01:04:07,970 --> 01:04:12,240 Because we've rolled this ourselves, we can really easily do that. 1045 01:04:12,240 --> 01:04:17,630 Let's open up our last quote file here, so quote7. 1046 01:04:17,630 --> 01:04:23,200 >> Same thing. I've just created another PHP file that will return to us more than just the symbols. 1047 01:04:23,200 --> 01:04:25,550 It will also give us back the company's names. 1048 01:04:25,550 --> 01:04:28,150 And so we're doing the same thing. We're making an AJAX request. 1049 01:04:28,150 --> 01:04:32,370 Once the request has completed, we're going to execute this function here, 1050 01:04:32,370 --> 01:04:36,520 and this function is going to build up a big string of elements. 1051 01:04:36,520 --> 01:04:39,520 But the difference here is that the value of these lists is no longer just the symbol, 1052 01:04:39,520 --> 01:04:45,370 it's now the name. 1053 01:04:45,370 --> 01:04:47,070 So we have one small problem. 1054 01:04:47,070 --> 01:04:51,590 When we use our lookup, we need to somehow pass it the symbol. 1055 01:04:51,590 --> 01:04:54,950 We can't pass lookup something like Microsoft Corporation. 1056 01:04:54,950 --> 01:04:57,900 We need to pass it MSFT. 1057 01:04:57,900 --> 01:05:01,640 When we're writing HTML, we have lots of nice built-in attributes. 1058 01:05:01,640 --> 01:05:05,440 An A might have associated with it an href or a class. 1059 01:05:05,440 --> 01:05:08,230 But what we really need now is for each of these links 1060 01:05:08,230 --> 01:05:11,120 to have a stock symbol associated with it. 1061 01:05:11,120 --> 01:05:14,240 There's no built-in HTML attribute for stock symbol, 1062 01:05:14,240 --> 01:05:21,010 but luckily, HTML5 allows us to create our own attributes to be whatever we want. 1063 01:05:21,010 --> 01:05:24,620 By saying data-symbol, I've introduced a new attribute 1064 01:05:24,620 --> 01:05:29,350 whose name I just made up, and this is okay because I prefaced it with this data. 1065 01:05:29,350 --> 01:05:34,270 We're going to store inside of there the symbol from the stock now. 1066 01:05:34,270 --> 01:05:39,590 What that means is that even though we're displaying the value of the company's name 1067 01:05:39,590 --> 01:05:43,380 inside of our autocomplete, we're still remembering the symbol 1068 01:05:43,380 --> 01:05:47,110 that is associated with each company. 1069 01:05:47,110 --> 01:05:50,350 The way we're doing that is inside of this element itself. 1070 01:05:50,350 --> 01:05:52,930 So that means we need to make one more change. 1071 01:05:52,930 --> 01:05:57,090 When we click it now, we need to actually take advantage of the symbol attribute 1072 01:05:57,090 --> 01:06:00,220 rather than just its value. 1073 01:06:00,220 --> 01:06:05,010 If we back up, we attach an event handler to suggestions. 1074 01:06:05,010 --> 01:06:09,280 Whenever one of these suggestions is clicked now, I want to do something. 1075 01:06:09,280 --> 01:06:13,160 What I want to do is change the value of that input box. 1076 01:06:13,160 --> 01:06:16,100 Now I want to set this same val function. 1077 01:06:16,100 --> 01:06:21,060 >> So without any arguments this val function returns to you what's already in the text box, 1078 01:06:21,060 --> 01:06:27,070 but if you give it a string, it's going to take that string and put it into the text box. 1079 01:06:27,070 --> 01:06:28,980 I'm selecting its text box in the same way. 1080 01:06:28,980 --> 01:06:31,230 It's name is symbol inside of form-quote. 1081 01:06:31,230 --> 01:06:37,540 Now I'm sending it the value of the attribute data-symbol. 1082 01:06:37,540 --> 01:06:41,560 This thing here is new, this $(this). 1083 01:06:41,560 --> 01:06:46,850 What this refers to is the element that was clicked. 1084 01:06:46,850 --> 01:06:50,880 We can see here that we're not attaching a click event 1085 01:06:50,880 --> 01:06:54,690 to each element with a class of suggestion individually. 1086 01:06:54,690 --> 01:06:57,140 Rather, we're approaching this a little differently. 1087 01:06:57,140 --> 01:07:01,700 Instead we're saying whenever anything inside of this suggestions div, 1088 01:07:01,700 --> 01:07:04,080 which remember is just the container for that list, 1089 01:07:04,080 --> 01:07:10,150 if something inside of this div is clicked and it has a class of suggestion, 1090 01:07:10,150 --> 01:07:13,000 I want this event to fire. 1091 01:07:13,000 --> 01:07:17,490 Basically what this means we can do is we can reuse this same event handler 1092 01:07:17,490 --> 01:07:20,000 for all of the things in the list. 1093 01:07:20,000 --> 01:07:22,080 So we don't have to have one event handler for the first element 1094 01:07:22,080 --> 01:07:24,550 and a different event handler for the second element. 1095 01:07:24,550 --> 01:07:29,880 We can instead say, "I want the same event handler to apply to everything in my list." 1096 01:07:29,880 --> 01:07:34,420 But we need to somehow know which element was clicked. 1097 01:07:34,420 --> 01:07:38,450 This "this" keyword represents just that. 1098 01:07:38,450 --> 01:07:42,360 This is the object that was just clicked by the user. 1099 01:07:42,360 --> 01:07:47,680 If I just clicked the 3rd link, this represents the element of that 3rd link, 1100 01:07:47,680 --> 01:07:51,670 which means that I can get its attribute, data-symbol, 1101 01:07:51,670 --> 01:07:57,760 which we know has to contain the symbol that's associated with the company I just clicked. 1102 01:07:57,760 --> 01:08:04,550 If we jump back to our finance page, 1103 01:08:04,550 --> 01:08:08,580 we can see now that once I start typing something like m-s-f-t, 1104 01:08:08,580 --> 01:08:11,220 we're no longer getting just the stock symbols, 1105 01:08:11,220 --> 01:08:13,720 we're now getting the actual companies. 1106 01:08:13,720 --> 01:08:20,410 But when I click on one of these companies, 1107 01:08:20,410 --> 01:08:25,180 we can see that we're actually populating the text box not with the name of the company 1108 01:08:25,180 --> 01:08:29,850 but with whatever was stored inside of those data attributes. 1109 01:08:29,850 --> 01:08:32,880 And so if I actually inspect one of these elements by right clicking it 1110 01:08:32,880 --> 01:08:36,200 and clicking Inspect Element, we can actually see what this looks like. 1111 01:08:36,200 --> 01:08:40,290 >> Remember this is something that we created inside of that for loop 1112 01:08:40,290 --> 01:08:42,649 when we were building up that string of HTML. 1113 01:08:42,649 --> 01:08:47,870 We can see here that this data-symbol has the value of MSFT, which is great. 1114 01:08:47,870 --> 01:08:49,189 That's what we were expecting. 1115 01:08:49,189 --> 01:08:53,170 That's the symbol and that's how we got the value that we needed to use 1116 01:08:53,170 --> 01:08:56,140 inside of this text box. 1117 01:08:56,140 --> 01:08:58,850 That's enough for the quote form because that's kind of boring. 1118 01:08:58,850 --> 01:09:02,990 Let's just make some quick enhancements to our portfolio page. 1119 01:09:02,990 --> 01:09:08,109 If you've used CS50 Finance for a while and you start buying and selling a lot of stocks, 1120 01:09:08,109 --> 01:09:11,300 eventually this table is going to get pretty big, 1121 01:09:11,300 --> 01:09:13,850 and you're going to want a stock ticker, of course. 1122 01:09:13,850 --> 01:09:20,350 Once the table is really, really big, it could be useful for the user to try to search over it. 1123 01:09:20,350 --> 01:09:23,290 Inside of the search box if I start typing something like Disney 1124 01:09:23,290 --> 01:09:26,359 and looking for my Mickey Mouse stock, we can see that the table is now filtering 1125 01:09:26,359 --> 01:09:28,189 based on what I just typed in. 1126 01:09:28,189 --> 01:09:31,640 This functionality looks super complicated, but it's really, really easy 1127 01:09:31,640 --> 01:09:33,859 with jQuery and JavaScript. 1128 01:09:33,859 --> 01:09:39,189 This portfolio.php file includes a JavaScript file called portfolio.js. 1129 01:09:39,189 --> 01:09:41,130 Let's take a look at that. 1130 01:09:41,130 --> 01:09:44,890 So html, js, portfolio. 1131 01:09:44,890 --> 01:09:49,210 Here's where we're doing that searching on the table. 1132 01:09:49,210 --> 01:09:52,750 The first thing I need to do is attach an event handler to that text box 1133 01:09:52,750 --> 01:09:55,760 because we know that we want our filtering function to fire 1134 01:09:55,760 --> 01:09:59,800 every time the user presses something because we don't have time for Search buttons. 1135 01:09:59,800 --> 01:10:03,000 The first thing we need to do is figure out what the user is searching for, 1136 01:10:03,000 --> 01:10:04,780 just like we did before. 1137 01:10:04,780 --> 01:10:11,320 This keyword refers to the current element the user is interacting with. 1138 01:10:11,320 --> 01:10:14,070 >> Because the user is interacting with the search box, 1139 01:10:14,070 --> 01:10:17,020 $ this represents the search box, 1140 01:10:17,020 --> 01:10:21,820 so this.val gives us what's inside of the search box the user is currently typing. 1141 01:10:22,810 --> 01:10:27,320 So, now what we want to do is we want to iterate over all of the rows 1142 01:10:27,320 --> 01:10:29,240 inside of our table. 1143 01:10:29,240 --> 01:10:35,630 To select all of the rows in our table, I gave that table an ID of table portfolio, 1144 01:10:35,630 --> 01:10:39,060 and each row is represented by a TR element, 1145 01:10:39,060 --> 01:10:42,080 so this selector is going to return to me a big array 1146 01:10:42,080 --> 01:10:44,370 of all the rows in my table. 1147 01:10:44,370 --> 01:10:47,010 Now I want to iterate over that array. 1148 01:10:47,010 --> 01:10:52,390 I could you a for loop, but jQuery actually provides us the nice function called "each." 1149 01:10:52,390 --> 01:10:55,220 What each does is each takes one argument, 1150 01:10:55,220 --> 01:10:57,090 and that argument is a function. 1151 01:10:57,090 --> 01:11:02,760 What it's going to do is it's going to apply that function to every element inside of this list. 1152 01:11:02,760 --> 01:11:05,550 This function takes one argument that's e, 1153 01:11:05,550 --> 01:11:10,090 and when this function is executed, this e is going to be replaced with the first row, 1154 01:11:10,090 --> 01:11:12,070 then the second row, and then the third row. 1155 01:11:12,070 --> 01:11:15,150 By this way, this is the same thing as running a for loop 1156 01:11:15,150 --> 01:11:21,360 and then figuring the current element based on the index inside of your for loop. 1157 01:11:21,360 --> 01:11:24,750 At each iteration, for each of these elements in the table, 1158 01:11:24,750 --> 01:11:30,560 I want to check if the text of the element--the text of the cell inside of the row-- 1159 01:11:30,560 --> 01:11:33,130 matches what I'm searching for. 1160 01:11:33,130 --> 01:11:36,390 This big long string of commands is how I could do that. 1161 01:11:36,390 --> 01:11:40,900 First, again, this now refers to--because it's inside of a new function-- 1162 01:11:40,900 --> 01:11:45,020 this is now the current row in the table. 1163 01:11:45,020 --> 01:11:47,340 I want to take the current row in the table, 1164 01:11:47,340 --> 01:11:49,950 and I want to get all of its children. 1165 01:11:49,950 --> 01:11:51,940 Remember, the DOM is a hierarchical tree, 1166 01:11:51,940 --> 01:11:54,200 which means that elements have a number of children. 1167 01:11:54,200 --> 01:12:00,180 >> This .children function is going to return to me back an array of all of the elements 1168 01:12:00,180 --> 01:12:03,240 that are the children of, in this case, a row in the table. 1169 01:12:03,240 --> 01:12:07,150 This is just simply the cells inside of the row. 1170 01:12:07,150 --> 01:12:09,230 I just want to search over the first cell. 1171 01:12:09,230 --> 01:12:13,090 This .first function says give me the first element in that array. 1172 01:12:13,090 --> 01:12:17,070 Then the text function says get me exactly what's inside of that cell 1173 01:12:17,070 --> 01:12:19,530 since I want to search over that text. 1174 01:12:19,530 --> 01:12:21,040 Finally, let's convert it to lowercase, 1175 01:12:21,040 --> 01:12:23,940 so we can do text case insensitive queries. 1176 01:12:23,940 --> 01:12:29,990 Finally, we want to see if that string inside of a table contains the string we're searching for. 1177 01:12:29,990 --> 01:12:32,980 The indexOf function in JavaScript does just that. 1178 01:12:32,980 --> 01:12:37,060 It tells us whether or not this string contains another string. 1179 01:12:37,060 --> 01:12:40,150 If it's true that the cell contains what I'm searching for, 1180 01:12:40,150 --> 01:12:42,140 then I want to make sure that it's shown. 1181 01:12:42,140 --> 01:12:45,330 The show method will say, "Show the element." 1182 01:12:45,330 --> 01:12:50,350 If this is not the case, then that means whatever I'm searching for is not contained 1183 01:12:50,350 --> 01:12:53,550 within that row, and so I want to hide is from the user. 1184 01:12:53,550 --> 01:12:59,240 That achieves that nice filtering effect where no longer we see the entire table. 1185 01:12:59,240 --> 01:13:01,480 If you're interested in how to make this ticker as well, 1186 01:13:01,480 --> 01:13:04,180 we'll post the source online. But it's really simple. 1187 01:13:04,180 --> 01:13:09,860 JQuery has awesome methods for these animations and manipulating CSS properties. 1188 01:13:09,860 --> 01:13:11,020 So, that's it for me. 1189 01:13:11,020 --> 01:13:15,560 >> What then lies ahead? As you'll see in a few days, the final projects proposal is due. 1190 01:13:15,560 --> 01:13:17,730 The final projects proposal will ask you a few questions, 1191 01:13:17,730 --> 01:13:19,420 but among them will be three milestones-- 1192 01:13:19,420 --> 01:13:22,840 one a "good" milestone, one a better milestone, and one a best. 1193 01:13:22,840 --> 01:13:25,870 The idea being really to help you guys set your expectations 1194 01:13:25,870 --> 01:13:29,160 so that minimally you will be happy with the output of your final project 1195 01:13:29,160 --> 01:13:32,060 and it will be "good" so far as you are concerned. 1196 01:13:32,060 --> 01:13:34,540 But then in the interest of getting you to reach just a little bit to something better 1197 01:13:34,540 --> 01:13:37,680 or something best, we'll also sort of push you toward that as well. 1198 01:13:37,680 --> 01:13:40,660 The CS50 Hack-a-thon, meanwhile, is in a few weeks. 1199 01:13:40,660 --> 01:13:44,340 Typically, we do this on a lottery basis basis because of interest, 1200 01:13:44,340 --> 01:13:47,680 but odds are we'll take a few hundred of us in shuttle buses from Harvard Square 1201 01:13:47,680 --> 01:13:51,540 down to Kendall Square where Microsoft has a beautiful facility aptly called "N.E.R.D."-- 1202 01:13:51,540 --> 01:13:53,830 the New England Research and Development Center. 1203 01:13:53,830 --> 01:13:56,380 We'll get there around 8 p.m. We'll have some food. 1204 01:13:56,380 --> 01:13:58,160 Around 1 a.m. we'll have some more food. 1205 01:13:58,160 --> 01:14:02,150 Around 5 a.m. if you're still awake we'll head over to IHOP or take you back to campus. 1206 01:14:02,150 --> 01:14:04,380 The objective there is to dive into final projects 1207 01:14:04,380 --> 01:14:06,190 alongside of classmates and staff. 1208 01:14:06,190 --> 01:14:08,280 Then a few days later is the CS50 Fair, 1209 01:14:08,280 --> 01:14:10,990 which is really meant to be a opportunity for you guys to showcase your work 1210 01:14:10,990 --> 01:14:12,700 and accomplishments for the semester 1211 01:14:12,700 --> 01:14:15,610 while rubbing shoulders with each other and getting a sense of what everyone did. 1212 01:14:15,610 --> 01:14:17,850 With that said, many thanks to Tommy and to Joseph, 1213 01:14:17,850 --> 01:14:19,960 and we will see you on Monday. 1214 01:14:19,960 --> 01:14:24,070 [applause]