1 00:00:00,000 --> 00:00:14,910 2 00:00:14,910 --> 00:00:18,450 SPEAKER 1: All right, this is CS50, week 10. 3 00:00:18,450 --> 00:00:20,820 And you'll recall that last time we introduced 4 00:00:20,820 --> 00:00:25,920 one of our additional languages in CS40, that of SQL, Structured Query Language. 5 00:00:25,920 --> 00:00:29,850 And this, recall, was a language that we used to query databases, insert data 6 00:00:29,850 --> 00:00:32,130 into databases, delete, update, and more, 7 00:00:32,130 --> 00:00:34,390 so that we actually have a way of persisting data 8 00:00:34,390 --> 00:00:38,080 once we built a web-based application, or really any other application 9 00:00:38,080 --> 00:00:41,020 that we want to be able to store data long-term. 10 00:00:41,020 --> 00:00:45,550 And we had such statements as create for creating a database or a table, insert, 11 00:00:45,550 --> 00:00:48,130 select, update, delete, and a few others as well. 12 00:00:48,130 --> 00:00:50,600 And with these relatively few building blocks, 13 00:00:50,600 --> 00:00:53,910 we're able to start building a back-end for a web service. 14 00:00:53,910 --> 00:00:57,930 And indeed weeks ago when we first implemented a front-end for Google, 15 00:00:57,930 --> 00:01:00,180 simply by implementing that web form, we didn't really 16 00:01:00,180 --> 00:01:03,450 have anything to do with the data or anywhere to query for data. 17 00:01:03,450 --> 00:01:07,680 But now we actually do via our own database in the form of SQLite 18 00:01:07,680 --> 00:01:10,900 and via this new language, SQL itself. 19 00:01:10,900 --> 00:01:15,602 But today we introduce really the last of our formal languages in CS50. 20 00:01:15,602 --> 00:01:17,560 Recall that we began the semester with Scratch, 21 00:01:17,560 --> 00:01:21,030 transitioning quickly thereafter to C where we spent a lot of the semester. 22 00:01:21,030 --> 00:01:23,540 We have since pivoted to Python of course, 23 00:01:23,540 --> 00:01:26,410 whose syntax is quite different, but whose ideas 24 00:01:26,410 --> 00:01:28,000 are really fundamentally the same. 25 00:01:28,000 --> 00:01:30,500 Today we transition to JavaScript. 26 00:01:30,500 --> 00:01:33,790 And JavaScript you'll find is more syntactically similar probably 27 00:01:33,790 --> 00:01:37,185 to C than it is to Python itself. 28 00:01:37,185 --> 00:01:39,310 So you'll see that a few more parentheses are back, 29 00:01:39,310 --> 00:01:41,000 perhaps some semi-colons as well. 30 00:01:41,000 --> 00:01:44,810 But what's most important today is that really the fundamentals of programming 31 00:01:44,810 --> 00:01:45,820 aren't changing. 32 00:01:45,820 --> 00:01:51,090 But rather the method via which we actually execute or run this code. 33 00:01:51,090 --> 00:01:52,980 In particular, thus far, when we've written 34 00:01:52,980 --> 00:01:57,550 C code, when we've written Python code, all of that code has run on the server, 35 00:01:57,550 --> 00:02:01,510 so to speak, within CS50 IDE or maybe on your own Mac or your own PC 36 00:02:01,510 --> 00:02:03,560 if you have some prior programming experience. 37 00:02:03,560 --> 00:02:07,530 But today we introduce a language that is generally, though not always, 38 00:02:07,530 --> 00:02:10,380 used within the client, the browser. 39 00:02:10,380 --> 00:02:13,000 Which is to say the code that we start writing today-- 40 00:02:13,000 --> 00:02:17,290 and when you generally use JavaScript in order create front-end user interfaces, 41 00:02:17,290 --> 00:02:20,890 you will find that the code you write, like HTML or CSS, 42 00:02:20,890 --> 00:02:25,080 is actually sent to the user's browser where it's executed, again 43 00:02:25,080 --> 00:02:26,820 client-side, on the Mac on the PC. 44 00:02:26,820 --> 00:02:28,630 It is not executed server-side. 45 00:02:28,630 --> 00:02:32,010 Now to be fair, JavaScript can be and is increasingly used on the server-side 46 00:02:32,010 --> 00:02:35,210 as well via frameworks called Node.js, if not others. 47 00:02:35,210 --> 00:02:38,997 But we'll focus predominantly on client-side usage thereof. 48 00:02:38,997 --> 00:02:41,830 And you'll see that you can start to do some pretty powerful things, 49 00:02:41,830 --> 00:02:45,510 because not only now do we have the ability to have a dynamic back-end that 50 00:02:45,510 --> 00:02:47,920 serves up data and searches things for us, 51 00:02:47,920 --> 00:02:51,650 but a front-end that gives us all the better user interface and features 52 00:02:51,650 --> 00:02:52,350 still. 53 00:02:52,350 --> 00:02:56,000 So I was thinking back yesterday on when I first started using JavaScript. 54 00:02:56,000 --> 00:02:59,600 And it was in a very, very small isolated instance. 55 00:02:59,600 --> 00:03:03,060 But way back in the day-- and this is thanks to the wayback machine, 56 00:03:03,060 --> 00:03:06,150 you may recall Frosh IMs was something I did in college. 57 00:03:06,150 --> 00:03:08,280 Not so much in sports but more the website. 58 00:03:08,280 --> 00:03:14,020 And this was essentially the layout-- apologies-- of the Frosh IMs website 59 00:03:14,020 --> 00:03:15,002 some years ago. 60 00:03:15,002 --> 00:03:16,960 Now this actually post-dates me by a few years, 61 00:03:16,960 --> 00:03:20,560 since it seems the codebase actually survived me by quite a few years, 62 00:03:20,560 --> 00:03:21,360 surprisingly. 63 00:03:21,360 --> 00:03:25,390 But early on, when you would hover over these menu options at top right, 64 00:03:25,390 --> 00:03:30,350 those would have what are called event listeners attached to them so 65 00:03:30,350 --> 00:03:32,550 that when you hover over some of those menu options, 66 00:03:32,550 --> 00:03:34,100 the color would actually change. 67 00:03:34,100 --> 00:03:35,980 And I think they shifted positions slightly. 68 00:03:35,980 --> 00:03:39,671 So [INAUDIBLE] ultimately took over the site and took it further than that. 69 00:03:39,671 --> 00:03:41,420 But this was my first taste of JavaScript. 70 00:03:41,420 --> 00:03:44,390 And it was just to give the website a sense of dynamism 71 00:03:44,390 --> 00:03:48,280 and to give it a sense of interactivity that wasn't possible, certainly 72 00:03:48,280 --> 00:03:51,870 not at the time, with HTML alone. 73 00:03:51,870 --> 00:03:54,880 So let's do a quick compare and contrast of JavaScript 74 00:03:54,880 --> 00:03:57,910 with things we've seen in the past, just to kind of bring ourselves up 75 00:03:57,910 --> 00:03:59,030 to speed on some of the syntax. 76 00:03:59,030 --> 00:04:01,321 But you'll find we need to spend relatively little time 77 00:04:01,321 --> 00:04:03,970 on the syntax and the language itself, because you'll 78 00:04:03,970 --> 00:04:05,940 find syntactically it's so similar. 79 00:04:05,940 --> 00:04:09,700 And so instead we'll focus more on ideas and new features of the language 80 00:04:09,700 --> 00:04:10,450 itself. 81 00:04:10,450 --> 00:04:12,860 So as in C and in Python, we have the ability 82 00:04:12,860 --> 00:04:14,722 to express functions in JavaScript. 83 00:04:14,722 --> 00:04:17,180 They look a little bit different, at least at first glance. 84 00:04:17,180 --> 00:04:18,680 But fundamentally they're really the same. 85 00:04:18,680 --> 00:04:20,519 In JavaScript, if we want to function, we're 86 00:04:20,519 --> 00:04:22,610 going to use the keyword function to say, 87 00:04:22,610 --> 00:04:25,796 hey browser, here comes a function followed by the function's names, 88 00:04:25,796 --> 00:04:27,920 zero or more parameters, and then between the curly 89 00:04:27,920 --> 00:04:31,320 braces a bit of code that implements that function. 90 00:04:31,320 --> 00:04:35,110 So gone is the ability to just indent your code 91 00:04:35,110 --> 00:04:37,490 and have the interpreter know what you mean. 92 00:04:37,490 --> 00:04:41,642 Those curly braces are back as are more parentheses for us here in JavaScript. 93 00:04:41,642 --> 00:04:44,100 But in terms of loops you should find this fairly familiar. 94 00:04:44,100 --> 00:04:47,310 In JavaScript if you want to iterate over something again and again 95 00:04:47,310 --> 00:04:50,210 and again, the do while construct is actually back. 96 00:04:50,210 --> 00:04:52,790 So we have something very similar here as we do in C. 97 00:04:52,790 --> 00:04:55,280 And what you use that loop for can be any number of things. 98 00:04:55,280 --> 00:04:57,630 But we do have that capability again. 99 00:04:57,630 --> 00:05:00,480 Similarly, do we have while or while true loop here, 100 00:05:00,480 --> 00:05:01,980 which would induce an infinite loop. 101 00:05:01,980 --> 00:05:05,250 And again, these are the kinds of things that might trip you up unnecessarily 102 00:05:05,250 --> 00:05:06,770 at first, but quite reasonably. 103 00:05:06,770 --> 00:05:10,240 Like if you start capitalizing true again, 104 00:05:10,240 --> 00:05:12,020 it's not going to work in JavaScript. 105 00:05:12,020 --> 00:05:14,380 So again, reasonable people will disagree when 106 00:05:14,380 --> 00:05:16,230 it comes to designing these languages. 107 00:05:16,230 --> 00:05:20,220 And so the authors of JavaScript decided to lower case true and false, 108 00:05:20,220 --> 00:05:24,030 where again in Python we've been capitalizing recently, true and false. 109 00:05:24,030 --> 00:05:28,860 Meanwhile, if you want to declare a loop using a for loop, that is back. 110 00:05:28,860 --> 00:05:31,430 But you'll notice perhaps implicit in this example 111 00:05:31,430 --> 00:05:36,050 is the fact that JavaScript is, like Python, not strongly typed. 112 00:05:36,050 --> 00:05:37,880 It does have the notion of data types. 113 00:05:37,880 --> 00:05:40,230 And you can access or look at those data types. 114 00:05:40,230 --> 00:05:42,720 But you don't have to specify them as the programmer 115 00:05:42,720 --> 00:05:44,260 when you're declaring variables. 116 00:05:44,260 --> 00:05:46,010 Rather, in the case like this, when you're 117 00:05:46,010 --> 00:05:50,100 declaring a counter like I, which should be an integer from 0 up to 50, 118 00:05:50,100 --> 00:05:53,510 you literally say, var, for variable, than the name you want to declare 119 00:05:53,510 --> 00:05:57,900 and then just the rest of the syntax is as we've seen before. 120 00:05:57,900 --> 00:06:02,190 Meanwhile, there's another handy feature-- and you'll see this in use 121 00:06:02,190 --> 00:06:07,080 in various examples perhaps online-- is the very easy ability, like in Python, 122 00:06:07,080 --> 00:06:10,360 to iterate over the keys in an object. 123 00:06:10,360 --> 00:06:12,470 So recall that an object, at least in Python, 124 00:06:12,470 --> 00:06:15,320 is really just a collection of key value pairs. 125 00:06:15,320 --> 00:06:17,570 But it's an object can also have methods inside of it. 126 00:06:17,570 --> 00:06:20,970 But if we focus entirely on data, keys, and values, 127 00:06:20,970 --> 00:06:24,190 this syntax here would allow you to iterate over all of the keys 128 00:06:24,190 --> 00:06:25,430 and some value coming back. 129 00:06:25,430 --> 00:06:27,780 So maybe if you have a stock object, you could 130 00:06:27,780 --> 00:06:30,690 iterate over its name and its price and its symbol, 131 00:06:30,690 --> 00:06:35,060 simply by using syntax like this, and an index into the object 132 00:06:35,060 --> 00:06:37,140 to get at that object's value. 133 00:06:37,140 --> 00:06:39,210 Meanwhile, variables are fairly straightforward. 134 00:06:39,210 --> 00:06:43,560 To declare a variable like I, we would say var I equals 0, and a semi-colon. 135 00:06:43,560 --> 00:06:45,956 Boolean expressions, meanwhile, are with us still. 136 00:06:45,956 --> 00:06:47,080 And these are no different. 137 00:06:47,080 --> 00:06:49,140 I is less than 50 might be expressed with this. 138 00:06:49,140 --> 00:06:51,420 X is less than y might be expressed with this. 139 00:06:51,420 --> 00:06:52,650 So nothing new there. 140 00:06:52,650 --> 00:06:56,200 Meanwhile with conditions, we have syntax identical to C. 141 00:06:56,200 --> 00:06:58,160 So again, the curly braces are necessary, 142 00:06:58,160 --> 00:07:01,900 at least if you have multiple lines that you intend to be associated 143 00:07:01,900 --> 00:07:03,700 with the if or the else if or the else. 144 00:07:03,700 --> 00:07:08,400 Again we're back to, else space if, instead of L if in Python. 145 00:07:08,400 --> 00:07:11,840 But again, there's nothing really new here in terms of content, really just 146 00:07:11,840 --> 00:07:12,450 syntax. 147 00:07:12,450 --> 00:07:14,660 So after practice and after some trial and error, 148 00:07:14,660 --> 00:07:17,870 you'll generally find that it becomes second nature. 149 00:07:17,870 --> 00:07:19,620 Meanwhile, we have arrays in JavaScript. 150 00:07:19,620 --> 00:07:22,510 So for instance, if we want to declare an array called numbers, 151 00:07:22,510 --> 00:07:27,140 again we don't specify the type of this array or the members therein. 152 00:07:27,140 --> 00:07:29,020 We simply say var, to give us a variable, 153 00:07:29,020 --> 00:07:30,770 number shall be the name of that variable. 154 00:07:30,770 --> 00:07:35,170 And then a list here of arbitrary numbers themselves 155 00:07:35,170 --> 00:07:37,130 nested in between square brackets. 156 00:07:37,130 --> 00:07:40,080 So in JavaScript, as we've seen in Python, 157 00:07:40,080 --> 00:07:43,250 we have the ability to express lists or arrays specifically 158 00:07:43,250 --> 00:07:47,510 in JavaScript that simply use square bracket notation to define them 159 00:07:47,510 --> 00:07:49,140 in a context like this. 160 00:07:49,140 --> 00:07:51,310 Meanwhile, speaking of objects a moment ago, 161 00:07:51,310 --> 00:07:54,250 we have that same ability in JavaScript to declare them. 162 00:07:54,250 --> 00:07:58,610 So for instance, if we wanted to declare an object, and we'll call it quote, 163 00:07:58,610 --> 00:08:01,520 we use, as in Python, curly braces. 164 00:08:01,520 --> 00:08:04,250 And I say as in Python because in Python really 165 00:08:04,250 --> 00:08:06,730 when I say object, focusing entirely on data, 166 00:08:06,730 --> 00:08:10,350 I really mean a Python dictionary or dict object, which again 167 00:08:10,350 --> 00:08:12,190 is this collection of key value pairs. 168 00:08:12,190 --> 00:08:14,750 We don't necessarily do things quite the same way. 169 00:08:14,750 --> 00:08:17,600 But in this case here, var quote is a way of porting, 170 00:08:17,600 --> 00:08:21,120 say, from a CS50 finance example, a company's name 171 00:08:21,120 --> 00:08:23,080 and its price and its symbol. 172 00:08:23,080 --> 00:08:26,560 And worth noting here, that as in Python, you actually 173 00:08:26,560 --> 00:08:29,802 have choice over the quotes that you use, at least in this context. 174 00:08:29,802 --> 00:08:30,760 Single quotes are fine. 175 00:08:30,760 --> 00:08:31,718 Double quotes are fine. 176 00:08:31,718 --> 00:08:33,880 So long as you are stylistically consistent, 177 00:08:33,880 --> 00:08:37,319 it's probably fair to say that many people in the JavaScript community 178 00:08:37,319 --> 00:08:38,610 tend to use single quotes here. 179 00:08:38,610 --> 00:08:41,299 There's no functional difference as there is in C. 180 00:08:41,299 --> 00:08:44,220 However, they do matter, as you'll perhaps 181 00:08:44,220 --> 00:08:49,130 eventually see, when you're using not JavaScript per se, but JSON notation. 182 00:08:49,130 --> 00:08:53,130 JavaScript Object Notation, which is a simple data 183 00:08:53,130 --> 00:08:58,670 format not unlike CSV, but that allows you to store a hierarchical data 184 00:08:58,670 --> 00:08:59,660 inside of an object. 185 00:08:59,660 --> 00:09:04,790 And the subtlety there is that when you want to store data in this JSON format, 186 00:09:04,790 --> 00:09:08,150 you have to quote literally everything with specifically double quotes 187 00:09:08,150 --> 00:09:09,490 on the left and on the right. 188 00:09:09,490 --> 00:09:10,600 So it's an annoying distinction. 189 00:09:10,600 --> 00:09:12,141 And don't fret too much about it now. 190 00:09:12,141 --> 00:09:14,610 But just realize any time we're talking about JSON 191 00:09:14,610 --> 00:09:17,930 and a technology called AJAX-- more on that soon-- it's 192 00:09:17,930 --> 00:09:19,770 got to look like this with the double quotes 193 00:09:19,770 --> 00:09:22,810 on both sides of the colon for those key value pairs. 194 00:09:22,810 --> 00:09:26,270 Now with that said, let's start to give ourselves some context. 195 00:09:26,270 --> 00:09:30,621 Let me introduce a few features that we've kind of sort of seen in Python-- 196 00:09:30,621 --> 00:09:32,370 didn't necessarily leverage, but are going 197 00:09:32,370 --> 00:09:36,400 to be really integral to the way in which many people use JavaScript 198 00:09:36,400 --> 00:09:37,420 within browsers. 199 00:09:37,420 --> 00:09:39,760 So here, for instance, is that old simple example 200 00:09:39,760 --> 00:09:42,600 of HTML, perhaps the simplest web page that we can write, 201 00:09:42,600 --> 00:09:46,880 that quite simply says in its title and its body, hello world. 202 00:09:46,880 --> 00:09:51,450 And recall that the indentation here is functionally meaningless. 203 00:09:51,450 --> 00:09:55,030 The browser doesn't really care how pretty your HTML looks, just 204 00:09:55,030 --> 00:09:58,905 nicer for us humans to see everything nested and nicely indented, 205 00:09:58,905 --> 00:10:00,530 because it's just a lot easier to read. 206 00:10:00,530 --> 00:10:04,010 And it's also a lot easier to detect if you type something wrong, if something 207 00:10:04,010 --> 00:10:06,130 doesn't really line up as you expect. 208 00:10:06,130 --> 00:10:11,360 But another way, recall, of viewing this same piece of HTML 209 00:10:11,360 --> 00:10:13,750 is in the form of a data structure like a tree, which 210 00:10:13,750 --> 00:10:16,140 we discussed way back when in the context of C. 211 00:10:16,140 --> 00:10:19,670 And we might draw this same example of HTML 212 00:10:19,670 --> 00:10:23,730 with a Dom, document object model, which is a fancy way of saying tree. 213 00:10:23,730 --> 00:10:25,430 And that tree might look like this. 214 00:10:25,430 --> 00:10:28,890 It's got some special root node that we'll just generically call document, 215 00:10:28,890 --> 00:10:30,730 because there might actually be some other stuff like comments 216 00:10:30,730 --> 00:10:31,870 or whatever up there. 217 00:10:31,870 --> 00:10:35,070 But the root element of a web page, recall, is HTML. 218 00:10:35,070 --> 00:10:38,810 The second thing you type is open bracket HTML. 219 00:10:38,810 --> 00:10:42,860 The first thing you should type with HTML5 is open bracket doc type HTML. 220 00:10:42,860 --> 00:10:46,040 So you can think of the doc type as meaning this node essentially, 221 00:10:46,040 --> 00:10:49,860 and the open bracket HTML close bracket meaning this root element. 222 00:10:49,860 --> 00:10:52,360 Of course this page here has both a head and a body. 223 00:10:52,360 --> 00:10:55,490 That head a title, and that title has a text value inside of it, 224 00:10:55,490 --> 00:10:59,990 or a text node so to speak as does the body that happens to be identical. 225 00:10:59,990 --> 00:11:04,810 So what's nice about this mental model is that if we tie everything together 226 00:11:04,810 --> 00:11:07,840 from weeks past, sort of the markup language of HTML 227 00:11:07,840 --> 00:11:11,270 and the data structure of trees and specifically this Dom 228 00:11:11,270 --> 00:11:15,570 here, it turns out that you have the ability with JavaScript-- something 229 00:11:15,570 --> 00:11:18,230 we didn't have in C really and didn't really 230 00:11:18,230 --> 00:11:23,620 have with Python-- but the ability to change this tree in real time. 231 00:11:23,620 --> 00:11:27,480 After a browser has downloaded some HTML from a server, 232 00:11:27,480 --> 00:11:29,770 typically that content has been static. 233 00:11:29,770 --> 00:11:33,357 You can open up Chrome's console in the elements tab and futz with it manually, 234 00:11:33,357 --> 00:11:35,940 but those changes aren't persistent, even though you see them. 235 00:11:35,940 --> 00:11:40,290 And certainly no user, or no typical user is going to do or know to do that. 236 00:11:40,290 --> 00:11:42,790 But you the programmer, if you want a user 237 00:11:42,790 --> 00:11:45,840 to be able to download some web page, but then interact with it 238 00:11:45,840 --> 00:11:48,110 and have that content change-- very similar in spirit 239 00:11:48,110 --> 00:11:51,350 to something like Gmail, whereby every time you get an email, 240 00:11:51,350 --> 00:11:54,610 a new row in your inbox appears without the whole page 241 00:11:54,610 --> 00:11:57,820 having to reload and certainly without you having to click Reload. 242 00:11:57,820 --> 00:12:02,700 Or something like Facebook Messenger, where no matter the time of day 243 00:12:02,700 --> 00:12:06,000 if you have Facebook open in a tab, it's just going to pop up a message 244 00:12:06,000 --> 00:12:08,940 and keep adding to that little window-- another line, another line, 245 00:12:08,940 --> 00:12:10,270 another line of text. 246 00:12:10,270 --> 00:12:15,410 So there's this dynamism you get that you can't get from HTML and CSS alone, 247 00:12:15,410 --> 00:12:16,911 but you can with JavaScript. 248 00:12:16,911 --> 00:12:19,410 If you think of it just intuitively, if you have the ability 249 00:12:19,410 --> 00:12:22,790 to run code inside of a user's browser, you 250 00:12:22,790 --> 00:12:26,280 could have essentially kind of a while loop that's just constantly waiting. 251 00:12:26,280 --> 00:12:27,730 Did the server send me more data? 252 00:12:27,730 --> 00:12:29,104 Did the server send me more data? 253 00:12:29,104 --> 00:12:35,824 And if so, go ahead with an if condition and write more text to the web page. 254 00:12:35,824 --> 00:12:38,240 Write another message in the little Facebook chat message. 255 00:12:38,240 --> 00:12:40,560 Write another row to the Gmail inbox. 256 00:12:40,560 --> 00:12:44,060 And that's what we're going to get and more with JavaScript. 257 00:12:44,060 --> 00:12:49,590 And it turns out, with JavaScript, can we listen for a whole bunch of events 258 00:12:49,590 --> 00:12:50,590 so to speak. 259 00:12:50,590 --> 00:12:54,240 I eluded to an event, a listener being attached earlier. 260 00:12:54,240 --> 00:12:57,050 And this is just a small sample of the events 261 00:12:57,050 --> 00:12:59,670 that can be triggered within the confines of a web page. 262 00:12:59,670 --> 00:13:03,450 So unlike our Python programming thus far, and unlike our C programming, 263 00:13:03,450 --> 00:13:07,340 we have in JavaScript this asynchronicity. 264 00:13:07,340 --> 00:13:10,280 Multiple things can kind of sort of happen at the same time 265 00:13:10,280 --> 00:13:14,040 or really at unpredictable times because users, of course, 266 00:13:14,040 --> 00:13:15,940 are interacting now with our web pages. 267 00:13:15,940 --> 00:13:18,530 And who knows when or where a user is going to click. 268 00:13:18,530 --> 00:13:21,500 Who knows when he or she is going to click and drag something 269 00:13:21,500 --> 00:13:26,170 across the screen or select some menu option or click check some checkbox. 270 00:13:26,170 --> 00:13:29,890 So we can't really just write a program top to bottom in JavaScript 271 00:13:29,890 --> 00:13:31,970 as we've done in the past per se. 272 00:13:31,970 --> 00:13:36,790 Rather, we have to start writing code that says, if I hear a mouse click, 273 00:13:36,790 --> 00:13:40,820 or if the user drags their mouse, or if the user checks a checkbox, 274 00:13:40,820 --> 00:13:42,010 do something. 275 00:13:42,010 --> 00:13:45,980 So kind of like if this then that, if this then that. 276 00:13:45,980 --> 00:13:47,170 So a lot of conditions. 277 00:13:47,170 --> 00:13:49,100 But it turns out that it's relatively simple 278 00:13:49,100 --> 00:13:52,930 to register functions-- that is, associate functions 279 00:13:52,930 --> 00:13:54,970 with these various events. 280 00:13:54,970 --> 00:13:59,370 And so for instance, when you check a box in Gmail and all of a sudden 281 00:13:59,370 --> 00:14:01,820 the row becomes a different color or whatnot, 282 00:14:01,820 --> 00:14:04,770 that's because there's an event listener for the click event 283 00:14:04,770 --> 00:14:07,010 that Gmail is saying, as soon as the user clicks 284 00:14:07,010 --> 00:14:10,950 this event go ahead and change the color or change the interface in some way. 285 00:14:10,950 --> 00:14:14,270 Or if you click the little X in the top right-hand corner of a Facebook chat 286 00:14:14,270 --> 00:14:16,860 window, the reason it goes away is because there's 287 00:14:16,860 --> 00:14:18,940 a click event happening. 288 00:14:18,940 --> 00:14:21,950 And Facebook has written code that listens for that click event. 289 00:14:21,950 --> 00:14:25,530 And as soon as they hear that event, they close the window 290 00:14:25,530 --> 00:14:28,480 and remove it from the web page altogether. 291 00:14:28,480 --> 00:14:30,482 So Google Maps, for instance-- drag is an event. 292 00:14:30,482 --> 00:14:32,190 So if you've ever kind of wondered, well, 293 00:14:32,190 --> 00:14:35,381 how do I click and drag in Google Maps and they just know to show me 294 00:14:35,381 --> 00:14:37,880 more of the map, whatever direction I'm clicking in, they're 295 00:14:37,880 --> 00:14:39,440 listening for the drag event. 296 00:14:39,440 --> 00:14:42,800 And so this is where things get really interesting with GUI side programming-- 297 00:14:42,800 --> 00:14:44,860 graphical user interface programming. 298 00:14:44,860 --> 00:14:48,570 There's this whole event model, where a bunch of events, a bunch of things 299 00:14:48,570 --> 00:14:51,320 can happen at any number of times. 300 00:14:51,320 --> 00:14:53,410 Or at any point in time. 301 00:14:53,410 --> 00:14:58,412 So let's offer a few general definitions of terms and features of JavaScript. 302 00:14:58,412 --> 00:15:00,870 But let's actually discuss them in the context of examples. 303 00:15:00,870 --> 00:15:05,840 So JavaScript supports and really, really leverages, 304 00:15:05,840 --> 00:15:08,240 typically things called anonymous functions, 305 00:15:08,240 --> 00:15:09,820 otherwise known as lambda functions. 306 00:15:09,820 --> 00:15:12,407 And these quite simply are functions that have no name. 307 00:15:12,407 --> 00:15:13,740 And that seems a little strange. 308 00:15:13,740 --> 00:15:17,210 But we will see contexts in which functions don't need names 309 00:15:17,210 --> 00:15:20,840 if you're only going to call them once, or if you only 310 00:15:20,840 --> 00:15:23,160 need to refer to them really once. 311 00:15:23,160 --> 00:15:27,200 So we'll see how to declare and define a function that doesn't actually have 312 00:15:27,200 --> 00:15:29,830 a name like foo or bar or whatever. 313 00:15:29,830 --> 00:15:34,210 Meanwhile, we're going to see a methodology involving callbacks, 314 00:15:34,210 --> 00:15:37,380 which is very similar in spirit to the events I rattled off a moment ago. 315 00:15:37,380 --> 00:15:40,620 Whereby a call back is just a function that's 316 00:15:40,620 --> 00:15:43,500 supposed to get called when something happens. 317 00:15:43,500 --> 00:15:46,550 So in other words, Google and Facebook with those user interfaces, 318 00:15:46,550 --> 00:15:48,120 they are registering functions. 319 00:15:48,120 --> 00:15:52,080 Really, they're registering callbacks, so that when the user clicks on an X 320 00:15:52,080 --> 00:15:55,780 or when the user clicks on a checkbox, or when the user clicks and drags 321 00:15:55,780 --> 00:16:01,430 on a map, they have in advanced register a function that gets called back. 322 00:16:01,430 --> 00:16:04,700 It's like leaving a message for someone on voicemail. 323 00:16:04,700 --> 00:16:07,050 They call you back in response to that voicemail. 324 00:16:07,050 --> 00:16:09,677 They call you back in response to the beep 325 00:16:09,677 --> 00:16:11,760 that their phone makes when they've received that. 326 00:16:11,760 --> 00:16:15,100 So it triggers some kind of functionality, these callbacks. 327 00:16:15,100 --> 00:16:17,410 Callbacks are just functions that have been 328 00:16:17,410 --> 00:16:21,139 configured to be called at a certain point in time when something happens. 329 00:16:21,139 --> 00:16:22,930 Now meanwhile, and lastly, we'll talk about 330 00:16:22,930 --> 00:16:25,100 AJAX, which isn't a technology unto itself 331 00:16:25,100 --> 00:16:28,610 but a use of various existing features within browsers 332 00:16:28,610 --> 00:16:32,420 that allow you to query from a browser, a server 333 00:16:32,420 --> 00:16:37,360 to get more data even after the original page has been loaded. 334 00:16:37,360 --> 00:16:43,010 Let me go ahead here and create a file called, say, Dom 0 dot HTML. 335 00:16:43,010 --> 00:16:46,090 Document object 0 dot HTML just to line up with some of the examples 336 00:16:46,090 --> 00:16:48,890 that we'll place online for everyone to play with. 337 00:16:48,890 --> 00:16:51,670 I'm going to go ahead and start my page as I usually do. 338 00:16:51,670 --> 00:16:53,706 And I'm going to go ahead and say HTML. 339 00:16:53,706 --> 00:16:55,580 And then in here I'm going to have a head tag 340 00:16:55,580 --> 00:16:57,120 and in here I'm going to have a title tag. 341 00:16:57,120 --> 00:16:59,480 And I'm just going to call this Dom 0 for simplicity. 342 00:16:59,480 --> 00:17:01,110 Down here I'm going to a body tag. 343 00:17:01,110 --> 00:17:03,450 And in here I'm going to have a form. 344 00:17:03,450 --> 00:17:05,560 I'm going to give this form, similar in spirit 345 00:17:05,560 --> 00:17:08,640 as we did in our discussions of CSS, a unique ID, simply 346 00:17:08,640 --> 00:17:12,160 so that I can refer to it as a demo, a demonstration. 347 00:17:12,160 --> 00:17:14,950 But let's come back to what more I want to associate with that. 348 00:17:14,950 --> 00:17:18,690 First let me go ahead and give it an input, an ID of names 349 00:17:18,690 --> 00:17:21,390 so that I can refer specifically to this input field. 350 00:17:21,390 --> 00:17:24,099 Let me give it a placeholder of name. 351 00:17:24,099 --> 00:17:26,540 And let me say that the type of this field 352 00:17:26,540 --> 00:17:28,890 is a text field to close that tag. 353 00:17:28,890 --> 00:17:32,500 And then input type equals submit. 354 00:17:32,500 --> 00:17:36,380 So a very, very simple web page that looks like this. 355 00:17:36,380 --> 00:17:39,780 Now what could go wrong if I present a user with a web page like this? 356 00:17:39,780 --> 00:17:42,530 Well, he or she might not give me their name. 357 00:17:42,530 --> 00:17:44,490 They might just click submit and this form 358 00:17:44,490 --> 00:17:46,570 is going to get submitted to some server. 359 00:17:46,570 --> 00:17:50,566 Well that doesn't seem all that great, because I don't have a chance to check, 360 00:17:50,566 --> 00:17:51,940 did they actually type in a name? 361 00:17:51,940 --> 00:17:54,730 I don't have a chance to do something with it on the client. 362 00:17:54,730 --> 00:17:57,700 And indeed that's now the new feature we get with JavaScript. 363 00:17:57,700 --> 00:17:59,750 Notice what I can actually do. 364 00:17:59,750 --> 00:18:02,530 Let me go into the head of this web page, 365 00:18:02,530 --> 00:18:06,150 where thus far we've pretty much only put the title tag. 366 00:18:06,150 --> 00:18:08,380 We've put the link tag for CSS. 367 00:18:08,380 --> 00:18:10,940 And you may have seen with CS50 Finance that we also 368 00:18:10,940 --> 00:18:14,610 had a script tag that referenced a library called Bootstrap, 369 00:18:14,610 --> 00:18:16,050 and another one called Jquery. 370 00:18:16,050 --> 00:18:17,570 More on those in a bit. 371 00:18:17,570 --> 00:18:21,410 But indeed, inside of the head of a web page can go with script tag. 372 00:18:21,410 --> 00:18:23,700 And you know what, inside of a script tag 373 00:18:23,700 --> 00:18:26,830 can go code, specifically JavaScript. 374 00:18:26,830 --> 00:18:30,030 And in here I can define a function, literally. 375 00:18:30,030 --> 00:18:33,190 I'm going to call it, greet, just to kind of say what it does. 376 00:18:33,190 --> 00:18:36,710 And inside of this function I'm going to do the following-- alert, 377 00:18:36,710 --> 00:18:40,730 quote unquote, hello, comma, world, semi-colon. 378 00:18:40,730 --> 00:18:44,020 So this is how in this example I've defined a function called greet. 379 00:18:44,020 --> 00:18:46,930 I've put it inside script tags, open and closed inside 380 00:18:46,930 --> 00:18:48,270 of the head of this web page. 381 00:18:48,270 --> 00:18:51,410 Now, nothing's going to happen with that unless I 382 00:18:51,410 --> 00:18:55,330 tell the browser to do it on an event. 383 00:18:55,330 --> 00:18:58,960 So I'm going to go into my form tag here and say on Submit, 384 00:18:58,960 --> 00:19:01,310 go ahead and execute the following code. 385 00:19:01,310 --> 00:19:05,210 Go ahead and call the greet method and greet function, 386 00:19:05,210 --> 00:19:07,200 and just for good measure return false. 387 00:19:07,200 --> 00:19:08,966 But more on that in a moment. 388 00:19:08,966 --> 00:19:10,590 So again, my function's defined up top. 389 00:19:10,590 --> 00:19:11,423 But nothing happens. 390 00:19:11,423 --> 00:19:13,770 Again, when you define a function, nothing automatically 391 00:19:13,770 --> 00:19:15,290 happens until you call it. 392 00:19:15,290 --> 00:19:16,570 So when am I going to call it? 393 00:19:16,570 --> 00:19:21,400 On the form tag here, I have an on submit attribute, 394 00:19:21,400 --> 00:19:26,670 which is new today, that says, call the greet function and then return false. 395 00:19:26,670 --> 00:19:28,490 But again, more on that in just a moment. 396 00:19:28,490 --> 00:19:30,290 So what actually happens here? 397 00:19:30,290 --> 00:19:33,660 Let me go into another window, open up DOM 0. 398 00:19:33,660 --> 00:19:36,880 And you'll see, if I now zoom in on this form, 399 00:19:36,880 --> 00:19:39,400 will see that it's a very simple HTML form with just a name 400 00:19:39,400 --> 00:19:40,940 field and a submit box. 401 00:19:40,940 --> 00:19:45,900 And if I go ahead now and type in my name, David and click Submit, 402 00:19:45,900 --> 00:19:46,920 hello world. 403 00:19:46,920 --> 00:19:49,999 So it's not actually saying hello, David, it's just saying hello world. 404 00:19:49,999 --> 00:19:51,040 But notice what happened. 405 00:19:51,040 --> 00:19:54,430 This is a very bad user interface just using this built-in prompt. 406 00:19:54,430 --> 00:19:56,370 But it demonstrates the built into JavaScript 407 00:19:56,370 --> 00:19:58,750 are a bunch of functions, one of which is alert. 408 00:19:58,750 --> 00:20:00,792 And that function is designed to do exactly this. 409 00:20:00,792 --> 00:20:02,833 The window will look a little different if you're 410 00:20:02,833 --> 00:20:05,890 using Chrome or Edge or Firefox or Safari or whatever other browser, 411 00:20:05,890 --> 00:20:08,570 but you'll see that it simply says, hello world. 412 00:20:08,570 --> 00:20:11,320 And it's going to say whatever the URL on your page happens to be. 413 00:20:11,320 --> 00:20:14,720 In my case it's just this local IP address for lecture's sake. 414 00:20:14,720 --> 00:20:17,620 But this isn't all that interesting to just hard code, hello world, 415 00:20:17,620 --> 00:20:21,520 especially when I have the opportunity to take in a user's name. 416 00:20:21,520 --> 00:20:24,770 So if I instead go back into my code here, 417 00:20:24,770 --> 00:20:27,500 and don't just print out, hello world, but perhaps 418 00:20:27,500 --> 00:20:30,650 concatenate with JavaScript's plus operator, 419 00:20:30,650 --> 00:20:36,140 the result of this method call, document dot get element by ID, 420 00:20:36,140 --> 00:20:40,000 quote unquote name, then dot value. 421 00:20:40,000 --> 00:20:40,890 So that's a mouthful. 422 00:20:40,890 --> 00:20:43,440 Let's see what this does before we explain what it does. 423 00:20:43,440 --> 00:20:45,620 Let me go ahead and reload the page. 424 00:20:45,620 --> 00:20:48,110 And now we see the same form again. 425 00:20:48,110 --> 00:20:50,960 But this time I'm going to type in David and click Submit. 426 00:20:50,960 --> 00:20:52,800 And now it says, hello, David. 427 00:20:52,800 --> 00:20:54,090 So how does this work? 428 00:20:54,090 --> 00:20:58,830 Somehow or other, I wrote code that not only alerts the user with this window, 429 00:20:58,830 --> 00:21:02,370 but it somehow grabs data that he or she has typed in 430 00:21:02,370 --> 00:21:03,940 and embeds it in this message. 431 00:21:03,940 --> 00:21:07,160 Well here is where we can leverage the DOM, the Document Object 432 00:21:07,160 --> 00:21:10,410 Model, and a bunch of functions that come with JavaScript that 433 00:21:10,410 --> 00:21:15,510 allow you to programmatically get elements and get data ultimately 434 00:21:15,510 --> 00:21:16,479 from a web page. 435 00:21:16,479 --> 00:21:18,020 Specifically notice we're doing this. 436 00:21:18,020 --> 00:21:20,120 We're calling alert, and then open paren close 437 00:21:20,120 --> 00:21:22,040 paren because it's a function call. 438 00:21:22,040 --> 00:21:24,441 Quote unquote hello comma, with a space. 439 00:21:24,441 --> 00:21:26,440 And again, single quotes, double quotes, doesn't 440 00:21:26,440 --> 00:21:29,030 matter so long as I'm consistent here. 441 00:21:29,030 --> 00:21:33,910 Plus, which is concatenation, document doc get element by ID, quote 442 00:21:33,910 --> 00:21:35,049 unquote name, dot value. 443 00:21:35,049 --> 00:21:37,340 So it's kind of a mouthful and it's definitely verbose. 444 00:21:37,340 --> 00:21:40,381 And we'll see before long slightly more succinct ways of expressing this. 445 00:21:40,381 --> 00:21:44,330 But you can think of document as being this special global variable that's 446 00:21:44,330 --> 00:21:46,720 just accessible to JavaScript code that you write. 447 00:21:46,720 --> 00:21:50,100 And that really is that uppermost node in our tree, 448 00:21:50,100 --> 00:21:52,000 that top-most node in our DOM. 449 00:21:52,000 --> 00:21:55,175 And associated with that node, which is just an object, 450 00:21:55,175 --> 00:21:58,770 are a bunch of methods or functions, that just come with JavaScript, 451 00:21:58,770 --> 00:22:01,080 and that your browser just supports for you. 452 00:22:01,080 --> 00:22:03,390 One of those is called get elements by ID. 453 00:22:03,390 --> 00:22:05,150 And recall, we've used this jargon before. 454 00:22:05,150 --> 00:22:07,600 An element in a web page is the combination 455 00:22:07,600 --> 00:22:10,350 of an open tag and a closed tag and everything in between it. 456 00:22:10,350 --> 00:22:14,560 So get element by ID quote unquote name means, hey browser, 457 00:22:14,560 --> 00:22:19,750 go get me this entire element from start to finish. 458 00:22:19,750 --> 00:22:22,070 And this is an empty element because we've 459 00:22:22,070 --> 00:22:24,150 closed it within the it's own tag. 460 00:22:24,150 --> 00:22:26,150 So that just means, go get me. 461 00:22:26,150 --> 00:22:28,500 Kind of a pointer to that node in the tree. 462 00:22:28,500 --> 00:22:30,010 There's no pointers in JavaScript. 463 00:22:30,010 --> 00:22:32,720 So we should really call this like a reference to this node. 464 00:22:32,720 --> 00:22:34,200 But it really just means that. 465 00:22:34,200 --> 00:22:36,850 Go get me somehow this node in the tree. 466 00:22:36,850 --> 00:22:39,070 And what do I care about once I have that node? 467 00:22:39,070 --> 00:22:40,650 I care about its value. 468 00:22:40,650 --> 00:22:43,990 So dot value, you can think of like syntax like a struct. 469 00:22:43,990 --> 00:22:48,960 That means, if you have this node now, via get element by ID, go inside of it 470 00:22:48,960 --> 00:22:52,660 and look for the field with a property called value. 471 00:22:52,660 --> 00:22:56,640 And that's going to line up, it turns out, with exactly what the user types. 472 00:22:56,640 --> 00:22:58,330 So I can do this again to be clear. 473 00:22:58,330 --> 00:23:02,240 Let me go up here and for instance type in Andy and click Submit. 474 00:23:02,240 --> 00:23:04,450 And voila, now it says hello, Andy. 475 00:23:04,450 --> 00:23:08,140 But now the browser-- and this is perhaps a curse from 10 476 00:23:08,140 --> 00:23:12,170 and 20 years ago when people started to abuse JavaScript and give you 477 00:23:12,170 --> 00:23:14,830 hundreds of popovers so to speak, hundreds of 478 00:23:14,830 --> 00:23:17,910 prompts if you visit a website that's trying to mess with you. 479 00:23:17,910 --> 00:23:20,780 Chrome and other browsers will let you check a box like this, 480 00:23:20,780 --> 00:23:23,067 prevent this page from creating additional dialogs, 481 00:23:23,067 --> 00:23:26,150 just because it thinks that maybe the page is buggy, maybe it's malicious, 482 00:23:26,150 --> 00:23:28,860 and it's really just pestering you as these things are annoying. 483 00:23:28,860 --> 00:23:32,230 But at least during CS50 development for P-sets projects, 484 00:23:32,230 --> 00:23:36,090 don't check this because it'll only confuse if the page no longer does 485 00:23:36,090 --> 00:23:37,550 as you tell it to do. 486 00:23:37,550 --> 00:23:41,560 Fortunately that doesn't come up too often on actual websites. 487 00:23:41,560 --> 00:23:42,060 All right. 488 00:23:42,060 --> 00:23:45,170 So we seem then to have the ability to not only get data 489 00:23:45,170 --> 00:23:49,280 from a web page programmatically and display it dynamically. 490 00:23:49,280 --> 00:23:52,570 But can we design this code a little better? 491 00:23:52,570 --> 00:23:55,560 Well it turns out that we technically don't need 492 00:23:55,560 --> 00:24:00,370 to co-mingle our code and our HTML. 493 00:24:00,370 --> 00:24:03,707 And notice too there's one other line of code here that's a little sloppy. 494 00:24:03,707 --> 00:24:05,540 I mean literally between these double quotes 495 00:24:05,540 --> 00:24:09,340 do I have two statements-- greet, which is a function call, 496 00:24:09,340 --> 00:24:10,520 and then return false. 497 00:24:10,520 --> 00:24:15,510 The reason I had return false is that if I didn't, after clicking Submit 498 00:24:15,510 --> 00:24:18,460 and submitting this form, the only thing stopping 499 00:24:18,460 --> 00:24:22,270 this form from just being submitted to the server is return false. 500 00:24:22,270 --> 00:24:25,680 This says, hey browser, even when the user tries to submit this form, don't. 501 00:24:25,680 --> 00:24:26,920 Return false. 502 00:24:26,920 --> 00:24:28,330 The default is true. 503 00:24:28,330 --> 00:24:32,410 Otherwise, if I didn't have return false and I click Submit, 504 00:24:32,410 --> 00:24:35,130 I would see that alert as expected, but the moment I dismiss it, 505 00:24:35,130 --> 00:24:37,630 I'm going to be led to some other web page, presumably wherever 506 00:24:37,630 --> 00:24:39,540 the form is going to be submitted, which coincidentally 507 00:24:39,540 --> 00:24:41,050 happens to be the same page. 508 00:24:41,050 --> 00:24:44,680 But now that we're developing client-side applications, 509 00:24:44,680 --> 00:24:47,130 client-side web apps, we don't necessarily 510 00:24:47,130 --> 00:24:49,040 want forms to be submitted to the server. 511 00:24:49,040 --> 00:24:52,966 We want to use them, for now, only within the confines of a browser. 512 00:24:52,966 --> 00:24:55,340 Indeed there is no back-end, there is no action attribute 513 00:24:55,340 --> 00:24:57,240 for this particular example. 514 00:24:57,240 --> 00:24:58,720 But this feels messy. 515 00:24:58,720 --> 00:25:03,120 Any time in CS50 when we've introduced some new language like CSS 516 00:25:03,120 --> 00:25:07,850 in the context of HTML, or our HTML in the context of Python via our Jinja 517 00:25:07,850 --> 00:25:11,640 templates, did we try to factor out one language from another, so as not 518 00:25:11,640 --> 00:25:15,520 to blur these worlds and make the code very messy, very unmaintainable. 519 00:25:15,520 --> 00:25:20,540 So how can we begin to remove, from these quoted values, 520 00:25:20,540 --> 00:25:26,110 code, but still have this feature of listening for a form submission? 521 00:25:26,110 --> 00:25:29,740 Well let me go ahead and propose another variant of this program, 522 00:25:29,740 --> 00:25:33,270 that I'll go ahead and call DOM 1 dot HTML. 523 00:25:33,270 --> 00:25:35,190 I'm going to start with the code from before, 524 00:25:35,190 --> 00:25:37,044 but I'm going to make a few changes. 525 00:25:37,044 --> 00:25:39,460 Instead of putting it in the head of my web page, for now, 526 00:25:39,460 --> 00:25:42,060 I'm actually going to put it down here in the body. 527 00:25:42,060 --> 00:25:43,370 More on that soon. 528 00:25:43,370 --> 00:25:46,130 But instead of even declaring this as a function, 529 00:25:46,130 --> 00:25:48,940 I'm going to instead simply do this. 530 00:25:48,940 --> 00:25:51,030 I'm going to get rid of this event handler. 531 00:25:51,030 --> 00:25:55,890 So now all that remains up here, to be clear, is just pure HTML. 532 00:25:55,890 --> 00:25:58,910 I still have those ID attributes so that I can uniquely 533 00:25:58,910 --> 00:26:03,980 identify those forms and that form and those inputs if I want, 534 00:26:03,980 --> 00:26:05,460 or that input if I want. 535 00:26:05,460 --> 00:26:06,690 But notice what I can do now. 536 00:26:06,690 --> 00:26:11,790 Document dot get element by ID quote unquote demo, because that's 537 00:26:11,790 --> 00:26:18,820 the name of my form, dot on submit, gets function open paren close paren. 538 00:26:18,820 --> 00:26:22,440 And then just for stylistic purposes, let me go ahead 539 00:26:22,440 --> 00:26:26,120 and do this, which is what most JavaScript programmers would do. 540 00:26:26,120 --> 00:26:28,300 So what am I doing now? 541 00:26:28,300 --> 00:26:31,014 Now I have pure HTML appear. 542 00:26:31,014 --> 00:26:33,680 But to be fair, I now have a script tag inside of which is code. 543 00:26:33,680 --> 00:26:36,420 But at least I've removed the code from like an attribute, which 544 00:26:36,420 --> 00:26:38,620 just looked or felt a little sloppy. 545 00:26:38,620 --> 00:26:42,170 And look at the code now, document dot get element by ID demo. 546 00:26:42,170 --> 00:26:46,120 So this gives me essentially a reference to the entire form, not just 547 00:26:46,120 --> 00:26:48,100 that name field. 548 00:26:48,100 --> 00:26:53,720 And it turns out that provided that node in the tree is a form, 549 00:26:53,720 --> 00:26:57,700 and indeed it is, that has associated with it a property 550 00:26:57,700 --> 00:27:01,170 by the definition of HTML5 called on submit. 551 00:27:01,170 --> 00:27:06,860 This is a property, that if you assign it the value of a function, 552 00:27:06,860 --> 00:27:10,880 that function will get called when the form is submitted. 553 00:27:10,880 --> 00:27:14,580 And yet what function do I want to Call Well, function open paren close paren 554 00:27:14,580 --> 00:27:18,110 seems to omit a key detail that we've seen in Python and C, which 555 00:27:18,110 --> 00:27:19,530 is the name of the function. 556 00:27:19,530 --> 00:27:23,030 But here's an example where I don't care what the name of this function is. 557 00:27:23,030 --> 00:27:25,130 I don't need to know the name of this function. 558 00:27:25,130 --> 00:27:29,660 Because all I need is a function, a chunk of code that will ultimately get 559 00:27:29,660 --> 00:27:34,900 executed when this form is submitted. 560 00:27:34,900 --> 00:27:38,430 And that line of code is identical to what it was before. 561 00:27:38,430 --> 00:27:42,400 So just to be clear, this anonymous function, so to speak that I'm using, 562 00:27:42,400 --> 00:27:44,190 is not strictly necessary. 563 00:27:44,190 --> 00:27:47,860 If I really wanted to, I could do something like this. 564 00:27:47,860 --> 00:27:51,790 I could declare a function called greet, just as before. 565 00:27:51,790 --> 00:27:54,040 And I'll format it exactly as I did before. 566 00:27:54,040 --> 00:27:56,190 And I could declare this right up here. 567 00:27:56,190 --> 00:27:59,070 And then down here I could say, greet. 568 00:27:59,070 --> 00:28:01,480 In other words, the on submit handler just 569 00:28:01,480 --> 00:28:03,820 wants to know what function to call. 570 00:28:03,820 --> 00:28:04,460 So fine. 571 00:28:04,460 --> 00:28:08,790 If I find a function call greet, I can tell on submit to call greet. 572 00:28:08,790 --> 00:28:10,310 Notice, no parentheses here. 573 00:28:10,310 --> 00:28:14,160 I don't want to call the greet function when that line of code is executed. 574 00:28:14,160 --> 00:28:16,410 Rather, I want to assign that function, which 575 00:28:16,410 --> 00:28:23,090 you can think of as a variable unto itself to this on submit handler. 576 00:28:23,090 --> 00:28:23,997 But why? 577 00:28:23,997 --> 00:28:25,580 This hasn't really gained me anything. 578 00:28:25,580 --> 00:28:27,163 Yes, it's nice that it's called greet. 579 00:28:27,163 --> 00:28:31,480 But I'm defining a function called greet only to configure my browser 580 00:28:31,480 --> 00:28:33,074 to call that function one line later. 581 00:28:33,074 --> 00:28:35,240 The nice thing about anonymous functions is that you 582 00:28:35,240 --> 00:28:37,030 can just kind of tighten things up. 583 00:28:37,030 --> 00:28:39,400 Why clutter your namespace so to speak? 584 00:28:39,400 --> 00:28:42,140 Why fill up your brain with names of functions 585 00:28:42,140 --> 00:28:44,330 that you're never again going to need? 586 00:28:44,330 --> 00:28:48,050 And so more common and cleaner, better design arguably, 587 00:28:48,050 --> 00:28:51,520 would be something like this. 588 00:28:51,520 --> 00:28:52,192 All right. 589 00:28:52,192 --> 00:28:54,150 And actually just for good measure because this 590 00:28:54,150 --> 00:28:56,160 is all part of a statement, in this example 591 00:28:56,160 --> 00:28:58,129 let me put that semi-colon there. 592 00:28:58,129 --> 00:29:00,170 So the example is going to work exactly the same. 593 00:29:00,170 --> 00:29:03,420 Indeed if I go back to my browser and go into DOM 1 594 00:29:03,420 --> 00:29:07,820 dot HTML and type in something like summer and click Submit. 595 00:29:07,820 --> 00:29:08,800 Hello, summer. 596 00:29:08,800 --> 00:29:11,376 And so it behaves exactly as before. 597 00:29:11,376 --> 00:29:14,000 And for good measure, let me go ahead and change the title here 598 00:29:14,000 --> 00:29:15,754 to match the name of the file. 599 00:29:15,754 --> 00:29:17,670 But now let me go ahead and open up an example 600 00:29:17,670 --> 00:29:19,586 I wrote in advance, like many of these, called 601 00:29:19,586 --> 00:29:23,100 DOM 2 dot HTML, the code for which admittedly 602 00:29:23,100 --> 00:29:25,530 is much more cryptic at first glance. 603 00:29:25,530 --> 00:29:27,860 And indeed the syntax will take some getting used to. 604 00:29:27,860 --> 00:29:30,340 And you don't strictly need to do things this way. 605 00:29:30,340 --> 00:29:35,360 But a super popular library in the world of JavaScript today to this day 606 00:29:35,360 --> 00:29:36,560 is something called jQuery. 607 00:29:36,560 --> 00:29:38,480 And indeed the bootstrap library with which 608 00:29:38,480 --> 00:29:42,230 you're now acquainted by CS50 Finance actually uses, 609 00:29:42,230 --> 00:29:44,110 for some of its features, the jQuery library. 610 00:29:44,110 --> 00:29:47,320 So let's introduce the syntax so that you've seen it, so that you can use it. 611 00:29:47,320 --> 00:29:49,836 But realize, this is not giving us any new functionality. 612 00:29:49,836 --> 00:29:51,460 It's just giving us a different syntax. 613 00:29:51,460 --> 00:29:55,330 And over time, you'll see that jQuery, like certain other libraries, 614 00:29:55,330 --> 00:29:58,990 it tends to make it more pleasurable, more efficient to write JavaScript, 615 00:29:58,990 --> 00:30:01,190 because you can do things a little more succinctly. 616 00:30:01,190 --> 00:30:04,060 The price you pay is a little bit of complexity. 617 00:30:04,060 --> 00:30:07,930 So let's take a look syntactically at this library called jQuery. 618 00:30:07,930 --> 00:30:11,740 Notice, in DOM 2 dot HTML, I have this URL up here. 619 00:30:11,740 --> 00:30:15,310 There's any number of places to get the jQuery library and libraries more 620 00:30:15,310 --> 00:30:15,810 generally. 621 00:30:15,810 --> 00:30:18,190 But this one happens to be hosted, for instance, at this URL. 622 00:30:18,190 --> 00:30:19,690 And it's the latest version thereof. 623 00:30:19,690 --> 00:30:23,820 And this attribute source simply says, hey browser, 624 00:30:23,820 --> 00:30:28,470 go get the JavaScript code that I want to have access to from this URL, 625 00:30:28,470 --> 00:30:32,370 and assume that it's equivalent to my having written in this web page 626 00:30:32,370 --> 00:30:35,190 itself, like our other script tags thus far. 627 00:30:35,190 --> 00:30:38,590 Meanwhile, after that, an order is generally important 628 00:30:38,590 --> 00:30:40,210 when including things like this. 629 00:30:40,210 --> 00:30:42,940 Let me go ahead and do the following. 630 00:30:42,940 --> 00:30:46,000 Up here notice that I have this line of code, 631 00:30:46,000 --> 00:30:48,510 which generally is a good thing to have because it 632 00:30:48,510 --> 00:30:50,010 says the following to the browser. 633 00:30:50,010 --> 00:30:53,940 Hey, browser, when the document is ready-- 634 00:30:53,940 --> 00:30:56,130 that is, when the whole web page has been loaded, 635 00:30:56,130 --> 00:30:58,710 when all the bytes have come back from the server, 636 00:30:58,710 --> 00:31:01,590 please go ahead and execute the following code. 637 00:31:01,590 --> 00:31:04,810 And we'll see that this allows us to ensure that things don't 638 00:31:04,810 --> 00:31:07,640 happen sooner than we actually expect. 639 00:31:07,640 --> 00:31:09,380 Specifically, let's do the following. 640 00:31:09,380 --> 00:31:12,810 When the document is ready I want the browser to execute 641 00:31:12,810 --> 00:31:17,260 the following lines of code that I've highlighted here-- 642 00:31:17,260 --> 00:31:22,570 dollar sign, quote unquote, hash demo. 643 00:31:22,570 --> 00:31:23,720 It's kind of a mouthful. 644 00:31:23,720 --> 00:31:26,920 But this is simply reminiscent perhaps of the CSS syntax 645 00:31:26,920 --> 00:31:29,790 that you might be familiar, that simply says, hey browser, go 646 00:31:29,790 --> 00:31:34,280 get me the element from the DOM, from the tree representing this page, that 647 00:31:34,280 --> 00:31:35,910 has a unique ID of demo. 648 00:31:35,910 --> 00:31:39,480 So hashtag demo is just a more succinct way of saying, 649 00:31:39,480 --> 00:31:41,640 document dot get element by ID. 650 00:31:41,640 --> 00:31:44,400 You can do this all in just a few characters. 651 00:31:44,400 --> 00:31:47,480 And the dollar sign here is a feature of jQuery. 652 00:31:47,480 --> 00:31:50,500 It's actually just a synonym for jQuery. 653 00:31:50,500 --> 00:31:52,460 Dollar signs can actually be variable names. 654 00:31:52,460 --> 00:31:56,030 So dollar sign quote unquote hash demo means, hey, browser, 655 00:31:56,030 --> 00:32:00,260 execute the equivalent of document dot get element by ID, quote unquote demo. 656 00:32:00,260 --> 00:32:03,770 Just more succinct, even though it's a little bit cryptic at first glance. 657 00:32:03,770 --> 00:32:07,260 Meanwhile, submit, not to be confused with on submit submit-- submit 658 00:32:07,260 --> 00:32:09,910 is a function that per jQuery's documentation says, 659 00:32:09,910 --> 00:32:14,220 hey, browser, register the following event handler for the submit event. 660 00:32:14,220 --> 00:32:16,662 The way you do this is you provide the library 661 00:32:16,662 --> 00:32:19,620 with an anonymous function, which in this case I've just said function. 662 00:32:19,620 --> 00:32:20,580 It takes one argument. 663 00:32:20,580 --> 00:32:23,200 And I would only know this from having read the documentation. 664 00:32:23,200 --> 00:32:25,617 Function takes an argument that we'll call event. 665 00:32:25,617 --> 00:32:27,450 But we can call it call it anything we want. 666 00:32:27,450 --> 00:32:30,070 And then inside of this code, what do I want 667 00:32:30,070 --> 00:32:33,250 to do when the demo form is submitted? 668 00:32:33,250 --> 00:32:36,210 Well, I want to use alert. 669 00:32:36,210 --> 00:32:37,660 But I want to paste in this value. 670 00:32:37,660 --> 00:32:39,130 So again, just new syntax here. 671 00:32:39,130 --> 00:32:41,450 And it's fine if you prefer the other syntax for now. 672 00:32:41,450 --> 00:32:43,280 Dollar sign quote unquote hash name, means 673 00:32:43,280 --> 00:32:48,370 go get the element from the DOM that has a unique ID of name, 674 00:32:48,370 --> 00:32:51,150 and go get its value using this method call. 675 00:32:51,150 --> 00:32:56,640 So jQuery essentially does this. jQuery wraps existing elements in a DOM. 676 00:32:56,640 --> 00:32:59,376 It goes ahead and adds like another bigger rectangle 677 00:32:59,376 --> 00:33:01,250 around those smaller rectangles that give you 678 00:33:01,250 --> 00:33:03,670 additional features, among which is the ability 679 00:33:03,670 --> 00:33:08,310 to use these CSS-style selectors, among whose features is to call like dot val 680 00:33:08,310 --> 00:33:10,640 and get the value without having to do dot value, 681 00:33:10,640 --> 00:33:12,910 which isn't all that compelling in this case. 682 00:33:12,910 --> 00:33:16,640 And then we're appending, in this case, an exclamation point for good measure, 683 00:33:16,640 --> 00:33:20,650 just so to show that we can to continue to concatenate beyond one string. 684 00:33:20,650 --> 00:33:23,442 And then lastly, is this, which granted, more verbose-- event dot 685 00:33:23,442 --> 00:33:25,150 prevent default just means, hey, browser, 686 00:33:25,150 --> 00:33:28,740 whatever your default behavior is for handling forms, don't do it. 687 00:33:28,740 --> 00:33:32,790 Prevent it, because I want to handle this form submission. 688 00:33:32,790 --> 00:33:35,460 So this is a really long way of saying, this is another way 689 00:33:35,460 --> 00:33:39,030 to implement exactly the same program that we did earlier, 690 00:33:39,030 --> 00:33:41,950 albeit with an added exclamation point, which 691 00:33:41,950 --> 00:33:44,390 has nothing to do here with jQuery. 692 00:33:44,390 --> 00:33:47,580 So why is this a good thing overall? 693 00:33:47,580 --> 00:33:49,979 Well one, your code will actually get shorter over time. 694 00:33:49,979 --> 00:33:51,770 But it's fine if you'd rather not use this. 695 00:33:51,770 --> 00:33:55,250 But this first line was actually rather important. 696 00:33:55,250 --> 00:34:00,040 If I instead were to implement this code like this, there's actually a problem. 697 00:34:00,040 --> 00:34:04,370 And actually there's a problem even if I were to do it this way. 698 00:34:04,370 --> 00:34:08,719 If I were to go back to DOM 1, and I were 699 00:34:08,719 --> 00:34:16,159 to do something like this in this example, and not use jQuery at all, 700 00:34:16,159 --> 00:34:21,260 but just, in my head tag, have a script tag that has this code here, 701 00:34:21,260 --> 00:34:24,380 there's a problem of the order of operations. 702 00:34:24,380 --> 00:34:27,239 On this first line, when I say document dot get element 703 00:34:27,239 --> 00:34:35,679 by ID quote unquote demo dot on submit, assign that listener this function, 704 00:34:35,679 --> 00:34:36,904 it's too soon. 705 00:34:36,904 --> 00:34:38,820 Because the browser at this point in the story 706 00:34:38,820 --> 00:34:41,278 literally is reading the file top to bottom, left to right. 707 00:34:41,278 --> 00:34:44,050 And the browser has not got to the line of code, 708 00:34:44,050 --> 00:34:49,239 where in this form, and its demo ID is actually defined. 709 00:34:49,239 --> 00:34:53,520 So this would actually be broken, in so far as the browser's reading 710 00:34:53,520 --> 00:34:55,320 it top to bottom, left to right. 711 00:34:55,320 --> 00:34:59,170 But it sees this code and it says, hey, browser, go get the element by ID demo. 712 00:34:59,170 --> 00:35:02,310 There is no element with that ID at this moment, 713 00:35:02,310 --> 00:35:04,120 because it doesn't come until later. 714 00:35:04,120 --> 00:35:07,770 So a way of solving this using just JavaScript, 715 00:35:07,770 --> 00:35:10,140 is you could do something like the following. 716 00:35:10,140 --> 00:35:17,840 Window dot on load get function, and then you could do something like this, 717 00:35:17,840 --> 00:35:21,300 albeit fairly verbosely. 718 00:35:21,300 --> 00:35:22,260 So that would work. 719 00:35:22,260 --> 00:35:25,160 Hey, browser, when the whole window is loaded, 720 00:35:25,160 --> 00:35:27,620 then please call this anonymous function. 721 00:35:27,620 --> 00:35:31,580 Or we can use jQuery which frankly tends to be 722 00:35:31,580 --> 00:35:34,690 more common, at least when using other libraries as well, 723 00:35:34,690 --> 00:35:36,810 which says that exact same thing. 724 00:35:36,810 --> 00:35:41,590 And in fact, a little bit more than that via this line of code here. 725 00:35:41,590 --> 00:35:44,920 So just another way of doing something, another form of syntax. 726 00:35:44,920 --> 00:35:47,510 But we won't necessarily assume that or complicate things 727 00:35:47,510 --> 00:35:51,080 by using that library syntax along the way. 728 00:35:51,080 --> 00:35:51,650 All right. 729 00:35:51,650 --> 00:35:55,910 So now that we have the ability to access data inside of my web page, 730 00:35:55,910 --> 00:35:56,870 specifically in forms. 731 00:35:56,870 --> 00:35:59,282 And I have the ability to alert the user, 732 00:35:59,282 --> 00:36:01,490 it would seem we can actually create useful features, 733 00:36:01,490 --> 00:36:04,940 not silly little programs that just say hello, world, or hello, David. 734 00:36:04,940 --> 00:36:08,910 What if I now started updating past examples 735 00:36:08,910 --> 00:36:11,620 to do client-side form validation? 736 00:36:11,620 --> 00:36:13,570 In the past, a couple of weeks back, when 737 00:36:13,570 --> 00:36:16,490 we did like the Frosh IMs website, or really any website 738 00:36:16,490 --> 00:36:19,770 that submits data-- maybe CS50 Finance, if the user doesn't cooperate 739 00:36:19,770 --> 00:36:22,930 and doesn't give me a valid symbol or doesn't type his or her name 740 00:36:22,930 --> 00:36:26,340 or password or the passwords don't match in the case of registration, 741 00:36:26,340 --> 00:36:28,460 the data gets submitted to the server nonetheless 742 00:36:28,460 --> 00:36:31,330 and then your Python code thus far has been using an if condition 743 00:36:31,330 --> 00:36:35,900 or l if or whatever to check if the user provided the data that you expect. 744 00:36:35,900 --> 00:36:38,790 And if not, you apologize to them in some way 745 00:36:38,790 --> 00:36:41,030 by just printing out some message to the screen. 746 00:36:41,030 --> 00:36:42,570 That's a lot of work. 747 00:36:42,570 --> 00:36:45,120 If you can anticipate that something is wrong, 748 00:36:45,120 --> 00:36:48,452 why bother sending all of that data or lack thereof to the server, 749 00:36:48,452 --> 00:36:50,410 letting the Python code figure out what's wrong 750 00:36:50,410 --> 00:36:52,350 and then wait for this response to get back, 751 00:36:52,350 --> 00:36:55,433 even though frankly, it happens pretty fast on today's internet, certainly 752 00:36:55,433 --> 00:36:56,340 on campus. 753 00:36:56,340 --> 00:36:58,540 That's a lot of unnecessary work if you have 754 00:36:58,540 --> 00:37:01,350 a programming language like JavaScript that 755 00:37:01,350 --> 00:37:05,020 allows you to run code in the browser. 756 00:37:05,020 --> 00:37:07,930 Let's open up an example that we did in the past 757 00:37:07,930 --> 00:37:10,070 wherein we just have a form that asks for a user's 758 00:37:10,070 --> 00:37:12,402 name, their password, their password again, 759 00:37:12,402 --> 00:37:14,360 and then has a checkbox by which they can agree 760 00:37:14,360 --> 00:37:15,985 to some terms and then a Submit button. 761 00:37:15,985 --> 00:37:18,610 And you'll recall that in the past we might have used something 762 00:37:18,610 --> 00:37:19,944 like this to have them register. 763 00:37:19,944 --> 00:37:22,443 And then we said, no, not really, because we didn't actually 764 00:37:22,443 --> 00:37:23,720 have a back-end at that point. 765 00:37:23,720 --> 00:37:27,030 But a lot of things can go wrong when we present the user with this many things 766 00:37:27,030 --> 00:37:27,650 to do. 767 00:37:27,650 --> 00:37:31,210 Now we know from Python, we can catch these things, 768 00:37:31,210 --> 00:37:33,890 and we can apologize and display an error message on the screen. 769 00:37:33,890 --> 00:37:36,900 So we have all of that program added capability. 770 00:37:36,900 --> 00:37:40,900 But what if we could create a better UX, user experience. 771 00:37:40,900 --> 00:37:42,912 A lot of websites do fancy things these days 772 00:37:42,912 --> 00:37:44,620 like, they don't actually submit the form 773 00:37:44,620 --> 00:37:47,160 and then show a big erroneous message with a cat. 774 00:37:47,160 --> 00:37:50,900 Instead, they just show the text box into which 775 00:37:50,900 --> 00:37:55,570 you were supposed to type a value into in red, or green if you got it right. 776 00:37:55,570 --> 00:37:57,540 Or a little alert message saying, you need 777 00:37:57,540 --> 00:38:00,210 to give us a longer password, or your name, or your email, 778 00:38:00,210 --> 00:38:01,460 or your passwords don't match. 779 00:38:01,460 --> 00:38:04,770 But you can do all this instantly on the client side, 780 00:38:04,770 --> 00:38:08,180 if we somehow can hook into this HTML. 781 00:38:08,180 --> 00:38:11,370 So all of these inputs can be uniquely identified, 782 00:38:11,370 --> 00:38:14,140 especially if we go at our own IDs. 783 00:38:14,140 --> 00:38:16,990 So let's see if we can't take things up a notch 784 00:38:16,990 --> 00:38:21,449 and actually write some code that validates a form like this. 785 00:38:21,449 --> 00:38:23,240 I'm going to go ahead and do the following. 786 00:38:23,240 --> 00:38:26,600 Inform 1 dot HTML, our next version of this program. 787 00:38:26,600 --> 00:38:29,480 We'll start with where I began, with just a simple form. 788 00:38:29,480 --> 00:38:33,027 But below this form, just for now so we can get things started, 789 00:38:33,027 --> 00:38:34,860 I'm going to go ahead and have a script tag. 790 00:38:34,860 --> 00:38:39,580 I'm going to declare a variable called form and call document dot get element 791 00:38:39,580 --> 00:38:43,290 by ID quote unquote registration. 792 00:38:43,290 --> 00:38:44,100 Why? 793 00:38:44,100 --> 00:38:50,070 Well, I'm going to go ahead up here and add an ID that equals registration. 794 00:38:50,070 --> 00:38:52,670 And again, here I'm using double quotes in HTML, 795 00:38:52,670 --> 00:38:55,252 even though both single quotes or double quotes are allowed. 796 00:38:55,252 --> 00:38:56,960 Down here I'm using single quotes, mostly 797 00:38:56,960 --> 00:38:59,330 just to be conformant with convention. 798 00:38:59,330 --> 00:39:03,390 But you can certainly stylistically do whatever you want with both of these. 799 00:39:03,390 --> 00:39:06,220 Now I'm going to do form, which is just an HTML form, 800 00:39:06,220 --> 00:39:10,310 and say on submit, get function. 801 00:39:10,310 --> 00:39:14,110 So in other words, hey, browser, when this form is submitted, 802 00:39:14,110 --> 00:39:15,577 call this anonymous function. 803 00:39:15,577 --> 00:39:17,660 But again, the fact that the function is anonymous 804 00:39:17,660 --> 00:39:19,200 really is not an interesting detail. 805 00:39:19,200 --> 00:39:20,760 It just means it has no name. 806 00:39:20,760 --> 00:39:24,700 This is the chunk of code that will be called when this form is submitted. 807 00:39:24,700 --> 00:39:25,200 All right. 808 00:39:25,200 --> 00:39:26,340 What do I want to do? 809 00:39:26,340 --> 00:39:27,060 How about this. 810 00:39:27,060 --> 00:39:32,970 If form, its e-mail field has a value that equals 811 00:39:32,970 --> 00:39:35,830 equals quote unquote, that's a problem. 812 00:39:35,830 --> 00:39:39,257 Let me go ahead and just alert the user, missing email. 813 00:39:39,257 --> 00:39:42,340 And because we don't indeed want the form to be submitted, let me go ahead 814 00:39:42,340 --> 00:39:44,150 and return false. 815 00:39:44,150 --> 00:39:48,339 Else if, form dot password equals equals nothing-- 816 00:39:48,339 --> 00:39:50,380 the so-called empty string-- then let me go ahead 817 00:39:50,380 --> 00:39:53,192 and alert the user that we're missing their password. 818 00:39:53,192 --> 00:39:55,900 And then let we return false so that the form does not go through 819 00:39:55,900 --> 00:39:57,570 because it's not ready to go through. 820 00:39:57,570 --> 00:40:02,520 How about else if form dot password dot value. 821 00:40:02,520 --> 00:40:05,540 Oops, and up here I need value as well. 822 00:40:05,540 --> 00:40:08,320 Otherwise you get the element from the DOM, 823 00:40:08,320 --> 00:40:11,320 you don't get the value inside of that rectangle. 824 00:40:11,320 --> 00:40:16,205 Else if form dot password dot value does not equal form 825 00:40:16,205 --> 00:40:19,420 dot confirmation dot value. 826 00:40:19,420 --> 00:40:20,860 And why confirmation? 827 00:40:20,860 --> 00:40:24,769 Well, if I look back at my HTML, the first field was called e-mail. 828 00:40:24,769 --> 00:40:26,310 The second field was called password. 829 00:40:26,310 --> 00:40:28,490 The third was called confirmation, even though it's 830 00:40:28,490 --> 00:40:31,750 also a password field, because that's where I want the user's password again. 831 00:40:31,750 --> 00:40:34,560 But if those passwords don't match, let me tell the user, 832 00:40:34,560 --> 00:40:41,974 passwords don't match semi-colon return false. 833 00:40:41,974 --> 00:40:44,890 Now wait a minute, my color-- my syntax highlighting is all messed up. 834 00:40:44,890 --> 00:40:45,600 Why? 835 00:40:45,600 --> 00:40:47,195 So this is a common gotcha. 836 00:40:47,195 --> 00:40:49,320 If I just want to use English grammar in this case, 837 00:40:49,320 --> 00:40:51,010 don't is the right spelling there. 838 00:40:51,010 --> 00:40:54,069 But because I have quotes just like in C or in Python 839 00:40:54,069 --> 00:40:56,360 when you've used double quotes inside of double quotes, 840 00:40:56,360 --> 00:40:59,080 you're going to confuse the program in this case. 841 00:40:59,080 --> 00:41:00,620 And so I need to escape this. 842 00:41:00,620 --> 00:41:04,640 But as in other languages, escaping a back quote here is as simple as this. 843 00:41:04,640 --> 00:41:06,640 Or if you don't really like that because it just 844 00:41:06,640 --> 00:41:08,890 looks a little ridiculous and a little harder to read, 845 00:41:08,890 --> 00:41:10,840 we could switch to double quotes here. 846 00:41:10,840 --> 00:41:13,130 But again, just because I'm using single quotes everywhere else, 847 00:41:13,130 --> 00:41:15,296 I'm going to stick with single quotes and escape it. 848 00:41:15,296 --> 00:41:17,338 But again, you could make an argument either way. 849 00:41:17,338 --> 00:41:17,837 Ouch. 850 00:41:17,837 --> 00:41:19,260 There's still that checkbox. 851 00:41:19,260 --> 00:41:22,750 And that checkbox, let's see, was called agreement. 852 00:41:22,750 --> 00:41:27,240 So it turns out in JavaScript you can express that as follows. 853 00:41:27,240 --> 00:41:34,310 Else if it is not the case that the form's agreement checkbox is checked. 854 00:41:34,310 --> 00:41:36,430 So it turns out, associated with checkboxes 855 00:41:36,430 --> 00:41:39,970 in JavaScript is a property called checked 856 00:41:39,970 --> 00:41:41,680 that's going to be true or false. 857 00:41:41,680 --> 00:41:44,490 So if that's not checked, I'm just going to tell the user as much. 858 00:41:44,490 --> 00:41:47,820 Checkbox unchecked, and then return false. 859 00:41:47,820 --> 00:41:56,070 Otherwise, if none of these checks fail, and I get all the way through all 860 00:41:56,070 --> 00:41:59,100 of these if's and else if's and nothing seems to be wrong, 861 00:41:59,100 --> 00:42:03,785 you know what, the form is ready for submission, return true. 862 00:42:03,785 --> 00:42:06,160 And so now it actually makes a little more sense perhaps, 863 00:42:06,160 --> 00:42:10,810 to return false or return true, because in all of these erroneous cases 864 00:42:10,810 --> 00:42:12,890 you want to return false. 865 00:42:12,890 --> 00:42:15,770 But if everything's OK, by default, we're just going to return true. 866 00:42:15,770 --> 00:42:17,728 And the browser's default behavior in that case 867 00:42:17,728 --> 00:42:22,670 is going to be to go ahead and submit the form to the server. 868 00:42:22,670 --> 00:42:23,570 So let's try that. 869 00:42:23,570 --> 00:42:25,660 Let's go into form 1 dot HTML. 870 00:42:25,660 --> 00:42:28,770 Notice that if I zoom up here, we have more fields than before. 871 00:42:28,770 --> 00:42:31,690 E-mail, password, password, again I agree in register. 872 00:42:31,690 --> 00:42:32,780 So let's try this. 873 00:42:32,780 --> 00:42:35,140 Let me go ahead and say, no, I'm not going 874 00:42:35,140 --> 00:42:36,640 to give you any of this information. 875 00:42:36,640 --> 00:42:38,420 So let me click Register. 876 00:42:38,420 --> 00:42:39,250 Missing email. 877 00:42:39,250 --> 00:42:40,010 All right, fine. 878 00:42:40,010 --> 00:42:43,530 I'll cooperate and give you at least my e-mail, mail in at Harvard dot edu. 879 00:42:43,530 --> 00:42:46,430 Let me click register now-- missing password. 880 00:42:46,430 --> 00:42:48,260 Now there's the additional checkbox there 881 00:42:48,260 --> 00:42:50,660 because now Chrome, or your browser more generally 882 00:42:50,660 --> 00:42:53,100 thinks that, maybe this website's buggy or it's 883 00:42:53,100 --> 00:42:55,520 being malicious or annoying at best. 884 00:42:55,520 --> 00:42:59,850 Let me not check that box, otherwise none of the rest of the demo will work. 885 00:42:59,850 --> 00:43:00,930 All right. 886 00:43:00,930 --> 00:43:03,960 I'll give you a password. 887 00:43:03,960 --> 00:43:05,430 Register. 888 00:43:05,430 --> 00:43:08,130 Passwords don't match, that's because I didn't type it again. 889 00:43:08,130 --> 00:43:10,760 So let me type the same password again over here. 890 00:43:10,760 --> 00:43:11,705 Nice. 891 00:43:11,705 --> 00:43:13,380 Ah, checkbox unchecked. 892 00:43:13,380 --> 00:43:14,330 All right. 893 00:43:14,330 --> 00:43:16,330 Agree, register. 894 00:43:16,330 --> 00:43:19,700 Ah, and it even wants to save my password, but not really. 895 00:43:19,700 --> 00:43:21,100 So where did this actually go? 896 00:43:21,100 --> 00:43:23,480 Well just to show you what's going on behind the scenes, 897 00:43:23,480 --> 00:43:26,050 notice that the action attribute of the past couple of forms 898 00:43:26,050 --> 00:43:27,380 have been slash register. 899 00:43:27,380 --> 00:43:31,390 Well it turns out with today's examples, I'm actually currently running Flask. 900 00:43:31,390 --> 00:43:34,000 And inside of there I have a couple of routes. 901 00:43:34,000 --> 00:43:36,000 We're going to use one of those in just a bit. 902 00:43:36,000 --> 00:43:37,600 For now I'm just using this one here. 903 00:43:37,600 --> 00:43:39,720 I have a route for slash register, that calls 904 00:43:39,720 --> 00:43:43,840 a function register that simply renders a template called register dot HTML. 905 00:43:43,840 --> 00:43:45,310 So where did that text come from? 906 00:43:45,310 --> 00:43:47,640 Again, this is just stuff from a couple of weeks back. 907 00:43:47,640 --> 00:43:52,860 If I go into registered dot HTML in my template's directory, it's just that. 908 00:43:52,860 --> 00:43:53,890 You are registered. 909 00:43:53,890 --> 00:43:55,030 Well not really. 910 00:43:55,030 --> 00:43:56,790 So we're not focusing on the back-end. 911 00:43:56,790 --> 00:43:57,998 We're not focusing on Python. 912 00:43:57,998 --> 00:43:59,250 We're not focusing on Flask. 913 00:43:59,250 --> 00:44:02,150 But I do have it running right now, so that we can see what 914 00:44:02,150 --> 00:44:05,490 does happen if the form is submitted. 915 00:44:05,490 --> 00:44:07,479 But that could be any server in the world. 916 00:44:07,479 --> 00:44:10,270 It could even be Google if we're building that search engine again. 917 00:44:10,270 --> 00:44:12,670 I just need something running there. 918 00:44:12,670 --> 00:44:16,520 Let me go ahead and show you just an alternative take on this form, version 919 00:44:16,520 --> 00:44:19,279 two, that does things using jQuery. 920 00:44:19,279 --> 00:44:20,820 Again we won't dwell as much on this. 921 00:44:20,820 --> 00:44:23,695 But do get familiar with the syntax, because you'll see it everywhere 922 00:44:23,695 --> 00:44:24,410 online. 923 00:44:24,410 --> 00:44:27,650 This says, hey, browser, when the document is ready, 924 00:44:27,650 --> 00:44:31,170 go ahead and associate this anonymous function 925 00:44:31,170 --> 00:44:35,930 with the submit handler of the form with this unique ID. 926 00:44:35,930 --> 00:44:39,990 And then here a slightly different syntax by which you can select 927 00:44:39,990 --> 00:44:41,039 fields on the web page. 928 00:44:41,039 --> 00:44:42,580 Let me wave my hands at that for now. 929 00:44:42,580 --> 00:44:45,340 Because again, you can go with the DOM-specific functions 930 00:44:45,340 --> 00:44:46,472 we've been using thus far. 931 00:44:46,472 --> 00:44:48,430 Or when the time comes, just read a little more 932 00:44:48,430 --> 00:44:50,120 closely some of this code here. 933 00:44:50,120 --> 00:44:52,850 But this is the equivalent code in jQuery, 934 00:44:52,850 --> 00:44:57,690 which is just a library that just gives you different ways of expressing things 935 00:44:57,690 --> 00:45:00,040 in JavaScript. 936 00:45:00,040 --> 00:45:02,270 But this form is pretty ugly, right? 937 00:45:02,270 --> 00:45:05,170 Like, this is really not something to write home about. 938 00:45:05,170 --> 00:45:07,220 This also does not suggest the best error 939 00:45:07,220 --> 00:45:09,540 handling if every time I do something wrong 940 00:45:09,540 --> 00:45:11,380 I just get this ugly looking alert. 941 00:45:11,380 --> 00:45:13,190 Can I make something prettier? 942 00:45:13,190 --> 00:45:15,250 Well we certainly could with JavaScript alone. 943 00:45:15,250 --> 00:45:17,940 And I could certainly write some HTML, some CSS, 944 00:45:17,940 --> 00:45:20,260 and a whole bunch of JavaScript myself and get 945 00:45:20,260 --> 00:45:22,750 a much better UX, user experience. 946 00:45:22,750 --> 00:45:25,580 I could get a much better aesthetic to the site, 947 00:45:25,580 --> 00:45:27,910 so that maybe we print some red text or green text, 948 00:45:27,910 --> 00:45:29,889 depending on whether the user is cooperating. 949 00:45:29,889 --> 00:45:31,180 But that's a whole lot of work. 950 00:45:31,180 --> 00:45:34,230 And honestly, there are millions of websites out there these days. 951 00:45:34,230 --> 00:45:38,450 Surely someone else has had to validate a form before, 952 00:45:38,450 --> 00:45:40,490 and he or she has done it with JavaScript, 953 00:45:40,490 --> 00:45:43,680 and he or she has been nice enough to make their code freely 954 00:45:43,680 --> 00:45:47,200 available as open source online so that the rest of us making 955 00:45:47,200 --> 00:45:50,160 the other millions of websites can stand on their shoulders 956 00:45:50,160 --> 00:45:51,630 and not reinvent that wheel. 957 00:45:51,630 --> 00:45:54,570 And indeed, just like in Python, there's lots and lots of libraries, 958 00:45:54,570 --> 00:45:58,970 and lots and lots of frameworks, so in JavaScript it's there the same. 959 00:45:58,970 --> 00:46:03,810 So it turns out, if I go into form 3 dot HTML, 960 00:46:03,810 --> 00:46:07,960 I have a slightly prettier version that is using the bootstrap library. 961 00:46:07,960 --> 00:46:09,980 There's no banner or menu or anything like. 962 00:46:09,980 --> 00:46:11,420 I kept it pretty simple here. 963 00:46:11,420 --> 00:46:16,670 But just by adding a little bit of more HTML markup, and a little more CSS, can 964 00:46:16,670 --> 00:46:18,770 I stylize my form to be much prettier. 965 00:46:18,770 --> 00:46:22,874 Indeed in CS50 Finance we had much nicer forms than the previous few examples 966 00:46:22,874 --> 00:46:25,040 because we used Bootstrap, though you could use most 967 00:46:25,040 --> 00:46:27,790 any other library that's out there as well just 968 00:46:27,790 --> 00:46:29,810 to make the forms a little prettier. 969 00:46:29,810 --> 00:46:32,010 But I'm adding one additional library. 970 00:46:32,010 --> 00:46:35,840 This one that supports Bootstrap, so that if the user doesn't cooperate 971 00:46:35,840 --> 00:46:40,940 with this version three, notice they can't even click Register 972 00:46:40,940 --> 00:46:42,760 without the following happening. 973 00:46:42,760 --> 00:46:44,902 Red email, please fill out this field. 974 00:46:44,902 --> 00:46:46,610 Red password, please fill out this field. 975 00:46:46,610 --> 00:46:50,369 And by the way, not long enough, because it's not even any characters. 976 00:46:50,369 --> 00:46:52,160 Password again, please fill out this field. 977 00:46:52,160 --> 00:46:53,870 Checkbox unchecked. 978 00:46:53,870 --> 00:46:57,480 So you can immediately give much prettier output to the user 979 00:46:57,480 --> 00:47:00,372 without using that sort of a lame prompt that's just going 980 00:47:00,372 --> 00:47:01,830 to pester the user again and again. 981 00:47:01,830 --> 00:47:03,704 And even though there's still an opportunity, 982 00:47:03,704 --> 00:47:08,420 I think, to improve the aesthetics, this is much more akin to web 2.0. 983 00:47:08,420 --> 00:47:12,140 So modern websites that are using these and other libraries to just create 984 00:47:12,140 --> 00:47:13,550 better user experiences. 985 00:47:13,550 --> 00:47:14,750 So let's cooperate now. 986 00:47:14,750 --> 00:47:17,320 M-A-L-A-N. And notice, whoops. 987 00:47:17,320 --> 00:47:18,900 That's not even my email address. 988 00:47:18,900 --> 00:47:22,585 The error message now goes away entirely because the field is not blank. 989 00:47:22,585 --> 00:47:26,240 All right password, 1, 2, 3, 4, 5. 990 00:47:26,240 --> 00:47:27,040 OK. 991 00:47:27,040 --> 00:47:29,319 It's now no longer telling me to please fill it out, 992 00:47:29,319 --> 00:47:30,610 but it's still not long enough. 993 00:47:30,610 --> 00:47:31,110 All right. 994 00:47:31,110 --> 00:47:34,046 1, 2, 3, 4, 5, 6, 7, 8. 995 00:47:34,046 --> 00:47:35,811 Eight characters seems to be enough. 996 00:47:35,811 --> 00:47:36,310 All right. 997 00:47:36,310 --> 00:47:40,220 Let me go ahead and type in foo bar baz. 998 00:47:40,220 --> 00:47:41,230 Passwords don't match. 999 00:47:41,230 --> 00:47:41,730 OK. 1000 00:47:41,730 --> 00:47:46,810 1, 2, 3, 4, 5, 6, 7, 8. 1001 00:47:46,810 --> 00:47:47,920 That one now matches. 1002 00:47:47,920 --> 00:47:49,730 And finally, I agree. 1003 00:47:49,730 --> 00:47:51,900 So we get so much functionality for free. 1004 00:47:51,900 --> 00:47:55,120 We could implement all of that ourselves using just the primitives we've 1005 00:47:55,120 --> 00:47:57,755 looked at thus far, just our understanding of where JavaScript 1006 00:47:57,755 --> 00:48:00,880 has to go in the web page, just our understanding of how to write functions 1007 00:48:00,880 --> 00:48:03,960 and if conditions and for loops and while loops or whatever. 1008 00:48:03,960 --> 00:48:05,630 But it's not interesting work. 1009 00:48:05,630 --> 00:48:09,960 If I'm trying to build a finance website or a final project more generally, 1010 00:48:09,960 --> 00:48:11,960 I don't really want to focus on form validation. 1011 00:48:11,960 --> 00:48:16,380 I want to focus on my own intellectual property, my own ideas, my own project 1012 00:48:16,380 --> 00:48:17,400 itself. 1013 00:48:17,400 --> 00:48:22,890 And so in form 3 dot HTML is a few additional things. 1014 00:48:22,890 --> 00:48:25,990 Not only have I included the Bootstrap library at the top, 1015 00:48:25,990 --> 00:48:28,690 as you might have noticed in CS50 Finance, as well as the latest 1016 00:48:28,690 --> 00:48:32,950 version of jQuery, and Bootstrap's own JavaScript, I've also included-- 1017 00:48:32,950 --> 00:48:34,690 and I found this just by Googling around. 1018 00:48:34,690 --> 00:48:38,370 A very nice person made his or her code available at this URL. 1019 00:48:38,370 --> 00:48:39,780 And there's documentation online. 1020 00:48:39,780 --> 00:48:42,040 And he or she based it on Bootstrap so that if you 1021 00:48:42,040 --> 00:48:45,000 want to use Bootstrap and have pretty error messages, that you don't 1022 00:48:45,000 --> 00:48:47,420 want to think about creating yourself. 1023 00:48:47,420 --> 00:48:49,240 You can use their library. 1024 00:48:49,240 --> 00:48:51,800 And indeed, notice how I changed my HTML. 1025 00:48:51,800 --> 00:48:55,260 It's a little more verbose to be fair, but you'll 1026 00:48:55,260 --> 00:48:57,720 remember some of this from maybe your log-in form 1027 00:48:57,720 --> 00:48:59,459 or registration form from CS50 Finance. 1028 00:48:59,459 --> 00:49:02,250 Most of this just comes from Bootstrap and you're using the classes 1029 00:49:02,250 --> 00:49:03,390 that they tell you to. 1030 00:49:03,390 --> 00:49:05,890 But there's a few fields here that control 1031 00:49:05,890 --> 00:49:09,760 how this new library is working for form validation. 1032 00:49:09,760 --> 00:49:13,350 Notice, on my input, not only do I have a Bootstrap class, which 1033 00:49:13,350 --> 00:49:16,610 I just read from the documentation and in the unique ID, 1034 00:49:16,610 --> 00:49:18,450 I've got a required attribute. 1035 00:49:18,450 --> 00:49:22,410 And by saying required, that's a clue, not only to the browser, 1036 00:49:22,410 --> 00:49:25,490 but also to this library specifically that I should not 1037 00:49:25,490 --> 00:49:28,490 be allowed to submit this form until this field is filled out. 1038 00:49:28,490 --> 00:49:31,640 Now notice down here, input class equals form control, 1039 00:49:31,640 --> 00:49:33,190 which is just a Bootstrap thing. 1040 00:49:33,190 --> 00:49:36,440 Data dash min length equals 8. 1041 00:49:36,440 --> 00:49:40,810 This is how that library knows that I, the programmer of this page, 1042 00:49:40,810 --> 00:49:45,170 wanted the user to type in a password that's at least eight characters long. 1043 00:49:45,170 --> 00:49:49,050 It turns out, in HTML5, you can prefix, or rather you 1044 00:49:49,050 --> 00:49:50,710 can invent your own attributes. 1045 00:49:50,710 --> 00:49:54,290 Any attribute that starts with data dash, and then 1046 00:49:54,290 --> 00:49:57,860 some other sequence of characters can be your own custom attribute 1047 00:49:57,860 --> 00:49:59,790 that does not come with HTML itself. 1048 00:49:59,790 --> 00:50:01,810 So a lot of libraries, this one among them, 1049 00:50:01,810 --> 00:50:05,020 use those data attributes in order to configure themselves. 1050 00:50:05,020 --> 00:50:08,520 In this case, it's configuring itself to use a minimum length of eight. 1051 00:50:08,520 --> 00:50:10,210 That's also required. 1052 00:50:10,210 --> 00:50:11,940 Down here it's a little more advanced. 1053 00:50:11,940 --> 00:50:14,940 But I just figured this out by reading the documentation. 1054 00:50:14,940 --> 00:50:19,510 Down here, notice, I've got that confirmation text box that's 1055 00:50:19,510 --> 00:50:23,810 also an input with a Bootstrap class data dash match 1056 00:50:23,810 --> 00:50:25,800 equals hashtag password. 1057 00:50:25,800 --> 00:50:29,040 So this is-- and you'd only know this from the documentation of the library-- 1058 00:50:29,040 --> 00:50:35,370 this is how the author decided to let us configure this text field in such a way 1059 00:50:35,370 --> 00:50:38,200 that it must match this password field. 1060 00:50:38,200 --> 00:50:41,120 And you know what, data match error-- I would only know this too 1061 00:50:41,120 --> 00:50:42,530 from its documentation. 1062 00:50:42,530 --> 00:50:46,330 But the way the author designed his or her library is if there is an error 1063 00:50:46,330 --> 00:50:50,370 and the passwords don't match, this is the read text 1064 00:50:50,370 --> 00:50:52,500 that I want the library to display on the screen. 1065 00:50:52,500 --> 00:50:55,830 And though it's cut off, this field too is required. 1066 00:50:55,830 --> 00:50:59,080 And meanwhile the checkbox, if we scroll to the last feature here, 1067 00:50:59,080 --> 00:51:01,305 that too has been prescribed as required. 1068 00:51:01,305 --> 00:51:06,234 And notice, I've also added some divs here and there, help block with errors. 1069 00:51:06,234 --> 00:51:07,900 This is not some fundamental HTML thing. 1070 00:51:07,900 --> 00:51:10,420 This is, again, just the author of the library who's 1071 00:51:10,420 --> 00:51:12,460 decided that wherever you, the programmer, 1072 00:51:12,460 --> 00:51:16,290 put a div with these classes, the library will plop those 1073 00:51:16,290 --> 00:51:17,140 read error messages. 1074 00:51:17,140 --> 00:51:18,470 So they don't have to be right there. 1075 00:51:18,470 --> 00:51:20,290 You could centralize them at the top of the screen. 1076 00:51:20,290 --> 00:51:23,040 You could put them in a banner at the bottom or wherever you want. 1077 00:51:23,040 --> 00:51:24,920 You have some programmatic control. 1078 00:51:24,920 --> 00:51:27,107 And so this library is implemented in JavaScript, 1079 00:51:27,107 --> 00:51:30,440 though we haven't written any additional JavaScript code because this author has 1080 00:51:30,440 --> 00:51:35,080 been pretty clever and is using special HTML attributes 1081 00:51:35,080 --> 00:51:37,070 to configure his or her library. 1082 00:51:37,070 --> 00:51:44,010 And it suffices, at the top of the page, simply to include that library. 1083 00:51:44,010 --> 00:51:48,400 And it has been written, probably with a line of code like document on ready. 1084 00:51:48,400 --> 00:51:52,930 Like when the document is ready, search the HTML for those special tags 1085 00:51:52,930 --> 00:51:57,230 and make sure that this form shall be validated accordingly. 1086 00:51:57,230 --> 00:52:01,232 So this is what's really exciting about JavaScript and Python as well, 1087 00:52:01,232 --> 00:52:03,940 and any of these higher level languages is just how many features 1088 00:52:03,940 --> 00:52:08,290 you get access to for free, without having to implement them yourselves. 1089 00:52:08,290 --> 00:52:10,140 How you use them is going to totally differ. 1090 00:52:10,140 --> 00:52:12,900 And indeed, part of the process of making a final project or a web 1091 00:52:12,900 --> 00:52:15,000 application or a mobile application in general, 1092 00:52:15,000 --> 00:52:17,372 is using a fundamental understanding of programming 1093 00:52:17,372 --> 00:52:20,580 and loops and conditions and functions and so forth, but then googling around 1094 00:52:20,580 --> 00:52:22,860 and looking up documentation that empowers 1095 00:52:22,860 --> 00:52:25,570 you to do other things with that understanding, 1096 00:52:25,570 --> 00:52:27,270 using other people's code. 1097 00:52:27,270 --> 00:52:29,860 So again, the goal is not to absorb all of this en masse, 1098 00:52:29,860 --> 00:52:33,020 but rather to realize the fundamentals, the ingredients by which we 1099 00:52:33,020 --> 00:52:36,480 can configure and do things ourselves. 1100 00:52:36,480 --> 00:52:39,460 Let me go ahead and propose now this example. 1101 00:52:39,460 --> 00:52:43,700 So back in my day, when I first learned HTML, for better or for worse, 1102 00:52:43,700 --> 00:52:46,620 mostly for worse, there was a blink tag. 1103 00:52:46,620 --> 00:52:49,720 So someone back in the '90s thought this was a good idea. 1104 00:52:49,720 --> 00:52:54,540 Let's empower people to have blinking text on their screen for everyone 1105 00:52:54,540 --> 00:52:55,090 to see. 1106 00:52:55,090 --> 00:52:57,410 There was even worse, perhaps, or as bad, 1107 00:52:57,410 --> 00:53:01,612 like a marquee, where you could scroll text across the screen 1108 00:53:01,612 --> 00:53:04,820 from left to right or right to left-- I forget which direction-- and that too 1109 00:53:04,820 --> 00:53:08,360 felt like a good idea at the time that has since been removed as well. 1110 00:53:08,360 --> 00:53:12,770 But it invites an opportunity, I dare say, to reimplement this feature, 1111 00:53:12,770 --> 00:53:16,740 even though browsers do not support the blink tag now. 1112 00:53:16,740 --> 00:53:18,340 But I can figure out how to do this. 1113 00:53:18,340 --> 00:53:18,840 Right. 1114 00:53:18,840 --> 00:53:19,506 What's going on? 1115 00:53:19,506 --> 00:53:22,610 There's some big text on the screen, that's roughly centered. 1116 00:53:22,610 --> 00:53:27,340 So I can probably use some CSS for that to make it big and bold and centered. 1117 00:53:27,340 --> 00:53:28,890 It's blinking on and off. 1118 00:53:28,890 --> 00:53:31,220 Well what does it mean to blink on and off? 1119 00:53:31,220 --> 00:53:33,470 Again, reduce this to first principles. 1120 00:53:33,470 --> 00:53:36,150 What capabilities does a browser have? 1121 00:53:36,150 --> 00:53:40,620 Clearly to display text, also to display colors, we have seen. 1122 00:53:40,620 --> 00:53:44,060 So maybe the act of blinking, hello, world, 1123 00:53:44,060 --> 00:53:47,779 is really just a matter of hiding it, showing it, hiding it, showing it. 1124 00:53:47,779 --> 00:53:49,070 Maybe there's a way to do that. 1125 00:53:49,070 --> 00:53:51,290 And indeed there is in CSS. 1126 00:53:51,290 --> 00:53:55,380 Or maybe it's still there, it's just going black to white to black to white 1127 00:53:55,380 --> 00:53:56,920 to black to white. 1128 00:53:56,920 --> 00:54:01,260 So it feels like, so long as I have the ability to kind of sit-in a loop, maybe 1129 00:54:01,260 --> 00:54:05,000 even an infinite loop if this just keeps going, and every second or so, 1130 00:54:05,000 --> 00:54:08,580 every half second go ahead and change from black to white, to black to white, 1131 00:54:08,580 --> 00:54:11,040 or hide show, hide show. 1132 00:54:11,040 --> 00:54:16,705 I just need to kind of commingle these capabilities of JavaScript and CSS. 1133 00:54:16,705 --> 00:54:18,710 And right now I can't stare at this anymore. 1134 00:54:18,710 --> 00:54:24,530 So let's go ahead and open up blink dot HTML and see how I implemented this. 1135 00:54:24,530 --> 00:54:26,140 So here's a body tag. 1136 00:54:26,140 --> 00:54:29,074 Here's a div tag that has unique ID greeting. 1137 00:54:29,074 --> 00:54:30,490 And then, hello, world as my text. 1138 00:54:30,490 --> 00:54:32,540 So the HTML to this page is super simple. 1139 00:54:32,540 --> 00:54:37,940 If I scroll just a little bit, this is why that text is now centered and big. 1140 00:54:37,940 --> 00:54:40,560 So 96-point, I decided, pretty arbitrarily, 1141 00:54:40,560 --> 00:54:44,850 just to make big centered text on the screen. 1142 00:54:44,850 --> 00:54:47,060 What about the JavaScript code? 1143 00:54:47,060 --> 00:54:53,080 It turns out with JavaScript, just as you 1144 00:54:53,080 --> 00:54:59,120 can gain access to data in the page, so can you gain access to CSS in the page. 1145 00:54:59,120 --> 00:55:01,850 And in fact, even though we won't dive in underneath the hood 1146 00:55:01,850 --> 00:55:05,620 of that library for Bootstrap that made our text fields read, 1147 00:55:05,620 --> 00:55:07,550 how did it make our text fields read? 1148 00:55:07,550 --> 00:55:10,050 Well, if we really looked underneath the hood, that library, 1149 00:55:10,050 --> 00:55:13,091 upon seeing that you didn't type your name or your passwords don't match, 1150 00:55:13,091 --> 00:55:17,800 it changed underneath the hood the CSS of my web page 1151 00:55:17,800 --> 00:55:21,590 to go from default colors to red or to green or to whatever. 1152 00:55:21,590 --> 00:55:22,714 But how did it do that? 1153 00:55:22,714 --> 00:55:25,380 Well, it turns out that browsers have the following capability-- 1154 00:55:25,380 --> 00:55:26,770 one, to declare functions. 1155 00:55:26,770 --> 00:55:28,230 And we know that already. 1156 00:55:28,230 --> 00:55:30,339 Two, to get elements by their ID. 1157 00:55:30,339 --> 00:55:31,380 And we know that already. 1158 00:55:31,380 --> 00:55:33,650 And here I'm just declaring a variable called divs, 1159 00:55:33,650 --> 00:55:35,650 so my code's a little more succinct. 1160 00:55:35,650 --> 00:55:38,420 But it turns out that elements on a web page, 1161 00:55:38,420 --> 00:55:41,880 certainly divs, which are just big rectangular divisions of the page, 1162 00:55:41,880 --> 00:55:44,650 have a style property associated with them. 1163 00:55:44,650 --> 00:55:49,300 And a style property, in this case, lines up with that div element, 1164 00:55:49,300 --> 00:55:51,490 CSS properties, if any. 1165 00:55:51,490 --> 00:55:55,820 And if I want to change the visibility of this div style, 1166 00:55:55,820 --> 00:55:58,900 and visibility happens to be a CSS property that we haven't necessarily 1167 00:55:58,900 --> 00:56:01,530 used, but if you googled around you'd see an online reference 1168 00:56:01,530 --> 00:56:04,110 of available CSS properties. 1169 00:56:04,110 --> 00:56:07,420 If the visibility of this element equals equals hidden, 1170 00:56:07,420 --> 00:56:09,220 I'm going to make it visible. 1171 00:56:09,220 --> 00:56:12,090 Else, I'm going to make it hidden. 1172 00:56:12,090 --> 00:56:16,360 So if visibility is hidden, make it visible. 1173 00:56:16,360 --> 00:56:19,750 Else, if the visibility is visible, make it hidden. 1174 00:56:19,750 --> 00:56:24,160 For whatever reason, the opposite of visible in CSS is not invisible. 1175 00:56:24,160 --> 00:56:26,760 It is hidden, which makes this a bit of a mouthful. 1176 00:56:26,760 --> 00:56:31,600 But this if block here, this if else, really is just saying, if visible, 1177 00:56:31,600 --> 00:56:32,410 make it hidden. 1178 00:56:32,410 --> 00:56:33,860 If hidden, make it visible. 1179 00:56:33,860 --> 00:56:37,090 So just toggles the state, so to speak, from one to the other. 1180 00:56:37,090 --> 00:56:39,680 But why would this function operate more than once? 1181 00:56:39,680 --> 00:56:40,460 There's no loop. 1182 00:56:40,460 --> 00:56:43,640 There's no for loop, no while loop, no do while loop, nothing. 1183 00:56:43,640 --> 00:56:45,520 Look at this last line of code. 1184 00:56:45,520 --> 00:56:48,200 It turns out that in JavaScript you have the ability 1185 00:56:48,200 --> 00:56:51,770 to do things again and again with a clock that's running inside 1186 00:56:51,770 --> 00:56:53,180 of your computer, essentially. 1187 00:56:53,180 --> 00:56:57,380 Window dot set interval is a function you can call in JavaScript that says, 1188 00:56:57,380 --> 00:57:01,139 hey, browser, call this function every 500 milliseconds. 1189 00:57:01,139 --> 00:57:02,930 So couldn't quite glean it before visually. 1190 00:57:02,930 --> 00:57:07,360 Every half a second, call this function, call this function, call this function. 1191 00:57:07,360 --> 00:57:12,580 And notice again, as before, when I'm passing around a function by its name, 1192 00:57:12,580 --> 00:57:14,420 I don't want to do this. 1193 00:57:14,420 --> 00:57:18,510 If I said, blink open paren close paren, that would call the blink function, 1194 00:57:18,510 --> 00:57:20,230 and it's only going to call it once. 1195 00:57:20,230 --> 00:57:23,500 I instead want to pass this function by its name. 1196 00:57:23,500 --> 00:57:25,590 In C we would call this a function pointer. 1197 00:57:25,590 --> 00:57:31,600 In JavaScript we call it by reference, passing in the name of this function 1198 00:57:31,600 --> 00:57:32,710 to set interval. 1199 00:57:32,710 --> 00:57:36,300 So that set interval knows later what function essentially 1200 00:57:36,300 --> 00:57:41,162 to append parentheses to, so as to call it every 500 milliseconds. 1201 00:57:41,162 --> 00:57:42,870 Now how that's implemented, I don't know. 1202 00:57:42,870 --> 00:57:43,411 I don't care. 1203 00:57:43,411 --> 00:57:44,670 It's abstracted away from me. 1204 00:57:44,670 --> 00:57:47,670 But set interval is a function that comes with the browser that probably 1205 00:57:47,670 --> 00:57:49,700 has some kind of infinite loop that knows 1206 00:57:49,700 --> 00:57:54,470 to check every 500 milliseconds what's going on underneath the hood. 1207 00:57:54,470 --> 00:57:58,260 So this is to say, in JavaScript, we have the ability to control CSS. 1208 00:57:58,260 --> 00:58:00,820 And indeed, if we now think back retrospectively, 1209 00:58:00,820 --> 00:58:04,540 that must be how that bootstrap library was doing the form validation 1210 00:58:04,540 --> 00:58:08,380 and making my fields red when I did something wrong. 1211 00:58:08,380 --> 00:58:13,120 So you have another feature in JavaScript called local storage. 1212 00:58:13,120 --> 00:58:16,680 This is relatively newer, but it's a way, on a website, 1213 00:58:16,680 --> 00:58:21,200 of storing information for the long term, in a user's browser. 1214 00:58:21,200 --> 00:58:25,280 So in CS50 Finance, and in Web Programming with Flask more generally, 1215 00:58:25,280 --> 00:58:27,570 we had the ability to store data in sessions. 1216 00:58:27,570 --> 00:58:28,650 And that's fine. 1217 00:58:28,650 --> 00:58:33,130 But sometimes it'd be nice to store data locally inside of the user's browser 1218 00:58:33,130 --> 00:58:36,390 so that you don't have to remember states on the server side. 1219 00:58:36,390 --> 00:58:41,250 So that you don't have to contact the server to get that information. 1220 00:58:41,250 --> 00:58:44,190 And so this is particularly common in web applications 1221 00:58:44,190 --> 00:58:46,380 that you kind of want to be able to run offline. 1222 00:58:46,380 --> 00:58:46,540 Right. 1223 00:58:46,540 --> 00:58:49,120 It's increasingly convenient, especially on mobile devices, 1224 00:58:49,120 --> 00:58:52,410 to be able to run those web pages when you're not connected to the internet, 1225 00:58:52,410 --> 00:58:55,060 when you're underground or on a plane, so long as you 1226 00:58:55,060 --> 00:58:56,530 loaded the page in advance. 1227 00:58:56,530 --> 00:59:00,080 So with local storage, you actually have exactly that feature in HTML 1228 00:59:00,080 --> 00:59:01,742 to store information locally. 1229 00:59:01,742 --> 00:59:03,700 So let's take a look at this page does and then 1230 00:59:03,700 --> 00:59:06,750 we can deconstruct how it's doing that. 1231 00:59:06,750 --> 00:59:11,150 If I open up storage dot HTML, notice that it says in the top corner-- 1232 00:59:11,150 --> 00:59:14,330 and I'll zoom in, just the number 0. 1233 00:59:14,330 --> 00:59:19,690 If I reload, and reload, and reload-- and to be clear, all I'm doing 1234 00:59:19,690 --> 00:59:25,880 is reloading by using my keyboard-- and reload, and reload, and reload, 1235 00:59:25,880 --> 00:59:27,860 the counter is going up. 1236 00:59:27,860 --> 00:59:30,050 But why is that happening? 1237 00:59:30,050 --> 00:59:35,020 Well, let me go back into the IDE and focus on these lines of code here. 1238 00:59:35,020 --> 00:59:39,590 If it's not the case that there is an item called counter 1239 00:59:39,590 --> 00:59:42,730 in this special global variable called local storage, then you know what, 1240 00:59:42,730 --> 00:59:45,990 set an item called counter equal to zero. 1241 00:59:45,990 --> 00:59:50,160 So local storage is really just a JavaScript dictionary-- an object 1242 00:59:50,160 --> 00:59:52,030 that's accessible globally to you. 1243 00:59:52,030 --> 00:59:54,986 Now we've not seen this before, and it's not all that common to need, 1244 00:59:54,986 --> 00:59:58,110 but I did it just so I could display something dynamically in the web page. 1245 00:59:58,110 --> 01:00:00,693 You can call it document dot right, which is similar in spirit 1246 01:00:00,693 --> 01:00:03,550 to prints in Python or print F in C. But, again, we don't really 1247 01:00:03,550 --> 01:00:06,240 print to the screen as much as we change values 1248 01:00:06,240 --> 01:00:07,847 or HTML as we've done in the past. 1249 01:00:07,847 --> 01:00:09,430 So we won't really use this too often. 1250 01:00:09,430 --> 01:00:13,900 But for now, I just want to write local storage dot get items return value 1251 01:00:13,900 --> 01:00:15,050 when I ask it for counter. 1252 01:00:15,050 --> 01:00:17,870 But then, and this is the key detail. 1253 01:00:17,870 --> 01:00:21,670 Every time I print or write that value to the screen, 1254 01:00:21,670 --> 01:00:25,000 I want to go ahead and reset the item, called counter, 1255 01:00:25,000 --> 01:00:28,090 to the result of calling parse ent on local storage 1256 01:00:28,090 --> 01:00:30,020 dot get item dot counter plus 1. 1257 01:00:30,020 --> 01:00:34,180 So long story short, local storage is going to store key value pairs for you, 1258 01:00:34,180 --> 01:00:34,901 but as strings. 1259 01:00:34,901 --> 01:00:37,650 And that's fine, because like quote unquote one, quote unquote two 1260 01:00:37,650 --> 01:00:41,580 is still useful, but parseInt is a function built into JavaScript 1261 01:00:41,580 --> 01:00:44,230 that's going to allow me to parse this string that I get back 1262 01:00:44,230 --> 01:00:47,870 and convert quote unquote something to an actual integer 1263 01:00:47,870 --> 01:00:50,740 so that I can then add 1 to it and set it back. 1264 01:00:50,740 --> 01:00:53,760 So this example is only to say, there is an ability 1265 01:00:53,760 --> 01:00:55,630 to store data locally in the browser. 1266 01:00:55,630 --> 01:00:59,540 And this is a fundamental alternative, especially for offline mobile apps, 1267 01:00:59,540 --> 01:01:02,600 to storing data in sessions on the server side. 1268 01:01:02,600 --> 01:01:05,180 But things get much cooler, quickly. 1269 01:01:05,180 --> 01:01:10,620 In fact, let me go into geolocation dot HTML, which 1270 01:01:10,620 --> 01:01:13,630 creepily wants to know my location. 1271 01:01:13,630 --> 01:01:15,900 Not my location in the sense of the IP address. 1272 01:01:15,900 --> 01:01:18,900 I'm seeing the IP address of my computer here. 1273 01:01:18,900 --> 01:01:22,420 You'll see something with CS50 dot IO or the like most likely. 1274 01:01:22,420 --> 01:01:25,860 But this is standard prompt that Chrome and Edge and other browsers 1275 01:01:25,860 --> 01:01:30,710 will trigger if a browser is running JavaScript code that is creepily 1276 01:01:30,710 --> 01:01:33,160 trying to get your GPS coordinates. 1277 01:01:33,160 --> 01:01:36,400 So it's a good thing that there's privacy defenses in place. 1278 01:01:36,400 --> 01:01:38,340 And you really see this on Android and iOS, 1279 01:01:38,340 --> 01:01:41,721 which don't let apps do anything without your permission typically. 1280 01:01:41,721 --> 01:01:43,970 But I'm going to go ahead and let it know my location. 1281 01:01:43,970 --> 01:01:48,980 I'm going to go ahead and click Allow, and see what happens. 1282 01:01:48,980 --> 01:01:50,520 It's taking a moment. 1283 01:01:50,520 --> 01:01:53,140 The computer is thinking. 1284 01:01:53,140 --> 01:02:00,130 I am apparently at GPS coordinate 42.38 comma negative 77.11. 1285 01:02:00,130 --> 01:02:02,690 So that's my latitude and my longitude. 1286 01:02:02,690 --> 01:02:04,790 Now that's not all that interesting unto itself, 1287 01:02:04,790 --> 01:02:08,170 but let me go to something like maps.google.com. 1288 01:02:08,170 --> 01:02:11,520 Turns out you can search by latitude and longitude. 1289 01:02:11,520 --> 01:02:12,020 OK. 1290 01:02:12,020 --> 01:02:15,740 We didn't have to go very far to triangulate my position there. 1291 01:02:15,740 --> 01:02:19,750 There we are, roughly in the middle of the building, Sanders Theater 1292 01:02:19,750 --> 01:02:20,610 here in Cambridge. 1293 01:02:20,610 --> 01:02:21,905 So that's kind of cool. 1294 01:02:21,905 --> 01:02:24,780 This is all to say that a browser can apparently infer your location. 1295 01:02:24,780 --> 01:02:26,036 Now why is that useful? 1296 01:02:26,036 --> 01:02:28,660 Well if you're building a website that is designed to show maps 1297 01:02:28,660 --> 01:02:31,800 to the user like Google Maps or MapQuest or Yahoo Maps or Bing 1298 01:02:31,800 --> 01:02:34,530 Maps or any number of tools, it's kind of a nice feature 1299 01:02:34,530 --> 01:02:37,930 to just let the user see where he or she is in the world by default, 1300 01:02:37,930 --> 01:02:39,930 rather than just showing them the generic United 1301 01:02:39,930 --> 01:02:41,020 States or the whole globe. 1302 01:02:41,020 --> 01:02:43,520 It'd be kind of nice to at least show them the general area. 1303 01:02:43,520 --> 01:02:46,985 And indeed, that's exactly what happened when I went to Maps.Google.com. 1304 01:02:46,985 --> 01:02:53,280 It knew, within some range, where I was already, even before I typed this in. 1305 01:02:53,280 --> 01:02:56,504 If you're implementing Yelp or some restaurant review site 1306 01:02:56,504 --> 01:02:59,670 or something like that where you want to be able to find something near you, 1307 01:02:59,670 --> 01:03:03,090 it's nice to not have to have me, the human, type in my GPS 1308 01:03:03,090 --> 01:03:05,210 coordinates, which I certainly would never know. 1309 01:03:05,210 --> 01:03:08,950 And it's nice to not make me type in Cambridge, Massachusetts or New Haven, 1310 01:03:08,950 --> 01:03:14,430 Connecticut or whatnot, which is in 06511. 1311 01:03:14,430 --> 01:03:19,630 Rather just let the browser actually figure out where I am, so long as I 1312 01:03:19,630 --> 01:03:22,500 consent to actually doing that. 1313 01:03:22,500 --> 01:03:24,610 I did get that right this time, right? 1314 01:03:24,610 --> 01:03:25,540 OK. 1315 01:03:25,540 --> 01:03:29,600 So why is this a useful thing? 1316 01:03:29,600 --> 01:03:31,270 So this, of course, is useless. 1317 01:03:31,270 --> 01:03:33,310 Like, who cares what GPS coordinates I'm at? 1318 01:03:33,310 --> 01:03:37,760 Not all that useful unless you want to target me right now in a map. 1319 01:03:37,760 --> 01:03:40,870 Rather, we can do something more interesting. 1320 01:03:40,870 --> 01:03:44,090 So we need the ability to actually get a map. 1321 01:03:44,090 --> 01:03:48,490 Thus far I have no ability to pull down pictures of maps. 1322 01:03:48,490 --> 01:03:53,240 But what if I could make a website, that after downloading some HTML and CSS 1323 01:03:53,240 --> 01:03:59,570 and JavaScript, what if, ala Google Maps, I could go get maps of Cambridge, 1324 01:03:59,570 --> 01:04:02,130 go get maps of New Haven or wherever I am in the world 1325 01:04:02,130 --> 01:04:03,430 and display them to the user. 1326 01:04:03,430 --> 01:04:06,720 And better yet, what if I could then use the drag event 1327 01:04:06,720 --> 01:04:09,900 and actually get more of that map-- whatever's off the screens 1328 01:04:09,900 --> 01:04:12,020 above, to the left, to the right, or below me, 1329 01:04:12,020 --> 01:04:13,590 when that user clicks and drags. 1330 01:04:13,590 --> 01:04:16,700 Drag being one of the events we can listen for. 1331 01:04:16,700 --> 01:04:21,790 Well it turns out, as mentioned earlier, that browsers today support 1332 01:04:21,790 --> 01:04:26,099 AJAX, which is formally called asynchronous JavaScript in XML. 1333 01:04:26,099 --> 01:04:28,140 But people don't really use XML for this anymore. 1334 01:04:28,140 --> 01:04:32,070 They use JSON, JavaScript Object Notation. 1335 01:04:32,070 --> 01:04:37,400 And this is ultimately referring to the ability of modern browsers today, 1336 01:04:37,400 --> 01:04:41,080 upon already having downloaded a web page and CSS and JavaScript, 1337 01:04:41,080 --> 01:04:45,590 to make additional HTTP requests from browser to server, 1338 01:04:45,590 --> 01:04:49,510 without having to reload the whole page, and certainly without the user 1339 01:04:49,510 --> 01:04:52,732 having to click Reload and then see a big blank screen for a moment, 1340 01:04:52,732 --> 01:04:53,940 after which they see content. 1341 01:04:53,940 --> 01:04:55,480 It can all happen dynamically. 1342 01:04:55,480 --> 01:04:59,230 So Facebook Messenger, Google Maps, Google Gmail 1343 01:04:59,230 --> 01:05:01,190 and so forth-- any number of websites you 1344 01:05:01,190 --> 01:05:05,860 use today, certainly the most modern of them, all use this capability. 1345 01:05:05,860 --> 01:05:09,240 So how do we go about using it? 1346 01:05:09,240 --> 01:05:15,950 Let me go ahead and open up a file called AJAX 0 dot HTML. 1347 01:05:15,950 --> 01:05:20,840 And here is now where honestly you want to use something like jQuery. 1348 01:05:20,840 --> 01:05:22,430 It tends to still be super popular. 1349 01:05:22,430 --> 01:05:24,630 There's other libraries that can do this for you. 1350 01:05:24,630 --> 01:05:28,180 But what you don't really want to do is start writing native browser code, 1351 01:05:28,180 --> 01:05:30,775 so to speak, that's specific to Chrome or specific to Edge 1352 01:05:30,775 --> 01:05:32,510 or specific to any number of browsers. 1353 01:05:32,510 --> 01:05:34,720 One of the nicest features about libraries today 1354 01:05:34,720 --> 01:05:38,810 is that there are so many stupid cross-browser incompatibilities whereby 1355 01:05:38,810 --> 01:05:42,170 reasonable smart people can disagree, and so different companies have 1356 01:05:42,170 --> 01:05:45,570 implemented browsers ever so differently in terms of JavaScript, 1357 01:05:45,570 --> 01:05:47,400 in terms of HTML, in terms of CSS. 1358 01:05:47,400 --> 01:05:50,120 So literally, you might build a beautiful looking website. 1359 01:05:50,120 --> 01:05:54,190 Spend hours and hours getting it to look perfect on your Google Chrome browser, 1360 01:05:54,190 --> 01:05:58,010 and you open it up in Internet Explorer or Edge or Firefox or Safari, 1361 01:05:58,010 --> 01:05:59,961 and damn it, it doesn't look right. 1362 01:05:59,961 --> 01:06:01,210 Something's off aesthetically. 1363 01:06:01,210 --> 01:06:02,580 It doesn't even work maybe. 1364 01:06:02,580 --> 01:06:03,800 It doesn't even load. 1365 01:06:03,800 --> 01:06:07,420 And so a lot of the process of getting websites just right 1366 01:06:07,420 --> 01:06:09,370 is certainly building them in the first place, 1367 01:06:09,370 --> 01:06:14,070 but then that last stretch is really about making 1368 01:06:14,070 --> 01:06:17,540 sure in testing that things work on multiple browsers. 1369 01:06:17,540 --> 01:06:21,680 So this is all to say, this is when it gets really useful to use something 1370 01:06:21,680 --> 01:06:26,710 like jQuery, because stuff like AJAX does get relatively simpler as follows. 1371 01:06:26,710 --> 01:06:29,780 Here is a web page that's including the jQuery library up top. 1372 01:06:29,780 --> 01:06:34,150 Inside of my own script tag now is a commented function called quote, 1373 01:06:34,150 --> 01:06:38,960 similar in spirit to what we might have wanted in CS50 Finance 1374 01:06:38,960 --> 01:06:41,230 if we were using JavaScript at that point. 1375 01:06:41,230 --> 01:06:43,300 Notice what I'm doing in JavaScript though. 1376 01:06:43,300 --> 01:06:45,420 Give me a variable called URL. 1377 01:06:45,420 --> 01:06:50,730 Set it equal to quote unquote slash quote, which looks like a route, 1378 01:06:50,730 --> 01:06:54,470 question mark symbol equals, closed quote, 1379 01:06:54,470 --> 01:06:57,850 plus which is concatenation, the value of the symbol field. 1380 01:06:57,850 --> 01:06:58,570 Now what is this? 1381 01:06:58,570 --> 01:07:02,660 Let me fast forward to the HTML down here in AJAX 0. 1382 01:07:02,660 --> 01:07:05,410 Pretty simple web form and I'm doing it old school here. 1383 01:07:05,410 --> 01:07:08,650 Form on submit, call the quote function return false. 1384 01:07:08,650 --> 01:07:13,130 And then have an input whose ID is symbol of type-- 1385 01:07:13,130 --> 01:07:15,300 and it's a little cut off-- is text. 1386 01:07:15,300 --> 01:07:17,450 So what does this page look like? 1387 01:07:17,450 --> 01:07:21,220 If I go over to AJAX 0, and open this here, 1388 01:07:21,220 --> 01:07:23,720 it's a very simple web page that simply has 1389 01:07:23,720 --> 01:07:25,930 a text field with a placeholder that says symbol, 1390 01:07:25,930 --> 01:07:30,890 and then an HTML submit button that says get quote. 1391 01:07:30,890 --> 01:07:33,100 But I want this site to do is the following. 1392 01:07:33,100 --> 01:07:37,480 If I type in GOOG for Google's stock ticker symbol, 1393 01:07:37,480 --> 01:07:42,580 I want to know right now that it's worth $772.02. 1394 01:07:42,580 --> 01:07:47,440 If I type in something like Microsoft, that's $59.705. 1395 01:07:47,440 --> 01:07:50,705 So I'm getting another digit of precision from Yahoo Finance 1396 01:07:50,705 --> 01:07:52,540 as it turns out, as we'll see. 1397 01:07:52,540 --> 01:07:57,106 Netflix, get quote, $123.3405. 1398 01:07:57,106 --> 01:07:59,730 So in this case we're really getting some additional precision. 1399 01:07:59,730 --> 01:08:01,840 But all of that is immaterial at the moment. 1400 01:08:01,840 --> 01:08:05,430 What I really just care about is how this is working. 1401 01:08:05,430 --> 01:08:09,547 So again, when that form is submitted, the quote function is called. 1402 01:08:09,547 --> 01:08:10,630 And then it returns false. 1403 01:08:10,630 --> 01:08:13,254 And that's just so that it doesn't get submitted to a back-end, 1404 01:08:13,254 --> 01:08:15,520 because there is no back-end at the moment. 1405 01:08:15,520 --> 01:08:19,870 Rather, I'm using JavaScript to talk to my back-end as follows. 1406 01:08:19,870 --> 01:08:23,290 Var URL gets this URL equals this value. 1407 01:08:23,290 --> 01:08:25,500 And this value is whatever the user just typed in. 1408 01:08:25,500 --> 01:08:28,670 Me, like Google or Microsoft or Netflix. 1409 01:08:28,670 --> 01:08:34,550 So this a way, notice, of constructing your own path for an HTTP get request. 1410 01:08:34,550 --> 01:08:36,779 If you think back to week six, we know that you 1411 01:08:36,779 --> 01:08:41,649 can contact websites ultimately via this route, like slash quote. 1412 01:08:41,649 --> 01:08:47,250 The question mark is what separates the route from the HTTP query, 1413 01:08:47,250 --> 01:08:50,979 or the request parameters, the HTTP parameters that you're passing in, 1414 01:08:50,979 --> 01:08:53,630 one of which I've decided to call symbol. 1415 01:08:53,630 --> 01:08:58,750 And now notice what the jQuery library does for us, pretty straightforwardly. 1416 01:08:58,750 --> 01:09:02,520 jQuery comes with a method called get JSON. 1417 01:09:02,520 --> 01:09:04,319 Now what is this weird syntax? 1418 01:09:04,319 --> 01:09:09,029 Again, this is just JavaScript being cool, or jQuery being cool. 1419 01:09:09,029 --> 01:09:13,740 The dollar sign is literally a synonym for an object 1420 01:09:13,740 --> 01:09:16,990 called jQuery, a global object that happens 1421 01:09:16,990 --> 01:09:19,020 to exist because of this line of code. 1422 01:09:19,020 --> 01:09:23,720 But the author of jQuery, some time ago realized, dollar sign 1423 01:09:23,720 --> 01:09:27,050 is actually a valid character for a variable name, 1424 01:09:27,050 --> 01:09:29,180 which is not the case in C. 1425 01:09:29,180 --> 01:09:34,030 So you know what, I am just going to call my library's global object dollar 1426 01:09:34,030 --> 01:09:34,530 sign. 1427 01:09:34,530 --> 01:09:35,030 Why? 1428 01:09:35,030 --> 01:09:38,330 Well one, it kind of looks cool, but two, it's just much shorter to type. 1429 01:09:38,330 --> 01:09:40,069 You don't have to actually write out the whole word. 1430 01:09:40,069 --> 01:09:40,821 But that's all. 1431 01:09:40,821 --> 01:09:43,029 There's nothing syntactically interesting about this. 1432 01:09:43,029 --> 01:09:46,020 It's just valid variable symbol. 1433 01:09:46,020 --> 01:09:47,529 Get JSON does that. 1434 01:09:47,529 --> 01:09:50,069 It contacts a server at a certain URL and expects 1435 01:09:50,069 --> 01:09:53,630 to get back a JSON object, which we saw an example of a bit ago. 1436 01:09:53,630 --> 01:09:55,540 And what does it do? 1437 01:09:55,540 --> 01:09:59,170 It will call a function, in this case anonymous, 1438 01:09:59,170 --> 01:10:01,660 but that's an immaterial detail at this point. 1439 01:10:01,660 --> 01:10:04,840 And it will pass to that function a reference 1440 01:10:04,840 --> 01:10:07,700 to the data it gets back from the server. 1441 01:10:07,700 --> 01:10:10,710 So again, get JSON somehow figures out underneath the hood, 1442 01:10:10,710 --> 01:10:16,170 how to make an HTTP request to that URL that's passed in as the first argument. 1443 01:10:16,170 --> 01:10:19,884 And when the server finally replies, this anonymous function is called. 1444 01:10:19,884 --> 01:10:20,800 It's passed that data. 1445 01:10:20,800 --> 01:10:23,290 And then we call alert on data dot price. 1446 01:10:23,290 --> 01:10:25,010 So what is inside of that object? 1447 01:10:25,010 --> 01:10:26,520 Well I can actually simulate this. 1448 01:10:26,520 --> 01:10:27,019 Right. 1449 01:10:27,019 --> 01:10:30,440 If you understand HTTP, you can do all of this yourself. 1450 01:10:30,440 --> 01:10:34,580 My IP address happens to be on my local machine, 127.0.0.1. 1451 01:10:34,580 --> 01:10:35,910 And then I'm on port 80. 1452 01:10:35,910 --> 01:10:38,320 Your URL might be different, on CS50 IDE. 1453 01:10:38,320 --> 01:10:42,480 But what I do know is I can construct my own HTTP 1454 01:10:42,480 --> 01:10:49,230 request by just doing slash quote question mark symbol equals NFLX 1455 01:10:49,230 --> 01:10:50,970 and Enter. 1456 01:10:50,970 --> 01:10:52,270 And notice what comes back. 1457 01:10:52,270 --> 01:10:57,316 If I zoom in on that, this is JSON, JavaScript Object Notation. 1458 01:10:57,316 --> 01:10:58,440 Why does it look like this? 1459 01:10:58,440 --> 01:11:00,320 Well, the world just decided, we need a way 1460 01:11:00,320 --> 01:11:02,230 of standardizing how you get back data. 1461 01:11:02,230 --> 01:11:06,260 It's useful to get back data in terms of metadata keys, 1462 01:11:06,260 --> 01:11:08,260 and the actual values you care about. 1463 01:11:08,260 --> 01:11:10,210 So the world decided that JSON data is going 1464 01:11:10,210 --> 01:11:12,377 to start with a curly brace, end with a curly brace. 1465 01:11:12,377 --> 01:11:14,251 It's going to have a whole bunch of key value 1466 01:11:14,251 --> 01:11:15,920 pairs, which are separated by colons. 1467 01:11:15,920 --> 01:11:19,160 Each of the values, each of the keys rather, is quoted. 1468 01:11:19,160 --> 01:11:21,660 Each of the values is quoted if there are strings. 1469 01:11:21,660 --> 01:11:24,204 Otherwise if it's a number you can just write it like that. 1470 01:11:24,204 --> 01:11:26,370 Commas are separating each of those key value pairs. 1471 01:11:26,370 --> 01:11:29,500 And again, you must use double quotes in this context, which 1472 01:11:29,500 --> 01:11:35,860 is a long way of saying, this is what my slash quote route returns. 1473 01:11:35,860 --> 01:11:37,300 This is not a web page. 1474 01:11:37,300 --> 01:11:41,290 This is not my quote route from CS50 Finance, which was must prettier 1475 01:11:41,290 --> 01:11:44,055 and it actually had CSS and HTML and it said, 1476 01:11:44,055 --> 01:11:46,230 a share of Netflix costs such and such. 1477 01:11:46,230 --> 01:11:48,100 This is just raw data. 1478 01:11:48,100 --> 01:11:51,280 And this is where AJAX gets compelling. 1479 01:11:51,280 --> 01:11:57,870 AJAX is the use of raw data like that, you have programmatically 1480 01:11:57,870 --> 01:12:01,480 requested from browser to server, after the original web 1481 01:12:01,480 --> 01:12:05,700 page is already loaded, because you want to get more data for the user, 1482 01:12:05,700 --> 01:12:08,870 perhaps in response, as in this case, to his or her input, 1483 01:12:08,870 --> 01:12:12,280 like when I typed in Netflix or Google or Microsoft. 1484 01:12:12,280 --> 01:12:14,770 This web page isn't all that pretty though, of course. 1485 01:12:14,770 --> 01:12:15,270 Right. 1486 01:12:15,270 --> 01:12:17,810 It's ending up just using that alert. 1487 01:12:17,810 --> 01:12:21,350 And it probably is the case that we can do things a little bit better. 1488 01:12:21,350 --> 01:12:22,740 And indeed we can. 1489 01:12:22,740 --> 01:12:25,520 Right now, again, I've kind of regressed. 1490 01:12:25,520 --> 01:12:27,030 I should not slip into this habit. 1491 01:12:27,030 --> 01:12:28,980 It's fine for perhaps a lecture demonstration, 1492 01:12:28,980 --> 01:12:30,890 but let's clean this up right now. 1493 01:12:30,890 --> 01:12:38,330 If I go into AJAX 1 dot HTML, notice I've gone in and cleaned up my HTML. 1494 01:12:38,330 --> 01:12:43,380 No longer do I have some hackish call to a function semi-colon return 1495 01:12:43,380 --> 01:12:46,210 false inside of the value of an HTML attribute. 1496 01:12:46,210 --> 01:12:47,590 It's just bad design to do that. 1497 01:12:47,590 --> 01:12:49,820 It's fine to sort of get warmed up. 1498 01:12:49,820 --> 01:12:52,640 But let's get rid of that, clean up my HTML, 1499 01:12:52,640 --> 01:12:56,080 and now relegate everything to the top of a file. 1500 01:12:56,080 --> 01:13:00,460 I'm still using jQuery, but I need one additional line, recall. 1501 01:13:00,460 --> 01:13:02,720 Now I need this line here. 1502 01:13:02,720 --> 01:13:05,030 Because a browser reads my code top to bottom, 1503 01:13:05,030 --> 01:13:09,630 I want to make sure that this code is not executed until the page is ready. 1504 01:13:09,630 --> 01:13:12,370 Before, I didn't need to worry about this, because by the time 1505 01:13:12,370 --> 01:13:17,720 the browser got to my HTML, saw the on click or on submit attribute, rather, 1506 01:13:17,720 --> 01:13:20,930 and saw the code to execute, that's fine because everything else had already 1507 01:13:20,930 --> 01:13:21,700 been loaded. 1508 01:13:21,700 --> 01:13:25,280 But in this case, I have my code up front before the HTML. 1509 01:13:25,280 --> 01:13:29,160 So I have to say, hey, browser, don't do this, until you're actually ready. 1510 01:13:29,160 --> 01:13:30,540 What do I want you to do? 1511 01:13:30,540 --> 01:13:34,000 I want you to, as before, register a submit handler, 1512 01:13:34,000 --> 01:13:37,470 calling in this function, calling get JSON as before, 1513 01:13:37,470 --> 01:13:41,530 and then return false here. 1514 01:13:41,530 --> 01:13:44,930 As an aside, let me point out just one thing. 1515 01:13:44,930 --> 01:13:49,220 It turns out that putting your JavaScript code in your file, that 1516 01:13:49,220 --> 01:13:50,972 too is not generally good design. 1517 01:13:50,972 --> 01:13:52,680 Certainly as your pages get more involved 1518 01:13:52,680 --> 01:13:55,830 and your code gets more complex, just like in CSS 1519 01:13:55,830 --> 01:13:57,930 when we factored out our CSS, we should be 1520 01:13:57,930 --> 01:14:00,360 able to factor out our JavaScript code too. 1521 01:14:00,360 --> 01:14:03,740 So actually a better practice longer term and certainly with projects 1522 01:14:03,740 --> 01:14:05,410 would be to do something like this. 1523 01:14:05,410 --> 01:14:08,210 To take all of this code that I've written, 1524 01:14:08,210 --> 01:14:13,200 save it in a file called whatever, scripts dot js is perhaps common. 1525 01:14:13,200 --> 01:14:18,110 And then in my HTML page, don't just have this big open tag and closed tag. 1526 01:14:18,110 --> 01:14:24,170 Instead, go ahead and say something like this, scripts dot js. 1527 01:14:24,170 --> 01:14:27,160 In other words, have a URL or partial URL 1528 01:14:27,160 --> 01:14:30,160 that says to my browser, hey, browser, besides the page you're currently 1529 01:14:30,160 --> 01:14:32,270 reading, go get this file as well. 1530 01:14:32,270 --> 01:14:38,340 Execute any code in there and then proceed to run whatever's inside. 1531 01:14:38,340 --> 01:14:38,950 All right. 1532 01:14:38,950 --> 01:14:43,855 But-- but, but, but, I bet we can make this even cooler. 1533 01:14:43,855 --> 01:14:48,170 It is pretty, pretty lame to keep using these alerts. 1534 01:14:48,170 --> 01:14:53,470 What if instead we had this capability as well. 1535 01:14:53,470 --> 01:14:56,770 In AJAX 2 we have this example here. 1536 01:14:56,770 --> 01:14:58,030 Let me go ahead and zoom in. 1537 01:14:58,030 --> 01:15:02,157 And let me go ahead and type in NFLX for Netflix and click get quote. 1538 01:15:02,157 --> 01:15:04,740 I don't want that damn alert anymore, which is pretty hackish. 1539 01:15:04,740 --> 01:15:07,420 And again, it's going to look ugly and different on different browsers. 1540 01:15:07,420 --> 01:15:08,590 Let me click, get quote. 1541 01:15:08,590 --> 01:15:09,840 Woo, hoo, hoo. 1542 01:15:09,840 --> 01:15:11,300 Very nice. 1543 01:15:11,300 --> 01:15:15,130 So this time it seems to have embedded the response in the web page itself. 1544 01:15:15,130 --> 01:15:20,640 And that's going to change GOOG, get quotes, aka Alphabet, or Microsoft, 1545 01:15:20,640 --> 01:15:22,530 or whatever other company. 1546 01:15:22,530 --> 01:15:24,609 Somehow we're changing the page. 1547 01:15:24,609 --> 01:15:27,650 In other words, now we're not just using this out of band alert function. 1548 01:15:27,650 --> 01:15:29,250 We are changing our DOM. 1549 01:15:29,250 --> 01:15:30,520 And in fact, let me do this. 1550 01:15:30,520 --> 01:15:33,230 Let me reload the page to get back to original state. 1551 01:15:33,230 --> 01:15:38,050 Let me control or right click on Chrome and go into Elements. 1552 01:15:38,050 --> 01:15:42,300 As you may know here, notice that here in my web page, 1553 01:15:42,300 --> 01:15:44,987 apparently is a paragraph that we can't see, 1554 01:15:44,987 --> 01:15:46,570 because it's got no text inside of it. 1555 01:15:46,570 --> 01:15:48,195 It's just an open tag and a closed tag. 1556 01:15:48,195 --> 01:15:51,860 But notice the unique ID called quote. 1557 01:15:51,860 --> 01:15:53,410 And notice what happens. 1558 01:15:53,410 --> 01:15:55,491 I'll have to zoom out to see this. 1559 01:15:55,491 --> 01:15:56,490 But notice what happens. 1560 01:15:56,490 --> 01:15:59,040 If I type in like GOOG and click, get quote. 1561 01:15:59,040 --> 01:15:59,922 Don't watch the top. 1562 01:15:59,922 --> 01:16:00,630 Watch the bottom. 1563 01:16:00,630 --> 01:16:03,310 1564 01:16:03,310 --> 01:16:07,161 A triangle appeared, because now there's something inside of that. 1565 01:16:07,161 --> 01:16:08,910 So that sentence was dynamically inserted. 1566 01:16:08,910 --> 01:16:09,785 Let's try this again. 1567 01:16:09,785 --> 01:16:14,597 Let me try with Microsoft click, get quote, and my page's HTML is changing. 1568 01:16:14,597 --> 01:16:16,680 And it's also flashing it in purple just so Chrome 1569 01:16:16,680 --> 01:16:17,929 can draw your attention to it. 1570 01:16:17,929 --> 01:16:20,080 How about Netflix, get quote. 1571 01:16:20,080 --> 01:16:23,420 So this is where we're really now tying everything together. 1572 01:16:23,420 --> 01:16:26,550 We have the ability with JavaScript to get values from this field. 1573 01:16:26,550 --> 01:16:30,230 We have the ability with JavaScript via AJAX, which is just a use of JavaScript 1574 01:16:30,230 --> 01:16:31,960 to get more data from the server. 1575 01:16:31,960 --> 01:16:35,490 We have the ability with JavaScript to change my DOM, my web 1576 01:16:35,490 --> 01:16:39,610 page, which really just means change the HTML in that page, not permanently. 1577 01:16:39,610 --> 01:16:42,620 None of this is happening on the server, these changes here. 1578 01:16:42,620 --> 01:16:44,160 It's just in my own local browser. 1579 01:16:44,160 --> 01:16:47,110 And indeed if I reload, the changes go away. 1580 01:16:47,110 --> 01:16:51,480 But if you think of this sentence here as being like another row in your Gmail 1581 01:16:51,480 --> 01:16:54,494 inbox, or another message in your Facebook chat window, 1582 01:16:54,494 --> 01:16:55,660 that's all that's happening. 1583 01:16:55,660 --> 01:16:59,050 Now I might be just clobbering, that is deleting and changing 1584 01:16:59,050 --> 01:17:00,192 the previous sentence. 1585 01:17:00,192 --> 01:17:01,900 But there's nothing stopping me from just 1586 01:17:01,900 --> 01:17:07,290 writing every individual message to the screen again and again and again. 1587 01:17:07,290 --> 01:17:10,280 I don't have to overwrite it as I'm doing here. 1588 01:17:10,280 --> 01:17:13,700 So how do we do this? 1589 01:17:13,700 --> 01:17:20,050 So if I go ahead and open up now, AJAX 2 dot HTML, it's almost entirely the same 1590 01:17:20,050 --> 01:17:23,820 as before, except I am now embedding inside 1591 01:17:23,820 --> 01:17:28,650 of my DOM via these method calls, the actual data I want the user to see. 1592 01:17:28,650 --> 01:17:32,310 Indeed, this is saying, hey, browser, go get the HTML element 1593 01:17:32,310 --> 01:17:34,270 whose unique idea is quote. 1594 01:17:34,270 --> 01:17:36,700 Call a method associated with that, called 1595 01:17:36,700 --> 01:17:38,290 HTML, which we haven't seen before. 1596 01:17:38,290 --> 01:17:41,940 But it just literally changes the HTML of that element 1597 01:17:41,940 --> 01:17:44,030 to be whatever I pass in as an argument. 1598 01:17:44,030 --> 01:17:46,360 It's a long argument, but that's just the concatenation 1599 01:17:46,360 --> 01:17:51,520 of a bunch of strings-- A share of, plus data dot name, costs, 1600 01:17:51,520 --> 01:17:53,925 dollar sign data dot price, period. 1601 01:17:53,925 --> 01:17:55,050 Now, what is data dot name? 1602 01:17:55,050 --> 01:17:56,070 What is data dot price? 1603 01:17:56,070 --> 01:18:01,780 Well data is just the argument to the callback function, which 1604 01:18:01,780 --> 01:18:06,450 was, again, the anonymous function that I passed in the second argument 1605 01:18:06,450 --> 01:18:07,430 to get JSON. 1606 01:18:07,430 --> 01:18:09,101 Data dot name gives me the name therein. 1607 01:18:09,101 --> 01:18:10,850 Data dot price gives me the price therein. 1608 01:18:10,850 --> 01:18:12,683 If I really wanted the symbol again, I could 1609 01:18:12,683 --> 01:18:15,520 do data dot symbol, based on what we've seen inside of that object. 1610 01:18:15,520 --> 01:18:21,890 But, just like in C, structures, we just use the dot operator in JavaScript 1611 01:18:21,890 --> 01:18:25,730 to get at the properties of the data inside of an object. 1612 01:18:25,730 --> 01:18:29,110 Now again, the only way I would know how to do this with jQuery 1613 01:18:29,110 --> 01:18:31,160 specifically is by looking up its documentation. 1614 01:18:31,160 --> 01:18:35,150 And I would know that if I want to get JSON I called dollar sign dot get JSON. 1615 01:18:35,150 --> 01:18:37,720 I give it a URL, which I've constructed here. 1616 01:18:37,720 --> 01:18:39,840 And it can be just the relative path if I'm 1617 01:18:39,840 --> 01:18:41,640 assuming that page is on the same server, 1618 01:18:41,640 --> 01:18:43,377 that route's on the same server. 1619 01:18:43,377 --> 01:18:45,460 And then the second argument should be a function. 1620 01:18:45,460 --> 01:18:47,950 It can be anonymous, doesn't have to be anonymous, 1621 01:18:47,950 --> 01:18:51,690 doesn't matter so long as that function, per jQuery's documentation 1622 01:18:51,690 --> 01:18:54,270 takes at least this one argument, which I could called data. 1623 01:18:54,270 --> 01:18:55,520 I could call it anything else. 1624 01:18:55,520 --> 01:19:02,370 But the documentation for jQuery says, hey, user, I will pass to this function 1625 01:19:02,370 --> 01:19:06,510 that I will call back as soon as I have some data for you, 1626 01:19:06,510 --> 01:19:08,120 whatever the server gives me. 1627 01:19:08,120 --> 01:19:10,880 And the server has given me a name, a symbol, and a price 1628 01:19:10,880 --> 01:19:14,952 all inside of this object, this JavaScript Object Notation. 1629 01:19:14,952 --> 01:19:17,160 Finally, this last line is just kind of nice to have. 1630 01:19:17,160 --> 01:19:20,560 I realize, you know what, it'd be a nice feature if after the user searches 1631 01:19:20,560 --> 01:19:22,420 for a stock quote that we not only see it 1632 01:19:22,420 --> 01:19:25,080 but we also reset the form to be a blank value. 1633 01:19:25,080 --> 01:19:30,020 So notice that this symbol refers to a unique element, 1634 01:19:30,020 --> 01:19:35,320 the unique ID of an element that's not a paragraph tag, as this one is. 1635 01:19:35,320 --> 01:19:36,890 This is an input field. 1636 01:19:36,890 --> 01:19:38,694 And input fields don't have HTML inside. 1637 01:19:38,694 --> 01:19:40,360 They literally just have textual values. 1638 01:19:40,360 --> 01:19:44,190 So I use dot val instead, passing it in an empty string. 1639 01:19:44,190 --> 01:19:50,260 But the net effects, notice, this time with that line is the following. 1640 01:19:50,260 --> 01:19:54,080 Once I've added that line, I have, GOOG, get quote. 1641 01:19:54,080 --> 01:19:56,390 And notice the field clears itself this time. 1642 01:19:56,390 --> 01:20:01,440 Once I have Yahoo here, get quote, it clears itself this time. 1643 01:20:01,440 --> 01:20:04,040 So by adding that kind of line to this example, which 1644 01:20:04,040 --> 01:20:05,930 just happens to be using a bit more jQuery, 1645 01:20:05,930 --> 01:20:09,198 I now have the ability to reset the field as well. 1646 01:20:09,198 --> 01:20:13,031 1647 01:20:13,031 --> 01:20:13,530 All right. 1648 01:20:13,530 --> 01:20:16,420 Now where was that JSON coming from though? 1649 01:20:16,420 --> 01:20:20,259 Well recall in application dot pie, we had a couple of routes, one of which 1650 01:20:20,259 --> 01:20:22,300 was register, which was not all that interesting. 1651 01:20:22,300 --> 01:20:24,890 It just rendered a template called registered dot HTML. 1652 01:20:24,890 --> 01:20:28,140 But the other route, which we only glanced at a moment ago, 1653 01:20:28,140 --> 01:20:29,300 was slash quote. 1654 01:20:29,300 --> 01:20:30,670 This one's a bit more involved. 1655 01:20:30,670 --> 01:20:32,250 And I've actually omitted some error checking 1656 01:20:32,250 --> 01:20:33,620 to keep the code a little tight. 1657 01:20:33,620 --> 01:20:36,335 You'll see more error checking and more code inside of helpers 1658 01:20:36,335 --> 01:20:38,900 dot pie from CS50 Finance. 1659 01:20:38,900 --> 01:20:41,640 But long story short, these five rows of code 1660 01:20:41,640 --> 01:20:45,890 simply contact Yahoo Finance, passing in that symbol that's been provided, 1661 01:20:45,890 --> 01:20:52,070 get back the response in CSV, convert the CSV to JSON, and return that JSON. 1662 01:20:52,070 --> 01:20:56,270 And so this is the code that responds to get 1663 01:20:56,270 --> 01:21:02,550 requests of the slash quote route, which is what my JavaScript code is using. 1664 01:21:02,550 --> 01:21:06,610 So again to be clear, we don't have new capabilities 1665 01:21:06,610 --> 01:21:10,880 necessarily with rendering this financial information that we 1666 01:21:10,880 --> 01:21:12,670 didn't already have with Python. 1667 01:21:12,670 --> 01:21:17,600 What has changed is, now I am doing that HTTP request, 1668 01:21:17,600 --> 01:21:20,780 and I am changing that web page client-side. 1669 01:21:20,780 --> 01:21:24,920 I'm contacting the server, yes, but only for additional data, only 1670 01:21:24,920 --> 01:21:29,860 to get that JSON data, only to get the name, the symbol again, and the price. 1671 01:21:29,860 --> 01:21:31,920 I am not asking the server, hey, server, could 1672 01:21:31,920 --> 01:21:36,192 you also give me a brand new web page with HTML tags 1673 01:21:36,192 --> 01:21:38,650 and a body tag and a head tag and a title tag and all that. 1674 01:21:38,650 --> 01:21:40,980 I'm not asking the server for a whole darn new page 1675 01:21:40,980 --> 01:21:45,400 as Jinja might have given me by using a template in, say, CS50 Finance. 1676 01:21:45,400 --> 01:21:49,200 All I'm asking the server for, is please just give me a stock quote, 1677 01:21:49,200 --> 01:21:51,420 and I'll take it from there. 1678 01:21:51,420 --> 01:21:55,090 And so now we have, frankly, a much more responsive interface, 1679 01:21:55,090 --> 01:21:57,210 because I'm requesting less data of the server. 1680 01:21:57,210 --> 01:21:59,960 That's going to be a smaller number of bytes, which means 1681 01:21:59,960 --> 01:22:01,700 it's quicker to send it back to me. 1682 01:22:01,700 --> 01:22:05,760 And I already know how to display it so there's just a lot less work to do. 1683 01:22:05,760 --> 01:22:08,510 So in this case, it would seem that the introduction of JavaScript 1684 01:22:08,510 --> 01:22:12,930 hasn't changed what I can do, but certainly has changed how I can do it. 1685 01:22:12,930 --> 01:22:14,870 But it's easy to be misled. 1686 01:22:14,870 --> 01:22:18,350 In our previous examples, when we did some form validation, 1687 01:22:18,350 --> 01:22:21,370 recall that we could similarly validate that the user typed 1688 01:22:21,370 --> 01:22:24,540 in the right thing or the wrong thing, client-side, without talking 1689 01:22:24,540 --> 01:22:25,490 to the server. 1690 01:22:25,490 --> 01:22:27,770 And the result was prettier for sure. 1691 01:22:27,770 --> 01:22:29,480 We had a little red text and so forth. 1692 01:22:29,480 --> 01:22:31,340 Though technically we could do that server-side as well. 1693 01:22:31,340 --> 01:22:33,180 It's just easier to do it client-side. 1694 01:22:33,180 --> 01:22:34,155 But it was faster. 1695 01:22:34,155 --> 01:22:36,780 I mean, we don't really notice on the wonderful internet speeds 1696 01:22:36,780 --> 01:22:38,238 we might have right here on campus. 1697 01:22:38,238 --> 01:22:41,230 But certainly on mobile devices, if I took out my own phone, 1698 01:22:41,230 --> 01:22:44,400 it's going to feel slower, certainly if you're on a slower connection 1699 01:22:44,400 --> 01:22:46,710 it will certainly be slower. 1700 01:22:46,710 --> 01:22:51,070 But it's not sufficient to just get rid of the server altogether 1701 01:22:51,070 --> 01:22:52,810 and only do client-side. 1702 01:22:52,810 --> 01:22:57,970 In fact, it turns out, an adversary, whether maliciously or just 1703 01:22:57,970 --> 01:23:00,110 accidentally, could do something like this. 1704 01:23:00,110 --> 01:23:02,610 Recall that this form here asked for my email, password, 1705 01:23:02,610 --> 01:23:04,340 password again, and an agreement. 1706 01:23:04,340 --> 01:23:06,321 And if I don't cooperate, it yells at me-- 1707 01:23:06,321 --> 01:23:08,320 missing email, missing password, passwords don't 1708 01:23:08,320 --> 01:23:10,980 match, checkbox unchecked, or whatever. 1709 01:23:10,980 --> 01:23:14,790 But it turns out that hacking JavaScript, turning it off, 1710 01:23:14,790 --> 01:23:18,360 is as simple in Chrome or any other browser, poking around your settings, 1711 01:23:18,360 --> 01:23:21,040 as I'm doing here, scrolling down to an option called, 1712 01:23:21,040 --> 01:23:22,830 in this case, disable JavaScript. 1713 01:23:22,830 --> 01:23:26,400 And now after simply disabling JavaScript, woo. 1714 01:23:26,400 --> 01:23:27,330 I am registered. 1715 01:23:27,330 --> 01:23:28,050 Well, not really. 1716 01:23:28,050 --> 01:23:29,260 But I am not registered. 1717 01:23:29,260 --> 01:23:30,320 I did not give an email address. 1718 01:23:30,320 --> 01:23:31,280 I did not give a password. 1719 01:23:31,280 --> 01:23:32,980 I definitely didn't give it the same password again. 1720 01:23:32,980 --> 01:23:35,450 And I certainly didn't agree to those terms and conditions. 1721 01:23:35,450 --> 01:23:38,630 So JavaScript is really just a client-side nicety. 1722 01:23:38,630 --> 01:23:40,090 It gives us amazing new features. 1723 01:23:40,090 --> 01:23:41,960 It gives us amazing responsiveness. 1724 01:23:41,960 --> 01:23:45,460 It is not an alternative to security checks, 1725 01:23:45,460 --> 01:23:48,300 to validation of data on the server. 1726 01:23:48,300 --> 01:23:52,990 All of those lines of code from CS50 Finance, all of the lines of code 1727 01:23:52,990 --> 01:23:55,880 you might have on the server in Python or whatever language that 1728 01:23:55,880 --> 01:24:00,180 are validating user submissions to make sure they're cooperating, apologizing 1729 01:24:00,180 --> 01:24:04,460 or admonishing them accordingly, if they don't cooperate are still necessary. 1730 01:24:04,460 --> 01:24:07,240 So it's a little annoying that in order to benefit 1731 01:24:07,240 --> 01:24:11,520 from this client-side responsiveness, this better user experience, 1732 01:24:11,520 --> 01:24:14,430 you have to now pretty much invent the wheel in two places. 1733 01:24:14,430 --> 01:24:18,470 In the client-side in JavaScript, on the server in Python or whatever language. 1734 01:24:18,470 --> 01:24:19,610 But that's the way it is. 1735 01:24:19,610 --> 01:24:23,720 If you want to achieve the best of both worlds. 1736 01:24:23,720 --> 01:24:26,580 The security that you get by actually doing something 1737 01:24:26,580 --> 01:24:29,070 as close to your database as possible on the server, 1738 01:24:29,070 --> 01:24:31,740 and the nicety that you get, the user experience that you get, 1739 01:24:31,740 --> 01:24:37,060 and the immediacy of responding to the user by using JavaScript alone. 1740 01:24:37,060 --> 01:24:38,780 So it turns out, there are some libraries 1741 01:24:38,780 --> 01:24:42,590 that allow you to, on the server, specify what fields are valid. 1742 01:24:42,590 --> 01:24:44,980 And you can let the library on the server 1743 01:24:44,980 --> 01:24:48,845 generate the requisite JavaScript code with which to validate your form. 1744 01:24:48,845 --> 01:24:50,720 So long story short, thankfully, other people 1745 01:24:50,720 --> 01:24:53,350 have helped us solve this as well so that you only 1746 01:24:53,350 --> 01:24:56,530 do need to write the code once if using the right library. 1747 01:24:56,530 --> 01:24:58,570 But it's the principle that's important. 1748 01:24:58,570 --> 01:25:01,060 In fact, too often on poorly written websites, 1749 01:25:01,060 --> 01:25:05,040 is it possible to circumvent some silly checkbox or some requirements that's 1750 01:25:05,040 --> 01:25:06,200 not really a requirement. 1751 01:25:06,200 --> 01:25:10,150 It's really just a JavaScript imposed request for data, 1752 01:25:10,150 --> 01:25:12,800 if they're not actually validating as much on the server. 1753 01:25:12,800 --> 01:25:16,600 So realize that that need on the server remains. 1754 01:25:16,600 --> 01:25:18,510 All right. 1755 01:25:18,510 --> 01:25:20,100 Back to that map. 1756 01:25:20,100 --> 01:25:24,870 We have the ability, recall, to get the GPS coordinates of where someone is. 1757 01:25:24,870 --> 01:25:28,480 We have the ability, with AJAX, to get more data from the server. 1758 01:25:28,480 --> 01:25:31,480 And though the data we've gotten this far has been stock data, 1759 01:25:31,480 --> 01:25:34,550 there's nothing stopping us from getting images from the server-- more 1760 01:25:34,550 --> 01:25:38,010 and more images as might composer ultimately a map. 1761 01:25:38,010 --> 01:25:42,370 And indeed, let me go ahead and open up the following. 1762 01:25:42,370 --> 01:25:49,010 In map dot HTML is a relatively short page that has a few characteristics. 1763 01:25:49,010 --> 01:25:49,840 The top of my page. 1764 01:25:49,840 --> 01:25:50,797 I've got some CSS. 1765 01:25:50,797 --> 01:25:53,130 To be cleaner I could factor this out to a separate file 1766 01:25:53,130 --> 01:25:55,505 but I wanted to keep the demo in lecture pretty succinct. 1767 01:25:55,505 --> 01:25:57,136 So everything's in this one page. 1768 01:25:57,136 --> 01:25:59,780 HTML, body and hash map. 1769 01:25:59,780 --> 01:26:03,330 So the commas in the CSS declaration here just mean, 1770 01:26:03,330 --> 01:26:07,680 apply the following properties to the HTML tag and to the body tag 1771 01:26:07,680 --> 01:26:10,010 and to whatever element has this unique ID. 1772 01:26:10,010 --> 01:26:13,360 I want to make sure all three of those are 100%, because by default your web 1773 01:26:13,360 --> 01:26:14,340 page has no height. 1774 01:26:14,340 --> 01:26:16,381 Because if you have no content there's no height. 1775 01:26:16,381 --> 01:26:19,290 But I want to make sure that my web page literally fills the browser. 1776 01:26:19,290 --> 01:26:21,870 And I don't want any white margin around the edges. 1777 01:26:21,870 --> 01:26:25,350 I want everything flush up against the sides and the top and the bottom. 1778 01:26:25,350 --> 01:26:28,720 So that's all this does for me, nothing more than those aesthetics. 1779 01:26:28,720 --> 01:26:32,080 Down here, in the body of the page, notice 1780 01:26:32,080 --> 01:26:36,200 that I have quite simply a div that has nothing inside of it, 1781 01:26:36,200 --> 01:26:39,390 open tag close tag, but that has unique ID called map. 1782 01:26:39,390 --> 01:26:43,710 This is really a place-holder where I want to put a map. 1783 01:26:43,710 --> 01:26:45,290 Down here I have my script tag. 1784 01:26:45,290 --> 01:26:47,640 And I could have put this in the head page. 1785 01:26:47,640 --> 01:26:49,810 Really what I've done is mimic one of the getting 1786 01:26:49,810 --> 01:26:52,357 started examples in some of Google's online documentation, 1787 01:26:52,357 --> 01:26:54,190 so that if you'd like to play along further, 1788 01:26:54,190 --> 01:26:57,231 you'll see that this lines up almost perfectly with some of their getting 1789 01:26:57,231 --> 01:26:58,330 started exercises. 1790 01:26:58,330 --> 01:27:02,350 Indeed, even the function name I have here, INET map mimics theirs. 1791 01:27:02,350 --> 01:27:06,360 And you'll see too, even though in Python, or rather not in Python, in C, 1792 01:27:06,360 --> 01:27:08,790 we generally put these curly braces on the same line. 1793 01:27:08,790 --> 01:27:12,800 You'll see that stylistically, probably more common in JavaScript 1794 01:27:12,800 --> 01:27:15,320 certainly to do it on the same line here, 1795 01:27:15,320 --> 01:27:17,656 even though the closing brace ends up over here. 1796 01:27:17,656 --> 01:27:20,280 Again, all that matters is that you are consistent with respect 1797 01:27:20,280 --> 01:27:22,440 to your own code and nice and neat. 1798 01:27:22,440 --> 01:27:25,460 So what's going on inside of this INET map 1799 01:27:25,460 --> 01:27:28,600 function, which I know to implement because Google told me to 1800 01:27:28,600 --> 01:27:30,300 by reading its documentation. 1801 01:27:30,300 --> 01:27:32,490 Go ahead and declare a variable called map. 1802 01:27:32,490 --> 01:27:35,900 Go ahead and instantiats-- it turns out that JavaScript 1803 01:27:35,900 --> 01:27:40,110 allows you to create or instantiate new objects, much like you can in Python. 1804 01:27:40,110 --> 01:27:42,080 And JavaScript though, in this kind of context, 1805 01:27:42,080 --> 01:27:45,410 you need to say new, which says to the browser, kind of like malloc, 1806 01:27:45,410 --> 01:27:48,000 hey, browser, give me memory four-- although we're not 1807 01:27:48,000 --> 01:27:51,490 managing memory like we do at a low level in C for a map. 1808 01:27:51,490 --> 01:27:57,180 And Google dot maps dot map, you can think of as a class in JavaScript 1809 01:27:57,180 --> 01:27:58,630 that represents a map. 1810 01:27:58,630 --> 01:28:00,250 Like literally a world map. 1811 01:28:00,250 --> 01:28:02,254 It's not technically a class in this case here, 1812 01:28:02,254 --> 01:28:05,420 all the newer versions of JavaScript will introduce that and other features. 1813 01:28:05,420 --> 01:28:10,030 But this is Google's way of allowing me to specify hey, Google, I 1814 01:28:10,030 --> 01:28:14,530 want to map at the location identified by this unique ID. 1815 01:28:14,530 --> 01:28:17,439 So document [INAUDIBLE] gets me that div, 1816 01:28:17,439 --> 01:28:18,980 because its ID was quote unquote map. 1817 01:28:18,980 --> 01:28:23,040 And hey, Google, here's how I want you to configure that div. 1818 01:28:23,040 --> 01:28:26,839 I want you to center a world map at this latitude 1819 01:28:26,839 --> 01:28:28,880 and this longitude-- which based on some googling 1820 01:28:28,880 --> 01:28:31,840 is apparently roughly the middle of the United States, arbitrarily. 1821 01:28:31,840 --> 01:28:32,861 Zoom level is four. 1822 01:28:32,861 --> 01:28:35,610 I want to be able to see a lot of the country, not the whole world 1823 01:28:35,610 --> 01:28:37,610 because then it won't fill the page. 1824 01:28:37,610 --> 01:28:40,840 But I don't want to just see some middle state for instance. 1825 01:28:40,840 --> 01:28:42,190 I want to be zoomed up higher. 1826 01:28:42,190 --> 01:28:44,439 And I would know what number to use by trial and error 1827 01:28:44,439 --> 01:28:45,690 or from the documentation. 1828 01:28:45,690 --> 01:28:47,040 Then I want two markers. 1829 01:28:47,040 --> 01:28:51,120 I want one marker, one little red pushpin on Cambridge, 1830 01:28:51,120 --> 01:28:52,940 one pushpin on New Haven. 1831 01:28:52,940 --> 01:28:55,920 And from some googling, I found that the latitude of Cambridge 1832 01:28:55,920 --> 01:29:00,570 is roughly 42.3762 and the longitude is negative 71. 1833 01:29:00,570 --> 01:29:04,050 And New Haven's 41 and negative 72, give or take. 1834 01:29:04,050 --> 01:29:08,330 And the map I want those markers to be positioned on is map. 1835 01:29:08,330 --> 01:29:10,710 So map is the key, per the documentation. 1836 01:29:10,710 --> 01:29:12,630 Map is also the name of my variable. 1837 01:29:12,630 --> 01:29:17,170 A little confusing, but it also keeps things clean because I mean what I say. 1838 01:29:17,170 --> 01:29:19,480 So with just these few lines of code, I have 1839 01:29:19,480 --> 01:29:22,450 implemented a function called INET map, whose purpose in life 1840 01:29:22,450 --> 01:29:27,640 is to instantiate a map-- create a map, and put it in this div. 1841 01:29:27,640 --> 01:29:29,390 Then with these chunks of code, I'm saying 1842 01:29:29,390 --> 01:29:32,310 give me a marker, a little pushpin, at this position. 1843 01:29:32,310 --> 01:29:35,110 Give me another marker at this position. 1844 01:29:35,110 --> 01:29:37,320 That's pretty much it. 1845 01:29:37,320 --> 01:29:40,830 The only other thing I'm doing in this page, notice, is this. 1846 01:29:40,830 --> 01:29:43,500 At the bottom of the file I have a script tag 1847 01:29:43,500 --> 01:29:45,860 whose source value is this long URL. 1848 01:29:45,860 --> 01:29:47,987 It's got a key, which I signed up for earlier. 1849 01:29:47,987 --> 01:29:50,070 And indeed, if you want to play with this example, 1850 01:29:50,070 --> 01:29:54,930 you'll have to go to Google's documentation for the JavaScript API-- 1851 01:29:54,930 --> 01:29:57,377 Application Programming Interface-- for Google Maps 1852 01:29:57,377 --> 01:30:00,460 and sign up for your own key, paste it in there so that it actually works. 1853 01:30:00,460 --> 01:30:05,030 But what's key at the end of this line is this call back. 1854 01:30:05,030 --> 01:30:08,079 This is just Google's way-- it's completely 1855 01:30:08,079 --> 01:30:09,370 a design decision of their own. 1856 01:30:09,370 --> 01:30:12,280 But they have configured their documentation and their back-end code 1857 01:30:12,280 --> 01:30:13,570 base to say this. 1858 01:30:13,570 --> 01:30:17,380 Tell us the name of your function, because as soon as the Google Maps 1859 01:30:17,380 --> 01:30:21,250 server hears from you, we will call this function of yours, 1860 01:30:21,250 --> 01:30:24,160 as soon as the Google Maps API is ready. 1861 01:30:24,160 --> 01:30:25,276 And I keep saying API. 1862 01:30:25,276 --> 01:30:28,570 API is just application programming interface. 1863 01:30:28,570 --> 01:30:33,110 It's a generic way of saying, someone else has written code that you can use, 1864 01:30:33,110 --> 01:30:35,980 and the API describes how you use it. 1865 01:30:35,980 --> 01:30:38,370 Indeed, when I keep saying, I've read the documentation, 1866 01:30:38,370 --> 01:30:40,800 I've read the documentation, I really read 1867 01:30:40,800 --> 01:30:45,990 their API or some human-friendly version there of-- a user's manual. 1868 01:30:45,990 --> 01:30:51,030 And for instance, their API prescribes that this special object 1869 01:30:51,030 --> 01:30:55,830 map it takes in a reference to the elements in which you 1870 01:30:55,830 --> 01:30:56,830 want to put the map. 1871 01:30:56,830 --> 01:31:00,840 Then it takes in an object as implied by the curly brace and the curly brace 1872 01:31:00,840 --> 01:31:03,540 that takes at least these keys, the center of the map, 1873 01:31:03,540 --> 01:31:06,700 and a zoom level-- or at least those are the two keys that I'm using. 1874 01:31:06,700 --> 01:31:10,760 Meanwhile, the API for Google's marker specifies 1875 01:31:10,760 --> 01:31:13,950 that you should also pass in an object, per the curly braces, that gives it 1876 01:31:13,950 --> 01:31:17,670 a map on which to put that marker, that pushpin, and a position 1877 01:31:17,670 --> 01:31:18,850 at which to put it. 1878 01:31:18,850 --> 01:31:20,110 And I'm just doing that twice. 1879 01:31:20,110 --> 01:31:21,940 So application programming interface will 1880 01:31:21,940 --> 01:31:24,030 mean a little something different in real terms 1881 01:31:24,030 --> 01:31:27,030 depending on whether you're using Google or Bing or any number of tools 1882 01:31:27,030 --> 01:31:28,650 completely unrelated to Maps. 1883 01:31:28,650 --> 01:31:31,510 But it just refers to features-- functionality that someone else 1884 01:31:31,510 --> 01:31:35,970 has provided that you can then integrate typically into your own program. 1885 01:31:35,970 --> 01:31:40,450 So what if I now visit Map dot HTML? 1886 01:31:40,450 --> 01:31:42,060 What do I get? 1887 01:31:42,060 --> 01:31:45,320 I get a map of the Earth, or of the United States 1888 01:31:45,320 --> 01:31:48,730 in this case, centered roughly around the middle of your country. 1889 01:31:48,730 --> 01:31:52,010 And then I have a marker here for Cambridge, a marker here for New Haven. 1890 01:31:52,010 --> 01:31:57,900 But, notice, this map has so much functionality built into it for free. 1891 01:31:57,900 --> 01:31:59,860 I can click and drag. 1892 01:31:59,860 --> 01:32:02,557 And notice-- and if you look quickly-- well now 1893 01:32:02,557 --> 01:32:04,390 we are literally over the edge of the Earth. 1894 01:32:04,390 --> 01:32:05,750 So let's go back. 1895 01:32:05,750 --> 01:32:09,880 If you do this quickly, you'll see that those rectangular gray spots appear. 1896 01:32:09,880 --> 01:32:11,910 And that's because, at that moment in time, 1897 01:32:11,910 --> 01:32:14,670 Google has not yet downloaded the images, the pings 1898 01:32:14,670 --> 01:32:18,180 or whatever they are, PNGs for that part of the world. 1899 01:32:18,180 --> 01:32:20,180 But, notice, if we do this. 1900 01:32:20,180 --> 01:32:27,010 If I go into my Chrome tools and open up my Developer Tools 1901 01:32:27,010 --> 01:32:31,570 and watch the Network tab, notice what happens every time I click and drag. 1902 01:32:31,570 --> 01:32:35,960 Each of those rows in this table at the bottom represents another HTTP request. 1903 01:32:35,960 --> 01:32:38,960 And a lot of them, notice, are pings. 1904 01:32:38,960 --> 01:32:41,650 So really useful when developing JavaScript code 1905 01:32:41,650 --> 01:32:45,050 is to watch the network tab because you can see your own data or someone else's 1906 01:32:45,050 --> 01:32:47,330 data coming back and forth for you that's 1907 01:32:47,330 --> 01:32:50,080 then somehow being used by your JavaScript code to update the map. 1908 01:32:50,080 --> 01:32:52,780 We in our previous example were updating a price 1909 01:32:52,780 --> 01:32:54,390 and a name of a company on the screen. 1910 01:32:54,390 --> 01:32:57,690 But in this case, Google is clearly updating images on the screen 1911 01:32:57,690 --> 01:33:00,440 after having initially drawn these markers. 1912 01:33:00,440 --> 01:33:04,880 And if I now go to the Elements tab here in Chrome, 1913 01:33:04,880 --> 01:33:08,570 you'll see that script tag that I had before, 1914 01:33:08,570 --> 01:33:12,040 and this other script tag, which contains my own JavaScript code. 1915 01:33:12,040 --> 01:33:13,210 But notice this. 1916 01:33:13,210 --> 01:33:17,920 Div ID map, which was previously empty-- let me zoom in. 1917 01:33:17,920 --> 01:33:23,250 If I expand this triangle, apparently inside of that div now is another div. 1918 01:33:23,250 --> 01:33:25,040 Inside of there is another div. 1919 01:33:25,040 --> 01:33:27,380 Inside of there is a whole bunch of divs. 1920 01:33:27,380 --> 01:33:31,140 And indeed, this is what Google's Maps API has done. 1921 01:33:31,140 --> 01:33:35,940 They have dynamically generated, using JavaScript, all of this HTML. 1922 01:33:35,940 --> 01:33:37,140 I didn't write any of that. 1923 01:33:37,140 --> 01:33:41,000 All I gave them was an empty div with a unique ID of ID, 1924 01:33:41,000 --> 01:33:45,250 and the Google Maps API, upon being told where to put this map, 1925 01:33:45,250 --> 01:33:48,340 has filled in that blank so to speak with a whole lot 1926 01:33:48,340 --> 01:33:52,190 more content from its server thanks to JavaScript and thanks to this technique 1927 01:33:52,190 --> 01:33:54,920 known as AJAX. 1928 01:33:54,920 --> 01:33:57,370 Meanwhile, we can zoom in and out, because in addition 1929 01:33:57,370 --> 01:34:01,640 to that drag handler that you see there, there is the plus sign over here. 1930 01:34:01,640 --> 01:34:03,250 There's the minus sign over here. 1931 01:34:03,250 --> 01:34:06,480 There's the satellite map, where it's going to re-download all of the tiles 1932 01:34:06,480 --> 01:34:07,320 all together. 1933 01:34:07,320 --> 01:34:09,680 So all of these features-- this is my website. 1934 01:34:09,680 --> 01:34:10,620 Like, I made this. 1935 01:34:10,620 --> 01:34:12,030 Well, I made this. 1936 01:34:12,030 --> 01:34:14,100 All I had made was an empty div and maybe 1937 01:34:14,100 --> 01:34:15,740 a dozen or so lines of JavaScript code. 1938 01:34:15,740 --> 01:34:20,570 But this is again where programming gets really exciting and really fun, 1939 01:34:20,570 --> 01:34:24,190 because you can start building things on top of other people's work in a way 1940 01:34:24,190 --> 01:34:25,850 that they've made available so that you can do this. 1941 01:34:25,850 --> 01:34:27,599 And if you think about apps you might have 1942 01:34:27,599 --> 01:34:29,670 in your pocket, Lyft or Uber or the like, 1943 01:34:29,670 --> 01:34:31,640 those apps have maps built in, right. 1944 01:34:31,640 --> 01:34:35,130 And Uber probably didn't go around the world with cars or other technologies, 1945 01:34:35,130 --> 01:34:37,000 figuring out where all the roads are. 1946 01:34:37,000 --> 01:34:41,010 Rather, they're probably using Google Maps API or something like it, 1947 01:34:41,010 --> 01:34:42,480 in order to show you those maps. 1948 01:34:42,480 --> 01:34:46,320 And they built their business on top of that API. 1949 01:34:46,320 --> 01:34:50,384 And this is again where things get really powerful, really quickly. 1950 01:34:50,384 --> 01:34:51,800 Now there's another feature still. 1951 01:34:51,800 --> 01:34:54,560 And just to show you that we're only scratching the surface, 1952 01:34:54,560 --> 01:34:58,830 let me open up something like this so that we've at least filled in one gap. 1953 01:34:58,830 --> 01:35:01,030 Earlier today we started with the alert function, 1954 01:35:01,030 --> 01:35:02,730 which really should never be used. 1955 01:35:02,730 --> 01:35:05,389 If you ever see a website that has that ugly alert pop up, 1956 01:35:05,389 --> 01:35:08,680 that is cutting corners, just as I have because I wanted to focus on the ideas, 1957 01:35:08,680 --> 01:35:10,300 not on the printing of information. 1958 01:35:10,300 --> 01:35:13,810 But this underwhelming button at first glance, 1959 01:35:13,810 --> 01:35:15,727 has actually been implemented using Bootstrap. 1960 01:35:15,727 --> 01:35:17,893 So that's why it doesn't look like a default button. 1961 01:35:17,893 --> 01:35:19,940 It's got more of a nicer gray border around it, 1962 01:35:19,940 --> 01:35:23,040 even though it's still there in the top left-hand corner. 1963 01:35:23,040 --> 01:35:26,249 But there's an event listener on this button for on click. 1964 01:35:26,249 --> 01:35:28,790 And when that button is clicked, we're going to see an alert, 1965 01:35:28,790 --> 01:35:30,450 but it's an alert that's a lot nicer. 1966 01:35:30,450 --> 01:35:33,410 And maybe it's not perfectly beautiful as you would have it, 1967 01:35:33,410 --> 01:35:37,130 but it's being generated entirely with JavaScript HTML and CSS. 1968 01:35:37,130 --> 01:35:39,877 It's not the browsers built-in default. 1969 01:35:39,877 --> 01:35:41,460 And indeed, notice what just happened. 1970 01:35:41,460 --> 01:35:43,432 The back of my screen went kind of gray. 1971 01:35:43,432 --> 01:35:44,890 There's this nice drop shadow here. 1972 01:35:44,890 --> 01:35:45,960 There's a title. 1973 01:35:45,960 --> 01:35:46,650 There's a body. 1974 01:35:46,650 --> 01:35:47,570 There's a close. 1975 01:35:47,570 --> 01:35:49,670 And for convenience there's this little x up here. 1976 01:35:49,670 --> 01:35:52,640 And that's because Bootstrap, the library to which I've been referring, 1977 01:35:52,640 --> 01:35:56,640 has bunches of other features-- not only these things, called modals, which 1978 01:35:56,640 --> 01:35:57,510 are fancier alerts. 1979 01:35:57,510 --> 01:35:59,360 And indeed, notice what a modal does. 1980 01:35:59,360 --> 01:36:02,840 It deliberately, by design, blocks you from seeing other things 1981 01:36:02,840 --> 01:36:03,770 until you dismiss it. 1982 01:36:03,770 --> 01:36:06,240 Now it's dismissed itself and it's gone. 1983 01:36:06,240 --> 01:36:08,840 But these are the kinds of features you get with JavaScript. 1984 01:36:08,840 --> 01:36:11,832 So form validation, maps, interactivity like that. 1985 01:36:11,832 --> 01:36:13,540 We're really just scratching the surface. 1986 01:36:13,540 --> 01:36:17,460 But at the end of the day, it just boils down to a few features. 1987 01:36:17,460 --> 01:36:20,480 And it's these libraries that take advantage of features like that. 1988 01:36:20,480 --> 01:36:23,220 jQuery, which you can take a look at in a bit more detail here. 1989 01:36:23,220 --> 01:36:25,580 Bootstrap, which again you'll recall from CS50 Finance, 1990 01:36:25,580 --> 01:36:26,960 but you can see more about it here. 1991 01:36:26,960 --> 01:36:28,210 It doesn't just come with CSS. 1992 01:36:28,210 --> 01:36:30,120 It comes now with JavaScript capabilities. 1993 01:36:30,120 --> 01:36:33,550 And then this is the URL of that other library that uses Bootstrap and gives 1994 01:36:33,550 --> 01:36:35,934 us form validation. 1995 01:36:35,934 --> 01:36:38,100 So let's look at one last example so that we can now 1996 01:36:38,100 --> 01:36:41,400 tie together what we did some weeks ago with what 1997 01:36:41,400 --> 01:36:42,670 we're now doing in JavaScript. 1998 01:36:42,670 --> 01:36:45,460 It turns out that in C we of course manipulated 1999 01:36:45,460 --> 01:36:48,620 images for forensics problems and whodunit and so forth. 2000 01:36:48,620 --> 01:36:50,840 But you can do this in JavaScript as well. 2001 01:36:50,840 --> 01:36:53,600 In fact, if you go to this URL here, there's some fun, 2002 01:36:53,600 --> 01:36:57,380 exercises if you will, from our same friend Nick [INAUDIBLE] from Stanford, 2003 01:36:57,380 --> 01:37:01,060 whom you may recall starred in that binky claymation video. 2004 01:37:01,060 --> 01:37:06,440 Well, what Nick has put together online is a bunch of JavaScript examples 2005 01:37:06,440 --> 01:37:09,010 that give us puzzles like this. 2006 01:37:09,010 --> 01:37:10,570 So iron image puzzle. 2007 01:37:10,570 --> 01:37:12,640 So here's something, not just with red noise, 2008 01:37:12,640 --> 01:37:14,580 but with red and green noise still. 2009 01:37:14,580 --> 01:37:18,615 And no matter what angle I look at this one, I really can't tell what it is. 2010 01:37:18,615 --> 01:37:20,740 And it's not actually one of those magic eye things 2011 01:37:20,740 --> 01:37:23,323 where you just kind of stare through it and something appears. 2012 01:37:23,323 --> 01:37:25,170 Rather, there's a lot of noise here. 2013 01:37:25,170 --> 01:37:26,420 And there's that image hidden. 2014 01:37:26,420 --> 01:37:28,470 If we actually read the information here, 2015 01:37:28,470 --> 01:37:31,507 we'll see that it contains an image of something famous. 2016 01:37:31,507 --> 01:37:33,090 However, the image has been distorted. 2017 01:37:33,090 --> 01:37:36,170 The famous object is in the red values. 2018 01:37:36,170 --> 01:37:39,100 However, the red values have been all divided by 10. 2019 01:37:39,100 --> 01:37:41,080 So they are too small by a factor of 10. 2020 01:37:41,080 --> 01:37:43,760 So it's like Nick turned a knob and ratcheted down 2021 01:37:43,760 --> 01:37:45,700 all the red by a factor of 10. 2022 01:37:45,700 --> 01:37:49,600 The blue and green values are all just meaningless random values, noise, 2023 01:37:49,600 --> 01:37:51,490 added to obscure the real image. 2024 01:37:51,490 --> 01:37:55,310 And Nick tells us, you must undo these distortions to reveal the real image. 2025 01:37:55,310 --> 01:37:59,500 First, set all the blue and green values to zero, to get them out of the way. 2026 01:37:59,500 --> 01:38:02,980 Look at the result. And then if you look very carefully you may see the image, 2027 01:38:02,980 --> 01:38:04,510 although it's very dark. 2028 01:38:04,510 --> 01:38:07,770 So at which point we can multiply the red values by 10. 2029 01:38:07,770 --> 01:38:09,195 So let me go ahead and do this. 2030 01:38:09,195 --> 01:38:13,274 This now is using a simple image API that Nick has provided here. 2031 01:38:13,274 --> 01:38:15,940 And I know this only from having read through his documentation, 2032 01:38:15,940 --> 01:38:18,440 poking around the source code and understanding what exists. 2033 01:38:18,440 --> 01:38:21,610 And I gleaned, by poking around and reading his documentation, 2034 01:38:21,610 --> 01:38:24,510 that there's at least six functions or methods 2035 01:38:24,510 --> 01:38:28,230 associated with this simple image API. 2036 01:38:28,230 --> 01:38:30,700 This API doesn't get more data from the server per se. 2037 01:38:30,700 --> 01:38:34,170 It's just an API in the sense that it provides me with a set of functions 2038 01:38:34,170 --> 01:38:35,430 that I can call. 2039 01:38:35,430 --> 01:38:38,280 So these functions include, get red, get green, 2040 01:38:38,280 --> 01:38:41,236 and get blue, and set red, and set green, and set blue. 2041 01:38:41,236 --> 01:38:43,110 And it turns out that Nick's already given me 2042 01:38:43,110 --> 01:38:46,100 some starter code here in JavaScript. 2043 01:38:46,100 --> 01:38:49,760 And I can now add some additional code inside of these nested for loops. 2044 01:38:49,760 --> 01:38:51,980 Because much like your own forensics piece 2045 01:38:51,980 --> 01:38:55,340 set where you probably iterated from left to right and top 2046 01:38:55,340 --> 01:38:58,640 to bottom over your image's scan lines and pixels, 2047 01:38:58,640 --> 01:39:01,470 so can we do the same in JavaScript as follows. 2048 01:39:01,470 --> 01:39:05,550 So Nick suggests, and I'll take that advice, that I should first 2049 01:39:05,550 --> 01:39:07,780 set the green and blue to 0. 2050 01:39:07,780 --> 01:39:09,524 So I'm going to do IM for image. 2051 01:39:09,524 --> 01:39:11,440 And that's the variable he's defined up there. 2052 01:39:11,440 --> 01:39:14,460 And just for good measure you can think of this identical as before. 2053 01:39:14,460 --> 01:39:18,090 We'll make it just like we did with our variables declarations. 2054 01:39:18,090 --> 01:39:24,180 Image dot sets green at location x, y to 0. 2055 01:39:24,180 --> 01:39:27,950 So again, I know the syntax for this API only by having read his documentation. 2056 01:39:27,950 --> 01:39:33,160 Image dot set blue at location x comma y to 0. 2057 01:39:33,160 --> 01:39:35,220 And Nick has given me this handy run save button. 2058 01:39:35,220 --> 01:39:37,320 Let's do that. 2059 01:39:37,320 --> 01:39:38,250 He is right. 2060 01:39:38,250 --> 01:39:41,680 So this is another copy of that blue and green image. 2061 01:39:41,680 --> 01:39:46,390 And I definitely can't really make out the image. 2062 01:39:46,390 --> 01:39:49,089 I mean, it looks like-- there's a little bit of red there. 2063 01:39:49,089 --> 01:39:51,630 I can actually way up close here-- and perhaps on your screen 2064 01:39:51,630 --> 01:39:53,410 you can see the faintest of red. 2065 01:39:53,410 --> 01:39:55,036 Let me enhance that. 2066 01:39:55,036 --> 01:39:55,910 But the red is there. 2067 01:39:55,910 --> 01:39:57,170 The information is there. 2068 01:39:57,170 --> 01:40:01,770 I've set all of the green and blue bytes to 0, but there's still some red. 2069 01:40:01,770 --> 01:40:03,280 I just need to bump that up. 2070 01:40:03,280 --> 01:40:05,870 Well let me go ahead and do something like this. 2071 01:40:05,870 --> 01:40:10,810 Var red equals image to get red at location x,y. 2072 01:40:10,810 --> 01:40:11,310 All right. 2073 01:40:11,310 --> 01:40:18,260 So let me do, image dot set red at location x,y, equal to red times 10, 2074 01:40:18,260 --> 01:40:20,090 as Nick suggests. 2075 01:40:20,090 --> 01:40:21,840 Click run save. 2076 01:40:21,840 --> 01:40:23,310 Ho, ho. 2077 01:40:23,310 --> 01:40:27,920 It's all very red, but now I can clearly see the Eiffel Tower. 2078 01:40:27,920 --> 01:40:30,089 So we're really just scratching the surface now. 2079 01:40:30,089 --> 01:40:32,130 I mean there's this whole field of steganography, 2080 01:40:32,130 --> 01:40:35,300 the art of hiding information within images, for instance. 2081 01:40:35,300 --> 01:40:37,610 And this is just an example-- a simple example at that. 2082 01:40:37,610 --> 01:40:40,460 But notice the things that we did in C are all the more 2083 01:40:40,460 --> 01:40:44,190 possible now in Python, or are just as possible if not more possible 2084 01:40:44,190 --> 01:40:44,990 in JavaScript. 2085 01:40:44,990 --> 01:40:47,410 But it's ultimately the mental models that are important. 2086 01:40:47,410 --> 01:40:51,160 There's no server interactivity here once we've downloaded this page. 2087 01:40:51,160 --> 01:40:54,450 We have been using today, JavaScript entirely on the client side. 2088 01:40:54,450 --> 01:40:57,850 Which is to say that even once you've download an image, 2089 01:40:57,850 --> 01:41:02,292 can you permute that image, in memory, in the browser, to manipulate it here. 2090 01:41:02,292 --> 01:41:03,750 Or we could have sent it to Python. 2091 01:41:03,750 --> 01:41:05,620 You could do the exact same kind of thing in Python. 2092 01:41:05,620 --> 01:41:08,900 Use the appropriate library with extra read, those pixels, and those RGB 2093 01:41:08,900 --> 01:41:11,070 triples if you will, and do it server-side. 2094 01:41:11,070 --> 01:41:13,910 So it really just depends on what problem you want to solve. 2095 01:41:13,910 --> 01:41:16,990 It did JavaScript itself, by a framework called node js can 2096 01:41:16,990 --> 01:41:18,700 be written on the server-side too. 2097 01:41:18,700 --> 01:41:22,390 You don't need to use Python or PHP or Ruby or Java or anything. 2098 01:41:22,390 --> 01:41:23,730 You can use JavaScript. 2099 01:41:23,730 --> 01:41:27,960 And as an aside, JavaScript has nothing to do with Java. 2100 01:41:27,960 --> 01:41:30,180 It was really just a marketing ploy at the time. 2101 01:41:30,180 --> 01:41:32,997 But JavaScript is the programming language 2102 01:41:32,997 --> 01:41:34,580 that is typically used in the browser. 2103 01:41:34,580 --> 01:41:36,050 It can be used on the server. 2104 01:41:36,050 --> 01:41:39,290 And its syntax is exactly what we've seen here today. 2105 01:41:39,290 --> 01:41:41,840 But it's especially useful in the context of web pages 2106 01:41:41,840 --> 01:41:45,791 because it gives us a language with which we can manipulate the DOM 2107 01:41:45,791 --> 01:41:47,290 that we've seen, the tree structure. 2108 01:41:47,290 --> 01:41:49,810 It gives us a language with which you can change and add 2109 01:41:49,810 --> 01:41:53,750 to and remove the HTML, and the CSS, and really anything you see. 2110 01:41:53,750 --> 01:41:57,860 And indeed, it's this trio of HTML, CSS, and JavaScript, 2111 01:41:57,860 --> 01:42:03,180 coupled with some back-end, Python or Ruby or PHP or Java or C+ or anything 2112 01:42:03,180 --> 01:42:06,400 else, that together implement today's web apps. 2113 01:42:06,400 --> 01:42:09,240 And so now with that, have you the vocabulary, 2114 01:42:09,240 --> 01:42:11,430 coupled with SQL and your own database back-end 2115 01:42:11,430 --> 01:42:14,560 to build most anything you want in the world. 2116 01:42:14,560 --> 01:42:16,540 This was week 10. 2117 01:42:16,540 --> 01:42:23,440 2118 01:42:23,440 --> 01:42:26,349 SPEAKER 2: Like I said, I don't know anything more than you do. 2119 01:42:26,349 --> 01:42:28,932 SPEAKER 3: There must be something from your grad school days. 2120 01:42:28,932 --> 01:42:54,757 2121 01:42:54,757 --> 01:42:55,590 SPEAKER 4: Hey, man. 2122 01:42:55,590 --> 01:42:56,548 Not going to the party? 2123 01:42:56,548 --> 01:43:01,130 2124 01:43:01,130 --> 01:43:03,314 We really should get started on that [INAUDIBLE]. 2125 01:43:03,314 --> 01:43:05,290 It's a doozy. 2126 01:43:05,290 --> 01:43:09,022