1 00:00:00,000 --> 00:00:03,465 [MUSIC PLAYING] 2 00:00:03,465 --> 00:00:15,652 3 00:00:15,652 --> 00:00:17,860 SPEAKER 1: Welcome back, everyone, to Web Programming 4 00:00:17,860 --> 00:00:19,150 with Python and JavaScript. 5 00:00:19,150 --> 00:00:20,892 And let's pick up where we last left off. 6 00:00:20,892 --> 00:00:22,850 So over the course of the past couple of weeks, 7 00:00:22,850 --> 00:00:26,680 we've been working on designing web applications, primarily using Flask. 8 00:00:26,680 --> 00:00:30,910 And if we think about web applications in terms of clients and servers-- 9 00:00:30,910 --> 00:00:34,690 where the client is the user of the application on their computer who goes 10 00:00:34,690 --> 00:00:37,990 to your web address and is interacting with your web application, 11 00:00:37,990 --> 00:00:42,410 and your server is where your Flask application code is running-- 12 00:00:42,410 --> 00:00:44,380 then you can think about where code is actually 13 00:00:44,380 --> 00:00:45,820 running in terms of this diagram. 14 00:00:45,820 --> 00:00:49,960 And so so far, when we've been writing Python code in Flask, all of that code 15 00:00:49,960 --> 00:00:52,010 has been running on the server. 16 00:00:52,010 --> 00:00:55,420 So the user on their computer makes a request for a particular web page. 17 00:00:55,420 --> 00:00:58,510 I have either Get, or Post, or some other HTTP method. 18 00:00:58,510 --> 00:01:02,440 That request is made to our web server, which is running in Flask with Python. 19 00:01:02,440 --> 00:01:04,750 That server tries to process that response, 20 00:01:04,750 --> 00:01:07,270 understand what it is that the client is asking for. 21 00:01:07,270 --> 00:01:11,350 And then ultimately, that server sends back some HTML and maybe CSS 22 00:01:11,350 --> 00:01:16,240 content back to the client, which is rendered in that client's web browser. 23 00:01:16,240 --> 00:01:18,310 What we're going to transition to today is 24 00:01:18,310 --> 00:01:21,220 looking at code that doesn't run on the server but rather runs 25 00:01:21,220 --> 00:01:26,350 instead on the client, on the user's own computer inside of their web browser. 26 00:01:26,350 --> 00:01:31,150 Now, what might be some reasons why we would want code that runs on the client 27 00:01:31,150 --> 00:01:33,190 as opposed to just on the server like we have 28 00:01:33,190 --> 00:01:37,148 been over the course of the past couple weeks? 29 00:01:37,148 --> 00:01:43,124 AUDIENCE: [INAUDIBLE] 30 00:01:43,124 --> 00:01:43,790 SPEAKER 1: Sure. 31 00:01:43,790 --> 00:01:44,150 Certainly. 32 00:01:44,150 --> 00:01:46,040 So one possible reason is that if you have 33 00:01:46,040 --> 00:01:47,960 a lot of users that are all trying to access 34 00:01:47,960 --> 00:01:50,000 your application at the same time, than anything 35 00:01:50,000 --> 00:01:52,100 you can do to take some of the load off of the server 36 00:01:52,100 --> 00:01:54,920 so that you don't have too many clients all trying to connect to the server 37 00:01:54,920 --> 00:01:57,800 simultaneously, that can help to reduce the load on the server. 38 00:01:57,800 --> 00:01:58,350 Fantastic. 39 00:01:58,350 --> 00:02:01,433 And that would be one reason why we might want code running on the client. 40 00:02:01,433 --> 00:02:05,570 Why else might we want code, in some cases, to run on the client 41 00:02:05,570 --> 00:02:06,650 instead of on the server? 42 00:02:06,650 --> 00:02:07,771 Other thoughts or ideas? 43 00:02:07,771 --> 00:02:08,270 Yeah? 44 00:02:08,270 --> 00:02:11,808 AUDIENCE: It's faster to [INAUDIBLE] have to go to the server and back. 45 00:02:11,808 --> 00:02:13,272 You can just [INAUDIBLE]. 46 00:02:13,272 --> 00:02:14,230 SPEAKER 1: It's faster. 47 00:02:14,230 --> 00:02:14,730 Sure. 48 00:02:14,730 --> 00:02:18,800 So if we want something to happen and that something or computation doesn't 49 00:02:18,800 --> 00:02:20,990 need to be something that the server is processing, 50 00:02:20,990 --> 00:02:24,496 then we may as well just have the client run that code in the web browser 51 00:02:24,496 --> 00:02:26,870 as opposed to the additional latency, the additional time 52 00:02:26,870 --> 00:02:29,690 that it would take for the client to make a request to the server, 53 00:02:29,690 --> 00:02:31,815 for the server to run the code, and then the server 54 00:02:31,815 --> 00:02:33,259 to respond back to the client. 55 00:02:33,259 --> 00:02:35,300 And so these are some reasons, as we'll soon see, 56 00:02:35,300 --> 00:02:38,425 where it becomes more powerful and more useful to have code that's actually 57 00:02:38,425 --> 00:02:40,370 running inside of the web browser. 58 00:02:40,370 --> 00:02:42,867 And that's what we're looking at over the course of today. 59 00:02:42,867 --> 00:02:45,450 So to do that, we're going to be introducing another language. 60 00:02:45,450 --> 00:02:47,616 We spent the last couple of weeks working in Python, 61 00:02:47,616 --> 00:02:49,670 but today we're going to introduce JavaScript, 62 00:02:49,670 --> 00:02:53,810 which is a language really designed for usage to be run inside of web browsers, 63 00:02:53,810 --> 00:02:55,820 although now it's used elsewhere as well. 64 00:02:55,820 --> 00:02:58,850 But primarily, we're going to be using JavaScript inside of web browsers 65 00:02:58,850 --> 00:03:01,400 to run code on the client, so that we don't 66 00:03:01,400 --> 00:03:04,160 need to talk to some external server necessarily 67 00:03:04,160 --> 00:03:06,461 for all of the computational work that we need to do. 68 00:03:06,461 --> 00:03:08,960 Now, JavaScript has come in a number of different variations 69 00:03:08,960 --> 00:03:10,460 and it's been updated over time. 70 00:03:10,460 --> 00:03:13,640 And different browsers obey slightly different variations 71 00:03:13,640 --> 00:03:17,060 of the language, where some web browsers support some features of JavaScript 72 00:03:17,060 --> 00:03:18,524 and others support other features. 73 00:03:18,524 --> 00:03:21,440 And so in order to manage all of this complexity of different versions 74 00:03:21,440 --> 00:03:23,231 and different features of JavaScript, there 75 00:03:23,231 --> 00:03:25,160 are certain standard versions of JavaScript 76 00:03:25,160 --> 00:03:27,080 that have been released over the years, such 77 00:03:27,080 --> 00:03:29,720 that we can make sure that most modern browsers will 78 00:03:29,720 --> 00:03:31,370 be compliant with particular standards. 79 00:03:31,370 --> 00:03:34,370 And the version of JavaScript that we're going to be using in this class 80 00:03:34,370 --> 00:03:38,270 is one of the more popular, more recent versions of JavaScript known as ES6. 81 00:03:38,270 --> 00:03:41,570 And so this is just one particular standard version of JavaScript 82 00:03:41,570 --> 00:03:44,330 that pre-defines a certain list of features, some of which 83 00:03:44,330 --> 00:03:47,060 are new features that weren't in previous versions of JavaScript. 84 00:03:47,060 --> 00:03:51,094 But most web browsers nowadays support this latest version of JavaScript ES6. 85 00:03:51,094 --> 00:03:53,510 And so that's going to be the version that we're primarily 86 00:03:53,510 --> 00:03:55,800 going to be using in this class. 87 00:03:55,800 --> 00:03:58,430 So let's take a look at some actual JavaScript code 88 00:03:58,430 --> 00:04:00,990 and what it might look like if we were to run it. 89 00:04:00,990 --> 00:04:04,520 And so if we were going to try to put some JavaScript code inside of a web 90 00:04:04,520 --> 00:04:06,710 page, it might look something like this. 91 00:04:06,710 --> 00:04:09,870 This would be a very simple JavaScript section of a web page. 92 00:04:09,870 --> 00:04:13,320 And what you'll notice is that it's enclosed inside of script tags. 93 00:04:13,320 --> 00:04:16,682 We saw HTML tags over the course of several weeks prior. 94 00:04:16,682 --> 00:04:18,890 And what we're going to be looking at with JavaScript 95 00:04:18,890 --> 00:04:22,640 is JavaScript code that is inside of our HTML pages, 96 00:04:22,640 --> 00:04:26,510 located, in particular, inside of these script tags. 97 00:04:26,510 --> 00:04:30,360 And in this case, what we have appears to be a calling a function. 98 00:04:30,360 --> 00:04:31,880 We have a function called alert. 99 00:04:31,880 --> 00:04:35,660 And inside the body of this function, we have the phrase "Hello, world!" 100 00:04:35,660 --> 00:04:38,990 And so let's take a look at this code actually in action 101 00:04:38,990 --> 00:04:41,450 if we were going to try to run this inside of a web page. 102 00:04:41,450 --> 00:04:45,420 103 00:04:45,420 --> 00:04:48,650 So I go ahead and open up hello0.html. 104 00:04:48,650 --> 00:04:50,930 This is just an HTML document, a web page 105 00:04:50,930 --> 00:04:52,580 where we have some web content here. 106 00:04:52,580 --> 00:04:56,270 You'll notice that, just like before, we have a head section to the web page, 107 00:04:56,270 --> 00:04:59,240 we have a body section to the web page, where all that's inside of it 108 00:04:59,240 --> 00:05:01,430 is one big heading that says "Welcome." 109 00:05:01,430 --> 00:05:06,230 And inside of these script tags, we have this call to an alert function. 110 00:05:06,230 --> 00:05:09,710 And that alert function just has, as its argument, the string "hello!" 111 00:05:09,710 --> 00:05:11,180 with an exclamation point. 112 00:05:11,180 --> 00:05:13,160 And as you might guess, this alert function 113 00:05:13,160 --> 00:05:15,050 is a function that is part of JavaScript. 114 00:05:15,050 --> 00:05:18,230 And what it will do is it will display an alert window for us. 115 00:05:18,230 --> 00:05:22,460 So if I were to now open hello0.html, what 116 00:05:22,460 --> 00:05:26,090 I get is an alert in my web browser that says, this page says "hello," 117 00:05:26,090 --> 00:05:27,350 exclamation point. 118 00:05:27,350 --> 00:05:28,610 And I would press OK. 119 00:05:28,610 --> 00:05:30,860 Now I see the rest of that web page. 120 00:05:30,860 --> 00:05:34,157 So that was our very first JavaScript application, or web page. 121 00:05:34,157 --> 00:05:35,990 And the way we were able to make that happen 122 00:05:35,990 --> 00:05:40,760 was just by including JavaScript code inside of our HTML document, 123 00:05:40,760 --> 00:05:44,820 so long as it is enclosed inside of these script tags. 124 00:05:44,820 --> 00:05:47,210 And so that was a very simple example of how 125 00:05:47,210 --> 00:05:52,151 we might want a JavaScript code to run when it's inside of a web page. 126 00:05:52,151 --> 00:05:53,900 What you probably noticed is that I didn't 127 00:05:53,900 --> 00:05:56,930 have to do anything other than just open this web page in order 128 00:05:56,930 --> 00:05:58,490 for this JavaScript code to run. 129 00:05:58,490 --> 00:06:01,580 As soon as I opened the page, it gave me the alert that said "hello," 130 00:06:01,580 --> 00:06:03,040 and that was that. 131 00:06:03,040 --> 00:06:06,860 What we likely want to do, though, as we begin to develop more sophisticated web 132 00:06:06,860 --> 00:06:09,500 pages is make it so that all of the JavaScript code 133 00:06:09,500 --> 00:06:12,410 isn't running right all at the beginning all at once. 134 00:06:12,410 --> 00:06:16,430 But instead, we want certain JavaScript code only to run or only 135 00:06:16,430 --> 00:06:20,790 to execute after certain things happen or when certain events happen, 136 00:06:20,790 --> 00:06:21,750 so to speak. 137 00:06:21,750 --> 00:06:28,220 And so in order to do that, what we'll do is we'll take a look at events.html. 138 00:06:28,220 --> 00:06:32,390 And what you'll notice here is inside of the script tag, just like before, 139 00:06:32,390 --> 00:06:35,070 rather than just immediately say, alert hello, 140 00:06:35,070 --> 00:06:38,860 where "hello" is the argument that's being passed into this alert function, 141 00:06:38,860 --> 00:06:41,280 we're instead defining a function. 142 00:06:41,280 --> 00:06:44,120 And so this function is called hello. 143 00:06:44,120 --> 00:06:45,690 It takes no arguments. 144 00:06:45,690 --> 00:06:51,260 And inside the body of this function, we say, alert('Hello!'). 145 00:06:51,260 --> 00:06:53,720 And you notice that JavaScript will use these curly braces 146 00:06:53,720 --> 00:06:56,810 to denote things that are contained within the function, 147 00:06:56,810 --> 00:07:00,530 unlike Python which used indentation to denote what's inside of the function 148 00:07:00,530 --> 00:07:01,250 and what's not. 149 00:07:01,250 --> 00:07:03,740 These are just syntactic differences, but the general idea 150 00:07:03,740 --> 00:07:05,656 is going to be the same thing, that hello here 151 00:07:05,656 --> 00:07:08,780 is a function, some block of code that we can later call on when 152 00:07:08,780 --> 00:07:11,120 we want the alert message to appear. 153 00:07:11,120 --> 00:07:15,050 But notice inside of the script tag, we never actually have any code that says, 154 00:07:15,050 --> 00:07:16,430 run the hello function. 155 00:07:16,430 --> 00:07:18,560 We just have these three lines that are defining, 156 00:07:18,560 --> 00:07:22,610 this is what the hello function is, but no actual use case in which 157 00:07:22,610 --> 00:07:25,040 we are running that hello function yet. 158 00:07:25,040 --> 00:07:28,190 But if we look down later in the HTML page, 159 00:07:28,190 --> 00:07:30,260 we have this heading that says "Welcome." 160 00:07:30,260 --> 00:07:31,760 And we also have this button. 161 00:07:31,760 --> 00:07:34,580 And the button says, click here, just defined by button tags 162 00:07:34,580 --> 00:07:36,560 with "click here" inside of those tags. 163 00:07:36,560 --> 00:07:40,430 But we've given this button an additional attribute-- onclick. 164 00:07:40,430 --> 00:07:42,580 And inside of its onclick attribute, we've 165 00:07:42,580 --> 00:07:46,250 set it equal to "hello," the JavaScript code that we want to run. 166 00:07:46,250 --> 00:07:50,069 We want to run the hello function when this button is clicked. 167 00:07:50,069 --> 00:07:52,610 And the way to think about this from a JavaScript perspective 168 00:07:52,610 --> 00:07:55,760 is that JavaScript understands some certain events, where 169 00:07:55,760 --> 00:07:58,550 click is an event, where if you click on a button, 170 00:07:58,550 --> 00:08:00,782 that triggers the click event, so to speak. 171 00:08:00,782 --> 00:08:03,740 And when that click event is triggered, when that button is clicked on, 172 00:08:03,740 --> 00:08:06,900 when I click on Click Here, what should JavaScript do? 173 00:08:06,900 --> 00:08:09,470 Well, in this case, I'm telling the web browser 174 00:08:09,470 --> 00:08:14,150 that I want to run the hello function that I've defined up here earlier 175 00:08:14,150 --> 00:08:16,200 inside of these script tags. 176 00:08:16,200 --> 00:08:20,450 And so the result of this is if I open events.html, 177 00:08:20,450 --> 00:08:22,470 no alert message pops up right away. 178 00:08:22,470 --> 00:08:24,110 I just see "Welcome!" as the heading. 179 00:08:24,110 --> 00:08:28,130 And then I also see this Click Here button down below. 180 00:08:28,130 --> 00:08:31,710 And it's only when I click that button that the click event is triggered, 181 00:08:31,710 --> 00:08:35,000 which triggers the calling of the hello function inside of my JavaScript. 182 00:08:35,000 --> 00:08:37,309 And the result of that is that when I click there, 183 00:08:37,309 --> 00:08:40,654 then I get the pop-up window that says, This Page Says Hello. 184 00:08:40,654 --> 00:08:43,820 And if I were to click on it multiple times, I would see it again and again. 185 00:08:43,820 --> 00:08:48,350 This is equivalent to me calling that function on multiple occasions. 186 00:08:48,350 --> 00:08:52,700 So questions about what we've seen so far in terms of JavaScript code, 187 00:08:52,700 --> 00:08:55,190 and enclosing things in script tags, and events? 188 00:08:55,190 --> 00:08:55,985 Yes. 189 00:08:55,985 --> 00:08:58,999 AUDIENCE: Can you go back to the first one? 190 00:08:58,999 --> 00:09:01,790 SPEAKER 1: Yup, so this was the original code that we started with. 191 00:09:01,790 --> 00:09:05,150 AUDIENCE: Can you put the script after the [INAUDIBLE]?? 192 00:09:05,150 --> 00:09:08,030 193 00:09:08,030 --> 00:09:09,210 SPEAKER 1: Good question. 194 00:09:09,210 --> 00:09:12,001 So the question is, what would happen if you took these script tags 195 00:09:12,001 --> 00:09:16,100 and placed it after "Welcome," just placed it down there, 196 00:09:16,100 --> 00:09:18,230 and then tried to open it? 197 00:09:18,230 --> 00:09:22,820 In this case, it still says This Page Says Hello before you see it. 198 00:09:22,820 --> 00:09:26,900 And this, I think, is just Chrome that is processing the alert message first 199 00:09:26,900 --> 00:09:32,450 before it goes on to dealing with the rest of the content of the page. 200 00:09:32,450 --> 00:09:33,800 Other questions? 201 00:09:33,800 --> 00:09:34,944 Yeah. 202 00:09:34,944 --> 00:09:37,776 AUDIENCE: Is that for all JavaScript or just [INAUDIBLE]?? 203 00:09:37,776 --> 00:09:39,960 204 00:09:39,960 --> 00:09:41,960 SPEAKER 1: I'll have to get back to you on that, 205 00:09:41,960 --> 00:09:43,930 but generally speaking, JavaScript will try 206 00:09:43,930 --> 00:09:46,763 to execute top to bottom, though there are certain cases in which it 207 00:09:46,763 --> 00:09:48,220 can behave in asynchronous ways. 208 00:09:48,220 --> 00:09:50,340 And we'll take a look at a couple examples of that 209 00:09:50,340 --> 00:09:51,340 later on in the lecture. 210 00:09:51,340 --> 00:09:55,260 211 00:09:55,260 --> 00:09:55,800 OK. 212 00:09:55,800 --> 00:10:00,300 So let's do a quick recap of the things we've talked about so far. 213 00:10:00,300 --> 00:10:04,290 And so what we saw just now was an example of functions in JavaScript, 214 00:10:04,290 --> 00:10:07,410 where a function can be defined just by the word "function" followed 215 00:10:07,410 --> 00:10:10,740 by the name of the function that we want to define followed by, optionally, 216 00:10:10,740 --> 00:10:13,150 some number of arguments that that function is taking. 217 00:10:13,150 --> 00:10:16,260 And then enclosed in curly braces, we have all of the code 218 00:10:16,260 --> 00:10:18,600 that we want to run when that function is executed. 219 00:10:18,600 --> 00:10:21,900 So in this case, we want to run an alert that says "Hello World," 220 00:10:21,900 --> 00:10:23,590 or just "Hello," or something else. 221 00:10:23,590 --> 00:10:26,100 And in particular, we were calling these functions 222 00:10:26,100 --> 00:10:27,850 when particular events happened. 223 00:10:27,850 --> 00:10:30,930 So we saw that before, this hello function only happened when 224 00:10:30,930 --> 00:10:32,460 we clicked on a button, for example. 225 00:10:32,460 --> 00:10:35,100 When the onclick event was triggered, that 226 00:10:35,100 --> 00:10:37,252 resulted in the hello function being called. 227 00:10:37,252 --> 00:10:38,710 But there are other events as well. 228 00:10:38,710 --> 00:10:41,040 And so here are some other common events that you might see. 229 00:10:41,040 --> 00:10:44,081 This is not a comprehensive list, but some common events that may come up 230 00:10:44,081 --> 00:10:47,160 and that may be useful if you want particular blocks of JavaScript code 231 00:10:47,160 --> 00:10:51,790 to only run under certain circumstances or under certain conditions. 232 00:10:51,790 --> 00:10:53,820 So the onclick event was the one we just saw 233 00:10:53,820 --> 00:10:55,740 that happens if there's a button, for example, 234 00:10:55,740 --> 00:10:57,990 and someone clicks on that button. 235 00:10:57,990 --> 00:10:59,880 onmouseover is good if you want something 236 00:10:59,880 --> 00:11:03,420 to happen if someone hovers over a part of the window as opposed 237 00:11:03,420 --> 00:11:04,950 to having to actually click on it. 238 00:11:04,950 --> 00:11:06,580 So onmouseover works well for that. 239 00:11:06,580 --> 00:11:09,830 There are also keyboard events related to not what's being done with the mouse 240 00:11:09,830 --> 00:11:12,690 or with the cursor, but what's being done with the keyboard itself. 241 00:11:12,690 --> 00:11:17,010 onkeydown is an event that's triggered when someone presses down on the key. 242 00:11:17,010 --> 00:11:21,390 And when they release that key, that triggers the onkeyup event. 243 00:11:21,390 --> 00:11:23,099 onload is one that happens when something 244 00:11:23,099 --> 00:11:25,598 is finished loading, like when the entire window is finished 245 00:11:25,598 --> 00:11:27,780 loading with all of its images, and CSS resources, 246 00:11:27,780 --> 00:11:30,480 and everything else that's included in the window of the page. 247 00:11:30,480 --> 00:11:34,530 And onblur is also a common one that used when an object loses focus. 248 00:11:34,530 --> 00:11:36,182 So for example, an input field. 249 00:11:36,182 --> 00:11:38,640 If you're in the input field, and it's highlighted in blue, 250 00:11:38,640 --> 00:11:42,120 as you might commonly see, and then you click out of it, and it loses focus, 251 00:11:42,120 --> 00:11:45,690 you can use events like onblur in order to handle situations like that. 252 00:11:45,690 --> 00:11:49,380 And so by running different functions in response to different events, 253 00:11:49,380 --> 00:11:52,410 the result is that we can begin to build much more dynamic user 254 00:11:52,410 --> 00:11:55,979 interfaces, where it's not just that the server responds to the client, 255 00:11:55,979 --> 00:11:58,020 and the client sees a web page, and they can just 256 00:11:58,020 --> 00:12:00,645 view the contents of that web page, but they can actually 257 00:12:00,645 --> 00:12:01,770 interact with the web page. 258 00:12:01,770 --> 00:12:04,350 So they can click on buttons that trigger actions to happen 259 00:12:04,350 --> 00:12:07,300 without needing to request additional information from the server, 260 00:12:07,300 --> 00:12:10,530 but just because JavaScript code is going to be running inside 261 00:12:10,530 --> 00:12:11,940 of the user's own web browser. 262 00:12:11,940 --> 00:12:16,800 And so these events can ultimately help in order to make some of that possible. 263 00:12:16,800 --> 00:12:19,890 So now what we'll take a look at is how we 264 00:12:19,890 --> 00:12:23,490 might begin to use some of the information 265 00:12:23,490 --> 00:12:26,040 that we are able to look at inside of the DOM, 266 00:12:26,040 --> 00:12:28,890 inside of the Document Object Model, the contents of the web page, 267 00:12:28,890 --> 00:12:32,820 in order to write JavaScript that is able to access and manipulate 268 00:12:32,820 --> 00:12:36,000 the DOM-- in other words, using JavaScript code that actually 269 00:12:36,000 --> 00:12:38,160 manipulates the contents of the web page. 270 00:12:38,160 --> 00:12:41,550 So far we've just seen JavaScript used to display an alert, for example, 271 00:12:41,550 --> 00:12:44,140 but it actually is far more powerful than that. 272 00:12:44,140 --> 00:12:46,650 And so what I'm going to introduce is the idea 273 00:12:46,650 --> 00:12:48,630 of querying for something in the documents, 274 00:12:48,630 --> 00:12:51,690 searching for something inside of the document of the web page 275 00:12:51,690 --> 00:12:53,740 in order to make something happen. 276 00:12:53,740 --> 00:12:58,800 So let's take a look now at query.html. 277 00:12:58,800 --> 00:13:02,130 And so inside of the body of this web page, right now 278 00:13:02,130 --> 00:13:05,730 it just, again, has a heading that says "Welcome!" and a button that says 279 00:13:05,730 --> 00:13:08,200 Click Here, where, when we click on that button, 280 00:13:08,200 --> 00:13:10,560 it's going to trigger the hello function. 281 00:13:10,560 --> 00:13:14,600 But what's actually happening inside of the hello function? 282 00:13:14,600 --> 00:13:15,600 Let's take a look at it. 283 00:13:15,600 --> 00:13:18,930 So inside of these script tags, inside of the JavaScript contents 284 00:13:18,930 --> 00:13:22,680 of the web page, we've defined a function called hello, same as before. 285 00:13:22,680 --> 00:13:24,630 And that hello function is triggered whenever 286 00:13:24,630 --> 00:13:26,200 this button down here is clicked on. 287 00:13:26,200 --> 00:13:28,075 So when someone clicks the Click Here button, 288 00:13:28,075 --> 00:13:30,000 it's going to run the hello function. 289 00:13:30,000 --> 00:13:32,987 Now, instead of just alerting something inside of this function, 290 00:13:32,987 --> 00:13:34,320 let's see what's happening here. 291 00:13:34,320 --> 00:13:36,450 Document is just a variable in JavaScript 292 00:13:36,450 --> 00:13:40,290 that refers to the web document, the web page that we're currently displaying. 293 00:13:40,290 --> 00:13:43,380 And querySelector is a special function that 294 00:13:43,380 --> 00:13:45,690 will allow us to search through the contents of the web 295 00:13:45,690 --> 00:13:48,720 page for a particular CSS selector. 296 00:13:48,720 --> 00:13:50,700 So if you recall from way back when we were 297 00:13:50,700 --> 00:13:53,530 talking about CSS in the first and second weeks of the course, 298 00:13:53,530 --> 00:13:57,717 we had different ways of using CSS selectors in order to style 299 00:13:57,717 --> 00:13:59,050 particular elements of the text. 300 00:13:59,050 --> 00:14:04,780 You recall that we could say li, for instance, followed by some CSS code 301 00:14:04,780 --> 00:14:06,630 to style all of the list elements. 302 00:14:06,630 --> 00:14:09,900 Or we could use the pound sign in front of the name of an ID 303 00:14:09,900 --> 00:14:12,450 in order to style only that particular ID. 304 00:14:12,450 --> 00:14:15,290 Or the dot sign followed by the name of a class 305 00:14:15,290 --> 00:14:18,120 to style all of the different things that belong to that class. 306 00:14:18,120 --> 00:14:23,400 We can use that same syntax and the same sophistication that we could use in CSS 307 00:14:23,400 --> 00:14:26,550 selectors inside of this querySelector function, 308 00:14:26,550 --> 00:14:30,880 which will extract from the website one particular HTML element. 309 00:14:30,880 --> 00:14:34,190 So in this case, I'm querying for an H1 element. 310 00:14:34,190 --> 00:14:37,440 And if we were to search through this web page just using our own eyes, 311 00:14:37,440 --> 00:14:40,770 we would find that the H1 element is down here. 312 00:14:40,770 --> 00:14:47,530 And then we're accessing the .InnerHTML property of this H1 element. 313 00:14:47,530 --> 00:14:50,970 Any ideas what the inner HTML property of the H1 element 314 00:14:50,970 --> 00:14:52,170 could refer to in this case? 315 00:14:52,170 --> 00:14:54,720 316 00:14:54,720 --> 00:14:56,080 So the H1 tag-- 317 00:14:56,080 --> 00:14:56,830 it's a good guess. 318 00:14:56,830 --> 00:14:58,590 So this is, in fact, the element. 319 00:14:58,590 --> 00:15:02,235 But the inner HTML would refer more specifically to-- yeah? 320 00:15:02,235 --> 00:15:04,315 AUDIENCE: [INAUDIBLE] 321 00:15:04,315 --> 00:15:05,190 SPEAKER 1: Precisely. 322 00:15:05,190 --> 00:15:08,950 The content in between the opening and closing tags of H1. 323 00:15:08,950 --> 00:15:13,860 So if I querySelect for the H1, that will select this H1 element. 324 00:15:13,860 --> 00:15:17,322 And the inner HTML of that H1 element is the HTML content 325 00:15:17,322 --> 00:15:18,780 that's contained within those tags. 326 00:15:18,780 --> 00:15:21,920 So in this case, it's just the word "welcome." 327 00:15:21,920 --> 00:15:25,470 And so now if I instead set that inner HTML to "goodbye," 328 00:15:25,470 --> 00:15:29,400 the result is that I'm able to use this JavaScript code to actually edit 329 00:15:29,400 --> 00:15:32,400 the contents of the DOM, edit the contents of the web page 330 00:15:32,400 --> 00:15:37,000 in order to change what's contained inside of the body of the page. 331 00:15:37,000 --> 00:15:38,030 Yeah, question? 332 00:15:38,030 --> 00:15:41,259 AUDIENCE: [INAUDIBLE] 333 00:15:41,259 --> 00:15:42,300 SPEAKER 1: Good question. 334 00:15:42,300 --> 00:15:44,430 So can you make a button called Multiple Functions? 335 00:15:44,430 --> 00:15:47,160 Certainly inside of these quotation marks here, 336 00:15:47,160 --> 00:15:48,960 we could add more sophisticated JavaScript 337 00:15:48,960 --> 00:15:50,850 that potentially did call multiple functions. 338 00:15:50,850 --> 00:15:52,590 But ultimately, this is going to start getting messy 339 00:15:52,590 --> 00:15:54,450 if we have a lot of different functions contained inside 340 00:15:54,450 --> 00:15:55,770 of this onclick attribute. 341 00:15:55,770 --> 00:15:58,110 We'll see very shortly how we can begin to factor 342 00:15:58,110 --> 00:16:00,630 some of this out of the actual HTML contents 343 00:16:00,630 --> 00:16:03,999 in order to use just plain JavaScript inside of these script tags 344 00:16:03,999 --> 00:16:05,790 that allow us to do much of the same thing. 345 00:16:05,790 --> 00:16:06,500 But yes, you can. 346 00:16:06,500 --> 00:16:07,000 Yeah? 347 00:16:07,000 --> 00:16:09,560 AUDIENCE: Will it change all the H1s if there 348 00:16:09,560 --> 00:16:11,037 were multiple H1s in the document? 349 00:16:11,037 --> 00:16:12,120 SPEAKER 1: Great question. 350 00:16:12,120 --> 00:16:14,828 What would happen if there were multiple H1 tags is the question? 351 00:16:14,828 --> 00:16:16,272 Would it change all of them? 352 00:16:16,272 --> 00:16:16,980 The answer is no. 353 00:16:16,980 --> 00:16:19,830 What querySelector will do is it will look 354 00:16:19,830 --> 00:16:22,020 through the web page for something, but it will only 355 00:16:22,020 --> 00:16:24,360 select the first thing that it finds. 356 00:16:24,360 --> 00:16:28,020 So if there were multiple H1 tags, it would only select upon that first one. 357 00:16:28,020 --> 00:16:29,940 We'll look at least one example later where 358 00:16:29,940 --> 00:16:32,912 we want to select for multiple things using querySelector. 359 00:16:32,912 --> 00:16:34,620 And we'll see how we can do that as well. 360 00:16:34,620 --> 00:16:36,870 But just this querySelector function will only 361 00:16:36,870 --> 00:16:40,290 select one thing that matches what we're searching for. 362 00:16:40,290 --> 00:16:42,480 So let's see this page in action. 363 00:16:42,480 --> 00:16:44,940 So this is query.html. 364 00:16:44,940 --> 00:16:49,800 So if I now open query.html, what I see is the word "Welcome!" 365 00:16:49,800 --> 00:16:52,590 in my big heading and this button that says Click Here. 366 00:16:52,590 --> 00:16:54,600 And recall, when I click the Click Here button, 367 00:16:54,600 --> 00:16:57,930 that will trigger the calling of the hello function, which, 368 00:16:57,930 --> 00:17:00,510 ironically enough in this case, changes the contents of H1 369 00:17:00,510 --> 00:17:03,220 to say "goodbye" instead of "welcome." 370 00:17:03,220 --> 00:17:06,089 And if I refresh the page, now it goes back to "Welcome!" 371 00:17:06,089 --> 00:17:07,980 because I reloaded the entire page again. 372 00:17:07,980 --> 00:17:10,050 But clicking the button again takes me back 373 00:17:10,050 --> 00:17:12,151 to saying "goodbye" instead of "welcome." 374 00:17:12,151 --> 00:17:14,609 And so I've been able to manipulate the contents of the web 375 00:17:14,609 --> 00:17:18,030 page using JavaScript without needing to contact another server. 376 00:17:18,030 --> 00:17:20,160 I didn't load another web page that said goodbye. 377 00:17:20,160 --> 00:17:21,560 This is the same web page. 378 00:17:21,560 --> 00:17:24,180 I've just used JavaScript in order to modify the contents 379 00:17:24,180 --> 00:17:26,940 of what was actually on that page. 380 00:17:26,940 --> 00:17:29,000 Questions about anything so far? 381 00:17:29,000 --> 00:17:29,654 Yeah. 382 00:17:29,654 --> 00:17:31,590 AUDIENCE: [INAUDIBLE] 383 00:17:31,590 --> 00:17:33,270 SPEAKER 1: Is what case-sensitive? 384 00:17:33,270 --> 00:17:36,512 AUDIENCE: Attribute [INAUDIBLE]. 385 00:17:36,512 --> 00:17:38,970 SPEAKER 1: The property, I believe, is case-sensitive, yes. 386 00:17:38,970 --> 00:17:42,315 AUDIENCE: So something like a getID-- 387 00:17:42,315 --> 00:17:44,303 so it went [INAUDIBLE]. 388 00:17:44,303 --> 00:17:47,259 389 00:17:47,259 --> 00:17:48,300 SPEAKER 1: Good question. 390 00:17:48,300 --> 00:17:52,466 So the question is about a different function called getElement by ID. 391 00:17:52,466 --> 00:17:54,090 And that is, I believe, case-sensitive. 392 00:17:54,090 --> 00:17:56,964 And the way getElementById works, which you won't actually see today, 393 00:17:56,964 --> 00:18:00,060 is it's very similar to querySelector except it will only select something 394 00:18:00,060 --> 00:18:02,520 by its particular ID name. 395 00:18:02,520 --> 00:18:05,880 And just to give you a brief overview of the simple things 396 00:18:05,880 --> 00:18:08,760 that you can do with querySelector, what we saw just now 397 00:18:08,760 --> 00:18:11,820 was using document.querySelector to select a tag, 398 00:18:11,820 --> 00:18:14,010 like an H1 tag in this instance. 399 00:18:14,010 --> 00:18:17,580 We could also have used querySelector to select for a particular ID 400 00:18:17,580 --> 00:18:19,570 just by using the pound sign in front of it. 401 00:18:19,570 --> 00:18:22,230 This is the equivalent of what getElementById would do 402 00:18:22,230 --> 00:18:26,500 or, alternatively, by a particular class just by using the dot in front of it. 403 00:18:26,500 --> 00:18:28,980 And this might be syntax you remember from way back when 404 00:18:28,980 --> 00:18:30,450 we were talking about CSS. 405 00:18:30,450 --> 00:18:34,035 And if you recall, we can also use the more sophisticated CSS selectors. 406 00:18:34,035 --> 00:18:35,910 Remember we talked about selectors that would 407 00:18:35,910 --> 00:18:40,380 allow us to access just the children of a particular type of element 408 00:18:40,380 --> 00:18:44,250 or looking at only input fields that were of a certain type. 409 00:18:44,250 --> 00:18:47,010 We can do all the same things using querySelector 410 00:18:47,010 --> 00:18:50,790 in order to extract from the HTML page just the element that we 411 00:18:50,790 --> 00:18:53,670 care about modifying in this case. 412 00:18:53,670 --> 00:18:55,770 So let's start to take all of these features 413 00:18:55,770 --> 00:18:57,900 and put them together into an application that 414 00:18:57,900 --> 00:19:02,190 does something a little more than just replace the contents of a heading, 415 00:19:02,190 --> 00:19:03,310 for instance. 416 00:19:03,310 --> 00:19:08,360 And let's take a look at counter0.html. 417 00:19:08,360 --> 00:19:11,749 And so counter0.html, I'll show you what it's ultimately going to do, 418 00:19:11,749 --> 00:19:14,040 and then we'll look at the code that makes this happen. 419 00:19:14,040 --> 00:19:15,789 Right now the button that says Click Here. 420 00:19:15,789 --> 00:19:19,410 And my heading, instead of being some text, is just the number 0. 421 00:19:19,410 --> 00:19:23,010 And you'll notice that when I click on Click Here, the 0 changes to 1. 422 00:19:23,010 --> 00:19:25,102 If I click again, it changes to 2. 423 00:19:25,102 --> 00:19:27,060 And then the more I click, the number will just 424 00:19:27,060 --> 00:19:31,270 keep counting higher and higher and higher, incrementing by one every time. 425 00:19:31,270 --> 00:19:34,780 So what is the code that I need in order to make something like this happen? 426 00:19:34,780 --> 00:19:39,510 Well, let's take a look at counter0.html. 427 00:19:39,510 --> 00:19:42,030 So first, let's look at the body of this code. 428 00:19:42,030 --> 00:19:44,430 I have an H1 and I've given it an ID. 429 00:19:44,430 --> 00:19:45,990 And I've called the ID counter. 430 00:19:45,990 --> 00:19:48,990 This is just so that later on I can access this particular 431 00:19:48,990 --> 00:19:51,060 heading by referencing it by its ID. 432 00:19:51,060 --> 00:19:54,540 Its ID is counter, and this gives me an easy way to get at this heading. 433 00:19:54,540 --> 00:19:57,281 And by default, it's just going to say 0 to begin with. 434 00:19:57,281 --> 00:20:00,280 And this Click Here button is the same as the buttons we've seen before. 435 00:20:00,280 --> 00:20:02,488 It's a Click Here button, where, when we click on it, 436 00:20:02,488 --> 00:20:05,190 we'll call the count function. 437 00:20:05,190 --> 00:20:08,470 What's now happening inside of the script? 438 00:20:08,470 --> 00:20:12,450 Well, inside of the script, the first thing we've done is define a variable. 439 00:20:12,450 --> 00:20:15,840 Just like variables exist in Python that allow us to store values and manipulate 440 00:20:15,840 --> 00:20:19,560 values, we can likewise have variables existing in JavaScript as well. 441 00:20:19,560 --> 00:20:22,710 And the syntax here for that is let counter equal 0. 442 00:20:22,710 --> 00:20:27,020 We've defined a variable called counter, and its initial value is going to be 0. 443 00:20:27,020 --> 00:20:29,820 And so that variable now exists inside of our page. 444 00:20:29,820 --> 00:20:33,720 And now underneath it, we've defined a function called count. 445 00:20:33,720 --> 00:20:37,320 And what the count function does is it will increment the counter. 446 00:20:37,320 --> 00:20:41,800 Counter++ is just another way of saying, counter equals counter plus one. 447 00:20:41,800 --> 00:20:45,030 It sets counter to be a value one larger than it. 448 00:20:45,030 --> 00:20:47,190 And then after we've incremented counter, 449 00:20:47,190 --> 00:20:51,450 we're doing document.querySelector #counter 450 00:20:51,450 --> 00:20:55,860 in order to extract the item that has ID with name counter. 451 00:20:55,860 --> 00:20:59,490 And then taking that HTML element, which is the heading down below, 452 00:20:59,490 --> 00:21:01,830 and setting its inner HTML to be whatever 453 00:21:01,830 --> 00:21:04,570 the value of this counter variable currently is. 454 00:21:04,570 --> 00:21:07,670 And so the result of that is that if counter begins at 0, then 455 00:21:07,670 --> 00:21:09,420 when I click the button for the first time 456 00:21:09,420 --> 00:21:13,110 and the count function gets called, counter on line 9 457 00:21:13,110 --> 00:21:16,890 here is incremented to be 2 or 1 instead of 0. 458 00:21:16,890 --> 00:21:20,366 And then we select that heading and update the inner HTML of it 459 00:21:20,366 --> 00:21:23,847 and update the contents of that heading to be the new number. 460 00:21:23,847 --> 00:21:26,680 So questions about that code and how we were able to make that work? 461 00:21:26,680 --> 00:21:30,370 462 00:21:30,370 --> 00:21:31,780 All right. 463 00:21:31,780 --> 00:21:38,470 So now we'll take a look at some other features that we can begin to use. 464 00:21:38,470 --> 00:21:42,330 We'll take a look at counter1.html. 465 00:21:42,330 --> 00:21:46,420 And in particular here, we'll start to look at conditions 466 00:21:46,420 --> 00:21:47,710 that we can add to code. 467 00:21:47,710 --> 00:21:51,460 So just like Python has loops, and conditions, and all 468 00:21:51,460 --> 00:21:53,230 of these other programming constructs that 469 00:21:53,230 --> 00:21:55,625 let us do interesting things with our code, 470 00:21:55,625 --> 00:21:57,250 we can do the same thing in JavaScript. 471 00:21:57,250 --> 00:21:59,166 Although the syntax is a little bit different, 472 00:21:59,166 --> 00:22:01,130 the ideas, fundamentally, are all the same. 473 00:22:01,130 --> 00:22:04,240 And so here we have, inside of our body, a heading 474 00:22:04,240 --> 00:22:06,520 that's called counter that starts off at zero, 475 00:22:06,520 --> 00:22:09,580 and a button where, when we click on it, it updates the count. 476 00:22:09,580 --> 00:22:11,686 And inside of these script tags here, we are 477 00:22:11,686 --> 00:22:14,560 going to define some JavaScript that's very similar to the code we've 478 00:22:14,560 --> 00:22:15,700 been using before. 479 00:22:15,700 --> 00:22:18,700 let counter equal 0 is the definition of our variable counter, which 480 00:22:18,700 --> 00:22:20,110 starts off at zero. 481 00:22:20,110 --> 00:22:23,530 And inside of this count function, after we increment the counter, 482 00:22:23,530 --> 00:22:27,280 after we update the inner HTML of our counter heading to be whatever 483 00:22:27,280 --> 00:22:30,860 the current value of the count is, we have this condition, 484 00:22:30,860 --> 00:22:35,740 which is that if counter % 10 equals equals equals 0, 485 00:22:35,740 --> 00:22:38,105 which you should read as, if counter mod 10, 486 00:22:38,105 --> 00:22:41,230 where mod is the operator where you take the remainder of one thing divided 487 00:22:41,230 --> 00:22:45,310 by the other-- in other words, if you take one number and divide it by 10, 488 00:22:45,310 --> 00:22:50,020 whatever the remainder is, that will be what counter mod 10 is equal to. 489 00:22:50,020 --> 00:22:52,540 And the triple equal sign is JavaScript's way 490 00:22:52,540 --> 00:22:55,274 of comparing things for exact equality. 491 00:22:55,274 --> 00:22:57,940 In other words, they have to be identical to each other in order 492 00:22:57,940 --> 00:22:59,330 for this to hold true. 493 00:22:59,330 --> 00:23:06,970 So if counter mod 10 is equal to 0, then we alert and say the counter is at-- 494 00:23:06,970 --> 00:23:11,080 and here, this is an interesting feature of the more recent versions 495 00:23:11,080 --> 00:23:15,160 of JavaScript, including ES6, where this is known as a template literal. 496 00:23:15,160 --> 00:23:17,286 You think of them like formatted strings in Python, 497 00:23:17,286 --> 00:23:19,326 where I want to alert something, but I don't just 498 00:23:19,326 --> 00:23:22,010 want to alert some string that is always going to stay the same. 499 00:23:22,010 --> 00:23:24,610 I want to dynamically generate that string 500 00:23:24,610 --> 00:23:29,200 with some contents of variables that exist inside of my JavaScript code. 501 00:23:29,200 --> 00:23:32,230 And so to do something like this, the way you 502 00:23:32,230 --> 00:23:34,052 would do that is instead of using quotes, 503 00:23:34,052 --> 00:23:36,760 either single or double quotes as you normally would for strings, 504 00:23:36,760 --> 00:23:39,176 we're using that back tick symbol, which, on US keyboards, 505 00:23:39,176 --> 00:23:41,050 is right above the Tab key. 506 00:23:41,050 --> 00:23:44,890 And we say in this alert, the counter is at-- 507 00:23:44,890 --> 00:23:48,250 and then to plug in a variable, the way we do this in JavaScript 508 00:23:48,250 --> 00:23:50,860 is to use the dollar sign and then, inside 509 00:23:50,860 --> 00:23:54,440 of curly braces, the name of the variable that we want to plug in. 510 00:23:54,440 --> 00:23:56,470 And so here, we're saying, counter is at-- 511 00:23:56,470 --> 00:23:59,200 and this code here is saying, take the variable counter 512 00:23:59,200 --> 00:24:02,200 and just plug it in to this part of the template string. 513 00:24:02,200 --> 00:24:05,350 So it's the back ticks around the string, and then the dollar sign, 514 00:24:05,350 --> 00:24:08,200 and the curly braces that allow me to format the string 515 00:24:08,200 --> 00:24:11,680 and treat it like a template that I'm able to plug in certain variable values 516 00:24:11,680 --> 00:24:12,790 into it. 517 00:24:12,790 --> 00:24:16,480 So what do we think the result of running this web page is going to be? 518 00:24:16,480 --> 00:24:19,630 How is the behavior going to be different than the example we 519 00:24:19,630 --> 00:24:22,540 saw just a moment ago? 520 00:24:22,540 --> 00:24:25,690 In particular, what will this if condition inside of the count function 521 00:24:25,690 --> 00:24:26,920 do? 522 00:24:26,920 --> 00:24:27,823 Yeah? 523 00:24:27,823 --> 00:24:31,792 AUDIENCE: [INAUDIBLE] 524 00:24:31,792 --> 00:24:32,500 SPEAKER 1: Great. 525 00:24:32,500 --> 00:24:34,666 Every 10 times we click the button, it should pop up 526 00:24:34,666 --> 00:24:38,230 with an alert, because every 10 times we click it, when we get to counter 527 00:24:38,230 --> 00:24:43,194 is 10, then 10 mod 10, 10 divided by 10, leaves a remainder of 0. 528 00:24:43,194 --> 00:24:45,610 And so 0 will be equal to 0, and then we'll get the alert. 529 00:24:45,610 --> 00:24:47,620 But in other cases, we won't. 530 00:24:47,620 --> 00:24:53,110 So if we now open up counter1.html, we can count just as we did before. 531 00:24:53,110 --> 00:24:54,950 But it's only when we are at 9. 532 00:24:54,950 --> 00:24:58,259 And when we click again, then we get the alert saying that the counter is a 10. 533 00:24:58,259 --> 00:25:00,550 And if we were to continue counting, when we get to 20, 534 00:25:00,550 --> 00:25:03,260 it would give me another alert, 30, so on and so forth. 535 00:25:03,260 --> 00:25:05,470 And so this allows us to have a little more control. 536 00:25:05,470 --> 00:25:08,890 Just like we were able to have if conditions inside of Python, 537 00:25:08,890 --> 00:25:10,390 we do the same thing in JavaScript. 538 00:25:10,390 --> 00:25:13,840 And like the distinction between functions in Python and JavaScript, 539 00:25:13,840 --> 00:25:17,260 the way that we denote the contents of an if condition in JavaScript 540 00:25:17,260 --> 00:25:19,900 is to enclose it inside of curly braces. 541 00:25:19,900 --> 00:25:21,610 Strictly speaking, this is only necessary 542 00:25:21,610 --> 00:25:24,400 for if conditions that run onto multiple lines. 543 00:25:24,400 --> 00:25:26,950 If the condition were just a single line, as it is now, 544 00:25:26,950 --> 00:25:29,200 the curly braces aren't, strictly speaking, necessary. 545 00:25:29,200 --> 00:25:31,960 But oftentimes, they're good just as a visual cue so that anyone 546 00:25:31,960 --> 00:25:35,350 looking at the code can see what is contained inside of the if condition 547 00:25:35,350 --> 00:25:36,952 and what is not. 548 00:25:36,952 --> 00:25:38,410 Questions about any of that so far? 549 00:25:38,410 --> 00:25:41,010 550 00:25:41,010 --> 00:25:42,490 OK, great. 551 00:25:42,490 --> 00:25:47,740 Now let's take a look at counter2.html. 552 00:25:47,740 --> 00:25:51,377 And so in this case, what we've done is if we look down at the body 553 00:25:51,377 --> 00:25:53,710 before we look at the actual contents of the JavaScript, 554 00:25:53,710 --> 00:25:56,290 we'll notice that one thing is different here. 555 00:25:56,290 --> 00:26:00,762 We have H1 id is counter is 0, and then a button that says Click Here. 556 00:26:00,762 --> 00:26:03,220 What is different between this and all of the other buttons 557 00:26:03,220 --> 00:26:05,840 that we've seen so far? 558 00:26:05,840 --> 00:26:08,179 Great, the onclick property is no longer present. 559 00:26:08,179 --> 00:26:09,970 So I have this button that says Click Here, 560 00:26:09,970 --> 00:26:14,227 but I don't have anything that is saying, when this button is clicked, 561 00:26:14,227 --> 00:26:15,310 here's what you should do. 562 00:26:15,310 --> 00:26:18,150 Or at least it doesn't appear to be that way. 563 00:26:18,150 --> 00:26:20,350 What we'll soon see is an attempt at trying 564 00:26:20,350 --> 00:26:23,200 to take all this JavaScript logic and JavaScript code, 565 00:26:23,200 --> 00:26:24,790 and factor it out of the HTML. 566 00:26:24,790 --> 00:26:29,400 So I don't need to have JavaScript code inside the body of the HTML contents 567 00:26:29,400 --> 00:26:31,150 in order to tell the button what to do. 568 00:26:31,150 --> 00:26:33,810 But instead, I can put it all inside of these script tags. 569 00:26:33,810 --> 00:26:37,547 And so this looks, in between the script tags here, a little more complicated, 570 00:26:37,547 --> 00:26:39,630 but let's take it one step at a time and see if we 571 00:26:39,630 --> 00:26:42,580 can understand what's happening here. 572 00:26:42,580 --> 00:26:46,920 So up on line 6, we have document.addEventListener. 573 00:26:46,920 --> 00:26:49,260 So we haven't used addEventListener before, 574 00:26:49,260 --> 00:26:51,122 but we have talked about the idea of events, 575 00:26:51,122 --> 00:26:52,830 that when something is clicked on, that's 576 00:26:52,830 --> 00:26:55,800 an event; when you mouse over something, that's an event. 577 00:26:55,800 --> 00:26:58,620 It turns out that the document, the web page, 578 00:26:58,620 --> 00:27:00,690 has an event that almost all modern web browsers 579 00:27:00,690 --> 00:27:03,480 support called DOMContentLoaded. 580 00:27:03,480 --> 00:27:07,110 And that event is the event that's triggered when the DOM, the Document 581 00:27:07,110 --> 00:27:10,860 Object Model, that structure of all of the HTML tags inside of our page, 582 00:27:10,860 --> 00:27:13,170 is done being loaded by the web browser. 583 00:27:13,170 --> 00:27:17,250 And so when that is done being loaded, when we've loaded the web browser, 584 00:27:17,250 --> 00:27:20,830 now we can start to do some interesting work. 585 00:27:20,830 --> 00:27:25,020 And so what we've done is we've called this addEventListener function, which 586 00:27:25,020 --> 00:27:26,890 really takes two arguments. 587 00:27:26,890 --> 00:27:29,400 It takes, as its first argument, the name of the event 588 00:27:29,400 --> 00:27:30,750 that we want to listen for-- 589 00:27:30,750 --> 00:27:33,420 in this case, the DOMContentLoaded event. 590 00:27:33,420 --> 00:27:36,990 But the second event is actually a function. 591 00:27:36,990 --> 00:27:40,410 And so JavaScript allows us to do what are 592 00:27:40,410 --> 00:27:42,600 called higher order functions, where we can 593 00:27:42,600 --> 00:27:45,310 treat functions themselves as values. 594 00:27:45,310 --> 00:27:48,210 And if we want to take a function and pass it into an argument 595 00:27:48,210 --> 00:27:50,100 to another function, the same way we would 596 00:27:50,100 --> 00:27:53,700 pass an integer into a function or a string into a function, for example, 597 00:27:53,700 --> 00:27:55,080 JavaScript allows us to do that. 598 00:27:55,080 --> 00:27:58,246 Python allows us to do it too, and it's a feature of many modern programming 599 00:27:58,246 --> 00:27:59,160 languages nowadays. 600 00:27:59,160 --> 00:28:02,910 But we can take this whole function that starts with function 601 00:28:02,910 --> 00:28:05,580 and is enclosed inside of these curly braces, 602 00:28:05,580 --> 00:28:09,150 and pass that whole function in as the second argument 603 00:28:09,150 --> 00:28:14,670 to this addEventListener function that we're calling here. 604 00:28:14,670 --> 00:28:18,510 And this parenthetical at the end is closing the argument list 605 00:28:18,510 --> 00:28:19,800 to addEventListener. 606 00:28:19,800 --> 00:28:21,250 And so what does this all mean? 607 00:28:21,250 --> 00:28:24,840 It means that we're telling the document that when the content of the DOM 608 00:28:24,840 --> 00:28:27,390 is loaded, this is the function that should run. 609 00:28:27,390 --> 00:28:28,830 It's not going to run right away. 610 00:28:28,830 --> 00:28:30,960 It's what we might call a callback function. 611 00:28:30,960 --> 00:28:34,050 When the content of the DOM is loaded, then JavaScript 612 00:28:34,050 --> 00:28:36,090 is going to call this function and it's going 613 00:28:36,090 --> 00:28:39,000 to run the contents of that function only when 614 00:28:39,000 --> 00:28:41,190 that event listener is done running. 615 00:28:41,190 --> 00:28:43,590 So what are we saying here? 616 00:28:43,590 --> 00:28:47,700 Inside, when the DOM is done running, we're going to document .querySelector 617 00:28:47,700 --> 00:28:48,279 button-- 618 00:28:48,279 --> 00:28:50,320 in other words, extract the button from the page. 619 00:28:50,320 --> 00:28:51,270 There's only one in this case. 620 00:28:51,270 --> 00:28:54,000 But as was mentioned before, if there had been multiple buttons, 621 00:28:54,000 --> 00:28:56,640 querySelector would just select the first one. 622 00:28:56,640 --> 00:29:00,170 And then we're setting the onclick attribute of the button. 623 00:29:00,170 --> 00:29:01,920 This is effectively the same thing as what 624 00:29:01,920 --> 00:29:05,230 we were doing before, where we actually had the button tag and we said, 625 00:29:05,230 --> 00:29:06,960 onclick equals-- 626 00:29:06,960 --> 00:29:08,550 here's what to do. 627 00:29:08,550 --> 00:29:12,450 And we're setting onclick equal to count, 628 00:29:12,450 --> 00:29:16,155 where count is also itself a function that's defined down here. 629 00:29:16,155 --> 00:29:18,030 And this is the same function that we've been 630 00:29:18,030 --> 00:29:20,250 looking at before that just increments the counter, 631 00:29:20,250 --> 00:29:23,400 updates the HTML of the heading, and then has this if condition that 632 00:29:23,400 --> 00:29:24,900 alerts or doesn't alert. 633 00:29:24,900 --> 00:29:27,120 But we're taking that function and treating it 634 00:29:27,120 --> 00:29:29,580 like a value, which JavaScript allows us to do. 635 00:29:29,580 --> 00:29:33,300 And we're saying, when the button is clicked on, what should you do? 636 00:29:33,300 --> 00:29:34,560 Run the count function. 637 00:29:34,560 --> 00:29:36,570 Again, that count function won't run right away. 638 00:29:36,570 --> 00:29:40,870 It will only run when that button is clicked on. 639 00:29:40,870 --> 00:29:43,410 So questions about these three lines of code 640 00:29:43,410 --> 00:29:46,792 in particular that are sort of strange to wrap your mind around at first-- 641 00:29:46,792 --> 00:29:49,500 treating functions the same way you would treat any other values, 642 00:29:49,500 --> 00:29:50,970 like numbers or strings. 643 00:29:50,970 --> 00:29:54,120 But ultimately, this is one of the most powerful features of JavaScript, 644 00:29:54,120 --> 00:29:57,150 which is the ability to take functions and pass them 645 00:29:57,150 --> 00:30:00,660 as arguments into other functions, and to set them as callback functions that 646 00:30:00,660 --> 00:30:04,210 only run when certain things happen. 647 00:30:04,210 --> 00:30:04,817 Yes? 648 00:30:04,817 --> 00:30:07,233 AUDIENCE: Does that mean we can't create a variable called 649 00:30:07,233 --> 00:30:09,470 count in the function [INAUDIBLE],, if we just 650 00:30:09,470 --> 00:30:12,960 try to create a variable without [INAUDIBLE]?? 651 00:30:12,960 --> 00:30:15,660 SPEAKER 1: If you tried to create a variable called count, 652 00:30:15,660 --> 00:30:18,160 you would likely get namespace collision from that case, in which case 653 00:30:18,160 --> 00:30:19,080 you would try to avoid that. 654 00:30:19,080 --> 00:30:19,563 Yeah. 655 00:30:19,563 --> 00:30:21,938 AUDIENCE: Why is this better than just explicitly putting 656 00:30:21,938 --> 00:30:25,842 the count function as the onclick attribute when you create the button 657 00:30:25,842 --> 00:30:26,820 [INAUDIBLE]? 658 00:30:26,820 --> 00:30:27,903 SPEAKER 1: Great question. 659 00:30:27,903 --> 00:30:31,426 Why is this any better than just putting the onclick inside of the button 660 00:30:31,426 --> 00:30:34,050 inside of the HTML, which seemed a whole lot simpler as opposed 661 00:30:34,050 --> 00:30:37,440 to this complexity of DOMContentLoaded and such. 662 00:30:37,440 --> 00:30:41,116 As sites start to get more and more complex, 663 00:30:41,116 --> 00:30:43,240 you'll see added value that we can get out of this. 664 00:30:43,240 --> 00:30:45,570 For example, if we had 100 buttons and we 665 00:30:45,570 --> 00:30:49,380 wanted all 100 buttons to do something in particular when they're clicked on, 666 00:30:49,380 --> 00:30:51,900 we could go through all 100 buttons in our HTML 667 00:30:51,900 --> 00:30:54,180 and add onclick attributes to all of them. 668 00:30:54,180 --> 00:30:57,390 Or we could, in JavaScript, do things a little more programmatically, 669 00:30:57,390 --> 00:30:59,730 and try and select all of the buttons, and give them 670 00:30:59,730 --> 00:31:02,730 all an onclick attribute in some loop, for example, 671 00:31:02,730 --> 00:31:07,365 which would be slightly cleaner in terms of using programming 672 00:31:07,365 --> 00:31:09,240 structures like loops and conditions in order 673 00:31:09,240 --> 00:31:12,050 to modify the attributes of the events. 674 00:31:12,050 --> 00:31:14,910 And in other cases, you might want a little more control over what 675 00:31:14,910 --> 00:31:16,368 happens when you click on a button. 676 00:31:16,368 --> 00:31:19,590 You might want a button to do one thing in certain situations 677 00:31:19,590 --> 00:31:21,360 and another thing in other situations. 678 00:31:21,360 --> 00:31:24,960 And being able to programmatically say "if something is true, 679 00:31:24,960 --> 00:31:28,080 then set the onclick attribute to count; and if it's not true, 680 00:31:28,080 --> 00:31:30,777 then something else" gives us a little more flexibility there. 681 00:31:30,777 --> 00:31:32,610 And finally, it's just a little bit cleaner. 682 00:31:32,610 --> 00:31:37,450 That inside of the body of the HTML now, we no longer have any JavaScript code. 683 00:31:37,450 --> 00:31:40,650 So if I need to change anything in terms of just the JavaScript, 684 00:31:40,650 --> 00:31:44,542 I only need to change what's inside the contents of the script tags. 685 00:31:44,542 --> 00:31:46,500 And we'll see another example of factoring this 686 00:31:46,500 --> 00:31:48,690 out even more in just a moment. 687 00:31:48,690 --> 00:31:49,830 But good question. 688 00:31:49,830 --> 00:31:53,940 Was there another question someone had? 689 00:31:53,940 --> 00:31:54,440 All right. 690 00:31:54,440 --> 00:31:57,080 So this was just allowing us to add an event listener 691 00:31:57,080 --> 00:31:58,490 for when the DOM is done loading. 692 00:31:58,490 --> 00:32:01,670 And we'll see this syntax quite a lot in the examples today, 693 00:32:01,670 --> 00:32:06,570 where when the DOM is finished loading, then we want a particular code to run. 694 00:32:06,570 --> 00:32:10,370 So this is an example of us trying to factor out some of the JavaScript code 695 00:32:10,370 --> 00:32:14,030 from the HTML that's down below into this script tag. 696 00:32:14,030 --> 00:32:16,670 But what we might like to do is factor this out even more 697 00:32:16,670 --> 00:32:21,680 and put the JavaScript code not just at the top of the HTML file, 698 00:32:21,680 --> 00:32:23,930 but in a second file altogether. 699 00:32:23,930 --> 00:32:26,054 Now, aside from just cleanliness and moving things 700 00:32:26,054 --> 00:32:28,220 out into separate places, what might be a reason why 701 00:32:28,220 --> 00:32:30,380 we might want JavaScript code factored out 702 00:32:30,380 --> 00:32:35,020 into an external file instead of inside of the same file as everything else? 703 00:32:35,020 --> 00:32:35,520 Yeah? 704 00:32:35,520 --> 00:32:36,450 AUDIENCE: You can reuse it. 705 00:32:36,450 --> 00:32:37,250 SPEAKER 1: It's reusable. 706 00:32:37,250 --> 00:32:37,750 Great. 707 00:32:37,750 --> 00:32:41,000 If I had multiple HTML files that wanted to use the same JavaScript, 708 00:32:41,000 --> 00:32:43,250 I could just reference them all to the same JavaScript 709 00:32:43,250 --> 00:32:47,120 file in much the same way that, when we were designing style sheets in CSS, 710 00:32:47,120 --> 00:32:49,130 we could factor them out into a separate CSS 711 00:32:49,130 --> 00:32:52,790 file such that multiple different pages could use the same CSS style sheet. 712 00:32:52,790 --> 00:32:55,040 And so what would this look like to try and factor out 713 00:32:55,040 --> 00:32:57,650 our JavaScript into a separate file? 714 00:32:57,650 --> 00:33:01,160 Let's take a look now at counter3.html. 715 00:33:01,160 --> 00:33:03,860 And this is the same thing, except instead 716 00:33:03,860 --> 00:33:06,590 of something inside of the script tags, I've just said, 717 00:33:06,590 --> 00:33:10,450 script src equals counter3.js. 718 00:33:10,450 --> 00:33:14,960 counter3.js is the JavaScript file that contains all the JavaScript code 719 00:33:14,960 --> 00:33:16,130 that I care about. 720 00:33:16,130 --> 00:33:19,460 And in the body, I just have a heading and a button. 721 00:33:19,460 --> 00:33:24,580 But inside of counter3.js, this is all the same JavaScript as before. 722 00:33:24,580 --> 00:33:28,460 Add the addEventListener for when the DOM content loads, which adds 723 00:33:28,460 --> 00:33:31,610 count to be what happens when the button is clicked on. 724 00:33:31,610 --> 00:33:35,460 And then I have the count function here, which actually does the incrementing, 725 00:33:35,460 --> 00:33:37,930 and the query selecting, and the alerting. 726 00:33:37,930 --> 00:33:41,450 And so this allows us to factor that JavaScript out even more, 727 00:33:41,450 --> 00:33:43,550 helps to clean up the contents of the HTML page. 728 00:33:43,550 --> 00:33:46,435 It also makes it reusable, as was just mentioned. 729 00:33:46,435 --> 00:33:49,670 And so these are more examples of how we can begin to clean up the code 730 00:33:49,670 --> 00:33:51,560 that we've been writing. 731 00:33:51,560 --> 00:33:55,030 Questions about anything so far? 732 00:33:55,030 --> 00:33:55,550 OK. 733 00:33:55,550 --> 00:33:58,820 I'll talk briefly about variables just for a moment. 734 00:33:58,820 --> 00:34:01,730 The latest versions of JavaScript have a bunch of different ways 735 00:34:01,730 --> 00:34:02,570 to define variables. 736 00:34:02,570 --> 00:34:05,960 And we've seen the example of let counter equal 0 737 00:34:05,960 --> 00:34:10,670 to be one example of how variables might be defined in JavaScript. 738 00:34:10,670 --> 00:34:13,850 But there are actually multiple ways in which we can use variables. 739 00:34:13,850 --> 00:34:15,949 And there are three that are the most common-- 740 00:34:15,949 --> 00:34:18,399 const, and let, and var. 741 00:34:18,399 --> 00:34:20,690 And so we've seen let in the example that we just used. 742 00:34:20,690 --> 00:34:23,023 But I'll talk about the distinction between these three. 743 00:34:23,023 --> 00:34:26,540 const is the variable type that means a constant value, 744 00:34:26,540 --> 00:34:28,469 as you might guess from the name. 745 00:34:28,469 --> 00:34:31,070 And so if I define a variable as a const variable, 746 00:34:31,070 --> 00:34:32,420 then I can't reassign it later. 747 00:34:32,420 --> 00:34:35,600 If I try to reassign it to some other thing later on in the JavaScript page, 748 00:34:35,600 --> 00:34:37,308 it's going to give me some kind of error. 749 00:34:37,308 --> 00:34:40,250 And so it's useful if I want to define a variable 750 00:34:40,250 --> 00:34:42,090 that I know is not going to change. 751 00:34:42,090 --> 00:34:45,162 And it can help to avoid potential bugs later 752 00:34:45,162 --> 00:34:47,120 on down the line where I might try to change it 753 00:34:47,120 --> 00:34:48,929 even though it shouldn't be changed. 754 00:34:48,929 --> 00:34:52,850 And so this just helps to enforce that that variable's value will not change. 755 00:34:52,850 --> 00:34:54,739 let is the example of the variable that we've 756 00:34:54,739 --> 00:34:58,760 been using so far, where let will exist inside 757 00:34:58,760 --> 00:35:04,324 of the scope of the innermost curly braces surrounding it. 758 00:35:04,324 --> 00:35:06,240 And you'll see an example of that in a moment. 759 00:35:06,240 --> 00:35:09,650 But in particular, if you define a variable with let inside 760 00:35:09,650 --> 00:35:13,220 of a block of curly braces, then outside of that block of curly braces, 761 00:35:13,220 --> 00:35:15,320 that variable will no longer exist. 762 00:35:15,320 --> 00:35:18,170 As opposed to var, which operates similarly 763 00:35:18,170 --> 00:35:19,920 to let but slightly differently. 764 00:35:19,920 --> 00:35:24,290 If you define a variable as var, then it will exist all the way inside 765 00:35:24,290 --> 00:35:26,430 of whatever function it was originally defined 766 00:35:26,430 --> 00:35:28,280 in if it was defined inside of a function 767 00:35:28,280 --> 00:35:32,180 even if it was included in an enclosing set of curly braces. 768 00:35:32,180 --> 00:35:34,940 And so that was sort of a lot of complexities and nuances 769 00:35:34,940 --> 00:35:35,780 between the three. 770 00:35:35,780 --> 00:35:38,990 We'll take a look at some examples of those variables actually in action 771 00:35:38,990 --> 00:35:41,960 now, so that you can get a sense for when 772 00:35:41,960 --> 00:35:44,420 you might use one of these variable types over another 773 00:35:44,420 --> 00:35:47,730 and how their behavior differs a little bit. 774 00:35:47,730 --> 00:35:50,820 So let's take a look at variable0.html. 775 00:35:50,820 --> 00:35:55,800 And so all variable0.html does is if true-- 776 00:35:55,800 --> 00:35:57,630 so if true is true, which is always true, 777 00:35:57,630 --> 00:35:59,540 so this condition will always run-- 778 00:35:59,540 --> 00:36:02,720 we set var message equal to Hello! 779 00:36:02,720 --> 00:36:06,030 And then we alert with that particular message. 780 00:36:06,030 --> 00:36:08,900 And because it's defined as a var, then it's 781 00:36:08,900 --> 00:36:13,040 going to exist even outside of just the contents of that if condition. 782 00:36:13,040 --> 00:36:19,520 And so if I now open up variable0.html, I get an alert and this page 783 00:36:19,520 --> 00:36:20,860 says hello. 784 00:36:20,860 --> 00:36:25,550 So it behaves as we might want the page to behave, because I define it as a var 785 00:36:25,550 --> 00:36:28,910 and even though it's inside this span of curly braces, when I alert, 786 00:36:28,910 --> 00:36:33,290 it alerts with the correct value of message. 787 00:36:33,290 --> 00:36:37,370 variable1.html instead is going to use let instead of var. 788 00:36:37,370 --> 00:36:39,680 So the only change here is that instead of var message 789 00:36:39,680 --> 00:36:43,280 equals Hello!, I've said, let message equal Hello! 790 00:36:43,280 --> 00:36:47,240 And then down below, I get an alert that says alert message. 791 00:36:47,240 --> 00:36:51,200 Any guesses as to what might happen now if I try to open variables1.html? 792 00:36:51,200 --> 00:36:54,590 793 00:36:54,590 --> 00:36:55,497 A blank alert. 794 00:36:55,497 --> 00:36:56,330 That's a good guess. 795 00:36:56,330 --> 00:36:57,830 Other thoughts? 796 00:36:57,830 --> 00:36:58,820 An error. 797 00:36:58,820 --> 00:37:00,150 All right, let's try it out. 798 00:37:00,150 --> 00:37:01,108 Let's see what happens. 799 00:37:01,108 --> 00:37:03,800 Let's open up variables1.html. 800 00:37:03,800 --> 00:37:06,380 And it just says "Welcome!" and I don't see anything so far. 801 00:37:06,380 --> 00:37:08,900 And I also don't see an error message just yet. 802 00:37:08,900 --> 00:37:11,202 And so one thing to look for if the page doesn't 803 00:37:11,202 --> 00:37:13,910 seem to be doing what you might initially think it might be doing 804 00:37:13,910 --> 00:37:16,460 is to actually look at the JavaScript console, which 805 00:37:16,460 --> 00:37:18,980 is built into most modern web browsers, and just take a look 806 00:37:18,980 --> 00:37:20,800 and see if there actually were any errors. 807 00:37:20,800 --> 00:37:23,390 And so an easy way to get to that, in Google Chrome at least, 808 00:37:23,390 --> 00:37:28,460 is to Ctrl-click on the page and go to Inspect, which opens up the Inspector. 809 00:37:28,460 --> 00:37:32,210 And if I click over here now to the console, what I get 810 00:37:32,210 --> 00:37:33,670 is the actual JavaScript error. 811 00:37:33,670 --> 00:37:35,420 And so this is where JavaScript errors are 812 00:37:35,420 --> 00:37:37,916 going to appear if I'm running them in the web browser, 813 00:37:37,916 --> 00:37:40,790 because all of the JavaScript code is running inside the web browser, 814 00:37:40,790 --> 00:37:42,130 inside of Google Chrome. 815 00:37:42,130 --> 00:37:46,119 And so any errors that pop up are going to be part of-- 816 00:37:46,119 --> 00:37:48,160 they're going to show up inside of Google Chrome. 817 00:37:48,160 --> 00:37:50,210 And so this says, "uncaught reference error, 818 00:37:50,210 --> 00:37:56,870 message is not defined at variables1.html:11," meaning line 11. 819 00:37:56,870 --> 00:38:00,980 And so if I go back to variables1.html, line 11, this is that line. 820 00:38:00,980 --> 00:38:02,960 And the reason why message is no longer defined 821 00:38:02,960 --> 00:38:05,900 is because let only defines the variable in the scope 822 00:38:05,900 --> 00:38:07,920 of the outermost set of curly braces. 823 00:38:07,920 --> 00:38:10,435 So this is very similar to how programming languages like C 824 00:38:10,435 --> 00:38:12,560 treat their variables, where the variables are only 825 00:38:12,560 --> 00:38:15,680 existing inside of the scope in which they're 826 00:38:15,680 --> 00:38:18,260 defined based on those curly braces. 827 00:38:18,260 --> 00:38:21,530 And finally, we'll take a look at one other example. 828 00:38:21,530 --> 00:38:25,130 We'll look at variables2.html, where, in this case, 829 00:38:25,130 --> 00:38:28,580 we have const message equals Hello! 830 00:38:28,580 --> 00:38:30,650 And now I'm trying to reset the value of message. 831 00:38:30,650 --> 00:38:32,690 Message equals Goodbye! 832 00:38:32,690 --> 00:38:35,840 And then I'm going to alert that message. 833 00:38:35,840 --> 00:38:37,280 Guesses as to what might happen? 834 00:38:37,280 --> 00:38:39,452 Plenty of reasonable guesses here, but let's-- 835 00:38:39,452 --> 00:38:40,160 what do we think? 836 00:38:40,160 --> 00:38:40,832 AUDIENCE: Another error. 837 00:38:40,832 --> 00:38:42,456 SPEAKER 1: You could get another error. 838 00:38:42,456 --> 00:38:46,646 839 00:38:46,646 --> 00:38:48,770 And in fact, that's exactly what's going to happen. 840 00:38:48,770 --> 00:38:49,478 We see "Welcome!" 841 00:38:49,478 --> 00:38:50,890 We don't see any error message. 842 00:38:50,890 --> 00:38:54,700 But if I go ahead and inspect this and go to the console again, 843 00:38:54,700 --> 00:38:58,090 we see "uncaught type error, assignment to constant variable 844 00:38:58,090 --> 00:39:00,579 at variables2.html, line 8." 845 00:39:00,579 --> 00:39:02,620 And so we're not allowed to take a const variable 846 00:39:02,620 --> 00:39:04,317 and reassign it to something else. 847 00:39:04,317 --> 00:39:06,150 And so here on line 8, trying to set message 848 00:39:06,150 --> 00:39:09,587 to be "Goodbye!" before we alert it is not going to be something 849 00:39:09,587 --> 00:39:12,670 that JavaScript allows us to do, whereas if we had defined a variable with 850 00:39:12,670 --> 00:39:14,800 let or var, then we could have. 851 00:39:14,800 --> 00:39:17,560 So three slightly different ways of defining 852 00:39:17,560 --> 00:39:19,810 variables that result in slightly different behavior. 853 00:39:19,810 --> 00:39:22,420 It's good just to understand all three and to know how 854 00:39:22,420 --> 00:39:25,209 they behave in different circumstances. 855 00:39:25,209 --> 00:39:27,250 And those are just different ways of how we might 856 00:39:27,250 --> 00:39:31,370 go about using variables in our code. 857 00:39:31,370 --> 00:39:31,870 Yeah? 858 00:39:31,870 --> 00:39:35,359 AUDIENCE: Is there a default if you don't say what it is? 859 00:39:35,359 --> 00:39:37,150 SPEAKER 1: If you don't specify what it is, 860 00:39:37,150 --> 00:39:41,890 I believe it will default to binding as if it were a var, 861 00:39:41,890 --> 00:39:43,625 but I'm not 100% sure about that. 862 00:39:43,625 --> 00:39:45,280 I'll have to check on that. 863 00:39:45,280 --> 00:39:45,880 Good question. 864 00:39:45,880 --> 00:39:46,421 Other things? 865 00:39:46,421 --> 00:39:49,660 866 00:39:49,660 --> 00:39:50,320 OK. 867 00:39:50,320 --> 00:39:53,829 One other interesting thing to note about this JavaScript console 868 00:39:53,829 --> 00:39:55,870 that we're looking at here inside the web browser 869 00:39:55,870 --> 00:40:00,280 is that it actually allows us to execute JavaScript code in much the same way 870 00:40:00,280 --> 00:40:04,040 as the Python interpreter allows us to execute code here as well. 871 00:40:04,040 --> 00:40:09,220 So for example, if I wanted to define another variable, like let x equal 28, 872 00:40:09,220 --> 00:40:12,040 I can just type JavaScript code into the console here. 873 00:40:12,040 --> 00:40:15,092 And if I type "x" now, for instance, that's going to be equal to 28. 874 00:40:15,092 --> 00:40:18,050 And that's something that you can do inside of this JavaScript console. 875 00:40:18,050 --> 00:40:21,640 So if you're ever confused as to what exactly is going on here, 876 00:40:21,640 --> 00:40:24,700 oftentimes it can be a good idea to use the JavaScript console, run 877 00:40:24,700 --> 00:40:27,830 some JavaScript code in order to get a sense for what's really happening. 878 00:40:27,830 --> 00:40:32,530 For example, if I were to run document.querySelector, 879 00:40:32,530 --> 00:40:36,790 h1, then what I get back is it'll actually 880 00:40:36,790 --> 00:40:40,330 show me what happens when I run document.querySelector h1. 881 00:40:40,330 --> 00:40:45,094 Well, it gets me that h1, "Welcome," exclamation point, end the h1 tag. 882 00:40:45,094 --> 00:40:47,260 And so you can see what the actual result of running 883 00:40:47,260 --> 00:40:49,000 some of this JavaScript code would be. 884 00:40:49,000 --> 00:40:53,900 And likewise, if I tried to run document.querySelector, h1, 885 00:40:53,900 --> 00:40:57,160 .innerHTML to see what's the inner HTML contents of it, 886 00:40:57,160 --> 00:41:01,880 then I get just that string, "Welcome!" as the result of that. 887 00:41:01,880 --> 00:41:04,420 And so this can often be a helpful debugging tool 888 00:41:04,420 --> 00:41:07,420 if you're trying to understand what's going on inside of your JavaScript 889 00:41:07,420 --> 00:41:10,360 code, where you can actually run JavaScript inside of the console 890 00:41:10,360 --> 00:41:13,020 in order to manipulate things and change things. 891 00:41:13,020 --> 00:41:14,770 And one nice example of that, actually, is 892 00:41:14,770 --> 00:41:19,622 if I go back to our counter one example, this example where 893 00:41:19,622 --> 00:41:22,330 I could click here and just increment the counter again and again 894 00:41:22,330 --> 00:41:24,910 and again, if I wanted to, I could go here and say, 895 00:41:24,910 --> 00:41:27,460 what is the value of this variable counter? 896 00:41:27,460 --> 00:41:28,810 It's currently 7. 897 00:41:28,810 --> 00:41:32,260 If I set counter equal to 27 instead, what's 898 00:41:32,260 --> 00:41:34,960 going to happen when I click here? 899 00:41:34,960 --> 00:41:35,481 28. 900 00:41:35,481 --> 00:41:35,980 Exactly. 901 00:41:35,980 --> 00:41:37,813 Because I've reset the value of counter, you 902 00:41:37,813 --> 00:41:41,590 can actually manipulate the values of variables inside of the JavaScript 903 00:41:41,590 --> 00:41:43,960 console and make manipulations however you like them. 904 00:41:43,960 --> 00:41:46,840 And you can see the results actually appear on the web page. 905 00:41:46,840 --> 00:41:51,880 I can do document.querySelector, h1 to get at that counter. 906 00:41:51,880 --> 00:41:56,560 And if I set the innerHTML to be "Hello," well, now 907 00:41:56,560 --> 00:41:59,620 I've just changed the contents of the web page to be, instead of 28, 908 00:41:59,620 --> 00:42:00,901 now it says "Hello!" 909 00:42:00,901 --> 00:42:03,400 But as soon as I click here again, it increments the counter 910 00:42:03,400 --> 00:42:04,730 and resets the contents. 911 00:42:04,730 --> 00:42:08,500 So this allows you to manipulate web pages using JavaScript, using 912 00:42:08,500 --> 00:42:10,030 the console in that way as well. 913 00:42:10,030 --> 00:42:12,710 914 00:42:12,710 --> 00:42:16,670 Questions about anything we've gone over so far? 915 00:42:16,670 --> 00:42:17,290 OK. 916 00:42:17,290 --> 00:42:19,665 Let's take a look at a couple other more common use cases 917 00:42:19,665 --> 00:42:22,390 that we might find with regards to JavaScript. 918 00:42:22,390 --> 00:42:24,850 Let's take a look now at hello1.html. 919 00:42:24,850 --> 00:42:27,550 So we saw an example of an alert that just said "Hello!" 920 00:42:27,550 --> 00:42:30,370 Let's take that to another level now. 921 00:42:30,370 --> 00:42:32,990 Inside the body of our web page in hello1.html, 922 00:42:32,990 --> 00:42:37,450 we have a form whose ID is form just to make it easy to reference later. 923 00:42:37,450 --> 00:42:39,010 And I have an input field. 924 00:42:39,010 --> 00:42:42,150 This ID is name-- again, just to make it easy to reference later. 925 00:42:42,150 --> 00:42:45,184 And the placeholder that we're going to fill into the input field 926 00:42:45,184 --> 00:42:46,600 is just going to be the word name. 927 00:42:46,600 --> 00:42:49,300 And it's going to be an input field where I can type text. 928 00:42:49,300 --> 00:42:52,470 And underneath that, I'm going to have an input whose type is submit. 929 00:42:52,470 --> 00:42:55,820 That's just going to be a button that allows me to submit the form. 930 00:42:55,820 --> 00:42:59,380 So now what is going on inside of my JavaScript? 931 00:42:59,380 --> 00:43:03,670 Well, when the DOM content is loaded, I'm going to run this function. 932 00:43:03,670 --> 00:43:05,330 And what am I doing here? 933 00:43:05,330 --> 00:43:09,965 I'm running document.querySelector #form .onsubmit. 934 00:43:09,965 --> 00:43:12,340 Onsubmit is yet another event that we've been looking at. 935 00:43:12,340 --> 00:43:14,590 We thought when something is clicked on, that's an event. 936 00:43:14,590 --> 00:43:16,150 When something's moused over, that's an event. 937 00:43:16,150 --> 00:43:18,340 When the DOM content is loaded, that's an event. 938 00:43:18,340 --> 00:43:21,054 When a form is submitted, that's also an event. 939 00:43:21,054 --> 00:43:23,470 And so what's going to happen when this form is submitted? 940 00:43:23,470 --> 00:43:26,880 We're going to run this function, again, passing this function in 941 00:43:26,880 --> 00:43:31,000 to be the value of this onsubmit attribute of my form. 942 00:43:31,000 --> 00:43:34,570 And I'm defining name as a const, because it's not going to change, 943 00:43:34,570 --> 00:43:40,540 equal to document.querySelector #name .value. 944 00:43:40,540 --> 00:43:44,740 Any guesses as to what that's going to extract? 945 00:43:44,740 --> 00:43:47,792 What is querySelector #name .value? 946 00:43:47,792 --> 00:43:48,291 Yeah? 947 00:43:48,291 --> 00:43:50,920 948 00:43:50,920 --> 00:43:51,420 Great. 949 00:43:51,420 --> 00:43:53,920 It's going to be whatever the user typed into that text box, 950 00:43:53,920 --> 00:43:56,050 because that text box had an ID of name. 951 00:43:56,050 --> 00:43:59,070 And so if I querySelect for #name, that's 952 00:43:59,070 --> 00:44:03,120 going to get me just that HTML input field. 953 00:44:03,120 --> 00:44:06,610 And if I get the value of an input field, the value of the input field 954 00:44:06,610 --> 00:44:09,900 is whatever it is the user was typing in to that input field. 955 00:44:09,900 --> 00:44:11,190 And then I'm going to alert. 956 00:44:11,190 --> 00:44:13,148 This is, again, one of those template literals, 957 00:44:13,148 --> 00:44:15,510 those formatted strings, where I'm saying "hello" 958 00:44:15,510 --> 00:44:19,050 and then plugging in the value of that name variable there. 959 00:44:19,050 --> 00:44:22,510 And so I'm going to say hello to whoever typed in their name. 960 00:44:22,510 --> 00:44:29,550 So if I go back to the actual page and open up hello1.html, 961 00:44:29,550 --> 00:44:34,050 if I type in "Brian" and press Submit, it says "Hello, Brian." 962 00:44:34,050 --> 00:44:38,590 If I instead type "Meredith," for example, and press Submit, 963 00:44:38,590 --> 00:44:40,110 then it says, "Hello, Meredith." 964 00:44:40,110 --> 00:44:43,890 And so I'm able to use the contents of the value of the input field 965 00:44:43,890 --> 00:44:47,079 to dynamically create whatever alerts that I wanted to create, in this case. 966 00:44:47,079 --> 00:44:49,370 But I could have done anything with this name variable. 967 00:44:49,370 --> 00:44:54,690 I'm just using JavaScript now to extract information out of the form. 968 00:44:54,690 --> 00:44:56,800 Questions about that so far? 969 00:44:56,800 --> 00:44:57,300 Yeah. 970 00:44:57,300 --> 00:44:58,799 AUDIENCE: So you call it a constant? 971 00:44:58,799 --> 00:45:01,244 But then you're able to do it twice. 972 00:45:01,244 --> 00:45:03,387 Isn't that changing your constant? 973 00:45:03,387 --> 00:45:04,470 SPEAKER 1: Great question. 974 00:45:04,470 --> 00:45:08,974 So it was a const variable, but I was able to use it twice, right? 975 00:45:08,974 --> 00:45:10,890 I typed in my name and it said "hello, Brian," 976 00:45:10,890 --> 00:45:13,350 and then I typed in Meredith's name and then it said "hello, Meredith." 977 00:45:13,350 --> 00:45:14,470 What's going on there? 978 00:45:14,470 --> 00:45:15,630 Why did it let me do that? 979 00:45:15,630 --> 00:45:16,220 Any guesses? 980 00:45:16,220 --> 00:45:19,014 981 00:45:19,014 --> 00:45:20,430 Well, one is that the page reload. 982 00:45:20,430 --> 00:45:20,970 Yes. 983 00:45:20,970 --> 00:45:22,230 Certainly. 984 00:45:22,230 --> 00:45:25,800 Because when the form was submitted, it ended up going to the page again. 985 00:45:25,800 --> 00:45:28,110 But another thing to bear in mind is that const here 986 00:45:28,110 --> 00:45:31,920 is located inside of the scope of the function, which becomes relevant 987 00:45:31,920 --> 00:45:33,400 as well. 988 00:45:33,400 --> 00:45:33,900 All right. 989 00:45:33,900 --> 00:45:35,460 Let's take a look at-- 990 00:45:35,460 --> 00:45:38,370 so we saw now that we can use JavaScript to be able to access 991 00:45:38,370 --> 00:45:39,965 the HTML contents of the page. 992 00:45:39,965 --> 00:45:42,090 Now let's take a look at using JavaScript to modify 993 00:45:42,090 --> 00:45:44,080 the styling of the page as well. 994 00:45:44,080 --> 00:45:48,720 So let's take a look at colors0.html. 995 00:45:48,720 --> 00:45:52,200 I'll show you first what color0.html is going to do. 996 00:45:52,200 --> 00:45:53,684 This web page says "Hello!" 997 00:45:53,684 --> 00:45:55,350 And it's got two buttons at the bottom-- 998 00:45:55,350 --> 00:45:56,610 Red, Blue, and Green. 999 00:45:56,610 --> 00:45:59,470 And when I click on those buttons, Red changes "Hello!" 1000 00:45:59,470 --> 00:46:04,240 to red, Blue changes "Hello!" to be in blue, Green changes it to be in green. 1001 00:46:04,240 --> 00:46:07,240 And so how is that working in terms of the code? 1002 00:46:07,240 --> 00:46:12,660 Well, here in the body of the page, I have a heading that says "Hello," 1003 00:46:12,660 --> 00:46:15,480 then a button whose ID is red, which just says Red; 1004 00:46:15,480 --> 00:46:18,810 a button whose ID is blue, and that button's labeled Blue; 1005 00:46:18,810 --> 00:46:23,250 and a button whose ID is green, and that button is just labeled Green. 1006 00:46:23,250 --> 00:46:26,130 And now what's here inside of the script tag? 1007 00:46:26,130 --> 00:46:28,800 Well, I have document.addEventListener DOMContentLoaded. 1008 00:46:28,800 --> 00:46:30,787 So here is the code that is going to run when 1009 00:46:30,787 --> 00:46:33,870 the DOM is done loading when we're ready to actually do interesting things 1010 00:46:33,870 --> 00:46:35,700 with the content of the site. 1011 00:46:35,700 --> 00:46:40,110 I say, document.querySelector #red onclick, 1012 00:46:40,110 --> 00:46:43,230 meaning when the Red button is clicked, this is the code that should run, 1013 00:46:43,230 --> 00:46:44,770 this following function. 1014 00:46:44,770 --> 00:46:50,100 And so inside of this function, we have document.querySelector #hello 1015 00:46:50,100 --> 00:46:53,775 getting that thing with ID hello, which was that heading that says hello. 1016 00:46:53,775 --> 00:46:55,950 .style gets at its style attribute. 1017 00:46:55,950 --> 00:46:58,890 And then I can modify any of the CSS properties that I had. 1018 00:46:58,890 --> 00:47:01,890 Remember that we had CSS properties for the color of something, 1019 00:47:01,890 --> 00:47:05,160 or the font size of something, or the background for something. 1020 00:47:05,160 --> 00:47:09,570 And any of those CSS properties I can now modify by accessing this .style 1021 00:47:09,570 --> 00:47:12,000 attribute of the HTML element. 1022 00:47:12,000 --> 00:47:13,920 So I'm saying .style .color. 1023 00:47:13,920 --> 00:47:16,110 That's going to be equal to red. 1024 00:47:16,110 --> 00:47:19,590 And likewise, I'm doing the same thing for when I click on Blue. 1025 00:47:19,590 --> 00:47:22,860 Then I change the color of the "Hello!" element to be blue. 1026 00:47:22,860 --> 00:47:27,810 And likewise, when I click on Green, I change the color of that to be green. 1027 00:47:27,810 --> 00:47:31,710 Questions about how that was able to work? 1028 00:47:31,710 --> 00:47:33,900 Anyone see areas for improvement in this code? 1029 00:47:33,900 --> 00:47:38,940 Something that might look suboptimal, at least at first glance? 1030 00:47:38,940 --> 00:47:40,380 Yeah. 1031 00:47:40,380 --> 00:47:47,502 AUDIENCE: [INAUDIBLE] 1032 00:47:47,502 --> 00:47:49,960 SPEAKER 1: Yeah, I have three functions that are all really 1033 00:47:49,960 --> 00:47:51,190 doing the same thing. 1034 00:47:51,190 --> 00:47:54,997 I have a Red button that changes the "Hello!" to be red instead of black 1035 00:47:54,997 --> 00:47:56,830 or whatever it was originally; a Blue button 1036 00:47:56,830 --> 00:47:59,204 that does the same thing; Green that does the same thing. 1037 00:47:59,204 --> 00:48:02,650 And this is happening because querySelector, as we've seen it so far, 1038 00:48:02,650 --> 00:48:06,680 really only allows us to extract the first element that it finds. 1039 00:48:06,680 --> 00:48:09,490 So I'm extracting the Red button and then doing something with, 1040 00:48:09,490 --> 00:48:11,865 extracting the Blue button and doing something with that. 1041 00:48:11,865 --> 00:48:13,697 And these functions are slightly different. 1042 00:48:13,697 --> 00:48:16,030 And so what I'd like is for some way to generalize this, 1043 00:48:16,030 --> 00:48:21,340 to be able to only need to write this code once, and then have it apply 1044 00:48:21,340 --> 00:48:23,170 to all of these different buttons. 1045 00:48:23,170 --> 00:48:25,850 And so there are a number of different ways to do that, 1046 00:48:25,850 --> 00:48:29,290 but we'll take a look at one way right now. 1047 00:48:29,290 --> 00:48:35,230 And so here what we have inside of the DOM Content Loaded section is, 1048 00:48:35,230 --> 00:48:41,050 instead of document.querySelector, I have document.querySelectorAll. 1049 00:48:41,050 --> 00:48:45,130 And what querySelectorAll is going to do is instead of just selecting 1050 00:48:45,130 --> 00:48:48,340 the first thing that matched, as querySelector did, 1051 00:48:48,340 --> 00:48:52,270 querySelectorAll is going to return to me an array of all of the things 1052 00:48:52,270 --> 00:48:54,920 that matched the query that I was trying to perform. 1053 00:48:54,920 --> 00:49:01,090 And so here, I'm querying for anything that has the class Color-Change. 1054 00:49:01,090 --> 00:49:04,510 In particular, as we'll see down below in the HTML contents 1055 00:49:04,510 --> 00:49:07,300 of the page in just a moment, I've given all of these buttons 1056 00:49:07,300 --> 00:49:08,920 the class Color-Change. 1057 00:49:08,920 --> 00:49:11,290 And as a result, when I querySelectorAll for anything 1058 00:49:11,290 --> 00:49:13,150 with the class Color-Change, the result is 1059 00:49:13,150 --> 00:49:17,950 that I'm going to get back an array of all of those different buttons. 1060 00:49:17,950 --> 00:49:21,430 Then after that, I have this .ForEach. 1061 00:49:21,430 --> 00:49:23,650 And so ForEach is a built-in function that we 1062 00:49:23,650 --> 00:49:29,470 can use on JavaScript arrays that allows me to run a function on each element 1063 00:49:29,470 --> 00:49:31,060 inside of that array. 1064 00:49:31,060 --> 00:49:34,060 And so ForEach is another example of a higher order function. 1065 00:49:34,060 --> 00:49:37,840 ForEach is a function that is taking, as input, yet another function that I 1066 00:49:37,840 --> 00:49:39,540 want to do something interesting with. 1067 00:49:39,540 --> 00:49:41,290 And it's a function that is going to take, 1068 00:49:41,290 --> 00:49:45,620 as input, one particular element of that array. 1069 00:49:45,620 --> 00:49:48,370 And so before we go on to seeing what that function actually does, 1070 00:49:48,370 --> 00:49:51,730 let me show you the HTML content of this page. 1071 00:49:51,730 --> 00:49:56,170 So inside of my body, I have this heading that says "Hello!" 1072 00:49:56,170 --> 00:49:57,250 I have three buttons. 1073 00:49:57,250 --> 00:49:59,450 All of them have this class, Color-Change, 1074 00:49:59,450 --> 00:50:02,200 that is going to be the class that allows me to select all of them 1075 00:50:02,200 --> 00:50:02,700 at once. 1076 00:50:02,700 --> 00:50:05,440 By selecting everything that has the class Color-Change, 1077 00:50:05,440 --> 00:50:07,930 I can select all three of those different buttons. 1078 00:50:07,930 --> 00:50:12,970 And then what you'll find is I've added this data-color attribute 1079 00:50:12,970 --> 00:50:14,660 to all of my buttons. 1080 00:50:14,660 --> 00:50:17,410 Now, data-color is not just some attribute 1081 00:50:17,410 --> 00:50:19,990 that is built into all buttons, but rather it's 1082 00:50:19,990 --> 00:50:24,400 an example of a data attribute where, in HTML oftentimes, if I 1083 00:50:24,400 --> 00:50:28,060 want to associate additional data with an HTML element 1084 00:50:28,060 --> 00:50:30,610 that's not displayed on the page, I can put it 1085 00:50:30,610 --> 00:50:33,230 inside of a data attribute with the name of my own choosing 1086 00:50:33,230 --> 00:50:37,840 so long as it begins with data, hyphen, something in order to give that HTML 1087 00:50:37,840 --> 00:50:40,510 element a little more information about itself 1088 00:50:40,510 --> 00:50:44,990 or information that it would need to know for purposes of being used later, 1089 00:50:44,990 --> 00:50:47,020 oftentimes in JavaScript. 1090 00:50:47,020 --> 00:50:49,630 And so what I've done here is I've defined these buttons 1091 00:50:49,630 --> 00:50:51,970 that all have class Color-Change, but they all 1092 00:50:51,970 --> 00:50:57,670 have this color data attribute, data-color, which is equal to the color 1093 00:50:57,670 --> 00:51:00,790 that they should try to turn the text into. 1094 00:51:00,790 --> 00:51:04,490 So this one has data-color red, the Blue button has data-color blue, 1095 00:51:04,490 --> 00:51:07,150 the Green button has data-color green. 1096 00:51:07,150 --> 00:51:10,600 And how do I actually use these data attributes? 1097 00:51:10,600 --> 00:51:14,380 Well, if we look back up here at the JavaScript code, 1098 00:51:14,380 --> 00:51:18,360 when I do this querySelectorAll selecting for all of the buttons, 1099 00:51:18,360 --> 00:51:22,360 or all of the HTML elements that have the class Color-Change, I'm saying, 1100 00:51:22,360 --> 00:51:23,170 ForEach-- 1101 00:51:23,170 --> 00:51:26,620 in other words, run this function on each one of these individual buttons-- 1102 00:51:26,620 --> 00:51:28,300 here is that function. 1103 00:51:28,300 --> 00:51:30,950 That function takes, as input, one of those buttons. 1104 00:51:30,950 --> 00:51:33,950 It's going to first operate on the first button, then the second button, 1105 00:51:33,950 --> 00:51:35,060 and then the third button. 1106 00:51:35,060 --> 00:51:39,760 And we're setting the button.onclick property of each 1107 00:51:39,760 --> 00:51:41,240 to be this new function. 1108 00:51:41,240 --> 00:51:44,160 So this is the function that should run when we click on that button. 1109 00:51:44,160 --> 00:51:48,291 document.querySelector #hello .style .color is the same thing we've seen 1110 00:51:48,291 --> 00:51:48,790 before. 1111 00:51:48,790 --> 00:51:51,123 We're going to take that heading, that "Hello!" heading, 1112 00:51:51,123 --> 00:51:54,280 get at its style attributes, and change the color of its styling. 1113 00:51:54,280 --> 00:51:57,130 And in particular, what color do we want to change its styling to? 1114 00:51:57,130 --> 00:52:00,820 Well, we want to change it to whatever that data-color attribute 1115 00:52:00,820 --> 00:52:02,840 of the button itself was. 1116 00:52:02,840 --> 00:52:05,470 And so we have access to this variable button, 1117 00:52:05,470 --> 00:52:08,890 because the ForEach function will loop over each element in the array 1118 00:52:08,890 --> 00:52:12,280 and let us run a function, passing in just an individual element as input. 1119 00:52:12,280 --> 00:52:14,230 And we called that button. 1120 00:52:14,230 --> 00:52:17,260 And in JavaScript, to access any of the data attributes, 1121 00:52:17,260 --> 00:52:19,950 we use the .dataset property. 1122 00:52:19,950 --> 00:52:24,790 And so by going to button.dataset.color, what that's going to do is it's going 1123 00:52:24,790 --> 00:52:30,010 to take that button, extract its data attributes-- in this case, data-color-- 1124 00:52:30,010 --> 00:52:32,110 and get at one particular attribute. 1125 00:52:32,110 --> 00:52:34,890 In this case, we want the color attribute. 1126 00:52:34,890 --> 00:52:37,330 And so the long story short of what all of this is doing 1127 00:52:37,330 --> 00:52:40,000 is we're selecting for all of the different elements that 1128 00:52:40,000 --> 00:52:42,550 have the Color-Change cloths, which is all the buttons. 1129 00:52:42,550 --> 00:52:45,680 And for each one of those, we're going to run this function that 1130 00:52:45,680 --> 00:52:48,320 sets the onclick property of that button to be 1131 00:52:48,320 --> 00:52:51,260 a function that takes the "Hello!" 1132 00:52:51,260 --> 00:52:55,700 heading and changes its color to be whatever the data-color attribute 1133 00:52:55,700 --> 00:52:57,950 of that button originally was. 1134 00:52:57,950 --> 00:53:03,310 And the result of this is that colors1 behaves exactly the same way as color0. 1135 00:53:03,310 --> 00:53:05,220 They have these Red, Blue, and Green buttons. 1136 00:53:05,220 --> 00:53:07,053 And when I click on individual ones of them, 1137 00:53:07,053 --> 00:53:09,080 it causes the color of that "Hello!" 1138 00:53:09,080 --> 00:53:12,890 heading to change all based on this dataset property. 1139 00:53:12,890 --> 00:53:15,770 And we were able to do that now using just a single function that 1140 00:53:15,770 --> 00:53:19,460 changes the color as opposed to color0, where 1141 00:53:19,460 --> 00:53:24,385 we needed three different functions, one for each of those individual colors. 1142 00:53:24,385 --> 00:53:26,760 Questions about any of the stuff that was happening here? 1143 00:53:26,760 --> 00:53:28,052 So this is a lot of new syntax. 1144 00:53:28,052 --> 00:53:28,552 Yeah? 1145 00:53:28,552 --> 00:53:33,779 AUDIENCE: [INAUDIBLE] 1146 00:53:33,779 --> 00:53:34,820 SPEAKER 1: Good question. 1147 00:53:34,820 --> 00:53:38,600 So what happens if we try to inspect one of these buttons inside of the Chrome 1148 00:53:38,600 --> 00:53:39,470 Inspector? 1149 00:53:39,470 --> 00:53:43,010 So I can do document.querySelector. 1150 00:53:43,010 --> 00:53:46,509 And I'm just going to select for just an individual button for now. 1151 00:53:46,509 --> 00:53:48,800 And remember, the querySelector only returns one thing. 1152 00:53:48,800 --> 00:53:53,690 So even though there are three buttons here inside of the HTML document, 1153 00:53:53,690 --> 00:53:56,180 running querySelector on button is just going 1154 00:53:56,180 --> 00:53:59,930 to return to me the first button, the Red button. 1155 00:53:59,930 --> 00:54:04,492 And if I do onclick, what I get back is that function. 1156 00:54:04,492 --> 00:54:07,700 This document.querySelector #hello is equal to whatever the button's data set 1157 00:54:07,700 --> 00:54:11,270 color is, because I've updated the onclick attribute of that button 1158 00:54:11,270 --> 00:54:13,250 to be that new function. 1159 00:54:13,250 --> 00:54:14,684 Great question. 1160 00:54:14,684 --> 00:54:15,608 Other things? 1161 00:54:15,608 --> 00:54:19,770 1162 00:54:19,770 --> 00:54:20,430 All right. 1163 00:54:20,430 --> 00:54:24,186 So inside of colors1.html, what you've likely noticed now 1164 00:54:24,186 --> 00:54:26,310 is that we have a lot of these different functions. 1165 00:54:26,310 --> 00:54:28,435 Here's a function that doesn't take any parameters. 1166 00:54:28,435 --> 00:54:30,601 Here's another one that doesn't take any parameters. 1167 00:54:30,601 --> 00:54:32,520 Here's one that takes button as a parameter. 1168 00:54:32,520 --> 00:54:34,560 Functions are incredibly common in JavaScript, 1169 00:54:34,560 --> 00:54:36,750 as we've seen already, because we have these callback functions that 1170 00:54:36,750 --> 00:54:38,560 are called whenever events are fired. 1171 00:54:38,560 --> 00:54:42,120 And in the latest versions of JavaScript, ES6 in particular, 1172 00:54:42,120 --> 00:54:44,435 they've introduced a new syntax for functions 1173 00:54:44,435 --> 00:54:46,810 that makes things just a little bit simpler to deal with. 1174 00:54:46,810 --> 00:54:48,810 And so I'll introduce that syntax now, and we'll 1175 00:54:48,810 --> 00:54:52,140 use it for the remainder of the lecture today just to give you a taste for it. 1176 00:54:52,140 --> 00:54:57,160 So inside of colors2.html, which is going to do exactly the same thing, 1177 00:54:57,160 --> 00:55:00,630 we're going to introduce this arrow notation syntax. 1178 00:55:00,630 --> 00:55:03,180 And let me briefly talk about what that arrow notation 1179 00:55:03,180 --> 00:55:06,362 syntax looks like to define what are called arrow functions. 1180 00:55:06,362 --> 00:55:09,070 And then we'll take a closer look at them, actually, in practice. 1181 00:55:09,070 --> 00:55:13,290 And so this is an example of an arrow function that takes no arguments. 1182 00:55:13,290 --> 00:55:17,430 And so in particular, an arrow function is defined without the use of the word 1183 00:55:17,430 --> 00:55:18,360 "function." 1184 00:55:18,360 --> 00:55:22,650 And instead, it just has any arguments the function takes, 1185 00:55:22,650 --> 00:55:27,210 with the just empty parentheses meaning no arguments, followed by equal sign, 1186 00:55:27,210 --> 00:55:32,920 arrow just to be an arrow, meaning, take this as input and then run this code. 1187 00:55:32,920 --> 00:55:35,700 And so this is just ES6's way of defining functions. 1188 00:55:35,700 --> 00:55:37,710 You can use functions the old way just as well. 1189 00:55:37,710 --> 00:55:40,170 And these functions behave very slightly differently, 1190 00:55:40,170 --> 00:55:42,790 as we'll see later on today, but are, in fact, 1191 00:55:42,790 --> 00:55:48,089 just a more succinct, more compact way of writing functions in ES6. 1192 00:55:48,089 --> 00:55:50,130 And so this is a function that takes no arguments 1193 00:55:50,130 --> 00:55:51,519 and just alerts "Hello, world!" 1194 00:55:51,519 --> 00:55:53,310 in much the same way as that hello function 1195 00:55:53,310 --> 00:55:55,770 that we saw earlier this evening did. 1196 00:55:55,770 --> 00:56:00,420 And this, for example, is a function that takes, as input, a variable 1197 00:56:00,420 --> 00:56:04,290 x as its input and then, in the body of the function, alerts whatever 1198 00:56:04,290 --> 00:56:06,850 the contents of x was, for example. 1199 00:56:06,850 --> 00:56:10,290 And you can see these functions represented even more succinctly. 1200 00:56:10,290 --> 00:56:13,920 If there's a function that's just taking input and returning a value almost 1201 00:56:13,920 --> 00:56:17,130 right away, you can, in fact, represent a function as simply as this, 1202 00:56:17,130 --> 00:56:20,130 where you have an x, arrow, x times 2. 1203 00:56:20,130 --> 00:56:23,850 This is a function defined in ES6 that takes, as input, 1204 00:56:23,850 --> 00:56:27,840 a number x and returns whatever x times 2 is. 1205 00:56:27,840 --> 00:56:30,555 And no curly braces required in that case either. 1206 00:56:30,555 --> 00:56:33,180 So these are just more succinct ways of representing functions. 1207 00:56:33,180 --> 00:56:35,220 If you take a look at modern JavaScript code, 1208 00:56:35,220 --> 00:56:36,730 you'll see syntax like this a lot. 1209 00:56:36,730 --> 00:56:39,870 So I just wanted to introduce it to you to give you a feel for what it is 1210 00:56:39,870 --> 00:56:40,770 and how it works. 1211 00:56:40,770 --> 00:56:43,380 And so if we were to take that color example 1212 00:56:43,380 --> 00:56:47,550 and rewrite it using arrow functions, it would just look something like this. 1213 00:56:47,550 --> 00:56:52,800 Instead of after DOMContentLoaded function and then the curly braces, 1214 00:56:52,800 --> 00:56:56,370 we would just say, parentheses, meaning this takes no arguments; 1215 00:56:56,370 --> 00:57:00,240 followed by equal sign, arrow; and then the contents of what 1216 00:57:00,240 --> 00:57:02,610 should happen when the DOM contents is loaded. 1217 00:57:02,610 --> 00:57:04,650 In the example in the old example, when we 1218 00:57:04,650 --> 00:57:08,610 were running that ForEach function and we had a function that took, 1219 00:57:08,610 --> 00:57:13,440 as input, the button, and then ran all of this code in here, 1220 00:57:13,440 --> 00:57:17,250 in the new example with arrow functions, we would write that as button-- 1221 00:57:17,250 --> 00:57:19,560 that's the input-- then arrow. 1222 00:57:19,560 --> 00:57:21,000 So button is the input. 1223 00:57:21,000 --> 00:57:24,450 And then this is what should happen in the body of that function. 1224 00:57:24,450 --> 00:57:28,290 When the button is clicked, then run a new function that takes no arguments. 1225 00:57:28,290 --> 00:57:33,420 And then runs this code as a result. So colors1 and colors2 are effectively 1226 00:57:33,420 --> 00:57:34,750 doing the same thing here. 1227 00:57:34,750 --> 00:57:37,800 We're just using the new ES6 arrow function notation 1228 00:57:37,800 --> 00:57:40,740 to achieve the same thing in just a slightly more concise way. 1229 00:57:40,740 --> 00:57:42,780 And it's just good to see examples of both, 1230 00:57:42,780 --> 00:57:45,690 so that you know that both are perfectly reasonable ways of writing 1231 00:57:45,690 --> 00:57:47,940 these functions. 1232 00:57:47,940 --> 00:57:51,580 Questions about anything so far? 1233 00:57:51,580 --> 00:57:52,080 OK. 1234 00:57:52,080 --> 00:57:55,870 We'll take a look at one last example before we take a short break. 1235 00:57:55,870 --> 00:57:59,190 We're going to take a look at colors3. 1236 00:57:59,190 --> 00:58:01,500 And so in colors3, what you'll notice is-- 1237 00:58:01,500 --> 00:58:03,030 I'll show you how it works first. 1238 00:58:03,030 --> 00:58:03,960 It says "Hello!" 1239 00:58:03,960 --> 00:58:06,240 And instead of three buttons, we have a dropdown box. 1240 00:58:06,240 --> 00:58:07,530 It starts off as black. 1241 00:58:07,530 --> 00:58:09,305 We also have red, blue, and green. 1242 00:58:09,305 --> 00:58:12,180 And what this dropdown box will do is whenever I select a new color-- 1243 00:58:12,180 --> 00:58:16,350 I select red, for instance-- then it changes the contents to red. 1244 00:58:16,350 --> 00:58:17,807 Blue changes it to blue. 1245 00:58:17,807 --> 00:58:18,890 Green changes it to green. 1246 00:58:18,890 --> 00:58:20,190 So slightly different. 1247 00:58:20,190 --> 00:58:23,860 But we'll see how that's implemented as well just to give you another example. 1248 00:58:23,860 --> 00:58:26,785 So in colors3.html, I have a heading. 1249 00:58:26,785 --> 00:58:27,660 It just says "Hello!" 1250 00:58:27,660 --> 00:58:28,830 Same as before. 1251 00:58:28,830 --> 00:58:31,680 Instead of buttons, I have a select dropdown. 1252 00:58:31,680 --> 00:58:33,900 Select id is color-change. 1253 00:58:33,900 --> 00:58:36,300 And I have all these individual options. 1254 00:58:36,300 --> 00:58:39,390 Each option is an option in that dropdown list. 1255 00:58:39,390 --> 00:58:41,580 What's enclosed in between the option tags 1256 00:58:41,580 --> 00:58:44,820 is the actual text of the option, which would show up to the user. 1257 00:58:44,820 --> 00:58:46,381 Each one also has a value. 1258 00:58:46,381 --> 00:58:49,005 And that value I'm going to use JavaScript in order to extract. 1259 00:58:49,005 --> 00:58:51,840 So the value of each is just whatever the actual string 1260 00:58:51,840 --> 00:58:57,390 of the color that I want to change "Hello!" to be in is going to be. 1261 00:58:57,390 --> 00:59:00,510 And now inside of the script contents of the page, 1262 00:59:00,510 --> 00:59:03,600 when the page is done loading, here's what should run. 1263 00:59:03,600 --> 00:59:06,600 Document.querySelector color-change. 1264 00:59:06,600 --> 00:59:09,450 So color-change is that select dropdown. 1265 00:59:09,450 --> 00:59:12,970 And onchange, as you might guess, is yet another event. 1266 00:59:12,970 --> 00:59:16,470 So onchange is the event that gets fired when I change my selection 1267 00:59:16,470 --> 00:59:19,040 in the dropdown box of the Select menu. 1268 00:59:19,040 --> 00:59:22,540 And when that happens, I'm going to run this function, which gets at "Hello!" 1269 00:59:22,540 --> 00:59:26,770 and change style.color to be this .value. 1270 00:59:26,770 --> 00:59:29,850 And so the only really new thing here, aside from the onchange event, 1271 00:59:29,850 --> 00:59:31,850 which should hopefully be pretty straightforward 1272 00:59:31,850 --> 00:59:35,770 if you've seen examples of other events already, is this keyword "this." 1273 00:59:35,770 --> 00:59:38,070 And what does "this" refer to? 1274 00:59:38,070 --> 00:59:42,640 Well, "this" will, generally speaking, refer to whatever value 1275 00:59:42,640 --> 00:59:45,140 this function is being operated upon. 1276 00:59:45,140 --> 00:59:50,540 And so in this case, "this" refers to document.querySelector color-change-- 1277 00:59:50,540 --> 00:59:54,010 in other words, what I got when I extracted out 1278 00:59:54,010 --> 00:59:57,790 that color-change ID, because I'm setting this function 1279 00:59:57,790 --> 01:00:00,760 to be this onchange function, what happens when 1280 01:00:00,760 --> 01:00:04,000 I change the color-change dropdown. 1281 01:00:04,000 --> 01:00:06,580 And so this is whatever that select dropdown is. 1282 01:00:06,580 --> 01:00:09,580 And so if I take that select dropdown and get at its value, 1283 01:00:09,580 --> 01:00:12,430 that will be whatever the color is. 1284 01:00:12,430 --> 01:00:16,270 And this is a little more sophisticated than you'll need to really worry about 1285 01:00:16,270 --> 01:00:17,950 for purposes of just this class. 1286 01:00:17,950 --> 01:00:21,940 But the way "this" knows what value it should be bound to, so to speak, 1287 01:00:21,940 --> 01:00:24,430 what value "this" should take on is based 1288 01:00:24,430 --> 01:00:28,180 on the function in which it is defined. 1289 01:00:28,180 --> 01:00:33,670 And the long story short of it is that "this" will only be bound to the thing 1290 01:00:33,670 --> 01:00:36,554 that you're calling the function on if you are using functions 1291 01:00:36,554 --> 01:00:39,220 in the traditional functions without actually explicitly writing 1292 01:00:39,220 --> 01:00:40,180 the word "function." 1293 01:00:40,180 --> 01:00:43,540 If you use arrow functions, then "this" will instead 1294 01:00:43,540 --> 01:00:48,580 be bound to whatever "this" was bound to in the code that 1295 01:00:48,580 --> 01:00:50,710 was enclosing that arrow function. 1296 01:00:50,710 --> 01:00:53,920 So long story short, doing "this," for instance, 1297 01:00:53,920 --> 01:00:56,950 would not produce the same effects, because "this" would no longer 1298 01:00:56,950 --> 01:01:00,610 be bound to the color-change dropdown. 1299 01:01:00,610 --> 01:01:02,890 It's this keyword function and defining a function 1300 01:01:02,890 --> 01:01:06,910 in the traditional way that allows "this" to be bound to the thing 1301 01:01:06,910 --> 01:01:08,800 that I'm actually trying to modify. 1302 01:01:08,800 --> 01:01:11,860 And so as you go about experimenting with functions 1303 01:01:11,860 --> 01:01:15,010 and maybe writing some functions this way and some using arrow functions, 1304 01:01:15,010 --> 01:01:17,920 you may run into being tripped up by when "this" takes 1305 01:01:17,920 --> 01:01:20,260 on one value as opposed to another. 1306 01:01:20,260 --> 01:01:24,040 A good way to begin to debug this, again, is just to use the debugger. 1307 01:01:24,040 --> 01:01:26,777 And we'll see more examples of that later. 1308 01:01:26,777 --> 01:01:28,360 But for now, we'll take a short break. 1309 01:01:28,360 --> 01:01:31,300 And when we come back, we'll take a look at more examples of using JavaScript. 1310 01:01:31,300 --> 01:01:33,820 And then we'll integrate JavaScript back in with Python 1311 01:01:33,820 --> 01:01:36,250 to build dynamic web applications in Flask, 1312 01:01:36,250 --> 01:01:39,100 but use both Python and JavaScript as well. 1313 01:01:39,100 --> 01:01:41,721 But all that in a couple minutes. 1314 01:01:41,721 --> 01:01:42,220 OK. 1315 01:01:42,220 --> 01:01:42,790 Welcome back. 1316 01:01:42,790 --> 01:01:44,650 So so far, we've been taking a look at JavaScript, 1317 01:01:44,650 --> 01:01:46,441 looking at ways that we can use it in order 1318 01:01:46,441 --> 01:01:50,110 to manipulate the DOM by editing elements that exist there already 1319 01:01:50,110 --> 01:01:54,370 or by reading elements and values from dropdown boxes and input fields 1320 01:01:54,370 --> 01:01:56,320 in order to do interesting and useful things. 1321 01:01:56,320 --> 01:01:58,780 What we'll take a look at now is yet another example 1322 01:01:58,780 --> 01:02:00,820 of how we can actually add things to the DOM, 1323 01:02:00,820 --> 01:02:03,040 how we can add to the contents of the web page, 1324 01:02:03,040 --> 01:02:05,980 adding elements that weren't there before in order to do 1325 01:02:05,980 --> 01:02:08,012 interesting or useful things as well. 1326 01:02:08,012 --> 01:02:10,720 And so I'll show you what we're going to try to build up towards, 1327 01:02:10,720 --> 01:02:13,594 and then we'll look at the code that'll actually allow us to do that. 1328 01:02:13,594 --> 01:02:16,660 So open up tasks0.html. 1329 01:02:16,660 --> 01:02:21,490 And what tasks0.html is is it's a simple to-do list application, 1330 01:02:21,490 --> 01:02:24,290 where I can keep track of different tasks that I need to perform. 1331 01:02:24,290 --> 01:02:26,840 So here's a thing to do. 1332 01:02:26,840 --> 01:02:30,250 And when I click Submit, it adds "thing to do" as one of my tasks. 1333 01:02:30,250 --> 01:02:33,380 And I add "another thing," and I click Submit. 1334 01:02:33,380 --> 01:02:35,470 There's another thing that I need to do. 1335 01:02:35,470 --> 01:02:38,637 And it will just continue to maintain this ever-growing list of tasks 1336 01:02:38,637 --> 01:02:41,470 that I need to complete based on what I type into the New Task input 1337 01:02:41,470 --> 01:02:45,192 field and then clicking on the Submit button to add that to the list of tasks 1338 01:02:45,192 --> 01:02:46,150 that I need to perform. 1339 01:02:46,150 --> 01:02:49,090 And all of this is just happening using JavaScript. 1340 01:02:49,090 --> 01:02:51,550 So let's take a look at the code that we would 1341 01:02:51,550 --> 01:02:53,650 need in order to make that happen. 1342 01:02:53,650 --> 01:02:58,080 Inside the body of the HTML so far, we have 1343 01:02:58,080 --> 01:03:01,000 a heading that just says "Tasks" at the top, then a UL, 1344 01:03:01,000 --> 01:03:04,251 or an unordered list, whose ID is task, just so we can reference it later. 1345 01:03:04,251 --> 01:03:06,250 And to begin with, that unordered list is empty. 1346 01:03:06,250 --> 01:03:09,250 It has no list items inside of it, which seems sort of strange, 1347 01:03:09,250 --> 01:03:11,560 because in all of the unordered lists or ordered 1348 01:03:11,560 --> 01:03:13,810 lists we've seen before, they've had within them 1349 01:03:13,810 --> 01:03:17,260 li, list item elements, that define the contents of the actual list. 1350 01:03:17,260 --> 01:03:20,070 But to begin with, we have no tasks to start out with, 1351 01:03:20,070 --> 01:03:21,850 and so we need to start with an empty list 1352 01:03:21,850 --> 01:03:26,040 and wait for things to be added before we can populate that unordered list. 1353 01:03:26,040 --> 01:03:29,080 And then I have a form, whose ID is new-task. 1354 01:03:29,080 --> 01:03:31,480 And inside that form, I have two parts to the form. 1355 01:03:31,480 --> 01:03:33,110 One is just an input field. 1356 01:03:33,110 --> 01:03:35,830 Its type is text, because I'm going to be typing in the task. 1357 01:03:35,830 --> 01:03:38,020 Its placeholder is just New Task. 1358 01:03:38,020 --> 01:03:41,330 And then I have this submit input field, which is just going to be that button. 1359 01:03:41,330 --> 01:03:44,450 When I click on it, it will cause the task to be submitted. 1360 01:03:44,450 --> 01:03:48,490 So what is the actual JavaScript code now that makes all of this happen? 1361 01:03:48,490 --> 01:03:53,240 So when the DOM content is loaded, here is what I'm ultimately doing. 1362 01:03:53,240 --> 01:03:55,600 Let's take a look at this code. 1363 01:03:55,600 --> 01:03:59,050 So document.querySelector New-Task. 1364 01:03:59,050 --> 01:04:02,050 New-Task is the ID of that form, the form that contains the input 1365 01:04:02,050 --> 01:04:04,030 field and the button for submission. 1366 01:04:04,030 --> 01:04:06,850 When I submit the form, here is the function 1367 01:04:06,850 --> 01:04:09,640 that should run-- all of this code enclosed in curly braces. 1368 01:04:09,640 --> 01:04:14,429 I'm creating a constant variable, a constant inside of this function, 1369 01:04:14,429 --> 01:04:15,970 at least-- it's not going to change-- 1370 01:04:15,970 --> 01:04:17,500 called li. 1371 01:04:17,500 --> 01:04:21,930 And I'm setting that equal to document.createElement li. 1372 01:04:21,930 --> 01:04:24,550 So I'm creating a new element, and the tag of that element 1373 01:04:24,550 --> 01:04:27,280 is going to be an li tag, a list item tag. 1374 01:04:27,280 --> 01:04:33,020 And then I'm setting li's inner HTML to be whatever the task's value is. 1375 01:04:33,020 --> 01:04:35,950 Remember, the task here is the ID of that input field. 1376 01:04:35,950 --> 01:04:38,680 And extracting its value will get at to mean all of the text 1377 01:04:38,680 --> 01:04:41,080 that the user typed into that input field. 1378 01:04:41,080 --> 01:04:46,520 And now, once I have this list item-- it's a new list item element and its 1379 01:04:46,520 --> 01:04:48,640 inner HTML is whatever was inside that task-- 1380 01:04:48,640 --> 01:04:51,070 I need to now actually take that new element 1381 01:04:51,070 --> 01:04:53,290 and put it into the website somewhere, because I've 1382 01:04:53,290 --> 01:04:56,380 created the element in the document, but I haven't yet 1383 01:04:56,380 --> 01:05:01,150 told JavaScript where inside the DOM tree, where inside the page should 1384 01:05:01,150 --> 01:05:02,770 this new list element go. 1385 01:05:02,770 --> 01:05:06,340 And so what I'll do is document.querySelector Tasks, 1386 01:05:06,340 --> 01:05:09,640 getting the thing with ID Tasks, which is that unordered list. 1387 01:05:09,640 --> 01:05:11,170 And append to it. 1388 01:05:11,170 --> 01:05:13,624 And these HTML elements have all sorts of properties 1389 01:05:13,624 --> 01:05:15,540 that you can look up in terms of what they do. 1390 01:05:15,540 --> 01:05:19,120 Append just happens to be one that adds a new thing to the end of it. 1391 01:05:19,120 --> 01:05:23,470 And I can append to it li, which is this variable that I created here. 1392 01:05:23,470 --> 01:05:26,537 And that's going to actually add the new item to the task list. 1393 01:05:26,537 --> 01:05:28,870 And afterwards, we're going to do a couple other things. 1394 01:05:28,870 --> 01:05:32,410 We're going to select that Task input field, set 1395 01:05:32,410 --> 01:05:33,739 its value to the empty string. 1396 01:05:33,739 --> 01:05:35,530 And so all that's going to do is it's going 1397 01:05:35,530 --> 01:05:38,327 to take the input field that I started out with, 1398 01:05:38,327 --> 01:05:39,660 and it's just going to clear it. 1399 01:05:39,660 --> 01:05:41,826 So that I've already typed the task, the input field 1400 01:05:41,826 --> 01:05:44,020 should clear now, because I've already submitted it. 1401 01:05:44,020 --> 01:05:45,820 And then return false. 1402 01:05:45,820 --> 01:05:49,520 So normally when you submit a form, the default behavior for submitting a form 1403 01:05:49,520 --> 01:05:51,660 is that I'm submitting a form to some other website 1404 01:05:51,660 --> 01:05:53,320 and it's going to try and load that new website. 1405 01:05:53,320 --> 01:05:55,028 And if I don't specify, it's going to try 1406 01:05:55,028 --> 01:05:58,390 and reload the same page again by trying to submit the form to it. 1407 01:05:58,390 --> 01:06:02,650 return false stops the form from submitting to some other website, 1408 01:06:02,650 --> 01:06:06,850 from trying to reload some new page, because I want to stay on the same page 1409 01:06:06,850 --> 01:06:08,830 when I'm done submitting this form. 1410 01:06:08,830 --> 01:06:11,110 And so we create the new element, we set its contents 1411 01:06:11,110 --> 01:06:15,424 to be whatever the task is, add it to my list of tasks, clear the input field, 1412 01:06:15,424 --> 01:06:17,590 and then stop the form, ultimately, from submitting. 1413 01:06:17,590 --> 01:06:22,720 And that's what allows us to get this behavior, where we have a list of tasks 1414 01:06:22,720 --> 01:06:25,386 and I can add more tasks to it. 1415 01:06:25,386 --> 01:06:28,510 Now, there are certainly areas where I could improve upon this application. 1416 01:06:28,510 --> 01:06:30,490 Right now if I just click Submit over and over, 1417 01:06:30,490 --> 01:06:33,409 I can keep submitting blank elements again and again. 1418 01:06:33,409 --> 01:06:35,450 So maybe I'd like to prevent that from happening. 1419 01:06:35,450 --> 01:06:39,370 I'd like to make it so that I can't submit anything unless I've actually 1420 01:06:39,370 --> 01:06:42,290 typed text into this New Task field. 1421 01:06:42,290 --> 01:06:45,620 And so how might I go about doing that? 1422 01:06:45,620 --> 01:06:50,410 Let's take a look now at tasks1.html, which is similar 1423 01:06:50,410 --> 01:06:55,160 but we've added some additional JavaScript code. 1424 01:06:55,160 --> 01:06:59,570 So up here, the first thing that I do is get the Submit button-- 1425 01:06:59,570 --> 01:07:01,819 whose ID is Submit, I've given it the ID Submit-- 1426 01:07:01,819 --> 01:07:03,610 and I'm setting one of its HTML properties. 1427 01:07:03,610 --> 01:07:07,854 I can edit any of the HTML properties of an HTML element using JavaScript. 1428 01:07:07,854 --> 01:07:10,270 And one property that's going to prove particularly useful 1429 01:07:10,270 --> 01:07:12,429 here is the disabled property of a button 1430 01:07:12,429 --> 01:07:15,220 that just determines whether or not that button is disabled or not, 1431 01:07:15,220 --> 01:07:16,740 whether or not I can click on it. 1432 01:07:16,740 --> 01:07:19,480 And so I'm setting the disabled property to true. 1433 01:07:19,480 --> 01:07:22,900 And now I have document.querySelector Task-- 1434 01:07:22,900 --> 01:07:24,610 again, that's the input field-- 1435 01:07:24,610 --> 01:07:25,960 onkeyup. 1436 01:07:25,960 --> 01:07:28,210 When I press a key, when I lift that key up, 1437 01:07:28,210 --> 01:07:32,020 I've typed in text now, and so what should happen when I lift up that key? 1438 01:07:32,020 --> 01:07:35,540 Well, now I've typed in text into the input field, 1439 01:07:35,540 --> 01:07:39,610 and so the Submit field's disabled field can now be false. 1440 01:07:39,610 --> 01:07:43,300 Because I don't want the Submit button to be disabled. 1441 01:07:43,300 --> 01:07:45,710 And then onsubmit works effectively the same way. 1442 01:07:45,710 --> 01:07:47,710 When I actually click the Submit button, I still 1443 01:07:47,710 --> 01:07:50,650 want to add that new task to my list of tasks. 1444 01:07:50,650 --> 01:07:54,380 But in particular, in addition to clearing the input field, 1445 01:07:54,380 --> 01:07:56,440 I also want to disable the button again. 1446 01:07:56,440 --> 01:07:59,940 So I querySelect for the button, which has ID submit. 1447 01:07:59,940 --> 01:08:04,540 And I set its disabled property to be true instead of false. 1448 01:08:04,540 --> 01:08:09,850 And so the result of that is that I have this list of tasks. 1449 01:08:09,850 --> 01:08:13,510 I can start typing in one task here. 1450 01:08:13,510 --> 01:08:16,726 And notice that the Submit button is disabled. 1451 01:08:16,726 --> 01:08:19,100 I can't click the Submit button and submit an empty task. 1452 01:08:19,100 --> 01:08:22,060 And it's not until I type in a second task 1453 01:08:22,060 --> 01:08:25,880 that I can actually click on the Submit button and submit yet another task. 1454 01:08:25,880 --> 01:08:29,620 So that allows me to manipulate the HTML attributes of the Submit button, 1455 01:08:29,620 --> 01:08:31,899 setting its disabled property to true or false 1456 01:08:31,899 --> 01:08:33,910 depending on what I want it to be. 1457 01:08:33,910 --> 01:08:36,063 Anyone spot a potential bug with my implementation? 1458 01:08:36,063 --> 01:08:37,479 An area where that might go wrong? 1459 01:08:37,479 --> 01:08:38,465 Yeah? 1460 01:08:38,465 --> 01:08:43,356 AUDIENCE: [INAUDIBLE] 1461 01:08:43,356 --> 01:08:44,439 SPEAKER 1: Great question. 1462 01:08:44,439 --> 01:08:45,670 If I-- or great answer. 1463 01:08:45,670 --> 01:08:49,000 If I type something, some text, and then I erase it, 1464 01:08:49,000 --> 01:08:51,760 and now I've gone back to the empty task field, 1465 01:08:51,760 --> 01:08:54,670 now the Submit button is still active, and I can still submit a task. 1466 01:08:54,670 --> 01:08:55,878 Why was I allowed to do that? 1467 01:08:55,878 --> 01:08:58,585 1468 01:08:58,585 --> 01:08:59,960 Yeah, because I made a keystroke. 1469 01:08:59,960 --> 01:09:02,750 And technically, hitting the Delete button is still a keystroke. 1470 01:09:02,750 --> 01:09:04,064 And when I lift the Delete button, that's 1471 01:09:04,064 --> 01:09:07,370 a keyup, as well as all the other characters that I was typing before it. 1472 01:09:07,370 --> 01:09:10,160 So I'm going to need something a little more robust in order 1473 01:09:10,160 --> 01:09:12,109 to allow myself to deal with this situation. 1474 01:09:12,109 --> 01:09:16,435 And so we'll go ahead and fix this bug inside of tasks2.html. 1475 01:09:16,435 --> 01:09:19,100 And so here, onkeyup. 1476 01:09:19,100 --> 01:09:22,800 When I lift up the key, when I type in a new key into the input field, 1477 01:09:22,800 --> 01:09:23,930 I went to check. 1478 01:09:23,930 --> 01:09:28,670 Let me query for the task input field, get at its adds value, 1479 01:09:28,670 --> 01:09:32,720 and I can use the .length property of a string in JavaScript that just gets me 1480 01:09:32,720 --> 01:09:34,490 the length of how long a string is. 1481 01:09:34,490 --> 01:09:37,319 And if the length of the string is greater than 0-- in other words, 1482 01:09:37,319 --> 01:09:40,220 there are more than zero characters inside the input field-- 1483 01:09:40,220 --> 01:09:43,029 then yeah, I don't want the button to be disabled. 1484 01:09:43,029 --> 01:09:45,090 So disabled equals false. 1485 01:09:45,090 --> 01:09:49,100 Otherwise, if there were zero characters inside the input field, 1486 01:09:49,100 --> 01:09:53,200 then I want the disabled field to be true instead. 1487 01:09:53,200 --> 01:09:58,250 And so the result of that is that the Submit button is disabled. 1488 01:09:58,250 --> 01:10:00,380 I can add one task. 1489 01:10:00,380 --> 01:10:01,639 It's disabled again. 1490 01:10:01,639 --> 01:10:04,430 If I start typing in a second task but then delete, delete, delete, 1491 01:10:04,430 --> 01:10:06,920 delete, once I empty out the whole thing, 1492 01:10:06,920 --> 01:10:08,810 now the Submit button is disabled again. 1493 01:10:08,810 --> 01:10:11,390 It's enabled here, and now it's disabled. 1494 01:10:11,390 --> 01:10:14,240 And so this allows me to dynamically, using conditions and using 1495 01:10:14,240 --> 01:10:18,800 event handlers, begin to make my user interface better and better 1496 01:10:18,800 --> 01:10:21,380 by making it dynamic, making it responsive to what 1497 01:10:21,380 --> 01:10:23,630 it is that the user is actually doing. 1498 01:10:23,630 --> 01:10:26,224 Questions about anything so far? 1499 01:10:26,224 --> 01:10:28,390 So a couple of people have asked about jQuery, which 1500 01:10:28,390 --> 01:10:30,120 is a library you may be familiar with. 1501 01:10:30,120 --> 01:10:32,578 We're not going to talk about it at all in today's lecture, 1502 01:10:32,578 --> 01:10:35,000 but jQuery just happens to be a JavaScript library that 1503 01:10:35,000 --> 01:10:37,992 is commonly used in order to do similar things, 1504 01:10:37,992 --> 01:10:39,950 so the things we've been seeing so far in terms 1505 01:10:39,950 --> 01:10:42,680 of selecting, and updating HTML elements, 1506 01:10:42,680 --> 01:10:44,950 and updating, and modifying the DOM. 1507 01:10:44,950 --> 01:10:47,000 Ultimately, jQuery's become slightly less 1508 01:10:47,000 --> 01:10:50,540 popular in recent years as JavaScript itself has become more 1509 01:10:50,540 --> 01:10:54,110 and more powerful without the need to use an external library like jQuery. 1510 01:10:54,110 --> 01:10:56,990 Using things like querySelector and querySelectorAll, 1511 01:10:56,990 --> 01:10:59,210 you can do much of the same stuff that jQuery 1512 01:10:59,210 --> 01:11:02,930 was good with relative efficiency. 1513 01:11:02,930 --> 01:11:06,980 And so jQuery, as a relatively large library that takes time in order 1514 01:11:06,980 --> 01:11:09,260 to load and might slow things down a little bit, 1515 01:11:09,260 --> 01:11:11,810 is becoming slightly less popular, although you will still 1516 01:11:11,810 --> 01:11:12,950 see it in many instances. 1517 01:11:12,950 --> 01:11:16,380 In fact, if you are using Bootstrap for any of your projects, for example, 1518 01:11:16,380 --> 01:11:19,100 and are using any of Bootstrap's JavaScript features, 1519 01:11:19,100 --> 01:11:21,860 Bootstrap is still using jQuery as a library in order 1520 01:11:21,860 --> 01:11:24,410 to do most of its JavaScript work. 1521 01:11:24,410 --> 01:11:28,010 And so you might stumble across jQuery-like syntax 1522 01:11:28,010 --> 01:11:31,220 if you're looking at either Bootstrap's JavaScript or JavaScript 1523 01:11:31,220 --> 01:11:33,131 on some other web pages or other libraries. 1524 01:11:33,131 --> 01:11:35,130 And so just wanted to make you all aware of what 1525 01:11:35,130 --> 01:11:39,302 jQuery is even though we're not going to look at it too much in today's lecture. 1526 01:11:39,302 --> 01:11:41,510 We'll take a look, though, at a couple other features 1527 01:11:41,510 --> 01:11:43,700 that are built into JavaScript itself. 1528 01:11:43,700 --> 01:11:49,430 In particular, let's take a look at interval.html. 1529 01:11:49,430 --> 01:11:53,840 And so interval.html, inside the body, just has a heading that says counter. 1530 01:11:53,840 --> 01:11:55,520 There's no longer a button. 1531 01:11:55,520 --> 01:11:58,490 But let's take a look at what's happening inside of the actual script 1532 01:11:58,490 --> 01:12:00,200 contents. 1533 01:12:00,200 --> 01:12:03,800 When the DOM content is loaded, I'm calling the setInterval function, 1534 01:12:03,800 --> 01:12:05,840 a function built into JavaScript. 1535 01:12:05,840 --> 01:12:08,190 And the setInterval function takes two arguments. 1536 01:12:08,190 --> 01:12:10,280 The first is another function-- 1537 01:12:10,280 --> 01:12:12,350 in this case, count, which is a function. 1538 01:12:12,350 --> 01:12:15,140 And the second is the interval at which I should call it. 1539 01:12:15,140 --> 01:12:19,490 And so setInterval count 1,000 is saying, call this count function 1540 01:12:19,490 --> 01:12:21,830 every 1,000 milliseconds, every second. 1541 01:12:21,830 --> 01:12:24,955 And the count function is the same as the count function we've seen before. 1542 01:12:24,955 --> 01:12:27,859 It takes this counter value and it increments it every time. 1543 01:12:27,859 --> 01:12:29,900 And so the result of this is that without needing 1544 01:12:29,900 --> 01:12:35,330 to click on any buttons, if I open up interval.html, it'll start at zero 1545 01:12:35,330 --> 01:12:38,459 and will count one, two, three, four, counting one number per second 1546 01:12:38,459 --> 01:12:40,250 without my needing to click on any buttons. 1547 01:12:40,250 --> 01:12:42,380 JavaScript is just running my count function 1548 01:12:42,380 --> 01:12:44,532 one time every 1,000 milliseconds. 1549 01:12:44,532 --> 01:12:46,490 And so that can be useful if you want something 1550 01:12:46,490 --> 01:12:48,890 happening on a recurring basis. 1551 01:12:48,890 --> 01:12:51,890 But another thing you might notice about all of the JavaScript web pages 1552 01:12:51,890 --> 01:12:54,977 that we've had so far is that they aren't able to remember anything. 1553 01:12:54,977 --> 01:12:56,810 If I'm looking at my website right now, it's 1554 01:12:56,810 --> 01:13:00,080 counting 23, 24, 25, and it's continuing counting. 1555 01:13:00,080 --> 01:13:03,140 But if it gets to 28, and I close the page, 1556 01:13:03,140 --> 01:13:07,340 and then I open interval.html again, for instance, now I'm back to zero. 1557 01:13:07,340 --> 01:13:11,180 It reset the entire page because all of that updating of the variables gets 1558 01:13:11,180 --> 01:13:12,720 lost when I close that page. 1559 01:13:12,720 --> 01:13:15,620 So what are some ways that I can get around that and actually store 1560 01:13:15,620 --> 01:13:17,990 information such that if I close the page 1561 01:13:17,990 --> 01:13:22,430 and open a page later on today or in the next day, that I can still 1562 01:13:22,430 --> 01:13:25,250 retain some information, some memory of some state? 1563 01:13:25,250 --> 01:13:27,770 In order to do that, we'll use a feature of JavaScript 1564 01:13:27,770 --> 01:13:30,530 that many modern web browsers support called local storage, which 1565 01:13:30,530 --> 01:13:34,820 allows us to store things inside of the local machine 1566 01:13:34,820 --> 01:13:37,970 such that even if I close the page and reload the page later, 1567 01:13:37,970 --> 01:13:41,430 I still have access to that same local storage. 1568 01:13:41,430 --> 01:13:45,680 So let's take a look now at storage.html. 1569 01:13:45,680 --> 01:13:48,500 So storage has a counter and a button that says Click Here, 1570 01:13:48,500 --> 01:13:51,110 much like the examples we've seen that are counting before. 1571 01:13:51,110 --> 01:13:53,380 And what's happening inside of it? 1572 01:13:53,380 --> 01:13:58,040 And the first thing I'm doing is I'm doing localStorage.getItem, counter. 1573 01:13:58,040 --> 01:14:00,830 So localStorage is just a variable I have access to. 1574 01:14:00,830 --> 01:14:02,930 And it has two functions that I'm likely going 1575 01:14:02,930 --> 01:14:07,640 to want to use-- getItem, which tries to get an item for me from local storage; 1576 01:14:07,640 --> 01:14:11,210 and setItem, which sets the value of something in local storage. 1577 01:14:11,210 --> 01:14:13,880 And so I'm trying to get the item called counter. 1578 01:14:13,880 --> 01:14:15,800 And exclamation point just means "not." 1579 01:14:15,800 --> 01:14:17,370 So if not getItem counter-- 1580 01:14:17,370 --> 01:14:19,880 in other words, there was nothing called counter-- 1581 01:14:19,880 --> 01:14:23,060 I'm going to setItem, localStorage, set it equal to 0. 1582 01:14:23,060 --> 01:14:25,760 So I'm setting counter equal to 0. 1583 01:14:25,760 --> 01:14:33,590 And now what I'm going to do is initially set the counter's inner HTML 1584 01:14:33,590 --> 01:14:37,760 to be whatever the value of the counter variable in localStorage is. 1585 01:14:37,760 --> 01:14:40,310 So if localStorage starts off at zero, then the counter 1586 01:14:40,310 --> 01:14:41,712 is going to initially display 0. 1587 01:14:41,712 --> 01:14:44,420 But if it's something else, it's going to display something else. 1588 01:14:44,420 --> 01:14:46,220 And now every time this button is clicked, 1589 01:14:46,220 --> 01:14:49,880 querySelector button onclick, what am I going to do? 1590 01:14:49,880 --> 01:14:52,850 Well, instead of setting the variable counter to be zero at first, 1591 01:14:52,850 --> 01:14:56,929 let's set counter to be whatever localStorage's counter is. 1592 01:14:56,929 --> 01:14:58,970 Then I'm going to increment the variable counter. 1593 01:14:58,970 --> 01:15:00,890 counter++. 1594 01:15:00,890 --> 01:15:06,380 Then I'm going to set the inner HTML of my counter heading to be 1595 01:15:06,380 --> 01:15:08,360 whatever that counter variable was. 1596 01:15:08,360 --> 01:15:09,920 And then I'm going to setItem-- 1597 01:15:09,920 --> 01:15:11,710 localStorage.setItem. 1598 01:15:11,710 --> 01:15:15,260 Set the value of counter to be whatever my variable counter is equal to. 1599 01:15:15,260 --> 01:15:18,260 And you could get around this without even needing the counter variable, 1600 01:15:18,260 --> 01:15:21,080 but I'm including all the steps here just to be explicit about it. 1601 01:15:21,080 --> 01:15:22,670 And so what's the result of this? 1602 01:15:22,670 --> 01:15:26,150 This local storage is a variable I have access to. 1603 01:15:26,150 --> 01:15:29,120 Or it's storage that I have access to even when I close the page 1604 01:15:29,120 --> 01:15:30,020 and reopen it. 1605 01:15:30,020 --> 01:15:32,382 So if I open up storage.html here-- 1606 01:15:32,382 --> 01:15:34,340 and I have this button that will keep counting. 1607 01:15:34,340 --> 01:15:38,120 And I count up to five, for example, or six, seven, eight, nine, 1608 01:15:38,120 --> 01:15:41,544 if I now close this page, in the examples 1609 01:15:41,544 --> 01:15:44,460 we've seen before, it would reset back to zero when I opened the page. 1610 01:15:44,460 --> 01:15:46,418 But now when I open the page, I'm back at nine. 1611 01:15:46,418 --> 01:15:49,490 It's retrieved that value from localStorage, and it's using it, 1612 01:15:49,490 --> 01:15:51,710 and now I can continue to click and continue 1613 01:15:51,710 --> 01:15:53,930 to update the value of the variable in localStorage. 1614 01:15:53,930 --> 01:15:54,430 Yeah? 1615 01:15:54,430 --> 01:15:57,720 AUDIENCE: So the localStorage is storing it in Chrome? 1616 01:15:57,720 --> 01:16:00,710 SPEAKER 1: Yeah, the browsers need to support localStorage, 1617 01:16:00,710 --> 01:16:05,120 and so Chrome happens to be a browser that allows us to store information 1618 01:16:05,120 --> 01:16:06,050 locally within Chrome. 1619 01:16:06,050 --> 01:16:09,805 And most other modern web browsers will also support localStorage now as well. 1620 01:16:09,805 --> 01:16:12,990 AUDIENCE: [INAUDIBLE] 1621 01:16:12,990 --> 01:16:15,270 SPEAKER 1: Yep, it will continue to persist. 1622 01:16:15,270 --> 01:16:19,452 And so it's a nice way of being able to store data locally such 1623 01:16:19,452 --> 01:16:21,410 that you can reference it later in future uses. 1624 01:16:21,410 --> 01:16:23,701 And you may find this proves useful in future projects. 1625 01:16:23,701 --> 01:16:24,592 AUDIENCE: [INAUDIBLE] 1626 01:16:24,592 --> 01:16:25,550 SPEAKER 1: Repeat that. 1627 01:16:25,550 --> 01:16:27,462 AUDIENCE: [INAUDIBLE] 1628 01:16:27,462 --> 01:16:28,920 SPEAKER 1: You can think of it as-- 1629 01:16:28,920 --> 01:16:32,420 so a cookie-- so the question is the relationship between this and a cookie. 1630 01:16:32,420 --> 01:16:36,680 So a cookie would be with regards to interactions with some kind of server, 1631 01:16:36,680 --> 01:16:41,360 that a server might use a cookie in order to remember a particular user. 1632 01:16:41,360 --> 01:16:44,120 With regards to this storage website, there is no server involved. 1633 01:16:44,120 --> 01:16:47,230 It is just data that is being stored on the computer. 1634 01:16:47,230 --> 01:16:50,440 But it's got some similar elements in spirit. 1635 01:16:50,440 --> 01:16:51,085 Yeah? 1636 01:16:51,085 --> 01:16:54,055 AUDIENCE: How do you avoid [INAUDIBLE] collisions? 1637 01:16:54,055 --> 01:17:00,490 Because you just said [INAUDIBLE] that somebody could use 1638 01:17:00,490 --> 01:17:02,965 counter in their web page? 1639 01:17:02,965 --> 01:17:04,150 SPEAKER 1: Great question. 1640 01:17:04,150 --> 01:17:06,566 So the question is, how do you avoid namespace collisions? 1641 01:17:06,566 --> 01:17:11,070 What if someone else is also using a localStorage variable named counter? 1642 01:17:11,070 --> 01:17:16,330 The way localStorage works is that it is reserved for a particular domain name. 1643 01:17:16,330 --> 01:17:19,320 And so if your website, at one domain name, 1644 01:17:19,320 --> 01:17:21,387 is using a particular variable in localStorage 1645 01:17:21,387 --> 01:17:23,220 and some other website at a different domain 1646 01:17:23,220 --> 01:17:25,380 is using a variable in localStorage, those names 1647 01:17:25,380 --> 01:17:26,950 will not conflict with each other. 1648 01:17:26,950 --> 01:17:29,190 But if you, on your domain on two different pages, 1649 01:17:29,190 --> 01:17:31,140 for example, are using localStorage, those 1650 01:17:31,140 --> 01:17:33,069 will be the same values for localStorage. 1651 01:17:33,069 --> 01:17:34,860 And so it would be your responsibility then 1652 01:17:34,860 --> 01:17:38,540 to make sure that those names don't conflict with each other. 1653 01:17:38,540 --> 01:17:39,890 Yup. 1654 01:17:39,890 --> 01:17:42,659 AUDIENCE: [INAUDIBLE] 1655 01:17:42,659 --> 01:17:44,200 SPEAKER 1: It's still going to be 18. 1656 01:17:44,200 --> 01:17:46,430 Yeah. 1657 01:17:46,430 --> 01:17:47,340 OK. 1658 01:17:47,340 --> 01:17:51,900 So those were some other features of JavaScript-- the intervals 1659 01:17:51,900 --> 01:17:52,850 and localStorage. 1660 01:17:52,850 --> 01:17:55,860 What we're now going to take a look at is taking a step back 1661 01:17:55,860 --> 01:17:58,230 to our world of Flask and Python, and looking 1662 01:17:58,230 --> 01:18:00,840 at how we can develop applications using Flask 1663 01:18:00,840 --> 01:18:04,720 that are able to take advantage of JavaScript to do interesting things. 1664 01:18:04,720 --> 01:18:08,430 And so in order to do this, we are going to introduce 1665 01:18:08,430 --> 01:18:12,930 the concept of Ajax, which stands for Asynchronous JavaScript and XML, which 1666 01:18:12,930 --> 01:18:16,440 you can just think of as a technology that we can use in order 1667 01:18:16,440 --> 01:18:20,070 to get more information from a server even without needing 1668 01:18:20,070 --> 01:18:21,520 to reload an entire new page. 1669 01:18:21,520 --> 01:18:25,415 So if we need to get information from some website or some web server, 1670 01:18:25,415 --> 01:18:27,540 and incorporate it into the page that we're already 1671 01:18:27,540 --> 01:18:31,510 on without reloading a new page, we can use Ajax in order to do that. 1672 01:18:31,510 --> 01:18:33,690 And we'll see an example of that right now. 1673 01:18:33,690 --> 01:18:38,190 So what I'm going to go do is go into the Currency example. 1674 01:18:38,190 --> 01:18:40,810 And Currency is a Flask program. 1675 01:18:40,810 --> 01:18:44,310 So if I take this URL and go here-- 1676 01:18:44,310 --> 01:18:46,140 we saw in previous examples in past weeks 1677 01:18:46,140 --> 01:18:49,410 how we were able to use the Currency API on fixer.io 1678 01:18:49,410 --> 01:18:52,149 to get at exchange rates between different currencies. 1679 01:18:52,149 --> 01:18:54,690 And we saw a command-line program that allowed us to do that. 1680 01:18:54,690 --> 01:18:57,070 Now we're taking this application to the internet. 1681 01:18:57,070 --> 01:19:00,570 What I have is a page that just gives me a text field to type in a currency 1682 01:19:00,570 --> 01:19:02,520 and a button that says Get Exchange Rate. 1683 01:19:02,520 --> 01:19:06,030 And so if I type in "euro," for example, and click Get Exchange Rate, 1684 01:19:06,030 --> 01:19:07,132 without any new page-- 1685 01:19:07,132 --> 01:19:09,090 I didn't go to any new page-- it just tells me, 1686 01:19:09,090 --> 01:19:10,890 1 US dollar is equal to this many euros. 1687 01:19:10,890 --> 01:19:14,460 And if I do Japanese yen, then I get one US dollar 1688 01:19:14,460 --> 01:19:16,980 is equal to 105.65 Japanese yen. 1689 01:19:16,980 --> 01:19:19,650 And it's not the case that when I loaded this page 1690 01:19:19,650 --> 01:19:22,350 I needed to load all of the different currency exchange rates 1691 01:19:22,350 --> 01:19:23,730 in order to load this page. 1692 01:19:23,730 --> 01:19:25,860 What's happening, as we'll soon see, is that when 1693 01:19:25,860 --> 01:19:30,540 I type "Great British pounds," for example, when I click the Get Exchange 1694 01:19:30,540 --> 01:19:32,610 Rate, I'm making an Ajax request. 1695 01:19:32,610 --> 01:19:35,280 I'm making another request to my web server, 1696 01:19:35,280 --> 01:19:38,010 my Flask web server, which is going to get the exchange 1697 01:19:38,010 --> 01:19:40,660 rate for the Great British pound, give it back to me, 1698 01:19:40,660 --> 01:19:43,140 and then I'm using JavaScript to update the DOM in order 1699 01:19:43,140 --> 01:19:45,060 to render this new content. 1700 01:19:45,060 --> 01:19:49,180 And so we'll take a look at how all of that actually works. 1701 01:19:49,180 --> 01:19:54,270 So let's take a look at application.pi inside of this Currency application. 1702 01:19:54,270 --> 01:19:58,620 Inside of this default route, I'm just returning an index.html template-- 1703 01:19:58,620 --> 01:20:00,920 same as the Flask programs we've seen before. 1704 01:20:00,920 --> 01:20:05,220 And I also have a route called /convert, which takes the request method 1705 01:20:05,220 --> 01:20:05,781 of POST-- 1706 01:20:05,781 --> 01:20:07,530 and this is going to be the route that I'm 1707 01:20:07,530 --> 01:20:11,130 going to use when I need to get a currency exchange rate. 1708 01:20:11,130 --> 01:20:14,400 And so what's happening inside of this convert function? 1709 01:20:14,400 --> 01:20:18,450 Well, I'm first going to get at the data that's associated with this form 1710 01:20:18,450 --> 01:20:22,980 submission, in particular getting at whatever the value of a currency form 1711 01:20:22,980 --> 01:20:26,760 attribute is, and save that inside of a variable called currency. 1712 01:20:26,760 --> 01:20:32,400 And then I'm going to make an API call to the API, 1713 01:20:32,400 --> 01:20:35,720 passing in US dollars and the currency that I want to convert to. 1714 01:20:35,720 --> 01:20:38,490 And you can take a look at the examples from past weeks 1715 01:20:38,490 --> 01:20:40,890 when we were dealing with APIs last time in order 1716 01:20:40,890 --> 01:20:42,604 to see in more detail how this API works. 1717 01:20:42,604 --> 01:20:43,770 It's exactly the same thing. 1718 01:20:43,770 --> 01:20:47,250 I'm just now doing it inside of a Flask application instead of inside 1719 01:20:47,250 --> 01:20:48,840 of a command-line application. 1720 01:20:48,840 --> 01:20:51,000 And so I'm going to request that new exchange rate. 1721 01:20:51,000 --> 01:20:53,541 If, for some reason, the response for that wasn't successful, 1722 01:20:53,541 --> 01:20:55,770 the status code was not 200, then I'm going 1723 01:20:55,770 --> 01:20:59,340 to return a JSON object that just says, success false, 1724 01:20:59,340 --> 01:21:00,960 this request was not successful. 1725 01:21:00,960 --> 01:21:04,140 And I want to let my client know that, let them know that, for some reason, 1726 01:21:04,140 --> 01:21:06,700 this request was not successful. 1727 01:21:06,700 --> 01:21:13,350 Then I'm going to get the JSON data from that request response 1728 01:21:13,350 --> 01:21:16,914 and check to make sure that the currency is actually in that response. 1729 01:21:16,914 --> 01:21:19,580 And this just has to do with the way that the API is structured. 1730 01:21:19,580 --> 01:21:22,620 So this code is going to vary depending on what API you're using. 1731 01:21:22,620 --> 01:21:24,870 But the way this API happens to work is that I 1732 01:21:24,870 --> 01:21:27,150 need to check to make sure that the currency is 1733 01:21:27,150 --> 01:21:30,796 inside of my list of the rates that came back to me. 1734 01:21:30,796 --> 01:21:32,670 And if, for some reason, that currency wasn't 1735 01:21:32,670 --> 01:21:34,420 in the list of rates that came back to me, 1736 01:21:34,420 --> 01:21:37,380 then I'm going to return success is false as well. 1737 01:21:37,380 --> 01:21:41,310 But if none of that was true-- if the status code was 200 and the currency is 1738 01:21:41,310 --> 01:21:43,410 inside the data that came back to me-- 1739 01:21:43,410 --> 01:21:46,710 then I'm going to return this JSON object-- 1740 01:21:46,710 --> 01:21:51,706 success was true and the rate is whatever data rates' currency is. 1741 01:21:51,706 --> 01:21:53,580 And if you recall from last time, this is how 1742 01:21:53,580 --> 01:21:56,160 we extracted the actual exchange rate. 1743 01:21:56,160 --> 01:21:59,550 And so the long story short of what the convert route is doing 1744 01:21:59,550 --> 01:22:03,930 is if I provide, as input to this route, a currency value, 1745 01:22:03,930 --> 01:22:07,020 like Japanese yen or euro, then it's going 1746 01:22:07,020 --> 01:22:11,730 to make an API request to our currency converter API, 1747 01:22:11,730 --> 01:22:14,250 and then return back to me, ideally, a JSON 1748 01:22:14,250 --> 01:22:16,650 object telling me that the request was successful 1749 01:22:16,650 --> 01:22:20,580 and also giving me back a number representing that exchange rate. 1750 01:22:20,580 --> 01:22:22,650 It's not giving me back a full HTML page. 1751 01:22:22,650 --> 01:22:25,524 You can think of this like an API route that's just giving back to me 1752 01:22:25,524 --> 01:22:28,800 a JSON object, telling me whether the request was successful or not, 1753 01:22:28,800 --> 01:22:31,440 and telling me what the actual exchange rate is. 1754 01:22:31,440 --> 01:22:35,200 And I'm going to use that route now inside of my application. 1755 01:22:35,200 --> 01:22:39,750 So what's inside of my application? 1756 01:22:39,750 --> 01:22:44,160 Well, inside of index.html, I have a script tag 1757 01:22:44,160 --> 01:22:47,160 where I'm including this index.js JavaScript file. 1758 01:22:47,160 --> 01:22:50,920 And this URL for static is just Flask's way of incorporating static files. 1759 01:22:50,920 --> 01:22:53,850 We've seen a couple examples of this in prior weeks. 1760 01:22:53,850 --> 01:22:57,900 And inside the body of this page, I have a form where I can type in a currency 1761 01:22:57,900 --> 01:22:59,340 and click a Submit button. 1762 01:22:59,340 --> 01:23:01,770 And then I have this div down here, just a section 1763 01:23:01,770 --> 01:23:04,410 of the website whose ID is result. This is 1764 01:23:04,410 --> 01:23:06,670 where I'm going to put the result of the computation. 1765 01:23:06,670 --> 01:23:08,919 But to begin with, I haven't requested a currency yet. 1766 01:23:08,919 --> 01:23:10,210 So that result field is blank. 1767 01:23:10,210 --> 01:23:12,640 There's nothing there just yet. 1768 01:23:12,640 --> 01:23:15,720 And so all of the logic for what's actually going to happen 1769 01:23:15,720 --> 01:23:20,460 is going to happen inside of index.js. 1770 01:23:20,460 --> 01:23:23,590 And so let's take a look at that now and see what's happening. 1771 01:23:23,590 --> 01:23:26,760 So when the DOM content is done being loaded, 1772 01:23:26,760 --> 01:23:28,560 here's the code that's going to run. 1773 01:23:28,560 --> 01:23:32,550 What I want to happen is I only need to make some sort of interesting request 1774 01:23:32,550 --> 01:23:34,050 when someone submits the form. 1775 01:23:34,050 --> 01:23:37,380 When they click Get the Exchange Rate, then I want to do something. 1776 01:23:37,380 --> 01:23:40,620 So I select for the form, the thing that has ID form. 1777 01:23:40,620 --> 01:23:44,460 And when it is submitted, I'm going to run this function. 1778 01:23:44,460 --> 01:23:46,830 What's happening inside of this function? 1779 01:23:46,830 --> 01:23:51,420 Well, I'm going to define a variable called request, which is a new XML HTTP 1780 01:23:51,420 --> 01:23:52,290 request. 1781 01:23:52,290 --> 01:23:55,230 This is just an object that I'm creating in JavaScript 1782 01:23:55,230 --> 01:23:57,810 that is going to allow me to make an Ajax request, that's 1783 01:23:57,810 --> 01:24:02,100 going to allow me to make an HTTP request to some other web server 1784 01:24:02,100 --> 01:24:04,570 in order to get some information. 1785 01:24:04,570 --> 01:24:07,980 So then I'm going to define a variable called 1786 01:24:07,980 --> 01:24:12,820 currency, which is going to be whatever the current value of the Currency input 1787 01:24:12,820 --> 01:24:13,320 field is. 1788 01:24:13,320 --> 01:24:15,580 Currency, again, is that text input field. 1789 01:24:15,580 --> 01:24:17,790 Getting at its value will just get me whatever 1790 01:24:17,790 --> 01:24:20,010 it is the user typed in-- either euros, or pounds, 1791 01:24:20,010 --> 01:24:22,240 or whatever the currency might be. 1792 01:24:22,240 --> 01:24:24,270 And so I now have this variable request that 1793 01:24:24,270 --> 01:24:28,950 is going to represent a way to make new requests to other websites, 1794 01:24:28,950 --> 01:24:31,590 much like the request library in Python does, although perhaps 1795 01:24:31,590 --> 01:24:33,720 a little more wordy, as we'll soon see. 1796 01:24:33,720 --> 01:24:36,300 And I have a variable called currency that is that currency. 1797 01:24:36,300 --> 01:24:41,700 And now I'm going to say, request.open, meaning, initialize a new request. 1798 01:24:41,700 --> 01:24:45,000 It's going to be a POST request, because my route accepts the request method 1799 01:24:45,000 --> 01:24:45,614 POST. 1800 01:24:45,614 --> 01:24:47,280 And where am I going to request this to? 1801 01:24:47,280 --> 01:24:49,020 I need to provide the URL. 1802 01:24:49,020 --> 01:24:51,720 And I'm going to hit the route /convert. 1803 01:24:51,720 --> 01:24:54,090 And that's taken straight from application.pi, 1804 01:24:54,090 --> 01:24:58,100 where we defined a route called /convert and said that it accepts request 1805 01:24:58,100 --> 01:25:00,510 methods of POST. 1806 01:25:00,510 --> 01:25:02,020 So what happens next? 1807 01:25:02,020 --> 01:25:04,620 Well, now I need to tell my request, what should you 1808 01:25:04,620 --> 01:25:07,230 do when you're done being loaded? 1809 01:25:07,230 --> 01:25:10,650 In other words, when the request is done, what should happen? 1810 01:25:10,650 --> 01:25:12,150 And so here's what's happening here. 1811 01:25:12,150 --> 01:25:16,590 I'm taking my request variable and setting its onload attribute. 1812 01:25:16,590 --> 01:25:18,840 Again, when it's done being loaded-- 1813 01:25:18,840 --> 01:25:20,850 in other words, when the request is done-- 1814 01:25:20,850 --> 01:25:22,760 here's the function that should run. 1815 01:25:22,760 --> 01:25:25,030 And I'm creating a variable called data. 1816 01:25:25,030 --> 01:25:26,890 And what should data be equal to? 1817 01:25:26,890 --> 01:25:31,380 Well, ideally, I want data to be equal to that JSON object that got returned 1818 01:25:31,380 --> 01:25:35,520 to me when I made a request of a /convert route. 1819 01:25:35,520 --> 01:25:38,260 All I have, though, is this request variable. 1820 01:25:38,260 --> 01:25:41,970 So what you'll learn is that request.responseText 1821 01:25:41,970 --> 01:25:44,340 is an attribute of request that I can use 1822 01:25:44,340 --> 01:25:47,130 to get the text of the response, whatever the text that came back 1823 01:25:47,130 --> 01:25:50,030 to me when I made the request was. 1824 01:25:50,030 --> 01:25:55,830 And JSON.parse is a built-in function in JavaScript that takes that text 1825 01:25:55,830 --> 01:25:58,620 and tries to parse it as a JSON object that 1826 01:25:58,620 --> 01:26:03,480 lets me access it using keys and values, like we saw in the API lecture 1827 01:26:03,480 --> 01:26:04,530 last week. 1828 01:26:04,530 --> 01:26:08,760 So now I have this data variable that should be equal to whatever came back 1829 01:26:08,760 --> 01:26:11,340 to me from that /convert route. 1830 01:26:11,340 --> 01:26:14,250 And if you remember, the /convert route did a couple things. 1831 01:26:14,250 --> 01:26:18,480 If the request was successful, then the success key in the JSON object 1832 01:26:18,480 --> 01:26:19,690 was true. 1833 01:26:19,690 --> 01:26:22,240 Otherwise, that success key was false. 1834 01:26:22,240 --> 01:26:23,850 And so here, I'm checking for that. 1835 01:26:23,850 --> 01:26:27,730 If data.success-- in other words, if the request was successful, 1836 01:26:27,730 --> 01:26:32,160 meaning that success attribute of my JSON object had a value of true-- 1837 01:26:32,160 --> 01:26:33,850 then here's what should happen. 1838 01:26:33,850 --> 01:26:36,780 Well, I'm defining the new variable, contents. 1839 01:26:36,780 --> 01:26:43,560 The contents of my result div should be 1 US dollar is equal to-- 1840 01:26:43,560 --> 01:26:46,530 and then I want to specify what the exchange rate actually is. 1841 01:26:46,530 --> 01:26:49,680 And remember, the exchange rate came back to me in this request. 1842 01:26:49,680 --> 01:26:53,070 It came back in the response text of the request, which I then 1843 01:26:53,070 --> 01:26:55,770 converted into this JSON data value. 1844 01:26:55,770 --> 01:27:00,165 And to get at the rate from that data value, I do data.rate. 1845 01:27:00,165 --> 01:27:03,690 And so 1 US dollar is equal to, plug in the rate 1846 01:27:03,690 --> 01:27:07,710 here, and then plug in the name of the currency, where that currency was 1847 01:27:07,710 --> 01:27:10,470 defined in a variable up above, just drawn from whatever it is 1848 01:27:10,470 --> 01:27:12,780 the user typed in to that input field. 1849 01:27:12,780 --> 01:27:16,110 And so this is going to be what I want to fill in to that result field 1850 01:27:16,110 --> 01:27:17,910 inside of my HTML page. 1851 01:27:17,910 --> 01:27:20,850 And so now I say, we'll get at that result div 1852 01:27:20,850 --> 01:27:25,640 and update the inner HTML to be whatever those contents were. 1853 01:27:25,640 --> 01:27:28,110 And so that, if the request was successful, 1854 01:27:28,110 --> 01:27:32,760 has the effect of providing, inside that result div, the actual contents 1855 01:27:32,760 --> 01:27:34,120 that I care about. 1856 01:27:34,120 --> 01:27:35,130 And then finally, else. 1857 01:27:35,130 --> 01:27:37,770 If the request was not successful, then I just 1858 01:27:37,770 --> 01:27:40,650 want to set the inner HTML to be, there was an error just 1859 01:27:40,650 --> 01:27:44,220 to indicate that something went wrong. 1860 01:27:44,220 --> 01:27:46,200 Any ideas on what's missing from the request? 1861 01:27:46,200 --> 01:27:47,700 Not from the onload function. 1862 01:27:47,700 --> 01:27:49,260 But so far, I've created a request. 1863 01:27:49,260 --> 01:27:53,760 I said, I want that request to be POST request that goes through /convert. 1864 01:27:53,760 --> 01:27:57,870 And this is the code that should run when the request is done being loaded. 1865 01:27:57,870 --> 01:28:01,241 What information have I not yet included or used? 1866 01:28:01,241 --> 01:28:01,740 Yeah? 1867 01:28:01,740 --> 01:28:04,174 AUDIENCE: I didn't see your URL. 1868 01:28:04,174 --> 01:28:05,340 SPEAKER 1: The URL is there. 1869 01:28:05,340 --> 01:28:09,990 So if you would look a little higher, I specify when I initialized the request 1870 01:28:09,990 --> 01:28:13,590 in request.open, we're going to make a POST request to the /convert route 1871 01:28:13,590 --> 01:28:15,060 or URL. 1872 01:28:15,060 --> 01:28:17,874 But what's still missing? 1873 01:28:17,874 --> 01:28:18,816 Any thoughts? 1874 01:28:18,816 --> 01:28:23,530 1875 01:28:23,530 --> 01:28:26,470 So I'm making a POST request to /convert, 1876 01:28:26,470 --> 01:28:30,010 which is going to try and do some currency conversion for me and find 1877 01:28:30,010 --> 01:28:34,000 the exchange rate between US dollars and some other exchange rate. 1878 01:28:34,000 --> 01:28:40,090 But I haven't yet actually told this request about the currency 1879 01:28:40,090 --> 01:28:43,647 that I want information about I haven't told this request, look up 1880 01:28:43,647 --> 01:28:44,980 the exchange rate for euros yet. 1881 01:28:44,980 --> 01:28:47,950 I've just used this variable currency so far just 1882 01:28:47,950 --> 01:28:51,021 inside this contents of what should be displayed on the page, 1883 01:28:51,021 --> 01:28:53,270 but I haven't sent that information to the server yet. 1884 01:28:53,270 --> 01:28:57,310 So I need some way of taking that currency 1885 01:28:57,310 --> 01:29:02,540 and putting it inside of the form data that I want to send to the server. 1886 01:29:02,540 --> 01:29:08,140 And so in order to do that, what I'm going to do is create a new variable 1887 01:29:08,140 --> 01:29:12,550 called data, which is going to be equal to a new form data object, which 1888 01:29:12,550 --> 01:29:14,500 is going to hold the form data. 1889 01:29:14,500 --> 01:29:20,230 And I'm going to add to this data, using data.append, a key called currency, 1890 01:29:20,230 --> 01:29:23,800 whose value is the currency variable that I defined up above, 1891 01:29:23,800 --> 01:29:27,910 that currency variable that was the name of the currency. 1892 01:29:27,910 --> 01:29:32,380 Finally, finally, I do request.send, and I send this data along with it. 1893 01:29:32,380 --> 01:29:35,500 I want to send a request to the /convert route, 1894 01:29:35,500 --> 01:29:38,590 but I want to pass in the data about what currency I actually care about 1895 01:29:38,590 --> 01:29:39,910 converting to. 1896 01:29:39,910 --> 01:29:42,160 And then return false just stops the page 1897 01:29:42,160 --> 01:29:44,380 from reloading after I submit the form. 1898 01:29:44,380 --> 01:29:46,430 And so high-level overview of all of this. 1899 01:29:46,430 --> 01:29:48,430 And the source code we made available afterwards 1900 01:29:48,430 --> 01:29:50,096 if you want to take a closer look at it. 1901 01:29:50,096 --> 01:29:54,580 We create a new request; tell it where to request to, the /convert route; 1902 01:29:54,580 --> 01:29:56,800 tell it what to do when the request is done, 1903 01:29:56,800 --> 01:30:00,940 getting at that JSON data and doing something with that data; then finally, 1904 01:30:00,940 --> 01:30:04,300 specifying what information should be included with the submission 1905 01:30:04,300 --> 01:30:08,800 of the form; and then finally, actually making the request down here. 1906 01:30:08,800 --> 01:30:12,670 And so the result of all of that is that I can type in something like "euro" 1907 01:30:12,670 --> 01:30:14,496 and get the exchange rate for a euro. 1908 01:30:14,496 --> 01:30:17,620 And if I type in a currency that doesn't exist and try and get the exchange 1909 01:30:17,620 --> 01:30:21,550 rate, I get "There was an error" coming back to me all on the same page, 1910 01:30:21,550 --> 01:30:25,030 all by making Ajax requests that, without needing to reload the page, 1911 01:30:25,030 --> 01:30:27,480 allow me to get additional information. 1912 01:30:27,480 --> 01:30:28,460 Yeah. 1913 01:30:28,460 --> 01:30:36,867 AUDIENCE: [INAUDIBLE] 1914 01:30:36,867 --> 01:30:37,950 SPEAKER 1: Great question. 1915 01:30:37,950 --> 01:30:40,991 So the question is, could I have instead just set up an Ajax request that 1916 01:30:40,991 --> 01:30:42,510 was directly accessing the currency? 1917 01:30:42,510 --> 01:30:43,010 Absolutely. 1918 01:30:43,010 --> 01:30:46,490 You could have just requested the API directly and parsed that JSON response, 1919 01:30:46,490 --> 01:30:49,781 but this was just meant to be an example of how you can use a Flask server back 1920 01:30:49,781 --> 01:30:52,820 end if you have your own data that you want to process in some way 1921 01:30:52,820 --> 01:30:54,070 in order to return. 1922 01:30:54,070 --> 01:30:56,941 But yeah, good question. 1923 01:30:56,941 --> 01:30:57,440 All right. 1924 01:30:57,440 --> 01:31:01,470 We'll take a look at one other feature of JavaScript 1925 01:31:01,470 --> 01:31:04,490 that web browsers now support that will be powerful 1926 01:31:04,490 --> 01:31:07,110 as we begin to develop more sophisticated web pages. 1927 01:31:07,110 --> 01:31:10,250 And that is a feature known as web sockets. 1928 01:31:10,250 --> 01:31:15,707 And so normally when we think about making web page requests 1929 01:31:15,707 --> 01:31:17,540 on the internet between clients and servers, 1930 01:31:17,540 --> 01:31:20,660 we think of it in terms of the request response model, 1931 01:31:20,660 --> 01:31:25,220 where I, on my computer, make an HTTP request to some web server requesting 1932 01:31:25,220 --> 01:31:29,630 for some information, and then that server gives back to me some response. 1933 01:31:29,630 --> 01:31:32,500 And that's useful so long as any time I need data, 1934 01:31:32,500 --> 01:31:34,820 it's only because I'm requesting that data first 1935 01:31:34,820 --> 01:31:36,500 and then I get back that response. 1936 01:31:36,500 --> 01:31:38,780 But what you'll soon see is that in Project 2, which 1937 01:31:38,780 --> 01:31:42,080 we'll release later today, what you're going to be building is a chat 1938 01:31:42,080 --> 01:31:43,880 room-style application, kind of like Slack 1939 01:31:43,880 --> 01:31:45,390 that we've been using in the class. 1940 01:31:45,390 --> 01:31:48,410 And what that will mean is that it's not really 1941 01:31:48,410 --> 01:31:53,480 going to be the case that if someone sends a message via some chat room, 1942 01:31:53,480 --> 01:31:56,210 that you're not going to want to refresh your page in order 1943 01:31:56,210 --> 01:31:59,240 to request any new messages and then get those messages. 1944 01:31:59,240 --> 01:32:01,730 What you want is real-time communication, 1945 01:32:01,730 --> 01:32:05,900 where your client and server can both be talking to each other simultaneously, 1946 01:32:05,900 --> 01:32:08,360 or what's called full-duplex communication. 1947 01:32:08,360 --> 01:32:10,280 And to do that, modern web browsers support 1948 01:32:10,280 --> 01:32:13,100 what are called web sockets, which allow for a protocol that 1949 01:32:13,100 --> 01:32:16,040 allow for that full-duplex communication between client and server 1950 01:32:16,040 --> 01:32:19,850 simultaneously that allow for more real-time communication 1951 01:32:19,850 --> 01:32:21,170 between the client and server. 1952 01:32:21,170 --> 01:32:24,740 And Socket.IO happens to be one example of a JavaScript library 1953 01:32:24,740 --> 01:32:26,480 that lets us do things like this. 1954 01:32:26,480 --> 01:32:28,460 So we'll take a look at some examples of that 1955 01:32:28,460 --> 01:32:32,510 in order to show you how this can work and how it can ultimately be powerful. 1956 01:32:32,510 --> 01:32:36,200 And so what we're going to do is build an application 1957 01:32:36,200 --> 01:32:39,020 that allows different people on different pages 1958 01:32:39,020 --> 01:32:40,940 to cast votes for something. 1959 01:32:40,940 --> 01:32:44,540 They can vote yes on a motion or on a bill, or they can vote no, 1960 01:32:44,540 --> 01:32:47,040 and they can vote maybe-- is what we're going to try and do. 1961 01:32:47,040 --> 01:32:48,748 And ultimately, we're trying to build out 1962 01:32:48,748 --> 01:32:53,090 an application that lets anyone logging in see the results of this voting. 1963 01:32:53,090 --> 01:32:56,790 Lets anyone see whenever someone else votes in real time. 1964 01:32:56,790 --> 01:33:06,820 So let's take a look now at vote0application.pi. 1965 01:33:06,820 --> 01:33:14,740 And so what's going to happen here is I am going to define, inside 1966 01:33:14,740 --> 01:33:18,670 of my index function, the route. 1967 01:33:18,670 --> 01:33:21,360 I'm going to return the index.html page. 1968 01:33:21,360 --> 01:33:24,580 And what I'm going to use is a library called 1969 01:33:24,580 --> 01:33:29,140 Flask Socket.IO, which is going to allow me to use web sockets inside 1970 01:33:29,140 --> 01:33:30,370 of a Flask application. 1971 01:33:30,370 --> 01:33:32,840 And you'll see how all this works in just a moment. 1972 01:33:32,840 --> 01:33:37,750 But the idea of it is going to be that my web server and my web client 1973 01:33:37,750 --> 01:33:42,100 are going to be sending events, or emitting events, that are broadcasted 1974 01:33:42,100 --> 01:33:46,540 to everyone else; and they're going to be listening for events, receiving 1975 01:33:46,540 --> 01:33:48,880 those web socket events; and doing something 1976 01:33:48,880 --> 01:33:50,960 interesting with those events. 1977 01:33:50,960 --> 01:33:53,540 And let's take a look at just some of this code 1978 01:33:53,540 --> 01:33:55,390 and then get a sense for what's happening. 1979 01:33:55,390 --> 01:34:01,599 If we go to vote0index.html, what we see is inside of index.html, 1980 01:34:01,599 --> 01:34:02,390 it's pretty simple. 1981 01:34:02,390 --> 01:34:05,830 I'm including an index.js JavaScript file, which we'll soon 1982 01:34:05,830 --> 01:34:08,050 see at work in just a moment. 1983 01:34:08,050 --> 01:34:09,801 And inside the body of this application, I 1984 01:34:09,801 --> 01:34:12,966 have an unordered list that's going to keep track of all the different votes 1985 01:34:12,966 --> 01:34:14,140 that people have cast. 1986 01:34:14,140 --> 01:34:15,550 And then three buttons-- 1987 01:34:15,550 --> 01:34:18,430 a Yes button, a No button, and a Maybe button. 1988 01:34:18,430 --> 01:34:21,340 And notice, in particular, that each one of these buttons 1989 01:34:21,340 --> 01:34:24,940 has a date-of-vote attribute, where date-of-vote is just 1990 01:34:24,940 --> 01:34:27,180 me giving additional information to these buttons 1991 01:34:27,180 --> 01:34:29,704 such that, in JavaScript, I can extract this data out of it. 1992 01:34:29,704 --> 01:34:32,620 And so I have a data vote that's equal to yes, one that's equal to no, 1993 01:34:32,620 --> 01:34:34,390 and one that's equal to maybe. 1994 01:34:34,390 --> 01:34:40,270 And so the interesting stuff is all going to happen inside of index.js. 1995 01:34:40,270 --> 01:34:42,980 And so what's happening here? 1996 01:34:42,980 --> 01:34:46,420 Well, when the web page is done loading, the first thing I need to do 1997 01:34:46,420 --> 01:34:51,130 is connect to the web socket to allow for this communication in real time 1998 01:34:51,130 --> 01:34:52,880 between the client and the server. 1999 01:34:52,880 --> 01:34:56,530 And so this is just a standard line that Socket.IO will use. 2000 01:34:56,530 --> 01:35:01,570 We'll connect to location.protocol, which will be either HTTP or HTTPS, 2001 01:35:01,570 --> 01:35:05,050 most likely, plus the domain name, and then whatever 2002 01:35:05,050 --> 01:35:06,586 port you're currently working on. 2003 01:35:06,586 --> 01:35:08,710 So you can sort of just copy this line and treat it 2004 01:35:08,710 --> 01:35:11,650 as, this is what's going to allow me to connect to this web socket 2005 01:35:11,650 --> 01:35:13,030 implementation. 2006 01:35:13,030 --> 01:35:18,940 And now these web sockets can listen for particular events. 2007 01:35:18,940 --> 01:35:23,170 And so in this case, what I want to do is once the web socket is connected, 2008 01:35:23,170 --> 01:35:25,990 I want to make sure all of my buttons are configured 2009 01:35:25,990 --> 01:35:27,940 to do something with the web socket. 2010 01:35:27,940 --> 01:35:30,260 In particular, when the button is clicked, 2011 01:35:30,260 --> 01:35:32,950 I want to emit a new event, telling the world, 2012 01:35:32,950 --> 01:35:37,520 or telling my web server in particular, that a vote has been submitted. 2013 01:35:37,520 --> 01:35:39,230 So how am I going to do that? 2014 01:35:39,230 --> 01:35:43,400 Well, once the web socket is connected, here is the code that I want to run. 2015 01:35:43,400 --> 01:35:47,470 I'm going to do a querySelectorAll, selecting all of my buttons. 2016 01:35:47,470 --> 01:35:53,380 And for each one of those buttons, here is the code that I want to run. 2017 01:35:53,380 --> 01:35:56,980 When that button is clicked, I'm going to run this function. 2018 01:35:56,980 --> 01:35:59,230 And that function is going to define a variable called 2019 01:35:59,230 --> 01:36:04,077 selection, which is equal to whatever the button's data-vote attribute is. 2020 01:36:04,077 --> 01:36:06,160 Remember, data-set gives me access to all the data 2021 01:36:06,160 --> 01:36:08,260 attributes of the HTML element. 2022 01:36:08,260 --> 01:36:11,440 And so each of my buttons had a different data-vote attribute-- 2023 01:36:11,440 --> 01:36:13,180 either yes, or no, or maybe. 2024 01:36:13,180 --> 01:36:16,360 And I'm going to save that in a variable called selection. 2025 01:36:16,360 --> 01:36:19,450 And now I'm going to run this code, which is the interesting code. 2026 01:36:19,450 --> 01:36:24,460 socket.emit is going to emit this event to my web server 2027 01:36:24,460 --> 01:36:26,850 in order to notify my web server of this new event. 2028 01:36:26,850 --> 01:36:28,150 I'm giving the event a name. 2029 01:36:28,150 --> 01:36:30,430 I'm just going to call it submit vote. 2030 01:36:30,430 --> 01:36:34,540 And then I'm passing in the data that is associated with that event. 2031 01:36:34,540 --> 01:36:39,430 In this case, it's just a JSON object that contains a key called selection. 2032 01:36:39,430 --> 01:36:42,010 And its value is whatever it is that I actually 2033 01:36:42,010 --> 01:36:44,410 selected-- either yes, or no, or maybe. 2034 01:36:44,410 --> 01:36:48,310 So what this code will ultimately do is that once my web sockets are configured 2035 01:36:48,310 --> 01:36:51,427 and connected, when I click on a button-- either yes, or no, or maybe-- 2036 01:36:51,427 --> 01:36:54,010 it's going to figure out which button did I click on, and save 2037 01:36:54,010 --> 01:36:55,780 that in a variable called selection. 2038 01:36:55,780 --> 01:36:59,260 And then it's going to emit an event to my web server. 2039 01:36:59,260 --> 01:37:01,210 That event is called submit vote. 2040 01:37:01,210 --> 01:37:05,917 And I'm passing in that selection data as part of it. 2041 01:37:05,917 --> 01:37:07,750 And so now before I go on to what's actually 2042 01:37:07,750 --> 01:37:10,000 happening later on in this JavaScript code, 2043 01:37:10,000 --> 01:37:12,174 let's go back to the web server code. 2044 01:37:12,174 --> 01:37:14,590 So to draw the distinction, remember, this JavaScript code 2045 01:37:14,590 --> 01:37:16,756 is code that's happening on the user's own machine-- 2046 01:37:16,756 --> 01:37:18,280 locally on their computer. 2047 01:37:18,280 --> 01:37:22,840 And here in application.pi is the code that's running on our Flask server. 2048 01:37:22,840 --> 01:37:25,860 And so down here, we have this special syntax-- 2049 01:37:25,860 --> 01:37:29,090 socket.io.onsubmitvote. 2050 01:37:29,090 --> 01:37:33,040 So this is my way of saying, when the socket detects this event, 2051 01:37:33,040 --> 01:37:36,220 an event called submit vote, and recalled it in the JavaScript-- 2052 01:37:36,220 --> 01:37:39,070 when we emitted the event, we named the event submit vote. 2053 01:37:39,070 --> 01:37:41,900 So that's going to connect it to this particular function. 2054 01:37:41,900 --> 01:37:45,670 So when someone submits the submit vote event, here's what you should do. 2055 01:37:45,670 --> 01:37:48,550 First, take the data and get at the selection, 2056 01:37:48,550 --> 01:37:51,940 because that was the data that was passed in via this event. 2057 01:37:51,940 --> 01:37:54,630 And save it inside of a variable called selection. 2058 01:37:54,630 --> 01:37:56,380 And so now if we think about this in terms 2059 01:37:56,380 --> 01:37:59,860 of making sure all of our computers know about what vote has been cast, 2060 01:37:59,860 --> 01:38:02,610 if one computer casts a yes vote and says, 2061 01:38:02,610 --> 01:38:05,610 I've submitted a vote, submit vote event, tell the server that I've cast 2062 01:38:05,610 --> 01:38:06,660 a yes vote. 2063 01:38:06,660 --> 01:38:09,720 And I now get this notification, effectively, 2064 01:38:09,720 --> 01:38:11,400 that a yes vote has been cast. 2065 01:38:11,400 --> 01:38:15,780 The next step for me is going to be to tell-- to broadcast to everyone else-- 2066 01:38:15,780 --> 01:38:20,130 that yes, a submit vote has just been cast, and that vote was a yes vote. 2067 01:38:20,130 --> 01:38:22,570 And so that's what this emit function is doing. 2068 01:38:22,570 --> 01:38:24,720 And you can import it from Socket.IO up above. 2069 01:38:24,720 --> 01:38:27,870 And I'm emitting a new event called announce vote. 2070 01:38:27,870 --> 01:38:29,760 And I can also pass in data to it. 2071 01:38:29,760 --> 01:38:32,280 And I'm announcing that the selection is the selection. 2072 01:38:32,280 --> 01:38:35,460 And this is going to announce it to any other sockets that are listening, 2073 01:38:35,460 --> 01:38:37,830 not just the original user. 2074 01:38:37,830 --> 01:38:40,530 And so I've saved the selection, I'm emitting 2075 01:38:40,530 --> 01:38:42,870 a new event called announce vote, its selection 2076 01:38:42,870 --> 01:38:44,880 is equal to whatever the selection was. 2077 01:38:44,880 --> 01:38:47,950 And broadcast equals true means I want to broadcast it to everyone, 2078 01:38:47,950 --> 01:38:51,480 including the person who originally cast the vote, because they should 2079 01:38:51,480 --> 01:38:53,620 theoretically know about it as well. 2080 01:38:53,620 --> 01:38:55,500 So I've emitted this announce vote. 2081 01:38:55,500 --> 01:38:58,740 And so now back on the client side, back inside the JavaScript, 2082 01:38:58,740 --> 01:39:01,830 to continue this story, what's going to happen 2083 01:39:01,830 --> 01:39:05,340 is that I'm going to tell the socket, when you receive an announce vote 2084 01:39:05,340 --> 01:39:08,910 signal, this is what you should now do. 2085 01:39:08,910 --> 01:39:11,569 Run this function that takes, as input, the data. 2086 01:39:11,569 --> 01:39:13,860 We're going to create a new list item, just like we did 2087 01:39:13,860 --> 01:39:16,110 before using document.createElement. 2088 01:39:16,110 --> 01:39:18,180 The inner HTML of that list item is going 2089 01:39:18,180 --> 01:39:22,070 to be Vote recorded followed by whatever the selection was, 2090 01:39:22,070 --> 01:39:24,480 whatever it is that they actually voted for. 2091 01:39:24,480 --> 01:39:29,430 And then I'm going to append this list item to #votes, that list of votes 2092 01:39:29,430 --> 01:39:31,080 that I've been accumulating. 2093 01:39:31,080 --> 01:39:35,490 So to tell the story very briefly one more time, when I first 2094 01:39:35,490 --> 01:39:38,980 connect the sockets, I set it up such that whenever a button is clicked, 2095 01:39:38,980 --> 01:39:42,900 I emit a submit vote event, telling the server that a vote has been submitted. 2096 01:39:42,900 --> 01:39:46,200 On my server now, when I receive this submit vote event, 2097 01:39:46,200 --> 01:39:48,820 I check what the selection is, and I broadcast 2098 01:39:48,820 --> 01:39:51,300 to everyone this announce vote event, telling people 2099 01:39:51,300 --> 01:39:54,810 that a vote has been made, and I want to announce it to everyone. 2100 01:39:54,810 --> 01:39:57,570 And in everyone's index.js file now, when 2101 01:39:57,570 --> 01:39:59,700 they receive this announce vote event, they're 2102 01:39:59,700 --> 01:40:03,240 going to run this function, which is going to add to my list of votes, 2103 01:40:03,240 --> 01:40:05,880 telling everyone what that vote is. 2104 01:40:05,880 --> 01:40:16,299 So if I now go into vote0 and do Flask run, I'm going to go to this URL. 2105 01:40:16,299 --> 01:40:19,340 And what I'm actually going to do is I'm going to open up this URL twice. 2106 01:40:19,340 --> 01:40:21,240 I'm going to open it up in two different windows. 2107 01:40:21,240 --> 01:40:22,890 So you can think of this as two different users that 2108 01:40:22,890 --> 01:40:24,242 are both using the system. 2109 01:40:24,242 --> 01:40:25,950 They both have a yes, no, and maybe vote. 2110 01:40:25,950 --> 01:40:29,640 And so when I click on this Yes button, what ultimately happens is-- 2111 01:40:29,640 --> 01:40:31,710 oh, sorry, refresh these. 2112 01:40:31,710 --> 01:40:35,230 When I click on the Yes button, it says, "Vote recorded-- yes." 2113 01:40:35,230 --> 01:40:37,140 And so how did that appear on both of them? 2114 01:40:37,140 --> 01:40:39,750 Well, on one side, I clicked the Yes button. 2115 01:40:39,750 --> 01:40:42,090 That sends the announcement up to the server 2116 01:40:42,090 --> 01:40:43,477 that I've submitted the yes vote. 2117 01:40:43,477 --> 01:40:46,560 And then the other person, without needing to refresh their page or reload 2118 01:40:46,560 --> 01:40:50,340 anything, is notified, because the web server that announces, or emits, 2119 01:40:50,340 --> 01:40:52,810 and broadcasts to everyone that a new vote has been cast. 2120 01:40:52,810 --> 01:40:55,090 So I can cast Yes vote, No vote, Maybe vote. 2121 01:40:55,090 --> 01:40:58,320 And it updates for all of the users that are connected to this socket. 2122 01:40:58,320 --> 01:41:00,540 And likewise on this side, I can also cast votes, 2123 01:41:00,540 --> 01:41:03,720 and it will appear on the first side as well. 2124 01:41:03,720 --> 01:41:05,500 And so this is Socket.IO in action. 2125 01:41:05,500 --> 01:41:07,680 And as you begin to develop your chat application, 2126 01:41:07,680 --> 01:41:10,330 you can see how this would be useful-- that when someone sends a message 2127 01:41:10,330 --> 01:41:13,204 and presses Return, the other person can see that message immediately 2128 01:41:13,204 --> 01:41:16,170 without needing to wait a couple seconds, and refresh the page, 2129 01:41:16,170 --> 01:41:19,650 or do something else in order to see the results of that. 2130 01:41:19,650 --> 01:41:23,010 We'll take a look at one other example of this, of just Socket.IO in action, 2131 01:41:23,010 --> 01:41:26,790 in terms of how this casting of votes and how the emitting of events 2132 01:41:26,790 --> 01:41:28,840 on the client and server work. 2133 01:41:28,840 --> 01:41:31,200 An improvement to this vote application would likely 2134 01:41:31,200 --> 01:41:34,320 be that I don't really care about seeing this hierarchical list of votes. 2135 01:41:34,320 --> 01:41:36,360 What I really care about is seeing the vote totals. 2136 01:41:36,360 --> 01:41:38,820 I want to know how many yes votes are there, how many not votes are there, 2137 01:41:38,820 --> 01:41:40,660 how many maybe votes are there. 2138 01:41:40,660 --> 01:41:44,100 And in particular, one other drawback of the approach we have right here 2139 01:41:44,100 --> 01:41:48,570 is that if I ever close one of these windows and then open it again, well, 2140 01:41:48,570 --> 01:41:49,970 now all the votes are gone. 2141 01:41:49,970 --> 01:41:51,720 Like, on this side, I don't see any votes. 2142 01:41:51,720 --> 01:41:54,970 And if I say no on this side, we'll now know it appears over here. 2143 01:41:54,970 --> 01:41:58,110 But because, by default, my page loads with an empty list, 2144 01:41:58,110 --> 01:42:01,110 I didn't get all that history of all of the previous votes that 2145 01:42:01,110 --> 01:42:02,200 had been submitted. 2146 01:42:02,200 --> 01:42:04,830 So I need some way of storing that information such 2147 01:42:04,830 --> 01:42:07,800 that, when future people visit the website later, 2148 01:42:07,800 --> 01:42:10,450 they can see that information as well. 2149 01:42:10,450 --> 01:42:15,240 So let's take a look now at vote1. 2150 01:42:15,240 --> 01:42:22,170 And inside of application.pi for vote1, we're going to maintain one thing. 2151 01:42:22,170 --> 01:42:27,046 I have here a variable, just a global variable, inside of Flask's memory 2152 01:42:27,046 --> 01:42:28,920 that's going to just store information, store 2153 01:42:28,920 --> 01:42:32,100 information that any client connecting to my Flask server 2154 01:42:32,100 --> 01:42:34,202 is going to be able to take advantage of. 2155 01:42:34,202 --> 01:42:35,910 And this is just going to be a dictionary 2156 01:42:35,910 --> 01:42:37,530 that stores the current vote counts. 2157 01:42:37,530 --> 01:42:40,500 Currently, yes's have zero votes, no's have zero votes, 2158 01:42:40,500 --> 01:42:42,150 maybes have zero votes. 2159 01:42:42,150 --> 01:42:45,810 And when I go to the default route, just go to the index page, 2160 01:42:45,810 --> 01:42:50,190 I'm going to return index.html, passing in that votes variable, 2161 01:42:50,190 --> 01:42:55,380 because I want my index.html template to know what the initial vote counts are. 2162 01:42:55,380 --> 01:42:58,590 They start out at zero, but maybe by the time that I get to the website, 2163 01:42:58,590 --> 01:43:00,381 different people have made different votes, 2164 01:43:00,381 --> 01:43:03,380 and I want to know what those current vote tallies are. 2165 01:43:03,380 --> 01:43:08,950 So if I go to index.html now, what I see inside my body 2166 01:43:08,950 --> 01:43:12,940 is three divs, one that says Yes votes. 2167 01:43:12,940 --> 01:43:13,990 And then I have a span. 2168 01:43:13,990 --> 01:43:17,410 Recall that a span is just a segment on my HTML page 2169 01:43:17,410 --> 01:43:20,930 that I can give attributes, like a name, or an ID in this case. 2170 01:43:20,930 --> 01:43:23,530 And I'm giving this one an ID of yes, because later on, I 2171 01:43:23,530 --> 01:43:25,154 want to fill something in to that spot. 2172 01:43:25,154 --> 01:43:26,740 But we'll see that in just a moment. 2173 01:43:26,740 --> 01:43:29,650 And that is going to be set to whatever votes yes is, 2174 01:43:29,650 --> 01:43:32,522 the Yes field of that votes object that I passed in. 2175 01:43:32,522 --> 01:43:34,480 And likewise, I'm doing the same for displaying 2176 01:43:34,480 --> 01:43:37,570 the current number of no votes and the current number of maybe votes. 2177 01:43:37,570 --> 01:43:41,030 And then these buttons are the same as well. 2178 01:43:41,030 --> 01:43:47,140 So what's happening now inside of index.js? 2179 01:43:47,140 --> 01:43:49,540 Well, this is mostly the same. 2180 01:43:49,540 --> 01:43:51,910 When I submit a vote, this is identical. 2181 01:43:51,910 --> 01:43:55,510 When I click on a button, I want to figure out what vote am I voting for 2182 01:43:55,510 --> 01:43:59,110 and then emit this submit vote event, passing in that selection. 2183 01:43:59,110 --> 01:44:03,170 What changes is what happens on the server side. 2184 01:44:03,170 --> 01:44:06,487 So what do I want to happen when a vote is submitted? 2185 01:44:06,487 --> 01:44:08,320 Well, when a vote is submitted, I still want 2186 01:44:08,320 --> 01:44:10,510 to get the selection of data.selection. 2187 01:44:10,510 --> 01:44:14,250 But rather than just emit it right away, I want to store it in memory. 2188 01:44:14,250 --> 01:44:17,170 I want to make sure my application knows what the vote total is, 2189 01:44:17,170 --> 01:44:19,390 so that the next time that a user comes to the site, 2190 01:44:19,390 --> 01:44:21,587 they're informed of that latest vote total. 2191 01:44:21,587 --> 01:44:24,670 And so I want to update this Votes dictionary that's keeping track of yes, 2192 01:44:24,670 --> 01:44:25,890 and no, and maybe votes. 2193 01:44:25,890 --> 01:44:29,110 And to do that, I'm doing votes to access this variable. 2194 01:44:29,110 --> 01:44:32,230 In square brackets, selection, where selection is going to be one of yes, 2195 01:44:32,230 --> 01:44:33,850 or no, or maybe. 2196 01:44:33,850 --> 01:44:36,760 And then plus equals 1, just to say, increment that total. 2197 01:44:36,760 --> 01:44:40,030 Increment either yes, or no, or maybe to be 2198 01:44:40,030 --> 01:44:43,450 one larger than it was to indicate that I now have one more vote. 2199 01:44:43,450 --> 01:44:47,590 And then finally, down here, I'm going to emit a new event called vote totals 2200 01:44:47,590 --> 01:44:51,250 and pass in this votes variable here, which 2201 01:44:51,250 --> 01:44:55,270 is just this Python dictionary that contains all of those vote totals. 2202 01:44:55,270 --> 01:44:57,880 That's the data that I want to send to all my clients. 2203 01:44:57,880 --> 01:45:01,260 That's the data that I want to broadcast for everyone to know about such that 2204 01:45:01,260 --> 01:45:03,370 now, if we go back to the client side of things 2205 01:45:03,370 --> 01:45:08,170 on my computer, what should happen when I get this vote total event? 2206 01:45:08,170 --> 01:45:14,680 Well, I want to update my yes span, the thing that 2207 01:45:14,680 --> 01:45:19,630 has ID yes, set its inner HTML to be whatever data.yes is, and likewise 2208 01:45:19,630 --> 01:45:23,230 with no and maybe, such that when I get the new vote totals back, 2209 01:45:23,230 --> 01:45:27,860 I want to update my current counts of what all the votes are. 2210 01:45:27,860 --> 01:45:31,780 And so the result of this, if I go in to vote one and do Flask run-- 2211 01:45:31,780 --> 01:45:35,620 2212 01:45:35,620 --> 01:45:38,600 and I'll open it twice for good measure. 2213 01:45:38,600 --> 01:45:42,180 I now see yes, no, and maybe votes, and three buttons at the bottom. 2214 01:45:42,180 --> 01:45:44,330 And when I click Yes, for example, on one of them, 2215 01:45:44,330 --> 01:45:46,610 the vote tally updates on both my computer 2216 01:45:46,610 --> 01:45:50,212 and presumably someone else's computer that is also connected by web sockets 2217 01:45:50,212 --> 01:45:51,170 to the same web server. 2218 01:45:51,170 --> 01:45:56,690 And clicking on any of these individual buttons will result in updating that. 2219 01:45:56,690 --> 01:46:00,740 And unlike last time, where if I closed the window and then reopened it, 2220 01:46:00,740 --> 01:46:04,580 it reset back to the original state, because I'm saving this information 2221 01:46:04,580 --> 01:46:08,390 inside of Flask's memory, in server-side memory in my Flask application, 2222 01:46:08,390 --> 01:46:11,420 when I go back to this site now, I see the same vote 2223 01:46:11,420 --> 01:46:13,670 totals, because it's able to take that information, 2224 01:46:13,670 --> 01:46:17,750 pass it into the index.html template, and now allow me to continue 2225 01:46:17,750 --> 01:46:21,450 voting just as I was able to before. 2226 01:46:21,450 --> 01:46:22,730 So that's Socket.IO in action. 2227 01:46:22,730 --> 01:46:25,790 Ultimately acts as a way to allow for this real-time communication 2228 01:46:25,790 --> 01:46:27,950 and will likely prove helpful to you in Project 2 2229 01:46:27,950 --> 01:46:32,870 as you begin to dive deeper into Python, and Flask, and JavaScript, 2230 01:46:32,870 --> 01:46:36,050 and sockets in particular in order to build these increasingly more and more 2231 01:46:36,050 --> 01:46:39,230 dynamic web applications that include client-side code that's 2232 01:46:39,230 --> 01:46:43,310 really running on the inside of the browser inside of the client's 2233 01:46:43,310 --> 01:46:43,940 computer. 2234 01:46:43,940 --> 01:46:47,120 And all of this is just a taste of what JavaScript is really capable of. 2235 01:46:47,120 --> 01:46:49,700 We've just seen a couple of the features of DOM manipulation, 2236 01:46:49,700 --> 01:46:51,940 and sockets, and other features. 2237 01:46:51,940 --> 01:46:53,940 But JavaScript can do a whole lot more, as we'll 2238 01:46:53,940 --> 01:46:55,810 begin to look into in future weeks. 2239 01:46:55,810 --> 01:46:58,400 But for now, that's it for JavaScript for today. 2240 01:46:58,400 --> 01:47:01,450 And best of luck with Project 2. 2241 01:47:01,450 --> 01:47:05,030