1 00:00:00,000 --> 00:00:02,994 [MUSIC PLAYING] 2 00:00:02,994 --> 00:00:17,745 3 00:00:17,745 --> 00:00:20,120 BRIAN YU: OK, welcome back, everyone, to "Web Programming 4 00:00:20,120 --> 00:00:21,433 with Python and JavaScript." 5 00:00:21,433 --> 00:00:24,350 And today, we turn our attention to the second of the main programming 6 00:00:24,350 --> 00:00:28,010 languages that we'll be looking at in this class, in particular, JavaScript. 7 00:00:28,010 --> 00:00:31,470 And to get an understanding for why it is that JavaScript is actually helpful, 8 00:00:31,470 --> 00:00:35,060 let's go back and revisit this diagram of what communication over the internet 9 00:00:35,060 --> 00:00:36,380 will generally look like. 10 00:00:36,380 --> 00:00:39,170 Oftentimes, we'll have a user, otherwise known as the client, 11 00:00:39,170 --> 00:00:41,330 using their computer on their web browser, 12 00:00:41,330 --> 00:00:44,000 whether that's Chrome, or Safari, or some other web browser, 13 00:00:44,000 --> 00:00:46,190 that sends an HTTP request-- 14 00:00:46,190 --> 00:00:49,080 a web request-- to some sort of web server. 15 00:00:49,080 --> 00:00:53,210 That server then processes that request, and then returns some sort of response 16 00:00:53,210 --> 00:00:54,920 that comes back to the client. 17 00:00:54,920 --> 00:00:56,930 Thus far, all of the code that we've written-- 18 00:00:56,930 --> 00:01:00,450 the Python web application code running in a Django web application, 19 00:01:00,450 --> 00:01:01,350 for example-- 20 00:01:01,350 --> 00:01:04,190 has all been code that runs on some sort of server, 21 00:01:04,190 --> 00:01:07,400 code that is listening for requests, doing some computation in order 22 00:01:07,400 --> 00:01:10,940 to process that request, and then generating some sort of response, 23 00:01:10,940 --> 00:01:15,770 usually in the form of an HTML template that we then send back to the client. 24 00:01:15,770 --> 00:01:17,990 What JavaScript is going to enable us to do 25 00:01:17,990 --> 00:01:20,480 is to begin to write client-side code. 26 00:01:20,480 --> 00:01:22,640 JavaScript is going to allow us to write code 27 00:01:22,640 --> 00:01:26,760 that actually runs inside of the user's web browser on the client. 28 00:01:26,760 --> 00:01:28,800 And this can be useful for a number of reasons. 29 00:01:28,800 --> 00:01:30,770 One, if there's computation that we want to do, 30 00:01:30,770 --> 00:01:34,080 but we don't need to go out and reach out to a server in order to do so, 31 00:01:34,080 --> 00:01:36,380 we can do the computation potentially faster 32 00:01:36,380 --> 00:01:39,242 just by running the code exclusively on the client. 33 00:01:39,242 --> 00:01:41,450 And in addition to that, we can begin to make our web 34 00:01:41,450 --> 00:01:43,190 pages a whole lot more interactive. 35 00:01:43,190 --> 00:01:45,410 JavaScript is going to give us the ability 36 00:01:45,410 --> 00:01:49,880 to directly manipulate the DOM, where again, the DOM is the Document Object 37 00:01:49,880 --> 00:01:50,540 Model-- 38 00:01:50,540 --> 00:01:53,645 that tree-like hierarchy that represents the web page 39 00:01:53,645 --> 00:01:55,270 that the user happens to be looking at. 40 00:01:55,270 --> 00:01:58,730 So JavaScript will enable us to write code that directly manipulates 41 00:01:58,730 --> 00:02:00,800 the content on the web page and we'll see how 42 00:02:00,800 --> 00:02:03,210 that can be quite powerful very soon. 43 00:02:03,210 --> 00:02:06,020 So how do we then use JavaScript inside of a web page 44 00:02:06,020 --> 00:02:10,370 in order to add some code, add some programming logic to a web page? 45 00:02:10,370 --> 00:02:12,320 Well, so far, we've already seen HTML-- 46 00:02:12,320 --> 00:02:15,050 the language we use to describe the structure of a web page-- 47 00:02:15,050 --> 00:02:17,870 where an HTML page just describes the structure 48 00:02:17,870 --> 00:02:20,180 of a page in terms of nested tags. 49 00:02:20,180 --> 00:02:22,370 We had those head tags at the top of the page, 50 00:02:22,370 --> 00:02:24,920 the body tags that describe the structure of the page, 51 00:02:24,920 --> 00:02:27,710 and then additional tags that could be nested within those. 52 00:02:27,710 --> 00:02:30,170 And in order to add JavaScript to a web page, 53 00:02:30,170 --> 00:02:33,350 it's as simple as including some script tags that are often 54 00:02:33,350 --> 00:02:36,830 located inside of the HTML page itself. 55 00:02:36,830 --> 00:02:39,560 When we use these script tags, we're telling the browser 56 00:02:39,560 --> 00:02:41,990 that anything in between these script tags 57 00:02:41,990 --> 00:02:46,490 should be interpreted, in this case, as JavaScript code that the web browser is 58 00:02:46,490 --> 00:02:48,330 then going to execute. 59 00:02:48,330 --> 00:02:51,800 So our very first program, for example, might just look like a line of code 60 00:02:51,800 --> 00:02:56,100 inside of the script tags, something like this, where alert, for example, 61 00:02:56,100 --> 00:02:59,450 is the name of a function-- a function that's going to produce an alert-- 62 00:02:59,450 --> 00:03:02,630 and then just as with functions in Python, functions in JavaScript 63 00:03:02,630 --> 00:03:03,740 can take arguments. 64 00:03:03,740 --> 00:03:06,380 So in between these parentheses, we have an argument, 65 00:03:06,380 --> 00:03:08,390 something like the string "hello, world"-- 66 00:03:08,390 --> 00:03:11,640 the text that we would like to display to the user. 67 00:03:11,640 --> 00:03:13,550 So let's go ahead and give this a try and see 68 00:03:13,550 --> 00:03:15,740 how we can actually use this code to write 69 00:03:15,740 --> 00:03:20,040 JavaScript that is going to run inside of the user's web browser. 70 00:03:20,040 --> 00:03:24,500 I'll go ahead and create a new file that we'll call hello.html. 71 00:03:24,500 --> 00:03:30,110 And inside of it, I'll include the same basic HTML structure 72 00:03:30,110 --> 00:03:33,450 that we've already seen before, where I have a head section that has a title, 73 00:03:33,450 --> 00:03:37,560 and then a body that maybe just says hello, for example. 74 00:03:37,560 --> 00:03:41,150 And so now, what I'd like to do is add a little bit of JavaScript 75 00:03:41,150 --> 00:03:42,530 to this web page. 76 00:03:42,530 --> 00:03:44,740 So in the head section of my web page, I'm 77 00:03:44,740 --> 00:03:48,710 going to go ahead and add a script tag, where in between these scripts 78 00:03:48,710 --> 00:03:51,770 tags now, I can write JavaScript code-- code that 79 00:03:51,770 --> 00:03:55,040 is going to be written in JavaScript that will run inside of the web browser 80 00:03:55,040 --> 00:03:57,950 when the user actually opens up this page. 81 00:03:57,950 --> 00:04:02,690 And for now, I'll just say, alert, and then hello world. 82 00:04:02,690 --> 00:04:05,660 It turns out in JavaScript, you can use either single quotation marks 83 00:04:05,660 --> 00:04:08,600 or double quotation marks in order to represent strings. 84 00:04:08,600 --> 00:04:11,930 I'll generally use single quotation marks here just by convention. 85 00:04:11,930 --> 00:04:13,820 So here, I'm running a function called alert 86 00:04:13,820 --> 00:04:16,880 that's going to display an alert, something like hello world to the user. 87 00:04:16,880 --> 00:04:22,110 And that's going to be inside of the script tags of this HTML page. 88 00:04:22,110 --> 00:04:26,600 So now if I want to actually open the page up, I can open hello.html 89 00:04:26,600 --> 00:04:28,850 or you could just visit it inside of your web browser, 90 00:04:28,850 --> 00:04:30,590 whether it's Chrome or something else. 91 00:04:30,590 --> 00:04:32,900 And now at the top of the page, what you'll notice 92 00:04:32,900 --> 00:04:35,750 is that I get a little bit of an alert-- some interaction where 93 00:04:35,750 --> 00:04:39,050 it says this page says hello world, and it gives me an option to, like, 94 00:04:39,050 --> 00:04:42,770 press a button, for example, like the OK button that'll 95 00:04:42,770 --> 00:04:44,688 say, all right, dismiss the alert now. 96 00:04:44,688 --> 00:04:46,730 And this is our very first example of JavaScript. 97 00:04:46,730 --> 00:04:50,270 We have a function called alert built into JavaScript for our web browser, 98 00:04:50,270 --> 00:04:53,030 and our web browser knows that when we call the alert function, 99 00:04:53,030 --> 00:04:55,370 the browser should display an alert message that 100 00:04:55,370 --> 00:04:57,300 looks a little something like that. 101 00:04:57,300 --> 00:04:59,720 And if I click the OK button to dismiss the alert, 102 00:04:59,720 --> 00:05:02,450 then we go ahead and get back the original page 103 00:05:02,450 --> 00:05:04,620 that I had from the beginning. 104 00:05:04,620 --> 00:05:07,940 And so now, we can begin to imagine that using this ability 105 00:05:07,940 --> 00:05:11,960 to programmatically display alerts, that we can add additional features 106 00:05:11,960 --> 00:05:13,460 to our applications as well. 107 00:05:13,460 --> 00:05:16,370 And one big area where JavaScript can be quite powerful 108 00:05:16,370 --> 00:05:18,240 is with event-driven programming. 109 00:05:18,240 --> 00:05:20,370 And what event-driven programming is all about 110 00:05:20,370 --> 00:05:25,145 is thinking about things that happen on the web in terms of events that happen. 111 00:05:25,145 --> 00:05:26,520 What are some examples of events? 112 00:05:26,520 --> 00:05:29,340 Events are things like the user clicks on a button, 113 00:05:29,340 --> 00:05:31,740 or the user selects something from a dropdown list, 114 00:05:31,740 --> 00:05:34,260 or the user scrolls through a list, or submits a form. 115 00:05:34,260 --> 00:05:37,870 Anything the user does can generally be thought of as an event. 116 00:05:37,870 --> 00:05:42,270 And what we can do with JavaScript is add event listeners or event handlers-- 117 00:05:42,270 --> 00:05:45,210 things that say when an event happens, go ahead 118 00:05:45,210 --> 00:05:49,020 and run this particular block of code or this function, for example. 119 00:05:49,020 --> 00:05:51,420 And using that, we can begin to allow our JavaScript 120 00:05:51,420 --> 00:05:55,860 code to respond to how the user is actually interacting with our web page 121 00:05:55,860 --> 00:05:58,080 to say when the user clicks on a button, I 122 00:05:58,080 --> 00:06:02,170 would like to run this particular JavaScript function, for example. 123 00:06:02,170 --> 00:06:04,380 So let's go ahead and give that a try. 124 00:06:04,380 --> 00:06:08,550 I'll go ahead and now instead of just saying, alert hello world, 125 00:06:08,550 --> 00:06:11,080 let me put this alert inside of a function. 126 00:06:11,080 --> 00:06:13,290 And to create a function in JavaScript, you just 127 00:06:13,290 --> 00:06:16,610 use the keyword function followed by the name of the function. 128 00:06:16,610 --> 00:06:18,630 I'll call the function hello, for example. 129 00:06:18,630 --> 00:06:21,465 And then in parentheses, any inputs that function takes. 130 00:06:21,465 --> 00:06:23,590 This hello function is not going to take any input, 131 00:06:23,590 --> 00:06:26,400 so I'll just use an empty set of parentheses. 132 00:06:26,400 --> 00:06:30,300 And then inside of curly braces, I include any of the code 133 00:06:30,300 --> 00:06:33,270 that I want to run in this function. 134 00:06:33,270 --> 00:06:36,632 And so what I've done here now is create a function called hello, 135 00:06:36,632 --> 00:06:38,340 and then inside of the curly braces, I've 136 00:06:38,340 --> 00:06:40,710 defined the body of the function-- what code should 137 00:06:40,710 --> 00:06:43,170 run when I run the hello function. 138 00:06:43,170 --> 00:06:45,150 And what the hello function should do is it 139 00:06:45,150 --> 00:06:49,270 should display an alert that, in this case, says hello, world. 140 00:06:49,270 --> 00:06:51,960 So now, what I'd like to do is get this function 141 00:06:51,960 --> 00:06:55,980 to run when something happens on the page-- for example, 142 00:06:55,980 --> 00:06:57,915 when a user clicks on a button. 143 00:06:57,915 --> 00:07:01,320 So to do that, the first thing I'll need to do is actually create a button. 144 00:07:01,320 --> 00:07:06,220 So I'll add a button that just says, like, click here, for example. 145 00:07:06,220 --> 00:07:11,160 So now if I refresh this page, I now see that I have hello 146 00:07:11,160 --> 00:07:13,260 and I also have this button that says click here, 147 00:07:13,260 --> 00:07:15,190 but when I click here, like, nothing happens. 148 00:07:15,190 --> 00:07:17,940 I'm clicking the Click Here button, but it's not changing anything 149 00:07:17,940 --> 00:07:20,430 because I haven't yet said what should happen when 150 00:07:20,430 --> 00:07:22,950 the user does click on this button. 151 00:07:22,950 --> 00:07:27,150 And so one way we could do this is by adding an attribute to this HTML 152 00:07:27,150 --> 00:07:30,450 element called onclick. 153 00:07:30,450 --> 00:07:33,480 What this is going to do is it's going to add an onclick 154 00:07:33,480 --> 00:07:34,620 handler to this button. 155 00:07:34,620 --> 00:07:38,250 It's going to say what should happen when the user clicks on this button. 156 00:07:38,250 --> 00:07:40,020 And I'm going to set the onclick attribute 157 00:07:40,020 --> 00:07:43,395 equal to running the function hello. 158 00:07:43,395 --> 00:07:45,270 And in order to run a function in JavaScript, 159 00:07:45,270 --> 00:07:47,160 just as you ran a function with Python, you 160 00:07:47,160 --> 00:07:50,370 use the name of the function followed by a set of parentheses 161 00:07:50,370 --> 00:07:52,740 to say, go ahead and actually run this function. 162 00:07:52,740 --> 00:07:54,920 Using those parentheses calls the function-- 163 00:07:54,920 --> 00:07:56,620 another word for running the function. 164 00:07:56,620 --> 00:07:59,120 And the fact that there's nothing in between the parentheses 165 00:07:59,120 --> 00:08:01,930 means we're not providing anything as input to the hello function, 166 00:08:01,930 --> 00:08:03,960 though if the hello function did take inputs, 167 00:08:03,960 --> 00:08:07,420 we could certainly add that in between the parentheses. 168 00:08:07,420 --> 00:08:10,800 So now, I've tied the two pieces of this page together. 169 00:08:10,800 --> 00:08:13,020 I have a button that says click here and I've 170 00:08:13,020 --> 00:08:16,860 added an onclick handler that says that when you click on the button, 171 00:08:16,860 --> 00:08:19,050 you should run the hello function. 172 00:08:19,050 --> 00:08:21,300 And then up above, I've defined the hello function 173 00:08:21,300 --> 00:08:23,050 to say what should the hello function do. 174 00:08:23,050 --> 00:08:24,967 Well, when the function is called, we're going 175 00:08:24,967 --> 00:08:28,840 to display an alert that in this case, says hello, world. 176 00:08:28,840 --> 00:08:32,309 So now, we should be able to refresh the page. 177 00:08:32,309 --> 00:08:34,309 We still see the same thing, at least initially, 178 00:08:34,309 --> 00:08:37,320 where it just says hello and a button that tells me to click here. 179 00:08:37,320 --> 00:08:39,750 But now if I go ahead and click the button that 180 00:08:39,750 --> 00:08:42,780 says click here, well, then I get the alert that says, 181 00:08:42,780 --> 00:08:44,760 this page says hello, world. 182 00:08:44,760 --> 00:08:45,562 I can press OK. 183 00:08:45,562 --> 00:08:47,520 And this event handler is always going to work. 184 00:08:47,520 --> 00:08:49,988 I click the button again, and I get the alert a second time 185 00:08:49,988 --> 00:08:51,780 because every time I click the button, it's 186 00:08:51,780 --> 00:08:53,610 going to call the hello function again. 187 00:08:53,610 --> 00:09:00,000 And when the hello function runs, it is going to display this particular alert. 188 00:09:00,000 --> 00:09:03,120 So this now appears to give us a fair amount of power. 189 00:09:03,120 --> 00:09:06,393 And much as in other programming languages, languages like Python 190 00:09:06,393 --> 00:09:08,310 or other languages you might have worked with, 191 00:09:08,310 --> 00:09:10,890 JavaScript has all these same types of language feature. 192 00:09:10,890 --> 00:09:13,835 So far, we've seen data types-- things like a string-- 193 00:09:13,835 --> 00:09:16,710 but we also have other data types that we'll take a look at soon too. 194 00:09:16,710 --> 00:09:19,740 We've seen functions-- some functions that are built into JavaScript, 195 00:09:19,740 --> 00:09:22,530 like the alert function, and other functions that we can write 196 00:09:22,530 --> 00:09:24,450 for ourselves, functions like hello-- 197 00:09:24,450 --> 00:09:27,690 but we also have the ability to include things like variables 198 00:09:27,690 --> 00:09:30,520 inside of our program as well. 199 00:09:30,520 --> 00:09:32,380 So what might that look like? 200 00:09:32,380 --> 00:09:36,605 Well, I'll go ahead and create a new file that we'll call counter.html. 201 00:09:36,605 --> 00:09:39,230 And counter is going to have some of the similar code to hello, 202 00:09:39,230 --> 00:09:41,070 so I'll just go ahead and copy it for now, 203 00:09:41,070 --> 00:09:45,480 but I'll clear out the script section, change the title from hello to counter. 204 00:09:45,480 --> 00:09:49,360 And now inside, I'll get rid of the button-- 205 00:09:49,360 --> 00:09:52,800 or actually, I'll keep the button, but instead of saying, click here, 206 00:09:52,800 --> 00:09:55,170 the button is going to say count. 207 00:09:55,170 --> 00:09:58,470 I'd like to create a program that just counts for me from 0 to 1 to 2, 208 00:09:58,470 --> 00:10:01,450 3, 4, so on and so forth. 209 00:10:01,450 --> 00:10:06,130 And now in order to do that, in order to have some way of counting repeatedly 0, 210 00:10:06,130 --> 00:10:10,590 1, 2, 3, 4, 5, I'm going to need to have some sort of variable inside 211 00:10:10,590 --> 00:10:14,190 of my program, something that is keeping track of data, like the number 212 00:10:14,190 --> 00:10:16,140 that I currently have counted to. 213 00:10:16,140 --> 00:10:20,580 So in order to do that in JavaScript, I can say something like let counter 214 00:10:20,580 --> 00:10:22,500 equal 0. 215 00:10:22,500 --> 00:10:25,650 This is the way in JavaScript that I define a new variable. 216 00:10:25,650 --> 00:10:30,520 I first say let counter, meaning let there be a new variable called counter, 217 00:10:30,520 --> 00:10:35,310 and I'm going to initially set the value of counter equal to the number 0. 218 00:10:35,310 --> 00:10:38,790 And now when I click on the button, instead of running the hello function, 219 00:10:38,790 --> 00:10:43,110 I'm going to go ahead and run the count function, which doesn't exist yet, 220 00:10:43,110 --> 00:10:44,630 but I'll now write it. 221 00:10:44,630 --> 00:10:47,730 I'll define a function called count. 222 00:10:47,730 --> 00:10:52,650 And what the count function is going to do is it is going to first increment 223 00:10:52,650 --> 00:10:53,535 the value of counter. 224 00:10:53,535 --> 00:10:55,410 And there are number of ways I could do that. 225 00:10:55,410 --> 00:11:00,150 One is by saying counter = counter + 1 to say, go ahead and reset 226 00:11:00,150 --> 00:11:02,538 the value of counter to whatever counter is plus 1. 227 00:11:02,538 --> 00:11:04,830 And there are a couple of shorthand notations for this. 228 00:11:04,830 --> 00:11:10,020 I could equivalently say counter += 1 to say, add 1 to the counter, 229 00:11:10,020 --> 00:11:13,260 or in the case of adding 1, JavaScript, much like languages like C 230 00:11:13,260 --> 00:11:17,130 if you've seen them before, support notation like this-- counter++, 231 00:11:17,130 --> 00:11:20,880 which just means take the value of counter and increment it-- add 1 to it. 232 00:11:20,880 --> 00:11:23,700 So I'll add 1 to the value of counter, and then I'll 233 00:11:23,700 --> 00:11:29,340 just display an alert that has whatever the current value of counter 234 00:11:29,340 --> 00:11:31,210 happens to be. 235 00:11:31,210 --> 00:11:33,090 And so I've incremented the value of counter, 236 00:11:33,090 --> 00:11:37,890 and then displayed an alert that shows me what's contained inside of counter. 237 00:11:37,890 --> 00:11:43,590 And so now if I go ahead and not go to hello.html, but to counter.html 238 00:11:43,590 --> 00:11:47,820 instead, I now see that I still see a button that says count. 239 00:11:47,820 --> 00:11:51,510 And if I click on that button, I get an alert that this time, says 1. 240 00:11:51,510 --> 00:11:54,330 We've incremented the value of counter from 0 to 1. 241 00:11:54,330 --> 00:11:57,030 The alert now says 1 and I can press OK. 242 00:11:57,030 --> 00:11:59,915 If I press count again, the count now goes to 2. 243 00:11:59,915 --> 00:12:02,790 If I press OK, press count again, it goes to 3. 244 00:12:02,790 --> 00:12:04,620 And every time I click count, it is going 245 00:12:04,620 --> 00:12:09,150 to increment the value of the variable counter inside of my JavaScript web 246 00:12:09,150 --> 00:12:12,120 page, and then it's going to display an alert that is going 247 00:12:12,120 --> 00:12:14,740 to contain the value of that variable. 248 00:12:14,740 --> 00:12:18,510 So using alerts now, we're able to manipulate-- we can inside a function, 249 00:12:18,510 --> 00:12:21,300 manipulate the values of variables, and then display alerts that 250 00:12:21,300 --> 00:12:23,680 show the contents of those variables. 251 00:12:23,680 --> 00:12:26,460 But ultimately when users are interacting with the page, 252 00:12:26,460 --> 00:12:28,890 it's going to be fairly annoying if the only way that we 253 00:12:28,890 --> 00:12:31,455 have to interact with the user is via displaying 254 00:12:31,455 --> 00:12:34,080 these alerts-- the equivalent of, like, printing something out, 255 00:12:34,080 --> 00:12:36,270 except instead of printing it to a terminal, 256 00:12:36,270 --> 00:12:39,003 we're printing it via an alert that appears on the screen. 257 00:12:39,003 --> 00:12:41,670 What would be more interesting, and more powerful, and much more 258 00:12:41,670 --> 00:12:45,600 useful in the context of a web page is if we could programmatically 259 00:12:45,600 --> 00:12:48,420 update the website-- change something about the web page 260 00:12:48,420 --> 00:12:51,450 that the user is actually seeing, changing the content that 261 00:12:51,450 --> 00:12:52,850 happens to be on the page. 262 00:12:52,850 --> 00:12:54,930 And it turns out JavaScript is going to enable 263 00:12:54,930 --> 00:12:58,350 us to do that as well because JavaScript allows us to manipulate 264 00:12:58,350 --> 00:13:02,520 the DOM-- the Document Object Model that represents all of the elements that 265 00:13:02,520 --> 00:13:05,200 happen to be on that page. 266 00:13:05,200 --> 00:13:09,810 So to do that, let's go ahead and return to hello.html. 267 00:13:09,810 --> 00:13:13,980 This again, was this web page that just said hello and gave me a button, 268 00:13:13,980 --> 00:13:17,640 where if I clicked on that button, it would display an alert that said, 269 00:13:17,640 --> 00:13:18,900 hello, world. 270 00:13:18,900 --> 00:13:23,430 Now what I'd like to do is instead of having the hello function display 271 00:13:23,430 --> 00:13:27,655 an alert, I'd like to have it manipulate something on the page. 272 00:13:27,655 --> 00:13:29,280 And what might I want it to manipulate? 273 00:13:29,280 --> 00:13:32,340 Well, inside the body of the page, I here have this heading-- 274 00:13:32,340 --> 00:13:34,710 this heading that just says hello, for example, 275 00:13:34,710 --> 00:13:37,050 which is inside of an h1 element. 276 00:13:37,050 --> 00:13:40,920 And what I might like to do is actually change that element. 277 00:13:40,920 --> 00:13:42,340 How can I do that? 278 00:13:42,340 --> 00:13:44,160 Well, it turns out that in JavaScript, we 279 00:13:44,160 --> 00:13:49,470 have access to a function called document.querySelector. 280 00:13:49,470 --> 00:13:51,940 And what document.querySelector is going to do 281 00:13:51,940 --> 00:13:56,310 is it is going to give us the ability to look through an HTML page 282 00:13:56,310 --> 00:14:00,870 and extract an element out of that page so that we can manipulate that HTML 283 00:14:00,870 --> 00:14:03,850 element using JavaScript code. 284 00:14:03,850 --> 00:14:06,690 And so if I want to select like an h1 element, 285 00:14:06,690 --> 00:14:08,940 I can say document.querySelector. 286 00:14:08,940 --> 00:14:12,330 And then as the argument, the input to document.querySelector, 287 00:14:12,330 --> 00:14:16,080 I'll go ahead and say each one, meaning go through the page, 288 00:14:16,080 --> 00:14:18,180 find me an h1 element. 289 00:14:18,180 --> 00:14:20,430 And querySelector is only going to return one element, 290 00:14:20,430 --> 00:14:23,160 so if there are multiple, it's going to return the first thing it finds. 291 00:14:23,160 --> 00:14:25,440 But here, we only have one h1 element, so it's OK. 292 00:14:25,440 --> 00:14:30,308 I'm going to say look through this document, try and find an h1 element, 293 00:14:30,308 --> 00:14:32,100 and when you do, I'd like to manipulate it. 294 00:14:32,100 --> 00:14:39,630 And the way I'd like to manipulate it is by saying .innerHTML =, let's say, 295 00:14:39,630 --> 00:14:42,170 goodbye, for example. 296 00:14:42,170 --> 00:14:46,070 So all right, what's going on 6 Well, right now initially when we first load 297 00:14:46,070 --> 00:14:48,800 the page, we have an h1-- a big heading at the top-- 298 00:14:48,800 --> 00:14:50,360 that just says hello. 299 00:14:50,360 --> 00:14:52,250 And now when this hello function is called, 300 00:14:52,250 --> 00:14:55,250 which is called when this button is clicked on because it has an onclick 301 00:14:55,250 --> 00:14:59,150 attribute that is equal to hello, calling the hello function, 302 00:14:59,150 --> 00:15:01,100 what the hello function is going to do is 303 00:15:01,100 --> 00:15:04,130 it's going to say document.querySelector h1. 304 00:15:04,130 --> 00:15:08,900 Find me the h1 element that will return this element right here-- 305 00:15:08,900 --> 00:15:12,260 the JavaScript representation of this HTML element 306 00:15:12,260 --> 00:15:16,950 that is just an h1, whose HTML inside of it says hello. 307 00:15:16,950 --> 00:15:19,610 And if I want to change that HTML, I can do that 308 00:15:19,610 --> 00:15:24,980 by modifying the innerHTML property of the JavaScript element. 309 00:15:24,980 --> 00:15:27,800 In order to update a property of anything in JavaScript, 310 00:15:27,800 --> 00:15:31,010 well generally use this dot notation, where dot accesses 311 00:15:31,010 --> 00:15:33,750 a property of some particular object. 312 00:15:33,750 --> 00:15:35,810 And so I have this element, this h1. 313 00:15:35,810 --> 00:15:40,770 And saying .innerHTML means take that element and access its innerHTML 314 00:15:40,770 --> 00:15:43,280 property, some property of that object. 315 00:15:43,280 --> 00:15:46,380 And I would like to update its innerHTML to just in this case 316 00:15:46,380 --> 00:15:51,120 be the word goodbye followed by an exclamation point, for example. 317 00:15:51,120 --> 00:15:54,110 So now, what we'll see is that when we run 318 00:15:54,110 --> 00:15:58,910 this page, when we open this page up as by opening up hello.html, 319 00:15:58,910 --> 00:16:00,830 I still see an h1 that says hello. 320 00:16:00,830 --> 00:16:02,990 I still see a button that says click here. 321 00:16:02,990 --> 00:16:07,080 But now when I actually click on the button click here, 322 00:16:07,080 --> 00:16:09,320 you'll see that hello changes to goodbye. 323 00:16:09,320 --> 00:16:13,040 We've run JavaScript code that finds an h1 element on the page 324 00:16:13,040 --> 00:16:17,310 and manipulates it, changing it to something else than it was originally. 325 00:16:17,310 --> 00:16:19,520 Now every time I click here, nothing else 326 00:16:19,520 --> 00:16:23,570 happens because every time I click here, it's going to find the same h1 327 00:16:23,570 --> 00:16:28,220 and it's going to update its HTML, changing it from hello to goodbye. 328 00:16:28,220 --> 00:16:30,650 So maybe what I'd really like then is the ability 329 00:16:30,650 --> 00:16:33,950 to toggle back and forth-- to toggle back and forth between hello 330 00:16:33,950 --> 00:16:37,350 and goodbye, rather than just change it from one thing to something else. 331 00:16:37,350 --> 00:16:40,360 Every time I click the button, I'd like it to alternate back and forth. 332 00:16:40,360 --> 00:16:42,860 And there are a number of ways you could imagine doing this, 333 00:16:42,860 --> 00:16:45,570 but one way is by taking advantage of conditions. 334 00:16:45,570 --> 00:16:48,650 So much in the same way that a language like Python has conditions-- 335 00:16:48,650 --> 00:16:50,600 if's, and elif's, and else's-- 336 00:16:50,600 --> 00:16:54,110 JavaScript too has if, and else if, and else that 337 00:16:54,110 --> 00:16:57,890 allow us to describe conditions, such that we can only 338 00:16:57,890 --> 00:17:02,330 run certain blocks of code when a particular Boolean expression is true, 339 00:17:02,330 --> 00:17:03,690 for example. 340 00:17:03,690 --> 00:17:05,099 So what would that look like? 341 00:17:05,099 --> 00:17:08,720 Well, let's go ahead and say inside of this hello function, 342 00:17:08,720 --> 00:17:10,160 I can ask a question. 343 00:17:10,160 --> 00:17:21,050 If document.querySelector h1 innerHTML is equal to hello, 344 00:17:21,050 --> 00:17:28,220 we'll then go ahead and set it to goodbye and else then go 345 00:17:28,220 --> 00:17:31,730 ahead and update the innerHTML of this h1 element, 346 00:17:31,730 --> 00:17:35,648 go ahead and set it to hello instead. 347 00:17:35,648 --> 00:17:37,190 So what is this hello function doing? 348 00:17:37,190 --> 00:17:38,898 It's now a little bit more sophisticated. 349 00:17:38,898 --> 00:17:42,290 It now has a condition where I say if-- the keyword if-- 350 00:17:42,290 --> 00:17:45,530 followed by in parentheses, the condition that I want to check for, 351 00:17:45,530 --> 00:17:48,080 the thing I want to see is this true or not. 352 00:17:48,080 --> 00:17:52,940 And what I'm checking for is let me run document.querySelector h1-- 353 00:17:52,940 --> 00:17:56,600 which again, looks through the page, finds me the h1 tag, 354 00:17:56,600 --> 00:17:58,460 and gets that element for me-- 355 00:17:58,460 --> 00:18:02,330 if I look at that innerHTML, if it is equal to hello, 356 00:18:02,330 --> 00:18:03,720 then I want to do something. 357 00:18:03,720 --> 00:18:06,380 And this triple equal sign here is JavaScript's way 358 00:18:06,380 --> 00:18:08,390 of checking for strict equality, checking 359 00:18:08,390 --> 00:18:11,030 to make sure the two values are equal and also 360 00:18:11,030 --> 00:18:12,740 that their types are the same thing-- 361 00:18:12,740 --> 00:18:15,482 that if this is a string, this must also be a string. 362 00:18:15,482 --> 00:18:17,690 It turns out in JavaScript, there's also a weaker way 363 00:18:17,690 --> 00:18:21,010 to check for equality that just uses two equal signs. 364 00:18:21,010 --> 00:18:24,140 And that is going to check that values are the same, 365 00:18:24,140 --> 00:18:27,460 but it's going to allow for a bit of differences in type. 366 00:18:27,460 --> 00:18:29,210 The two things might have different types, 367 00:18:29,210 --> 00:18:31,340 but so long as they're basically the same value, 368 00:18:31,340 --> 00:18:34,380 the double equal sign might generally come to be true. 369 00:18:34,380 --> 00:18:37,370 Usually if you can, you'll want to use this triple equal sign-- 370 00:18:37,370 --> 00:18:40,490 the strict equality-- to make sure that not only are the types the same, 371 00:18:40,490 --> 00:18:42,080 but the values are the same too. 372 00:18:42,080 --> 00:18:44,880 And the triple equal sign will check both of those things. 373 00:18:44,880 --> 00:18:48,770 So if I go ahead and find the h1 element and its innerHTML 374 00:18:48,770 --> 00:18:52,850 is the word hello, we'll then go ahead and find the h1 element 375 00:18:52,850 --> 00:18:57,890 and update its innerHTML, setting it equal to goodbye, for example. 376 00:18:57,890 --> 00:19:02,810 And else go ahead and find that same h1 element, update its innerHTML, 377 00:19:02,810 --> 00:19:04,490 set it equal to hello. 378 00:19:04,490 --> 00:19:08,210 And again, just as in functions, where we use these curly braces to enclose 379 00:19:08,210 --> 00:19:10,940 the body of the function-- all of lines of code that are inside 380 00:19:10,940 --> 00:19:11,810 of the function-- 381 00:19:11,810 --> 00:19:13,410 JavaScript does the same thing too-- 382 00:19:13,410 --> 00:19:16,910 that inside of a condition when we want to express that this is inside 383 00:19:16,910 --> 00:19:21,020 the body of an if condition, I can use curly braces to say this line of code 384 00:19:21,020 --> 00:19:24,740 and that line of code, that's inside of the if expression or that's inside 385 00:19:24,740 --> 00:19:27,492 of the else expression, for example. 386 00:19:27,492 --> 00:19:28,950 So let's go ahead and try this now. 387 00:19:28,950 --> 00:19:31,970 I can go ahead and open hello.html. 388 00:19:31,970 --> 00:19:32,470 Refresh it. 389 00:19:32,470 --> 00:19:35,900 It currently says hello with a button that says click here. 390 00:19:35,900 --> 00:19:40,730 And now when I click here, hello changes to goodbye. 391 00:19:40,730 --> 00:19:43,720 And when I click here again, goodbye changes back to hello. 392 00:19:43,720 --> 00:19:46,900 And every time I click the button, it's going to alternate between hello 393 00:19:46,900 --> 00:19:50,050 and goodbye because we either get caught in the if expression 394 00:19:50,050 --> 00:19:52,817 or we get caught in the else expression. 395 00:19:52,817 --> 00:19:55,400 Now, there are a couple of places where you might look at this 396 00:19:55,400 --> 00:19:58,420 and notice that maybe this isn't as efficient as this code could 397 00:19:58,420 --> 00:19:59,530 potentially be. 398 00:19:59,530 --> 00:20:03,380 And recall that every time we run document.querySelector to say, 399 00:20:03,380 --> 00:20:07,270 go ahead and try and find a particular HTML element for me, 400 00:20:07,270 --> 00:20:10,480 it's going to look through that page trying to find the h1 element. 401 00:20:10,480 --> 00:20:14,220 And it turns out that right now, we have three separate calls to querySelector, 402 00:20:14,220 --> 00:20:15,970 even though only two of them will ever run 403 00:20:15,970 --> 00:20:17,740 on any given instance of the function. 404 00:20:17,740 --> 00:20:20,290 But we call document.querySelector, then we call it 405 00:20:20,290 --> 00:20:22,600 again inside of the if expression. 406 00:20:22,600 --> 00:20:26,620 We can probably improve the design of this page by factoring that out, 407 00:20:26,620 --> 00:20:30,790 by just looking for the h1 element once, and then manipulating it and checking 408 00:20:30,790 --> 00:20:33,660 it using that element that we have found. 409 00:20:33,660 --> 00:20:36,790 And to do that, we can store an element inside of a variable. 410 00:20:36,790 --> 00:20:39,490 In the same way that a variable can store a number, 411 00:20:39,490 --> 00:20:41,860 like a counter, or a string, like hello world, 412 00:20:41,860 --> 00:20:44,830 it can also store other values like an HTML element 413 00:20:44,830 --> 00:20:48,370 that we get back from document.querySelector. 414 00:20:48,370 --> 00:20:53,080 So I could say something like let heading, 415 00:20:53,080 --> 00:20:55,120 where heading is just the name of a variable, 416 00:20:55,120 --> 00:21:00,050 be equal to document.querySelector h1, for instance. 417 00:21:00,050 --> 00:21:01,240 Find the h1 element. 418 00:21:01,240 --> 00:21:03,760 Save it inside of a variable called heading. 419 00:21:03,760 --> 00:21:06,370 And now rather than document.querySelector h1 420 00:21:06,370 --> 00:21:11,650 all the time, I can just say if the heading's innerHTML is hello, then set 421 00:21:11,650 --> 00:21:13,990 the heading's innerHTML to goodbye. 422 00:21:13,990 --> 00:21:17,053 Otherwise, set the heading's innerHTML to hello. 423 00:21:17,053 --> 00:21:18,970 So I've improve the efficiency of the program, 424 00:21:18,970 --> 00:21:21,192 but also reduced the number of characters of code 425 00:21:21,192 --> 00:21:22,150 that I've had to write. 426 00:21:22,150 --> 00:21:24,700 My lines are now much shorter, a little bit easier to read. 427 00:21:24,700 --> 00:21:27,853 This we would consider to be an improvement in design. 428 00:21:27,853 --> 00:21:29,770 And it turns out there's one other improvement 429 00:21:29,770 --> 00:21:34,120 we can make here too that we can define a variable like let something 430 00:21:34,120 --> 00:21:36,970 equal something else, but it turns out that JavaScript gives us 431 00:21:36,970 --> 00:21:39,620 a couple of ways to define a variable. 432 00:21:39,620 --> 00:21:43,210 And if we're going to be creating a variable whose value is never 433 00:21:43,210 --> 00:21:46,990 going to change, we're never going to reassign the variable name to something 434 00:21:46,990 --> 00:21:50,320 else, then instead of let, we can enforce 435 00:21:50,320 --> 00:21:54,280 that it's never going to change by calling it a const variable. 436 00:21:54,280 --> 00:21:58,170 So const heading = document.querySelector h1 437 00:21:58,170 --> 00:22:01,030 means I am going to create a variable called heading, setting 438 00:22:01,030 --> 00:22:05,050 it equal to the result of document.querySelector h1 and never 439 00:22:05,050 --> 00:22:07,788 again will I change what heading is equal to. 440 00:22:07,788 --> 00:22:09,580 I will never have another line of code that 441 00:22:09,580 --> 00:22:13,150 says heading equals something else because it is constant. 442 00:22:13,150 --> 00:22:16,430 And JavaScript will then enforce that this variable should not change. 443 00:22:16,430 --> 00:22:19,520 And if ever I do try to change it, JavaScript will give me an error. 444 00:22:19,520 --> 00:22:23,500 And this can just be helpful to prevent against possible unintended behavior-- 445 00:22:23,500 --> 00:22:26,590 that if you know you have a variable that is never going to change, 446 00:22:26,590 --> 00:22:29,890 it's often good design to label it as a const variable 447 00:22:29,890 --> 00:22:32,020 so that you and other people looking at your code 448 00:22:32,020 --> 00:22:36,820 know that that is never going to have a value that gets changed later on. 449 00:22:36,820 --> 00:22:40,330 So this then will behave the same way where it says hello, 450 00:22:40,330 --> 00:22:44,020 but I can toggle it back and forth, changing it to goodbye, 451 00:22:44,020 --> 00:22:46,910 and then changing it back to hello again. 452 00:22:46,910 --> 00:22:50,480 And so now using this ability-- this ability to manipulate the DOM-- 453 00:22:50,480 --> 00:22:53,920 we can go back to our counter program and actually improve upon it. 454 00:22:53,920 --> 00:22:59,110 Right now the counter program, I count and it displays an alert that says one. 455 00:22:59,110 --> 00:23:01,630 I count and it displays an alert that says two. 456 00:23:01,630 --> 00:23:03,950 I can probably do a little bit better than that 457 00:23:03,950 --> 00:23:06,370 by instead of displaying an alert, actually 458 00:23:06,370 --> 00:23:09,130 manipulating the DOM in some way-- 459 00:23:09,130 --> 00:23:10,930 that I would like to have this h1-- 460 00:23:10,930 --> 00:23:12,400 this big heading at the top-- 461 00:23:12,400 --> 00:23:17,350 instead of starting up by saying hello, let's have it start out by saying zero, 462 00:23:17,350 --> 00:23:20,800 for example-- just some initial value for the counter. 463 00:23:20,800 --> 00:23:22,990 And now when I increment the value of counter, 464 00:23:22,990 --> 00:23:26,140 rather than display an alert that just tells me the value of the counter 465 00:23:26,140 --> 00:23:36,670 in an alert, I'm going to instead say document.querySelector h1 .innerHTML = 466 00:23:36,670 --> 00:23:41,940 counter, where I'm saying find the h1 element, update its innerHTML, 467 00:23:41,940 --> 00:23:46,360 set it equal to whatever the value of the variable counter happens to be, 468 00:23:46,360 --> 00:23:50,350 such that now if I refresh this page, the value of this h1 initially is zero. 469 00:23:50,350 --> 00:23:51,582 That's the initial value. 470 00:23:51,582 --> 00:23:53,290 But every time I click count, we're going 471 00:23:53,290 --> 00:23:55,940 to update the contents of that h1 element. 472 00:23:55,940 --> 00:23:59,320 And this time, setting it to 1, 2, 3, 4, and so forth. 473 00:23:59,320 --> 00:24:01,090 Every time I click the count button, it's 474 00:24:01,090 --> 00:24:03,100 going to increment the value of the variable, 475 00:24:03,100 --> 00:24:06,760 as well as manipulate the DOM, actually making changes 476 00:24:06,760 --> 00:24:12,280 in order to produce the effect that I want to see on this actual page. 477 00:24:12,280 --> 00:24:15,190 And we can begin to add additional logic to this as well. 478 00:24:15,190 --> 00:24:17,470 Maybe I do occasionally want an alert, but I 479 00:24:17,470 --> 00:24:19,330 don't want an alert every single time. 480 00:24:19,330 --> 00:24:20,350 I could add a condition. 481 00:24:20,350 --> 00:24:23,620 I could say something like if I only want to display an alert every time I 482 00:24:23,620 --> 00:24:26,740 count to a multiple of 10-- like 10, and 20, and 30, and 40, and 50, 483 00:24:26,740 --> 00:24:27,890 and so forth-- 484 00:24:27,890 --> 00:24:32,350 I could add a condition that says that if counter mod 10-- 485 00:24:32,350 --> 00:24:35,227 and mod just gets the remainder when you divide by 10-- 486 00:24:35,227 --> 00:24:37,060 so if you take the counter, divide it by 10, 487 00:24:37,060 --> 00:24:40,430 if the remainder is 0 when I divide by 10, 488 00:24:40,430 --> 00:24:42,660 well, that means counter is a multiple of 10, 489 00:24:42,660 --> 00:24:47,400 and so I can now display an alert, where I can display an alert that says, like, 490 00:24:47,400 --> 00:24:52,138 I want to say something like the counter is now 10 or the counter is now 20. 491 00:24:52,138 --> 00:24:54,180 And in order to do that, what I really want to do 492 00:24:54,180 --> 00:24:57,660 is have some way of plugging in a variable 493 00:24:57,660 --> 00:25:00,753 into a string inside of JavaScript. 494 00:25:00,753 --> 00:25:02,670 And in Python, the way we would have done this 495 00:25:02,670 --> 00:25:07,870 is by prepending f in front of the string to create a formatted string. 496 00:25:07,870 --> 00:25:11,040 And then I would have said something like the count is now, 497 00:25:11,040 --> 00:25:13,770 and then I'd use curly braces to say go ahead 498 00:25:13,770 --> 00:25:15,600 and print out the value of counter. 499 00:25:15,600 --> 00:25:17,850 So this f for formatted string followed by this string 500 00:25:17,850 --> 00:25:20,475 would have been the way in Python that we would have done this. 501 00:25:20,475 --> 00:25:22,740 It turns out JavaScript does the same thing, just 502 00:25:22,740 --> 00:25:24,120 with slightly different syntax. 503 00:25:24,120 --> 00:25:25,690 It doesn't use f. 504 00:25:25,690 --> 00:25:30,300 Instead of using the regular quotation marks or the single or double quotation 505 00:25:30,300 --> 00:25:35,650 marks, JavaScript uses these backticks, which are usually located above the Tab 506 00:25:35,650 --> 00:25:38,468 key on a standard US keyboard. 507 00:25:38,468 --> 00:25:40,260 And this is going to create what JavaScript 508 00:25:40,260 --> 00:25:42,510 calls a template literal, where I can then 509 00:25:42,510 --> 00:25:47,130 substitute the value of a variable somewhere inside of this template. 510 00:25:47,130 --> 00:25:49,530 And then in order to actually do the substitution, 511 00:25:49,530 --> 00:25:53,100 while Python uses double curly braces to say plug-in the value of counter 512 00:25:53,100 --> 00:25:55,450 right here, JavaScript does something similar. 513 00:25:55,450 --> 00:25:57,540 It also uses double curly braces, but there 514 00:25:57,540 --> 00:25:59,280 needs to be dollar sign in front of it. 515 00:25:59,280 --> 00:26:02,070 The dollar sign, and then the double curly braces 516 00:26:02,070 --> 00:26:06,220 mean go ahead and plug-in the value of a variable there. 517 00:26:06,220 --> 00:26:09,330 So this then is a template literal, where every time we 518 00:26:09,330 --> 00:26:12,300 get to a multiple of 10, we're going to display an alert that says, 519 00:26:12,300 --> 00:26:15,720 the count is now, and then this dollar sign curly brace 520 00:26:15,720 --> 00:26:19,230 means actually plug-in whatever the value of counter 521 00:26:19,230 --> 00:26:22,240 happens to be right there. 522 00:26:22,240 --> 00:26:25,410 So now if I go ahead and refresh counter, it starts at 0. 523 00:26:25,410 --> 00:26:28,860 I can count 3, 4, 5, 6, 7, 8, 9, but when I get to 10, 524 00:26:28,860 --> 00:26:32,100 then I get an alert that says the count is now 10, and then I 525 00:26:32,100 --> 00:26:35,420 see the result update on the page. 526 00:26:35,420 --> 00:26:39,390 And so that template literal can allow us to combine variables and strings 527 00:26:39,390 --> 00:26:43,530 in order to generate new strings that are able to represent data inside 528 00:26:43,530 --> 00:26:45,753 of them as well. 529 00:26:45,753 --> 00:26:47,920 So now, what improvements can we begin to make here? 530 00:26:47,920 --> 00:26:50,880 What changes can we make to this to improve upon the design of it? 531 00:26:50,880 --> 00:26:52,860 Well, one thing, especially as our programs 532 00:26:52,860 --> 00:26:55,860 get a little bit more sophisticated, a little bit more complicated 533 00:26:55,860 --> 00:26:59,760 is that we often don't want to be intermingling our JavaScript 534 00:26:59,760 --> 00:27:02,340 code with the contents of our HTML. 535 00:27:02,340 --> 00:27:05,250 Down here, we have button onclick="count," 536 00:27:05,250 --> 00:27:06,600 this name of this function. 537 00:27:06,600 --> 00:27:09,450 And especially as our page starts to get more complicated, 538 00:27:09,450 --> 00:27:12,660 it's going to start to get a little bit annoying if we're constantly 539 00:27:12,660 --> 00:27:14,940 having to maintain a little bit of JavaScript code, 540 00:27:14,940 --> 00:27:17,408 like making a call to a function, inside of our HTML. 541 00:27:17,408 --> 00:27:20,700 We'll see a little bit later, there are other paradigms that actually encourage 542 00:27:20,700 --> 00:27:24,180 this type of thing, but right now, it can start to get a little poorly 543 00:27:24,180 --> 00:27:27,570 designed, as we'd really like to separate all of our JavaScript-related 544 00:27:27,570 --> 00:27:29,530 code from all of the HTML-- 545 00:27:29,530 --> 00:27:31,790 the general structure of our page. 546 00:27:31,790 --> 00:27:34,780 And so there are ways we can begin to do that as well. 547 00:27:34,780 --> 00:27:39,840 I can add an event listener inside of JavaScript too that I can say something 548 00:27:39,840 --> 00:27:53,020 like document.querySelector button, and then I can say .onclick = count. 549 00:27:53,020 --> 00:27:54,160 So what's going on here? 550 00:27:54,160 --> 00:27:57,280 And I can do this instead of this onclick="count." 551 00:27:57,280 --> 00:28:00,700 What I'm now saying is document.querySelector button, 552 00:28:00,700 --> 00:28:02,083 find me the button on the page. 553 00:28:02,083 --> 00:28:04,000 And it turns out there's only one button here, 554 00:28:04,000 --> 00:28:05,560 so it's fine, though if there were more, I might 555 00:28:05,560 --> 00:28:07,390 have to be a little bit more specific. 556 00:28:07,390 --> 00:28:12,400 But once I get that button, then I'm going to access its onclick property 557 00:28:12,400 --> 00:28:15,160 and I'm going to set it equal to count. 558 00:28:15,160 --> 00:28:16,570 And what is count? 559 00:28:16,570 --> 00:28:18,280 Count is the name of a function. 560 00:28:18,280 --> 00:28:20,270 Count is itself a function. 561 00:28:20,270 --> 00:28:22,360 And so what I'm here saying is I would like 562 00:28:22,360 --> 00:28:25,648 to set the value of the onclick property of the button 563 00:28:25,648 --> 00:28:27,940 equal to count-- that count is the function that should 564 00:28:27,940 --> 00:28:31,610 run when the button is clicked on. 565 00:28:31,610 --> 00:28:34,330 And notice that I am not actually calling the function. 566 00:28:34,330 --> 00:28:36,340 It's not count, and then parentheses, which 567 00:28:36,340 --> 00:28:39,670 would mean run the count function, and then get its return value 568 00:28:39,670 --> 00:28:42,010 and use that as the value for onclick. 569 00:28:42,010 --> 00:28:46,150 I'm just setting onclick equal literally to the count function itself 570 00:28:46,150 --> 00:28:48,110 without actually calling the function. 571 00:28:48,110 --> 00:28:50,050 And what this is going to do is it is going 572 00:28:50,050 --> 00:28:52,330 to say when the button is clicked on, then 573 00:28:52,330 --> 00:28:55,720 and only then should you actually run this count function. 574 00:28:55,720 --> 00:28:59,890 And we're not going to run the count function until that button actually 575 00:28:59,890 --> 00:29:00,940 gets clicked on. 576 00:29:00,940 --> 00:29:05,170 And so in JavaScript, functions can be treated as values of their own. 577 00:29:05,170 --> 00:29:08,050 Just as you can set a variable equal to a string, 578 00:29:08,050 --> 00:29:10,240 just as you can set a variable equal to an integer, 579 00:29:10,240 --> 00:29:13,000 just as you can set a variable equal to, like, an HTML element, 580 00:29:13,000 --> 00:29:15,340 like the result of document.querySelector, 581 00:29:15,340 --> 00:29:20,020 you can also set a variable equal to a function-- something like count-- 582 00:29:20,020 --> 00:29:24,230 and pass that around as a value, just as you could with any other value. 583 00:29:24,230 --> 00:29:27,280 And this is a paradigm we generally call functional programming, where 584 00:29:27,280 --> 00:29:31,300 we have functions as values of their own-- things that we can reassign, 585 00:29:31,300 --> 00:29:35,600 things that we can manipulate just as we could any other value. 586 00:29:35,600 --> 00:29:39,583 So now, I can try and run this program by going ahead and refreshing the page. 587 00:29:39,583 --> 00:29:40,250 I'll refresh it. 588 00:29:40,250 --> 00:29:41,080 It's 0. 589 00:29:41,080 --> 00:29:42,690 I press count. 590 00:29:42,690 --> 00:29:44,930 And all right, nothing seems to be happening. 591 00:29:44,930 --> 00:29:45,520 It's still 0. 592 00:29:45,520 --> 00:29:49,000 I want it to be counting, but it doesn't seem to be working. 593 00:29:49,000 --> 00:29:49,960 So why not? 594 00:29:49,960 --> 00:29:51,777 Anytime you run into problems in JavaScript 595 00:29:51,777 --> 00:29:54,110 where you're not getting the behavior you want, often it 596 00:29:54,110 --> 00:29:56,560 can be helpful to look at the JavaScript console, 597 00:29:56,560 --> 00:29:59,620 where the JavaScript console is the equivalent of, like, the terminal 598 00:29:59,620 --> 00:30:02,440 window when you were running your Django application in Python 599 00:30:02,440 --> 00:30:04,270 that would display any error messages. 600 00:30:04,270 --> 00:30:07,480 The JavaScript console will display any of the JavaScript logging 601 00:30:07,480 --> 00:30:10,390 information and error messages as well. 602 00:30:10,390 --> 00:30:12,670 In Chrome, I can get to it if I first go ahead 603 00:30:12,670 --> 00:30:17,578 and go to inspect, and then just open up the Console tab here. 604 00:30:17,578 --> 00:30:19,870 And all right, we seem to have some sort of error here. 605 00:30:19,870 --> 00:30:26,650 It's an Uncaught TypeError that says we cannot set property onclick of null 606 00:30:26,650 --> 00:30:29,095 in counter.html line 18. 607 00:30:29,095 --> 00:30:31,720 So that will generally tell you where the error is coming from. 608 00:30:31,720 --> 00:30:34,660 It's coming from counter.html on line 18. 609 00:30:34,660 --> 00:30:36,700 And the problem seems to be that I'm trying 610 00:30:36,700 --> 00:30:40,060 to access the onclick property of null. 611 00:30:40,060 --> 00:30:42,160 And null is JavaScript's way of expressing, like, 612 00:30:42,160 --> 00:30:45,670 nothing-- some object that doesn't exist. 613 00:30:45,670 --> 00:30:48,400 So somehow, I'm trying to set the onclick property of null. 614 00:30:48,400 --> 00:30:51,070 Well, let's see what's going on line 18, and see if we 615 00:30:51,070 --> 00:30:54,050 can figure out what's happening there. 616 00:30:54,050 --> 00:30:57,880 Well, all right, here's line 18, where I say document.querySelector button, 617 00:30:57,880 --> 00:31:01,150 setting it's onclick property equal to count. 618 00:31:01,150 --> 00:31:03,260 And now, what seems to be the problem here? 619 00:31:03,260 --> 00:31:05,440 Well, the error message was that I was trying 620 00:31:05,440 --> 00:31:08,530 to modify the onclick property of null. 621 00:31:08,530 --> 00:31:11,170 Well, here then is the onclick property, so why 622 00:31:11,170 --> 00:31:14,950 would this document.querySelector button be returning or giving me 623 00:31:14,950 --> 00:31:16,960 an output of null? 624 00:31:16,960 --> 00:31:20,020 Well, it turns out that document.querySelector will return null 625 00:31:20,020 --> 00:31:23,540 if it's not able to find something-- if I try and find a button, 626 00:31:23,540 --> 00:31:25,420 but it's not able to find a button. 627 00:31:25,420 --> 00:31:27,628 Well, this seems a little bit strange because there's 628 00:31:27,628 --> 00:31:31,360 a button down here on line 24 that I'd like for my JavaScript code 629 00:31:31,360 --> 00:31:34,120 to be able to find when it runs querySelector and tries 630 00:31:34,120 --> 00:31:35,338 to find the button. 631 00:31:35,338 --> 00:31:38,380 As it turns out, this is a bit of a quirk of the way the browser is going 632 00:31:38,380 --> 00:31:41,560 to work, but if the browser is running our code from top to bottom, 633 00:31:41,560 --> 00:31:46,060 just reading it from line 1 on and on, then it's going to get to line 18, 634 00:31:46,060 --> 00:31:49,870 where I've said document.querySelector button .onclick = count, 635 00:31:49,870 --> 00:31:52,630 and it's going to try and find a button on line 18, 636 00:31:52,630 --> 00:31:57,200 but the button doesn't show up in my HTML page until much further down 637 00:31:57,200 --> 00:31:57,850 in the page. 638 00:31:57,850 --> 00:32:00,700 So at this point, when we get to this line of JavaScript, 639 00:32:00,700 --> 00:32:03,310 JavaScript is looking for the button, but the DOM-- 640 00:32:03,310 --> 00:32:04,663 the body of the page-- 641 00:32:04,663 --> 00:32:05,830 hasn't finished loading yet. 642 00:32:05,830 --> 00:32:08,440 The content of the DOM has not yet loaded. 643 00:32:08,440 --> 00:32:11,857 And as a result, we're not able to find this button. 644 00:32:11,857 --> 00:32:13,190 So how do we solve this problem? 645 00:32:13,190 --> 00:32:16,180 How do we get it so we actually are able to, like, ask for the button 646 00:32:16,180 --> 00:32:17,462 and actually get the button? 647 00:32:17,462 --> 00:32:20,170 Well, it turns out there are a couple of strategies we could use. 648 00:32:20,170 --> 00:32:23,230 One would be take the script tag and go ahead and just move it 649 00:32:23,230 --> 00:32:26,440 to the bottom section of the body, so that after we've already 650 00:32:26,440 --> 00:32:29,800 defined the button that says count, then we have the script tag that then says, 651 00:32:29,800 --> 00:32:31,633 all right, go ahead and now find the button, 652 00:32:31,633 --> 00:32:33,110 and now we'll be able to find it. 653 00:32:33,110 --> 00:32:36,250 It turns out another way, and perhaps the more common way, 654 00:32:36,250 --> 00:32:39,822 is to instead add yet another event listener. 655 00:32:39,822 --> 00:32:42,280 And we're going to add an event listener not to the button, 656 00:32:42,280 --> 00:32:45,760 but to the entire document, where document is a variable built 657 00:32:45,760 --> 00:32:48,490 into this JavaScript that we have access to on the web page 658 00:32:48,490 --> 00:32:51,630 that just refers to this entire web document, where I've 659 00:32:51,630 --> 00:32:55,600 document.querySelector already to look through the whole web document trying 660 00:32:55,600 --> 00:32:59,050 to find a button or trying to find an h1 tag, for example. 661 00:32:59,050 --> 00:33:03,460 But I can also add an event listener to the document itself. 662 00:33:03,460 --> 00:33:09,340 And in order to do that, I can say document.addEventListener. 663 00:33:09,340 --> 00:33:12,873 And when I call addEventListener-- and I can do this on any HTML element, 664 00:33:12,873 --> 00:33:15,040 not just the document, but I could run this function 665 00:33:15,040 --> 00:33:18,610 on a button, or on an h1 element, or any other HTML element. 666 00:33:18,610 --> 00:33:22,930 addEventListener will generally take two arguments, where the first is 667 00:33:22,930 --> 00:33:24,843 what event I want to listen for. 668 00:33:24,843 --> 00:33:27,760 The event could be something like click, when I click on the document. 669 00:33:27,760 --> 00:33:31,620 It could be something like when I scroll through a page, for example. 670 00:33:31,620 --> 00:33:34,120 But with the event I'm going to listen for is a particularly 671 00:33:34,120 --> 00:33:38,380 special event called DOMContentLoaded. 672 00:33:38,380 --> 00:33:40,990 And the DOMContentLoaded event is an event 673 00:33:40,990 --> 00:33:44,350 that is going to be fired or triggered when the DOM-- 674 00:33:44,350 --> 00:33:46,780 the Document Object Model, the structure of the page-- 675 00:33:46,780 --> 00:33:47,560 is done loading. 676 00:33:47,560 --> 00:33:49,900 When all of the elements on the page are done loading, 677 00:33:49,900 --> 00:33:52,540 the DOM content has been loaded, and then 678 00:33:52,540 --> 00:33:54,610 if I attach an event listener to it, it'll 679 00:33:54,610 --> 00:33:57,220 run whatever code I want to run that should only 680 00:33:57,220 --> 00:34:01,660 run after the DOM is fully loaded, after all of the content on the page 681 00:34:01,660 --> 00:34:03,490 has then been loaded. 682 00:34:03,490 --> 00:34:06,370 And the second argument to addEventListener 683 00:34:06,370 --> 00:34:10,270 is what function should run once the event actually happens, 684 00:34:10,270 --> 00:34:12,400 when the DOMContentLoaded does happen. 685 00:34:12,400 --> 00:34:14,590 So I could pass in the name of a function 686 00:34:14,590 --> 00:34:17,679 if I had the name of a function that I wanted to pass in, 687 00:34:17,679 --> 00:34:22,510 but alternatively, JavaScript allows me to just directly write a function here 688 00:34:22,510 --> 00:34:24,760 in the argument to addEventListener. 689 00:34:24,760 --> 00:34:28,360 I can just say function, and then a set of parentheses to mean the function 690 00:34:28,360 --> 00:34:31,659 doesn't take any input, and then in curly braces, 691 00:34:31,659 --> 00:34:37,000 I can include the body of the function right here as the second argument 692 00:34:37,000 --> 00:34:38,082 to addEventListener. 693 00:34:38,082 --> 00:34:39,790 And this is a little bit of tricky syntax 694 00:34:39,790 --> 00:34:41,830 to wrap your mind around if you've never seen it before, 695 00:34:41,830 --> 00:34:43,630 but the big picture way to think of it is 696 00:34:43,630 --> 00:34:47,110 addEventListener takes two arguments-- one is the event, 697 00:34:47,110 --> 00:34:48,679 the second is the function. 698 00:34:48,679 --> 00:34:51,219 So here first is the event DOMContentLoaded. 699 00:34:51,219 --> 00:34:53,770 And the second argument is a function. 700 00:34:53,770 --> 00:34:56,710 And I would declare the function same as before, just using function. 701 00:34:56,710 --> 00:34:59,890 I haven't given the function a name because strictly speaking, 702 00:34:59,890 --> 00:35:01,090 it doesn't need a name. 703 00:35:01,090 --> 00:35:03,310 I'm never going to refer to this function by name. 704 00:35:03,310 --> 00:35:07,840 So it is what we might call an anonymous function-- a function that has no name, 705 00:35:07,840 --> 00:35:10,630 but I'm still passing it into the addEventListener function 706 00:35:10,630 --> 00:35:14,920 as an argument because I want to run the code inside of the function 707 00:35:14,920 --> 00:35:16,940 once the DOM has done loading. 708 00:35:16,940 --> 00:35:20,170 And so inside of curly braces then is the content of that function-- 709 00:35:20,170 --> 00:35:23,860 the content of what code should run when the DOM is done loading. 710 00:35:23,860 --> 00:35:26,800 And then at the end, I again use just this end parenthesis, 711 00:35:26,800 --> 00:35:30,070 where that end parenthesis lines up with this parenthesis here. 712 00:35:30,070 --> 00:35:34,240 This is enclosing all of the arguments to addEventListener, 713 00:35:34,240 --> 00:35:37,300 where the first one is DOMContentLoaded and the second one 714 00:35:37,300 --> 00:35:40,480 is this entire function that might span multiple lines. 715 00:35:40,480 --> 00:35:44,560 So you'll see syntax like this quite a bit in JavaScript. 716 00:35:44,560 --> 00:35:48,460 But now, what I want to do is adding the event listener to the button. 717 00:35:48,460 --> 00:35:51,590 I can go ahead and just replace and put it here. 718 00:35:51,590 --> 00:35:55,330 And it turns out that if I wanted to instead of saying .onclick = count, 719 00:35:55,330 --> 00:35:57,760 you could have used the same syntax of addEventListener. 720 00:35:57,760 --> 00:36:01,690 I could say addEventListener click, and then 721 00:36:01,690 --> 00:36:04,870 count to mean when the click event happens, 722 00:36:04,870 --> 00:36:06,680 go ahead and run the count function. 723 00:36:06,680 --> 00:36:11,140 But you can equivalently shorthand this and just say .onclick = count, 724 00:36:11,140 --> 00:36:13,150 and that would work just as well. 725 00:36:13,150 --> 00:36:16,780 So now, what we're saying here is that wait until the DOM has done loaded, 726 00:36:16,780 --> 00:36:20,140 wait until all the content on the page is loaded, and then go ahead 727 00:36:20,140 --> 00:36:21,577 and run this function. 728 00:36:21,577 --> 00:36:23,410 And what the function is going to do is it's 729 00:36:23,410 --> 00:36:26,220 going to add the event handler to this button. 730 00:36:26,220 --> 00:36:29,770 And that will work because now, we'll be able to find the button because now, 731 00:36:29,770 --> 00:36:32,740 all of the content of the DOM has loaded. 732 00:36:32,740 --> 00:36:36,100 So now, if I go back, refresh counter.html, 733 00:36:36,100 --> 00:36:38,290 you'll notice that the JavaScript error goes away. 734 00:36:38,290 --> 00:36:40,750 I don't seem to have that error anymore. 735 00:36:40,750 --> 00:36:43,540 And now if I press count, we're able to see the count 736 00:36:43,540 --> 00:36:46,700 increment just as before as well. 737 00:36:46,700 --> 00:36:48,940 And so this then is an improvement upon what 738 00:36:48,940 --> 00:36:53,080 I've had before, where now I'm able to separate out my JavaScript 739 00:36:53,080 --> 00:36:56,110 code from all of the rest of my code as well. 740 00:36:56,110 --> 00:36:58,480 But much as in the case of CSS, where we were 741 00:36:58,480 --> 00:37:01,860 able to take CSS that was originally located in the head of our page 742 00:37:01,860 --> 00:37:04,990 and move it into a separate file, you can do the same thing with JavaScript 743 00:37:04,990 --> 00:37:05,530 too. 744 00:37:05,530 --> 00:37:07,660 And this can be helpful if you have multiple people working 745 00:37:07,660 --> 00:37:08,452 on different files. 746 00:37:08,452 --> 00:37:11,050 You want one person working on the HTML and someone else 747 00:37:11,050 --> 00:37:12,580 working on the JavaScript. 748 00:37:12,580 --> 00:37:15,255 It can be helpful if you expect that one of these things 749 00:37:15,255 --> 00:37:17,380 is going to change more frequently than the others, 750 00:37:17,380 --> 00:37:19,820 so you might not need to load the other one as often. 751 00:37:19,820 --> 00:37:24,280 So there can be value in separating our HTML code from our JavaScript even more 752 00:37:24,280 --> 00:37:27,130 by moving our JavaScript into a separate file. 753 00:37:27,130 --> 00:37:30,760 And so in order to do that, I can create a new file 754 00:37:30,760 --> 00:37:35,620 that I'll just call counter.js, which will contain all of the JavaScript 755 00:37:35,620 --> 00:37:38,870 for my counter.html file. 756 00:37:38,870 --> 00:37:41,380 So in order to do that, what I can say is let's go ahead 757 00:37:41,380 --> 00:37:44,320 and copy all of this JavaScript code. 758 00:37:44,320 --> 00:37:48,220 Go ahead and cut it out of this page, and I'll paste it into counter.js. 759 00:37:48,220 --> 00:37:50,570 Remove some of that indentation. 760 00:37:50,570 --> 00:37:54,520 So now, I have a file called counter.js that 761 00:37:54,520 --> 00:38:00,460 just contains all of the JavaScript I want to run on my counter.html page. 762 00:38:00,460 --> 00:38:04,510 And now rather than include actual JavaScript in between these script 763 00:38:04,510 --> 00:38:10,570 tags, what I can say is script src-- src for source-- 764 00:38:10,570 --> 00:38:17,770 =counter.js, for example, to say go ahead and reference counter.js and use 765 00:38:17,770 --> 00:38:21,213 that JavaScript in the head of the page here. 766 00:38:21,213 --> 00:38:23,380 And that then is going to work exactly the same way. 767 00:38:23,380 --> 00:38:25,400 I still am able to count as high as I'd like. 768 00:38:25,400 --> 00:38:28,240 I still get an alert every time the count reaches a multiple of 10, 769 00:38:28,240 --> 00:38:30,380 but my HTML is now a little bit simpler. 770 00:38:30,380 --> 00:38:31,270 It's just the body. 771 00:38:31,270 --> 00:38:35,320 It's just the h1 and the button, and then all of my JavaScript 772 00:38:35,320 --> 00:38:39,340 is now located in a separate file that allows 773 00:38:39,340 --> 00:38:42,310 me to keep my HTML code and my JavaScript code separate 774 00:38:42,310 --> 00:38:43,180 from each other. 775 00:38:43,180 --> 00:38:46,330 And that can be valuable for a couple of reasons, among them 776 00:38:46,330 --> 00:38:50,500 if I have common JavaScript code that's in use by multiple different HTML 777 00:38:50,500 --> 00:38:55,138 pages, multiple HTML pages can all include the same JavaScript source 778 00:38:55,138 --> 00:38:56,680 rather than needing to repeat myself. 779 00:38:56,680 --> 00:38:59,710 If you use the same JavaScript across multiple different pages, 780 00:38:59,710 --> 00:39:02,650 I can just use the same JavaScript across all of them. 781 00:39:02,650 --> 00:39:05,200 And that'll be helpful too as we begin to take a look later 782 00:39:05,200 --> 00:39:08,960 at some JavaScript libraries, which are JavaScript written by other people. 783 00:39:08,960 --> 00:39:12,910 We can just include other people's JavaScript in our own web pages 784 00:39:12,910 --> 00:39:15,430 just by adding a script tag at the top of our page 785 00:39:15,430 --> 00:39:17,240 that specifies a particular source. 786 00:39:17,240 --> 00:39:19,210 You may already interacted with Bootstrap. 787 00:39:19,210 --> 00:39:21,220 That has its own JavaScript code. 788 00:39:21,220 --> 00:39:23,170 And you can include Bootstrap's JavaScript 789 00:39:23,170 --> 00:39:26,890 just by including a script tag at the top of our HTML page 790 00:39:26,890 --> 00:39:33,770 in order to say go ahead and include all of that JavaScript in our page as well. 791 00:39:33,770 --> 00:39:36,310 So what else can we do now, now that we have the ability 792 00:39:36,310 --> 00:39:40,330 to get at elements of the DOM and actually manipulate their contents? 793 00:39:40,330 --> 00:39:43,930 Well, one thing we can do is begin to make our pages a little bit more 794 00:39:43,930 --> 00:39:47,710 interactive, actually respond to what users are doing on the page, 795 00:39:47,710 --> 00:39:50,950 whether the user is typing something in or maybe filling out a form, 796 00:39:50,950 --> 00:39:52,040 for example. 797 00:39:52,040 --> 00:39:54,070 So let's go ahead and try an example of that, 798 00:39:54,070 --> 00:39:56,150 where the user might be filling out a form 799 00:39:56,150 --> 00:39:58,660 and we would like for our code to somehow respond 800 00:39:58,660 --> 00:40:00,310 to what it is that they type. 801 00:40:00,310 --> 00:40:04,870 I'll go ahead and go back into hello.html. 802 00:40:04,870 --> 00:40:08,500 And now inside of the body of the page, I've said hello at the top. 803 00:40:08,500 --> 00:40:12,400 And here instead of a button, I'm going to have a form. 804 00:40:12,400 --> 00:40:15,400 This HTML form will look like the HTML forms we've seen before. 805 00:40:15,400 --> 00:40:18,402 I have an input field that I'll add the autofocus attribute 806 00:40:18,402 --> 00:40:20,860 to to mean, like, automatically focus this input field when 807 00:40:20,860 --> 00:40:25,330 I open the page because I might want the user to start typing right away. 808 00:40:25,330 --> 00:40:30,430 I'm going to give this input field an id of name, for example, 809 00:40:30,430 --> 00:40:34,460 and then a placeholder of Name-- capital N-- 810 00:40:34,460 --> 00:40:36,648 whose type is text. 811 00:40:36,648 --> 00:40:37,690 So what have I done here? 812 00:40:37,690 --> 00:40:40,720 I've created an input field where the user can type in some text. 813 00:40:40,720 --> 00:40:43,840 The placeholder-- the thing the user sees filled into that input field 814 00:40:43,840 --> 00:40:46,240 originally-- will just be capital N Name, 815 00:40:46,240 --> 00:40:48,900 telling them they should type their name in here. 816 00:40:48,900 --> 00:40:53,030 And I've given this input field an id-- some unique identifier, 817 00:40:53,030 --> 00:40:58,720 such that I later on, can reference and find this particular input field. 818 00:40:58,720 --> 00:41:01,660 And then I have input type=submit-- 819 00:41:01,660 --> 00:41:06,530 some way for me to now submit this form as well. 820 00:41:06,530 --> 00:41:11,650 And so if I load this page, load hello.html, here's what I see-- 821 00:41:11,650 --> 00:41:14,650 hello, a field where I can type in my name, the placeholder name 822 00:41:14,650 --> 00:41:19,970 shows up there for me, and then a button where I can submit this form. 823 00:41:19,970 --> 00:41:22,930 And now, what I'd like to do inside of my JavaScript 824 00:41:22,930 --> 00:41:25,390 is instead of this hello function, what I'm going to do 825 00:41:25,390 --> 00:41:28,120 is I'm going to first run some JavaScript when 826 00:41:28,120 --> 00:41:29,360 the DOM is done loading. 827 00:41:29,360 --> 00:41:30,790 And so I'll use that same line from before. 828 00:41:30,790 --> 00:41:32,498 You're going to see it quite a bit, where 829 00:41:32,498 --> 00:41:34,950 we're going to say document.addEventListener 830 00:41:34,950 --> 00:41:38,620 DOMContentLoaded, and then this function to mean go ahead 831 00:41:38,620 --> 00:41:41,530 and run this code when the DOM is done loaded. 832 00:41:41,530 --> 00:41:46,840 And the code I'd like to run is to say when I submit the form, 833 00:41:46,840 --> 00:41:47,980 I want something to happen. 834 00:41:47,980 --> 00:41:50,398 When I submit the form, maybe I want to display an alert 835 00:41:50,398 --> 00:41:53,440 that if I typed in Brian, it'll say, hello, Brian or if I typed in David, 836 00:41:53,440 --> 00:41:55,520 it'll say, hello, David, for example. 837 00:41:55,520 --> 00:41:57,133 So how might I do that? 838 00:41:57,133 --> 00:41:58,300 Well, how do I get the form? 839 00:41:58,300 --> 00:41:59,383 That's the first question. 840 00:41:59,383 --> 00:42:01,210 Anytime you want to get at an element-- 841 00:42:01,210 --> 00:42:05,140 one particular element-- on an HTML page, usually what we're going to do 842 00:42:05,140 --> 00:42:10,128 is document.querySelector to say get me the element that is a form. 843 00:42:10,128 --> 00:42:11,920 And there's only one form on the page, so I 844 00:42:11,920 --> 00:42:13,420 don't have to worry about ambiguity. 845 00:42:13,420 --> 00:42:16,060 I'm just saying get me that form. 846 00:42:16,060 --> 00:42:19,060 And then I can say .onsubmit. 847 00:42:19,060 --> 00:42:22,560 When you submit the form, what code should run? 848 00:42:22,560 --> 00:42:25,030 And if I had a name of a function, like a function f, 849 00:42:25,030 --> 00:42:29,230 I could just say like, run function f when the form is submitted. 850 00:42:29,230 --> 00:42:31,510 But alternatively, just as before, instead 851 00:42:31,510 --> 00:42:34,090 of providing the name of a function, I can also just 852 00:42:34,090 --> 00:42:36,070 provide the function itself. 853 00:42:36,070 --> 00:42:40,570 I can say function, and then in between these curly braces, 854 00:42:40,570 --> 00:42:44,230 I can specify exactly what code should run 855 00:42:44,230 --> 00:42:48,070 when the form is submitted by providing this anonymous function instead, 856 00:42:48,070 --> 00:42:52,780 using this anonymous function as the value of the onsubmit property 857 00:42:52,780 --> 00:42:54,190 of this form. 858 00:42:54,190 --> 00:42:56,320 And so now, what I'd like to do is somehow 859 00:42:56,320 --> 00:42:59,500 get access to whatever the user typed into the input field, 860 00:42:59,500 --> 00:43:02,240 whatever the user's name happens to be. 861 00:43:02,240 --> 00:43:07,330 And so I could get the input field via document.querySelector input. 862 00:43:07,330 --> 00:43:09,490 And that would work this time, but we'll want 863 00:43:09,490 --> 00:43:11,470 to start to be a little bit careful because on this page, 864 00:43:11,470 --> 00:43:13,303 there are multiple different input elements. 865 00:43:13,303 --> 00:43:17,410 There's an input element here for typing in the name and a second input element 866 00:43:17,410 --> 00:43:20,080 here for telling me you're giving me a button where 867 00:43:20,080 --> 00:43:22,630 I can submit this particular HTML form. 868 00:43:22,630 --> 00:43:26,870 And so what I probably want to do is be a little bit more specific. 869 00:43:26,870 --> 00:43:28,900 And it turns out that inside of querySelector, 870 00:43:28,900 --> 00:43:31,780 I can use all of the standard ways in CSS 871 00:43:31,780 --> 00:43:34,550 that we could select for a particular element. 872 00:43:34,550 --> 00:43:37,600 So in CSS, if you'll recall, we had the ability 873 00:43:37,600 --> 00:43:41,650 to run CSS and just say style all the h1's or we could say style 874 00:43:41,650 --> 00:43:45,130 all the things with this particular ID or with this particular class. 875 00:43:45,130 --> 00:43:47,740 And document.querySelector works the same way, 876 00:43:47,740 --> 00:43:52,210 that I can say document.querySelector and pass in a tag to say like, 877 00:43:52,210 --> 00:43:56,210 get me the h1 element, or get me the button, or get me the form. 878 00:43:56,210 --> 00:43:59,500 But if there are multiple h1 elements or multiple buttons and multiple forms, 879 00:43:59,500 --> 00:44:04,570 I can be more specific than that if, for example, an element has an ID. 880 00:44:04,570 --> 00:44:07,600 In which case, I can say document.querySelector, and then 881 00:44:07,600 --> 00:44:11,560 in quotation marks, the hash mark, and then the name of the ID 882 00:44:11,560 --> 00:44:14,380 to say get me the element with that particular ID, 883 00:44:14,380 --> 00:44:17,020 again using the exact same syntax that CSS 884 00:44:17,020 --> 00:44:20,170 uses if I want to apply a particular set of styles 885 00:44:20,170 --> 00:44:23,890 to only one element that only has one ID. 886 00:44:23,890 --> 00:44:27,280 Likewise too, I can say document.querySelector, and then 887 00:44:27,280 --> 00:44:30,520 use dot followed by the name of a class if there's 888 00:44:30,520 --> 00:44:34,630 a particular class of elements and I want to just get one of those 889 00:44:34,630 --> 00:44:38,920 to say get me an element that has this particular class in order 890 00:44:38,920 --> 00:44:40,302 to manipulate it as well. 891 00:44:40,302 --> 00:44:42,010 So the same types of syntax that we could 892 00:44:42,010 --> 00:44:46,990 use in CSS for trying to reference and get at a particular HTML element, 893 00:44:46,990 --> 00:44:50,200 we can do the same thing here with document.querySelector 894 00:44:50,200 --> 00:44:54,430 to go ahead and try and get a particular element based on its tag name, 895 00:44:54,430 --> 00:44:57,040 based on its ID, or based on its class. 896 00:44:57,040 --> 00:45:01,900 And it was for that reason that inside of the HTML page for my input, 897 00:45:01,900 --> 00:45:04,810 I gave the input an ID of name. 898 00:45:04,810 --> 00:45:07,840 I wanted some way to be able to uniquely reference it. 899 00:45:07,840 --> 00:45:10,300 And I can uniquely reference it not by input, 900 00:45:10,300 --> 00:45:16,390 but by #name, where I can say get me the element that has an ID of name. 901 00:45:16,390 --> 00:45:19,120 And that is the element that I would like to extract inside 902 00:45:19,120 --> 00:45:21,110 of my JavaScript code. 903 00:45:21,110 --> 00:45:23,420 Once I have that HTML element, what I want 904 00:45:23,420 --> 00:45:26,790 is, like, what the user actually typed into that input field. 905 00:45:26,790 --> 00:45:29,600 And it turns out that if you have an input field in HTML, 906 00:45:29,600 --> 00:45:33,710 I can get access to what the user typed in by accessing its value property. 907 00:45:33,710 --> 00:45:38,820 Value is a property that refers to what it is the user actually typed in. 908 00:45:38,820 --> 00:45:41,660 So I can say .value. 909 00:45:41,660 --> 00:45:44,340 And I'm going to go ahead and save that inside of a variable. 910 00:45:44,340 --> 00:45:48,470 So I could say something like let name = whatever the user typed in. 911 00:45:48,470 --> 00:45:50,630 But if I'm not going to reassign name to something 912 00:45:50,630 --> 00:45:52,815 else inside of this function-- 913 00:45:52,815 --> 00:45:55,940 I'm really going to get the name once and I'm not going to change it inside 914 00:45:55,940 --> 00:45:57,050 of the function-- 915 00:45:57,050 --> 00:45:58,715 so I can use a const variable instead. 916 00:45:58,715 --> 00:46:00,590 And that would be better design to say I have 917 00:46:00,590 --> 00:46:04,700 a constant variable called name, which is equal to document.querySelector. 918 00:46:04,700 --> 00:46:09,990 Get me the element whose ID is name and get access to its value. 919 00:46:09,990 --> 00:46:11,690 And now, I can display an alert. 920 00:46:11,690 --> 00:46:16,940 I can alert something like in backticks, hello, comma. 921 00:46:16,940 --> 00:46:19,280 And then using the dollar sign, curly brace syntax, 922 00:46:19,280 --> 00:46:24,410 I can say plug-in the name there followed by an exclamation point. 923 00:46:24,410 --> 00:46:26,330 So I've extracted the name from the form. 924 00:46:26,330 --> 00:46:30,390 Get me the input field where they typed the name, get access to its value, 925 00:46:30,390 --> 00:46:35,160 and then I'm displaying an alert that is going to say hello to that person, 926 00:46:35,160 --> 00:46:37,430 for example. 927 00:46:37,430 --> 00:46:43,000 And so now, if I refresh the page, I type in my name, I press Submit, 928 00:46:43,000 --> 00:46:44,960 I get an alert that says hello, Brian. 929 00:46:44,960 --> 00:46:45,580 I press OK. 930 00:46:45,580 --> 00:46:46,930 I can try it again. 931 00:46:46,930 --> 00:46:51,070 I can type in something like David, press Submit, and now the page 932 00:46:51,070 --> 00:46:53,530 says hello, David. 933 00:46:53,530 --> 00:46:57,280 So here again, we've been able to combine event listeners, and functions, 934 00:46:57,280 --> 00:47:01,960 and querySelector to be able to both read information from the page in order 935 00:47:01,960 --> 00:47:06,580 to say get me this particular HTML element, find me an HTML element, 936 00:47:06,580 --> 00:47:10,870 and access what the user typed into it-- the .value property that gets me what 937 00:47:10,870 --> 00:47:12,700 the user typed into an input field. 938 00:47:12,700 --> 00:47:15,740 And we've been able to combine that with event listeners and alerts 939 00:47:15,740 --> 00:47:18,070 that are able to actually respond dynamically 940 00:47:18,070 --> 00:47:22,000 to when a user submits the form or when the entire content of the page 941 00:47:22,000 --> 00:47:26,990 is done loading in order to produce some interesting effects as well. 942 00:47:26,990 --> 00:47:28,990 But it turns out we can do more than just 943 00:47:28,990 --> 00:47:32,500 change, like, the HTML that is contained within an element. 944 00:47:32,500 --> 00:47:36,460 We can also change CSS as well-- change the style properties 945 00:47:36,460 --> 00:47:38,630 of a particular element as well. 946 00:47:38,630 --> 00:47:41,530 So let's go ahead and see an example of that. 947 00:47:41,530 --> 00:47:45,550 Go ahead and create a new file that I'll call colors.html. 948 00:47:45,550 --> 00:47:50,562 And inside of colors, I'll include the same standard HTML boilerplate code 949 00:47:50,562 --> 00:47:52,270 that we often start with-- a head section 950 00:47:52,270 --> 00:47:54,940 with a title and a body section. 951 00:47:54,940 --> 00:47:57,690 And inside of the body of this page, I'm going 952 00:47:57,690 --> 00:48:02,415 to display a heading that just says hello, for example. 953 00:48:02,415 --> 00:48:05,380 And maybe I'll give it an ID just so I can reference it by name. 954 00:48:05,380 --> 00:48:07,510 Maybe it has an ID of hello. 955 00:48:07,510 --> 00:48:10,330 And then I'll have three buttons. 956 00:48:10,330 --> 00:48:15,040 I'll have a button called red, a button called blue, 957 00:48:15,040 --> 00:48:18,620 and then a button called green, for example, 958 00:48:18,620 --> 00:48:23,588 where now if I open up colors.html, here's what I see. 959 00:48:23,588 --> 00:48:26,380 I see a big heading that says hello, and then I see three buttons-- 960 00:48:26,380 --> 00:48:27,300 Red, Blue, and Green. 961 00:48:27,300 --> 00:48:31,150 But of course right now, these buttons don't actually do anything. 962 00:48:31,150 --> 00:48:33,070 How do I get the buttons to do something? 963 00:48:33,070 --> 00:48:35,230 Well, that's where JavaScript is going to come in. 964 00:48:35,230 --> 00:48:37,710 I'll add a script tag to the top of my page. 965 00:48:37,710 --> 00:48:41,200 And I only want to run this JavaScript when the DOM is done loading. 966 00:48:41,200 --> 00:48:43,900 So again, we'll use the same syntax as before. 967 00:48:43,900 --> 00:48:49,780 document.addEventListener DOMContentLoaded, and then run 968 00:48:49,780 --> 00:48:53,440 this function to say everything in between these curly braces, 969 00:48:53,440 --> 00:48:57,130 this is all the code that should run once the page is done loading. 970 00:48:57,130 --> 00:49:00,040 And what I'd really like to do is get at these three buttons 971 00:49:00,040 --> 00:49:02,832 and say when you click on each one of them, do something different, 972 00:49:02,832 --> 00:49:05,688 like change the color of a particular HTML element. 973 00:49:05,688 --> 00:49:08,980 And in order to do that, I need some way of uniquely referencing these buttons. 974 00:49:08,980 --> 00:49:10,930 So to do that, I'm going to give them all IDs. 975 00:49:10,930 --> 00:49:12,880 This button will have an ID of red. 976 00:49:12,880 --> 00:49:14,830 This button will have an ID of blue. 977 00:49:14,830 --> 00:49:16,510 This button will have an ID of green. 978 00:49:16,510 --> 00:49:19,570 Just unique names I can give to the buttons in HTML, 979 00:49:19,570 --> 00:49:24,170 such that in JavaScript, I'm later able to reference them. 980 00:49:24,170 --> 00:49:28,090 So what do I include now here inside of my JavaScript code? 981 00:49:28,090 --> 00:49:35,130 Well, let me say document.querySelector #red to say 982 00:49:35,130 --> 00:49:38,610 get me the element whose ID is red. 983 00:49:38,610 --> 00:49:41,220 And when you're clicked on-- onclick-- 984 00:49:41,220 --> 00:49:44,083 go ahead and run this function. 985 00:49:44,083 --> 00:49:45,250 What should the function do? 986 00:49:45,250 --> 00:49:49,000 Well, I want to take this h1 element and change its color to red. 987 00:49:49,000 --> 00:49:51,810 I want to change the font color to red. 988 00:49:51,810 --> 00:49:53,430 And I'll leave a comment to myself. 989 00:49:53,430 --> 00:49:55,555 In JavaScript, the way you can leave a comment just 990 00:49:55,555 --> 00:49:58,170 to document what you're doing is using these two slashes. 991 00:49:58,170 --> 00:50:00,668 The two slashes indicate everything after that on the page 992 00:50:00,668 --> 00:50:01,710 is going to be a comment. 993 00:50:01,710 --> 00:50:04,917 The browser will ignore it, but it can be useful to you, the programmer, 994 00:50:04,917 --> 00:50:06,750 and to someone who's reading your code to be 995 00:50:06,750 --> 00:50:10,650 able to see what it is that you're describing here on the page. 996 00:50:10,650 --> 00:50:15,960 And now, what I'd like to do is document.querySelector #hello. 997 00:50:15,960 --> 00:50:19,230 Get me the HTML element whose ID is hello 998 00:50:19,230 --> 00:50:22,560 and go ahead and modify its style property. 999 00:50:22,560 --> 00:50:24,900 And now inside of this style object, I can 1000 00:50:24,900 --> 00:50:27,670 modify any of the CSS style properties. 1001 00:50:27,670 --> 00:50:30,780 One of them, for example, is something like color. 1002 00:50:30,780 --> 00:50:36,860 So I can update the color property and set it equal to red. 1003 00:50:36,860 --> 00:50:40,100 So here now, I'm saying when you click on the red button, 1004 00:50:40,100 --> 00:50:42,180 go ahead and run this function. 1005 00:50:42,180 --> 00:50:47,002 And what the function should do is find the hello element, update its style. 1006 00:50:47,002 --> 00:50:47,960 What part of the style? 1007 00:50:47,960 --> 00:50:49,460 Update its color. 1008 00:50:49,460 --> 00:50:51,140 What should we update it to? 1009 00:50:51,140 --> 00:50:52,945 We should update it to red. 1010 00:50:52,945 --> 00:50:55,820 And I'm going to do the same thing for the other two buttons as well. 1011 00:50:55,820 --> 00:50:58,500 And it's pretty similar code, so I'm just going to Copy-Paste. 1012 00:50:58,500 --> 00:50:59,890 Copy-Paste here. 1013 00:50:59,890 --> 00:51:02,240 I'm going to have one for changing the color to blue. 1014 00:51:02,240 --> 00:51:05,660 When I click the Blue button, it should change the color to blue. 1015 00:51:05,660 --> 00:51:09,710 And then we'll do it one more time, change the font color to green. 1016 00:51:09,710 --> 00:51:14,460 When you click on the Green button, you should change the color to green. 1017 00:51:14,460 --> 00:51:18,670 So now when I refresh the colors.html, right now, hello by default 1018 00:51:18,670 --> 00:51:21,470 is just in black-- standard font color for HTML. 1019 00:51:21,470 --> 00:51:23,360 I click Red, hello changes to red. 1020 00:51:23,360 --> 00:51:25,280 I click Blue, it changes to blue. 1021 00:51:25,280 --> 00:51:27,170 I click Green, it changes to green. 1022 00:51:27,170 --> 00:51:29,060 So depending on what button I click, that 1023 00:51:29,060 --> 00:51:32,870 triggers some event listener that's going to then say when the button is 1024 00:51:32,870 --> 00:51:34,440 clicked, run this function. 1025 00:51:34,440 --> 00:51:37,430 And what the function does is it grabs this h1 element-- 1026 00:51:37,430 --> 00:51:39,440 the element whose ID is hello-- 1027 00:51:39,440 --> 00:51:43,820 modifies it style, updates its color property to be something like red, 1028 00:51:43,820 --> 00:51:45,390 or blue, or green. 1029 00:51:45,390 --> 00:51:48,170 And thus showing that we can modify style in addition 1030 00:51:48,170 --> 00:51:52,330 to just modifying the content of the page itself. 1031 00:51:52,330 --> 00:51:54,830 But it turns out that as you looked at me writing that code, 1032 00:51:54,830 --> 00:51:57,920 something should've struck you as probably not optimal design-- 1033 00:51:57,920 --> 00:52:00,770 that in general, anytime you find yourself writing the same code 1034 00:52:00,770 --> 00:52:03,720 again and again and again, especially if you're copy-pasting, 1035 00:52:03,720 --> 00:52:06,560 that that is a generally bad sign-- usually a sign that there 1036 00:52:06,560 --> 00:52:10,760 is some better way of trying to modify, of trying to implement 1037 00:52:10,760 --> 00:52:12,800 the behavior that I'm trying to create. 1038 00:52:12,800 --> 00:52:14,120 And it turns out that there is. 1039 00:52:14,120 --> 00:52:16,370 And there are a number of ways that you could do this. 1040 00:52:16,370 --> 00:52:19,820 One way here is that I might like to consolidate these three event 1041 00:52:19,820 --> 00:52:23,330 listeners into just, like, a single function that 1042 00:52:23,330 --> 00:52:27,740 is going to handle changing the color to whatever the button says the color 1043 00:52:27,740 --> 00:52:29,140 should be changed to. 1044 00:52:29,140 --> 00:52:32,570 But one problem here is that if I just attach the same event 1045 00:52:32,570 --> 00:52:37,002 listener to all three of the buttons, it's not going to be clear to me 1046 00:52:37,002 --> 00:52:38,960 when I click on the button, how does the button 1047 00:52:38,960 --> 00:52:42,680 know what color we should change the text to. 1048 00:52:42,680 --> 00:52:46,640 And so to that effect, we can add some additional special attributes 1049 00:52:46,640 --> 00:52:51,520 to a particular HTML element that are called data attributes, 1050 00:52:51,520 --> 00:52:55,820 where a data attribute is my way of saying that I would like to associate 1051 00:52:55,820 --> 00:53:00,080 some data with this particular HTML element, where here, 1052 00:53:00,080 --> 00:53:09,410 I can say data-color="red", data-color="blue", data-color="green". 1053 00:53:09,410 --> 00:53:12,470 Data attributes always start with data followed by a dash, 1054 00:53:12,470 --> 00:53:15,830 and then I can specify really any name that I want for some information 1055 00:53:15,830 --> 00:53:18,800 that I would like to store about the HTML element. 1056 00:53:18,800 --> 00:53:21,050 And here, the information I want to store 1057 00:53:21,050 --> 00:53:25,400 is I want to store data about what color you should change the text to when 1058 00:53:25,400 --> 00:53:26,750 the button is clicked on. 1059 00:53:26,750 --> 00:53:30,080 And so what we're going to have the ability to do now is the ability to say 1060 00:53:30,080 --> 00:53:32,900 that if I have access to this element-- this button-- 1061 00:53:32,900 --> 00:53:36,830 I can access its data-color property to know 1062 00:53:36,830 --> 00:53:39,470 whether we should change the text to red, or blue, 1063 00:53:39,470 --> 00:53:43,910 or green by adding these data attributes to these HTML elements. 1064 00:53:43,910 --> 00:53:47,590 And so now, what I want is some way of getting all of these buttons. 1065 00:53:47,590 --> 00:53:53,300 Now document.querySelector, as you recall, just gets one element. 1066 00:53:53,300 --> 00:53:55,730 It's just going to get for me a single element 1067 00:53:55,730 --> 00:53:57,950 and it's going to get the first one that it finds. 1068 00:53:57,950 --> 00:54:01,280 If I want to get multiple elements, what I can do instead 1069 00:54:01,280 --> 00:54:06,110 is something like document.querySelectorAll. 1070 00:54:06,110 --> 00:54:09,720 querySelectorAll is going to return the same thing that querySelector does, 1071 00:54:09,720 --> 00:54:12,260 but instead of querySelector returning a single element that 1072 00:54:12,260 --> 00:54:14,930 matches what it looks for, querySelectorAll 1073 00:54:14,930 --> 00:54:18,650 is going to return to me an array of all of the elements 1074 00:54:18,650 --> 00:54:20,520 that matched my particular query. 1075 00:54:20,520 --> 00:54:23,220 So if I wanted to select not just the first button I find, 1076 00:54:23,220 --> 00:54:28,150 but all of the buttons I find, I can here say querySelectorAll for button. 1077 00:54:28,150 --> 00:54:31,430 And that will give me back a JavaScript array, the equivalent of a list, 1078 00:54:31,430 --> 00:54:34,430 that represents all of those buttons. 1079 00:54:34,430 --> 00:54:37,550 And we can actually test what this looks like by looking at things 1080 00:54:37,550 --> 00:54:40,820 inside of the JavaScript console. 1081 00:54:40,820 --> 00:54:46,490 If I go ahead and refresh this page colors, I can open up the inspector, 1082 00:54:46,490 --> 00:54:50,330 go into the JavaScript console, and just as you could see error messages here, 1083 00:54:50,330 --> 00:54:54,950 you can also actually write JavaScript code here as well. 1084 00:54:54,950 --> 00:55:00,300 So I can say something like document.querySelector button 1085 00:55:00,300 --> 00:55:03,870 to say, all right, what's going to happen when I try and select 1086 00:55:03,870 --> 00:55:07,050 for a button on this particular page? 1087 00:55:07,050 --> 00:55:10,710 And what I get is, all right, I get just this very first button-- 1088 00:55:10,710 --> 00:55:13,320 button who's data-color is equal to red. 1089 00:55:13,320 --> 00:55:16,380 That's what I would expect. querySelector just finds me one element 1090 00:55:16,380 --> 00:55:19,740 and it's going to find me the very first element. 1091 00:55:19,740 --> 00:55:22,650 And likewise, I can say, all right, instead of querySelector, 1092 00:55:22,650 --> 00:55:25,080 let's do querySelectorAll. 1093 00:55:25,080 --> 00:55:26,932 And what I get back is a NodeList, which you 1094 00:55:26,932 --> 00:55:28,890 can think of as kind of like an array or a list 1095 00:55:28,890 --> 00:55:33,810 in Python, that's got three buttons in it-- button 0, 1, and 2. 1096 00:55:33,810 --> 00:55:38,340 And just as with a list in Python as you can index into things, 1097 00:55:38,340 --> 00:55:40,650 arrays in JavaScript can be indexed into as well. 1098 00:55:40,650 --> 00:55:47,590 If I have something like const names = Harry, Ron, and Hermione-- 1099 00:55:47,590 --> 00:55:50,100 like an array of three names-- 1100 00:55:50,100 --> 00:55:54,270 I can say names square bracket 0 to get the first name, names square bracket 1 1101 00:55:54,270 --> 00:55:56,310 to get the second one, names square bracket 2 1102 00:55:56,310 --> 00:55:57,960 to get the third one, for example. 1103 00:55:57,960 --> 00:56:01,012 And that gives me each of the individual elements in the array. 1104 00:56:01,012 --> 00:56:02,970 If I want to get the whole length of the array, 1105 00:56:02,970 --> 00:56:08,160 I can do names.length to get, all right, the length of the names array 1106 00:56:08,160 --> 00:56:09,210 happens to be three. 1107 00:56:09,210 --> 00:56:11,085 So just some additional features that we have 1108 00:56:11,085 --> 00:56:13,680 access to if you happen to have an array of things. 1109 00:56:13,680 --> 00:56:16,260 It turns out querySelectorAll returns to me a NodeList, 1110 00:56:16,260 --> 00:56:18,320 which is kind of like an array. 1111 00:56:18,320 --> 00:56:20,490 And that's going to be useful because when 1112 00:56:20,490 --> 00:56:23,940 I say document.querySelectorAll button, I am saying 1113 00:56:23,940 --> 00:56:27,380 get me all of the buttons on the page. 1114 00:56:27,380 --> 00:56:29,940 And now, what I would like to do is effectively 1115 00:56:29,940 --> 00:56:34,680 loop over all of those buttons and say for each of the buttons 1116 00:56:34,680 --> 00:56:37,210 inside of this list that comes back to me, 1117 00:56:37,210 --> 00:56:40,830 I would like to add an event handler for when that button is clicked on 1118 00:56:40,830 --> 00:56:43,140 to say for each of the buttons that comes back, 1119 00:56:43,140 --> 00:56:47,850 go ahead and say when you're clicked on, change the color of the h1 element. 1120 00:56:47,850 --> 00:56:51,900 And so there are a number of ways, again, that you could do this, 1121 00:56:51,900 --> 00:56:56,910 but one way is to use a particular property called forEach. 1122 00:56:56,910 --> 00:57:02,040 And forEach is a function that accepts as an argument, another function, where 1123 00:57:02,040 --> 00:57:03,840 the idea is going to be I would like to run 1124 00:57:03,840 --> 00:57:07,890 a function for each of the elements inside of an array 1125 00:57:07,890 --> 00:57:10,840 or inside of a NodeList, for example. 1126 00:57:10,840 --> 00:57:16,170 So here, I can say forEach button, go ahead and run this function. 1127 00:57:16,170 --> 00:57:19,200 This is going to be a function now that takes something as input. 1128 00:57:19,200 --> 00:57:21,825 It's going to take one of the elements in the list 1129 00:57:21,825 --> 00:57:25,050 as input, something like a button. 1130 00:57:25,050 --> 00:57:29,370 And now for each button, what would I like to do for that button? 1131 00:57:29,370 --> 00:57:34,110 Well, when the button is clicked on, button.onclick, then 1132 00:57:34,110 --> 00:57:43,280 go ahead and run a function that is going to document.querySelector. 1133 00:57:43,280 --> 00:57:47,160 Get me the element whose ID is #hello. 1134 00:57:47,160 --> 00:57:48,680 Change its style. 1135 00:57:48,680 --> 00:57:50,990 Within the style, change its color. 1136 00:57:50,990 --> 00:57:53,042 And what do I want to change its color to? 1137 00:57:53,042 --> 00:57:54,500 Well, I have access to this button. 1138 00:57:54,500 --> 00:57:56,990 This argument to the function is whichever 1139 00:57:56,990 --> 00:58:00,170 button I'm currently trying to add an event listener for. 1140 00:58:00,170 --> 00:58:02,510 And in order to access its data properties, 1141 00:58:02,510 --> 00:58:06,650 I can access a special property of an HTML element called it's dataset 1142 00:58:06,650 --> 00:58:07,940 property. 1143 00:58:07,940 --> 00:58:11,900 And then I can say something like button.dataset.color 1144 00:58:11,900 --> 00:58:15,260 to get at the data-color attribute. 1145 00:58:15,260 --> 00:58:16,665 So a lot of stuff going on here. 1146 00:58:16,665 --> 00:58:19,040 Let's go ahead and try and read through this entire thing 1147 00:58:19,040 --> 00:58:21,165 and just get a feel for what's happening because we 1148 00:58:21,165 --> 00:58:23,360 have functions nested within other functions nested 1149 00:58:23,360 --> 00:58:24,800 within other functions. 1150 00:58:24,800 --> 00:58:28,520 Up at the very top, I've said add an event listener to the document. 1151 00:58:28,520 --> 00:58:30,810 When the document's DOM content is loaded, 1152 00:58:30,810 --> 00:58:33,320 meaning all of the content of the page is done loading, 1153 00:58:33,320 --> 00:58:35,280 go ahead and run this function. 1154 00:58:35,280 --> 00:58:37,450 This is the body of the function. 1155 00:58:37,450 --> 00:58:38,450 So what do I want to do? 1156 00:58:38,450 --> 00:58:42,650 When the page is done loading, I'm going to document.querySelectorAll, 1157 00:58:42,650 --> 00:58:44,827 looking for all of the buttons. 1158 00:58:44,827 --> 00:58:46,910 And if I wanted to if there could be more buttons, 1159 00:58:46,910 --> 00:58:48,890 I could have added a class to these buttons 1160 00:58:48,890 --> 00:58:51,015 and just looked for things of the particular class. 1161 00:58:51,015 --> 00:58:55,680 querySelectorAll just returns all of the elements that match a particular query. 1162 00:58:55,680 --> 00:58:58,610 And then I'm saying forEach of those buttons-- 1163 00:58:58,610 --> 00:59:00,930 for each of the buttons that came back-- 1164 00:59:00,930 --> 00:59:03,700 I would like to run a function on each of those buttons. 1165 00:59:03,700 --> 00:59:06,200 I'm basically saying if I have three buttons that came back, 1166 00:59:06,200 --> 00:59:08,217 let me run a function on the first button, 1167 00:59:08,217 --> 00:59:10,050 then the same function on the second button, 1168 00:59:10,050 --> 00:59:12,000 then the same function on the third button. 1169 00:59:12,000 --> 00:59:13,820 And what is that function? 1170 00:59:13,820 --> 00:59:15,530 Well, it's this function here-- 1171 00:59:15,530 --> 00:59:17,992 a function that takes as input, the button. 1172 00:59:17,992 --> 00:59:20,450 It's first going to pass in as input the first button, then 1173 00:59:20,450 --> 00:59:22,650 the second button, then the third. 1174 00:59:22,650 --> 00:59:27,170 And what this function does is it adds an onclick handler to the button. 1175 00:59:27,170 --> 00:59:31,480 It says when the button is clicked on, go ahead and run this other function. 1176 00:59:31,480 --> 00:59:33,230 And this function now is the function that 1177 00:59:33,230 --> 00:59:37,250 will run when the button is clicked on to say when the button is clicked on, 1178 00:59:37,250 --> 00:59:43,610 get me the #hello element, change its color to button.dataset.color. 1179 00:59:43,610 --> 00:59:45,980 And button.dataset.color takes a button-- 1180 00:59:45,980 --> 00:59:48,530 takes an HTML element like this one here-- 1181 00:59:48,530 --> 00:59:51,890 and accesses its data-set, all of its data properties, 1182 00:59:51,890 --> 00:59:56,000 and specifically accesses the color data property, which in this case 1183 00:59:56,000 --> 00:59:56,960 is equal to red. 1184 00:59:56,960 --> 01:00:00,690 And that is what we would like to set color equal to. 1185 01:00:00,690 --> 01:00:02,930 So a little bit more complex than we've seen before, 1186 01:00:02,930 --> 01:00:06,380 but now we've been able to reduce what was three different event 1187 01:00:06,380 --> 01:00:09,170 handlers into just a single one. 1188 01:00:09,170 --> 01:00:11,270 And now, this is going to work the same way. 1189 01:00:11,270 --> 01:00:15,730 Change it to red, blue, and green, all by just using those data properties 1190 01:00:15,730 --> 01:00:17,067 that we have access to. 1191 01:00:17,067 --> 01:00:19,400 And so when in doubt about how these things are working, 1192 01:00:19,400 --> 01:00:22,070 about what querySelector is returning, the JavaScript console 1193 01:00:22,070 --> 01:00:23,620 can be a very powerful tool for that. 1194 01:00:23,620 --> 01:00:26,840 So you can go into the JavaScript console and actually manipulate things. 1195 01:00:26,840 --> 01:00:28,670 You can run queries. 1196 01:00:28,670 --> 01:00:29,870 You can run functions. 1197 01:00:29,870 --> 01:00:32,210 You can even modify the values of variables. 1198 01:00:32,210 --> 01:00:35,820 Like if I go back, for instance, to counter.html, 1199 01:00:35,820 --> 01:00:39,920 where I had this counter that's counting 0, 1, 2, 3, 4, 1200 01:00:39,920 --> 01:00:44,450 if I wanted to, I could say something like counter = 27-- 1201 01:00:44,450 --> 01:00:46,787 just, like, change the value of the counter. 1202 01:00:46,787 --> 01:00:48,620 Nothing appears to have changed on the page. 1203 01:00:48,620 --> 01:00:50,750 I didn't say update anything on the page. 1204 01:00:50,750 --> 01:00:53,840 But now next time I run count, it's going to update the value of the count 1205 01:00:53,840 --> 01:00:54,710 to 28. 1206 01:00:54,710 --> 01:00:58,260 Because I had updated the value inside of the JavaScript console, 1207 01:00:58,260 --> 01:01:00,110 it's going to increment that value, display 1208 01:01:00,110 --> 01:01:02,810 that value inside of the h1 element. 1209 01:01:02,810 --> 01:01:04,310 So you can modify variables. 1210 01:01:04,310 --> 01:01:05,780 You can run functions. 1211 01:01:05,780 --> 01:01:08,750 You can run document.querySelector to figure out 1212 01:01:08,750 --> 01:01:11,180 what particular elements are going to come back all 1213 01:01:11,180 --> 01:01:14,270 through the use of the JavaScript console, which can be a very, very 1214 01:01:14,270 --> 01:01:16,490 powerful tool, especially as you begin working 1215 01:01:16,490 --> 01:01:20,300 on trying to debug these programs and trying to figure out 1216 01:01:20,300 --> 01:01:21,905 what might be wrong with them. 1217 01:01:21,905 --> 01:01:23,780 It turns out too that there are other changes 1218 01:01:23,780 --> 01:01:26,570 that we can make in order to optimize our code a little bit more, in order 1219 01:01:26,570 --> 01:01:28,323 to make it a little bit more succinct. 1220 01:01:28,323 --> 01:01:30,740 And one way is that in more recent versions of JavaScript, 1221 01:01:30,740 --> 01:01:33,500 they've introduced a particular notation for functions called 1222 01:01:33,500 --> 01:01:35,215 the arrow notation for functions. 1223 01:01:35,215 --> 01:01:37,340 And I'll just show it to you because it'll come up. 1224 01:01:37,340 --> 01:01:40,850 But oftentimes instead of using the keyword function before introducing 1225 01:01:40,850 --> 01:01:46,685 a function, you'll just have something like button, and then arrow, 1226 01:01:46,685 --> 01:01:47,600 then curly braces. 1227 01:01:47,600 --> 01:01:50,017 And strictly speaking, you don't even need the parentheses 1228 01:01:50,017 --> 01:01:53,300 around the input, where button arrow, and then in these curly braces, 1229 01:01:53,300 --> 01:01:57,320 some code just means here is going to be a function that takes as input, 1230 01:01:57,320 --> 01:02:01,880 a variable called button, and then runs this particular block of code 1231 01:02:01,880 --> 01:02:03,710 when that function is run. 1232 01:02:03,710 --> 01:02:06,950 And likewise if a function takes no input, like this function up here, 1233 01:02:06,950 --> 01:02:12,350 you can express it using arrow notation with just parentheses, arrow, block. 1234 01:02:12,350 --> 01:02:15,010 And so this is often a notation that you'll see in JavaScript. 1235 01:02:15,010 --> 01:02:16,927 So if you ever see it, know that that's really 1236 01:02:16,927 --> 01:02:18,630 just shorthand for creating a function. 1237 01:02:18,630 --> 01:02:21,857 Whatever it is to the left of the arrow sign is the input to the function 1238 01:02:21,857 --> 01:02:23,690 and whatever it is to the right of the arrow 1239 01:02:23,690 --> 01:02:27,590 is what code should actually run when the function body gets executed, when 1240 01:02:27,590 --> 01:02:29,690 the function is called upon. 1241 01:02:29,690 --> 01:02:33,500 So what other changes might we want to make to colors.html? 1242 01:02:33,500 --> 01:02:36,470 Well, if we look back at colors.html, here's what it looks like now. 1243 01:02:36,470 --> 01:02:39,650 We've got a heading that says hello, and then buttons to change the color 1244 01:02:39,650 --> 01:02:42,030 to red or blue or green, for example. 1245 01:02:42,030 --> 01:02:44,090 We might instead if we want the user to choose 1246 01:02:44,090 --> 01:02:47,300 from one from a number of options, decide upon the user interface 1247 01:02:47,300 --> 01:02:51,410 choice of using a dropdown instead of a bunch of buttons, for example. 1248 01:02:51,410 --> 01:02:52,970 And JavaScript supports that as well. 1249 01:02:52,970 --> 01:02:56,120 And we'll use this as an opportunity to explore some of the other event 1250 01:02:56,120 --> 01:02:58,670 handlers that exist within JavaScript. 1251 01:02:58,670 --> 01:03:02,690 So for example, instead of having these all inside of buttons, 1252 01:03:02,690 --> 01:03:04,940 I can make my life a little bit easier by making 1253 01:03:04,940 --> 01:03:07,760 this a select dropdown, where the select is 1254 01:03:07,760 --> 01:03:11,810 going to have an option whose value is, let's say, black is the default option. 1255 01:03:11,810 --> 01:03:13,040 We'll just say black. 1256 01:03:13,040 --> 01:03:17,060 And then we'll add another option whose value is red, and then we say red. 1257 01:03:17,060 --> 01:03:19,670 And the value is what we'll get in JavaScript when we try 1258 01:03:19,670 --> 01:03:22,580 and extract the value of a particular select dropdown. 1259 01:03:22,580 --> 01:03:24,860 What's in between the option tags themselves 1260 01:03:24,860 --> 01:03:27,860 is what the user is going to see on the page when they actually view it, 1261 01:03:27,860 --> 01:03:30,230 so I'm capitalizing it just for them. 1262 01:03:30,230 --> 01:03:32,340 Option value="blue". 1263 01:03:32,340 --> 01:03:33,380 That'll be Blue. 1264 01:03:33,380 --> 01:03:37,350 And then option value="green", and that'll be Green. 1265 01:03:37,350 --> 01:03:40,027 So now what the user sees is they see hello, 1266 01:03:40,027 --> 01:03:42,860 and then a dropdown menu where they can choose from a list of colors 1267 01:03:42,860 --> 01:03:45,750 rather than click buttons in order to do so. 1268 01:03:45,750 --> 01:03:49,130 And now of course, this select dropdown doesn't do anything at the moment, 1269 01:03:49,130 --> 01:03:51,510 but I can modify it so that it does. 1270 01:03:51,510 --> 01:03:54,172 So now instead of selecting for all of the buttons 1271 01:03:54,172 --> 01:03:55,880 and doing something with all the buttons, 1272 01:03:55,880 --> 01:03:57,620 we don't have any buttons anymore. 1273 01:03:57,620 --> 01:04:03,380 What I do have is I have a select dropdown. 1274 01:04:03,380 --> 01:04:05,450 And now just as we've seen like onclick to say 1275 01:04:05,450 --> 01:04:08,820 when you click on something, as we've seen DOMContentLoaded as an event, 1276 01:04:08,820 --> 01:04:11,450 there's another event called onchange, which 1277 01:04:11,450 --> 01:04:13,730 applies to things like select dropdowns, where 1278 01:04:13,730 --> 01:04:17,240 when something changes in the select dropdown, when a user chooses something 1279 01:04:17,240 --> 01:04:20,300 different, I can run some code, for example. 1280 01:04:20,300 --> 01:04:22,730 So I can run a function that in this case, 1281 01:04:22,730 --> 01:04:26,480 is going to take document.querySelector #hello, 1282 01:04:26,480 --> 01:04:30,382 meaning get me the hello HTML element, change its style. 1283 01:04:30,382 --> 01:04:31,340 What part of the style? 1284 01:04:31,340 --> 01:04:32,678 Change its color. 1285 01:04:32,678 --> 01:04:34,220 And I want to change it to something. 1286 01:04:34,220 --> 01:04:38,540 I want to change it to the value of this select dropdown. 1287 01:04:38,540 --> 01:04:41,930 But how do I get access to this particular select dropdown? 1288 01:04:41,930 --> 01:04:46,430 Well, in JavaScript, we have access to a special value called this. 1289 01:04:46,430 --> 01:04:49,010 And this has special meaning in JavaScript 1290 01:04:49,010 --> 01:04:51,300 and its meaning varies based on context. 1291 01:04:51,300 --> 01:04:53,660 But in the context of an event handler, a function that 1292 01:04:53,660 --> 01:04:56,330 is called when a particular event happens, 1293 01:04:56,330 --> 01:04:59,330 this is going to be a special keyword that always refers 1294 01:04:59,330 --> 01:05:01,970 to the thing that received the event. 1295 01:05:01,970 --> 01:05:03,320 So what received the event? 1296 01:05:03,320 --> 01:05:04,700 It was the select dropdown. 1297 01:05:04,700 --> 01:05:07,430 That is what received the event of being changed, 1298 01:05:07,430 --> 01:05:11,060 and so this is going to be a special keyword that always refers 1299 01:05:11,060 --> 01:05:13,940 to that-- that always refers to the dropdown menu 1300 01:05:13,940 --> 01:05:15,600 where I made a different selection. 1301 01:05:15,600 --> 01:05:18,058 So if I wanted to get the value of that dropdown menu, what 1302 01:05:18,058 --> 01:05:20,270 it is the user actually selected, I can just 1303 01:05:20,270 --> 01:05:25,250 say this.value to mean get that dropdown menu and get at the value-- the thing 1304 01:05:25,250 --> 01:05:27,710 that the user selected in that menu. 1305 01:05:27,710 --> 01:05:30,140 And now much more succinctly than before, 1306 01:05:30,140 --> 01:05:32,630 I've been able to implement the same kind of idea. 1307 01:05:32,630 --> 01:05:36,260 It says hello right now in black, but if I choose from the dropdown menu 1308 01:05:36,260 --> 01:05:38,600 to change its color to something like red for example, 1309 01:05:38,600 --> 01:05:40,280 the color changes to red. 1310 01:05:40,280 --> 01:05:42,860 If I instead choose blue, it changes to blue. 1311 01:05:42,860 --> 01:05:44,270 Green changes to green. 1312 01:05:44,270 --> 01:05:47,160 I choose black, it changes back to black. 1313 01:05:47,160 --> 01:05:50,690 So now, I have this ability to detect these other types of events 1314 01:05:50,690 --> 01:05:52,580 and respond to them as well. 1315 01:05:52,580 --> 01:05:55,910 And there are many, many different events that exist in JavaScript. 1316 01:05:55,910 --> 01:05:57,890 There's onclick, which we've seen already. 1317 01:05:57,890 --> 01:06:00,860 Onmouseover can detect like when you mouse over something, when you're 1318 01:06:00,860 --> 01:06:02,512 hovering over a particular element. 1319 01:06:02,512 --> 01:06:04,220 If you've ever seen websites that somehow 1320 01:06:04,220 --> 01:06:06,710 respond when your mouse moves over something, 1321 01:06:06,710 --> 01:06:08,540 that can be how it's implemented. 1322 01:06:08,540 --> 01:06:11,330 Onkeydown and onkeyup can respond to keyboard events, 1323 01:06:11,330 --> 01:06:14,610 something like when you press a key on the keyboard. 1324 01:06:14,610 --> 01:06:17,270 When you press down on the key, that's onkeydown, 1325 01:06:17,270 --> 01:06:19,810 and when you lift your finger off the key, that's onkeyup. 1326 01:06:19,810 --> 01:06:22,460 And there are other events as well, many more events 1327 01:06:22,460 --> 01:06:26,300 than are just listed here that you can listen for and respond to, 1328 01:06:26,300 --> 01:06:28,460 so that you can really interact with the user 1329 01:06:28,460 --> 01:06:30,920 based on what it is that they're doing. 1330 01:06:30,920 --> 01:06:34,760 So now, let's take a look at an example of how we can use some of these events 1331 01:06:34,760 --> 01:06:38,300 to now begin to create a little bit of a more interesting application. 1332 01:06:38,300 --> 01:06:41,030 We'll go ahead and build a to-do list application, 1333 01:06:41,030 --> 01:06:43,010 this time using exclusively JavaScript. 1334 01:06:43,010 --> 01:06:46,100 We've seen to-do lists before that involved communicating with a server, 1335 01:06:46,100 --> 01:06:47,720 making requests and responses. 1336 01:06:47,720 --> 01:06:51,920 We'll now build a to-do list that only uses JavaScript to do so. 1337 01:06:51,920 --> 01:06:54,220 So I'll create a new file called tasks.html. 1338 01:06:54,220 --> 01:06:57,040 1339 01:06:57,040 --> 01:07:02,760 And we'll create a head section whose title is tasks and a body section. 1340 01:07:02,760 --> 01:07:04,960 And inside the body of the page, I'll go ahead 1341 01:07:04,960 --> 01:07:07,270 and have a heading that says tasks. 1342 01:07:07,270 --> 01:07:11,215 And underneath that, I want an unordered list of all of my tasks. 1343 01:07:11,215 --> 01:07:12,880 So I'll have an unordered list. 1344 01:07:12,880 --> 01:07:15,470 I'll give it an ID of tasks just for good measure, 1345 01:07:15,470 --> 01:07:16,870 so I can reference it later. 1346 01:07:16,870 --> 01:07:19,540 But initially, nothing is going to be in here. 1347 01:07:19,540 --> 01:07:22,780 But what I'll have underneath the unordered list is a form-- 1348 01:07:22,780 --> 01:07:26,380 a form where I can submit a new task, for example. 1349 01:07:26,380 --> 01:07:29,200 So I'll give myself an input field, also give it an ID. 1350 01:07:29,200 --> 01:07:33,790 The ID will be task singular for the new task that I am typing in. 1351 01:07:33,790 --> 01:07:37,740 The placeholder will be New Task, just so the user knows what to type in. 1352 01:07:37,740 --> 01:07:40,100 And the type of the input field will be text. 1353 01:07:40,100 --> 01:07:43,390 So I have an input field where the user can type in some new task. 1354 01:07:43,390 --> 01:07:45,550 And I'll also add an input field for good measure 1355 01:07:45,550 --> 01:07:49,330 whose type is submit that allows the user to submit a new task once they've 1356 01:07:49,330 --> 01:07:50,780 created it. 1357 01:07:50,780 --> 01:07:55,090 So if I open up tasks.html, here's then what I see. 1358 01:07:55,090 --> 01:07:58,620 Big heading-- there is technically an unordered list underneath it here, 1359 01:07:58,620 --> 01:08:02,200 but there is nothing in that unordered list yet, so it just shows up as empty. 1360 01:08:02,200 --> 01:08:04,390 Then a text field where I can type in a task, 1361 01:08:04,390 --> 01:08:08,660 and then a Submit button where I can submit my new task. 1362 01:08:08,660 --> 01:08:11,960 So now, I'd like some JavaScript, such that when I submit this form, 1363 01:08:11,960 --> 01:08:13,800 we actually do something. 1364 01:08:13,800 --> 01:08:15,350 So I'll add a script tag. 1365 01:08:15,350 --> 01:08:23,210 I want this JavaScript to run after the DOM content is loaded, 1366 01:08:23,210 --> 01:08:27,350 so we'll go ahead and add the usual DOMContentLoaded event listener. 1367 01:08:27,350 --> 01:08:30,990 And now, I want to run code when the form is submitted. 1368 01:08:30,990 --> 01:08:38,240 So I can say document.querySelector form .onsubmit =, 1369 01:08:38,240 --> 01:08:39,740 and then I want to run a function. 1370 01:08:39,740 --> 01:08:41,270 And I could use the keyword function again, 1371 01:08:41,270 --> 01:08:42,630 but I can just use an arrow function, which 1372 01:08:42,630 --> 01:08:43,939 will be a little bit faster to type. 1373 01:08:43,939 --> 01:08:45,950 Just say, all right, here's the function that I 1374 01:08:45,950 --> 01:08:48,649 want to run when the form is submitted. 1375 01:08:48,649 --> 01:08:50,210 And what would I like to do? 1376 01:08:50,210 --> 01:08:52,127 Well, I'd first like to figure out, all right, 1377 01:08:52,127 --> 01:08:53,990 what did the user actually type in? 1378 01:08:53,990 --> 01:09:00,074 And what the user typed in, well, that'll be document.querySelector #task 1379 01:09:00,074 --> 01:09:02,140 .value. 1380 01:09:02,140 --> 01:09:03,550 Get me the element with ID #task. 1381 01:09:03,550 --> 01:09:04,899 That's the input field. 1382 01:09:04,899 --> 01:09:07,210 .value gets the value of the input field, 1383 01:09:07,210 --> 01:09:10,000 which is what the user actually typed in. 1384 01:09:10,000 --> 01:09:13,689 And I can save that as, like, const task. 1385 01:09:13,689 --> 01:09:17,109 That is what it is the user typed in. 1386 01:09:17,109 --> 01:09:19,270 And if I'm curious as to what the user typed in, 1387 01:09:19,270 --> 01:09:22,930 I can actually print it out to the JavaScript console. 1388 01:09:22,930 --> 01:09:26,995 And the way to do that is using a special function called console.log. 1389 01:09:26,995 --> 01:09:28,870 And that just logs something to the console-- 1390 01:09:28,870 --> 01:09:30,790 the equivalent of printing something out in Python, 1391 01:09:30,790 --> 01:09:32,707 where it just shows up in the Python terminal. 1392 01:09:32,707 --> 01:09:36,160 Here, this is going to show up in the JavaScript console. 1393 01:09:36,160 --> 01:09:38,020 And one other thing I'll add is by default, 1394 01:09:38,020 --> 01:09:40,640 forms will try and submit when you press the Submit button, 1395 01:09:40,640 --> 01:09:41,968 like take you to another page. 1396 01:09:41,968 --> 01:09:44,260 We've seen this before already in the context of Django 1397 01:09:44,260 --> 01:09:47,680 that when you submit a form it tries and submits another web request. 1398 01:09:47,680 --> 01:09:50,779 If I want to prevent that behavior, stop the form from submitting, 1399 01:09:50,779 --> 01:09:55,360 so stop form from submitting, I can return 1400 01:09:55,360 --> 01:09:58,360 false at the end of my forum submission handler 1401 01:09:58,360 --> 01:10:00,003 to say don't actually submit the form. 1402 01:10:00,003 --> 01:10:02,170 We're going to do everything client side, everything 1403 01:10:02,170 --> 01:10:04,070 just inside of the browser. 1404 01:10:04,070 --> 01:10:06,778 So now, this won't quite work yet, but it will be progress. 1405 01:10:06,778 --> 01:10:07,570 I refresh the page. 1406 01:10:07,570 --> 01:10:10,612 I'm going to open up the JavaScript console so I can see what's going on. 1407 01:10:10,612 --> 01:10:14,590 If I add a task, something just like foo, press Submit, 1408 01:10:14,590 --> 01:10:17,230 this now gets logged to the JavaScript console. 1409 01:10:17,230 --> 01:10:19,030 It's the equivalent of a way of providing 1410 01:10:19,030 --> 01:10:21,370 debugging information to myself to know, all right, 1411 01:10:21,370 --> 01:10:24,022 I now have access to this value foo. 1412 01:10:24,022 --> 01:10:26,230 And it's also telling me what line of code logged it. 1413 01:10:26,230 --> 01:10:30,683 It was tasks.html line 9 is the line of code that logged foo. 1414 01:10:30,683 --> 01:10:33,100 And so this can be useful when you're debugging a program. 1415 01:10:33,100 --> 01:10:35,500 When you want to see what the values of variables are, 1416 01:10:35,500 --> 01:10:38,065 you can just print them out using console.log 1417 01:10:38,065 --> 01:10:39,940 to figure out what's going on in your program 1418 01:10:39,940 --> 01:10:42,890 at any particular point in time. 1419 01:10:42,890 --> 01:10:45,070 But what I want to do is not console.log it. 1420 01:10:45,070 --> 01:10:47,830 What I want to do is really create a new element 1421 01:10:47,830 --> 01:10:51,640 that I'm going to add into my body of the HTML. 1422 01:10:51,640 --> 01:10:52,970 So how can I do that? 1423 01:10:52,970 --> 01:10:55,270 Well, to create a new element for my document, 1424 01:10:55,270 --> 01:10:59,290 I can run a function called document.createElement 1425 01:10:59,290 --> 01:11:02,170 followed by what type of element do I want to create. 1426 01:11:02,170 --> 01:11:04,870 Well, I have an unordered list-- a ul-- 1427 01:11:04,870 --> 01:11:09,340 and every item inside of an unordered list is a list item-- an li. 1428 01:11:09,340 --> 01:11:14,020 So I'll go ahead and create an li element, a list item. 1429 01:11:14,020 --> 01:11:18,340 And I'll save that in a variable that I'll call li. 1430 01:11:18,340 --> 01:11:20,440 So I've created a new list item. 1431 01:11:20,440 --> 01:11:22,930 And this list item's innerHTML-- 1432 01:11:22,930 --> 01:11:26,260 the HTML content inside of that list item-- 1433 01:11:26,260 --> 01:11:28,600 well, that's just going to be task-- 1434 01:11:28,600 --> 01:11:32,390 this variable from up here, which is whatever the user typed in. 1435 01:11:32,390 --> 01:11:35,440 So I've now created a new list item and said what 1436 01:11:35,440 --> 01:11:37,460 HTML should go inside of the list item. 1437 01:11:37,460 --> 01:11:40,210 It should be whatever task the user typed in. 1438 01:11:40,210 --> 01:11:45,670 And now, I'm going to say document.querySelector #tasks. 1439 01:11:45,670 --> 01:11:48,130 Get me the element whose ID is tasks, and that's 1440 01:11:48,130 --> 01:11:52,460 going to be this unordered list here-- the unordered list whose ID is tasks. 1441 01:11:52,460 --> 01:11:57,610 And if I have an HTML element, I can add a new element inside of it by saying 1442 01:11:57,610 --> 01:12:01,000 .append li. 1443 01:12:01,000 --> 01:12:03,130 And what that now is going to do is it's going 1444 01:12:03,130 --> 01:12:05,770 to say get me the unordered list whose ID is tasks. 1445 01:12:05,770 --> 01:12:09,010 Get me the element whose ID is tasks via querySelector here. 1446 01:12:09,010 --> 01:12:11,740 Once I have that element, append to the end 1447 01:12:11,740 --> 01:12:14,800 of what's inside of that element, this value 1448 01:12:14,800 --> 01:12:19,240 li, which happens to be this new element that I've created-- a new list item. 1449 01:12:19,240 --> 01:12:21,850 So I've been able to add a new HTML element. 1450 01:12:21,850 --> 01:12:23,830 And this line of code is going to say add it 1451 01:12:23,830 --> 01:12:30,110 to the DOM-- add it to the unordered list that I'm here now constructing. 1452 01:12:30,110 --> 01:12:32,590 So now, I rerun this. 1453 01:12:32,590 --> 01:12:33,250 I see tasks. 1454 01:12:33,250 --> 01:12:34,720 I type in something like foo. 1455 01:12:34,720 --> 01:12:35,967 I press Submit. 1456 01:12:35,967 --> 01:12:37,300 And all right, foo now shows up. 1457 01:12:37,300 --> 01:12:41,380 I type in something like-- or I delete that, type in bar, bar now shows up. 1458 01:12:41,380 --> 01:12:42,380 I type in baz. 1459 01:12:42,380 --> 01:12:43,540 Baz now shows up. 1460 01:12:43,540 --> 01:12:45,490 Now, one minor user interface annoyance is 1461 01:12:45,490 --> 01:12:47,920 that it seems that every time I submit a new task, 1462 01:12:47,920 --> 01:12:51,650 this input field retains the value of what it used to be. 1463 01:12:51,650 --> 01:12:54,700 And that's probably not what I want because I'd rather it just clear out. 1464 01:12:54,700 --> 01:12:56,033 I've already submitted the task. 1465 01:12:56,033 --> 01:12:57,400 No need for it to stay there. 1466 01:12:57,400 --> 01:12:59,500 But that's easy to manipulate in JavaScript. 1467 01:12:59,500 --> 01:13:01,690 If I want to clear out this input field-- 1468 01:13:01,690 --> 01:13:03,990 the input field whose ID is task-- 1469 01:13:03,990 --> 01:13:09,160 then all I need to do is say document.querySelector task-- 1470 01:13:09,160 --> 01:13:10,750 get me that input field-- 1471 01:13:10,750 --> 01:13:14,290 change its value equal to the empty string-- 1472 01:13:14,290 --> 01:13:17,140 equal to nothing just to say clear out the value 1473 01:13:17,140 --> 01:13:20,140 of what happens to be inside of that input field right now. 1474 01:13:20,140 --> 01:13:23,650 And now if I refresh the page, type in foo, press Submit, 1475 01:13:23,650 --> 01:13:27,220 input field clears out and now I can type in something like bar, 1476 01:13:27,220 --> 01:13:31,185 and then something like baz to continue to add tasks as well. 1477 01:13:31,185 --> 01:13:34,060 Now, one thing that might be slightly annoying is if I'm not careful, 1478 01:13:34,060 --> 01:13:38,530 if I press Submit, well, it submits the empty string as a task, 1479 01:13:38,530 --> 01:13:41,530 and so I just get this empty bullet point that shows up here. 1480 01:13:41,530 --> 01:13:44,650 I press Submit, and I just get all of these empty bullet points. 1481 01:13:44,650 --> 01:13:47,200 It might be nice from a user experience perspective 1482 01:13:47,200 --> 01:13:49,270 if I were to not allow the user to do that, 1483 01:13:49,270 --> 01:13:52,600 not allow them to submit a task if they haven't actually typed something 1484 01:13:52,600 --> 01:13:54,730 in to the new task field. 1485 01:13:54,730 --> 01:13:57,880 And we can do that just by modifying properties of elements. 1486 01:13:57,880 --> 01:14:01,780 It turns out that HTML elements have a property called disabled 1487 01:14:01,780 --> 01:14:07,220 that can be true or false that allows us to disable something like a button. 1488 01:14:07,220 --> 01:14:09,880 So if I want to disable the Submit button, 1489 01:14:09,880 --> 01:14:13,490 one thing I might want to do first is give this Submit button an ID. 1490 01:14:13,490 --> 01:14:17,110 I'll give it an ID of submit, so that in my JavaScript code, 1491 01:14:17,110 --> 01:14:20,110 I can reference the Submit button. 1492 01:14:20,110 --> 01:14:26,140 And now inside of this JavaScript code, when the DOM content is loaded, 1493 01:14:26,140 --> 01:14:31,390 by default, the Submit button should be disabled. 1494 01:14:31,390 --> 01:14:34,198 Like when I first load the page, I don't want the Submit button 1495 01:14:34,198 --> 01:14:36,490 to be enabled because I want the user to type in a task 1496 01:14:36,490 --> 01:14:38,990 first before I enable the Submit button. 1497 01:14:38,990 --> 01:14:40,520 So how do I do that? 1498 01:14:40,520 --> 01:14:44,410 Well, I can document.querySelector get me the element whose ID is submit. 1499 01:14:44,410 --> 01:14:49,240 Get me that Submit button, and just set its disabled property equal to true. 1500 01:14:49,240 --> 01:14:51,400 JavaScript has Boolean values true and false. 1501 01:14:51,400 --> 01:14:56,270 I set the disabled value equal to true to disable the Submit button. 1502 01:14:56,270 --> 01:14:58,863 Now if I refresh the page, I can type in a new task, 1503 01:14:58,863 --> 01:15:00,280 but the Submit button is disabled. 1504 01:15:00,280 --> 01:15:01,238 It doesn't do anything. 1505 01:15:01,238 --> 01:15:03,072 Obviously, I don't want to keep it that way. 1506 01:15:03,072 --> 01:15:05,350 I'd like it such that as I begin to type things in, 1507 01:15:05,350 --> 01:15:07,780 then the Submit button stops being disabled. 1508 01:15:07,780 --> 01:15:11,450 Disabled gets set from true to false instead. 1509 01:15:11,450 --> 01:15:14,890 And so what I really want to do is listen for me, 1510 01:15:14,890 --> 01:15:17,900 like, pressing keys on the keyboard. 1511 01:15:17,900 --> 01:15:22,210 And so the way I can do that is by adding yet another event listener. 1512 01:15:22,210 --> 01:15:26,350 document.querySelector-- what do I want to add a querySelector to? 1513 01:15:26,350 --> 01:15:28,435 What I want to add an event handler for? 1514 01:15:28,435 --> 01:15:30,310 Well, I want to add an event handler for when 1515 01:15:30,310 --> 01:15:32,950 I type something into this input field. 1516 01:15:32,950 --> 01:15:36,110 And this input field has an ID of task. 1517 01:15:36,110 --> 01:15:40,150 So let me go ahead and get the input field-- the element whose ID is task-- 1518 01:15:40,150 --> 01:15:42,880 and add an onkeyup handler. 1519 01:15:42,880 --> 01:15:48,130 onkeyup, again, is the event when I lift my finger off of a key, 1520 01:15:48,130 --> 01:15:50,590 go ahead and run this function. 1521 01:15:50,590 --> 01:15:52,070 And what should the function do? 1522 01:15:52,070 --> 01:15:55,570 Well, it's going to say document.querySelector #submit, set 1523 01:15:55,570 --> 01:15:59,210 the disabled property equal to false. 1524 01:15:59,210 --> 01:16:00,790 And so now, here's what we're doing. 1525 01:16:00,790 --> 01:16:04,680 We're saying by default when I first load the page, take the Submit button 1526 01:16:04,680 --> 01:16:05,670 and disable it. 1527 01:16:05,670 --> 01:16:08,010 Set .disabled equal to true. 1528 01:16:08,010 --> 01:16:11,190 Then anytime I type a key and my finger comes off 1529 01:16:11,190 --> 01:16:16,090 the key, that means onkeyup is the event that gets triggered, run this function. 1530 01:16:16,090 --> 01:16:19,470 And what the function is going to do is take that same Submit button 1531 01:16:19,470 --> 01:16:21,970 and set its disabled property equal to false. 1532 01:16:21,970 --> 01:16:24,570 So now instead of being disabled, it will be enabled. 1533 01:16:24,570 --> 01:16:27,250 1534 01:16:27,250 --> 01:16:30,840 So if I go back to the page, and go here, right now by default, 1535 01:16:30,840 --> 01:16:34,980 the Submit button is disabled, but as soon as I start typing something, 1536 01:16:34,980 --> 01:16:39,307 now the Submit button is active and I can actually click on it. 1537 01:16:39,307 --> 01:16:41,640 And all right, this isn't great because I clicked on it, 1538 01:16:41,640 --> 01:16:43,420 but the Submit button is still enabled. 1539 01:16:43,420 --> 01:16:46,020 So what I might like to do is after I've submitted 1540 01:16:46,020 --> 01:16:48,240 the form, after I've added a new task, let's 1541 01:16:48,240 --> 01:16:50,410 go back and disable the Submit button. 1542 01:16:50,410 --> 01:16:54,570 So after I've submitted the form, after we've 1543 01:16:54,570 --> 01:16:57,660 added the new task to my list of tasks, after we've cleared out 1544 01:16:57,660 --> 01:17:03,510 the value from the input field, let me also get the Submit button, 1545 01:17:03,510 --> 01:17:06,540 set its disabled property equal to true. 1546 01:17:06,540 --> 01:17:09,240 Now even after I submit the form, the Submit button 1547 01:17:09,240 --> 01:17:13,530 is still going to be disabled, such that I type in foo, now submit is active. 1548 01:17:13,530 --> 01:17:14,430 I press it. 1549 01:17:14,430 --> 01:17:18,003 The Submit button goes back to being inactive as well. 1550 01:17:18,003 --> 01:17:20,670 It turns out that even now, there's still a little bit of a bug. 1551 01:17:20,670 --> 01:17:23,490 If I go back here and I type in something like bar, 1552 01:17:23,490 --> 01:17:27,363 but then I backspace back to, like, nothing here, 1553 01:17:27,363 --> 01:17:28,780 the Submit button is still active. 1554 01:17:28,780 --> 01:17:33,100 So I can still technically submit a task that has no content inside of it. 1555 01:17:33,100 --> 01:17:36,367 And so I might like to have some way of preventing against that as well. 1556 01:17:36,367 --> 01:17:37,950 And that's just some additional logic. 1557 01:17:37,950 --> 01:17:40,260 We now have access to JavaScript that has conditions, 1558 01:17:40,260 --> 01:17:42,510 that has loops, that has functions. 1559 01:17:42,510 --> 01:17:47,250 And so if I want to do something like conditionally check, 1560 01:17:47,250 --> 01:17:57,200 I can say if document.querySelector #task .value.length is greater than 0, 1561 01:17:57,200 --> 01:18:00,650 meaning like something is actually typed in to the task field, 1562 01:18:00,650 --> 01:18:09,610 we'll then go ahead and set disabled to false, but otherwise, 1563 01:18:09,610 --> 01:18:13,160 go ahead and set disabled equal to true. 1564 01:18:13,160 --> 01:18:14,410 So now here, we're checking. 1565 01:18:14,410 --> 01:18:17,290 If the length of what the user has typed in is greater than 0, 1566 01:18:17,290 --> 01:18:19,600 they actually typed something in, then yes, 1567 01:18:19,600 --> 01:18:22,510 give them access to the Submit button, but otherwise, 1568 01:18:22,510 --> 01:18:25,040 don't give them access to that button. 1569 01:18:25,040 --> 01:18:26,500 So now, I refresh the page. 1570 01:18:26,500 --> 01:18:28,540 Disabled by default. I type something in. 1571 01:18:28,540 --> 01:18:29,380 It's enabled. 1572 01:18:29,380 --> 01:18:33,310 I delete, delete, delete, and it goes back to being disabled. 1573 01:18:33,310 --> 01:18:35,410 So JavaScript has allowed us to really make 1574 01:18:35,410 --> 01:18:38,500 our pages much more interactive and immediately interactive 1575 01:18:38,500 --> 01:18:40,990 based on how the user is interacting with the page. 1576 01:18:40,990 --> 01:18:44,500 As they begin to type things, as they begin to delete things, 1577 01:18:44,500 --> 01:18:47,710 as they press buttons, we're able to have the page respond either 1578 01:18:47,710 --> 01:18:51,550 by adding content to the DOM by literally adding parts to the HTML 1579 01:18:51,550 --> 01:18:53,980 page, changing the styles of things, changing 1580 01:18:53,980 --> 01:18:55,690 particular properties of elements. 1581 01:18:55,690 --> 01:18:58,120 And this is really where the power of JavaScript 1582 01:18:58,120 --> 01:19:02,700 begins to come in is in allowing ourselves to do things like that. 1583 01:19:02,700 --> 01:19:04,900 Now so far, we've only been able to have events 1584 01:19:04,900 --> 01:19:08,980 happen when the user does something-- when the user clicks on a button 1585 01:19:08,980 --> 01:19:11,200 or when the user presses a key, for example. 1586 01:19:11,200 --> 01:19:14,530 But it turns out JavaScript has other ways of allowing functions 1587 01:19:14,530 --> 01:19:15,828 to run in fact on their own. 1588 01:19:15,828 --> 01:19:17,620 We can set what are called intervals, where 1589 01:19:17,620 --> 01:19:22,130 a particular function runs every some number of milliseconds, for example. 1590 01:19:22,130 --> 01:19:25,900 And so if we go back to like the counter example from before, right now 1591 01:19:25,900 --> 01:19:28,330 for this counter example, I have to be the one 1592 01:19:28,330 --> 01:19:31,720 to press the count button that is going to increment the value of count 1593 01:19:31,720 --> 01:19:36,290 every single time, but I could put that inside of an interval instead. 1594 01:19:36,290 --> 01:19:42,860 So let me go back to counter.html, whose JavaScript is inside of counter.js. 1595 01:19:42,860 --> 01:19:50,550 And now, what I'd like to say is I would like when the DOM content is loaded, 1596 01:19:50,550 --> 01:19:58,210 let me set an interval for count and 1,000. 1597 01:19:58,210 --> 01:19:59,470 So what is that going to do? 1598 01:19:59,470 --> 01:20:02,260 setInterval is a function built into JavaScript here, 1599 01:20:02,260 --> 01:20:05,380 where I'm saying that I would like to create a new interval where every so 1600 01:20:05,380 --> 01:20:08,210 often, go ahead and run a particular function. 1601 01:20:08,210 --> 01:20:10,210 And I would like to run the count function. 1602 01:20:10,210 --> 01:20:13,570 We'll recall that count function is going to increment the value of count. 1603 01:20:13,570 --> 01:20:16,070 And I'll get rid of this alert for now, just for simplicity. 1604 01:20:16,070 --> 01:20:18,970 All I want the count function to do is update the h1 1605 01:20:18,970 --> 01:20:21,160 with the new value of the counter and go ahead 1606 01:20:21,160 --> 01:20:24,550 and run that count function every 1,000 milliseconds, otherwise known 1607 01:20:24,550 --> 01:20:28,970 as every 1 second, go ahead and run the count function. 1608 01:20:28,970 --> 01:20:34,510 So now when I open counter.html, it's 0, but every second now, it's 1609 01:20:34,510 --> 01:20:37,305 going to change-- every second, updating one by one by one. 1610 01:20:37,305 --> 01:20:38,680 I don't have to click the button. 1611 01:20:38,680 --> 01:20:41,150 Of course, I could and the event handler would still work, 1612 01:20:41,150 --> 01:20:44,530 but the interval is saying now every one second, 1613 01:20:44,530 --> 01:20:46,120 go ahead and run the count function. 1614 01:20:46,120 --> 01:20:47,830 And that has this particular result. 1615 01:20:47,830 --> 01:20:51,100 So if you've ever seen a web page that displays the current time in seconds 1616 01:20:51,100 --> 01:20:53,860 and it was like a countdown timer or it was displaying the current time 1617 01:20:53,860 --> 01:20:56,080 with seconds, it might be doing something like this, 1618 01:20:56,080 --> 01:20:58,900 just having some sort of interval that every second is 1619 01:20:58,900 --> 01:21:01,060 going to count and increment in order to say 1620 01:21:01,060 --> 01:21:05,680 update the number to the one greater, one greater, and one greater than that. 1621 01:21:05,680 --> 01:21:10,060 Of course if I close the page and go back to it-- if I close these pages, 1622 01:21:10,060 --> 01:21:14,470 and then open counter.html again, I've gone back to 0. 1623 01:21:14,470 --> 01:21:18,010 Like, JavaScript is not saving any state about my page. 1624 01:21:18,010 --> 01:21:20,410 It's just every time we're running the page, 1625 01:21:20,410 --> 01:21:23,553 it's going to go back to counter.js, it's going to say, 1626 01:21:23,553 --> 01:21:25,720 all right, we're defining a variable called counter, 1627 01:21:25,720 --> 01:21:27,860 we're setting that variable equal to 0. 1628 01:21:27,860 --> 01:21:31,180 So every time I load the page, it's going to be set back to 0. 1629 01:21:31,180 --> 01:21:33,810 And that might not be great depending on the type of page 1630 01:21:33,810 --> 01:21:34,810 you're trying to create. 1631 01:21:34,810 --> 01:21:38,770 Maybe you want to page that is somehow able to store information, 1632 01:21:38,770 --> 01:21:42,430 such as that on subsequent visits, we're able to utilize the information that 1633 01:21:42,430 --> 01:21:46,890 was already stored-- some way of remembering information for later use. 1634 01:21:46,890 --> 01:21:49,480 In later versions of JavaScript and more modern browsers 1635 01:21:49,480 --> 01:21:53,350 now allow us to do something just like that called localStorage. 1636 01:21:53,350 --> 01:21:55,690 And what localStorage is is it's a way for us 1637 01:21:55,690 --> 01:21:59,320 to be able to store information inside of the user's web browser-- 1638 01:21:59,320 --> 01:22:03,820 that a page can ask to store particular values inside the web browser and later 1639 01:22:03,820 --> 01:22:06,040 on, on subsequent visits to that page, we 1640 01:22:06,040 --> 01:22:09,370 can go back and say let's extract those values that were previously 1641 01:22:09,370 --> 01:22:12,580 stored inside of localStorage. 1642 01:22:12,580 --> 01:22:15,580 localStorage is going to give us access to two key functions 1643 01:22:15,580 --> 01:22:18,310 that we're going to use to manipulate this localStorage. 1644 01:22:18,310 --> 01:22:20,950 The first is localStorage.getItem, where we 1645 01:22:20,950 --> 01:22:23,560 would like to get something out of localStorage based 1646 01:22:23,560 --> 01:22:26,500 on its key-- some name that we have given to that value. 1647 01:22:26,500 --> 01:22:29,740 And we also have access to localStorage.setItem, 1648 01:22:29,740 --> 01:22:32,170 which goes ahead and adds a new value to localStorage 1649 01:22:32,170 --> 01:22:34,720 or replaces an existing value in localStorage, 1650 01:22:34,720 --> 01:22:38,590 setting this key equal to a particular value. 1651 01:22:38,590 --> 01:22:42,880 So we can use localStorage then to allow our web pages, using JavaScript, 1652 01:22:42,880 --> 01:22:46,940 to be able to store information and retrieve information from the browser. 1653 01:22:46,940 --> 01:22:50,380 And let's now try to use that in order to solve 1654 01:22:50,380 --> 01:22:55,600 this problem of the counter that seems to always reset back to 0. 1655 01:22:55,600 --> 01:22:59,260 So now in counter.js, instead of setting counter equal to 0, 1656 01:22:59,260 --> 01:23:02,230 the first thing I want to know is is there already 1657 01:23:02,230 --> 01:23:05,440 a value for the counter in localStorage? 1658 01:23:05,440 --> 01:23:12,880 So I can ask a question like if localStorage.getItem counter, meaning 1659 01:23:12,880 --> 01:23:17,500 go to local storage, try and get the counter, and anything in this 1660 01:23:17,500 --> 01:23:21,610 if expression will happen if there is something inside of localStorage 1661 01:23:21,610 --> 01:23:22,690 for counter. 1662 01:23:22,690 --> 01:23:25,588 But it turns out that if I want to do the inverse of that, say not, 1663 01:23:25,588 --> 01:23:27,130 I can just use the exclamation point. 1664 01:23:27,130 --> 01:23:30,810 Much like in C, in JavaScript, the exclamation point just means not. 1665 01:23:30,810 --> 01:23:34,060 So meaning if there is not something in localStorage 1666 01:23:34,060 --> 01:23:36,430 called counter, well, then let's go ahead 1667 01:23:36,430 --> 01:23:42,430 and just set the value in localStorage. localStorage.setItem counter, 1668 01:23:42,430 --> 01:23:44,600 and we'll set it equal to 0. 1669 01:23:44,600 --> 01:23:47,680 So what this is doing here is before anything else happens, 1670 01:23:47,680 --> 01:23:52,840 we are checking localStorage to say is there already a value for counter. 1671 01:23:52,840 --> 01:23:54,840 And if there is not already a value for counter, 1672 01:23:54,840 --> 01:23:57,673 we need to make sure there is something there inside of localStorage 1673 01:23:57,673 --> 01:23:58,610 for the counter. 1674 01:23:58,610 --> 01:24:03,663 So we are going to set the value of counter equal to 0, for example. 1675 01:24:03,663 --> 01:24:06,830 And so now, what needs to change, I'll go ahead and get rid of the interval, 1676 01:24:06,830 --> 01:24:08,810 so that it only happens when I click on it. 1677 01:24:08,810 --> 01:24:11,720 But what should this count function actually do? 1678 01:24:11,720 --> 01:24:14,710 Well, first, let me get the value of the counter. 1679 01:24:14,710 --> 01:24:20,110 Counter is going to be whatever localStorage.getItem is. 1680 01:24:20,110 --> 01:24:23,230 I'm going to get the counter out of localStorage. 1681 01:24:23,230 --> 01:24:26,020 I'm going to increment it, counter++. 1682 01:24:26,020 --> 01:24:30,370 We'll go ahead and set the value of this h1 element's innerHTML equal to that 1683 01:24:30,370 --> 01:24:31,690 counter. 1684 01:24:31,690 --> 01:24:37,900 But the last step is I'll also do localStorage.setItem counter is 1685 01:24:37,900 --> 01:24:41,170 equal to the new value of counter. 1686 01:24:41,170 --> 01:24:44,260 So what I've done here is to say that when I click the button, 1687 01:24:44,260 --> 01:24:45,970 count function is going to run. 1688 01:24:45,970 --> 01:24:47,920 We're first going to go into localStorage, 1689 01:24:47,920 --> 01:24:50,380 get the value for the key counter. 1690 01:24:50,380 --> 01:24:52,230 Whatever the value of counter happens to be, 1691 01:24:52,230 --> 01:24:54,408 save it inside of this variable called counter. 1692 01:24:54,408 --> 01:24:56,200 We'll go ahead and increment that variable, 1693 01:24:56,200 --> 01:25:00,670 setting it equal to itself plus 1, update the h1's innerHTML same 1694 01:25:00,670 --> 01:25:03,710 as before, just to update what we actually see on the page, 1695 01:25:03,710 --> 01:25:07,850 but then go ahead and localStorage.setItem counter 1696 01:25:07,850 --> 01:25:11,360 gets set to counter, for example. 1697 01:25:11,360 --> 01:25:17,440 So now, let's go ahead and see what's going to happen. 1698 01:25:17,440 --> 01:25:22,840 If I go ahead and open counter.html, we see 0. 1699 01:25:22,840 --> 01:25:24,530 We count 1, 2, 3, 4, 5. 1700 01:25:24,530 --> 01:25:26,230 Everything so far, so good. 1701 01:25:26,230 --> 01:25:28,870 Now, watch what happens if I refresh this page. 1702 01:25:28,870 --> 01:25:30,422 I refresh the page. 1703 01:25:30,422 --> 01:25:32,380 And all right, that seems a little bit strange. 1704 01:25:32,380 --> 01:25:33,312 It's 0. 1705 01:25:33,312 --> 01:25:35,020 Let me try counting and see what happens. 1706 01:25:35,020 --> 01:25:36,560 I press count. 1707 01:25:36,560 --> 01:25:38,765 And all right, the count change to 6. 1708 01:25:38,765 --> 01:25:41,140 So it seems like it did remember that I counted up to 5-- 1709 01:25:41,140 --> 01:25:42,313 0, 1, 2, 3, 4, 5. 1710 01:25:42,313 --> 01:25:44,230 But when I refreshed the page, it still showed 1711 01:25:44,230 --> 01:25:46,900 me 0, but then let me count up to the number 6. 1712 01:25:46,900 --> 01:25:49,025 And now, I can keep counting 7, 8, 9, 10. 1713 01:25:49,025 --> 01:25:50,650 What happens if I refresh the page now? 1714 01:25:50,650 --> 01:25:51,220 I can try it. 1715 01:25:51,220 --> 01:25:52,630 I refresh the page. 1716 01:25:52,630 --> 01:25:55,300 I've gone back to 0, but I count-- 1717 01:25:55,300 --> 01:25:56,440 and OK, now, I'm at 11. 1718 01:25:56,440 --> 01:25:59,060 So somehow, I am still remembering, but the first time, it's 1719 01:25:59,060 --> 01:26:00,760 still giving me 0 every time. 1720 01:26:00,760 --> 01:26:02,600 Why might that be? 1721 01:26:02,600 --> 01:26:04,900 Well, if you look back at counter.html, you'll 1722 01:26:04,900 --> 01:26:07,690 notice that the reason is just inside the body of the page. 1723 01:26:07,690 --> 01:26:10,720 The initial value of h1 is just always 0. 1724 01:26:10,720 --> 01:26:12,850 So if I want to fix that, then what I need to say 1725 01:26:12,850 --> 01:26:15,310 is when the DOM content is loaded, go ahead 1726 01:26:15,310 --> 01:26:19,010 and get document.querySelector h1. 1727 01:26:19,010 --> 01:26:25,990 Go ahead and update the innerHTML equal to whatever localStorage.getItem 1728 01:26:25,990 --> 01:26:28,120 counter happens to be. 1729 01:26:28,120 --> 01:26:31,360 So every time I open the page, even before I click the button, 1730 01:26:31,360 --> 01:26:33,580 even before the event listener is triggered, 1731 01:26:33,580 --> 01:26:35,860 I'd like to say, go ahead and replace this heading, 1732 01:26:35,860 --> 01:26:40,540 update its innerHTML to be the result of getting the counter out 1733 01:26:40,540 --> 01:26:43,070 of localStorage, for example. 1734 01:26:43,070 --> 01:26:45,696 So now if I refresh the page, it's at 11. 1735 01:26:45,696 --> 01:26:47,360 I can update, update, update. 1736 01:26:47,360 --> 01:26:49,390 Click again some number of times. 1737 01:26:49,390 --> 01:26:51,010 Bring it up to 18, for example. 1738 01:26:51,010 --> 01:26:53,490 Refresh the page, and it stays at the number 18. 1739 01:26:53,490 --> 01:26:55,420 And no matter what value I get it to, it's 1740 01:26:55,420 --> 01:26:58,360 going to store that number inside of local storage, such 1741 01:26:58,360 --> 01:27:01,470 that when I refresh the page, that number is going to stay there. 1742 01:27:01,470 --> 01:27:04,410 And we can actually see the value inside of localStorage 1743 01:27:04,410 --> 01:27:06,880 by, again, going into Chrome's inspector. 1744 01:27:06,880 --> 01:27:08,230 I go into Chrome. 1745 01:27:08,230 --> 01:27:14,360 If I go to the Application tab and I go to Local Storage here on the left, 1746 01:27:14,360 --> 01:27:17,740 I can see that I have a value for key counter, whose value in this case 1747 01:27:17,740 --> 01:27:18,680 happens to be 28. 1748 01:27:18,680 --> 01:27:19,900 And you could go into local storage. 1749 01:27:19,900 --> 01:27:21,250 You could manipulate this value. 1750 01:27:21,250 --> 01:27:22,510 You could delete it if you want. 1751 01:27:22,510 --> 01:27:24,468 But this just goes to show you that we have now 1752 01:27:24,468 --> 01:27:28,600 stored this value inside of my browser, such that on subsequent visits 1753 01:27:28,600 --> 01:27:32,530 if this page gets loaded again, we can access that value from inside 1754 01:27:32,530 --> 01:27:34,840 of the application as well. 1755 01:27:34,840 --> 01:27:38,258 And so now, we've been able to see how our pages are able to store data 1756 01:27:38,258 --> 01:27:41,050 in order to just make the user experience a little bit better if we 1757 01:27:41,050 --> 01:27:43,870 want the user to be able to have information remembered 1758 01:27:43,870 --> 01:27:47,320 from the last time they visited a particular page, which can sometimes 1759 01:27:47,320 --> 01:27:49,957 actually be quite helpful. 1760 01:27:49,957 --> 01:27:52,540 All right, so now, we've seen a lot of features of JavaScript. 1761 01:27:52,540 --> 01:27:55,010 We've seen a bunch of different ways of representing data. 1762 01:27:55,010 --> 01:27:59,410 We stored data in variables, and those variables have had types like integers. 1763 01:27:59,410 --> 01:28:01,360 Those variables have sometimes been strings. 1764 01:28:01,360 --> 01:28:03,100 Sometimes, they've been HTML elements. 1765 01:28:03,100 --> 01:28:06,075 Sometimes, they've been arrays or lists of items. 1766 01:28:06,075 --> 01:28:07,700 Sometimes, they've even been functions. 1767 01:28:07,700 --> 01:28:09,790 We can set a variable equal to a function. 1768 01:28:09,790 --> 01:28:14,020 But perhaps one of the most useful data types inside of JavaScript 1769 01:28:14,020 --> 01:28:16,240 is the JavaScript object. 1770 01:28:16,240 --> 01:28:18,990 So I'll go into the JavaScript console just to demonstrate this. 1771 01:28:18,990 --> 01:28:21,640 What the JavaScript object is is it's really 1772 01:28:21,640 --> 01:28:24,460 the equivalent of, like, a Python dictionary-- 1773 01:28:24,460 --> 01:28:27,340 some association of keys to values, where 1774 01:28:27,340 --> 01:28:30,100 you can look up something by a key or by a property 1775 01:28:30,100 --> 01:28:33,530 and see what its value happens to be. 1776 01:28:33,530 --> 01:28:36,160 So if I had a variable like person, I could 1777 01:28:36,160 --> 01:28:41,260 set person equal to a JavaScript object, whose first name is 1778 01:28:41,260 --> 01:28:45,700 Harry and whose last name is Potter, again, 1779 01:28:45,700 --> 01:28:49,810 using syntax very similar to what the dictionary syntax looks 1780 01:28:49,810 --> 01:28:52,480 like inside of Python as well. 1781 01:28:52,480 --> 01:28:55,510 And now that I have this variable person, which is first 1782 01:28:55,510 --> 01:28:58,623 Harry, last Potter, I can access a particular property 1783 01:28:58,623 --> 01:29:00,040 of the person in a number of ways. 1784 01:29:00,040 --> 01:29:03,610 I can say something like person.first to say get me the first named 1785 01:29:03,610 --> 01:29:06,230 property of this particular object. 1786 01:29:06,230 --> 01:29:07,900 And I see that it's equal to Harry. 1787 01:29:07,900 --> 01:29:11,140 I could equivalently use square bracket notation the way Python does. 1788 01:29:11,140 --> 01:29:14,800 Square bracket first, and that will also give me Harry. 1789 01:29:14,800 --> 01:29:17,350 But this turns out to be quite powerful to be 1790 01:29:17,350 --> 01:29:19,840 able to represent data in this structured way 1791 01:29:19,840 --> 01:29:22,120 like this, where I have an association of keys 1792 01:29:22,120 --> 01:29:25,180 or otherwise known as properties with particular values. 1793 01:29:25,180 --> 01:29:28,030 And then I have the ability given a JavaScript object, 1794 01:29:28,030 --> 01:29:30,640 to be able to access a particular value. 1795 01:29:30,640 --> 01:29:33,340 And it turns out that one of the ways this is most useful 1796 01:29:33,340 --> 01:29:38,420 is in the exchange of data-- moving data around from one service to another. 1797 01:29:38,420 --> 01:29:42,010 And so here, we're going to introduce what are known as APIs, otherwise known 1798 01:29:42,010 --> 01:29:45,940 as Application Programming Interfaces, which in the context of the web, 1799 01:29:45,940 --> 01:29:49,690 you can think of as some well-defined structured way for services 1800 01:29:49,690 --> 01:29:52,390 on the internet to communicate with each other. 1801 01:29:52,390 --> 01:29:56,020 If you want your application to be able to talk to some other service-- 1802 01:29:56,020 --> 01:29:58,745 maybe you want your application to interact with Google Maps, 1803 01:29:58,745 --> 01:30:01,870 or to be able to interact with Amazon, or some other weather service to get 1804 01:30:01,870 --> 01:30:02,860 the day's weather-- 1805 01:30:02,860 --> 01:30:06,370 then you might be able to access some API, some mechanism whereby 1806 01:30:06,370 --> 01:30:09,910 you can communicate with another service by sending a request 1807 01:30:09,910 --> 01:30:13,780 and receiving back data in some sort of very well-structured format. 1808 01:30:13,780 --> 01:30:17,560 And very often, that well-structured format happens to be a particular type 1809 01:30:17,560 --> 01:30:22,180 of data known as JSON, which stands for JavaScript Object Notation, 1810 01:30:22,180 --> 01:30:27,040 which is a way of transferring data in the form of JavaScript objects-- 1811 01:30:27,040 --> 01:30:30,880 these sort of objects that happen to have properties and values 1812 01:30:30,880 --> 01:30:32,630 associated with them. 1813 01:30:32,630 --> 01:30:34,880 And so what does JavaScript Object Notation look like? 1814 01:30:34,880 --> 01:30:37,755 Well, if we think back to the applications that we've been creating-- 1815 01:30:37,755 --> 01:30:40,720 these applications that are able to represent things like an airline 1816 01:30:40,720 --> 01:30:44,320 and movements of planes between particular destinations-- 1817 01:30:44,320 --> 01:30:48,640 a JavaScript object representing a flight might look something like this-- 1818 01:30:48,640 --> 01:30:52,210 a JavaScript object that has properties for origin is something, 1819 01:30:52,210 --> 01:30:56,260 destination is something, duration is something-- things we've seen before. 1820 01:30:56,260 --> 01:30:58,750 But you might imagine that if we wanted our airline 1821 01:30:58,750 --> 01:31:01,390 to be able to make its data available to other services, 1822 01:31:01,390 --> 01:31:04,120 so that other web applications or other programs 1823 01:31:04,120 --> 01:31:07,210 could programmatically access information about flights, 1824 01:31:07,210 --> 01:31:11,560 we could pass data in this format to those other applications 1825 01:31:11,560 --> 01:31:14,680 so that they could then treat this as a JavaScript object 1826 01:31:14,680 --> 01:31:16,810 and get access to the information about it. 1827 01:31:16,810 --> 01:31:19,540 And the nice thing about this particular representation 1828 01:31:19,540 --> 01:31:22,660 is that it is both human-readable and machine-readable-- 1829 01:31:22,660 --> 01:31:25,990 that we as people can look at this and get an intuitive understanding for what 1830 01:31:25,990 --> 01:31:28,720 all of this means, but also a computer knows 1831 01:31:28,720 --> 01:31:31,750 how to access particular properties that appear before the colon 1832 01:31:31,750 --> 01:31:36,820 and get access to what those values are, which appear after the colon as well. 1833 01:31:36,820 --> 01:31:40,060 So JavaScript Object Notation, otherwise known as JSON, 1834 01:31:40,060 --> 01:31:42,370 offers a very convenient representation. 1835 01:31:42,370 --> 01:31:45,820 And this isn't exactly what the JavaScript object syntax is. 1836 01:31:45,820 --> 01:31:48,730 In JavaScript objects, you don't strictly need the quotation marks 1837 01:31:48,730 --> 01:31:49,490 around the keys. 1838 01:31:49,490 --> 01:31:52,750 You could just say origin colon and not origin in quotation marks. 1839 01:31:52,750 --> 01:31:56,390 So JavaScript Object Notation uses slightly different syntax, 1840 01:31:56,390 --> 01:31:59,560 but ultimately very reminiscent of what we've seen in JavaScript objects. 1841 01:31:59,560 --> 01:32:02,410 And JavaScript knows how to take data in this form 1842 01:32:02,410 --> 01:32:04,663 and turn it into something like a JavaScript object. 1843 01:32:04,663 --> 01:32:07,330 And it turns out there are ways of doing this in Python as well. 1844 01:32:07,330 --> 01:32:09,610 Other programming languages have the ability 1845 01:32:09,610 --> 01:32:14,040 to interpret JSON data in order to use it in some meaningful way. 1846 01:32:14,040 --> 01:32:16,840 And another advantage of the JSON representation 1847 01:32:16,840 --> 01:32:20,140 is it is very conducive to representing structures of things. 1848 01:32:20,140 --> 01:32:23,350 So these values don't just need to be strings or numbers. 1849 01:32:23,350 --> 01:32:25,660 They could be lists, or arrays that happen 1850 01:32:25,660 --> 01:32:28,480 to have a sequence of possible values, or they could even 1851 01:32:28,480 --> 01:32:32,620 be other JavaScript objects that if we wanted to represent not just the city 1852 01:32:32,620 --> 01:32:35,620 name, but represent the city name and the airport code, 1853 01:32:35,620 --> 01:32:38,200 for example, as we saw that we wanted to do before, 1854 01:32:38,200 --> 01:32:42,280 I could, instead of having origin be equal to a string like New York, 1855 01:32:42,280 --> 01:32:47,170 have origin be equal to yet another JavaScript object that contains a city 1856 01:32:47,170 --> 01:32:50,560 property and a code property, where the city is the name of the city 1857 01:32:50,560 --> 01:32:52,930 and the code is the name in the airport code. 1858 01:32:52,930 --> 01:32:55,480 And the important thing is as long as I and the person 1859 01:32:55,480 --> 01:32:58,450 I'm communicating with agree upon this representation, 1860 01:32:58,450 --> 01:33:02,920 agree upon what the names of these keys are and what the structure of this JSON 1861 01:33:02,920 --> 01:33:07,450 payload, this JSON object happens to be, then the person on the receiving end 1862 01:33:07,450 --> 01:33:10,930 can take this data and write a program that's able to interpret it and use 1863 01:33:10,930 --> 01:33:13,540 that data in some meaningful way. 1864 01:33:13,540 --> 01:33:16,060 And so we'll see an example of this now of using JavaScript 1865 01:33:16,060 --> 01:33:19,030 to be able to communicate with yet another online service, 1866 01:33:19,030 --> 01:33:23,210 in particular for accessing information about currency exchange rates. 1867 01:33:23,210 --> 01:33:25,090 Currency exchange rates are always changing. 1868 01:33:25,090 --> 01:33:28,040 We want access to the latest currency exchange rate data. 1869 01:33:28,040 --> 01:33:30,550 And if there is an online service, an API, 1870 01:33:30,550 --> 01:33:33,400 that provides access to that data in JSON form-- 1871 01:33:33,400 --> 01:33:35,920 in a format like this that is machine-readable-- then 1872 01:33:35,920 --> 01:33:39,730 we can use that data to write a currency exchange 1873 01:33:39,730 --> 01:33:44,260 application that uses real-time data in order to make those conversions. 1874 01:33:44,260 --> 01:33:45,643 What might that data look like? 1875 01:33:45,643 --> 01:33:47,560 Well, the data could look something like this, 1876 01:33:47,560 --> 01:33:49,750 that we make a request for accessing what 1877 01:33:49,750 --> 01:33:52,630 are the exchange rates for converting from US dollars, 1878 01:33:52,630 --> 01:33:54,460 otherwise known as USD. 1879 01:33:54,460 --> 01:34:00,400 And we get back a JSON object that looks like this that has a base key of USD, 1880 01:34:00,400 --> 01:34:03,340 and then it has a rates key that has a whole bunch of rates within it, 1881 01:34:03,340 --> 01:34:07,510 so conversion to euros and Japanese yen, Great Britain pounds, as well as 1882 01:34:07,510 --> 01:34:10,600 Australian dollars, and all of the various different currency exchange 1883 01:34:10,600 --> 01:34:13,840 rates for all of these different currencies, for example. 1884 01:34:13,840 --> 01:34:16,740 And this doesn't have to be the way that this data is structured, 1885 01:34:16,740 --> 01:34:18,520 but it happens to be a convenient way. 1886 01:34:18,520 --> 01:34:21,040 And so long as the person providing this data to me 1887 01:34:21,040 --> 01:34:23,770 and I both know what this structure is, we 1888 01:34:23,770 --> 01:34:27,090 can begin to write programs that are able to use that data. 1889 01:34:27,090 --> 01:34:34,490 And so we'll now see our example of an API, which is exchangeratesapi.io. 1890 01:34:34,490 --> 01:34:38,770 And if we go to api.exchangeratesapi.io/latest 1891 01:34:38,770 --> 01:34:44,860 and provide a get parameter of base=USD, then what we get back is data that 1892 01:34:44,860 --> 01:34:46,770 looks like this. 1893 01:34:46,770 --> 01:34:49,910 Now, it's a little bit messy looking, not nearly as clean as we saw before, 1894 01:34:49,910 --> 01:34:52,390 but it's the same exact thing, just without the whitespace. 1895 01:34:52,390 --> 01:34:56,470 We have a JavaScript object that has a rates key that tells me, all right, 1896 01:34:56,470 --> 01:34:59,680 here is the exchange rate between US dollars 1897 01:34:59,680 --> 01:35:02,050 and Canadian dollars, and the pound, and the euro, 1898 01:35:02,050 --> 01:35:04,270 and other currencies that exist as well. 1899 01:35:04,270 --> 01:35:08,140 And down below, we have the base of what base currency we're converting from. 1900 01:35:08,140 --> 01:35:12,670 So all of this data can come back to me if I just make an HTTP request. 1901 01:35:12,670 --> 01:35:15,700 If I make a web request to this particular URL, 1902 01:35:15,700 --> 01:35:20,200 I then get access to all of this currency exchange rate information 1903 01:35:20,200 --> 01:35:22,850 that I can then use inside of my application. 1904 01:35:22,850 --> 01:35:24,100 So how can I do this? 1905 01:35:24,100 --> 01:35:29,200 How can I now begin to use this information inside of an application? 1906 01:35:29,200 --> 01:35:31,120 Let's now create a new page. 1907 01:35:31,120 --> 01:35:34,420 I'm going to call this currency.html. 1908 01:35:34,420 --> 01:35:40,630 Inside of currency.html, I'll add our usual HTML, a title 1909 01:35:40,630 --> 01:35:45,210 of currency exchange, and a body. 1910 01:35:45,210 --> 01:35:48,110 And inside the body, I'm just going to include nothing for now. 1911 01:35:48,110 --> 01:35:50,200 What I really care about is the JavaScript 1912 01:35:50,200 --> 01:35:55,450 that is going to make a web request in order to get access to additional data. 1913 01:35:55,450 --> 01:35:58,300 Now so far in JavaScript, our JavaScript code 1914 01:35:58,300 --> 01:36:02,740 has exclusively been running code that exists only on our computer. 1915 01:36:02,740 --> 01:36:06,190 It's running inside the web browser and all happening inside the web browser. 1916 01:36:06,190 --> 01:36:08,280 We're not communicating with some external server. 1917 01:36:08,280 --> 01:36:10,030 What we'll take a look at now is something 1918 01:36:10,030 --> 01:36:13,210 known as Ajax, which is about asynchronous JavaScript, where 1919 01:36:13,210 --> 01:36:17,650 the idea is that even after a page has loaded, using JavaScript, 1920 01:36:17,650 --> 01:36:21,880 we can make additional web requests to ask for additional information, 1921 01:36:21,880 --> 01:36:25,400 either from our own web servers or from some third-party web servers 1922 01:36:25,400 --> 01:36:28,510 if we want additional information on our page. 1923 01:36:28,510 --> 01:36:30,520 And what we want in this case is for our page 1924 01:36:30,520 --> 01:36:34,570 to make an asynchronous request-- a request for additional data 1925 01:36:34,570 --> 01:36:39,090 about the current currency exchange rates, for example. 1926 01:36:39,090 --> 01:36:40,610 So how am I going to do that? 1927 01:36:40,610 --> 01:36:46,790 Well, I want to do this after the DOM content is loaded, 1928 01:36:46,790 --> 01:36:48,892 so we'll add that usually there. 1929 01:36:48,892 --> 01:36:50,600 And what we're going to take advantage of 1930 01:36:50,600 --> 01:36:53,058 is a function built into more recent versions of JavaScript 1931 01:36:53,058 --> 01:36:57,380 and supported by most major browsers now, and it's a function called fetch. 1932 01:36:57,380 --> 01:37:00,680 And what fetch is going to do is it is going to make a web request. 1933 01:37:00,680 --> 01:37:02,427 It is going to query some website. 1934 01:37:02,427 --> 01:37:03,260 It could be our own. 1935 01:37:03,260 --> 01:37:04,550 It could be someone else's. 1936 01:37:04,550 --> 01:37:09,102 And it's going to get back some HTTP response from that page. 1937 01:37:09,102 --> 01:37:10,060 And I'm going to fetch. 1938 01:37:10,060 --> 01:37:13,280 And the page I'm going to fetch is this URL-- 1939 01:37:13,280 --> 01:37:18,110 api.exchangeratesapi.io/latest?base=USD. 1940 01:37:18,110 --> 01:37:20,600 And the only reason I happen to know how this API works 1941 01:37:20,600 --> 01:37:22,790 is because I've read the API's documentation 1942 01:37:22,790 --> 01:37:25,340 that describes how the URL parameters work 1943 01:37:25,340 --> 01:37:28,240 and what the structure of the data that I get back is. 1944 01:37:28,240 --> 01:37:31,850 And so I'm here going to say go ahead and fetch from this URL. 1945 01:37:31,850 --> 01:37:36,980 Make a HTTP request asking for additional information from this URL 1946 01:37:36,980 --> 01:37:39,980 and get back what the results are going to be. 1947 01:37:39,980 --> 01:37:42,260 And what fetch gives back to us is something 1948 01:37:42,260 --> 01:37:44,540 in JavaScript known as a promise. 1949 01:37:44,540 --> 01:37:48,590 And a promise is going to be a way of representing the idea that something 1950 01:37:48,590 --> 01:37:51,757 is going to come back, but it may not come back immediately. 1951 01:37:51,757 --> 01:37:54,840 We're not going to go into the details of exactly how those promises work, 1952 01:37:54,840 --> 01:37:57,750 but it turns out there's a particular syntax for dealing with them, 1953 01:37:57,750 --> 01:38:03,840 which is that I can say after I fetch, I can add a line called .then that says 1954 01:38:03,840 --> 01:38:05,870 what should I do when the promise comes back, 1955 01:38:05,870 --> 01:38:09,900 once I get back something like a response. 1956 01:38:09,900 --> 01:38:12,200 And so when I get back the response, what I want to do 1957 01:38:12,200 --> 01:38:14,630 is convert the response into JSON-- 1958 01:38:14,630 --> 01:38:18,290 treat it as JSON data-- a JavaScript object, as something 1959 01:38:18,290 --> 01:38:19,850 that I can then manipulate. 1960 01:38:19,850 --> 01:38:23,090 And so what I can do is just use this as a function to say go ahead 1961 01:38:23,090 --> 01:38:28,350 and return response.json. 1962 01:38:28,350 --> 01:38:32,640 And so what this is saying is go ahead and get me the latest exchange rates. 1963 01:38:32,640 --> 01:38:34,327 And then after that's done-- 1964 01:38:34,327 --> 01:38:35,660 this is an asynchronous process. 1965 01:38:35,660 --> 01:38:36,970 It might take some time. 1966 01:38:36,970 --> 01:38:40,350 But once I get back those results, then run this function. 1967 01:38:40,350 --> 01:38:44,340 Take the response and return the JSON version of the response. 1968 01:38:44,340 --> 01:38:46,890 Convert that response into just the raw JSON 1969 01:38:46,890 --> 01:38:50,790 data, such that I can use that data to then access the currency exchange 1970 01:38:50,790 --> 01:38:51,750 rates. 1971 01:38:51,750 --> 01:38:53,582 And it turns out that with arrow functions, 1972 01:38:53,582 --> 01:38:56,040 if you ever have a very simple function that all it's doing 1973 01:38:56,040 --> 01:38:59,010 is taking something and returning something else, 1974 01:38:59,010 --> 01:39:01,560 I can simplify this function even further 1975 01:39:01,560 --> 01:39:04,980 and I can omit the curly braces, I can omit the return. 1976 01:39:04,980 --> 01:39:08,460 I can just say response arrow response.json. 1977 01:39:08,460 --> 01:39:11,070 And this is a shorthand way of saying a function that 1978 01:39:11,070 --> 01:39:16,170 takes as input the response and returns as output response.json. 1979 01:39:16,170 --> 01:39:19,470 So here, I'm saying go ahead and fetch me the latest exchange 1980 01:39:19,470 --> 01:39:25,020 rates from this particular API, then convert the response to JSON data, 1981 01:39:25,020 --> 01:39:30,660 and then once you have the data, here's what I want you to do with that data. 1982 01:39:30,660 --> 01:39:34,605 And for now, let's just go ahead and console.log that data just 1983 01:39:34,605 --> 01:39:36,000 to print it out to the terminal. 1984 01:39:36,000 --> 01:39:37,750 So we're not doing anything else just yet. 1985 01:39:37,750 --> 01:39:40,380 All I'm doing is saying get me the exchange rates, 1986 01:39:40,380 --> 01:39:44,340 convert the exchange rates data into JSON, and then let's go ahead 1987 01:39:44,340 --> 01:39:47,070 and print out that data. 1988 01:39:47,070 --> 01:39:49,620 So I'll open up currency.html. 1989 01:39:49,620 --> 01:39:53,280 It's a blank page, but if I look in the JavaScript inspector, 1990 01:39:53,280 --> 01:39:56,430 I see what got logged is a JavaScript object, here indicated 1991 01:39:56,430 --> 01:39:57,810 by the word object. 1992 01:39:57,810 --> 01:40:01,290 And if I click the triangle at left, I can open up and see, all right, 1993 01:40:01,290 --> 01:40:05,190 inside of this object is all of this data about exchange 1994 01:40:05,190 --> 01:40:08,930 rates for a whole bunch of different exchange rates for converting 1995 01:40:08,930 --> 01:40:13,470 from the US dollar, where here, USD 1 means one US dollar is one US dollar, 1996 01:40:13,470 --> 01:40:15,720 for example. 1997 01:40:15,720 --> 01:40:17,720 So now that I've got this data, let's actually 1998 01:40:17,720 --> 01:40:19,890 try and use this inside of the program. 1999 01:40:19,890 --> 01:40:23,090 Maybe let's say I want to convert between US dollars and the euro 2000 01:40:23,090 --> 01:40:26,330 to figure out what the conversion rate is between dollars and euros. 2001 01:40:26,330 --> 01:40:28,640 Well, if we recall what the data looks like, 2002 01:40:28,640 --> 01:40:34,970 the data is a JavaScript object where we have a key called rates, 2003 01:40:34,970 --> 01:40:38,550 and inside of rates is this object, and inside of that object, 2004 01:40:38,550 --> 01:40:43,190 I can access the EUR property to get the exchange rate of one US dollar 2005 01:40:43,190 --> 01:40:45,990 is equal to some number of euros, for example. 2006 01:40:45,990 --> 01:40:50,360 So it's inside of the rates key, and then inside of the EUR key. 2007 01:40:50,360 --> 01:40:54,750 And that's how I know what to get access to inside of my data. 2008 01:40:54,750 --> 01:41:00,170 So what I really want to do is access data.rates.EUR. 2009 01:41:00,170 --> 01:41:03,090 2010 01:41:03,090 --> 01:41:07,370 That says get me all the data that came back, access the rates key, 2011 01:41:07,370 --> 01:41:09,750 and then access the euro key. 2012 01:41:09,750 --> 01:41:14,390 And we'll go ahead and save that in a variable called rate. 2013 01:41:14,390 --> 01:41:19,730 And now, I'll just document.querySelector body .innerHTML 2014 01:41:19,730 --> 01:41:20,690 = rate. 2015 01:41:20,690 --> 01:41:24,690 Just like take that rate, put it inside of the body. 2016 01:41:24,690 --> 01:41:31,550 So now if I refresh currency.html, what I see is just this value, 0.908443, 2017 01:41:31,550 --> 01:41:34,010 which means that right now, 1 US dollar happens 2018 01:41:34,010 --> 01:41:38,270 to be equal to about 0.91 euros, for instance. 2019 01:41:38,270 --> 01:41:39,260 So that's useful. 2020 01:41:39,260 --> 01:41:42,080 I can make this a little more human friendly by putting 2021 01:41:42,080 --> 01:41:43,670 this inside of a template string. 2022 01:41:43,670 --> 01:41:51,450 I could say 1 USD is equal to, and then rate EUR for example. 2023 01:41:51,450 --> 01:41:57,315 And so now if I refresh the page, I see 1 USD is equal to this many EUR. 2024 01:41:57,315 --> 01:41:58,940 And even this is a little bit annoying. 2025 01:41:58,940 --> 01:42:01,357 I probably don't care about it to this many decimal places 2026 01:42:01,357 --> 01:42:04,890 unless I'm really in the mood to be very precise about these exchange rates. 2027 01:42:04,890 --> 01:42:08,038 If I only care about it to like three decimal places, for example, 2028 01:42:08,038 --> 01:42:09,830 it turns out JavaScript has functions I can 2029 01:42:09,830 --> 01:42:14,750 use on numbers like rate.toFixed, passing in three as an argument 2030 01:42:14,750 --> 01:42:17,510 there to mean I'd like to take this exchange rate 2031 01:42:17,510 --> 01:42:21,120 and just round it to three decimal places, for example. 2032 01:42:21,120 --> 01:42:26,492 So now, I refresh the page, and I see 1 USD is equal to 0.909 EUR. 2033 01:42:26,492 --> 01:42:28,700 And the interesting thing about what's happening here 2034 01:42:28,700 --> 01:42:31,950 is this is happening as a result of an asynchronous request. 2035 01:42:31,950 --> 01:42:34,760 I am asking for the latest exchange rates. 2036 01:42:34,760 --> 01:42:37,040 And when I get back the exchange rates data, 2037 01:42:37,040 --> 01:42:40,460 JavaScript is plugging that information into the body of the page. 2038 01:42:40,460 --> 01:42:44,810 I'm now communicating with an API, getting back that API's data in JSON 2039 01:42:44,810 --> 01:42:50,270 form, and then using that data to update the contents of my HTML page. 2040 01:42:50,270 --> 01:42:54,357 Of course in practice, if I really want a currency exchange web page, 2041 01:42:54,357 --> 01:42:57,440 I probably don't just want to display the exchange rate between US dollars 2042 01:42:57,440 --> 01:42:58,310 and euros. 2043 01:42:58,310 --> 01:43:01,430 I probably want to let the user pick what currencies 2044 01:43:01,430 --> 01:43:03,350 they would like to exchange between. 2045 01:43:03,350 --> 01:43:07,220 And so here is how I might go about doing that. 2046 01:43:07,220 --> 01:43:11,120 Inside of the body of the page now, rather than just have an empty body, 2047 01:43:11,120 --> 01:43:12,630 let's go ahead and add a form. 2048 01:43:12,630 --> 01:43:15,920 That form is going to have an input, whose ID is currency, 2049 01:43:15,920 --> 01:43:18,050 just so I have a way of referencing it later. 2050 01:43:18,050 --> 01:43:22,570 The placeholder will just be currency, and the type of it is text. 2051 01:43:22,570 --> 01:43:25,490 And then I'll have an input whose type is submit, 2052 01:43:25,490 --> 01:43:27,127 and we'll give it a value of convert. 2053 01:43:27,127 --> 01:43:28,460 That'll be what the button says. 2054 01:43:28,460 --> 01:43:32,360 It says convert, and then I can convert to a particular currency. 2055 01:43:32,360 --> 01:43:35,210 And then I need some place to put my results, 2056 01:43:35,210 --> 01:43:39,167 so I'll go ahead and add a div whose ID is result. 2057 01:43:39,167 --> 01:43:41,750 And this is where after I've done all the currency conversion, 2058 01:43:41,750 --> 01:43:44,458 this is where I'm going to put the results of doing that currency 2059 01:43:44,458 --> 01:43:46,770 conversion. 2060 01:43:46,770 --> 01:43:50,220 So now rather than fetch right away, here's what I need to do. 2061 01:43:50,220 --> 01:43:53,740 I need to do something only when the form is submitted. 2062 01:43:53,740 --> 01:43:59,790 So I can get the form by saying document.querySelector form .onsubmit 2063 01:43:59,790 --> 01:44:01,813 equals this function. 2064 01:44:01,813 --> 01:44:03,730 And I'm going to go ahead and just in advance, 2065 01:44:03,730 --> 01:44:06,690 return false at the end of the function so we don't actually try 2066 01:44:06,690 --> 01:44:08,380 and submit the form to another page. 2067 01:44:08,380 --> 01:44:12,310 I just want to run everything locally on this same page. 2068 01:44:12,310 --> 01:44:15,780 But now inside of this form, once you submit it, 2069 01:44:15,780 --> 01:44:20,590 that is when I want to run this code that is going to fetch new data. 2070 01:44:20,590 --> 01:44:23,280 So I'm going to fetch data from the exchange rates API, 2071 01:44:23,280 --> 01:44:25,800 convert that data to JSON same as before, 2072 01:44:25,800 --> 01:44:28,330 then go ahead and get access to that data. 2073 01:44:28,330 --> 01:44:33,030 But now, what I want to do is I want to figure out what the user actually 2074 01:44:33,030 --> 01:44:34,568 typed in to the input field. 2075 01:44:34,568 --> 01:44:37,610 And that is going to be the currency that I care about getting access to. 2076 01:44:37,610 --> 01:44:40,050 So I'll create a variable called currency, 2077 01:44:40,050 --> 01:44:43,560 which will be equal to document.querySelector. 2078 01:44:43,560 --> 01:44:47,950 And the input field, if I scroll down, it has an ID of currency. 2079 01:44:47,950 --> 01:44:49,950 So if I want to get that input field, I'm 2080 01:44:49,950 --> 01:44:56,620 going to say get the element whose ID is currency and get its value. 2081 01:44:56,620 --> 01:45:02,590 So this now is the currency that the user wanted me to get access to. 2082 01:45:02,590 --> 01:45:10,160 And I can then say data.rates currency instead of data.rates.EUR. 2083 01:45:10,160 --> 01:45:13,070 And importantly, I can't do data.rates.currency. 2084 01:45:13,070 --> 01:45:14,990 That would literally try to access a property 2085 01:45:14,990 --> 01:45:17,210 of rates that is called currency. 2086 01:45:17,210 --> 01:45:19,520 If I use square brackets instead, that allows 2087 01:45:19,520 --> 01:45:22,580 me to use a variable-- something like the currency variable, which 2088 01:45:22,580 --> 01:45:26,990 I defined up here on line 13 as the currency that the user typed in. 2089 01:45:26,990 --> 01:45:31,770 I would like to access that particular currency inside of the rates. 2090 01:45:31,770 --> 01:45:33,960 And so now, I can ask a question. 2091 01:45:33,960 --> 01:45:35,520 There are two possibilities here. 2092 01:45:35,520 --> 01:45:40,600 Either the currency the user typed in is a valid currency or it's not. 2093 01:45:40,600 --> 01:45:42,750 And it turns out that if you try and access 2094 01:45:42,750 --> 01:45:45,870 a property of an object that doesn't exist, what you get back 2095 01:45:45,870 --> 01:45:48,750 is a particular JavaScript variable called undefined, 2096 01:45:48,750 --> 01:45:50,460 meaning there is no value there. 2097 01:45:50,460 --> 01:45:56,790 So for example, if I have something like let person = first name is Harry 2098 01:45:56,790 --> 01:45:59,700 and last name is Potter like we did before, 2099 01:45:59,700 --> 01:46:03,420 I can access something like person.first and get Harry. 2100 01:46:03,420 --> 01:46:05,910 I can access person.last and get Potter. 2101 01:46:05,910 --> 01:46:08,490 But if access person.middle, that is going 2102 01:46:08,490 --> 01:46:12,300 to be a special variable in JavaScript or a special value in JavaScript 2103 01:46:12,300 --> 01:46:16,187 called undefined, meaning there is no value there. 2104 01:46:16,187 --> 01:46:19,020 It's slightly different from null, which also has a similar meaning. 2105 01:46:19,020 --> 01:46:21,340 They're used in slightly different contexts. 2106 01:46:21,340 --> 01:46:27,090 So here, what I can say is if the rate is not undefined, well 2107 01:46:27,090 --> 01:46:37,330 then, let's go ahead and update not the body, but the result to say 1 USD 2108 01:46:37,330 --> 01:46:39,670 is equal to this rate-- 2109 01:46:39,670 --> 01:46:46,020 not necessarily euros, but whatever the currency happens to be. 2110 01:46:46,020 --> 01:46:51,890 And otherwise, let's go ahead and document.querySelector result 2111 01:46:51,890 --> 01:46:57,590 .innerHTML = invalid currency, just to let the user know that the currency 2112 01:46:57,590 --> 01:47:00,523 they tried to provide is not actually a valid currency, 2113 01:47:00,523 --> 01:47:03,440 and so we're going to need to try a different currency in order to get 2114 01:47:03,440 --> 01:47:05,350 the result to work. 2115 01:47:05,350 --> 01:47:07,300 So now, here's what we can do. 2116 01:47:07,300 --> 01:47:10,090 If I open up currency.html again, I now see 2117 01:47:10,090 --> 01:47:12,490 a form where I can type in a currency. 2118 01:47:12,490 --> 01:47:15,160 I can type in something like the euro, for example. 2119 01:47:15,160 --> 01:47:19,450 Press Convert, and I see, all right, 1 USD equal to 0.090 EUR. 2120 01:47:19,450 --> 01:47:21,370 I type in something like the pound. 2121 01:47:21,370 --> 01:47:22,290 Press Convert. 2122 01:47:22,290 --> 01:47:24,760 1 US dollar equal to 0.771 pounds. 2123 01:47:24,760 --> 01:47:27,010 I type in the Japanese yen. 2124 01:47:27,010 --> 01:47:30,370 1 USD is equal to 109.852 Japanese yen. 2125 01:47:30,370 --> 01:47:33,370 And all of this is happening where every time I submit the form, 2126 01:47:33,370 --> 01:47:34,940 it's making yet another request. 2127 01:47:34,940 --> 01:47:37,210 So if the exchange rates happen to change in 2128 01:47:37,210 --> 01:47:40,270 between when I submit the form, the next time I submit the form, 2129 01:47:40,270 --> 01:47:43,510 I will be getting the latest exchange rates according to that exchange rates 2130 01:47:43,510 --> 01:47:46,510 API and the results are going to come back here. 2131 01:47:46,510 --> 01:47:49,070 And of course, if I type in a currency that doesn't exist, 2132 01:47:49,070 --> 01:47:53,322 I type in something like foo for example and press Convert, invalid currency. 2133 01:47:53,322 --> 01:47:56,530 So it's going to report back to me that it wasn't able to find that currency, 2134 01:47:56,530 --> 01:47:58,970 and so it tells me that I need to type in something valid. 2135 01:47:58,970 --> 01:48:00,550 And so I can type in something valid. 2136 01:48:00,550 --> 01:48:02,570 Maybe I tried just US dollars itself. 2137 01:48:02,570 --> 01:48:05,830 It tells me 1 USD is equal to 1 USD-- 2138 01:48:05,830 --> 01:48:08,830 exactly what I would expect it to be. 2139 01:48:08,830 --> 01:48:12,200 Now, there are a couple of optimizations and improvements that we can make here. 2140 01:48:12,200 --> 01:48:14,770 One is that I can search for euros right now with EUR. 2141 01:48:14,770 --> 01:48:16,000 Press Convert. 2142 01:48:16,000 --> 01:48:19,220 But if I search for euros in lowercase, for example, 2143 01:48:19,220 --> 01:48:21,730 it turns out it thinks that's an invalid currency. 2144 01:48:21,730 --> 01:48:25,870 And the reason why is because if you look at the data that comes back to me 2145 01:48:25,870 --> 01:48:29,980 from the API, this is the data that I get back from the exchange rates API, 2146 01:48:29,980 --> 01:48:33,820 what you'll notice is that all of the currencies are all in capital letters-- 2147 01:48:33,820 --> 01:48:36,350 they're all capital letters, all capital letters-- 2148 01:48:36,350 --> 01:48:38,920 which means the only keys that I'm allowed to access 2149 01:48:38,920 --> 01:48:41,200 are, in fact, those that have capital letters in them 2150 01:48:41,200 --> 01:48:45,380 because these are the only keys that this API makes available to me. 2151 01:48:45,380 --> 01:48:49,510 So if I want to convert between usd and euros lowercase, 2152 01:48:49,510 --> 01:48:52,540 what I might want to do is first take the currency-- 2153 01:48:52,540 --> 01:48:54,490 the thing the user typed in-- 2154 01:48:54,490 --> 01:48:58,420 and first just call toUpperCase on it, which 2155 01:48:58,420 --> 01:49:02,047 is a JavaScript function that takes a string and converts it to uppercase. 2156 01:49:02,047 --> 01:49:03,880 I'd like to take whatever the user typed in, 2157 01:49:03,880 --> 01:49:06,040 and now just first convert it to uppercase. 2158 01:49:06,040 --> 01:49:11,140 That way, if I go back here, I can type in eur lowercase, press Convert, 2159 01:49:11,140 --> 01:49:14,917 and I'm still able to get the correct conversion rate. 2160 01:49:14,917 --> 01:49:18,250 The other thing that we won't noticeably notice the difference with here is that 2161 01:49:18,250 --> 01:49:21,625 right now, I'm assuming that all of this is going to go successfully-- 2162 01:49:21,625 --> 01:49:24,250 that we're going to successfully be able to make a web request, 2163 01:49:24,250 --> 01:49:26,578 we'll successfully convert the response back to JSON-- 2164 01:49:26,578 --> 01:49:27,370 but you never know. 2165 01:49:27,370 --> 01:49:28,600 An API could go down. 2166 01:49:28,600 --> 01:49:31,180 The API could change and do something unexpected. 2167 01:49:31,180 --> 01:49:33,650 And so anytime you're dealing with these types of promises 2168 01:49:33,650 --> 01:49:35,870 where you fetch something and say then do this, 2169 01:49:35,870 --> 01:49:38,350 then do that, it can often be a good idea 2170 01:49:38,350 --> 01:49:43,390 to add one last case, which is a catch case that basically says what should 2171 01:49:43,390 --> 01:49:45,830 you do if something goes wrong. 2172 01:49:45,830 --> 01:49:47,290 So I can say catch the error. 2173 01:49:47,290 --> 01:49:51,520 And what I can just do is say like console.log error, 2174 01:49:51,520 --> 01:49:53,590 and then log the error there. 2175 01:49:53,590 --> 01:49:56,410 And all that's really saying is that if anything above 2176 01:49:56,410 --> 01:49:59,740 goes wrong with the fetching and trying to process the response, 2177 01:49:59,740 --> 01:50:02,650 it's going to catch the error, and then it will just, like, print out 2178 01:50:02,650 --> 01:50:05,868 to the console that something went wrong-- some error message happened. 2179 01:50:05,868 --> 01:50:08,410 And so that can be helpful and nice to have just to make sure 2180 01:50:08,410 --> 01:50:10,840 that when things crash, they crash in a predictable way-- 2181 01:50:10,840 --> 01:50:15,100 that you're able to see exactly what the error is just by looking 2182 01:50:15,100 --> 01:50:16,990 inside the JavaScript console. 2183 01:50:16,990 --> 01:50:19,510 And so now, we have a fully working web page 2184 01:50:19,510 --> 01:50:22,360 that is able to communicate with an external API-- that 2185 01:50:22,360 --> 01:50:25,870 is able to ask for information from another service on the internet, 2186 01:50:25,870 --> 01:50:29,230 use those results, and put them back into the page-- really just going 2187 01:50:29,230 --> 01:50:33,700 to show the power now that we get by taking advantage of the JavaScript 2188 01:50:33,700 --> 01:50:34,210 language. 2189 01:50:34,210 --> 01:50:38,140 We have the ability now to not only use JavaScript to be able to run code 2190 01:50:38,140 --> 01:50:41,200 on the client, where we weren't able to before-- where right before, 2191 01:50:41,200 --> 01:50:44,450 we only had Python code that was running on a web server-- 2192 01:50:44,450 --> 01:50:47,650 but using JavaScript, the really powerful thing is now the ability 2193 01:50:47,650 --> 01:50:51,520 to manipulate the DOM-- the ability to use JavaScript to take the page 2194 01:50:51,520 --> 01:50:54,460 and change the contents of the page by updating things, 2195 01:50:54,460 --> 01:50:56,225 by reading what happens to be on the page, 2196 01:50:56,225 --> 01:50:59,350 whether it's inside of a particular element or what a user happened to type 2197 01:50:59,350 --> 01:51:02,920 in, and using that in conjunction with event handlers-- 2198 01:51:02,920 --> 01:51:05,770 ways that we can listen for when the user clicks on something, 2199 01:51:05,770 --> 01:51:07,630 or when the user scrolls through something, 2200 01:51:07,630 --> 01:51:09,130 or when the user types a key-- 2201 01:51:09,130 --> 01:51:13,750 to be able to respond and therefore make our web pages all the more interactive. 2202 01:51:13,750 --> 01:51:16,330 Next time, we'll continue our discussion of JavaScript, 2203 01:51:16,330 --> 01:51:18,730 looking at how we can leverage the features of JavaScript 2204 01:51:18,730 --> 01:51:20,590 to continue to build even more interesting 2205 01:51:20,590 --> 01:51:24,500 and engaging user interfaces, so we'll see you next time. 2206 01:51:24,500 --> 01:51:25,000