WEBVTT X-TIMESTAMP-MAP=LOCAL:00:00:00.000,MPEGTS:900000 00:00:00.000 --> 00:00:02.994 [MUSIC PLAYING] 00:00:17.745 --> 00:00:20.120 BRIAN YU: OK, welcome back, everyone, to "Web Programming 00:00:20.120 --> 00:00:21.433 with Python and JavaScript." 00:00:21.433 --> 00:00:24.350 And today, we turn our attention to the second of the main programming 00:00:24.350 --> 00:00:28.010 languages that we'll be looking at in this class, in particular, JavaScript. 00:00:28.010 --> 00:00:31.470 And to get an understanding for why it is that JavaScript is actually helpful, 00:00:31.470 --> 00:00:35.060 let's go back and revisit this diagram of what communication over the internet 00:00:35.060 --> 00:00:36.380 will generally look like. 00:00:36.380 --> 00:00:39.170 Oftentimes, we'll have a user, otherwise known as the client, 00:00:39.170 --> 00:00:41.330 using their computer on their web browser, 00:00:41.330 --> 00:00:44.000 whether that's Chrome, or Safari, or some other web browser, 00:00:44.000 --> 00:00:46.190 that sends an HTTP request-- 00:00:46.190 --> 00:00:49.080 a web request-- to some sort of web server. 00:00:49.080 --> 00:00:53.210 That server then processes that request, and then returns some sort of response 00:00:53.210 --> 00:00:54.920 that comes back to the client. 00:00:54.920 --> 00:00:56.930 Thus far, all of the code that we've written-- 00:00:56.930 --> 00:01:00.450 the Python web application code running in a Django web application, 00:01:00.450 --> 00:01:01.350 for example-- 00:01:01.350 --> 00:01:04.190 has all been code that runs on some sort of server, 00:01:04.190 --> 00:01:07.400 code that is listening for requests, doing some computation in order 00:01:07.400 --> 00:01:10.940 to process that request, and then generating some sort of response, 00:01:10.940 --> 00:01:15.770 usually in the form of an HTML template that we then send back to the client. 00:01:15.770 --> 00:01:17.990 What JavaScript is going to enable us to do 00:01:17.990 --> 00:01:20.480 is to begin to write client-side code. 00:01:20.480 --> 00:01:22.640 JavaScript is going to allow us to write code 00:01:22.640 --> 00:01:26.760 that actually runs inside of the user's web browser on the client. 00:01:26.760 --> 00:01:28.800 And this can be useful for a number of reasons. 00:01:28.800 --> 00:01:30.770 One, if there's computation that we want to do, 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, 00:01:34.080 --> 00:01:36.380 we can do the computation potentially faster 00:01:36.380 --> 00:01:39.242 just by running the code exclusively on the client. 00:01:39.242 --> 00:01:41.450 And in addition to that, we can begin to make our web 00:01:41.450 --> 00:01:43.190 pages a whole lot more interactive. 00:01:43.190 --> 00:01:45.410 JavaScript is going to give us the ability 00:01:45.410 --> 00:01:49.880 to directly manipulate the DOM, where again, the DOM is the Document Object 00:01:49.880 --> 00:01:50.540 Model-- 00:01:50.540 --> 00:01:53.645 that tree-like hierarchy that represents the web page 00:01:53.645 --> 00:01:55.270 that the user happens to be looking at. 00:01:55.270 --> 00:01:58.730 So JavaScript will enable us to write code that directly manipulates 00:01:58.730 --> 00:02:00.800 the content on the web page and we'll see how 00:02:00.800 --> 00:02:03.210 that can be quite powerful very soon. 00:02:03.210 --> 00:02:06.020 So how do we then use JavaScript inside of a web page 00:02:06.020 --> 00:02:10.370 in order to add some code, add some programming logic to a web page? 00:02:10.370 --> 00:02:12.320 Well, so far, we've already seen HTML-- 00:02:12.320 --> 00:02:15.050 the language we use to describe the structure of a web page-- 00:02:15.050 --> 00:02:17.870 where an HTML page just describes the structure 00:02:17.870 --> 00:02:20.180 of a page in terms of nested tags. 00:02:20.180 --> 00:02:22.370 We had those head tags at the top of the page, 00:02:22.370 --> 00:02:24.920 the body tags that describe the structure of the page, 00:02:24.920 --> 00:02:27.710 and then additional tags that could be nested within those. 00:02:27.710 --> 00:02:30.170 And in order to add JavaScript to a web page, 00:02:30.170 --> 00:02:33.350 it's as simple as including some script tags that are often 00:02:33.350 --> 00:02:36.830 located inside of the HTML page itself. 00:02:36.830 --> 00:02:39.560 When we use these script tags, we're telling the browser 00:02:39.560 --> 00:02:41.990 that anything in between these script tags 00:02:41.990 --> 00:02:46.490 should be interpreted, in this case, as JavaScript code that the web browser is 00:02:46.490 --> 00:02:48.330 then going to execute. 00:02:48.330 --> 00:02:51.800 So our very first program, for example, might just look like a line of code 00:02:51.800 --> 00:02:56.100 inside of the script tags, something like this, where alert, for example, 00:02:56.100 --> 00:02:59.450 is the name of a function-- a function that's going to produce an alert-- 00:02:59.450 --> 00:03:02.630 and then just as with functions in Python, functions in JavaScript 00:03:02.630 --> 00:03:03.740 can take arguments. 00:03:03.740 --> 00:03:06.380 So in between these parentheses, we have an argument, 00:03:06.380 --> 00:03:08.390 something like the string "hello, world"-- 00:03:08.390 --> 00:03:11.640 the text that we would like to display to the user. 00:03:11.640 --> 00:03:13.550 So let's go ahead and give this a try and see 00:03:13.550 --> 00:03:15.740 how we can actually use this code to write 00:03:15.740 --> 00:03:20.040 JavaScript that is going to run inside of the user's web browser. 00:03:20.040 --> 00:03:24.500 I'll go ahead and create a new file that we'll call hello.html. 00:03:24.500 --> 00:03:30.110 And inside of it, I'll include the same basic HTML structure 00:03:30.110 --> 00:03:33.450 that we've already seen before, where I have a head section that has a title, 00:03:33.450 --> 00:03:37.560 and then a body that maybe just says hello, for example. 00:03:37.560 --> 00:03:41.150 And so now, what I'd like to do is add a little bit of JavaScript 00:03:41.150 --> 00:03:42.530 to this web page. 00:03:42.530 --> 00:03:44.740 So in the head section of my web page, I'm 00:03:44.740 --> 00:03:48.710 going to go ahead and add a script tag, where in between these scripts 00:03:48.710 --> 00:03:51.770 tags now, I can write JavaScript code-- code that 00:03:51.770 --> 00:03:55.040 is going to be written in JavaScript that will run inside of the web browser 00:03:55.040 --> 00:03:57.950 when the user actually opens up this page. 00:03:57.950 --> 00:04:02.690 And for now, I'll just say, alert, and then hello world. 00:04:02.690 --> 00:04:05.660 It turns out in JavaScript, you can use either single quotation marks 00:04:05.660 --> 00:04:08.600 or double quotation marks in order to represent strings. 00:04:08.600 --> 00:04:11.930 I'll generally use single quotation marks here just by convention. 00:04:11.930 --> 00:04:13.820 So here, I'm running a function called alert 00:04:13.820 --> 00:04:16.880 that's going to display an alert, something like hello world to the user. 00:04:16.880 --> 00:04:22.110 And that's going to be inside of the script tags of this HTML page. 00:04:22.110 --> 00:04:26.600 So now if I want to actually open the page up, I can open hello.html 00:04:26.600 --> 00:04:28.850 or you could just visit it inside of your web browser, 00:04:28.850 --> 00:04:30.590 whether it's Chrome or something else. 00:04:30.590 --> 00:04:32.900 And now at the top of the page, what you'll notice 00:04:32.900 --> 00:04:35.750 is that I get a little bit of an alert-- some interaction where 00:04:35.750 --> 00:04:39.050 it says this page says hello world, and it gives me an option to, like, 00:04:39.050 --> 00:04:42.770 press a button, for example, like the OK button that'll 00:04:42.770 --> 00:04:44.688 say, all right, dismiss the alert now. 00:04:44.688 --> 00:04:46.730 And this is our very first example of JavaScript. 00:04:46.730 --> 00:04:50.270 We have a function called alert built into JavaScript for our web browser, 00:04:50.270 --> 00:04:53.030 and our web browser knows that when we call the alert function, 00:04:53.030 --> 00:04:55.370 the browser should display an alert message that 00:04:55.370 --> 00:04:57.300 looks a little something like that. 00:04:57.300 --> 00:04:59.720 And if I click the OK button to dismiss the alert, 00:04:59.720 --> 00:05:02.450 then we go ahead and get back the original page 00:05:02.450 --> 00:05:04.620 that I had from the beginning. 00:05:04.620 --> 00:05:07.940 And so now, we can begin to imagine that using this ability 00:05:07.940 --> 00:05:11.960 to programmatically display alerts, that we can add additional features 00:05:11.960 --> 00:05:13.460 to our applications as well. 00:05:13.460 --> 00:05:16.370 And one big area where JavaScript can be quite powerful 00:05:16.370 --> 00:05:18.240 is with event-driven programming. 00:05:18.240 --> 00:05:20.370 And what event-driven programming is all about 00:05:20.370 --> 00:05:25.145 is thinking about things that happen on the web in terms of events that happen. 00:05:25.145 --> 00:05:26.520 What are some examples of events? 00:05:26.520 --> 00:05:29.340 Events are things like the user clicks on a button, 00:05:29.340 --> 00:05:31.740 or the user selects something from a dropdown list, 00:05:31.740 --> 00:05:34.260 or the user scrolls through a list, or submits a form. 00:05:34.260 --> 00:05:37.870 Anything the user does can generally be thought of as an event. 00:05:37.870 --> 00:05:42.270 And what we can do with JavaScript is add event listeners or event handlers-- 00:05:42.270 --> 00:05:45.210 things that say when an event happens, go ahead 00:05:45.210 --> 00:05:49.020 and run this particular block of code or this function, for example. 00:05:49.020 --> 00:05:51.420 And using that, we can begin to allow our JavaScript 00:05:51.420 --> 00:05:55.860 code to respond to how the user is actually interacting with our web page 00:05:55.860 --> 00:05:58.080 to say when the user clicks on a button, I 00:05:58.080 --> 00:06:02.170 would like to run this particular JavaScript function, for example. 00:06:02.170 --> 00:06:04.380 So let's go ahead and give that a try. 00:06:04.380 --> 00:06:08.550 I'll go ahead and now instead of just saying, alert hello world, 00:06:08.550 --> 00:06:11.080 let me put this alert inside of a function. 00:06:11.080 --> 00:06:13.290 And to create a function in JavaScript, you just 00:06:13.290 --> 00:06:16.610 use the keyword function followed by the name of the function. 00:06:16.610 --> 00:06:18.630 I'll call the function hello, for example. 00:06:18.630 --> 00:06:21.465 And then in parentheses, any inputs that function takes. 00:06:21.465 --> 00:06:23.590 This hello function is not going to take any input, 00:06:23.590 --> 00:06:26.400 so I'll just use an empty set of parentheses. 00:06:26.400 --> 00:06:30.300 And then inside of curly braces, I include any of the code 00:06:30.300 --> 00:06:33.270 that I want to run in this function. 00:06:33.270 --> 00:06:36.632 And so what I've done here now is create a function called hello, 00:06:36.632 --> 00:06:38.340 and then inside of the curly braces, I've 00:06:38.340 --> 00:06:40.710 defined the body of the function-- what code should 00:06:40.710 --> 00:06:43.170 run when I run the hello function. 00:06:43.170 --> 00:06:45.150 And what the hello function should do is it 00:06:45.150 --> 00:06:49.270 should display an alert that, in this case, says hello, world. 00:06:49.270 --> 00:06:51.960 So now, what I'd like to do is get this function 00:06:51.960 --> 00:06:55.980 to run when something happens on the page-- for example, 00:06:55.980 --> 00:06:57.915 when a user clicks on a button. 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. 00:07:01.320 --> 00:07:06.220 So I'll add a button that just says, like, click here, for example. 00:07:06.220 --> 00:07:11.160 So now if I refresh this page, I now see that I have hello 00:07:11.160 --> 00:07:13.260 and I also have this button that says click here, 00:07:13.260 --> 00:07:15.190 but when I click here, like, nothing happens. 00:07:15.190 --> 00:07:17.940 I'm clicking the Click Here button, but it's not changing anything 00:07:17.940 --> 00:07:20.430 because I haven't yet said what should happen when 00:07:20.430 --> 00:07:22.950 the user does click on this button. 00:07:22.950 --> 00:07:27.150 And so one way we could do this is by adding an attribute to this HTML 00:07:27.150 --> 00:07:30.450 element called onclick. 00:07:30.450 --> 00:07:33.480 What this is going to do is it's going to add an onclick 00:07:33.480 --> 00:07:34.620 handler to this button. 00:07:34.620 --> 00:07:38.250 It's going to say what should happen when the user clicks on this button. 00:07:38.250 --> 00:07:40.020 And I'm going to set the onclick attribute 00:07:40.020 --> 00:07:43.395 equal to running the function hello. 00:07:43.395 --> 00:07:45.270 And in order to run a function in JavaScript, 00:07:45.270 --> 00:07:47.160 just as you ran a function with Python, you 00:07:47.160 --> 00:07:50.370 use the name of the function followed by a set of parentheses 00:07:50.370 --> 00:07:52.740 to say, go ahead and actually run this function. 00:07:52.740 --> 00:07:54.920 Using those parentheses calls the function-- 00:07:54.920 --> 00:07:56.620 another word for running the function. 00:07:56.620 --> 00:07:59.120 And the fact that there's nothing in between the parentheses 00:07:59.120 --> 00:08:01.930 means we're not providing anything as input to the hello function, 00:08:01.930 --> 00:08:03.960 though if the hello function did take inputs, 00:08:03.960 --> 00:08:07.420 we could certainly add that in between the parentheses. 00:08:07.420 --> 00:08:10.800 So now, I've tied the two pieces of this page together. 00:08:10.800 --> 00:08:13.020 I have a button that says click here and I've 00:08:13.020 --> 00:08:16.860 added an onclick handler that says that when you click on the button, 00:08:16.860 --> 00:08:19.050 you should run the hello function. 00:08:19.050 --> 00:08:21.300 And then up above, I've defined the hello function 00:08:21.300 --> 00:08:23.050 to say what should the hello function do. 00:08:23.050 --> 00:08:24.967 Well, when the function is called, we're going 00:08:24.967 --> 00:08:28.840 to display an alert that in this case, says hello, world. 00:08:28.840 --> 00:08:32.309 So now, we should be able to refresh the page. 00:08:32.309 --> 00:08:34.309 We still see the same thing, at least initially, 00:08:34.309 --> 00:08:37.320 where it just says hello and a button that tells me to click here. 00:08:37.320 --> 00:08:39.750 But now if I go ahead and click the button that 00:08:39.750 --> 00:08:42.780 says click here, well, then I get the alert that says, 00:08:42.780 --> 00:08:44.760 this page says hello, world. 00:08:44.760 --> 00:08:45.562 I can press OK. 00:08:45.562 --> 00:08:47.520 And this event handler is always going to work. 00:08:47.520 --> 00:08:49.988 I click the button again, and I get the alert a second time 00:08:49.988 --> 00:08:51.780 because every time I click the button, it's 00:08:51.780 --> 00:08:53.610 going to call the hello function again. 00:08:53.610 --> 00:09:00.000 And when the hello function runs, it is going to display this particular alert. 00:09:00.000 --> 00:09:03.120 So this now appears to give us a fair amount of power. 00:09:03.120 --> 00:09:06.393 And much as in other programming languages, languages like Python 00:09:06.393 --> 00:09:08.310 or other languages you might have worked with, 00:09:08.310 --> 00:09:10.890 JavaScript has all these same types of language feature. 00:09:10.890 --> 00:09:13.835 So far, we've seen data types-- things like a string-- 00:09:13.835 --> 00:09:16.710 but we also have other data types that we'll take a look at soon too. 00:09:16.710 --> 00:09:19.740 We've seen functions-- some functions that are built into JavaScript, 00:09:19.740 --> 00:09:22.530 like the alert function, and other functions that we can write 00:09:22.530 --> 00:09:24.450 for ourselves, functions like hello-- 00:09:24.450 --> 00:09:27.690 but we also have the ability to include things like variables 00:09:27.690 --> 00:09:30.520 inside of our program as well. 00:09:30.520 --> 00:09:32.380 So what might that look like? 00:09:32.380 --> 00:09:36.605 Well, I'll go ahead and create a new file that we'll call counter.html. 00:09:36.605 --> 00:09:39.230 And counter is going to have some of the similar code to hello, 00:09:39.230 --> 00:09:41.070 so I'll just go ahead and copy it for now, 00:09:41.070 --> 00:09:45.480 but I'll clear out the script section, change the title from hello to counter. 00:09:45.480 --> 00:09:49.360 And now inside, I'll get rid of the button-- 00:09:49.360 --> 00:09:52.800 or actually, I'll keep the button, but instead of saying, click here, 00:09:52.800 --> 00:09:55.170 the button is going to say count. 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, 00:09:58.470 --> 00:10:01.450 3, 4, so on and so forth. 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, 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 00:10:10.590 --> 00:10:14.190 of my program, something that is keeping track of data, like the number 00:10:14.190 --> 00:10:16.140 that I currently have counted to. 00:10:16.140 --> 00:10:20.580 So in order to do that in JavaScript, I can say something like let counter 00:10:20.580 --> 00:10:22.500 equal 0. 00:10:22.500 --> 00:10:25.650 This is the way in JavaScript that I define a new variable. 00:10:25.650 --> 00:10:30.520 I first say let counter, meaning let there be a new variable called counter, 00:10:30.520 --> 00:10:35.310 and I'm going to initially set the value of counter equal to the number 0. 00:10:35.310 --> 00:10:38.790 And now when I click on the button, instead of running the hello function, 00:10:38.790 --> 00:10:43.110 I'm going to go ahead and run the count function, which doesn't exist yet, 00:10:43.110 --> 00:10:44.630 but I'll now write it. 00:10:44.630 --> 00:10:47.730 I'll define a function called count. 00:10:47.730 --> 00:10:52.650 And what the count function is going to do is it is going to first increment 00:10:52.650 --> 00:10:53.535 the value of counter. 00:10:53.535 --> 00:10:55.410 And there are number of ways I could do that. 00:10:55.410 --> 00:11:00.150 One is by saying counter = counter + 1 to say, go ahead and reset 00:11:00.150 --> 00:11:02.538 the value of counter to whatever counter is plus 1. 00:11:02.538 --> 00:11:04.830 And there are a couple of shorthand notations for this. 00:11:04.830 --> 00:11:10.020 I could equivalently say counter += 1 to say, add 1 to the counter, 00:11:10.020 --> 00:11:13.260 or in the case of adding 1, JavaScript, much like languages like C 00:11:13.260 --> 00:11:17.130 if you've seen them before, support notation like this-- counter++, 00:11:17.130 --> 00:11:20.880 which just means take the value of counter and increment it-- add 1 to it. 00:11:20.880 --> 00:11:23.700 So I'll add 1 to the value of counter, and then I'll 00:11:23.700 --> 00:11:29.340 just display an alert that has whatever the current value of counter 00:11:29.340 --> 00:11:31.210 happens to be. 00:11:31.210 --> 00:11:33.090 And so I've incremented the value of counter, 00:11:33.090 --> 00:11:37.890 and then displayed an alert that shows me what's contained inside of counter. 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 00:11:43.590 --> 00:11:47.820 instead, I now see that I still see a button that says count. 00:11:47.820 --> 00:11:51.510 And if I click on that button, I get an alert that this time, says 1. 00:11:51.510 --> 00:11:54.330 We've incremented the value of counter from 0 to 1. 00:11:54.330 --> 00:11:57.030 The alert now says 1 and I can press OK. 00:11:57.030 --> 00:11:59.915 If I press count again, the count now goes to 2. 00:11:59.915 --> 00:12:02.790 If I press OK, press count again, it goes to 3. 00:12:02.790 --> 00:12:04.620 And every time I click count, it is going 00:12:04.620 --> 00:12:09.150 to increment the value of the variable counter inside of my JavaScript web 00:12:09.150 --> 00:12:12.120 page, and then it's going to display an alert that is going 00:12:12.120 --> 00:12:14.740 to contain the value of that variable. 00:12:14.740 --> 00:12:18.510 So using alerts now, we're able to manipulate-- we can inside a function, 00:12:18.510 --> 00:12:21.300 manipulate the values of variables, and then display alerts that 00:12:21.300 --> 00:12:23.680 show the contents of those variables. 00:12:23.680 --> 00:12:26.460 But ultimately when users are interacting with the page, 00:12:26.460 --> 00:12:28.890 it's going to be fairly annoying if the only way that we 00:12:28.890 --> 00:12:31.455 have to interact with the user is via displaying 00:12:31.455 --> 00:12:34.080 these alerts-- the equivalent of, like, printing something out, 00:12:34.080 --> 00:12:36.270 except instead of printing it to a terminal, 00:12:36.270 --> 00:12:39.003 we're printing it via an alert that appears on the screen. 00:12:39.003 --> 00:12:41.670 What would be more interesting, and more powerful, and much more 00:12:41.670 --> 00:12:45.600 useful in the context of a web page is if we could programmatically 00:12:45.600 --> 00:12:48.420 update the website-- change something about the web page 00:12:48.420 --> 00:12:51.450 that the user is actually seeing, changing the content that 00:12:51.450 --> 00:12:52.850 happens to be on the page. 00:12:52.850 --> 00:12:54.930 And it turns out JavaScript is going to enable 00:12:54.930 --> 00:12:58.350 us to do that as well because JavaScript allows us to manipulate 00:12:58.350 --> 00:13:02.520 the DOM-- the Document Object Model that represents all of the elements that 00:13:02.520 --> 00:13:05.200 happen to be on that page. 00:13:05.200 --> 00:13:09.810 So to do that, let's go ahead and return to hello.html. 00:13:09.810 --> 00:13:13.980 This again, was this web page that just said hello and gave me a button, 00:13:13.980 --> 00:13:17.640 where if I clicked on that button, it would display an alert that said, 00:13:17.640 --> 00:13:18.900 hello, world. 00:13:18.900 --> 00:13:23.430 Now what I'd like to do is instead of having the hello function display 00:13:23.430 --> 00:13:27.655 an alert, I'd like to have it manipulate something on the page. 00:13:27.655 --> 00:13:29.280 And what might I want it to manipulate? 00:13:29.280 --> 00:13:32.340 Well, inside the body of the page, I here have this heading-- 00:13:32.340 --> 00:13:34.710 this heading that just says hello, for example, 00:13:34.710 --> 00:13:37.050 which is inside of an h1 element. 00:13:37.050 --> 00:13:40.920 And what I might like to do is actually change that element. 00:13:40.920 --> 00:13:42.340 How can I do that? 00:13:42.340 --> 00:13:44.160 Well, it turns out that in JavaScript, we 00:13:44.160 --> 00:13:49.470 have access to a function called document.querySelector. 00:13:49.470 --> 00:13:51.940 And what document.querySelector is going to do 00:13:51.940 --> 00:13:56.310 is it is going to give us the ability to look through an HTML page 00:13:56.310 --> 00:14:00.870 and extract an element out of that page so that we can manipulate that HTML 00:14:00.870 --> 00:14:03.850 element using JavaScript code. 00:14:03.850 --> 00:14:06.690 And so if I want to select like an h1 element, 00:14:06.690 --> 00:14:08.940 I can say document.querySelector. 00:14:08.940 --> 00:14:12.330 And then as the argument, the input to document.querySelector, 00:14:12.330 --> 00:14:16.080 I'll go ahead and say each one, meaning go through the page, 00:14:16.080 --> 00:14:18.180 find me an h1 element. 00:14:18.180 --> 00:14:20.430 And querySelector is only going to return one element, 00:14:20.430 --> 00:14:23.160 so if there are multiple, it's going to return the first thing it finds. 00:14:23.160 --> 00:14:25.440 But here, we only have one h1 element, so it's OK. 00:14:25.440 --> 00:14:30.308 I'm going to say look through this document, try and find an h1 element, 00:14:30.308 --> 00:14:32.100 and when you do, I'd like to manipulate it. 00:14:32.100 --> 00:14:39.630 And the way I'd like to manipulate it is by saying .innerHTML =, let's say, 00:14:39.630 --> 00:14:42.170 goodbye, for example. 00:14:42.170 --> 00:14:46.070 So all right, what's going on 6 Well, right now initially when we first load 00:14:46.070 --> 00:14:48.800 the page, we have an h1-- a big heading at the top-- 00:14:48.800 --> 00:14:50.360 that just says hello. 00:14:50.360 --> 00:14:52.250 And now when this hello function is called, 00:14:52.250 --> 00:14:55.250 which is called when this button is clicked on because it has an onclick 00:14:55.250 --> 00:14:59.150 attribute that is equal to hello, calling the hello function, 00:14:59.150 --> 00:15:01.100 what the hello function is going to do is 00:15:01.100 --> 00:15:04.130 it's going to say document.querySelector h1. 00:15:04.130 --> 00:15:08.900 Find me the h1 element that will return this element right here-- 00:15:08.900 --> 00:15:12.260 the JavaScript representation of this HTML element 00:15:12.260 --> 00:15:16.950 that is just an h1, whose HTML inside of it says hello. 00:15:16.950 --> 00:15:19.610 And if I want to change that HTML, I can do that 00:15:19.610 --> 00:15:24.980 by modifying the innerHTML property of the JavaScript element. 00:15:24.980 --> 00:15:27.800 In order to update a property of anything in JavaScript, 00:15:27.800 --> 00:15:31.010 well generally use this dot notation, where dot accesses 00:15:31.010 --> 00:15:33.750 a property of some particular object. 00:15:33.750 --> 00:15:35.810 And so I have this element, this h1. 00:15:35.810 --> 00:15:40.770 And saying .innerHTML means take that element and access its innerHTML 00:15:40.770 --> 00:15:43.280 property, some property of that object. 00:15:43.280 --> 00:15:46.380 And I would like to update its innerHTML to just in this case 00:15:46.380 --> 00:15:51.120 be the word goodbye followed by an exclamation point, for example. 00:15:51.120 --> 00:15:54.110 So now, what we'll see is that when we run 00:15:54.110 --> 00:15:58.910 this page, when we open this page up as by opening up hello.html, 00:15:58.910 --> 00:16:00.830 I still see an h1 that says hello. 00:16:00.830 --> 00:16:02.990 I still see a button that says click here. 00:16:02.990 --> 00:16:07.080 But now when I actually click on the button click here, 00:16:07.080 --> 00:16:09.320 you'll see that hello changes to goodbye. 00:16:09.320 --> 00:16:13.040 We've run JavaScript code that finds an h1 element on the page 00:16:13.040 --> 00:16:17.310 and manipulates it, changing it to something else than it was originally. 00:16:17.310 --> 00:16:19.520 Now every time I click here, nothing else 00:16:19.520 --> 00:16:23.570 happens because every time I click here, it's going to find the same h1 00:16:23.570 --> 00:16:28.220 and it's going to update its HTML, changing it from hello to goodbye. 00:16:28.220 --> 00:16:30.650 So maybe what I'd really like then is the ability 00:16:30.650 --> 00:16:33.950 to toggle back and forth-- to toggle back and forth between hello 00:16:33.950 --> 00:16:37.350 and goodbye, rather than just change it from one thing to something else. 00:16:37.350 --> 00:16:40.360 Every time I click the button, I'd like it to alternate back and forth. 00:16:40.360 --> 00:16:42.860 And there are a number of ways you could imagine doing this, 00:16:42.860 --> 00:16:45.570 but one way is by taking advantage of conditions. 00:16:45.570 --> 00:16:48.650 So much in the same way that a language like Python has conditions-- 00:16:48.650 --> 00:16:50.600 if's, and elif's, and else's-- 00:16:50.600 --> 00:16:54.110 JavaScript too has if, and else if, and else that 00:16:54.110 --> 00:16:57.890 allow us to describe conditions, such that we can only 00:16:57.890 --> 00:17:02.330 run certain blocks of code when a particular Boolean expression is true, 00:17:02.330 --> 00:17:03.690 for example. 00:17:03.690 --> 00:17:05.099 So what would that look like? 00:17:05.099 --> 00:17:08.720 Well, let's go ahead and say inside of this hello function, 00:17:08.720 --> 00:17:10.160 I can ask a question. 00:17:10.160 --> 00:17:21.050 If document.querySelector h1 innerHTML is equal to hello, 00:17:21.050 --> 00:17:28.220 we'll then go ahead and set it to goodbye and else then go 00:17:28.220 --> 00:17:31.730 ahead and update the innerHTML of this h1 element, 00:17:31.730 --> 00:17:35.648 go ahead and set it to hello instead. 00:17:35.648 --> 00:17:37.190 So what is this hello function doing? 00:17:37.190 --> 00:17:38.898 It's now a little bit more sophisticated. 00:17:38.898 --> 00:17:42.290 It now has a condition where I say if-- the keyword if-- 00:17:42.290 --> 00:17:45.530 followed by in parentheses, the condition that I want to check for, 00:17:45.530 --> 00:17:48.080 the thing I want to see is this true or not. 00:17:48.080 --> 00:17:52.940 And what I'm checking for is let me run document.querySelector h1-- 00:17:52.940 --> 00:17:56.600 which again, looks through the page, finds me the h1 tag, 00:17:56.600 --> 00:17:58.460 and gets that element for me-- 00:17:58.460 --> 00:18:02.330 if I look at that innerHTML, if it is equal to hello, 00:18:02.330 --> 00:18:03.720 then I want to do something. 00:18:03.720 --> 00:18:06.380 And this triple equal sign here is JavaScript's way 00:18:06.380 --> 00:18:08.390 of checking for strict equality, checking 00:18:08.390 --> 00:18:11.030 to make sure the two values are equal and also 00:18:11.030 --> 00:18:12.740 that their types are the same thing-- 00:18:12.740 --> 00:18:15.482 that if this is a string, this must also be a string. 00:18:15.482 --> 00:18:17.690 It turns out in JavaScript, there's also a weaker way 00:18:17.690 --> 00:18:21.010 to check for equality that just uses two equal signs. 00:18:21.010 --> 00:18:24.140 And that is going to check that values are the same, 00:18:24.140 --> 00:18:27.460 but it's going to allow for a bit of differences in type. 00:18:27.460 --> 00:18:29.210 The two things might have different types, 00:18:29.210 --> 00:18:31.340 but so long as they're basically the same value, 00:18:31.340 --> 00:18:34.380 the double equal sign might generally come to be true. 00:18:34.380 --> 00:18:37.370 Usually if you can, you'll want to use this triple equal sign-- 00:18:37.370 --> 00:18:40.490 the strict equality-- to make sure that not only are the types the same, 00:18:40.490 --> 00:18:42.080 but the values are the same too. 00:18:42.080 --> 00:18:44.880 And the triple equal sign will check both of those things. 00:18:44.880 --> 00:18:48.770 So if I go ahead and find the h1 element and its innerHTML 00:18:48.770 --> 00:18:52.850 is the word hello, we'll then go ahead and find the h1 element 00:18:52.850 --> 00:18:57.890 and update its innerHTML, setting it equal to goodbye, for example. 00:18:57.890 --> 00:19:02.810 And else go ahead and find that same h1 element, update its innerHTML, 00:19:02.810 --> 00:19:04.490 set it equal to hello. 00:19:04.490 --> 00:19:08.210 And again, just as in functions, where we use these curly braces to enclose 00:19:08.210 --> 00:19:10.940 the body of the function-- all of lines of code that are inside 00:19:10.940 --> 00:19:11.810 of the function-- 00:19:11.810 --> 00:19:13.410 JavaScript does the same thing too-- 00:19:13.410 --> 00:19:16.910 that inside of a condition when we want to express that this is inside 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 00:19:21.020 --> 00:19:24.740 and that line of code, that's inside of the if expression or that's inside 00:19:24.740 --> 00:19:27.492 of the else expression, for example. 00:19:27.492 --> 00:19:28.950 So let's go ahead and try this now. 00:19:28.950 --> 00:19:31.970 I can go ahead and open hello.html. 00:19:31.970 --> 00:19:32.470 Refresh it. 00:19:32.470 --> 00:19:35.900 It currently says hello with a button that says click here. 00:19:35.900 --> 00:19:40.730 And now when I click here, hello changes to goodbye. 00:19:40.730 --> 00:19:43.720 And when I click here again, goodbye changes back to hello. 00:19:43.720 --> 00:19:46.900 And every time I click the button, it's going to alternate between hello 00:19:46.900 --> 00:19:50.050 and goodbye because we either get caught in the if expression 00:19:50.050 --> 00:19:52.817 or we get caught in the else expression. 00:19:52.817 --> 00:19:55.400 Now, there are a couple of places where you might look at this 00:19:55.400 --> 00:19:58.420 and notice that maybe this isn't as efficient as this code could 00:19:58.420 --> 00:19:59.530 potentially be. 00:19:59.530 --> 00:20:03.380 And recall that every time we run document.querySelector to say, 00:20:03.380 --> 00:20:07.270 go ahead and try and find a particular HTML element for me, 00:20:07.270 --> 00:20:10.480 it's going to look through that page trying to find the h1 element. 00:20:10.480 --> 00:20:14.220 And it turns out that right now, we have three separate calls to querySelector, 00:20:14.220 --> 00:20:15.970 even though only two of them will ever run 00:20:15.970 --> 00:20:17.740 on any given instance of the function. 00:20:17.740 --> 00:20:20.290 But we call document.querySelector, then we call it 00:20:20.290 --> 00:20:22.600 again inside of the if expression. 00:20:22.600 --> 00:20:26.620 We can probably improve the design of this page by factoring that out, 00:20:26.620 --> 00:20:30.790 by just looking for the h1 element once, and then manipulating it and checking 00:20:30.790 --> 00:20:33.660 it using that element that we have found. 00:20:33.660 --> 00:20:36.790 And to do that, we can store an element inside of a variable. 00:20:36.790 --> 00:20:39.490 In the same way that a variable can store a number, 00:20:39.490 --> 00:20:41.860 like a counter, or a string, like hello world, 00:20:41.860 --> 00:20:44.830 it can also store other values like an HTML element 00:20:44.830 --> 00:20:48.370 that we get back from document.querySelector. 00:20:48.370 --> 00:20:53.080 So I could say something like let heading, 00:20:53.080 --> 00:20:55.120 where heading is just the name of a variable, 00:20:55.120 --> 00:21:00.050 be equal to document.querySelector h1, for instance. 00:21:00.050 --> 00:21:01.240 Find the h1 element. 00:21:01.240 --> 00:21:03.760 Save it inside of a variable called heading. 00:21:03.760 --> 00:21:06.370 And now rather than document.querySelector h1 00:21:06.370 --> 00:21:11.650 all the time, I can just say if the heading's innerHTML is hello, then set 00:21:11.650 --> 00:21:13.990 the heading's innerHTML to goodbye. 00:21:13.990 --> 00:21:17.053 Otherwise, set the heading's innerHTML to hello. 00:21:17.053 --> 00:21:18.970 So I've improve the efficiency of the program, 00:21:18.970 --> 00:21:21.192 but also reduced the number of characters of code 00:21:21.192 --> 00:21:22.150 that I've had to write. 00:21:22.150 --> 00:21:24.700 My lines are now much shorter, a little bit easier to read. 00:21:24.700 --> 00:21:27.853 This we would consider to be an improvement in design. 00:21:27.853 --> 00:21:29.770 And it turns out there's one other improvement 00:21:29.770 --> 00:21:34.120 we can make here too that we can define a variable like let something 00:21:34.120 --> 00:21:36.970 equal something else, but it turns out that JavaScript gives us 00:21:36.970 --> 00:21:39.620 a couple of ways to define a variable. 00:21:39.620 --> 00:21:43.210 And if we're going to be creating a variable whose value is never 00:21:43.210 --> 00:21:46.990 going to change, we're never going to reassign the variable name to something 00:21:46.990 --> 00:21:50.320 else, then instead of let, we can enforce 00:21:50.320 --> 00:21:54.280 that it's never going to change by calling it a const variable. 00:21:54.280 --> 00:21:58.170 So const heading = document.querySelector h1 00:21:58.170 --> 00:22:01.030 means I am going to create a variable called heading, setting 00:22:01.030 --> 00:22:05.050 it equal to the result of document.querySelector h1 and never 00:22:05.050 --> 00:22:07.788 again will I change what heading is equal to. 00:22:07.788 --> 00:22:09.580 I will never have another line of code that 00:22:09.580 --> 00:22:13.150 says heading equals something else because it is constant. 00:22:13.150 --> 00:22:16.430 And JavaScript will then enforce that this variable should not change. 00:22:16.430 --> 00:22:19.520 And if ever I do try to change it, JavaScript will give me an error. 00:22:19.520 --> 00:22:23.500 And this can just be helpful to prevent against possible unintended behavior-- 00:22:23.500 --> 00:22:26.590 that if you know you have a variable that is never going to change, 00:22:26.590 --> 00:22:29.890 it's often good design to label it as a const variable 00:22:29.890 --> 00:22:32.020 so that you and other people looking at your code 00:22:32.020 --> 00:22:36.820 know that that is never going to have a value that gets changed later on. 00:22:36.820 --> 00:22:40.330 So this then will behave the same way where it says hello, 00:22:40.330 --> 00:22:44.020 but I can toggle it back and forth, changing it to goodbye, 00:22:44.020 --> 00:22:46.910 and then changing it back to hello again. 00:22:46.910 --> 00:22:50.480 And so now using this ability-- this ability to manipulate the DOM-- 00:22:50.480 --> 00:22:53.920 we can go back to our counter program and actually improve upon it. 00:22:53.920 --> 00:22:59.110 Right now the counter program, I count and it displays an alert that says one. 00:22:59.110 --> 00:23:01.630 I count and it displays an alert that says two. 00:23:01.630 --> 00:23:03.950 I can probably do a little bit better than that 00:23:03.950 --> 00:23:06.370 by instead of displaying an alert, actually 00:23:06.370 --> 00:23:09.130 manipulating the DOM in some way-- 00:23:09.130 --> 00:23:10.930 that I would like to have this h1-- 00:23:10.930 --> 00:23:12.400 this big heading at the top-- 00:23:12.400 --> 00:23:17.350 instead of starting up by saying hello, let's have it start out by saying zero, 00:23:17.350 --> 00:23:20.800 for example-- just some initial value for the counter. 00:23:20.800 --> 00:23:22.990 And now when I increment the value of counter, 00:23:22.990 --> 00:23:26.140 rather than display an alert that just tells me the value of the counter 00:23:26.140 --> 00:23:36.670 in an alert, I'm going to instead say document.querySelector h1 .innerHTML = 00:23:36.670 --> 00:23:41.940 counter, where I'm saying find the h1 element, update its innerHTML, 00:23:41.940 --> 00:23:46.360 set it equal to whatever the value of the variable counter happens to be, 00:23:46.360 --> 00:23:50.350 such that now if I refresh this page, the value of this h1 initially is zero. 00:23:50.350 --> 00:23:51.582 That's the initial value. 00:23:51.582 --> 00:23:53.290 But every time I click count, we're going 00:23:53.290 --> 00:23:55.940 to update the contents of that h1 element. 00:23:55.940 --> 00:23:59.320 And this time, setting it to 1, 2, 3, 4, and so forth. 00:23:59.320 --> 00:24:01.090 Every time I click the count button, it's 00:24:01.090 --> 00:24:03.100 going to increment the value of the variable, 00:24:03.100 --> 00:24:06.760 as well as manipulate the DOM, actually making changes 00:24:06.760 --> 00:24:12.280 in order to produce the effect that I want to see on this actual page. 00:24:12.280 --> 00:24:15.190 And we can begin to add additional logic to this as well. 00:24:15.190 --> 00:24:17.470 Maybe I do occasionally want an alert, but I 00:24:17.470 --> 00:24:19.330 don't want an alert every single time. 00:24:19.330 --> 00:24:20.350 I could add a condition. 00:24:20.350 --> 00:24:23.620 I could say something like if I only want to display an alert every time I 00:24:23.620 --> 00:24:26.740 count to a multiple of 10-- like 10, and 20, and 30, and 40, and 50, 00:24:26.740 --> 00:24:27.890 and so forth-- 00:24:27.890 --> 00:24:32.350 I could add a condition that says that if counter mod 10-- 00:24:32.350 --> 00:24:35.227 and mod just gets the remainder when you divide by 10-- 00:24:35.227 --> 00:24:37.060 so if you take the counter, divide it by 10, 00:24:37.060 --> 00:24:40.430 if the remainder is 0 when I divide by 10, 00:24:40.430 --> 00:24:42.660 well, that means counter is a multiple of 10, 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, 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. 00:24:52.138 --> 00:24:54.180 And in order to do that, what I really want to do 00:24:54.180 --> 00:24:57.660 is have some way of plugging in a variable 00:24:57.660 --> 00:25:00.753 into a string inside of JavaScript. 00:25:00.753 --> 00:25:02.670 And in Python, the way we would have done this 00:25:02.670 --> 00:25:07.870 is by prepending f in front of the string to create a formatted string. 00:25:07.870 --> 00:25:11.040 And then I would have said something like the count is now, 00:25:11.040 --> 00:25:13.770 and then I'd use curly braces to say go ahead 00:25:13.770 --> 00:25:15.600 and print out the value of counter. 00:25:15.600 --> 00:25:17.850 So this f for formatted string followed by this string 00:25:17.850 --> 00:25:20.475 would have been the way in Python that we would have done this. 00:25:20.475 --> 00:25:22.740 It turns out JavaScript does the same thing, just 00:25:22.740 --> 00:25:24.120 with slightly different syntax. 00:25:24.120 --> 00:25:25.690 It doesn't use f. 00:25:25.690 --> 00:25:30.300 Instead of using the regular quotation marks or the single or double quotation 00:25:30.300 --> 00:25:35.650 marks, JavaScript uses these backticks, which are usually located above the Tab 00:25:35.650 --> 00:25:38.468 key on a standard US keyboard. 00:25:38.468 --> 00:25:40.260 And this is going to create what JavaScript 00:25:40.260 --> 00:25:42.510 calls a template literal, where I can then 00:25:42.510 --> 00:25:47.130 substitute the value of a variable somewhere inside of this template. 00:25:47.130 --> 00:25:49.530 And then in order to actually do the substitution, 00:25:49.530 --> 00:25:53.100 while Python uses double curly braces to say plug-in the value of counter 00:25:53.100 --> 00:25:55.450 right here, JavaScript does something similar. 00:25:55.450 --> 00:25:57.540 It also uses double curly braces, but there 00:25:57.540 --> 00:25:59.280 needs to be dollar sign in front of it. 00:25:59.280 --> 00:26:02.070 The dollar sign, and then the double curly braces 00:26:02.070 --> 00:26:06.220 mean go ahead and plug-in the value of a variable there. 00:26:06.220 --> 00:26:09.330 So this then is a template literal, where every time we 00:26:09.330 --> 00:26:12.300 get to a multiple of 10, we're going to display an alert that says, 00:26:12.300 --> 00:26:15.720 the count is now, and then this dollar sign curly brace 00:26:15.720 --> 00:26:19.230 means actually plug-in whatever the value of counter 00:26:19.230 --> 00:26:22.240 happens to be right there. 00:26:22.240 --> 00:26:25.410 So now if I go ahead and refresh counter, it starts at 0. 00:26:25.410 --> 00:26:28.860 I can count 3, 4, 5, 6, 7, 8, 9, but when I get to 10, 00:26:28.860 --> 00:26:32.100 then I get an alert that says the count is now 10, and then I 00:26:32.100 --> 00:26:35.420 see the result update on the page. 00:26:35.420 --> 00:26:39.390 And so that template literal can allow us to combine variables and strings 00:26:39.390 --> 00:26:43.530 in order to generate new strings that are able to represent data inside 00:26:43.530 --> 00:26:45.753 of them as well. 00:26:45.753 --> 00:26:47.920 So now, what improvements can we begin to make here? 00:26:47.920 --> 00:26:50.880 What changes can we make to this to improve upon the design of it? 00:26:50.880 --> 00:26:52.860 Well, one thing, especially as our programs 00:26:52.860 --> 00:26:55.860 get a little bit more sophisticated, a little bit more complicated 00:26:55.860 --> 00:26:59.760 is that we often don't want to be intermingling our JavaScript 00:26:59.760 --> 00:27:02.340 code with the contents of our HTML. 00:27:02.340 --> 00:27:05.250 Down here, we have button onclick="count," 00:27:05.250 --> 00:27:06.600 this name of this function. 00:27:06.600 --> 00:27:09.450 And especially as our page starts to get more complicated, 00:27:09.450 --> 00:27:12.660 it's going to start to get a little bit annoying if we're constantly 00:27:12.660 --> 00:27:14.940 having to maintain a little bit of JavaScript code, 00:27:14.940 --> 00:27:17.408 like making a call to a function, inside of our HTML. 00:27:17.408 --> 00:27:20.700 We'll see a little bit later, there are other paradigms that actually encourage 00:27:20.700 --> 00:27:24.180 this type of thing, but right now, it can start to get a little poorly 00:27:24.180 --> 00:27:27.570 designed, as we'd really like to separate all of our JavaScript-related 00:27:27.570 --> 00:27:29.530 code from all of the HTML-- 00:27:29.530 --> 00:27:31.790 the general structure of our page. 00:27:31.790 --> 00:27:34.780 And so there are ways we can begin to do that as well. 00:27:34.780 --> 00:27:39.840 I can add an event listener inside of JavaScript too that I can say something 00:27:39.840 --> 00:27:53.020 like document.querySelector button, and then I can say .onclick = count. 00:27:53.020 --> 00:27:54.160 So what's going on here? 00:27:54.160 --> 00:27:57.280 And I can do this instead of this onclick="count." 00:27:57.280 --> 00:28:00.700 What I'm now saying is document.querySelector button, 00:28:00.700 --> 00:28:02.083 find me the button on the page. 00:28:02.083 --> 00:28:04.000 And it turns out there's only one button here, 00:28:04.000 --> 00:28:05.560 so it's fine, though if there were more, I might 00:28:05.560 --> 00:28:07.390 have to be a little bit more specific. 00:28:07.390 --> 00:28:12.400 But once I get that button, then I'm going to access its onclick property 00:28:12.400 --> 00:28:15.160 and I'm going to set it equal to count. 00:28:15.160 --> 00:28:16.570 And what is count? 00:28:16.570 --> 00:28:18.280 Count is the name of a function. 00:28:18.280 --> 00:28:20.270 Count is itself a function. 00:28:20.270 --> 00:28:22.360 And so what I'm here saying is I would like 00:28:22.360 --> 00:28:25.648 to set the value of the onclick property of the button 00:28:25.648 --> 00:28:27.940 equal to count-- that count is the function that should 00:28:27.940 --> 00:28:31.610 run when the button is clicked on. 00:28:31.610 --> 00:28:34.330 And notice that I am not actually calling the function. 00:28:34.330 --> 00:28:36.340 It's not count, and then parentheses, which 00:28:36.340 --> 00:28:39.670 would mean run the count function, and then get its return value 00:28:39.670 --> 00:28:42.010 and use that as the value for onclick. 00:28:42.010 --> 00:28:46.150 I'm just setting onclick equal literally to the count function itself 00:28:46.150 --> 00:28:48.110 without actually calling the function. 00:28:48.110 --> 00:28:50.050 And what this is going to do is it is going 00:28:50.050 --> 00:28:52.330 to say when the button is clicked on, then 00:28:52.330 --> 00:28:55.720 and only then should you actually run this count function. 00:28:55.720 --> 00:28:59.890 And we're not going to run the count function until that button actually 00:28:59.890 --> 00:29:00.940 gets clicked on. 00:29:00.940 --> 00:29:05.170 And so in JavaScript, functions can be treated as values of their own. 00:29:05.170 --> 00:29:08.050 Just as you can set a variable equal to a string, 00:29:08.050 --> 00:29:10.240 just as you can set a variable equal to an integer, 00:29:10.240 --> 00:29:13.000 just as you can set a variable equal to, like, an HTML element, 00:29:13.000 --> 00:29:15.340 like the result of document.querySelector, 00:29:15.340 --> 00:29:20.020 you can also set a variable equal to a function-- something like count-- 00:29:20.020 --> 00:29:24.230 and pass that around as a value, just as you could with any other value. 00:29:24.230 --> 00:29:27.280 And this is a paradigm we generally call functional programming, where 00:29:27.280 --> 00:29:31.300 we have functions as values of their own-- things that we can reassign, 00:29:31.300 --> 00:29:35.600 things that we can manipulate just as we could any other value. 00:29:35.600 --> 00:29:39.583 So now, I can try and run this program by going ahead and refreshing the page. 00:29:39.583 --> 00:29:40.250 I'll refresh it. 00:29:40.250 --> 00:29:41.080 It's 0. 00:29:41.080 --> 00:29:42.690 I press count. 00:29:42.690 --> 00:29:44.930 And all right, nothing seems to be happening. 00:29:44.930 --> 00:29:45.520 It's still 0. 00:29:45.520 --> 00:29:49.000 I want it to be counting, but it doesn't seem to be working. 00:29:49.000 --> 00:29:49.960 So why not? 00:29:49.960 --> 00:29:51.777 Anytime you run into problems in JavaScript 00:29:51.777 --> 00:29:54.110 where you're not getting the behavior you want, often it 00:29:54.110 --> 00:29:56.560 can be helpful to look at the JavaScript console, 00:29:56.560 --> 00:29:59.620 where the JavaScript console is the equivalent of, like, the terminal 00:29:59.620 --> 00:30:02.440 window when you were running your Django application in Python 00:30:02.440 --> 00:30:04.270 that would display any error messages. 00:30:04.270 --> 00:30:07.480 The JavaScript console will display any of the JavaScript logging 00:30:07.480 --> 00:30:10.390 information and error messages as well. 00:30:10.390 --> 00:30:12.670 In Chrome, I can get to it if I first go ahead 00:30:12.670 --> 00:30:17.578 and go to inspect, and then just open up the Console tab here. 00:30:17.578 --> 00:30:19.870 And all right, we seem to have some sort of error here. 00:30:19.870 --> 00:30:26.650 It's an Uncaught TypeError that says we cannot set property onclick of null 00:30:26.650 --> 00:30:29.095 in counter.html line 18. 00:30:29.095 --> 00:30:31.720 So that will generally tell you where the error is coming from. 00:30:31.720 --> 00:30:34.660 It's coming from counter.html on line 18. 00:30:34.660 --> 00:30:36.700 And the problem seems to be that I'm trying 00:30:36.700 --> 00:30:40.060 to access the onclick property of null. 00:30:40.060 --> 00:30:42.160 And null is JavaScript's way of expressing, like, 00:30:42.160 --> 00:30:45.670 nothing-- some object that doesn't exist. 00:30:45.670 --> 00:30:48.400 So somehow, I'm trying to set the onclick property of null. 00:30:48.400 --> 00:30:51.070 Well, let's see what's going on line 18, and see if we 00:30:51.070 --> 00:30:54.050 can figure out what's happening there. 00:30:54.050 --> 00:30:57.880 Well, all right, here's line 18, where I say document.querySelector button, 00:30:57.880 --> 00:31:01.150 setting it's onclick property equal to count. 00:31:01.150 --> 00:31:03.260 And now, what seems to be the problem here? 00:31:03.260 --> 00:31:05.440 Well, the error message was that I was trying 00:31:05.440 --> 00:31:08.530 to modify the onclick property of null. 00:31:08.530 --> 00:31:11.170 Well, here then is the onclick property, so why 00:31:11.170 --> 00:31:14.950 would this document.querySelector button be returning or giving me 00:31:14.950 --> 00:31:16.960 an output of null? 00:31:16.960 --> 00:31:20.020 Well, it turns out that document.querySelector will return null 00:31:20.020 --> 00:31:23.540 if it's not able to find something-- if I try and find a button, 00:31:23.540 --> 00:31:25.420 but it's not able to find a button. 00:31:25.420 --> 00:31:27.628 Well, this seems a little bit strange because there's 00:31:27.628 --> 00:31:31.360 a button down here on line 24 that I'd like for my JavaScript code 00:31:31.360 --> 00:31:34.120 to be able to find when it runs querySelector and tries 00:31:34.120 --> 00:31:35.338 to find the button. 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 00:31:38.380 --> 00:31:41.560 to work, but if the browser is running our code from top to bottom, 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, 00:31:46.060 --> 00:31:49.870 where I've said document.querySelector button .onclick = count, 00:31:49.870 --> 00:31:52.630 and it's going to try and find a button on line 18, 00:31:52.630 --> 00:31:57.200 but the button doesn't show up in my HTML page until much further down 00:31:57.200 --> 00:31:57.850 in the page. 00:31:57.850 --> 00:32:00.700 So at this point, when we get to this line of JavaScript, 00:32:00.700 --> 00:32:03.310 JavaScript is looking for the button, but the DOM-- 00:32:03.310 --> 00:32:04.663 the body of the page-- 00:32:04.663 --> 00:32:05.830 hasn't finished loading yet. 00:32:05.830 --> 00:32:08.440 The content of the DOM has not yet loaded. 00:32:08.440 --> 00:32:11.857 And as a result, we're not able to find this button. 00:32:11.857 --> 00:32:13.190 So how do we solve this problem? 00:32:13.190 --> 00:32:16.180 How do we get it so we actually are able to, like, ask for the button 00:32:16.180 --> 00:32:17.462 and actually get the button? 00:32:17.462 --> 00:32:20.170 Well, it turns out there are a couple of strategies we could use. 00:32:20.170 --> 00:32:23.230 One would be take the script tag and go ahead and just move it 00:32:23.230 --> 00:32:26.440 to the bottom section of the body, so that after we've already 00:32:26.440 --> 00:32:29.800 defined the button that says count, then we have the script tag that then says, 00:32:29.800 --> 00:32:31.633 all right, go ahead and now find the button, 00:32:31.633 --> 00:32:33.110 and now we'll be able to find it. 00:32:33.110 --> 00:32:36.250 It turns out another way, and perhaps the more common way, 00:32:36.250 --> 00:32:39.822 is to instead add yet another event listener. 00:32:39.822 --> 00:32:42.280 And we're going to add an event listener not to the button, 00:32:42.280 --> 00:32:45.760 but to the entire document, where document is a variable built 00:32:45.760 --> 00:32:48.490 into this JavaScript that we have access to on the web page 00:32:48.490 --> 00:32:51.630 that just refers to this entire web document, where I've 00:32:51.630 --> 00:32:55.600 document.querySelector already to look through the whole web document trying 00:32:55.600 --> 00:32:59.050 to find a button or trying to find an h1 tag, for example. 00:32:59.050 --> 00:33:03.460 But I can also add an event listener to the document itself. 00:33:03.460 --> 00:33:09.340 And in order to do that, I can say document.addEventListener. 00:33:09.340 --> 00:33:12.873 And when I call addEventListener-- and I can do this on any HTML element, 00:33:12.873 --> 00:33:15.040 not just the document, but I could run this function 00:33:15.040 --> 00:33:18.610 on a button, or on an h1 element, or any other HTML element. 00:33:18.610 --> 00:33:22.930 addEventListener will generally take two arguments, where the first is 00:33:22.930 --> 00:33:24.843 what event I want to listen for. 00:33:24.843 --> 00:33:27.760 The event could be something like click, when I click on the document. 00:33:27.760 --> 00:33:31.620 It could be something like when I scroll through a page, for example. 00:33:31.620 --> 00:33:34.120 But with the event I'm going to listen for is a particularly 00:33:34.120 --> 00:33:38.380 special event called DOMContentLoaded. 00:33:38.380 --> 00:33:40.990 And the DOMContentLoaded event is an event 00:33:40.990 --> 00:33:44.350 that is going to be fired or triggered when the DOM-- 00:33:44.350 --> 00:33:46.780 the Document Object Model, the structure of the page-- 00:33:46.780 --> 00:33:47.560 is done loading. 00:33:47.560 --> 00:33:49.900 When all of the elements on the page are done loading, 00:33:49.900 --> 00:33:52.540 the DOM content has been loaded, and then 00:33:52.540 --> 00:33:54.610 if I attach an event listener to it, it'll 00:33:54.610 --> 00:33:57.220 run whatever code I want to run that should only 00:33:57.220 --> 00:34:01.660 run after the DOM is fully loaded, after all of the content on the page 00:34:01.660 --> 00:34:03.490 has then been loaded. 00:34:03.490 --> 00:34:06.370 And the second argument to addEventListener 00:34:06.370 --> 00:34:10.270 is what function should run once the event actually happens, 00:34:10.270 --> 00:34:12.400 when the DOMContentLoaded does happen. 00:34:12.400 --> 00:34:14.590 So I could pass in the name of a function 00:34:14.590 --> 00:34:17.679 if I had the name of a function that I wanted to pass in, 00:34:17.679 --> 00:34:22.510 but alternatively, JavaScript allows me to just directly write a function here 00:34:22.510 --> 00:34:24.760 in the argument to addEventListener. 00:34:24.760 --> 00:34:28.360 I can just say function, and then a set of parentheses to mean the function 00:34:28.360 --> 00:34:31.659 doesn't take any input, and then in curly braces, 00:34:31.659 --> 00:34:37.000 I can include the body of the function right here as the second argument 00:34:37.000 --> 00:34:38.082 to addEventListener. 00:34:38.082 --> 00:34:39.790 And this is a little bit of tricky syntax 00:34:39.790 --> 00:34:41.830 to wrap your mind around if you've never seen it before, 00:34:41.830 --> 00:34:43.630 but the big picture way to think of it is 00:34:43.630 --> 00:34:47.110 addEventListener takes two arguments-- one is the event, 00:34:47.110 --> 00:34:48.679 the second is the function. 00:34:48.679 --> 00:34:51.219 So here first is the event DOMContentLoaded. 00:34:51.219 --> 00:34:53.770 And the second argument is a function. 00:34:53.770 --> 00:34:56.710 And I would declare the function same as before, just using function. 00:34:56.710 --> 00:34:59.890 I haven't given the function a name because strictly speaking, 00:34:59.890 --> 00:35:01.090 it doesn't need a name. 00:35:01.090 --> 00:35:03.310 I'm never going to refer to this function by name. 00:35:03.310 --> 00:35:07.840 So it is what we might call an anonymous function-- a function that has no name, 00:35:07.840 --> 00:35:10.630 but I'm still passing it into the addEventListener function 00:35:10.630 --> 00:35:14.920 as an argument because I want to run the code inside of the function 00:35:14.920 --> 00:35:16.940 once the DOM has done loading. 00:35:16.940 --> 00:35:20.170 And so inside of curly braces then is the content of that function-- 00:35:20.170 --> 00:35:23.860 the content of what code should run when the DOM is done loading. 00:35:23.860 --> 00:35:26.800 And then at the end, I again use just this end parenthesis, 00:35:26.800 --> 00:35:30.070 where that end parenthesis lines up with this parenthesis here. 00:35:30.070 --> 00:35:34.240 This is enclosing all of the arguments to addEventListener, 00:35:34.240 --> 00:35:37.300 where the first one is DOMContentLoaded and the second one 00:35:37.300 --> 00:35:40.480 is this entire function that might span multiple lines. 00:35:40.480 --> 00:35:44.560 So you'll see syntax like this quite a bit in JavaScript. 00:35:44.560 --> 00:35:48.460 But now, what I want to do is adding the event listener to the button. 00:35:48.460 --> 00:35:51.590 I can go ahead and just replace and put it here. 00:35:51.590 --> 00:35:55.330 And it turns out that if I wanted to instead of saying .onclick = count, 00:35:55.330 --> 00:35:57.760 you could have used the same syntax of addEventListener. 00:35:57.760 --> 00:36:01.690 I could say addEventListener click, and then 00:36:01.690 --> 00:36:04.870 count to mean when the click event happens, 00:36:04.870 --> 00:36:06.680 go ahead and run the count function. 00:36:06.680 --> 00:36:11.140 But you can equivalently shorthand this and just say .onclick = count, 00:36:11.140 --> 00:36:13.150 and that would work just as well. 00:36:13.150 --> 00:36:16.780 So now, what we're saying here is that wait until the DOM has done loaded, 00:36:16.780 --> 00:36:20.140 wait until all the content on the page is loaded, and then go ahead 00:36:20.140 --> 00:36:21.577 and run this function. 00:36:21.577 --> 00:36:23.410 And what the function is going to do is it's 00:36:23.410 --> 00:36:26.220 going to add the event handler to this button. 00:36:26.220 --> 00:36:29.770 And that will work because now, we'll be able to find the button because now, 00:36:29.770 --> 00:36:32.740 all of the content of the DOM has loaded. 00:36:32.740 --> 00:36:36.100 So now, if I go back, refresh counter.html, 00:36:36.100 --> 00:36:38.290 you'll notice that the JavaScript error goes away. 00:36:38.290 --> 00:36:40.750 I don't seem to have that error anymore. 00:36:40.750 --> 00:36:43.540 And now if I press count, we're able to see the count 00:36:43.540 --> 00:36:46.700 increment just as before as well. 00:36:46.700 --> 00:36:48.940 And so this then is an improvement upon what 00:36:48.940 --> 00:36:53.080 I've had before, where now I'm able to separate out my JavaScript 00:36:53.080 --> 00:36:56.110 code from all of the rest of my code as well. 00:36:56.110 --> 00:36:58.480 But much as in the case of CSS, where we were 00:36:58.480 --> 00:37:01.860 able to take CSS that was originally located in the head of our page 00:37:01.860 --> 00:37:04.990 and move it into a separate file, you can do the same thing with JavaScript 00:37:04.990 --> 00:37:05.530 too. 00:37:05.530 --> 00:37:07.660 And this can be helpful if you have multiple people working 00:37:07.660 --> 00:37:08.452 on different files. 00:37:08.452 --> 00:37:11.050 You want one person working on the HTML and someone else 00:37:11.050 --> 00:37:12.580 working on the JavaScript. 00:37:12.580 --> 00:37:15.255 It can be helpful if you expect that one of these things 00:37:15.255 --> 00:37:17.380 is going to change more frequently than the others, 00:37:17.380 --> 00:37:19.820 so you might not need to load the other one as often. 00:37:19.820 --> 00:37:24.280 So there can be value in separating our HTML code from our JavaScript even more 00:37:24.280 --> 00:37:27.130 by moving our JavaScript into a separate file. 00:37:27.130 --> 00:37:30.760 And so in order to do that, I can create a new file 00:37:30.760 --> 00:37:35.620 that I'll just call counter.js, which will contain all of the JavaScript 00:37:35.620 --> 00:37:38.870 for my counter.html file. 00:37:38.870 --> 00:37:41.380 So in order to do that, what I can say is let's go ahead 00:37:41.380 --> 00:37:44.320 and copy all of this JavaScript code. 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. 00:37:48.220 --> 00:37:50.570 Remove some of that indentation. 00:37:50.570 --> 00:37:54.520 So now, I have a file called counter.js that 00:37:54.520 --> 00:38:00.460 just contains all of the JavaScript I want to run on my counter.html page. 00:38:00.460 --> 00:38:04.510 And now rather than include actual JavaScript in between these script 00:38:04.510 --> 00:38:10.570 tags, what I can say is script src-- src for source-- 00:38:10.570 --> 00:38:17.770 =counter.js, for example, to say go ahead and reference counter.js and use 00:38:17.770 --> 00:38:21.213 that JavaScript in the head of the page here. 00:38:21.213 --> 00:38:23.380 And that then is going to work exactly the same way. 00:38:23.380 --> 00:38:25.400 I still am able to count as high as I'd like. 00:38:25.400 --> 00:38:28.240 I still get an alert every time the count reaches a multiple of 10, 00:38:28.240 --> 00:38:30.380 but my HTML is now a little bit simpler. 00:38:30.380 --> 00:38:31.270 It's just the body. 00:38:31.270 --> 00:38:35.320 It's just the h1 and the button, and then all of my JavaScript 00:38:35.320 --> 00:38:39.340 is now located in a separate file that allows 00:38:39.340 --> 00:38:42.310 me to keep my HTML code and my JavaScript code separate 00:38:42.310 --> 00:38:43.180 from each other. 00:38:43.180 --> 00:38:46.330 And that can be valuable for a couple of reasons, among them 00:38:46.330 --> 00:38:50.500 if I have common JavaScript code that's in use by multiple different HTML 00:38:50.500 --> 00:38:55.138 pages, multiple HTML pages can all include the same JavaScript source 00:38:55.138 --> 00:38:56.680 rather than needing to repeat myself. 00:38:56.680 --> 00:38:59.710 If you use the same JavaScript across multiple different pages, 00:38:59.710 --> 00:39:02.650 I can just use the same JavaScript across all of them. 00:39:02.650 --> 00:39:05.200 And that'll be helpful too as we begin to take a look later 00:39:05.200 --> 00:39:08.960 at some JavaScript libraries, which are JavaScript written by other people. 00:39:08.960 --> 00:39:12.910 We can just include other people's JavaScript in our own web pages 00:39:12.910 --> 00:39:15.430 just by adding a script tag at the top of our page 00:39:15.430 --> 00:39:17.240 that specifies a particular source. 00:39:17.240 --> 00:39:19.210 You may already interacted with Bootstrap. 00:39:19.210 --> 00:39:21.220 That has its own JavaScript code. 00:39:21.220 --> 00:39:23.170 And you can include Bootstrap's JavaScript 00:39:23.170 --> 00:39:26.890 just by including a script tag at the top of our HTML page 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. 00:39:33.770 --> 00:39:36.310 So what else can we do now, now that we have the ability 00:39:36.310 --> 00:39:40.330 to get at elements of the DOM and actually manipulate their contents? 00:39:40.330 --> 00:39:43.930 Well, one thing we can do is begin to make our pages a little bit more 00:39:43.930 --> 00:39:47.710 interactive, actually respond to what users are doing on the page, 00:39:47.710 --> 00:39:50.950 whether the user is typing something in or maybe filling out a form, 00:39:50.950 --> 00:39:52.040 for example. 00:39:52.040 --> 00:39:54.070 So let's go ahead and try an example of that, 00:39:54.070 --> 00:39:56.150 where the user might be filling out a form 00:39:56.150 --> 00:39:58.660 and we would like for our code to somehow respond 00:39:58.660 --> 00:40:00.310 to what it is that they type. 00:40:00.310 --> 00:40:04.870 I'll go ahead and go back into hello.html. 00:40:04.870 --> 00:40:08.500 And now inside of the body of the page, I've said hello at the top. 00:40:08.500 --> 00:40:12.400 And here instead of a button, I'm going to have a form. 00:40:12.400 --> 00:40:15.400 This HTML form will look like the HTML forms we've seen before. 00:40:15.400 --> 00:40:18.402 I have an input field that I'll add the autofocus attribute 00:40:18.402 --> 00:40:20.860 to to mean, like, automatically focus this input field when 00:40:20.860 --> 00:40:25.330 I open the page because I might want the user to start typing right away. 00:40:25.330 --> 00:40:30.430 I'm going to give this input field an id of name, for example, 00:40:30.430 --> 00:40:34.460 and then a placeholder of Name-- capital N-- 00:40:34.460 --> 00:40:36.648 whose type is text. 00:40:36.648 --> 00:40:37.690 So what have I done here? 00:40:37.690 --> 00:40:40.720 I've created an input field where the user can type in some text. 00:40:40.720 --> 00:40:43.840 The placeholder-- the thing the user sees filled into that input field 00:40:43.840 --> 00:40:46.240 originally-- will just be capital N Name, 00:40:46.240 --> 00:40:48.900 telling them they should type their name in here. 00:40:48.900 --> 00:40:53.030 And I've given this input field an id-- some unique identifier, 00:40:53.030 --> 00:40:58.720 such that I later on, can reference and find this particular input field. 00:40:58.720 --> 00:41:01.660 And then I have input type=submit-- 00:41:01.660 --> 00:41:06.530 some way for me to now submit this form as well. 00:41:06.530 --> 00:41:11.650 And so if I load this page, load hello.html, here's what I see-- 00:41:11.650 --> 00:41:14.650 hello, a field where I can type in my name, the placeholder name 00:41:14.650 --> 00:41:19.970 shows up there for me, and then a button where I can submit this form. 00:41:19.970 --> 00:41:22.930 And now, what I'd like to do inside of my JavaScript 00:41:22.930 --> 00:41:25.390 is instead of this hello function, what I'm going to do 00:41:25.390 --> 00:41:28.120 is I'm going to first run some JavaScript when 00:41:28.120 --> 00:41:29.360 the DOM is done loading. 00:41:29.360 --> 00:41:30.790 And so I'll use that same line from before. 00:41:30.790 --> 00:41:32.498 You're going to see it quite a bit, where 00:41:32.498 --> 00:41:34.950 we're going to say document.addEventListener 00:41:34.950 --> 00:41:38.620 DOMContentLoaded, and then this function to mean go ahead 00:41:38.620 --> 00:41:41.530 and run this code when the DOM is done loaded. 00:41:41.530 --> 00:41:46.840 And the code I'd like to run is to say when I submit the form, 00:41:46.840 --> 00:41:47.980 I want something to happen. 00:41:47.980 --> 00:41:50.398 When I submit the form, maybe I want to display an alert 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, 00:41:53.440 --> 00:41:55.520 it'll say, hello, David, for example. 00:41:55.520 --> 00:41:57.133 So how might I do that? 00:41:57.133 --> 00:41:58.300 Well, how do I get the form? 00:41:58.300 --> 00:41:59.383 That's the first question. 00:41:59.383 --> 00:42:01.210 Anytime you want to get at an element-- 00:42:01.210 --> 00:42:05.140 one particular element-- on an HTML page, usually what we're going to do 00:42:05.140 --> 00:42:10.128 is document.querySelector to say get me the element that is a form. 00:42:10.128 --> 00:42:11.920 And there's only one form on the page, so I 00:42:11.920 --> 00:42:13.420 don't have to worry about ambiguity. 00:42:13.420 --> 00:42:16.060 I'm just saying get me that form. 00:42:16.060 --> 00:42:19.060 And then I can say .onsubmit. 00:42:19.060 --> 00:42:22.560 When you submit the form, what code should run? 00:42:22.560 --> 00:42:25.030 And if I had a name of a function, like a function f, 00:42:25.030 --> 00:42:29.230 I could just say like, run function f when the form is submitted. 00:42:29.230 --> 00:42:31.510 But alternatively, just as before, instead 00:42:31.510 --> 00:42:34.090 of providing the name of a function, I can also just 00:42:34.090 --> 00:42:36.070 provide the function itself. 00:42:36.070 --> 00:42:40.570 I can say function, and then in between these curly braces, 00:42:40.570 --> 00:42:44.230 I can specify exactly what code should run 00:42:44.230 --> 00:42:48.070 when the form is submitted by providing this anonymous function instead, 00:42:48.070 --> 00:42:52.780 using this anonymous function as the value of the onsubmit property 00:42:52.780 --> 00:42:54.190 of this form. 00:42:54.190 --> 00:42:56.320 And so now, what I'd like to do is somehow 00:42:56.320 --> 00:42:59.500 get access to whatever the user typed into the input field, 00:42:59.500 --> 00:43:02.240 whatever the user's name happens to be. 00:43:02.240 --> 00:43:07.330 And so I could get the input field via document.querySelector input. 00:43:07.330 --> 00:43:09.490 And that would work this time, but we'll want 00:43:09.490 --> 00:43:11.470 to start to be a little bit careful because on this page, 00:43:11.470 --> 00:43:13.303 there are multiple different input elements. 00:43:13.303 --> 00:43:17.410 There's an input element here for typing in the name and a second input element 00:43:17.410 --> 00:43:20.080 here for telling me you're giving me a button where 00:43:20.080 --> 00:43:22.630 I can submit this particular HTML form. 00:43:22.630 --> 00:43:26.870 And so what I probably want to do is be a little bit more specific. 00:43:26.870 --> 00:43:28.900 And it turns out that inside of querySelector, 00:43:28.900 --> 00:43:31.780 I can use all of the standard ways in CSS 00:43:31.780 --> 00:43:34.550 that we could select for a particular element. 00:43:34.550 --> 00:43:37.600 So in CSS, if you'll recall, we had the ability 00:43:37.600 --> 00:43:41.650 to run CSS and just say style all the h1's or we could say style 00:43:41.650 --> 00:43:45.130 all the things with this particular ID or with this particular class. 00:43:45.130 --> 00:43:47.740 And document.querySelector works the same way, 00:43:47.740 --> 00:43:52.210 that I can say document.querySelector and pass in a tag to say like, 00:43:52.210 --> 00:43:56.210 get me the h1 element, or get me the button, or get me the form. 00:43:56.210 --> 00:43:59.500 But if there are multiple h1 elements or multiple buttons and multiple forms, 00:43:59.500 --> 00:44:04.570 I can be more specific than that if, for example, an element has an ID. 00:44:04.570 --> 00:44:07.600 In which case, I can say document.querySelector, and then 00:44:07.600 --> 00:44:11.560 in quotation marks, the hash mark, and then the name of the ID 00:44:11.560 --> 00:44:14.380 to say get me the element with that particular ID, 00:44:14.380 --> 00:44:17.020 again using the exact same syntax that CSS 00:44:17.020 --> 00:44:20.170 uses if I want to apply a particular set of styles 00:44:20.170 --> 00:44:23.890 to only one element that only has one ID. 00:44:23.890 --> 00:44:27.280 Likewise too, I can say document.querySelector, and then 00:44:27.280 --> 00:44:30.520 use dot followed by the name of a class if there's 00:44:30.520 --> 00:44:34.630 a particular class of elements and I want to just get one of those 00:44:34.630 --> 00:44:38.920 to say get me an element that has this particular class in order 00:44:38.920 --> 00:44:40.302 to manipulate it as well. 00:44:40.302 --> 00:44:42.010 So the same types of syntax that we could 00:44:42.010 --> 00:44:46.990 use in CSS for trying to reference and get at a particular HTML element, 00:44:46.990 --> 00:44:50.200 we can do the same thing here with document.querySelector 00:44:50.200 --> 00:44:54.430 to go ahead and try and get a particular element based on its tag name, 00:44:54.430 --> 00:44:57.040 based on its ID, or based on its class. 00:44:57.040 --> 00:45:01.900 And it was for that reason that inside of the HTML page for my input, 00:45:01.900 --> 00:45:04.810 I gave the input an ID of name. 00:45:04.810 --> 00:45:07.840 I wanted some way to be able to uniquely reference it. 00:45:07.840 --> 00:45:10.300 And I can uniquely reference it not by input, 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. 00:45:16.390 --> 00:45:19.120 And that is the element that I would like to extract inside 00:45:19.120 --> 00:45:21.110 of my JavaScript code. 00:45:21.110 --> 00:45:23.420 Once I have that HTML element, what I want 00:45:23.420 --> 00:45:26.790 is, like, what the user actually typed into that input field. 00:45:26.790 --> 00:45:29.600 And it turns out that if you have an input field in HTML, 00:45:29.600 --> 00:45:33.710 I can get access to what the user typed in by accessing its value property. 00:45:33.710 --> 00:45:38.820 Value is a property that refers to what it is the user actually typed in. 00:45:38.820 --> 00:45:41.660 So I can say .value. 00:45:41.660 --> 00:45:44.340 And I'm going to go ahead and save that inside of a variable. 00:45:44.340 --> 00:45:48.470 So I could say something like let name = whatever the user typed in. 00:45:48.470 --> 00:45:50.630 But if I'm not going to reassign name to something 00:45:50.630 --> 00:45:52.815 else inside of this function-- 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 00:45:55.940 --> 00:45:57.050 of the function-- 00:45:57.050 --> 00:45:58.715 so I can use a const variable instead. 00:45:58.715 --> 00:46:00.590 And that would be better design to say I have 00:46:00.590 --> 00:46:04.700 a constant variable called name, which is equal to document.querySelector. 00:46:04.700 --> 00:46:09.990 Get me the element whose ID is name and get access to its value. 00:46:09.990 --> 00:46:11.690 And now, I can display an alert. 00:46:11.690 --> 00:46:16.940 I can alert something like in backticks, hello, comma. 00:46:16.940 --> 00:46:19.280 And then using the dollar sign, curly brace syntax, 00:46:19.280 --> 00:46:24.410 I can say plug-in the name there followed by an exclamation point. 00:46:24.410 --> 00:46:26.330 So I've extracted the name from the form. 00:46:26.330 --> 00:46:30.390 Get me the input field where they typed the name, get access to its value, 00:46:30.390 --> 00:46:35.160 and then I'm displaying an alert that is going to say hello to that person, 00:46:35.160 --> 00:46:37.430 for example. 00:46:37.430 --> 00:46:43.000 And so now, if I refresh the page, I type in my name, I press Submit, 00:46:43.000 --> 00:46:44.960 I get an alert that says hello, Brian. 00:46:44.960 --> 00:46:45.580 I press OK. 00:46:45.580 --> 00:46:46.930 I can try it again. 00:46:46.930 --> 00:46:51.070 I can type in something like David, press Submit, and now the page 00:46:51.070 --> 00:46:53.530 says hello, David. 00:46:53.530 --> 00:46:57.280 So here again, we've been able to combine event listeners, and functions, 00:46:57.280 --> 00:47:01.960 and querySelector to be able to both read information from the page in order 00:47:01.960 --> 00:47:06.580 to say get me this particular HTML element, find me an HTML element, 00:47:06.580 --> 00:47:10.870 and access what the user typed into it-- the .value property that gets me what 00:47:10.870 --> 00:47:12.700 the user typed into an input field. 00:47:12.700 --> 00:47:15.740 And we've been able to combine that with event listeners and alerts 00:47:15.740 --> 00:47:18.070 that are able to actually respond dynamically 00:47:18.070 --> 00:47:22.000 to when a user submits the form or when the entire content of the page 00:47:22.000 --> 00:47:26.990 is done loading in order to produce some interesting effects as well. 00:47:26.990 --> 00:47:28.990 But it turns out we can do more than just 00:47:28.990 --> 00:47:32.500 change, like, the HTML that is contained within an element. 00:47:32.500 --> 00:47:36.460 We can also change CSS as well-- change the style properties 00:47:36.460 --> 00:47:38.630 of a particular element as well. 00:47:38.630 --> 00:47:41.530 So let's go ahead and see an example of that. 00:47:41.530 --> 00:47:45.550 Go ahead and create a new file that I'll call colors.html. 00:47:45.550 --> 00:47:50.562 And inside of colors, I'll include the same standard HTML boilerplate code 00:47:50.562 --> 00:47:52.270 that we often start with-- a head section 00:47:52.270 --> 00:47:54.940 with a title and a body section. 00:47:54.940 --> 00:47:57.690 And inside of the body of this page, I'm going 00:47:57.690 --> 00:48:02.415 to display a heading that just says hello, for example. 00:48:02.415 --> 00:48:05.380 And maybe I'll give it an ID just so I can reference it by name. 00:48:05.380 --> 00:48:07.510 Maybe it has an ID of hello. 00:48:07.510 --> 00:48:10.330 And then I'll have three buttons. 00:48:10.330 --> 00:48:15.040 I'll have a button called red, a button called blue, 00:48:15.040 --> 00:48:18.620 and then a button called green, for example, 00:48:18.620 --> 00:48:23.588 where now if I open up colors.html, here's what I see. 00:48:23.588 --> 00:48:26.380 I see a big heading that says hello, and then I see three buttons-- 00:48:26.380 --> 00:48:27.300 Red, Blue, and Green. 00:48:27.300 --> 00:48:31.150 But of course right now, these buttons don't actually do anything. 00:48:31.150 --> 00:48:33.070 How do I get the buttons to do something? 00:48:33.070 --> 00:48:35.230 Well, that's where JavaScript is going to come in. 00:48:35.230 --> 00:48:37.710 I'll add a script tag to the top of my page. 00:48:37.710 --> 00:48:41.200 And I only want to run this JavaScript when the DOM is done loading. 00:48:41.200 --> 00:48:43.900 So again, we'll use the same syntax as before. 00:48:43.900 --> 00:48:49.780 document.addEventListener DOMContentLoaded, and then run 00:48:49.780 --> 00:48:53.440 this function to say everything in between these curly braces, 00:48:53.440 --> 00:48:57.130 this is all the code that should run once the page is done loading. 00:48:57.130 --> 00:49:00.040 And what I'd really like to do is get at these three buttons 00:49:00.040 --> 00:49:02.832 and say when you click on each one of them, do something different, 00:49:02.832 --> 00:49:05.688 like change the color of a particular HTML element. 00:49:05.688 --> 00:49:08.980 And in order to do that, I need some way of uniquely referencing these buttons. 00:49:08.980 --> 00:49:10.930 So to do that, I'm going to give them all IDs. 00:49:10.930 --> 00:49:12.880 This button will have an ID of red. 00:49:12.880 --> 00:49:14.830 This button will have an ID of blue. 00:49:14.830 --> 00:49:16.510 This button will have an ID of green. 00:49:16.510 --> 00:49:19.570 Just unique names I can give to the buttons in HTML, 00:49:19.570 --> 00:49:24.170 such that in JavaScript, I'm later able to reference them. 00:49:24.170 --> 00:49:28.090 So what do I include now here inside of my JavaScript code? 00:49:28.090 --> 00:49:35.130 Well, let me say document.querySelector #red to say 00:49:35.130 --> 00:49:38.610 get me the element whose ID is red. 00:49:38.610 --> 00:49:41.220 And when you're clicked on-- onclick-- 00:49:41.220 --> 00:49:44.083 go ahead and run this function. 00:49:44.083 --> 00:49:45.250 What should the function do? 00:49:45.250 --> 00:49:49.000 Well, I want to take this h1 element and change its color to red. 00:49:49.000 --> 00:49:51.810 I want to change the font color to red. 00:49:51.810 --> 00:49:53.430 And I'll leave a comment to myself. 00:49:53.430 --> 00:49:55.555 In JavaScript, the way you can leave a comment just 00:49:55.555 --> 00:49:58.170 to document what you're doing is using these two slashes. 00:49:58.170 --> 00:50:00.668 The two slashes indicate everything after that on the page 00:50:00.668 --> 00:50:01.710 is going to be a comment. 00:50:01.710 --> 00:50:04.917 The browser will ignore it, but it can be useful to you, the programmer, 00:50:04.917 --> 00:50:06.750 and to someone who's reading your code to be 00:50:06.750 --> 00:50:10.650 able to see what it is that you're describing here on the page. 00:50:10.650 --> 00:50:15.960 And now, what I'd like to do is document.querySelector #hello. 00:50:15.960 --> 00:50:19.230 Get me the HTML element whose ID is hello 00:50:19.230 --> 00:50:22.560 and go ahead and modify its style property. 00:50:22.560 --> 00:50:24.900 And now inside of this style object, I can 00:50:24.900 --> 00:50:27.670 modify any of the CSS style properties. 00:50:27.670 --> 00:50:30.780 One of them, for example, is something like color. 00:50:30.780 --> 00:50:36.860 So I can update the color property and set it equal to red. 00:50:36.860 --> 00:50:40.100 So here now, I'm saying when you click on the red button, 00:50:40.100 --> 00:50:42.180 go ahead and run this function. 00:50:42.180 --> 00:50:47.002 And what the function should do is find the hello element, update its style. 00:50:47.002 --> 00:50:47.960 What part of the style? 00:50:47.960 --> 00:50:49.460 Update its color. 00:50:49.460 --> 00:50:51.140 What should we update it to? 00:50:51.140 --> 00:50:52.945 We should update it to red. 00:50:52.945 --> 00:50:55.820 And I'm going to do the same thing for the other two buttons as well. 00:50:55.820 --> 00:50:58.500 And it's pretty similar code, so I'm just going to Copy-Paste. 00:50:58.500 --> 00:50:59.890 Copy-Paste here. 00:50:59.890 --> 00:51:02.240 I'm going to have one for changing the color to blue. 00:51:02.240 --> 00:51:05.660 When I click the Blue button, it should change the color to blue. 00:51:05.660 --> 00:51:09.710 And then we'll do it one more time, change the font color to green. 00:51:09.710 --> 00:51:14.460 When you click on the Green button, you should change the color to green. 00:51:14.460 --> 00:51:18.670 So now when I refresh the colors.html, right now, hello by default 00:51:18.670 --> 00:51:21.470 is just in black-- standard font color for HTML. 00:51:21.470 --> 00:51:23.360 I click Red, hello changes to red. 00:51:23.360 --> 00:51:25.280 I click Blue, it changes to blue. 00:51:25.280 --> 00:51:27.170 I click Green, it changes to green. 00:51:27.170 --> 00:51:29.060 So depending on what button I click, that 00:51:29.060 --> 00:51:32.870 triggers some event listener that's going to then say when the button is 00:51:32.870 --> 00:51:34.440 clicked, run this function. 00:51:34.440 --> 00:51:37.430 And what the function does is it grabs this h1 element-- 00:51:37.430 --> 00:51:39.440 the element whose ID is hello-- 00:51:39.440 --> 00:51:43.820 modifies it style, updates its color property to be something like red, 00:51:43.820 --> 00:51:45.390 or blue, or green. 00:51:45.390 --> 00:51:48.170 And thus showing that we can modify style in addition 00:51:48.170 --> 00:51:52.330 to just modifying the content of the page itself. 00:51:52.330 --> 00:51:54.830 But it turns out that as you looked at me writing that code, 00:51:54.830 --> 00:51:57.920 something should've struck you as probably not optimal design-- 00:51:57.920 --> 00:52:00.770 that in general, anytime you find yourself writing the same code 00:52:00.770 --> 00:52:03.720 again and again and again, especially if you're copy-pasting, 00:52:03.720 --> 00:52:06.560 that that is a generally bad sign-- usually a sign that there 00:52:06.560 --> 00:52:10.760 is some better way of trying to modify, of trying to implement 00:52:10.760 --> 00:52:12.800 the behavior that I'm trying to create. 00:52:12.800 --> 00:52:14.120 And it turns out that there is. 00:52:14.120 --> 00:52:16.370 And there are a number of ways that you could do this. 00:52:16.370 --> 00:52:19.820 One way here is that I might like to consolidate these three event 00:52:19.820 --> 00:52:23.330 listeners into just, like, a single function that 00:52:23.330 --> 00:52:27.740 is going to handle changing the color to whatever the button says the color 00:52:27.740 --> 00:52:29.140 should be changed to. 00:52:29.140 --> 00:52:32.570 But one problem here is that if I just attach the same event 00:52:32.570 --> 00:52:37.002 listener to all three of the buttons, it's not going to be clear to me 00:52:37.002 --> 00:52:38.960 when I click on the button, how does the button 00:52:38.960 --> 00:52:42.680 know what color we should change the text to. 00:52:42.680 --> 00:52:46.640 And so to that effect, we can add some additional special attributes 00:52:46.640 --> 00:52:51.520 to a particular HTML element that are called data attributes, 00:52:51.520 --> 00:52:55.820 where a data attribute is my way of saying that I would like to associate 00:52:55.820 --> 00:53:00.080 some data with this particular HTML element, where here, 00:53:00.080 --> 00:53:09.410 I can say data-color="red", data-color="blue", data-color="green". 00:53:09.410 --> 00:53:12.470 Data attributes always start with data followed by a dash, 00:53:12.470 --> 00:53:15.830 and then I can specify really any name that I want for some information 00:53:15.830 --> 00:53:18.800 that I would like to store about the HTML element. 00:53:18.800 --> 00:53:21.050 And here, the information I want to store 00:53:21.050 --> 00:53:25.400 is I want to store data about what color you should change the text to when 00:53:25.400 --> 00:53:26.750 the button is clicked on. 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 00:53:30.080 --> 00:53:32.900 that if I have access to this element-- this button-- 00:53:32.900 --> 00:53:36.830 I can access its data-color property to know 00:53:36.830 --> 00:53:39.470 whether we should change the text to red, or blue, 00:53:39.470 --> 00:53:43.910 or green by adding these data attributes to these HTML elements. 00:53:43.910 --> 00:53:47.590 And so now, what I want is some way of getting all of these buttons. 00:53:47.590 --> 00:53:53.300 Now document.querySelector, as you recall, just gets one element. 00:53:53.300 --> 00:53:55.730 It's just going to get for me a single element 00:53:55.730 --> 00:53:57.950 and it's going to get the first one that it finds. 00:53:57.950 --> 00:54:01.280 If I want to get multiple elements, what I can do instead 00:54:01.280 --> 00:54:06.110 is something like document.querySelectorAll. 00:54:06.110 --> 00:54:09.720 querySelectorAll is going to return the same thing that querySelector does, 00:54:09.720 --> 00:54:12.260 but instead of querySelector returning a single element that 00:54:12.260 --> 00:54:14.930 matches what it looks for, querySelectorAll 00:54:14.930 --> 00:54:18.650 is going to return to me an array of all of the elements 00:54:18.650 --> 00:54:20.520 that matched my particular query. 00:54:20.520 --> 00:54:23.220 So if I wanted to select not just the first button I find, 00:54:23.220 --> 00:54:28.150 but all of the buttons I find, I can here say querySelectorAll for button. 00:54:28.150 --> 00:54:31.430 And that will give me back a JavaScript array, the equivalent of a list, 00:54:31.430 --> 00:54:34.430 that represents all of those buttons. 00:54:34.430 --> 00:54:37.550 And we can actually test what this looks like by looking at things 00:54:37.550 --> 00:54:40.820 inside of the JavaScript console. 00:54:40.820 --> 00:54:46.490 If I go ahead and refresh this page colors, I can open up the inspector, 00:54:46.490 --> 00:54:50.330 go into the JavaScript console, and just as you could see error messages here, 00:54:50.330 --> 00:54:54.950 you can also actually write JavaScript code here as well. 00:54:54.950 --> 00:55:00.300 So I can say something like document.querySelector button 00:55:00.300 --> 00:55:03.870 to say, all right, what's going to happen when I try and select 00:55:03.870 --> 00:55:07.050 for a button on this particular page? 00:55:07.050 --> 00:55:10.710 And what I get is, all right, I get just this very first button-- 00:55:10.710 --> 00:55:13.320 button who's data-color is equal to red. 00:55:13.320 --> 00:55:16.380 That's what I would expect. querySelector just finds me one element 00:55:16.380 --> 00:55:19.740 and it's going to find me the very first element. 00:55:19.740 --> 00:55:22.650 And likewise, I can say, all right, instead of querySelector, 00:55:22.650 --> 00:55:25.080 let's do querySelectorAll. 00:55:25.080 --> 00:55:26.932 And what I get back is a NodeList, which you 00:55:26.932 --> 00:55:28.890 can think of as kind of like an array or a list 00:55:28.890 --> 00:55:33.810 in Python, that's got three buttons in it-- button 0, 1, and 2. 00:55:33.810 --> 00:55:38.340 And just as with a list in Python as you can index into things, 00:55:38.340 --> 00:55:40.650 arrays in JavaScript can be indexed into as well. 00:55:40.650 --> 00:55:47.590 If I have something like const names = Harry, Ron, and Hermione-- 00:55:47.590 --> 00:55:50.100 like an array of three names-- 00:55:50.100 --> 00:55:54.270 I can say names square bracket 0 to get the first name, names square bracket 1 00:55:54.270 --> 00:55:56.310 to get the second one, names square bracket 2 00:55:56.310 --> 00:55:57.960 to get the third one, for example. 00:55:57.960 --> 00:56:01.012 And that gives me each of the individual elements in the array. 00:56:01.012 --> 00:56:02.970 If I want to get the whole length of the array, 00:56:02.970 --> 00:56:08.160 I can do names.length to get, all right, the length of the names array 00:56:08.160 --> 00:56:09.210 happens to be three. 00:56:09.210 --> 00:56:11.085 So just some additional features that we have 00:56:11.085 --> 00:56:13.680 access to if you happen to have an array of things. 00:56:13.680 --> 00:56:16.260 It turns out querySelectorAll returns to me a NodeList, 00:56:16.260 --> 00:56:18.320 which is kind of like an array. 00:56:18.320 --> 00:56:20.490 And that's going to be useful because when 00:56:20.490 --> 00:56:23.940 I say document.querySelectorAll button, I am saying 00:56:23.940 --> 00:56:27.380 get me all of the buttons on the page. 00:56:27.380 --> 00:56:29.940 And now, what I would like to do is effectively 00:56:29.940 --> 00:56:34.680 loop over all of those buttons and say for each of the buttons 00:56:34.680 --> 00:56:37.210 inside of this list that comes back to me, 00:56:37.210 --> 00:56:40.830 I would like to add an event handler for when that button is clicked on 00:56:40.830 --> 00:56:43.140 to say for each of the buttons that comes back, 00:56:43.140 --> 00:56:47.850 go ahead and say when you're clicked on, change the color of the h1 element. 00:56:47.850 --> 00:56:51.900 And so there are a number of ways, again, that you could do this, 00:56:51.900 --> 00:56:56.910 but one way is to use a particular property called forEach. 00:56:56.910 --> 00:57:02.040 And forEach is a function that accepts as an argument, another function, where 00:57:02.040 --> 00:57:03.840 the idea is going to be I would like to run 00:57:03.840 --> 00:57:07.890 a function for each of the elements inside of an array 00:57:07.890 --> 00:57:10.840 or inside of a NodeList, for example. 00:57:10.840 --> 00:57:16.170 So here, I can say forEach button, go ahead and run this function. 00:57:16.170 --> 00:57:19.200 This is going to be a function now that takes something as input. 00:57:19.200 --> 00:57:21.825 It's going to take one of the elements in the list 00:57:21.825 --> 00:57:25.050 as input, something like a button. 00:57:25.050 --> 00:57:29.370 And now for each button, what would I like to do for that button? 00:57:29.370 --> 00:57:34.110 Well, when the button is clicked on, button.onclick, then 00:57:34.110 --> 00:57:43.280 go ahead and run a function that is going to document.querySelector. 00:57:43.280 --> 00:57:47.160 Get me the element whose ID is #hello. 00:57:47.160 --> 00:57:48.680 Change its style. 00:57:48.680 --> 00:57:50.990 Within the style, change its color. 00:57:50.990 --> 00:57:53.042 And what do I want to change its color to? 00:57:53.042 --> 00:57:54.500 Well, I have access to this button. 00:57:54.500 --> 00:57:56.990 This argument to the function is whichever 00:57:56.990 --> 00:58:00.170 button I'm currently trying to add an event listener for. 00:58:00.170 --> 00:58:02.510 And in order to access its data properties, 00:58:02.510 --> 00:58:06.650 I can access a special property of an HTML element called it's dataset 00:58:06.650 --> 00:58:07.940 property. 00:58:07.940 --> 00:58:11.900 And then I can say something like button.dataset.color 00:58:11.900 --> 00:58:15.260 to get at the data-color attribute. 00:58:15.260 --> 00:58:16.665 So a lot of stuff going on here. 00:58:16.665 --> 00:58:19.040 Let's go ahead and try and read through this entire thing 00:58:19.040 --> 00:58:21.165 and just get a feel for what's happening because we 00:58:21.165 --> 00:58:23.360 have functions nested within other functions nested 00:58:23.360 --> 00:58:24.800 within other functions. 00:58:24.800 --> 00:58:28.520 Up at the very top, I've said add an event listener to the document. 00:58:28.520 --> 00:58:30.810 When the document's DOM content is loaded, 00:58:30.810 --> 00:58:33.320 meaning all of the content of the page is done loading, 00:58:33.320 --> 00:58:35.280 go ahead and run this function. 00:58:35.280 --> 00:58:37.450 This is the body of the function. 00:58:37.450 --> 00:58:38.450 So what do I want to do? 00:58:38.450 --> 00:58:42.650 When the page is done loading, I'm going to document.querySelectorAll, 00:58:42.650 --> 00:58:44.827 looking for all of the buttons. 00:58:44.827 --> 00:58:46.910 And if I wanted to if there could be more buttons, 00:58:46.910 --> 00:58:48.890 I could have added a class to these buttons 00:58:48.890 --> 00:58:51.015 and just looked for things of the particular class. 00:58:51.015 --> 00:58:55.680 querySelectorAll just returns all of the elements that match a particular query. 00:58:55.680 --> 00:58:58.610 And then I'm saying forEach of those buttons-- 00:58:58.610 --> 00:59:00.930 for each of the buttons that came back-- 00:59:00.930 --> 00:59:03.700 I would like to run a function on each of those buttons. 00:59:03.700 --> 00:59:06.200 I'm basically saying if I have three buttons that came back, 00:59:06.200 --> 00:59:08.217 let me run a function on the first button, 00:59:08.217 --> 00:59:10.050 then the same function on the second button, 00:59:10.050 --> 00:59:12.000 then the same function on the third button. 00:59:12.000 --> 00:59:13.820 And what is that function? 00:59:13.820 --> 00:59:15.530 Well, it's this function here-- 00:59:15.530 --> 00:59:17.992 a function that takes as input, the button. 00:59:17.992 --> 00:59:20.450 It's first going to pass in as input the first button, then 00:59:20.450 --> 00:59:22.650 the second button, then the third. 00:59:22.650 --> 00:59:27.170 And what this function does is it adds an onclick handler to the button. 00:59:27.170 --> 00:59:31.480 It says when the button is clicked on, go ahead and run this other function. 00:59:31.480 --> 00:59:33.230 And this function now is the function that 00:59:33.230 --> 00:59:37.250 will run when the button is clicked on to say when the button is clicked on, 00:59:37.250 --> 00:59:43.610 get me the #hello element, change its color to button.dataset.color. 00:59:43.610 --> 00:59:45.980 And button.dataset.color takes a button-- 00:59:45.980 --> 00:59:48.530 takes an HTML element like this one here-- 00:59:48.530 --> 00:59:51.890 and accesses its data-set, all of its data properties, 00:59:51.890 --> 00:59:56.000 and specifically accesses the color data property, which in this case 00:59:56.000 --> 00:59:56.960 is equal to red. 00:59:56.960 --> 01:00:00.690 And that is what we would like to set color equal to. 01:00:00.690 --> 01:00:02.930 So a little bit more complex than we've seen before, 01:00:02.930 --> 01:00:06.380 but now we've been able to reduce what was three different event 01:00:06.380 --> 01:00:09.170 handlers into just a single one. 01:00:09.170 --> 01:00:11.270 And now, this is going to work the same way. 01:00:11.270 --> 01:00:15.730 Change it to red, blue, and green, all by just using those data properties 01:00:15.730 --> 01:00:17.067 that we have access to. 01:00:17.067 --> 01:00:19.400 And so when in doubt about how these things are working, 01:00:19.400 --> 01:00:22.070 about what querySelector is returning, the JavaScript console 01:00:22.070 --> 01:00:23.620 can be a very powerful tool for that. 01:00:23.620 --> 01:00:26.840 So you can go into the JavaScript console and actually manipulate things. 01:00:26.840 --> 01:00:28.670 You can run queries. 01:00:28.670 --> 01:00:29.870 You can run functions. 01:00:29.870 --> 01:00:32.210 You can even modify the values of variables. 01:00:32.210 --> 01:00:35.820 Like if I go back, for instance, to counter.html, 01:00:35.820 --> 01:00:39.920 where I had this counter that's counting 0, 1, 2, 3, 4, 01:00:39.920 --> 01:00:44.450 if I wanted to, I could say something like counter = 27-- 01:00:44.450 --> 01:00:46.787 just, like, change the value of the counter. 01:00:46.787 --> 01:00:48.620 Nothing appears to have changed on the page. 01:00:48.620 --> 01:00:50.750 I didn't say update anything on the page. 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 01:00:53.840 --> 01:00:54.710 to 28. 01:00:54.710 --> 01:00:58.260 Because I had updated the value inside of the JavaScript console, 01:00:58.260 --> 01:01:00.110 it's going to increment that value, display 01:01:00.110 --> 01:01:02.810 that value inside of the h1 element. 01:01:02.810 --> 01:01:04.310 So you can modify variables. 01:01:04.310 --> 01:01:05.780 You can run functions. 01:01:05.780 --> 01:01:08.750 You can run document.querySelector to figure out 01:01:08.750 --> 01:01:11.180 what particular elements are going to come back all 01:01:11.180 --> 01:01:14.270 through the use of the JavaScript console, which can be a very, very 01:01:14.270 --> 01:01:16.490 powerful tool, especially as you begin working 01:01:16.490 --> 01:01:20.300 on trying to debug these programs and trying to figure out 01:01:20.300 --> 01:01:21.905 what might be wrong with them. 01:01:21.905 --> 01:01:23.780 It turns out too that there are other changes 01:01:23.780 --> 01:01:26.570 that we can make in order to optimize our code a little bit more, in order 01:01:26.570 --> 01:01:28.323 to make it a little bit more succinct. 01:01:28.323 --> 01:01:30.740 And one way is that in more recent versions of JavaScript, 01:01:30.740 --> 01:01:33.500 they've introduced a particular notation for functions called 01:01:33.500 --> 01:01:35.215 the arrow notation for functions. 01:01:35.215 --> 01:01:37.340 And I'll just show it to you because it'll come up. 01:01:37.340 --> 01:01:40.850 But oftentimes instead of using the keyword function before introducing 01:01:40.850 --> 01:01:46.685 a function, you'll just have something like button, and then arrow, 01:01:46.685 --> 01:01:47.600 then curly braces. 01:01:47.600 --> 01:01:50.017 And strictly speaking, you don't even need the parentheses 01:01:50.017 --> 01:01:53.300 around the input, where button arrow, and then in these curly braces, 01:01:53.300 --> 01:01:57.320 some code just means here is going to be a function that takes as input, 01:01:57.320 --> 01:02:01.880 a variable called button, and then runs this particular block of code 01:02:01.880 --> 01:02:03.710 when that function is run. 01:02:03.710 --> 01:02:06.950 And likewise if a function takes no input, like this function up here, 01:02:06.950 --> 01:02:12.350 you can express it using arrow notation with just parentheses, arrow, block. 01:02:12.350 --> 01:02:15.010 And so this is often a notation that you'll see in JavaScript. 01:02:15.010 --> 01:02:16.927 So if you ever see it, know that that's really 01:02:16.927 --> 01:02:18.630 just shorthand for creating a function. 01:02:18.630 --> 01:02:21.857 Whatever it is to the left of the arrow sign is the input to the function 01:02:21.857 --> 01:02:23.690 and whatever it is to the right of the arrow 01:02:23.690 --> 01:02:27.590 is what code should actually run when the function body gets executed, when 01:02:27.590 --> 01:02:29.690 the function is called upon. 01:02:29.690 --> 01:02:33.500 So what other changes might we want to make to colors.html? 01:02:33.500 --> 01:02:36.470 Well, if we look back at colors.html, here's what it looks like now. 01:02:36.470 --> 01:02:39.650 We've got a heading that says hello, and then buttons to change the color 01:02:39.650 --> 01:02:42.030 to red or blue or green, for example. 01:02:42.030 --> 01:02:44.090 We might instead if we want the user to choose 01:02:44.090 --> 01:02:47.300 from one from a number of options, decide upon the user interface 01:02:47.300 --> 01:02:51.410 choice of using a dropdown instead of a bunch of buttons, for example. 01:02:51.410 --> 01:02:52.970 And JavaScript supports that as well. 01:02:52.970 --> 01:02:56.120 And we'll use this as an opportunity to explore some of the other event 01:02:56.120 --> 01:02:58.670 handlers that exist within JavaScript. 01:02:58.670 --> 01:03:02.690 So for example, instead of having these all inside of buttons, 01:03:02.690 --> 01:03:04.940 I can make my life a little bit easier by making 01:03:04.940 --> 01:03:07.760 this a select dropdown, where the select is 01:03:07.760 --> 01:03:11.810 going to have an option whose value is, let's say, black is the default option. 01:03:11.810 --> 01:03:13.040 We'll just say black. 01:03:13.040 --> 01:03:17.060 And then we'll add another option whose value is red, and then we say red. 01:03:17.060 --> 01:03:19.670 And the value is what we'll get in JavaScript when we try 01:03:19.670 --> 01:03:22.580 and extract the value of a particular select dropdown. 01:03:22.580 --> 01:03:24.860 What's in between the option tags themselves 01:03:24.860 --> 01:03:27.860 is what the user is going to see on the page when they actually view it, 01:03:27.860 --> 01:03:30.230 so I'm capitalizing it just for them. 01:03:30.230 --> 01:03:32.340 Option value="blue". 01:03:32.340 --> 01:03:33.380 That'll be Blue. 01:03:33.380 --> 01:03:37.350 And then option value="green", and that'll be Green. 01:03:37.350 --> 01:03:40.027 So now what the user sees is they see hello, 01:03:40.027 --> 01:03:42.860 and then a dropdown menu where they can choose from a list of colors 01:03:42.860 --> 01:03:45.750 rather than click buttons in order to do so. 01:03:45.750 --> 01:03:49.130 And now of course, this select dropdown doesn't do anything at the moment, 01:03:49.130 --> 01:03:51.510 but I can modify it so that it does. 01:03:51.510 --> 01:03:54.172 So now instead of selecting for all of the buttons 01:03:54.172 --> 01:03:55.880 and doing something with all the buttons, 01:03:55.880 --> 01:03:57.620 we don't have any buttons anymore. 01:03:57.620 --> 01:04:03.380 What I do have is I have a select dropdown. 01:04:03.380 --> 01:04:05.450 And now just as we've seen like onclick to say 01:04:05.450 --> 01:04:08.820 when you click on something, as we've seen DOMContentLoaded as an event, 01:04:08.820 --> 01:04:11.450 there's another event called onchange, which 01:04:11.450 --> 01:04:13.730 applies to things like select dropdowns, where 01:04:13.730 --> 01:04:17.240 when something changes in the select dropdown, when a user chooses something 01:04:17.240 --> 01:04:20.300 different, I can run some code, for example. 01:04:20.300 --> 01:04:22.730 So I can run a function that in this case, 01:04:22.730 --> 01:04:26.480 is going to take document.querySelector #hello, 01:04:26.480 --> 01:04:30.382 meaning get me the hello HTML element, change its style. 01:04:30.382 --> 01:04:31.340 What part of the style? 01:04:31.340 --> 01:04:32.678 Change its color. 01:04:32.678 --> 01:04:34.220 And I want to change it to something. 01:04:34.220 --> 01:04:38.540 I want to change it to the value of this select dropdown. 01:04:38.540 --> 01:04:41.930 But how do I get access to this particular select dropdown? 01:04:41.930 --> 01:04:46.430 Well, in JavaScript, we have access to a special value called this. 01:04:46.430 --> 01:04:49.010 And this has special meaning in JavaScript 01:04:49.010 --> 01:04:51.300 and its meaning varies based on context. 01:04:51.300 --> 01:04:53.660 But in the context of an event handler, a function that 01:04:53.660 --> 01:04:56.330 is called when a particular event happens, 01:04:56.330 --> 01:04:59.330 this is going to be a special keyword that always refers 01:04:59.330 --> 01:05:01.970 to the thing that received the event. 01:05:01.970 --> 01:05:03.320 So what received the event? 01:05:03.320 --> 01:05:04.700 It was the select dropdown. 01:05:04.700 --> 01:05:07.430 That is what received the event of being changed, 01:05:07.430 --> 01:05:11.060 and so this is going to be a special keyword that always refers 01:05:11.060 --> 01:05:13.940 to that-- that always refers to the dropdown menu 01:05:13.940 --> 01:05:15.600 where I made a different selection. 01:05:15.600 --> 01:05:18.058 So if I wanted to get the value of that dropdown menu, what 01:05:18.058 --> 01:05:20.270 it is the user actually selected, I can just 01:05:20.270 --> 01:05:25.250 say this.value to mean get that dropdown menu and get at the value-- the thing 01:05:25.250 --> 01:05:27.710 that the user selected in that menu. 01:05:27.710 --> 01:05:30.140 And now much more succinctly than before, 01:05:30.140 --> 01:05:32.630 I've been able to implement the same kind of idea. 01:05:32.630 --> 01:05:36.260 It says hello right now in black, but if I choose from the dropdown menu 01:05:36.260 --> 01:05:38.600 to change its color to something like red for example, 01:05:38.600 --> 01:05:40.280 the color changes to red. 01:05:40.280 --> 01:05:42.860 If I instead choose blue, it changes to blue. 01:05:42.860 --> 01:05:44.270 Green changes to green. 01:05:44.270 --> 01:05:47.160 I choose black, it changes back to black. 01:05:47.160 --> 01:05:50.690 So now, I have this ability to detect these other types of events 01:05:50.690 --> 01:05:52.580 and respond to them as well. 01:05:52.580 --> 01:05:55.910 And there are many, many different events that exist in JavaScript. 01:05:55.910 --> 01:05:57.890 There's onclick, which we've seen already. 01:05:57.890 --> 01:06:00.860 Onmouseover can detect like when you mouse over something, when you're 01:06:00.860 --> 01:06:02.512 hovering over a particular element. 01:06:02.512 --> 01:06:04.220 If you've ever seen websites that somehow 01:06:04.220 --> 01:06:06.710 respond when your mouse moves over something, 01:06:06.710 --> 01:06:08.540 that can be how it's implemented. 01:06:08.540 --> 01:06:11.330 Onkeydown and onkeyup can respond to keyboard events, 01:06:11.330 --> 01:06:14.610 something like when you press a key on the keyboard. 01:06:14.610 --> 01:06:17.270 When you press down on the key, that's onkeydown, 01:06:17.270 --> 01:06:19.810 and when you lift your finger off the key, that's onkeyup. 01:06:19.810 --> 01:06:22.460 And there are other events as well, many more events 01:06:22.460 --> 01:06:26.300 than are just listed here that you can listen for and respond to, 01:06:26.300 --> 01:06:28.460 so that you can really interact with the user 01:06:28.460 --> 01:06:30.920 based on what it is that they're doing. 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 01:06:34.760 --> 01:06:38.300 to now begin to create a little bit of a more interesting application. 01:06:38.300 --> 01:06:41.030 We'll go ahead and build a to-do list application, 01:06:41.030 --> 01:06:43.010 this time using exclusively JavaScript. 01:06:43.010 --> 01:06:46.100 We've seen to-do lists before that involved communicating with a server, 01:06:46.100 --> 01:06:47.720 making requests and responses. 01:06:47.720 --> 01:06:51.920 We'll now build a to-do list that only uses JavaScript to do so. 01:06:51.920 --> 01:06:54.220 So I'll create a new file called tasks.html. 01:06:57.040 --> 01:07:02.760 And we'll create a head section whose title is tasks and a body section. 01:07:02.760 --> 01:07:04.960 And inside the body of the page, I'll go ahead 01:07:04.960 --> 01:07:07.270 and have a heading that says tasks. 01:07:07.270 --> 01:07:11.215 And underneath that, I want an unordered list of all of my tasks. 01:07:11.215 --> 01:07:12.880 So I'll have an unordered list. 01:07:12.880 --> 01:07:15.470 I'll give it an ID of tasks just for good measure, 01:07:15.470 --> 01:07:16.870 so I can reference it later. 01:07:16.870 --> 01:07:19.540 But initially, nothing is going to be in here. 01:07:19.540 --> 01:07:22.780 But what I'll have underneath the unordered list is a form-- 01:07:22.780 --> 01:07:26.380 a form where I can submit a new task, for example. 01:07:26.380 --> 01:07:29.200 So I'll give myself an input field, also give it an ID. 01:07:29.200 --> 01:07:33.790 The ID will be task singular for the new task that I am typing in. 01:07:33.790 --> 01:07:37.740 The placeholder will be New Task, just so the user knows what to type in. 01:07:37.740 --> 01:07:40.100 And the type of the input field will be text. 01:07:40.100 --> 01:07:43.390 So I have an input field where the user can type in some new task. 01:07:43.390 --> 01:07:45.550 And I'll also add an input field for good measure 01:07:45.550 --> 01:07:49.330 whose type is submit that allows the user to submit a new task once they've 01:07:49.330 --> 01:07:50.780 created it. 01:07:50.780 --> 01:07:55.090 So if I open up tasks.html, here's then what I see. 01:07:55.090 --> 01:07:58.620 Big heading-- there is technically an unordered list underneath it here, 01:07:58.620 --> 01:08:02.200 but there is nothing in that unordered list yet, so it just shows up as empty. 01:08:02.200 --> 01:08:04.390 Then a text field where I can type in a task, 01:08:04.390 --> 01:08:08.660 and then a Submit button where I can submit my new task. 01:08:08.660 --> 01:08:11.960 So now, I'd like some JavaScript, such that when I submit this form, 01:08:11.960 --> 01:08:13.800 we actually do something. 01:08:13.800 --> 01:08:15.350 So I'll add a script tag. 01:08:15.350 --> 01:08:23.210 I want this JavaScript to run after the DOM content is loaded, 01:08:23.210 --> 01:08:27.350 so we'll go ahead and add the usual DOMContentLoaded event listener. 01:08:27.350 --> 01:08:30.990 And now, I want to run code when the form is submitted. 01:08:30.990 --> 01:08:38.240 So I can say document.querySelector form .onsubmit =, 01:08:38.240 --> 01:08:39.740 and then I want to run a function. 01:08:39.740 --> 01:08:41.270 And I could use the keyword function again, 01:08:41.270 --> 01:08:42.630 but I can just use an arrow function, which 01:08:42.630 --> 01:08:43.939 will be a little bit faster to type. 01:08:43.939 --> 01:08:45.950 Just say, all right, here's the function that I 01:08:45.950 --> 01:08:48.649 want to run when the form is submitted. 01:08:48.649 --> 01:08:50.210 And what would I like to do? 01:08:50.210 --> 01:08:52.127 Well, I'd first like to figure out, all right, 01:08:52.127 --> 01:08:53.990 what did the user actually type in? 01:08:53.990 --> 01:09:00.074 And what the user typed in, well, that'll be document.querySelector #task 01:09:00.074 --> 01:09:02.140 .value. 01:09:02.140 --> 01:09:03.550 Get me the element with ID #task. 01:09:03.550 --> 01:09:04.899 That's the input field. 01:09:04.899 --> 01:09:07.210 .value gets the value of the input field, 01:09:07.210 --> 01:09:10.000 which is what the user actually typed in. 01:09:10.000 --> 01:09:13.689 And I can save that as, like, const task. 01:09:13.689 --> 01:09:17.109 That is what it is the user typed in. 01:09:17.109 --> 01:09:19.270 And if I'm curious as to what the user typed in, 01:09:19.270 --> 01:09:22.930 I can actually print it out to the JavaScript console. 01:09:22.930 --> 01:09:26.995 And the way to do that is using a special function called console.log. 01:09:26.995 --> 01:09:28.870 And that just logs something to the console-- 01:09:28.870 --> 01:09:30.790 the equivalent of printing something out in Python, 01:09:30.790 --> 01:09:32.707 where it just shows up in the Python terminal. 01:09:32.707 --> 01:09:36.160 Here, this is going to show up in the JavaScript console. 01:09:36.160 --> 01:09:38.020 And one other thing I'll add is by default, 01:09:38.020 --> 01:09:40.640 forms will try and submit when you press the Submit button, 01:09:40.640 --> 01:09:41.968 like take you to another page. 01:09:41.968 --> 01:09:44.260 We've seen this before already in the context of Django 01:09:44.260 --> 01:09:47.680 that when you submit a form it tries and submits another web request. 01:09:47.680 --> 01:09:50.779 If I want to prevent that behavior, stop the form from submitting, 01:09:50.779 --> 01:09:55.360 so stop form from submitting, I can return 01:09:55.360 --> 01:09:58.360 false at the end of my forum submission handler 01:09:58.360 --> 01:10:00.003 to say don't actually submit the form. 01:10:00.003 --> 01:10:02.170 We're going to do everything client side, everything 01:10:02.170 --> 01:10:04.070 just inside of the browser. 01:10:04.070 --> 01:10:06.778 So now, this won't quite work yet, but it will be progress. 01:10:06.778 --> 01:10:07.570 I refresh the page. 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. 01:10:10.612 --> 01:10:14.590 If I add a task, something just like foo, press Submit, 01:10:14.590 --> 01:10:17.230 this now gets logged to the JavaScript console. 01:10:17.230 --> 01:10:19.030 It's the equivalent of a way of providing 01:10:19.030 --> 01:10:21.370 debugging information to myself to know, all right, 01:10:21.370 --> 01:10:24.022 I now have access to this value foo. 01:10:24.022 --> 01:10:26.230 And it's also telling me what line of code logged it. 01:10:26.230 --> 01:10:30.683 It was tasks.html line 9 is the line of code that logged foo. 01:10:30.683 --> 01:10:33.100 And so this can be useful when you're debugging a program. 01:10:33.100 --> 01:10:35.500 When you want to see what the values of variables are, 01:10:35.500 --> 01:10:38.065 you can just print them out using console.log 01:10:38.065 --> 01:10:39.940 to figure out what's going on in your program 01:10:39.940 --> 01:10:42.890 at any particular point in time. 01:10:42.890 --> 01:10:45.070 But what I want to do is not console.log it. 01:10:45.070 --> 01:10:47.830 What I want to do is really create a new element 01:10:47.830 --> 01:10:51.640 that I'm going to add into my body of the HTML. 01:10:51.640 --> 01:10:52.970 So how can I do that? 01:10:52.970 --> 01:10:55.270 Well, to create a new element for my document, 01:10:55.270 --> 01:10:59.290 I can run a function called document.createElement 01:10:59.290 --> 01:11:02.170 followed by what type of element do I want to create. 01:11:02.170 --> 01:11:04.870 Well, I have an unordered list-- a ul-- 01:11:04.870 --> 01:11:09.340 and every item inside of an unordered list is a list item-- an li. 01:11:09.340 --> 01:11:14.020 So I'll go ahead and create an li element, a list item. 01:11:14.020 --> 01:11:18.340 And I'll save that in a variable that I'll call li. 01:11:18.340 --> 01:11:20.440 So I've created a new list item. 01:11:20.440 --> 01:11:22.930 And this list item's innerHTML-- 01:11:22.930 --> 01:11:26.260 the HTML content inside of that list item-- 01:11:26.260 --> 01:11:28.600 well, that's just going to be task-- 01:11:28.600 --> 01:11:32.390 this variable from up here, which is whatever the user typed in. 01:11:32.390 --> 01:11:35.440 So I've now created a new list item and said what 01:11:35.440 --> 01:11:37.460 HTML should go inside of the list item. 01:11:37.460 --> 01:11:40.210 It should be whatever task the user typed in. 01:11:40.210 --> 01:11:45.670 And now, I'm going to say document.querySelector #tasks. 01:11:45.670 --> 01:11:48.130 Get me the element whose ID is tasks, and that's 01:11:48.130 --> 01:11:52.460 going to be this unordered list here-- the unordered list whose ID is tasks. 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 01:11:57.610 --> 01:12:01.000 .append li. 01:12:01.000 --> 01:12:03.130 And what that now is going to do is it's going 01:12:03.130 --> 01:12:05.770 to say get me the unordered list whose ID is tasks. 01:12:05.770 --> 01:12:09.010 Get me the element whose ID is tasks via querySelector here. 01:12:09.010 --> 01:12:11.740 Once I have that element, append to the end 01:12:11.740 --> 01:12:14.800 of what's inside of that element, this value 01:12:14.800 --> 01:12:19.240 li, which happens to be this new element that I've created-- a new list item. 01:12:19.240 --> 01:12:21.850 So I've been able to add a new HTML element. 01:12:21.850 --> 01:12:23.830 And this line of code is going to say add it 01:12:23.830 --> 01:12:30.110 to the DOM-- add it to the unordered list that I'm here now constructing. 01:12:30.110 --> 01:12:32.590 So now, I rerun this. 01:12:32.590 --> 01:12:33.250 I see tasks. 01:12:33.250 --> 01:12:34.720 I type in something like foo. 01:12:34.720 --> 01:12:35.967 I press Submit. 01:12:35.967 --> 01:12:37.300 And all right, foo now shows up. 01:12:37.300 --> 01:12:41.380 I type in something like-- or I delete that, type in bar, bar now shows up. 01:12:41.380 --> 01:12:42.380 I type in baz. 01:12:42.380 --> 01:12:43.540 Baz now shows up. 01:12:43.540 --> 01:12:45.490 Now, one minor user interface annoyance is 01:12:45.490 --> 01:12:47.920 that it seems that every time I submit a new task, 01:12:47.920 --> 01:12:51.650 this input field retains the value of what it used to be. 01:12:51.650 --> 01:12:54.700 And that's probably not what I want because I'd rather it just clear out. 01:12:54.700 --> 01:12:56.033 I've already submitted the task. 01:12:56.033 --> 01:12:57.400 No need for it to stay there. 01:12:57.400 --> 01:12:59.500 But that's easy to manipulate in JavaScript. 01:12:59.500 --> 01:13:01.690 If I want to clear out this input field-- 01:13:01.690 --> 01:13:03.990 the input field whose ID is task-- 01:13:03.990 --> 01:13:09.160 then all I need to do is say document.querySelector task-- 01:13:09.160 --> 01:13:10.750 get me that input field-- 01:13:10.750 --> 01:13:14.290 change its value equal to the empty string-- 01:13:14.290 --> 01:13:17.140 equal to nothing just to say clear out the value 01:13:17.140 --> 01:13:20.140 of what happens to be inside of that input field right now. 01:13:20.140 --> 01:13:23.650 And now if I refresh the page, type in foo, press Submit, 01:13:23.650 --> 01:13:27.220 input field clears out and now I can type in something like bar, 01:13:27.220 --> 01:13:31.185 and then something like baz to continue to add tasks as well. 01:13:31.185 --> 01:13:34.060 Now, one thing that might be slightly annoying is if I'm not careful, 01:13:34.060 --> 01:13:38.530 if I press Submit, well, it submits the empty string as a task, 01:13:38.530 --> 01:13:41.530 and so I just get this empty bullet point that shows up here. 01:13:41.530 --> 01:13:44.650 I press Submit, and I just get all of these empty bullet points. 01:13:44.650 --> 01:13:47.200 It might be nice from a user experience perspective 01:13:47.200 --> 01:13:49.270 if I were to not allow the user to do that, 01:13:49.270 --> 01:13:52.600 not allow them to submit a task if they haven't actually typed something 01:13:52.600 --> 01:13:54.730 in to the new task field. 01:13:54.730 --> 01:13:57.880 And we can do that just by modifying properties of elements. 01:13:57.880 --> 01:14:01.780 It turns out that HTML elements have a property called disabled 01:14:01.780 --> 01:14:07.220 that can be true or false that allows us to disable something like a button. 01:14:07.220 --> 01:14:09.880 So if I want to disable the Submit button, 01:14:09.880 --> 01:14:13.490 one thing I might want to do first is give this Submit button an ID. 01:14:13.490 --> 01:14:17.110 I'll give it an ID of submit, so that in my JavaScript code, 01:14:17.110 --> 01:14:20.110 I can reference the Submit button. 01:14:20.110 --> 01:14:26.140 And now inside of this JavaScript code, when the DOM content is loaded, 01:14:26.140 --> 01:14:31.390 by default, the Submit button should be disabled. 01:14:31.390 --> 01:14:34.198 Like when I first load the page, I don't want the Submit button 01:14:34.198 --> 01:14:36.490 to be enabled because I want the user to type in a task 01:14:36.490 --> 01:14:38.990 first before I enable the Submit button. 01:14:38.990 --> 01:14:40.520 So how do I do that? 01:14:40.520 --> 01:14:44.410 Well, I can document.querySelector get me the element whose ID is submit. 01:14:44.410 --> 01:14:49.240 Get me that Submit button, and just set its disabled property equal to true. 01:14:49.240 --> 01:14:51.400 JavaScript has Boolean values true and false. 01:14:51.400 --> 01:14:56.270 I set the disabled value equal to true to disable the Submit button. 01:14:56.270 --> 01:14:58.863 Now if I refresh the page, I can type in a new task, 01:14:58.863 --> 01:15:00.280 but the Submit button is disabled. 01:15:00.280 --> 01:15:01.238 It doesn't do anything. 01:15:01.238 --> 01:15:03.072 Obviously, I don't want to keep it that way. 01:15:03.072 --> 01:15:05.350 I'd like it such that as I begin to type things in, 01:15:05.350 --> 01:15:07.780 then the Submit button stops being disabled. 01:15:07.780 --> 01:15:11.450 Disabled gets set from true to false instead. 01:15:11.450 --> 01:15:14.890 And so what I really want to do is listen for me, 01:15:14.890 --> 01:15:17.900 like, pressing keys on the keyboard. 01:15:17.900 --> 01:15:22.210 And so the way I can do that is by adding yet another event listener. 01:15:22.210 --> 01:15:26.350 document.querySelector-- what do I want to add a querySelector to? 01:15:26.350 --> 01:15:28.435 What I want to add an event handler for? 01:15:28.435 --> 01:15:30.310 Well, I want to add an event handler for when 01:15:30.310 --> 01:15:32.950 I type something into this input field. 01:15:32.950 --> 01:15:36.110 And this input field has an ID of task. 01:15:36.110 --> 01:15:40.150 So let me go ahead and get the input field-- the element whose ID is task-- 01:15:40.150 --> 01:15:42.880 and add an onkeyup handler. 01:15:42.880 --> 01:15:48.130 onkeyup, again, is the event when I lift my finger off of a key, 01:15:48.130 --> 01:15:50.590 go ahead and run this function. 01:15:50.590 --> 01:15:52.070 And what should the function do? 01:15:52.070 --> 01:15:55.570 Well, it's going to say document.querySelector #submit, set 01:15:55.570 --> 01:15:59.210 the disabled property equal to false. 01:15:59.210 --> 01:16:00.790 And so now, here's what we're doing. 01:16:00.790 --> 01:16:04.680 We're saying by default when I first load the page, take the Submit button 01:16:04.680 --> 01:16:05.670 and disable it. 01:16:05.670 --> 01:16:08.010 Set .disabled equal to true. 01:16:08.010 --> 01:16:11.190 Then anytime I type a key and my finger comes off 01:16:11.190 --> 01:16:16.090 the key, that means onkeyup is the event that gets triggered, run this function. 01:16:16.090 --> 01:16:19.470 And what the function is going to do is take that same Submit button 01:16:19.470 --> 01:16:21.970 and set its disabled property equal to false. 01:16:21.970 --> 01:16:24.570 So now instead of being disabled, it will be enabled. 01:16:27.250 --> 01:16:30.840 So if I go back to the page, and go here, right now by default, 01:16:30.840 --> 01:16:34.980 the Submit button is disabled, but as soon as I start typing something, 01:16:34.980 --> 01:16:39.307 now the Submit button is active and I can actually click on it. 01:16:39.307 --> 01:16:41.640 And all right, this isn't great because I clicked on it, 01:16:41.640 --> 01:16:43.420 but the Submit button is still enabled. 01:16:43.420 --> 01:16:46.020 So what I might like to do is after I've submitted 01:16:46.020 --> 01:16:48.240 the form, after I've added a new task, let's 01:16:48.240 --> 01:16:50.410 go back and disable the Submit button. 01:16:50.410 --> 01:16:54.570 So after I've submitted the form, after we've 01:16:54.570 --> 01:16:57.660 added the new task to my list of tasks, after we've cleared out 01:16:57.660 --> 01:17:03.510 the value from the input field, let me also get the Submit button, 01:17:03.510 --> 01:17:06.540 set its disabled property equal to true. 01:17:06.540 --> 01:17:09.240 Now even after I submit the form, the Submit button 01:17:09.240 --> 01:17:13.530 is still going to be disabled, such that I type in foo, now submit is active. 01:17:13.530 --> 01:17:14.430 I press it. 01:17:14.430 --> 01:17:18.003 The Submit button goes back to being inactive as well. 01:17:18.003 --> 01:17:20.670 It turns out that even now, there's still a little bit of a bug. 01:17:20.670 --> 01:17:23.490 If I go back here and I type in something like bar, 01:17:23.490 --> 01:17:27.363 but then I backspace back to, like, nothing here, 01:17:27.363 --> 01:17:28.780 the Submit button is still active. 01:17:28.780 --> 01:17:33.100 So I can still technically submit a task that has no content inside of it. 01:17:33.100 --> 01:17:36.367 And so I might like to have some way of preventing against that as well. 01:17:36.367 --> 01:17:37.950 And that's just some additional logic. 01:17:37.950 --> 01:17:40.260 We now have access to JavaScript that has conditions, 01:17:40.260 --> 01:17:42.510 that has loops, that has functions. 01:17:42.510 --> 01:17:47.250 And so if I want to do something like conditionally check, 01:17:47.250 --> 01:17:57.200 I can say if document.querySelector #task .value.length is greater than 0, 01:17:57.200 --> 01:18:00.650 meaning like something is actually typed in to the task field, 01:18:00.650 --> 01:18:09.610 we'll then go ahead and set disabled to false, but otherwise, 01:18:09.610 --> 01:18:13.160 go ahead and set disabled equal to true. 01:18:13.160 --> 01:18:14.410 So now here, we're checking. 01:18:14.410 --> 01:18:17.290 If the length of what the user has typed in is greater than 0, 01:18:17.290 --> 01:18:19.600 they actually typed something in, then yes, 01:18:19.600 --> 01:18:22.510 give them access to the Submit button, but otherwise, 01:18:22.510 --> 01:18:25.040 don't give them access to that button. 01:18:25.040 --> 01:18:26.500 So now, I refresh the page. 01:18:26.500 --> 01:18:28.540 Disabled by default. I type something in. 01:18:28.540 --> 01:18:29.380 It's enabled. 01:18:29.380 --> 01:18:33.310 I delete, delete, delete, and it goes back to being disabled. 01:18:33.310 --> 01:18:35.410 So JavaScript has allowed us to really make 01:18:35.410 --> 01:18:38.500 our pages much more interactive and immediately interactive 01:18:38.500 --> 01:18:40.990 based on how the user is interacting with the page. 01:18:40.990 --> 01:18:44.500 As they begin to type things, as they begin to delete things, 01:18:44.500 --> 01:18:47.710 as they press buttons, we're able to have the page respond either 01:18:47.710 --> 01:18:51.550 by adding content to the DOM by literally adding parts to the HTML 01:18:51.550 --> 01:18:53.980 page, changing the styles of things, changing 01:18:53.980 --> 01:18:55.690 particular properties of elements. 01:18:55.690 --> 01:18:58.120 And this is really where the power of JavaScript 01:18:58.120 --> 01:19:02.700 begins to come in is in allowing ourselves to do things like that. 01:19:02.700 --> 01:19:04.900 Now so far, we've only been able to have events 01:19:04.900 --> 01:19:08.980 happen when the user does something-- when the user clicks on a button 01:19:08.980 --> 01:19:11.200 or when the user presses a key, for example. 01:19:11.200 --> 01:19:14.530 But it turns out JavaScript has other ways of allowing functions 01:19:14.530 --> 01:19:15.828 to run in fact on their own. 01:19:15.828 --> 01:19:17.620 We can set what are called intervals, where 01:19:17.620 --> 01:19:22.130 a particular function runs every some number of milliseconds, for example. 01:19:22.130 --> 01:19:25.900 And so if we go back to like the counter example from before, right now 01:19:25.900 --> 01:19:28.330 for this counter example, I have to be the one 01:19:28.330 --> 01:19:31.720 to press the count button that is going to increment the value of count 01:19:31.720 --> 01:19:36.290 every single time, but I could put that inside of an interval instead. 01:19:36.290 --> 01:19:42.860 So let me go back to counter.html, whose JavaScript is inside of counter.js. 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, 01:19:50.550 --> 01:19:58.210 let me set an interval for count and 1,000. 01:19:58.210 --> 01:19:59.470 So what is that going to do? 01:19:59.470 --> 01:20:02.260 setInterval is a function built into JavaScript here, 01:20:02.260 --> 01:20:05.380 where I'm saying that I would like to create a new interval where every so 01:20:05.380 --> 01:20:08.210 often, go ahead and run a particular function. 01:20:08.210 --> 01:20:10.210 And I would like to run the count function. 01:20:10.210 --> 01:20:13.570 We'll recall that count function is going to increment the value of count. 01:20:13.570 --> 01:20:16.070 And I'll get rid of this alert for now, just for simplicity. 01:20:16.070 --> 01:20:18.970 All I want the count function to do is update the h1 01:20:18.970 --> 01:20:21.160 with the new value of the counter and go ahead 01:20:21.160 --> 01:20:24.550 and run that count function every 1,000 milliseconds, otherwise known 01:20:24.550 --> 01:20:28.970 as every 1 second, go ahead and run the count function. 01:20:28.970 --> 01:20:34.510 So now when I open counter.html, it's 0, but every second now, it's 01:20:34.510 --> 01:20:37.305 going to change-- every second, updating one by one by one. 01:20:37.305 --> 01:20:38.680 I don't have to click the button. 01:20:38.680 --> 01:20:41.150 Of course, I could and the event handler would still work, 01:20:41.150 --> 01:20:44.530 but the interval is saying now every one second, 01:20:44.530 --> 01:20:46.120 go ahead and run the count function. 01:20:46.120 --> 01:20:47.830 And that has this particular result. 01:20:47.830 --> 01:20:51.100 So if you've ever seen a web page that displays the current time in seconds 01:20:51.100 --> 01:20:53.860 and it was like a countdown timer or it was displaying the current time 01:20:53.860 --> 01:20:56.080 with seconds, it might be doing something like this, 01:20:56.080 --> 01:20:58.900 just having some sort of interval that every second is 01:20:58.900 --> 01:21:01.060 going to count and increment in order to say 01:21:01.060 --> 01:21:05.680 update the number to the one greater, one greater, and one greater than that. 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, 01:21:10.060 --> 01:21:14.470 and then open counter.html again, I've gone back to 0. 01:21:14.470 --> 01:21:18.010 Like, JavaScript is not saving any state about my page. 01:21:18.010 --> 01:21:20.410 It's just every time we're running the page, 01:21:20.410 --> 01:21:23.553 it's going to go back to counter.js, it's going to say, 01:21:23.553 --> 01:21:25.720 all right, we're defining a variable called counter, 01:21:25.720 --> 01:21:27.860 we're setting that variable equal to 0. 01:21:27.860 --> 01:21:31.180 So every time I load the page, it's going to be set back to 0. 01:21:31.180 --> 01:21:33.810 And that might not be great depending on the type of page 01:21:33.810 --> 01:21:34.810 you're trying to create. 01:21:34.810 --> 01:21:38.770 Maybe you want to page that is somehow able to store information, 01:21:38.770 --> 01:21:42.430 such as that on subsequent visits, we're able to utilize the information that 01:21:42.430 --> 01:21:46.890 was already stored-- some way of remembering information for later use. 01:21:46.890 --> 01:21:49.480 In later versions of JavaScript and more modern browsers 01:21:49.480 --> 01:21:53.350 now allow us to do something just like that called localStorage. 01:21:53.350 --> 01:21:55.690 And what localStorage is is it's a way for us 01:21:55.690 --> 01:21:59.320 to be able to store information inside of the user's web browser-- 01:21:59.320 --> 01:22:03.820 that a page can ask to store particular values inside the web browser and later 01:22:03.820 --> 01:22:06.040 on, on subsequent visits to that page, we 01:22:06.040 --> 01:22:09.370 can go back and say let's extract those values that were previously 01:22:09.370 --> 01:22:12.580 stored inside of localStorage. 01:22:12.580 --> 01:22:15.580 localStorage is going to give us access to two key functions 01:22:15.580 --> 01:22:18.310 that we're going to use to manipulate this localStorage. 01:22:18.310 --> 01:22:20.950 The first is localStorage.getItem, where we 01:22:20.950 --> 01:22:23.560 would like to get something out of localStorage based 01:22:23.560 --> 01:22:26.500 on its key-- some name that we have given to that value. 01:22:26.500 --> 01:22:29.740 And we also have access to localStorage.setItem, 01:22:29.740 --> 01:22:32.170 which goes ahead and adds a new value to localStorage 01:22:32.170 --> 01:22:34.720 or replaces an existing value in localStorage, 01:22:34.720 --> 01:22:38.590 setting this key equal to a particular value. 01:22:38.590 --> 01:22:42.880 So we can use localStorage then to allow our web pages, using JavaScript, 01:22:42.880 --> 01:22:46.940 to be able to store information and retrieve information from the browser. 01:22:46.940 --> 01:22:50.380 And let's now try to use that in order to solve 01:22:50.380 --> 01:22:55.600 this problem of the counter that seems to always reset back to 0. 01:22:55.600 --> 01:22:59.260 So now in counter.js, instead of setting counter equal to 0, 01:22:59.260 --> 01:23:02.230 the first thing I want to know is is there already 01:23:02.230 --> 01:23:05.440 a value for the counter in localStorage? 01:23:05.440 --> 01:23:12.880 So I can ask a question like if localStorage.getItem counter, meaning 01:23:12.880 --> 01:23:17.500 go to local storage, try and get the counter, and anything in this 01:23:17.500 --> 01:23:21.610 if expression will happen if there is something inside of localStorage 01:23:21.610 --> 01:23:22.690 for counter. 01:23:22.690 --> 01:23:25.588 But it turns out that if I want to do the inverse of that, say not, 01:23:25.588 --> 01:23:27.130 I can just use the exclamation point. 01:23:27.130 --> 01:23:30.810 Much like in C, in JavaScript, the exclamation point just means not. 01:23:30.810 --> 01:23:34.060 So meaning if there is not something in localStorage 01:23:34.060 --> 01:23:36.430 called counter, well, then let's go ahead 01:23:36.430 --> 01:23:42.430 and just set the value in localStorage. localStorage.setItem counter, 01:23:42.430 --> 01:23:44.600 and we'll set it equal to 0. 01:23:44.600 --> 01:23:47.680 So what this is doing here is before anything else happens, 01:23:47.680 --> 01:23:52.840 we are checking localStorage to say is there already a value for counter. 01:23:52.840 --> 01:23:54.840 And if there is not already a value for counter, 01:23:54.840 --> 01:23:57.673 we need to make sure there is something there inside of localStorage 01:23:57.673 --> 01:23:58.610 for the counter. 01:23:58.610 --> 01:24:03.663 So we are going to set the value of counter equal to 0, for example. 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, 01:24:06.830 --> 01:24:08.810 so that it only happens when I click on it. 01:24:08.810 --> 01:24:11.720 But what should this count function actually do? 01:24:11.720 --> 01:24:14.710 Well, first, let me get the value of the counter. 01:24:14.710 --> 01:24:20.110 Counter is going to be whatever localStorage.getItem is. 01:24:20.110 --> 01:24:23.230 I'm going to get the counter out of localStorage. 01:24:23.230 --> 01:24:26.020 I'm going to increment it, counter++. 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 01:24:30.370 --> 01:24:31.690 counter. 01:24:31.690 --> 01:24:37.900 But the last step is I'll also do localStorage.setItem counter is 01:24:37.900 --> 01:24:41.170 equal to the new value of counter. 01:24:41.170 --> 01:24:44.260 So what I've done here is to say that when I click the button, 01:24:44.260 --> 01:24:45.970 count function is going to run. 01:24:45.970 --> 01:24:47.920 We're first going to go into localStorage, 01:24:47.920 --> 01:24:50.380 get the value for the key counter. 01:24:50.380 --> 01:24:52.230 Whatever the value of counter happens to be, 01:24:52.230 --> 01:24:54.408 save it inside of this variable called counter. 01:24:54.408 --> 01:24:56.200 We'll go ahead and increment that variable, 01:24:56.200 --> 01:25:00.670 setting it equal to itself plus 1, update the h1's innerHTML same 01:25:00.670 --> 01:25:03.710 as before, just to update what we actually see on the page, 01:25:03.710 --> 01:25:07.850 but then go ahead and localStorage.setItem counter 01:25:07.850 --> 01:25:11.360 gets set to counter, for example. 01:25:11.360 --> 01:25:17.440 So now, let's go ahead and see what's going to happen. 01:25:17.440 --> 01:25:22.840 If I go ahead and open counter.html, we see 0. 01:25:22.840 --> 01:25:24.530 We count 1, 2, 3, 4, 5. 01:25:24.530 --> 01:25:26.230 Everything so far, so good. 01:25:26.230 --> 01:25:28.870 Now, watch what happens if I refresh this page. 01:25:28.870 --> 01:25:30.422 I refresh the page. 01:25:30.422 --> 01:25:32.380 And all right, that seems a little bit strange. 01:25:32.380 --> 01:25:33.312 It's 0. 01:25:33.312 --> 01:25:35.020 Let me try counting and see what happens. 01:25:35.020 --> 01:25:36.560 I press count. 01:25:36.560 --> 01:25:38.765 And all right, the count change to 6. 01:25:38.765 --> 01:25:41.140 So it seems like it did remember that I counted up to 5-- 01:25:41.140 --> 01:25:42.313 0, 1, 2, 3, 4, 5. 01:25:42.313 --> 01:25:44.230 But when I refreshed the page, it still showed 01:25:44.230 --> 01:25:46.900 me 0, but then let me count up to the number 6. 01:25:46.900 --> 01:25:49.025 And now, I can keep counting 7, 8, 9, 10. 01:25:49.025 --> 01:25:50.650 What happens if I refresh the page now? 01:25:50.650 --> 01:25:51.220 I can try it. 01:25:51.220 --> 01:25:52.630 I refresh the page. 01:25:52.630 --> 01:25:55.300 I've gone back to 0, but I count-- 01:25:55.300 --> 01:25:56.440 and OK, now, I'm at 11. 01:25:56.440 --> 01:25:59.060 So somehow, I am still remembering, but the first time, it's 01:25:59.060 --> 01:26:00.760 still giving me 0 every time. 01:26:00.760 --> 01:26:02.600 Why might that be? 01:26:02.600 --> 01:26:04.900 Well, if you look back at counter.html, you'll 01:26:04.900 --> 01:26:07.690 notice that the reason is just inside the body of the page. 01:26:07.690 --> 01:26:10.720 The initial value of h1 is just always 0. 01:26:10.720 --> 01:26:12.850 So if I want to fix that, then what I need to say 01:26:12.850 --> 01:26:15.310 is when the DOM content is loaded, go ahead 01:26:15.310 --> 01:26:19.010 and get document.querySelector h1. 01:26:19.010 --> 01:26:25.990 Go ahead and update the innerHTML equal to whatever localStorage.getItem 01:26:25.990 --> 01:26:28.120 counter happens to be. 01:26:28.120 --> 01:26:31.360 So every time I open the page, even before I click the button, 01:26:31.360 --> 01:26:33.580 even before the event listener is triggered, 01:26:33.580 --> 01:26:35.860 I'd like to say, go ahead and replace this heading, 01:26:35.860 --> 01:26:40.540 update its innerHTML to be the result of getting the counter out 01:26:40.540 --> 01:26:43.070 of localStorage, for example. 01:26:43.070 --> 01:26:45.696 So now if I refresh the page, it's at 11. 01:26:45.696 --> 01:26:47.360 I can update, update, update. 01:26:47.360 --> 01:26:49.390 Click again some number of times. 01:26:49.390 --> 01:26:51.010 Bring it up to 18, for example. 01:26:51.010 --> 01:26:53.490 Refresh the page, and it stays at the number 18. 01:26:53.490 --> 01:26:55.420 And no matter what value I get it to, it's 01:26:55.420 --> 01:26:58.360 going to store that number inside of local storage, such 01:26:58.360 --> 01:27:01.470 that when I refresh the page, that number is going to stay there. 01:27:01.470 --> 01:27:04.410 And we can actually see the value inside of localStorage 01:27:04.410 --> 01:27:06.880 by, again, going into Chrome's inspector. 01:27:06.880 --> 01:27:08.230 I go into Chrome. 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, 01:27:14.360 --> 01:27:17.740 I can see that I have a value for key counter, whose value in this case 01:27:17.740 --> 01:27:18.680 happens to be 28. 01:27:18.680 --> 01:27:19.900 And you could go into local storage. 01:27:19.900 --> 01:27:21.250 You could manipulate this value. 01:27:21.250 --> 01:27:22.510 You could delete it if you want. 01:27:22.510 --> 01:27:24.468 But this just goes to show you that we have now 01:27:24.468 --> 01:27:28.600 stored this value inside of my browser, such that on subsequent visits 01:27:28.600 --> 01:27:32.530 if this page gets loaded again, we can access that value from inside 01:27:32.530 --> 01:27:34.840 of the application as well. 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 01:27:38.258 --> 01:27:41.050 in order to just make the user experience a little bit better if we 01:27:41.050 --> 01:27:43.870 want the user to be able to have information remembered 01:27:43.870 --> 01:27:47.320 from the last time they visited a particular page, which can sometimes 01:27:47.320 --> 01:27:49.957 actually be quite helpful. 01:27:49.957 --> 01:27:52.540 All right, so now, we've seen a lot of features of JavaScript. 01:27:52.540 --> 01:27:55.010 We've seen a bunch of different ways of representing data. 01:27:55.010 --> 01:27:59.410 We stored data in variables, and those variables have had types like integers. 01:27:59.410 --> 01:28:01.360 Those variables have sometimes been strings. 01:28:01.360 --> 01:28:03.100 Sometimes, they've been HTML elements. 01:28:03.100 --> 01:28:06.075 Sometimes, they've been arrays or lists of items. 01:28:06.075 --> 01:28:07.700 Sometimes, they've even been functions. 01:28:07.700 --> 01:28:09.790 We can set a variable equal to a function. 01:28:09.790 --> 01:28:14.020 But perhaps one of the most useful data types inside of JavaScript 01:28:14.020 --> 01:28:16.240 is the JavaScript object. 01:28:16.240 --> 01:28:18.990 So I'll go into the JavaScript console just to demonstrate this. 01:28:18.990 --> 01:28:21.640 What the JavaScript object is is it's really 01:28:21.640 --> 01:28:24.460 the equivalent of, like, a Python dictionary-- 01:28:24.460 --> 01:28:27.340 some association of keys to values, where 01:28:27.340 --> 01:28:30.100 you can look up something by a key or by a property 01:28:30.100 --> 01:28:33.530 and see what its value happens to be. 01:28:33.530 --> 01:28:36.160 So if I had a variable like person, I could 01:28:36.160 --> 01:28:41.260 set person equal to a JavaScript object, whose first name is 01:28:41.260 --> 01:28:45.700 Harry and whose last name is Potter, again, 01:28:45.700 --> 01:28:49.810 using syntax very similar to what the dictionary syntax looks 01:28:49.810 --> 01:28:52.480 like inside of Python as well. 01:28:52.480 --> 01:28:55.510 And now that I have this variable person, which is first 01:28:55.510 --> 01:28:58.623 Harry, last Potter, I can access a particular property 01:28:58.623 --> 01:29:00.040 of the person in a number of ways. 01:29:00.040 --> 01:29:03.610 I can say something like person.first to say get me the first named 01:29:03.610 --> 01:29:06.230 property of this particular object. 01:29:06.230 --> 01:29:07.900 And I see that it's equal to Harry. 01:29:07.900 --> 01:29:11.140 I could equivalently use square bracket notation the way Python does. 01:29:11.140 --> 01:29:14.800 Square bracket first, and that will also give me Harry. 01:29:14.800 --> 01:29:17.350 But this turns out to be quite powerful to be 01:29:17.350 --> 01:29:19.840 able to represent data in this structured way 01:29:19.840 --> 01:29:22.120 like this, where I have an association of keys 01:29:22.120 --> 01:29:25.180 or otherwise known as properties with particular values. 01:29:25.180 --> 01:29:28.030 And then I have the ability given a JavaScript object, 01:29:28.030 --> 01:29:30.640 to be able to access a particular value. 01:29:30.640 --> 01:29:33.340 And it turns out that one of the ways this is most useful 01:29:33.340 --> 01:29:38.420 is in the exchange of data-- moving data around from one service to another. 01:29:38.420 --> 01:29:42.010 And so here, we're going to introduce what are known as APIs, otherwise known 01:29:42.010 --> 01:29:45.940 as Application Programming Interfaces, which in the context of the web, 01:29:45.940 --> 01:29:49.690 you can think of as some well-defined structured way for services 01:29:49.690 --> 01:29:52.390 on the internet to communicate with each other. 01:29:52.390 --> 01:29:56.020 If you want your application to be able to talk to some other service-- 01:29:56.020 --> 01:29:58.745 maybe you want your application to interact with Google Maps, 01:29:58.745 --> 01:30:01.870 or to be able to interact with Amazon, or some other weather service to get 01:30:01.870 --> 01:30:02.860 the day's weather-- 01:30:02.860 --> 01:30:06.370 then you might be able to access some API, some mechanism whereby 01:30:06.370 --> 01:30:09.910 you can communicate with another service by sending a request 01:30:09.910 --> 01:30:13.780 and receiving back data in some sort of very well-structured format. 01:30:13.780 --> 01:30:17.560 And very often, that well-structured format happens to be a particular type 01:30:17.560 --> 01:30:22.180 of data known as JSON, which stands for JavaScript Object Notation, 01:30:22.180 --> 01:30:27.040 which is a way of transferring data in the form of JavaScript objects-- 01:30:27.040 --> 01:30:30.880 these sort of objects that happen to have properties and values 01:30:30.880 --> 01:30:32.630 associated with them. 01:30:32.630 --> 01:30:34.880 And so what does JavaScript Object Notation look like? 01:30:34.880 --> 01:30:37.755 Well, if we think back to the applications that we've been creating-- 01:30:37.755 --> 01:30:40.720 these applications that are able to represent things like an airline 01:30:40.720 --> 01:30:44.320 and movements of planes between particular destinations-- 01:30:44.320 --> 01:30:48.640 a JavaScript object representing a flight might look something like this-- 01:30:48.640 --> 01:30:52.210 a JavaScript object that has properties for origin is something, 01:30:52.210 --> 01:30:56.260 destination is something, duration is something-- things we've seen before. 01:30:56.260 --> 01:30:58.750 But you might imagine that if we wanted our airline 01:30:58.750 --> 01:31:01.390 to be able to make its data available to other services, 01:31:01.390 --> 01:31:04.120 so that other web applications or other programs 01:31:04.120 --> 01:31:07.210 could programmatically access information about flights, 01:31:07.210 --> 01:31:11.560 we could pass data in this format to those other applications 01:31:11.560 --> 01:31:14.680 so that they could then treat this as a JavaScript object 01:31:14.680 --> 01:31:16.810 and get access to the information about it. 01:31:16.810 --> 01:31:19.540 And the nice thing about this particular representation 01:31:19.540 --> 01:31:22.660 is that it is both human-readable and machine-readable-- 01:31:22.660 --> 01:31:25.990 that we as people can look at this and get an intuitive understanding for what 01:31:25.990 --> 01:31:28.720 all of this means, but also a computer knows 01:31:28.720 --> 01:31:31.750 how to access particular properties that appear before the colon 01:31:31.750 --> 01:31:36.820 and get access to what those values are, which appear after the colon as well. 01:31:36.820 --> 01:31:40.060 So JavaScript Object Notation, otherwise known as JSON, 01:31:40.060 --> 01:31:42.370 offers a very convenient representation. 01:31:42.370 --> 01:31:45.820 And this isn't exactly what the JavaScript object syntax is. 01:31:45.820 --> 01:31:48.730 In JavaScript objects, you don't strictly need the quotation marks 01:31:48.730 --> 01:31:49.490 around the keys. 01:31:49.490 --> 01:31:52.750 You could just say origin colon and not origin in quotation marks. 01:31:52.750 --> 01:31:56.390 So JavaScript Object Notation uses slightly different syntax, 01:31:56.390 --> 01:31:59.560 but ultimately very reminiscent of what we've seen in JavaScript objects. 01:31:59.560 --> 01:32:02.410 And JavaScript knows how to take data in this form 01:32:02.410 --> 01:32:04.663 and turn it into something like a JavaScript object. 01:32:04.663 --> 01:32:07.330 And it turns out there are ways of doing this in Python as well. 01:32:07.330 --> 01:32:09.610 Other programming languages have the ability 01:32:09.610 --> 01:32:14.040 to interpret JSON data in order to use it in some meaningful way. 01:32:14.040 --> 01:32:16.840 And another advantage of the JSON representation 01:32:16.840 --> 01:32:20.140 is it is very conducive to representing structures of things. 01:32:20.140 --> 01:32:23.350 So these values don't just need to be strings or numbers. 01:32:23.350 --> 01:32:25.660 They could be lists, or arrays that happen 01:32:25.660 --> 01:32:28.480 to have a sequence of possible values, or they could even 01:32:28.480 --> 01:32:32.620 be other JavaScript objects that if we wanted to represent not just the city 01:32:32.620 --> 01:32:35.620 name, but represent the city name and the airport code, 01:32:35.620 --> 01:32:38.200 for example, as we saw that we wanted to do before, 01:32:38.200 --> 01:32:42.280 I could, instead of having origin be equal to a string like New York, 01:32:42.280 --> 01:32:47.170 have origin be equal to yet another JavaScript object that contains a city 01:32:47.170 --> 01:32:50.560 property and a code property, where the city is the name of the city 01:32:50.560 --> 01:32:52.930 and the code is the name in the airport code. 01:32:52.930 --> 01:32:55.480 And the important thing is as long as I and the person 01:32:55.480 --> 01:32:58.450 I'm communicating with agree upon this representation, 01:32:58.450 --> 01:33:02.920 agree upon what the names of these keys are and what the structure of this JSON 01:33:02.920 --> 01:33:07.450 payload, this JSON object happens to be, then the person on the receiving end 01:33:07.450 --> 01:33:10.930 can take this data and write a program that's able to interpret it and use 01:33:10.930 --> 01:33:13.540 that data in some meaningful way. 01:33:13.540 --> 01:33:16.060 And so we'll see an example of this now of using JavaScript 01:33:16.060 --> 01:33:19.030 to be able to communicate with yet another online service, 01:33:19.030 --> 01:33:23.210 in particular for accessing information about currency exchange rates. 01:33:23.210 --> 01:33:25.090 Currency exchange rates are always changing. 01:33:25.090 --> 01:33:28.040 We want access to the latest currency exchange rate data. 01:33:28.040 --> 01:33:30.550 And if there is an online service, an API, 01:33:30.550 --> 01:33:33.400 that provides access to that data in JSON form-- 01:33:33.400 --> 01:33:35.920 in a format like this that is machine-readable-- then 01:33:35.920 --> 01:33:39.730 we can use that data to write a currency exchange 01:33:39.730 --> 01:33:44.260 application that uses real-time data in order to make those conversions. 01:33:44.260 --> 01:33:45.643 What might that data look like? 01:33:45.643 --> 01:33:47.560 Well, the data could look something like this, 01:33:47.560 --> 01:33:49.750 that we make a request for accessing what 01:33:49.750 --> 01:33:52.630 are the exchange rates for converting from US dollars, 01:33:52.630 --> 01:33:54.460 otherwise known as USD. 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, 01:34:00.400 --> 01:34:03.340 and then it has a rates key that has a whole bunch of rates within it, 01:34:03.340 --> 01:34:07.510 so conversion to euros and Japanese yen, Great Britain pounds, as well as 01:34:07.510 --> 01:34:10.600 Australian dollars, and all of the various different currency exchange 01:34:10.600 --> 01:34:13.840 rates for all of these different currencies, for example. 01:34:13.840 --> 01:34:16.740 And this doesn't have to be the way that this data is structured, 01:34:16.740 --> 01:34:18.520 but it happens to be a convenient way. 01:34:18.520 --> 01:34:21.040 And so long as the person providing this data to me 01:34:21.040 --> 01:34:23.770 and I both know what this structure is, we 01:34:23.770 --> 01:34:27.090 can begin to write programs that are able to use that data. 01:34:27.090 --> 01:34:34.490 And so we'll now see our example of an API, which is exchangeratesapi.io. 01:34:34.490 --> 01:34:38.770 And if we go to api.exchangeratesapi.io/latest 01:34:38.770 --> 01:34:44.860 and provide a get parameter of base=USD, then what we get back is data that 01:34:44.860 --> 01:34:46.770 looks like this. 01:34:46.770 --> 01:34:49.910 Now, it's a little bit messy looking, not nearly as clean as we saw before, 01:34:49.910 --> 01:34:52.390 but it's the same exact thing, just without the whitespace. 01:34:52.390 --> 01:34:56.470 We have a JavaScript object that has a rates key that tells me, all right, 01:34:56.470 --> 01:34:59.680 here is the exchange rate between US dollars 01:34:59.680 --> 01:35:02.050 and Canadian dollars, and the pound, and the euro, 01:35:02.050 --> 01:35:04.270 and other currencies that exist as well. 01:35:04.270 --> 01:35:08.140 And down below, we have the base of what base currency we're converting from. 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. 01:35:12.670 --> 01:35:15.700 If I make a web request to this particular URL, 01:35:15.700 --> 01:35:20.200 I then get access to all of this currency exchange rate information 01:35:20.200 --> 01:35:22.850 that I can then use inside of my application. 01:35:22.850 --> 01:35:24.100 So how can I do this? 01:35:24.100 --> 01:35:29.200 How can I now begin to use this information inside of an application? 01:35:29.200 --> 01:35:31.120 Let's now create a new page. 01:35:31.120 --> 01:35:34.420 I'm going to call this currency.html. 01:35:34.420 --> 01:35:40.630 Inside of currency.html, I'll add our usual HTML, a title 01:35:40.630 --> 01:35:45.210 of currency exchange, and a body. 01:35:45.210 --> 01:35:48.110 And inside the body, I'm just going to include nothing for now. 01:35:48.110 --> 01:35:50.200 What I really care about is the JavaScript 01:35:50.200 --> 01:35:55.450 that is going to make a web request in order to get access to additional data. 01:35:55.450 --> 01:35:58.300 Now so far in JavaScript, our JavaScript code 01:35:58.300 --> 01:36:02.740 has exclusively been running code that exists only on our computer. 01:36:02.740 --> 01:36:06.190 It's running inside the web browser and all happening inside the web browser. 01:36:06.190 --> 01:36:08.280 We're not communicating with some external server. 01:36:08.280 --> 01:36:10.030 What we'll take a look at now is something 01:36:10.030 --> 01:36:13.210 known as Ajax, which is about asynchronous JavaScript, where 01:36:13.210 --> 01:36:17.650 the idea is that even after a page has loaded, using JavaScript, 01:36:17.650 --> 01:36:21.880 we can make additional web requests to ask for additional information, 01:36:21.880 --> 01:36:25.400 either from our own web servers or from some third-party web servers 01:36:25.400 --> 01:36:28.510 if we want additional information on our page. 01:36:28.510 --> 01:36:30.520 And what we want in this case is for our page 01:36:30.520 --> 01:36:34.570 to make an asynchronous request-- a request for additional data 01:36:34.570 --> 01:36:39.090 about the current currency exchange rates, for example. 01:36:39.090 --> 01:36:40.610 So how am I going to do that? 01:36:40.610 --> 01:36:46.790 Well, I want to do this after the DOM content is loaded, 01:36:46.790 --> 01:36:48.892 so we'll add that usually there. 01:36:48.892 --> 01:36:50.600 And what we're going to take advantage of 01:36:50.600 --> 01:36:53.058 is a function built into more recent versions of JavaScript 01:36:53.058 --> 01:36:57.380 and supported by most major browsers now, and it's a function called fetch. 01:36:57.380 --> 01:37:00.680 And what fetch is going to do is it is going to make a web request. 01:37:00.680 --> 01:37:02.427 It is going to query some website. 01:37:02.427 --> 01:37:03.260 It could be our own. 01:37:03.260 --> 01:37:04.550 It could be someone else's. 01:37:04.550 --> 01:37:09.102 And it's going to get back some HTTP response from that page. 01:37:09.102 --> 01:37:10.060 And I'm going to fetch. 01:37:10.060 --> 01:37:13.280 And the page I'm going to fetch is this URL-- 01:37:13.280 --> 01:37:18.110 api.exchangeratesapi.io/latest?base=USD. 01:37:18.110 --> 01:37:20.600 And the only reason I happen to know how this API works 01:37:20.600 --> 01:37:22.790 is because I've read the API's documentation 01:37:22.790 --> 01:37:25.340 that describes how the URL parameters work 01:37:25.340 --> 01:37:28.240 and what the structure of the data that I get back is. 01:37:28.240 --> 01:37:31.850 And so I'm here going to say go ahead and fetch from this URL. 01:37:31.850 --> 01:37:36.980 Make a HTTP request asking for additional information from this URL 01:37:36.980 --> 01:37:39.980 and get back what the results are going to be. 01:37:39.980 --> 01:37:42.260 And what fetch gives back to us is something 01:37:42.260 --> 01:37:44.540 in JavaScript known as a promise. 01:37:44.540 --> 01:37:48.590 And a promise is going to be a way of representing the idea that something 01:37:48.590 --> 01:37:51.757 is going to come back, but it may not come back immediately. 01:37:51.757 --> 01:37:54.840 We're not going to go into the details of exactly how those promises work, 01:37:54.840 --> 01:37:57.750 but it turns out there's a particular syntax for dealing with them, 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 01:38:03.840 --> 01:38:05.870 what should I do when the promise comes back, 01:38:05.870 --> 01:38:09.900 once I get back something like a response. 01:38:09.900 --> 01:38:12.200 And so when I get back the response, what I want to do 01:38:12.200 --> 01:38:14.630 is convert the response into JSON-- 01:38:14.630 --> 01:38:18.290 treat it as JSON data-- a JavaScript object, as something 01:38:18.290 --> 01:38:19.850 that I can then manipulate. 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 01:38:23.090 --> 01:38:28.350 and return response.json. 01:38:28.350 --> 01:38:32.640 And so what this is saying is go ahead and get me the latest exchange rates. 01:38:32.640 --> 01:38:34.327 And then after that's done-- 01:38:34.327 --> 01:38:35.660 this is an asynchronous process. 01:38:35.660 --> 01:38:36.970 It might take some time. 01:38:36.970 --> 01:38:40.350 But once I get back those results, then run this function. 01:38:40.350 --> 01:38:44.340 Take the response and return the JSON version of the response. 01:38:44.340 --> 01:38:46.890 Convert that response into just the raw JSON 01:38:46.890 --> 01:38:50.790 data, such that I can use that data to then access the currency exchange 01:38:50.790 --> 01:38:51.750 rates. 01:38:51.750 --> 01:38:53.582 And it turns out that with arrow functions, 01:38:53.582 --> 01:38:56.040 if you ever have a very simple function that all it's doing 01:38:56.040 --> 01:38:59.010 is taking something and returning something else, 01:38:59.010 --> 01:39:01.560 I can simplify this function even further 01:39:01.560 --> 01:39:04.980 and I can omit the curly braces, I can omit the return. 01:39:04.980 --> 01:39:08.460 I can just say response arrow response.json. 01:39:08.460 --> 01:39:11.070 And this is a shorthand way of saying a function that 01:39:11.070 --> 01:39:16.170 takes as input the response and returns as output response.json. 01:39:16.170 --> 01:39:19.470 So here, I'm saying go ahead and fetch me the latest exchange 01:39:19.470 --> 01:39:25.020 rates from this particular API, then convert the response to JSON data, 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. 01:39:30.660 --> 01:39:34.605 And for now, let's just go ahead and console.log that data just 01:39:34.605 --> 01:39:36.000 to print it out to the terminal. 01:39:36.000 --> 01:39:37.750 So we're not doing anything else just yet. 01:39:37.750 --> 01:39:40.380 All I'm doing is saying get me the exchange rates, 01:39:40.380 --> 01:39:44.340 convert the exchange rates data into JSON, and then let's go ahead 01:39:44.340 --> 01:39:47.070 and print out that data. 01:39:47.070 --> 01:39:49.620 So I'll open up currency.html. 01:39:49.620 --> 01:39:53.280 It's a blank page, but if I look in the JavaScript inspector, 01:39:53.280 --> 01:39:56.430 I see what got logged is a JavaScript object, here indicated 01:39:56.430 --> 01:39:57.810 by the word object. 01:39:57.810 --> 01:40:01.290 And if I click the triangle at left, I can open up and see, all right, 01:40:01.290 --> 01:40:05.190 inside of this object is all of this data about exchange 01:40:05.190 --> 01:40:08.930 rates for a whole bunch of different exchange rates for converting 01:40:08.930 --> 01:40:13.470 from the US dollar, where here, USD 1 means one US dollar is one US dollar, 01:40:13.470 --> 01:40:15.720 for example. 01:40:15.720 --> 01:40:17.720 So now that I've got this data, let's actually 01:40:17.720 --> 01:40:19.890 try and use this inside of the program. 01:40:19.890 --> 01:40:23.090 Maybe let's say I want to convert between US dollars and the euro 01:40:23.090 --> 01:40:26.330 to figure out what the conversion rate is between dollars and euros. 01:40:26.330 --> 01:40:28.640 Well, if we recall what the data looks like, 01:40:28.640 --> 01:40:34.970 the data is a JavaScript object where we have a key called rates, 01:40:34.970 --> 01:40:38.550 and inside of rates is this object, and inside of that object, 01:40:38.550 --> 01:40:43.190 I can access the EUR property to get the exchange rate of one US dollar 01:40:43.190 --> 01:40:45.990 is equal to some number of euros, for example. 01:40:45.990 --> 01:40:50.360 So it's inside of the rates key, and then inside of the EUR key. 01:40:50.360 --> 01:40:54.750 And that's how I know what to get access to inside of my data. 01:40:54.750 --> 01:41:00.170 So what I really want to do is access data.rates.EUR. 01:41:03.090 --> 01:41:07.370 That says get me all the data that came back, access the rates key, 01:41:07.370 --> 01:41:09.750 and then access the euro key. 01:41:09.750 --> 01:41:14.390 And we'll go ahead and save that in a variable called rate. 01:41:14.390 --> 01:41:19.730 And now, I'll just document.querySelector body .innerHTML 01:41:19.730 --> 01:41:20.690 = rate. 01:41:20.690 --> 01:41:24.690 Just like take that rate, put it inside of the body. 01:41:24.690 --> 01:41:31.550 So now if I refresh currency.html, what I see is just this value, 0.908443, 01:41:31.550 --> 01:41:34.010 which means that right now, 1 US dollar happens 01:41:34.010 --> 01:41:38.270 to be equal to about 0.91 euros, for instance. 01:41:38.270 --> 01:41:39.260 So that's useful. 01:41:39.260 --> 01:41:42.080 I can make this a little more human friendly by putting 01:41:42.080 --> 01:41:43.670 this inside of a template string. 01:41:43.670 --> 01:41:51.450 I could say 1 USD is equal to, and then rate EUR for example. 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. 01:41:57.315 --> 01:41:58.940 And even this is a little bit annoying. 01:41:58.940 --> 01:42:01.357 I probably don't care about it to this many decimal places 01:42:01.357 --> 01:42:04.890 unless I'm really in the mood to be very precise about these exchange rates. 01:42:04.890 --> 01:42:08.038 If I only care about it to like three decimal places, for example, 01:42:08.038 --> 01:42:09.830 it turns out JavaScript has functions I can 01:42:09.830 --> 01:42:14.750 use on numbers like rate.toFixed, passing in three as an argument 01:42:14.750 --> 01:42:17.510 there to mean I'd like to take this exchange rate 01:42:17.510 --> 01:42:21.120 and just round it to three decimal places, for example. 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. 01:42:26.492 --> 01:42:28.700 And the interesting thing about what's happening here 01:42:28.700 --> 01:42:31.950 is this is happening as a result of an asynchronous request. 01:42:31.950 --> 01:42:34.760 I am asking for the latest exchange rates. 01:42:34.760 --> 01:42:37.040 And when I get back the exchange rates data, 01:42:37.040 --> 01:42:40.460 JavaScript is plugging that information into the body of the page. 01:42:40.460 --> 01:42:44.810 I'm now communicating with an API, getting back that API's data in JSON 01:42:44.810 --> 01:42:50.270 form, and then using that data to update the contents of my HTML page. 01:42:50.270 --> 01:42:54.357 Of course in practice, if I really want a currency exchange web page, 01:42:54.357 --> 01:42:57.440 I probably don't just want to display the exchange rate between US dollars 01:42:57.440 --> 01:42:58.310 and euros. 01:42:58.310 --> 01:43:01.430 I probably want to let the user pick what currencies 01:43:01.430 --> 01:43:03.350 they would like to exchange between. 01:43:03.350 --> 01:43:07.220 And so here is how I might go about doing that. 01:43:07.220 --> 01:43:11.120 Inside of the body of the page now, rather than just have an empty body, 01:43:11.120 --> 01:43:12.630 let's go ahead and add a form. 01:43:12.630 --> 01:43:15.920 That form is going to have an input, whose ID is currency, 01:43:15.920 --> 01:43:18.050 just so I have a way of referencing it later. 01:43:18.050 --> 01:43:22.570 The placeholder will just be currency, and the type of it is text. 01:43:22.570 --> 01:43:25.490 And then I'll have an input whose type is submit, 01:43:25.490 --> 01:43:27.127 and we'll give it a value of convert. 01:43:27.127 --> 01:43:28.460 That'll be what the button says. 01:43:28.460 --> 01:43:32.360 It says convert, and then I can convert to a particular currency. 01:43:32.360 --> 01:43:35.210 And then I need some place to put my results, 01:43:35.210 --> 01:43:39.167 so I'll go ahead and add a div whose ID is result. 01:43:39.167 --> 01:43:41.750 And this is where after I've done all the currency conversion, 01:43:41.750 --> 01:43:44.458 this is where I'm going to put the results of doing that currency 01:43:44.458 --> 01:43:46.770 conversion. 01:43:46.770 --> 01:43:50.220 So now rather than fetch right away, here's what I need to do. 01:43:50.220 --> 01:43:53.740 I need to do something only when the form is submitted. 01:43:53.740 --> 01:43:59.790 So I can get the form by saying document.querySelector form .onsubmit 01:43:59.790 --> 01:44:01.813 equals this function. 01:44:01.813 --> 01:44:03.730 And I'm going to go ahead and just in advance, 01:44:03.730 --> 01:44:06.690 return false at the end of the function so we don't actually try 01:44:06.690 --> 01:44:08.380 and submit the form to another page. 01:44:08.380 --> 01:44:12.310 I just want to run everything locally on this same page. 01:44:12.310 --> 01:44:15.780 But now inside of this form, once you submit it, 01:44:15.780 --> 01:44:20.590 that is when I want to run this code that is going to fetch new data. 01:44:20.590 --> 01:44:23.280 So I'm going to fetch data from the exchange rates API, 01:44:23.280 --> 01:44:25.800 convert that data to JSON same as before, 01:44:25.800 --> 01:44:28.330 then go ahead and get access to that data. 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 01:44:33.030 --> 01:44:34.568 typed in to the input field. 01:44:34.568 --> 01:44:37.610 And that is going to be the currency that I care about getting access to. 01:44:37.610 --> 01:44:40.050 So I'll create a variable called currency, 01:44:40.050 --> 01:44:43.560 which will be equal to document.querySelector. 01:44:43.560 --> 01:44:47.950 And the input field, if I scroll down, it has an ID of currency. 01:44:47.950 --> 01:44:49.950 So if I want to get that input field, I'm 01:44:49.950 --> 01:44:56.620 going to say get the element whose ID is currency and get its value. 01:44:56.620 --> 01:45:02.590 So this now is the currency that the user wanted me to get access to. 01:45:02.590 --> 01:45:10.160 And I can then say data.rates currency instead of data.rates.EUR. 01:45:10.160 --> 01:45:13.070 And importantly, I can't do data.rates.currency. 01:45:13.070 --> 01:45:14.990 That would literally try to access a property 01:45:14.990 --> 01:45:17.210 of rates that is called currency. 01:45:17.210 --> 01:45:19.520 If I use square brackets instead, that allows 01:45:19.520 --> 01:45:22.580 me to use a variable-- something like the currency variable, which 01:45:22.580 --> 01:45:26.990 I defined up here on line 13 as the currency that the user typed in. 01:45:26.990 --> 01:45:31.770 I would like to access that particular currency inside of the rates. 01:45:31.770 --> 01:45:33.960 And so now, I can ask a question. 01:45:33.960 --> 01:45:35.520 There are two possibilities here. 01:45:35.520 --> 01:45:40.600 Either the currency the user typed in is a valid currency or it's not. 01:45:40.600 --> 01:45:42.750 And it turns out that if you try and access 01:45:42.750 --> 01:45:45.870 a property of an object that doesn't exist, what you get back 01:45:45.870 --> 01:45:48.750 is a particular JavaScript variable called undefined, 01:45:48.750 --> 01:45:50.460 meaning there is no value there. 01:45:50.460 --> 01:45:56.790 So for example, if I have something like let person = first name is Harry 01:45:56.790 --> 01:45:59.700 and last name is Potter like we did before, 01:45:59.700 --> 01:46:03.420 I can access something like person.first and get Harry. 01:46:03.420 --> 01:46:05.910 I can access person.last and get Potter. 01:46:05.910 --> 01:46:08.490 But if access person.middle, that is going 01:46:08.490 --> 01:46:12.300 to be a special variable in JavaScript or a special value in JavaScript 01:46:12.300 --> 01:46:16.187 called undefined, meaning there is no value there. 01:46:16.187 --> 01:46:19.020 It's slightly different from null, which also has a similar meaning. 01:46:19.020 --> 01:46:21.340 They're used in slightly different contexts. 01:46:21.340 --> 01:46:27.090 So here, what I can say is if the rate is not undefined, well 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 01:46:37.330 --> 01:46:39.670 is equal to this rate-- 01:46:39.670 --> 01:46:46.020 not necessarily euros, but whatever the currency happens to be. 01:46:46.020 --> 01:46:51.890 And otherwise, let's go ahead and document.querySelector result 01:46:51.890 --> 01:46:57.590 .innerHTML = invalid currency, just to let the user know that the currency 01:46:57.590 --> 01:47:00.523 they tried to provide is not actually a valid currency, 01:47:00.523 --> 01:47:03.440 and so we're going to need to try a different currency in order to get 01:47:03.440 --> 01:47:05.350 the result to work. 01:47:05.350 --> 01:47:07.300 So now, here's what we can do. 01:47:07.300 --> 01:47:10.090 If I open up currency.html again, I now see 01:47:10.090 --> 01:47:12.490 a form where I can type in a currency. 01:47:12.490 --> 01:47:15.160 I can type in something like the euro, for example. 01:47:15.160 --> 01:47:19.450 Press Convert, and I see, all right, 1 USD equal to 0.090 EUR. 01:47:19.450 --> 01:47:21.370 I type in something like the pound. 01:47:21.370 --> 01:47:22.290 Press Convert. 01:47:22.290 --> 01:47:24.760 1 US dollar equal to 0.771 pounds. 01:47:24.760 --> 01:47:27.010 I type in the Japanese yen. 01:47:27.010 --> 01:47:30.370 1 USD is equal to 109.852 Japanese yen. 01:47:30.370 --> 01:47:33.370 And all of this is happening where every time I submit the form, 01:47:33.370 --> 01:47:34.940 it's making yet another request. 01:47:34.940 --> 01:47:37.210 So if the exchange rates happen to change in 01:47:37.210 --> 01:47:40.270 between when I submit the form, the next time I submit the form, 01:47:40.270 --> 01:47:43.510 I will be getting the latest exchange rates according to that exchange rates 01:47:43.510 --> 01:47:46.510 API and the results are going to come back here. 01:47:46.510 --> 01:47:49.070 And of course, if I type in a currency that doesn't exist, 01:47:49.070 --> 01:47:53.322 I type in something like foo for example and press Convert, invalid currency. 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, 01:47:56.530 --> 01:47:58.970 and so it tells me that I need to type in something valid. 01:47:58.970 --> 01:48:00.550 And so I can type in something valid. 01:48:00.550 --> 01:48:02.570 Maybe I tried just US dollars itself. 01:48:02.570 --> 01:48:05.830 It tells me 1 USD is equal to 1 USD-- 01:48:05.830 --> 01:48:08.830 exactly what I would expect it to be. 01:48:08.830 --> 01:48:12.200 Now, there are a couple of optimizations and improvements that we can make here. 01:48:12.200 --> 01:48:14.770 One is that I can search for euros right now with EUR. 01:48:14.770 --> 01:48:16.000 Press Convert. 01:48:16.000 --> 01:48:19.220 But if I search for euros in lowercase, for example, 01:48:19.220 --> 01:48:21.730 it turns out it thinks that's an invalid currency. 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 01:48:25.870 --> 01:48:29.980 from the API, this is the data that I get back from the exchange rates API, 01:48:29.980 --> 01:48:33.820 what you'll notice is that all of the currencies are all in capital letters-- 01:48:33.820 --> 01:48:36.350 they're all capital letters, all capital letters-- 01:48:36.350 --> 01:48:38.920 which means the only keys that I'm allowed to access 01:48:38.920 --> 01:48:41.200 are, in fact, those that have capital letters in them 01:48:41.200 --> 01:48:45.380 because these are the only keys that this API makes available to me. 01:48:45.380 --> 01:48:49.510 So if I want to convert between usd and euros lowercase, 01:48:49.510 --> 01:48:52.540 what I might want to do is first take the currency-- 01:48:52.540 --> 01:48:54.490 the thing the user typed in-- 01:48:54.490 --> 01:48:58.420 and first just call toUpperCase on it, which 01:48:58.420 --> 01:49:02.047 is a JavaScript function that takes a string and converts it to uppercase. 01:49:02.047 --> 01:49:03.880 I'd like to take whatever the user typed in, 01:49:03.880 --> 01:49:06.040 and now just first convert it to uppercase. 01:49:06.040 --> 01:49:11.140 That way, if I go back here, I can type in eur lowercase, press Convert, 01:49:11.140 --> 01:49:14.917 and I'm still able to get the correct conversion rate. 01:49:14.917 --> 01:49:18.250 The other thing that we won't noticeably notice the difference with here is that 01:49:18.250 --> 01:49:21.625 right now, I'm assuming that all of this is going to go successfully-- 01:49:21.625 --> 01:49:24.250 that we're going to successfully be able to make a web request, 01:49:24.250 --> 01:49:26.578 we'll successfully convert the response back to JSON-- 01:49:26.578 --> 01:49:27.370 but you never know. 01:49:27.370 --> 01:49:28.600 An API could go down. 01:49:28.600 --> 01:49:31.180 The API could change and do something unexpected. 01:49:31.180 --> 01:49:33.650 And so anytime you're dealing with these types of promises 01:49:33.650 --> 01:49:35.870 where you fetch something and say then do this, 01:49:35.870 --> 01:49:38.350 then do that, it can often be a good idea 01:49:38.350 --> 01:49:43.390 to add one last case, which is a catch case that basically says what should 01:49:43.390 --> 01:49:45.830 you do if something goes wrong. 01:49:45.830 --> 01:49:47.290 So I can say catch the error. 01:49:47.290 --> 01:49:51.520 And what I can just do is say like console.log error, 01:49:51.520 --> 01:49:53.590 and then log the error there. 01:49:53.590 --> 01:49:56.410 And all that's really saying is that if anything above 01:49:56.410 --> 01:49:59.740 goes wrong with the fetching and trying to process the response, 01:49:59.740 --> 01:50:02.650 it's going to catch the error, and then it will just, like, print out 01:50:02.650 --> 01:50:05.868 to the console that something went wrong-- some error message happened. 01:50:05.868 --> 01:50:08.410 And so that can be helpful and nice to have just to make sure 01:50:08.410 --> 01:50:10.840 that when things crash, they crash in a predictable way-- 01:50:10.840 --> 01:50:15.100 that you're able to see exactly what the error is just by looking 01:50:15.100 --> 01:50:16.990 inside the JavaScript console. 01:50:16.990 --> 01:50:19.510 And so now, we have a fully working web page 01:50:19.510 --> 01:50:22.360 that is able to communicate with an external API-- that 01:50:22.360 --> 01:50:25.870 is able to ask for information from another service on the internet, 01:50:25.870 --> 01:50:29.230 use those results, and put them back into the page-- really just going 01:50:29.230 --> 01:50:33.700 to show the power now that we get by taking advantage of the JavaScript 01:50:33.700 --> 01:50:34.210 language. 01:50:34.210 --> 01:50:38.140 We have the ability now to not only use JavaScript to be able to run code 01:50:38.140 --> 01:50:41.200 on the client, where we weren't able to before-- where right before, 01:50:41.200 --> 01:50:44.450 we only had Python code that was running on a web server-- 01:50:44.450 --> 01:50:47.650 but using JavaScript, the really powerful thing is now the ability 01:50:47.650 --> 01:50:51.520 to manipulate the DOM-- the ability to use JavaScript to take the page 01:50:51.520 --> 01:50:54.460 and change the contents of the page by updating things, 01:50:54.460 --> 01:50:56.225 by reading what happens to be on the page, 01:50:56.225 --> 01:50:59.350 whether it's inside of a particular element or what a user happened to type 01:50:59.350 --> 01:51:02.920 in, and using that in conjunction with event handlers-- 01:51:02.920 --> 01:51:05.770 ways that we can listen for when the user clicks on something, 01:51:05.770 --> 01:51:07.630 or when the user scrolls through something, 01:51:07.630 --> 01:51:09.130 or when the user types a key-- 01:51:09.130 --> 01:51:13.750 to be able to respond and therefore make our web pages all the more interactive. 01:51:13.750 --> 01:51:16.330 Next time, we'll continue our discussion of JavaScript, 01:51:16.330 --> 01:51:18.730 looking at how we can leverage the features of JavaScript 01:51:18.730 --> 01:51:20.590 to continue to build even more interesting 01:51:20.590 --> 01:51:24.500 and engaging user interfaces, so we'll see you next time.