1 00:00:00,000 --> 00:00:03,912 [MUSIC PLAYING] 2 00:00:03,912 --> 00:00:17,968 3 00:00:17,968 --> 00:00:21,260 SPEAKER: Welcome back, everyone, to Web Programming with Python and JavaScript, 4 00:00:21,260 --> 00:00:24,080 and last time we took a look at JavaScript, that language that 5 00:00:24,080 --> 00:00:27,050 ran inside of a user's web browser client-side 6 00:00:27,050 --> 00:00:30,740 and allowed us to do a number of things to make our web pages more interactive. 7 00:00:30,740 --> 00:00:33,320 JavaScript enabled us to display alerts, to be 8 00:00:33,320 --> 00:00:36,350 able to manipulate the DOM, the structure of the web page, 9 00:00:36,350 --> 00:00:39,840 in order to add content or see what content was already there. 10 00:00:39,840 --> 00:00:42,200 And it also let us respond to user events. 11 00:00:42,200 --> 00:00:44,720 When the user clicked on a button, or submitted a form, 12 00:00:44,720 --> 00:00:46,670 or typed something into an input field, we 13 00:00:46,670 --> 00:00:50,090 could have JavaScript functions run that responded to those events 14 00:00:50,090 --> 00:00:52,580 in order to make our web pages more interactive. 15 00:00:52,580 --> 00:00:55,410 Today, we're going to continue that conversation, in particular, 16 00:00:55,410 --> 00:00:57,860 taking a look at user interface design, looking 17 00:00:57,860 --> 00:01:00,500 at some common paradigms in terms of user interfaces 18 00:01:00,500 --> 00:01:04,250 and how we can leverage JavaScript to be able to achieve those goals to create 19 00:01:04,250 --> 00:01:08,090 interactive user interfaces that will be very valuable when users 20 00:01:08,090 --> 00:01:10,410 are interacting with our applications. 21 00:01:10,410 --> 00:01:14,180 So one of the more common paradigms, especially nowadays, in web programming 22 00:01:14,180 --> 00:01:17,150 is the ID of single-page applications. 23 00:01:17,150 --> 00:01:19,610 Thus far, if we wanted to create a web application that 24 00:01:19,610 --> 00:01:22,130 has multiple different pages, we've generally 25 00:01:22,130 --> 00:01:25,250 done that via multiple different routes in our Django web application, 26 00:01:25,250 --> 00:01:28,580 for example, where you go to slash something to get one page 27 00:01:28,580 --> 00:01:31,670 and slash something else in order to get another page. 28 00:01:31,670 --> 00:01:34,130 But commonly using JavaScript, we have the ability 29 00:01:34,130 --> 00:01:37,880 to create single-page applications, where the entire web page is really 30 00:01:37,880 --> 00:01:41,570 just a single page, and then we use JavaScript to manipulate the DOM, 31 00:01:41,570 --> 00:01:44,840 to replace portions of the page with things we want to replace. 32 00:01:44,840 --> 00:01:47,900 And this has a number of advantages, one of them being that we only 33 00:01:47,900 --> 00:01:51,740 need to make modifications to the part of the page that is actually changing. 34 00:01:51,740 --> 00:01:53,970 If, for example, you have five different pages, 35 00:01:53,970 --> 00:01:55,970 but the general layout and structure of the page 36 00:01:55,970 --> 00:01:59,240 is pretty similar, when you switch between pages, rather than load 37 00:01:59,240 --> 00:02:02,990 an entirely new page, you can just load the part of the page that is changing. 38 00:02:02,990 --> 00:02:05,180 And this is especially helpful for applications 39 00:02:05,180 --> 00:02:07,080 that are changing quite frequently. 40 00:02:07,080 --> 00:02:09,870 So let's take a look now at how we could implement, for example, 41 00:02:09,870 --> 00:02:12,870 a very simple single-page application. 42 00:02:12,870 --> 00:02:16,640 So let's imagine, for example, that we want a single-page application that 43 00:02:16,640 --> 00:02:21,600 just displays three different pages, but all included in the same page. 44 00:02:21,600 --> 00:02:26,510 I'll go ahead and create a new file that I'll call a singlepage.html, 45 00:02:26,510 --> 00:02:29,540 inside of which we'll include our usual HTML tags. 46 00:02:29,540 --> 00:02:33,450 47 00:02:33,450 --> 00:02:35,830 And inside the body of this page now, I'm 48 00:02:35,830 --> 00:02:38,410 going to include three different sections of the page 49 00:02:38,410 --> 00:02:42,400 to represent the three different pages I might want to display to the user. 50 00:02:42,400 --> 00:02:46,607 So I'll have a division whose ID is page one that maybe just has a heading that 51 00:02:46,607 --> 00:02:49,690 says, this is page one-- and you can imagine there's more content on these 52 00:02:49,690 --> 00:02:51,060 pages, as well-- 53 00:02:51,060 --> 00:02:53,160 a div whose ID is page two-- 54 00:02:53,160 --> 00:02:56,080 we'll say, this is page two-- 55 00:02:56,080 --> 00:03:00,310 and then one final div whose ID is page three and has a heading that 56 00:03:00,310 --> 00:03:03,250 says, this is page three, for example. 57 00:03:03,250 --> 00:03:07,870 Now, right now, if I were to open up singlepage.html, what we'd see 58 00:03:07,870 --> 00:03:10,270 is we see all three pages at the same time. 59 00:03:10,270 --> 00:03:12,380 Now, that's probably not what we want. 60 00:03:12,380 --> 00:03:15,070 What we really want is by default to hide these pages 61 00:03:15,070 --> 00:03:18,590 until we want to view the pages one at a time, for example. 62 00:03:18,590 --> 00:03:22,510 So one thing I could do is use CSS to be able to toggle whether or not 63 00:03:22,510 --> 00:03:25,630 something is visible, adding some style tags to my page, 64 00:03:25,630 --> 00:03:30,940 to say that by default, all of my divs should have a display property set 65 00:03:30,940 --> 00:03:32,800 to none, meaning they're not visible. 66 00:03:32,800 --> 00:03:35,660 They're not displayed on the screen. 67 00:03:35,660 --> 00:03:38,950 Now if I refresh the page, I don't actually see any of the three headings 68 00:03:38,950 --> 00:03:40,405 that I had there before. 69 00:03:40,405 --> 00:03:42,280 But what I'd really like is for some buttons, 70 00:03:42,280 --> 00:03:45,040 now, to allow me to toggle between these three pages, 71 00:03:45,040 --> 00:03:47,500 so I'll give myself three buttons, one button that says, 72 00:03:47,500 --> 00:03:51,670 page one, one button that says, page two, and one button that says, 73 00:03:51,670 --> 00:03:53,720 page three, for example. 74 00:03:53,720 --> 00:03:56,470 And I need some mechanism for these buttons to know, 75 00:03:56,470 --> 00:03:59,830 when you click on this button, what page should be displayed, so I'll go ahead 76 00:03:59,830 --> 00:04:02,830 and use data attributes, which we saw last time with JavaScript, 77 00:04:02,830 --> 00:04:07,290 to add some additional information to these particular HTML elements, 78 00:04:07,290 --> 00:04:12,130 where I'll give the first button a data-page value of page one, 79 00:04:12,130 --> 00:04:15,430 the second one a data-page value of page two, 80 00:04:15,430 --> 00:04:19,089 and the third one a data-page value of page three. 81 00:04:19,089 --> 00:04:21,880 Here, again, just providing information so that later, 82 00:04:21,880 --> 00:04:24,880 when I write some JavaScript, I can have the JavaScript code look 83 00:04:24,880 --> 00:04:28,910 at the data page attribute to say that when you click on this button, 84 00:04:28,910 --> 00:04:32,230 you should let me see the div whose ID is page one. 85 00:04:32,230 --> 00:04:35,480 That's what this is going to allow us to signal. 86 00:04:35,480 --> 00:04:39,010 So now let's go ahead and write that JavaScript. 87 00:04:39,010 --> 00:04:41,380 What I want to be able to do is to be able to say, 88 00:04:41,380 --> 00:04:45,040 I would like to show page one and hide the other two, or show page two 89 00:04:45,040 --> 00:04:47,690 and hide the other two, or show page three, for example. 90 00:04:47,690 --> 00:04:50,690 And so to do that, I'll first write a function that will let me do that. 91 00:04:50,690 --> 00:04:53,140 I'll right a function called showPage that 92 00:04:53,140 --> 00:04:56,470 takes as its argument what page I want to show. 93 00:04:56,470 --> 00:04:59,150 And so what should this function do? 94 00:04:59,150 --> 00:05:02,650 Well, what we're going to do is we're going to say document.querySelector, 95 00:05:02,650 --> 00:05:06,190 and I want to get the thing that has a particular ID, the ID 96 00:05:06,190 --> 00:05:08,200 of whatever this input happens to be. 97 00:05:08,200 --> 00:05:12,130 This page is going to represent the ID of the div that I want to show. 98 00:05:12,130 --> 00:05:14,650 So I say, get me the thing that has this ID, 99 00:05:14,650 --> 00:05:19,060 and then using a template literal, I'll say, all right, get me the ID of page 100 00:05:19,060 --> 00:05:22,450 whenever element has that particular ID. 101 00:05:22,450 --> 00:05:24,490 And then I'd like to change its style property. 102 00:05:24,490 --> 00:05:25,540 Which part of the style? 103 00:05:25,540 --> 00:05:27,670 Well, I want to change its display property. 104 00:05:27,670 --> 00:05:30,790 And instead of none, which was the default here, where I said, 105 00:05:30,790 --> 00:05:33,430 don't show it at all, the other option for a div 106 00:05:33,430 --> 00:05:36,460 is block, meaning it shows up as just a block that is 107 00:05:36,460 --> 00:05:39,680 on the page that is actually visible. 108 00:05:39,680 --> 00:05:41,695 And so now I have this showPage function. 109 00:05:41,695 --> 00:05:42,820 And I can test it, in fact. 110 00:05:42,820 --> 00:05:46,480 If I go into my browser, refresh the page, I now see three buttons. 111 00:05:46,480 --> 00:05:50,667 The buttons don't do anything just yet, but what I can do is in the console, 112 00:05:50,667 --> 00:05:53,500 if I actually just try running this, I can run the showPage function 113 00:05:53,500 --> 00:05:57,870 and say, like, showPage page1, for example, press Return. 114 00:05:57,870 --> 00:06:00,380 And page one now appears on my page. 115 00:06:00,380 --> 00:06:04,950 And if I [INAUDIBLE] showPage page2, then page two will become visible. 116 00:06:04,950 --> 00:06:06,750 And that did half of what I wanted. 117 00:06:06,750 --> 00:06:09,880 Page two is now visible, but so is page one. 118 00:06:09,880 --> 00:06:12,820 So I probably want it such that if I ever show a page, 119 00:06:12,820 --> 00:06:14,320 I hide the other pages first. 120 00:06:14,320 --> 00:06:18,040 Like, hide all the pages, and then show page two, or hide all the pages, 121 00:06:18,040 --> 00:06:19,820 and then show page three. 122 00:06:19,820 --> 00:06:21,860 So how could I go about doing that? 123 00:06:21,860 --> 00:06:24,520 Well, first, I might want to just, when I show a page, 124 00:06:24,520 --> 00:06:27,580 first hide all of the other pages, hide all the pages. 125 00:06:27,580 --> 00:06:32,380 So to get all the pages, I'll do document.querySelectorAll, 126 00:06:32,380 --> 00:06:36,520 get all of the divs, which is what I'm using to enclose the pages 127 00:06:36,520 --> 00:06:39,340 and now, for each one of those, again, effectively 128 00:06:39,340 --> 00:06:42,280 creating a loop, where I'm looping over each of the divs. 129 00:06:42,280 --> 00:06:50,000 For each div, let's go ahead and set the div.dot.display property equal to none. 130 00:06:50,000 --> 00:06:52,210 And so what this showPage function is now doing 131 00:06:52,210 --> 00:06:55,270 is it is first querying for all of the divs, which 132 00:06:55,270 --> 00:06:58,422 are simulating my pages inside of this single-page application. 133 00:06:58,422 --> 00:07:00,130 And for each one of the divs, we're going 134 00:07:00,130 --> 00:07:04,347 to pass it as input into this function, which is the argument to forEach, 135 00:07:04,347 --> 00:07:07,180 again, using this arrow function notation, which is just a shorthand 136 00:07:07,180 --> 00:07:11,290 way of expressing a function, where I'm here saying that for each of the divs, 137 00:07:11,290 --> 00:07:13,330 we'll go ahead and modify it style property, 138 00:07:13,330 --> 00:07:17,620 setting display equal to none, meaning don't show any of the divs. 139 00:07:17,620 --> 00:07:21,200 And then show only the div that was requested. 140 00:07:21,200 --> 00:07:24,190 So now this should solve the problem of multiple pages appearing 141 00:07:24,190 --> 00:07:25,590 simultaneously. 142 00:07:25,590 --> 00:07:31,970 And if I go back to this page and I write, showPage page1, then page one 143 00:07:31,970 --> 00:07:32,900 appears. 144 00:07:32,900 --> 00:07:37,160 But if I run showPage of page two, then page two appears, 145 00:07:37,160 --> 00:07:38,990 but page one disappears. 146 00:07:38,990 --> 00:07:41,750 And likewise, when I showPage page three, 147 00:07:41,750 --> 00:07:44,550 that shows page three, but not the other two. 148 00:07:44,550 --> 00:07:48,090 So I can manipulate which page is visible all via the console, 149 00:07:48,090 --> 00:07:50,840 but now what I'd like to do is get these buttons to actually work, 150 00:07:50,840 --> 00:07:53,810 where if I click on one of the buttons, that has the effect of actually 151 00:07:53,810 --> 00:07:56,840 displaying the requested page. 152 00:07:56,840 --> 00:08:00,110 So in order to do that, well, I want to attach some event listeners 153 00:08:00,110 --> 00:08:03,410 to these buttons, which means I need to wait until those buttons have loaded 154 00:08:03,410 --> 00:08:04,740 onto the page. 155 00:08:04,740 --> 00:08:10,070 So we'll use document.addEventListener DOMContentLoaded, again, 156 00:08:10,070 --> 00:08:13,800 waiting until all of the content on the page has been loaded. 157 00:08:13,800 --> 00:08:17,660 And then only then will I say, let's go ahead 158 00:08:17,660 --> 00:08:21,800 and querySelectorAll for all of the buttons. 159 00:08:21,800 --> 00:08:25,948 And for each one of those buttons, let's go ahead and attach an even listener 160 00:08:25,948 --> 00:08:26,990 to each of those buttons. 161 00:08:26,990 --> 00:08:30,711 So I'm querying for all of the buttons and saying for each of the buttons, 162 00:08:30,711 --> 00:08:32,419 I would like to do this with each button. 163 00:08:32,419 --> 00:08:35,600 And what I'd like to do is say button.onclick. 164 00:08:35,600 --> 00:08:39,539 When the button is clicked on, go ahead and run this function. 165 00:08:39,539 --> 00:08:41,245 I'd like to show page-- 166 00:08:41,245 --> 00:08:42,620 and which page do I want to show? 167 00:08:42,620 --> 00:08:48,110 Well, I want to show whatever page is in the page part of the button's data set. 168 00:08:48,110 --> 00:08:51,170 And to get it the current button, the button that has been clicked on, 169 00:08:51,170 --> 00:08:53,390 recall that when we're inside of an event handler, 170 00:08:53,390 --> 00:08:55,940 we can take advantage of the JavaScript keyword "this," 171 00:08:55,940 --> 00:08:59,520 which refers to whatever element has received the event, so whatever button, 172 00:08:59,520 --> 00:09:01,310 in this case, that was clicked on. 173 00:09:01,310 --> 00:09:07,550 So I can say, this.dataset.page to mean that for each of the buttons, 174 00:09:07,550 --> 00:09:10,640 when the button is clicked on-- we're saying button.onclick for each 175 00:09:10,640 --> 00:09:11,600 of the buttons-- 176 00:09:11,600 --> 00:09:13,550 run this function when the button is clicked. 177 00:09:13,550 --> 00:09:14,930 We'd like to show a page. 178 00:09:14,930 --> 00:09:16,430 Which page do we want to show? 179 00:09:16,430 --> 00:09:19,850 We'll take this button, the button that received the event, 180 00:09:19,850 --> 00:09:23,900 access its data properties, access its data page attribute, which 181 00:09:23,900 --> 00:09:27,530 are down here, either page one, or page two, or page three, 182 00:09:27,530 --> 00:09:32,870 and go ahead and just call the showPage function that we wrote a moment ago. 183 00:09:32,870 --> 00:09:36,110 So now that we've done that, we've attached these event handlers 184 00:09:36,110 --> 00:09:37,310 to the buttons. 185 00:09:37,310 --> 00:09:40,550 So now if I refresh the page, I can click on these buttons 186 00:09:40,550 --> 00:09:43,780 and toggle between any of the three pages. 187 00:09:43,780 --> 00:09:46,490 And now, the interesting thing here is that we now 188 00:09:46,490 --> 00:09:48,830 have the ability to just, in a single page, 189 00:09:48,830 --> 00:09:52,970 allow myself to simulate the idea of having multiple pages, all enclosed 190 00:09:52,970 --> 00:09:56,330 in a single HTML file, but not needing to consistently make 191 00:09:56,330 --> 00:10:00,100 additional requests to a server in order to get access to that information. 192 00:10:00,100 --> 00:10:02,780 Now, sometimes, though, it might be reasonable to want 193 00:10:02,780 --> 00:10:05,810 to reach out to a server when you need new information for a page, 194 00:10:05,810 --> 00:10:06,590 for example. 195 00:10:06,590 --> 00:10:09,830 You might imagine that each of these pages contains a lot of text. 196 00:10:09,830 --> 00:10:12,260 It's going to be inefficient if immediately we're 197 00:10:12,260 --> 00:10:15,860 loading all of that data into HTML and just showing and hiding them 198 00:10:15,860 --> 00:10:18,080 when we need to, because maybe we're loading 199 00:10:18,080 --> 00:10:20,872 more information than the user is ever going to actually care about 200 00:10:20,872 --> 00:10:23,750 if they're never going to look at page two or page three. 201 00:10:23,750 --> 00:10:27,500 So one thing we might imagine doing is loading this data dynamically. 202 00:10:27,500 --> 00:10:29,570 Last time, when we were talking about JavaScript, 203 00:10:29,570 --> 00:10:32,750 we saw how we could use fetch to say, go ahead, and request 204 00:10:32,750 --> 00:10:35,030 some additional information from a web server. 205 00:10:35,030 --> 00:10:37,160 Last time it was currency exchange rates. 206 00:10:37,160 --> 00:10:39,560 But then we used that data that came back in order 207 00:10:39,560 --> 00:10:42,020 to fill in something onto our page. 208 00:10:42,020 --> 00:10:44,210 And likewise, we could do a similar thing here, 209 00:10:44,210 --> 00:10:47,460 that if we have the general structure of a single page 210 00:10:47,460 --> 00:10:50,870 and we want to load new content, rather than load entirely 211 00:10:50,870 --> 00:10:53,720 new HTML content and reload the entire page, 212 00:10:53,720 --> 00:10:57,710 we can just ask our own web server for what part of the page 213 00:10:57,710 --> 00:11:02,057 needs to change and then just replace that part of the page. 214 00:11:02,057 --> 00:11:03,890 And so that's what we'll take a look at now, 215 00:11:03,890 --> 00:11:07,190 now combining Django for our web server and JavaScript 216 00:11:07,190 --> 00:11:10,010 for writing the client-side code to be able to generate 217 00:11:10,010 --> 00:11:12,150 a single-page application. 218 00:11:12,150 --> 00:11:15,560 And so for this, we'll go ahead and go into an example I had an advance called 219 00:11:15,560 --> 00:11:18,830 singlepage1, and inside of singlepage1, this 220 00:11:18,830 --> 00:11:22,650 is just the Django application with a single app called singlepage. 221 00:11:22,650 --> 00:11:25,730 And what we'll notice is-- we'll go to URLs first. 222 00:11:25,730 --> 00:11:30,410 There are two URLs, one default URL that just loads the index function, 223 00:11:30,410 --> 00:11:33,230 and then a URL for loading different sections of a page 224 00:11:33,230 --> 00:11:35,460 that I might want to dynamically load, for example. 225 00:11:35,460 --> 00:11:38,740 So I have sections slash some particular number. 226 00:11:38,740 --> 00:11:41,990 And if we look at the views for what it is these URLs else are actually doing, 227 00:11:41,990 --> 00:11:45,890 the index function just returns index.html. 228 00:11:45,890 --> 00:11:47,930 And then what the section function does is 229 00:11:47,930 --> 00:11:50,390 it first makes sure the numbers between 1 and 3, 230 00:11:50,390 --> 00:11:56,010 and if so, responds with one of these just strings of text, for example. 231 00:11:56,010 --> 00:11:57,570 So how does this actually work? 232 00:11:57,570 --> 00:12:05,870 If I go into singlepage1 and run the server, if I go to this URL, 233 00:12:05,870 --> 00:12:11,710 /section/1 section, for example, what I get is this block of text. 234 00:12:11,710 --> 00:12:16,480 And if I go to /section/2, I get that block of text, section/3, 235 00:12:16,480 --> 00:12:19,370 a different block of text altogether, so just different text. 236 00:12:19,370 --> 00:12:24,000 And I'd like to incorporate this text into an existing HTML page, 237 00:12:24,000 --> 00:12:25,410 for instance. 238 00:12:25,410 --> 00:12:28,640 So here, I'll go into index.html, this template that gets 239 00:12:28,640 --> 00:12:31,850 loaded when I go to the default route. 240 00:12:31,850 --> 00:12:36,710 And inside of index.html, what we'll see is 241 00:12:36,710 --> 00:12:39,080 I have a showSection function that behaves 242 00:12:39,080 --> 00:12:43,020 very similar to the showPage function we saw from a moment ago. 243 00:12:43,020 --> 00:12:45,200 But instead, what showSection is going to do 244 00:12:45,200 --> 00:12:47,960 is it's going to fetch what text I should display 245 00:12:47,960 --> 00:12:49,970 on the page from my own web server. 246 00:12:49,970 --> 00:12:55,850 I'm fetching from /sections/ fill in a number here, a number like 1, or 2, 247 00:12:55,850 --> 00:12:56,930 or 3. 248 00:12:56,930 --> 00:12:58,502 When I get the response-- 249 00:12:58,502 --> 00:13:01,460 in the past, we've seen how we can convert that response into JSON data 250 00:13:01,460 --> 00:13:03,060 if it's unstructured data. 251 00:13:03,060 --> 00:13:06,410 We can also just convert the response into plain text. 252 00:13:06,410 --> 00:13:08,960 Then I'll take that text, console.log it, 253 00:13:08,960 --> 00:13:12,590 just so we can see it in the log output, but then go ahead and querySelect 254 00:13:12,590 --> 00:13:16,010 for the content of the page, something that has an ID of content, 255 00:13:16,010 --> 00:13:19,520 update it's inner HTML, and set it equal to that text. 256 00:13:19,520 --> 00:13:21,590 So what this entire function is now doing 257 00:13:21,590 --> 00:13:23,870 is it is going to reach out to my server, 258 00:13:23,870 --> 00:13:27,050 figure out what text content belongs in the new section, 259 00:13:27,050 --> 00:13:31,130 and fill in the part of my page accordingly with the text that 260 00:13:31,130 --> 00:13:34,340 comes back from that HTTP request. 261 00:13:34,340 --> 00:13:37,080 And then down further below, inside of the page, 262 00:13:37,080 --> 00:13:39,170 we'll see that I have a Hello! 263 00:13:39,170 --> 00:13:42,590 heading, three buttons that toggle between the different sections-- 264 00:13:42,590 --> 00:13:46,100 each of them has a data-section attribute this time for which section 265 00:13:46,100 --> 00:13:47,370 should be loaded-- 266 00:13:47,370 --> 00:13:52,800 and then a div that is initially blank just for the content of the page. 267 00:13:52,800 --> 00:13:56,300 So putting this all together now, If I go to the default route, 268 00:13:56,300 --> 00:13:58,340 I see Hello! plus three buttons to give me 269 00:13:58,340 --> 00:14:00,450 a choice between three different sections. 270 00:14:00,450 --> 00:14:02,660 And if I click Section 1, what's going to happen 271 00:14:02,660 --> 00:14:07,550 is JavaScript is going to query/section/1, ask for the text. 272 00:14:07,550 --> 00:14:09,770 It gets that text back, and it's going to fill it 273 00:14:09,770 --> 00:14:15,260 in into the page, section one, section two, and section three, so very 274 00:14:15,260 --> 00:14:16,430 similar to before. 275 00:14:16,430 --> 00:14:18,710 But unlike what we had before, where all of the text 276 00:14:18,710 --> 00:14:21,210 was being loaded into the HTML page all at once, 277 00:14:21,210 --> 00:14:25,160 now we're using asynchronous JavaScript to only dynamically load 278 00:14:25,160 --> 00:14:26,840 information when we need it. 279 00:14:26,840 --> 00:14:28,640 When we click on a section, then it's going 280 00:14:28,640 --> 00:14:31,098 to make the request for what content needs to be filled in, 281 00:14:31,098 --> 00:14:32,420 and it's going to fill it in. 282 00:14:32,420 --> 00:14:34,548 And everything else, these buttons, this heading-- 283 00:14:34,548 --> 00:14:36,590 and you might imagine, in a more complex website, 284 00:14:36,590 --> 00:14:40,040 you've got a lot more going on around the edges of this web page. 285 00:14:40,040 --> 00:14:41,250 All of that stays the same. 286 00:14:41,250 --> 00:14:43,550 We don't need to reload any of that information. 287 00:14:43,550 --> 00:14:46,160 We're only reloading the portion of the page that 288 00:14:46,160 --> 00:14:49,970 actually changes as we toggle between these various different section 289 00:14:49,970 --> 00:14:51,320 headings. 290 00:14:51,320 --> 00:14:53,330 Now, this seems to be an advantage in some ways, 291 00:14:53,330 --> 00:14:55,640 that maybe we can be more efficient about how we run 292 00:14:55,640 --> 00:14:57,710 our single-page applications like this. 293 00:14:57,710 --> 00:15:00,200 One thing we seem to lose, though, is the notion 294 00:15:00,200 --> 00:15:03,620 of maintaining state inside of the URL, that generally, 295 00:15:03,620 --> 00:15:06,860 the URL gives you an indication for what page you're on. 296 00:15:06,860 --> 00:15:09,590 You're on something like /1 if you're on section one, 297 00:15:09,590 --> 00:15:12,992 or /2 if you're on section two, /3 for section three. 298 00:15:12,992 --> 00:15:15,950 But of course, we're staying on the same page in all of these examples. 299 00:15:15,950 --> 00:15:20,210 Whenever I click a button, section 1, or 2, or 3, the URL is never changing. 300 00:15:20,210 --> 00:15:21,980 URL stays the same. 301 00:15:21,980 --> 00:15:24,950 It turns out there's a way in JavaScript to manipulate 302 00:15:24,950 --> 00:15:29,210 that URL, taking advantage of what's known if the JavaScript History API, 303 00:15:29,210 --> 00:15:33,260 where I can push something to the history, meaning update the URL, 304 00:15:33,260 --> 00:15:37,010 and actually save that inside the user's browser history so later on, 305 00:15:37,010 --> 00:15:39,350 they could potentially go back to that. 306 00:15:39,350 --> 00:15:44,930 And to do that, I'll show you yet another example inside of singlepage2, 307 00:15:44,930 --> 00:15:48,650 which is very similar, except inside of index.html, 308 00:15:48,650 --> 00:15:51,270 I've added a couple additional things. 309 00:15:51,270 --> 00:15:53,840 One is that when I click on a button, meaning 310 00:15:53,840 --> 00:15:57,050 when I click on section one, or section two, or section three, 311 00:15:57,050 --> 00:16:00,910 I've added this line here, history.pushState. 312 00:16:00,910 --> 00:16:03,170 What history.pushState is going to do is it 313 00:16:03,170 --> 00:16:07,790 is going to basically add a new element to my browsing history, where I first 314 00:16:07,790 --> 00:16:10,320 specify any data associated with the state. 315 00:16:10,320 --> 00:16:13,130 So in particular, I'm storing a JavaScript object 316 00:16:13,130 --> 00:16:16,970 representing what section number is being represented here. 317 00:16:16,970 --> 00:16:20,000 Next is a title parameter that most web browsers actually ignore, 318 00:16:20,000 --> 00:16:21,930 so that can generally be the empty string. 319 00:16:21,930 --> 00:16:24,890 But the third argument here is what should go in the URL, 320 00:16:24,890 --> 00:16:26,950 and what I want to go in the URL, in this case, 321 00:16:26,950 --> 00:16:29,660 is something like section followed by the section number. 322 00:16:29,660 --> 00:16:34,980 So I can go to /section1, or /section2, or /section3, for instance, 323 00:16:34,980 --> 00:16:39,842 and those will appear in the URL bar when I click on a different page. 324 00:16:39,842 --> 00:16:42,050 Then what I want to be able to support is the ability 325 00:16:42,050 --> 00:16:44,210 to say, when I go back through my history, 326 00:16:44,210 --> 00:16:46,310 if I click the Back button in my web browser, 327 00:16:46,310 --> 00:16:49,460 I'd like to go back from section three to section two 328 00:16:49,460 --> 00:16:51,830 if that was the page I visited previously. 329 00:16:51,830 --> 00:16:54,830 And there turns out to be an event handler for that, as well, 330 00:16:54,830 --> 00:16:59,240 window.onpopstate, meaning when I pop something off of the history, 331 00:16:59,240 --> 00:17:01,890 like, go back in my history. 332 00:17:01,890 --> 00:17:04,829 We have the ability to take some event as an argument. 333 00:17:04,829 --> 00:17:09,412 And if you look at event.state.section, which I've run console.log on, 334 00:17:09,412 --> 00:17:11,329 so we can take a look at it in a moment, we'll 335 00:17:11,329 --> 00:17:16,050 see what state was stored associated with that part of the user's history. 336 00:17:16,050 --> 00:17:19,020 And I can go ahead and show that section. 337 00:17:19,020 --> 00:17:21,109 So all in all, when I run this web application, 338 00:17:21,109 --> 00:17:29,630 going into singlepage2 this time, when I run the server, I see Hello!, 339 00:17:29,630 --> 00:17:31,310 three sections for buttons. 340 00:17:31,310 --> 00:17:34,550 When I click on one of those buttons, not only do I see text, 341 00:17:34,550 --> 00:17:38,240 but I also see in the URL bar that I'm now on /section1. 342 00:17:38,240 --> 00:17:40,700 That has been pushed onto my history, and I've 343 00:17:40,700 --> 00:17:42,790 updated the URL to reflect that, too. 344 00:17:42,790 --> 00:17:44,030 I click section two. 345 00:17:44,030 --> 00:17:45,710 That updates the URL, as well. 346 00:17:45,710 --> 00:17:47,480 Section 3 updates the URL, too. 347 00:17:47,480 --> 00:17:50,000 And when I've pushed things onto my history, 348 00:17:50,000 --> 00:17:54,230 I've associated some state with them so that I can go back if I ever need to. 349 00:17:54,230 --> 00:17:57,890 And in fact, if I open up the JavaScript console now and I go back, 350 00:17:57,890 --> 00:18:00,080 for example, back to section two. 351 00:18:00,080 --> 00:18:03,980 What you'll see is that what gets logged is the number 2. 352 00:18:03,980 --> 00:18:06,200 When I print out what is the current section that's 353 00:18:06,200 --> 00:18:08,990 associated with this URL, it's saving that state, 354 00:18:08,990 --> 00:18:11,150 that I should be loading section number two. 355 00:18:11,150 --> 00:18:14,960 And so it does load section number two here. 356 00:18:14,960 --> 00:18:18,620 So there's certainly nothing wrong with the original paradigm of just loading 357 00:18:18,620 --> 00:18:21,500 different pages dynamically using Django, like, make a request, 358 00:18:21,500 --> 00:18:22,640 and get a response. 359 00:18:22,640 --> 00:18:26,090 But oftentimes, as you begin to imagine applications where a lot of things 360 00:18:26,090 --> 00:18:28,190 are changing on the same page simultaneously, 361 00:18:28,190 --> 00:18:30,620 you might imagine social networking websites, where a lot of things 362 00:18:30,620 --> 00:18:31,190 stay the same. 363 00:18:31,190 --> 00:18:33,440 But new posts might be added, and you might be looking 364 00:18:33,440 --> 00:18:35,090 at different parts of the same page. 365 00:18:35,090 --> 00:18:37,310 Being able to dynamically load information, 366 00:18:37,310 --> 00:18:40,550 request additional information, and then display it on the page 367 00:18:40,550 --> 00:18:44,300 can actually be quite powerful and a way to make your web pages a little bit 368 00:18:44,300 --> 00:18:46,140 more interactive. 369 00:18:46,140 --> 00:18:49,070 So that, then, is how we might build the single-page application, 370 00:18:49,070 --> 00:18:52,700 taking advantage of JavaScript to asynchronously load new data 371 00:18:52,700 --> 00:18:55,190 and then taking advantage of this History API 372 00:18:55,190 --> 00:18:59,000 that let us add things to the URL, add things to the user's browsing history, 373 00:18:59,000 --> 00:19:03,660 such that we could go back to them later by listening for window.onpopstate. 374 00:19:03,660 --> 00:19:06,200 And it turns out that window object that we get access 375 00:19:06,200 --> 00:19:08,030 to in JavaScript is quite powerful. 376 00:19:08,030 --> 00:19:11,600 It represents the physical window on the computer screen that 377 00:19:11,600 --> 00:19:14,180 displays all of their web content, and there's 378 00:19:14,180 --> 00:19:16,940 certain properties of that window we can look at that allow 379 00:19:16,940 --> 00:19:18,972 us to enable some interesting features. 380 00:19:18,972 --> 00:19:20,930 So for example, your window is really described 381 00:19:20,930 --> 00:19:24,260 by what the user actually sees inside of their window in Google 382 00:19:24,260 --> 00:19:27,213 Chrome, or Safari, or whatever web browser they happen to be using. 383 00:19:27,213 --> 00:19:29,630 And there are a couple of properties that might be of use. 384 00:19:29,630 --> 00:19:33,020 Something like window.innerwidth will represent 385 00:19:33,020 --> 00:19:35,810 how wide is the window, which might be useful to know 386 00:19:35,810 --> 00:19:39,080 to know the size of the user's screen, for example, to know how many pixels 387 00:19:39,080 --> 00:19:41,120 wide the window happens to be. 388 00:19:41,120 --> 00:19:42,890 And just as there is a window.innerwidth, 389 00:19:42,890 --> 00:19:47,930 there is also a window.innerheight that represents the height of the window, 390 00:19:47,930 --> 00:19:49,200 as well. 391 00:19:49,200 --> 00:19:52,220 Now, "window" represents the physical part that they're actually seeing. 392 00:19:52,220 --> 00:19:55,250 We've also seen another variable that JavaScript gives us access to, 393 00:19:55,250 --> 00:19:57,240 and that is this document object. 394 00:19:57,240 --> 00:20:00,080 So what is the difference between the window and the document? 395 00:20:00,080 --> 00:20:03,590 Well, the document generally represents the entire web page, 396 00:20:03,590 --> 00:20:06,500 but if web pages are long, oftentimes a web page 397 00:20:06,500 --> 00:20:08,570 doesn't fit entirely inside of the window, 398 00:20:08,570 --> 00:20:11,570 that you generally have to scroll through an entire web page. 399 00:20:11,570 --> 00:20:15,900 And the window is only showing you one portion of that page at any given time. 400 00:20:15,900 --> 00:20:19,190 So you can represent the document as this big vertical section 401 00:20:19,190 --> 00:20:20,450 that goes beyond the window. 402 00:20:20,450 --> 00:20:22,242 There might be part of the document that is 403 00:20:22,242 --> 00:20:26,540 above the window, part of the document that is below the window, as well. 404 00:20:26,540 --> 00:20:31,160 So window.scrollY is another variable you have access to on the window, 405 00:20:31,160 --> 00:20:35,870 and window.scrollY represents how many pixels far down have you scrolled. 406 00:20:35,870 --> 00:20:39,080 So if you're at the top of the page, window.scrollY is 0. 407 00:20:39,080 --> 00:20:40,320 You haven't scrolled at all. 408 00:20:40,320 --> 00:20:43,820 But as you begin to scroll, if you want to know how far the user has scrolled 409 00:20:43,820 --> 00:20:46,970 on the page, you can look at window.scrollY 410 00:20:46,970 --> 00:20:49,040 to figure out the number of pixels the user has 411 00:20:49,040 --> 00:20:53,140 scrolled in the y-direction, the up and down direction. 412 00:20:53,140 --> 00:20:56,180 And the entire height of the page is represented 413 00:20:56,180 --> 00:20:59,270 in document.body.offsethight. 414 00:20:59,270 --> 00:21:02,890 That represents how tall the entire height of the document is. 415 00:21:02,890 --> 00:21:04,640 And we talk about all this, in addition to 416 00:21:04,640 --> 00:21:07,160 things like window.innerheight and window.innerwidth, 417 00:21:07,160 --> 00:21:09,780 because using all of these values together, 418 00:21:09,780 --> 00:21:12,140 you can begin to do some interesting calculations. 419 00:21:12,140 --> 00:21:14,820 So one thing you might want to detect, for example, 420 00:21:14,820 --> 00:21:18,552 is, has the user scrolls down to the bottom of the page or not? 421 00:21:18,552 --> 00:21:20,510 That might be something you care about knowing. 422 00:21:20,510 --> 00:21:23,677 And it turns out there isn't an event listener that does this automatically, 423 00:21:23,677 --> 00:21:26,240 but we can calculate it in order to try and figure this out. 424 00:21:26,240 --> 00:21:29,240 If inner height is the height of the window, 425 00:21:29,240 --> 00:21:32,810 scrollY is how far vertically the user has scrolled, 426 00:21:32,810 --> 00:21:36,860 and document.body.offsetheight is the entire height of the document, you 427 00:21:36,860 --> 00:21:40,670 can ask yourself, what needs to be true if the user has scroll 428 00:21:40,670 --> 00:21:42,800 to the bottom of the page? 429 00:21:42,800 --> 00:21:45,350 And well, if the user has scroll to the bottom of the page, 430 00:21:45,350 --> 00:21:48,980 well, then scrollY, plus the inner height, 431 00:21:48,980 --> 00:21:50,690 meaning the amount that they've scrolled, 432 00:21:50,690 --> 00:21:52,280 plus the height of the window-- 433 00:21:52,280 --> 00:21:56,600 that must be at least or equal to document.body.offsethight, 434 00:21:56,600 --> 00:21:59,570 meaning the amount that they scrolled plus the window takes you down 435 00:21:59,570 --> 00:22:01,690 to the bottom of the page, to the end of the page, 436 00:22:01,690 --> 00:22:04,310 to whoever tall the document happens to be. 437 00:22:04,310 --> 00:22:06,950 And using that mathematical comparison, we 438 00:22:06,950 --> 00:22:11,080 can actually detect when the user has reached the bottom of the page, 439 00:22:11,080 --> 00:22:13,830 and we can actually try now put that into practice. 440 00:22:13,830 --> 00:22:19,490 So I'll go ahead and open up an example that I have here called scroll.html, 441 00:22:19,490 --> 00:22:23,570 and all scroll.html has right now is 100 paragraphs. 442 00:22:23,570 --> 00:22:28,210 Inside of the body tag I have a p for paragraph, paragraph 1, paragraph 2, 443 00:22:28,210 --> 00:22:29,380 so on and so forth. 444 00:22:29,380 --> 00:22:34,000 I have 100 paragraphs inside of the body of this HTML page, 445 00:22:34,000 --> 00:22:36,760 and that's all that really is there right now, such 446 00:22:36,760 --> 00:22:42,520 that now if I go ahead and open scroll.html, 447 00:22:42,520 --> 00:22:47,110 I see that I have 100 paragraphs that I can scroll through. 448 00:22:47,110 --> 00:22:49,240 And what I might like to do is detect when 449 00:22:49,240 --> 00:22:52,330 I've reached the bottom of the page and maybe do something when I do so, 450 00:22:52,330 --> 00:22:56,490 something like change the color of the page, for instance. 451 00:22:56,490 --> 00:22:58,010 So might I go about doing that? 452 00:22:58,010 --> 00:23:01,630 Well, I'm going to need some JavaScript, so I'm going to add some JavaScript. 453 00:23:01,630 --> 00:23:05,410 And I'll add an event listener for window.onscroll. 454 00:23:05,410 --> 00:23:10,355 Onscroll is an event that listens for when I'm scrolling through the window, 455 00:23:10,355 --> 00:23:13,480 and when I scroll through the window, we'll go ahead and run this function. 456 00:23:13,480 --> 00:23:16,273 We'll just use an arrow function as a shorthand here. 457 00:23:16,273 --> 00:23:17,440 What do I want to calculate? 458 00:23:17,440 --> 00:23:21,160 Well, I want to calculate if window.innerheight, 459 00:23:21,160 --> 00:23:25,600 meaning the height of the window itself, plus window.scrollY, 460 00:23:25,600 --> 00:23:28,000 meaning the amount that I've scrolled-- 461 00:23:28,000 --> 00:23:33,835 if that is at least document.body.offsethight, 462 00:23:33,835 --> 00:23:36,460 well, that means I must have scrolled to the bottom of the page 463 00:23:36,460 --> 00:23:38,590 or maybe even a little bit further if there's a little wiggle room 464 00:23:38,590 --> 00:23:40,580 to scroll past the end of the page. 465 00:23:40,580 --> 00:23:44,490 So if this is true, well, then I've reached the end of the page. 466 00:23:44,490 --> 00:23:49,510 And then we'll go ahead and say, document.querySelector body. 467 00:23:49,510 --> 00:23:51,850 And let's go ahead and change its style, in particular, 468 00:23:51,850 --> 00:23:57,022 change its background color and change the background color to green. 469 00:23:57,022 --> 00:23:59,230 Otherwise, if we haven't reached the end of the page, 470 00:23:59,230 --> 00:24:06,590 then we'll take the body of the page and change its background color to white. 471 00:24:06,590 --> 00:24:09,340 So what we're now doing here is taking advantage of the properties 472 00:24:09,340 --> 00:24:11,830 we know of this window object, saying when we 473 00:24:11,830 --> 00:24:14,200 scroll the window, let's check to see-- 474 00:24:14,200 --> 00:24:17,620 if we add this up and it's at least the height of the entire document, 475 00:24:17,620 --> 00:24:19,060 we've reached the end of the page. 476 00:24:19,060 --> 00:24:22,450 Go ahead and change the style of the background to the body accordingly. 477 00:24:22,450 --> 00:24:24,760 Otherwise, change the background to white, 478 00:24:24,760 --> 00:24:27,440 or leave it at white if it already is. 479 00:24:27,440 --> 00:24:32,150 So now if I take a look at this actual HTML page and reload scroll.html, 480 00:24:32,150 --> 00:24:34,570 we'll see that the background is initially white. 481 00:24:34,570 --> 00:24:38,170 But as I scroll down, once I reach the bottom, 482 00:24:38,170 --> 00:24:40,180 we'll see that the page changes to green. 483 00:24:40,180 --> 00:24:42,400 It's white before I reach the bottom, but as soon 484 00:24:42,400 --> 00:24:45,130 as I get to the bottom of the page, it turns to green. 485 00:24:45,130 --> 00:24:50,110 And the reason why is because the height of the window here plus however much 486 00:24:50,110 --> 00:24:52,930 I've already scrolled from the top of the page up until now-- 487 00:24:52,930 --> 00:24:55,107 that together is equal to the entire height 488 00:24:55,107 --> 00:24:57,940 of the document, which means we're able to detect the fact that I've 489 00:24:57,940 --> 00:24:59,330 reached the end of the page. 490 00:24:59,330 --> 00:25:03,000 And as a result, we can change the color of the background to green. 491 00:25:03,000 --> 00:25:06,093 Now, this in itself is not a particularly practical use 492 00:25:06,093 --> 00:25:08,260 of detecting when we scroll to the end of something. 493 00:25:08,260 --> 00:25:11,010 We probably don't usually care about changing the background color 494 00:25:11,010 --> 00:25:12,500 when you reach the end of the page. 495 00:25:12,500 --> 00:25:14,290 But there actually are real applications, 496 00:25:14,290 --> 00:25:17,200 and you might imagine this in the context of websites 497 00:25:17,200 --> 00:25:19,240 that allow for things like infinite scroll, 498 00:25:19,240 --> 00:25:21,970 that if you're on a social networking site that has a whole bunch of posts, 499 00:25:21,970 --> 00:25:23,950 you scroll to the bottom of the list of posts, 500 00:25:23,950 --> 00:25:26,358 and then it generates the new set of posts, as well. 501 00:25:26,358 --> 00:25:29,650 Or you're looking at news articles, and you're scrolling through news articles. 502 00:25:29,650 --> 00:25:33,010 And once you reach the bottom, it'll load a whole new set of news articles 503 00:25:33,010 --> 00:25:35,290 without you having to go to another page. 504 00:25:35,290 --> 00:25:36,360 How is it doing that? 505 00:25:36,360 --> 00:25:38,110 Well, it's a combination of the same types 506 00:25:38,110 --> 00:25:41,007 of ideas that we've been talking about, number one, the ability 507 00:25:41,007 --> 00:25:43,090 to detect when you've reached the end of the page, 508 00:25:43,090 --> 00:25:46,810 using JavaScript to detect that you're at the bottom of the page, and number 509 00:25:46,810 --> 00:25:51,730 two, to be able to asynchronously, using JavaScript, load additional content, 510 00:25:51,730 --> 00:25:54,670 fetch some additional page that has some additional content, 511 00:25:54,670 --> 00:25:57,880 some additional news articles, some additional posts, and whatnot 512 00:25:57,880 --> 00:26:00,130 and then take that information and manipulate 513 00:26:00,130 --> 00:26:03,970 the DOM to add that information to the existing web page. 514 00:26:03,970 --> 00:26:05,890 And that ultimately is what's going to give us 515 00:26:05,890 --> 00:26:10,510 this power to be able to support something like infinite scroll. 516 00:26:10,510 --> 00:26:13,360 So let's now go ahead and try and see what it would 517 00:26:13,360 --> 00:26:16,120 look like to implement infinite scroll. 518 00:26:16,120 --> 00:26:18,700 I've already started to create a sample application 519 00:26:18,700 --> 00:26:21,070 inside of this application called scroll, 520 00:26:21,070 --> 00:26:23,530 and I've got an app called posts inside of it. 521 00:26:23,530 --> 00:26:27,640 And what the posts app does is it's has got a couple of URLs. 522 00:26:27,640 --> 00:26:30,460 It's got a default URL that just loads an index row 523 00:26:30,460 --> 00:26:34,820 and then a posts route that loads this posts view. 524 00:26:34,820 --> 00:26:36,850 And so let's look at what these do. 525 00:26:36,850 --> 00:26:38,890 Index-- all it does is it's going to load a file 526 00:26:38,890 --> 00:26:41,740 called index.html, this template. 527 00:26:41,740 --> 00:26:47,020 And if I make a request to /posts, I need to provide two arguments. 528 00:26:47,020 --> 00:26:50,130 I need to provide a start for what post I want to start with, 529 00:26:50,130 --> 00:26:52,250 an end for what post I want to end with, and then 530 00:26:52,250 --> 00:26:55,000 it's just going to generate some sample posts that just say, like, 531 00:26:55,000 --> 00:26:57,700 post number one, post number two, so on and so forth. 532 00:26:57,700 --> 00:27:01,420 In practice, you could actually use social network posts in place of this, 533 00:27:01,420 --> 00:27:04,460 but this is good just for demonstration purposes. 534 00:27:04,460 --> 00:27:14,100 So what this is going to do, if I go into scroll and run server, 535 00:27:14,100 --> 00:27:19,110 is that if I go to /posts and say, start equals 1 and end equals 10, 536 00:27:19,110 --> 00:27:25,040 for example, then I get a JavaScript object that looks like this. 537 00:27:25,040 --> 00:27:28,260 Recall that a JavaScript object is just a convenient format for passing 538 00:27:28,260 --> 00:27:30,810 information back and forth in JSON format, 539 00:27:30,810 --> 00:27:35,190 and what we have here is a JSON object with a key called posts that gives me 540 00:27:35,190 --> 00:27:37,530 all of the posts, post number one, post number two, 541 00:27:37,530 --> 00:27:38,880 all the way up to number 10. 542 00:27:38,880 --> 00:27:42,160 And it's giving me those posts because I said, start at 1, end at 10. 543 00:27:42,160 --> 00:27:44,690 But I could have specified other numbers, as well. 544 00:27:44,690 --> 00:27:48,900 If I had said something like, start at 20, and go to 28, 545 00:27:48,900 --> 00:27:52,150 then it's going to give me post number 20 through post number 28. 546 00:27:52,150 --> 00:27:54,790 I can specify the range of posts that I want. 547 00:27:54,790 --> 00:27:58,410 So this now is an API that I have implemented effectively 548 00:27:58,410 --> 00:28:02,340 that allows someone to get access to a variety of different posts 549 00:28:02,340 --> 00:28:05,820 by hitting this particular URL, this end point, so to speak, 550 00:28:05,820 --> 00:28:09,460 and passing in parameters, passing in what post they want to start with 551 00:28:09,460 --> 00:28:11,040 and what post they want to end with. 552 00:28:11,040 --> 00:28:14,370 And then they get all of this data back presented to them 553 00:28:14,370 --> 00:28:16,980 in JSON format that can then be used. 554 00:28:16,980 --> 00:28:20,100 And what's nice about this is that now, when we're loading posts, 555 00:28:20,100 --> 00:28:23,170 rather than have to just guess at how many posts we need to load 556 00:28:23,170 --> 00:28:25,170 and then require someone to go to another page, 557 00:28:25,170 --> 00:28:28,430 we can just do something like load the first 20 posts. 558 00:28:28,430 --> 00:28:31,530 And now what we'd like to do is if they reach the end of the page, 559 00:28:31,530 --> 00:28:35,460 go ahead and load the next 20 posts by hitting this API end point, 560 00:28:35,460 --> 00:28:40,780 getting the next 20 posts, and then filling that in into the HTML page. 561 00:28:40,780 --> 00:28:44,070 So let's see now how that actually works in practice by taking 562 00:28:44,070 --> 00:28:48,450 a look at that template in index.html. 563 00:28:48,450 --> 00:28:53,130 So we go into templates, index.html, and there's a fair bit of JavaScript here. 564 00:28:53,130 --> 00:28:54,450 But look at the body first. 565 00:28:54,450 --> 00:28:57,000 The body just has a div for all the posts 566 00:28:57,000 --> 00:28:59,760 that initially is going to be empty. 567 00:28:59,760 --> 00:29:03,150 Now, here's what the JavaScript is going to do, and we'll walk through it. 568 00:29:03,150 --> 00:29:05,010 We start with the first post, so counter is 569 00:29:05,010 --> 00:29:07,950 going to keep track of what post we need to load next. 570 00:29:07,950 --> 00:29:10,832 By default, we're just going to start by loading post number one. 571 00:29:10,832 --> 00:29:12,540 We have a variable called quantity that's 572 00:29:12,540 --> 00:29:14,800 going to tell us how many posts are we going to load at a time. 573 00:29:14,800 --> 00:29:16,467 Let's just say, load 20 posts at a time. 574 00:29:16,467 --> 00:29:21,970 So start with 1 to 20, then 21 to 40, 41 to 60, so on and so forth. 575 00:29:21,970 --> 00:29:25,260 And when DOM content is loaded, go ahead and just 576 00:29:25,260 --> 00:29:28,200 call this function that's called load. 577 00:29:28,200 --> 00:29:30,570 And what the load function does is it figures out 578 00:29:30,570 --> 00:29:32,550 what the start and end should be. 579 00:29:32,550 --> 00:29:35,280 It fetches all the new posts. 580 00:29:35,280 --> 00:29:37,690 And then for each of the posts that comes back, 581 00:29:37,690 --> 00:29:39,590 we call this add post function. 582 00:29:39,590 --> 00:29:42,240 So we're asynchronously asking for new posts, 583 00:29:42,240 --> 00:29:45,510 and what the add post function does is it creates a new div, 584 00:29:45,510 --> 00:29:49,530 populates the post inside of it, and adds it to the DOM. 585 00:29:49,530 --> 00:29:53,220 So now that we have these parts, the ability to load new posts, 586 00:29:53,220 --> 00:29:56,500 as by fetching from some URL all of the posts that we care about, 587 00:29:56,500 --> 00:29:59,310 and then for each of those posts that comes back, add something 588 00:29:59,310 --> 00:30:02,580 new to the DOM, as by creating a new HTML element 589 00:30:02,580 --> 00:30:05,010 and inserting it into the page, we have the ability 590 00:30:05,010 --> 00:30:07,740 to dynamically load all of these posts. 591 00:30:07,740 --> 00:30:12,210 So if I go, not to /posts, but just to this default route, 592 00:30:12,210 --> 00:30:17,970 I'll see that we have something like 20 posts that all show up, 593 00:30:17,970 --> 00:30:23,370 but just 20 posts, because every time I call the load function, 594 00:30:23,370 --> 00:30:26,940 that is going to load the next set of posts, for example. 595 00:30:26,940 --> 00:30:31,050 And so what I can do is in the console, if I try running the load function just 596 00:30:31,050 --> 00:30:35,310 by calling it myself, press Return, after a second or so, 597 00:30:35,310 --> 00:30:38,600 the next set of posts show up, 21 all the way through 40. 598 00:30:38,600 --> 00:30:40,050 I call load again. 599 00:30:40,050 --> 00:30:44,970 The next set of posts show up, 41 through 60, 20 posts at a time, 600 00:30:44,970 --> 00:30:47,700 all using that asynchronous JavaScript. 601 00:30:47,700 --> 00:30:50,730 But now what I'd like to happen is for all this to happen on its own 602 00:30:50,730 --> 00:30:54,030 without me having to intervene and manually write JavaScript calls. 603 00:30:54,030 --> 00:30:57,060 I would just like to say, well, the same type of logic 604 00:30:57,060 --> 00:30:59,670 as before, window.onscroll. 605 00:30:59,670 --> 00:31:04,890 Let's go ahead and say, if window.innerheight plus window.scrollY 606 00:31:04,890 --> 00:31:08,610 is at least document.body.offsethight, meaning 607 00:31:08,610 --> 00:31:11,680 if I have scrolled to the end of the page, 608 00:31:11,680 --> 00:31:15,545 we'll then just go ahead and call the load function. 609 00:31:15,545 --> 00:31:16,920 That's all these lines are doing. 610 00:31:16,920 --> 00:31:18,360 Every time I scroll, we check. 611 00:31:18,360 --> 00:31:20,140 Did we scroll to the end of the page? 612 00:31:20,140 --> 00:31:21,990 And if we did scroll to the end of the page, 613 00:31:21,990 --> 00:31:25,800 then go ahead and load the next set of posts. 614 00:31:25,800 --> 00:31:29,170 So now I refresh the page. 615 00:31:29,170 --> 00:31:32,215 I see post one all the way up through post 20. 616 00:31:32,215 --> 00:31:34,090 Now watch what happens when I get to post 20. 617 00:31:34,090 --> 00:31:38,242 If I scroll to the bottom, after a second the next set of posts appears. 618 00:31:38,242 --> 00:31:39,450 I scroll to the bottom again. 619 00:31:39,450 --> 00:31:40,305 I'm at 40. 620 00:31:40,305 --> 00:31:42,180 And then after a second the next set appears. 621 00:31:42,180 --> 00:31:46,050 Every time I scroll to the bottom, more posts are going to load after that, 622 00:31:46,050 --> 00:31:50,130 allowing me to effectively implement this idea of infinite scrolling 623 00:31:50,130 --> 00:31:53,880 by taking advantage of some JavaScript techniques, where I can check for when 624 00:31:53,880 --> 00:31:56,610 I've got to the end of the page and then dynamically do something 625 00:31:56,610 --> 00:32:01,700 as a result of that, something like load some additional pages onto the screen 626 00:32:01,700 --> 00:32:05,550 and so here, too, a lot of power to be had inside of JavaScript. 627 00:32:05,550 --> 00:32:08,370 And a lot of where the power of user interface comes from 628 00:32:08,370 --> 00:32:12,150 is from how it is that the user interface interacts with the user, 629 00:32:12,150 --> 00:32:14,170 thinking about what the there is going to do 630 00:32:14,170 --> 00:32:17,350 and how the page should interact as a result, something like user scrolls 631 00:32:17,350 --> 00:32:21,010 to the end of the page, and they see some new pages show up, as well. 632 00:32:21,010 --> 00:32:25,000 And one technique we can use for just making HTML elements a little more 633 00:32:25,000 --> 00:32:27,040 responsive, a little bit more interesting 634 00:32:27,040 --> 00:32:30,280 is by adding some animation to them, as well, the ability for things 635 00:32:30,280 --> 00:32:33,520 to move around and change their properties in some way. 636 00:32:33,520 --> 00:32:36,670 And it turns out that CSS has support for animation. 637 00:32:36,670 --> 00:32:40,000 CSS has already given us support for things like styling elements, 638 00:32:40,000 --> 00:32:43,780 saying we want this element to be this color and this size, for example. 639 00:32:43,780 --> 00:32:46,810 But it also gives us the ability to animate those properties, as well, 640 00:32:46,810 --> 00:32:50,260 to change the size of something or change the position of something 641 00:32:50,260 --> 00:32:52,503 over some amount of time. 642 00:32:52,503 --> 00:32:55,420 And so let's now take a look at an example of what that might actually 643 00:32:55,420 --> 00:32:56,450 look like. 644 00:32:56,450 --> 00:33:01,710 I'll go ahead and create a new file, and I'll call it animate.html. 645 00:33:01,710 --> 00:33:04,510 And inside of animate.html, I'll go ahead 646 00:33:04,510 --> 00:33:10,090 and start by including our usual HTML. 647 00:33:10,090 --> 00:33:11,260 Title is Animate. 648 00:33:11,260 --> 00:33:13,900 649 00:33:13,900 --> 00:33:18,270 And what I'd like to do is just add a little bit of animation, using CSS, 650 00:33:18,270 --> 00:33:19,682 into this particular page. 651 00:33:19,682 --> 00:33:22,140 I'm going to start with just a heading, a heading that says 652 00:33:22,140 --> 00:33:25,200 something like "Welcome!" for example-- 653 00:33:25,200 --> 00:33:27,270 it's just going to display a welcome message-- 654 00:33:27,270 --> 00:33:34,890 such that now, if I open animate.html, here's what I see, just a message 655 00:33:34,890 --> 00:33:36,900 that says, "Welcome!" 656 00:33:36,900 --> 00:33:39,640 But now let's add some CSS to it. 657 00:33:39,640 --> 00:33:44,400 Let's go into the style tag, and for each one for this heading, 658 00:33:44,400 --> 00:33:47,130 I'd like to apply a particular animation to it. 659 00:33:47,130 --> 00:33:51,640 And I first need to specify what the animation's name is going to be, 660 00:33:51,640 --> 00:33:53,590 and I can pick a name for the animation. 661 00:33:53,590 --> 00:33:57,090 I'll say something like grow, for example. 662 00:33:57,090 --> 00:34:00,900 I'll set the animation's duration to be two seconds, 663 00:34:00,900 --> 00:34:04,348 and then the animation fill mode is what direction should the animation move in. 664 00:34:04,348 --> 00:34:06,390 Should it go forwards, or should it go backwards? 665 00:34:06,390 --> 00:34:08,409 We'll generally want our animation to go forward 666 00:34:08,409 --> 00:34:11,639 so they're making some sort of forward progress according to some rules 667 00:34:11,639 --> 00:34:13,230 that we're going to specify. 668 00:34:13,230 --> 00:34:15,960 So here I'm saying we're going to animate all of our headings 669 00:34:15,960 --> 00:34:18,090 using an animation called grow. 670 00:34:18,090 --> 00:34:21,090 And now we need to define what that animation actually does, 671 00:34:21,090 --> 00:34:26,730 and to do that, up above, in style, I'm going to say, @keyframes grow. 672 00:34:26,730 --> 00:34:28,770 And what this is going to allow me to do is 673 00:34:28,770 --> 00:34:32,130 specify some keyframes for this particular element, 674 00:34:32,130 --> 00:34:36,130 meaning where should the element start, what should its style properties be. 675 00:34:36,130 --> 00:34:38,969 And then at the end, what should its style properties be? 676 00:34:38,969 --> 00:34:41,820 And CSS is going to take care of the process of figuring out 677 00:34:41,820 --> 00:34:44,860 what needs to happen in all those intermediary fractions of seconds, 678 00:34:44,860 --> 00:34:46,179 for example. 679 00:34:46,179 --> 00:34:49,560 So what I can say is something like, go ahead and grow from, 680 00:34:49,560 --> 00:34:51,840 meaning what should its initial properties be? 681 00:34:51,840 --> 00:34:55,679 And maybe initially I wanted to have a font size of 20 pixels. 682 00:34:55,679 --> 00:35:01,600 And then we'll say, to font size of 100 pixels, for example. 683 00:35:01,600 --> 00:35:03,630 So all in all, what this is saying is I would 684 00:35:03,630 --> 00:35:07,740 like to apply an animation called grow to all of my headings. 685 00:35:07,740 --> 00:35:10,450 This animation should last two seconds and go forwards. 686 00:35:10,450 --> 00:35:12,292 And what is the grow animation going to do? 687 00:35:12,292 --> 00:35:14,250 Well, it's going to mean at the start, anything 688 00:35:14,250 --> 00:35:18,120 that obeys the grow animation will start with a font size of 20 pixels, 689 00:35:18,120 --> 00:35:22,320 and at the end, it will grow to a font size of 100 pixels. 690 00:35:22,320 --> 00:35:26,550 And I have now defined what it is that that animation means. 691 00:35:26,550 --> 00:35:29,200 So now, if I go ahead and refresh this page, 692 00:35:29,200 --> 00:35:33,090 animate.html, you'll see that "Welcome!" changes size. 693 00:35:33,090 --> 00:35:37,000 Over the course of two seconds, it goes from smaller to larger by obeying those 694 00:35:37,000 --> 00:35:37,500 key frames. 695 00:35:37,500 --> 00:35:41,310 I told it to obey this particular step, a set of instructions 696 00:35:41,310 --> 00:35:44,680 where it goes from a particular font size to another font size. 697 00:35:44,680 --> 00:35:47,762 And as a result, we see the effect here on the page. 698 00:35:47,762 --> 00:35:50,220 And it turns out you can do more than just manipulate size. 699 00:35:50,220 --> 00:35:53,560 You can manipulate just about any CSS property you want. 700 00:35:53,560 --> 00:35:58,450 So if I tell the heading that it should have a relative position, 701 00:35:58,450 --> 00:36:01,760 meaning its position should be relative to other elements or other things 702 00:36:01,760 --> 00:36:07,530 in its parent, I can say, you should change your position from being 0% 703 00:36:07,530 --> 00:36:13,140 from the left side of the screen to being 50% of the way 704 00:36:13,140 --> 00:36:14,578 from the left side of the screen. 705 00:36:14,578 --> 00:36:17,620 And at this point, grow is probably not the best name for this animation. 706 00:36:17,620 --> 00:36:19,140 I'll call it move instead. 707 00:36:19,140 --> 00:36:20,578 So animation name is move. 708 00:36:20,578 --> 00:36:23,370 And so now with this animation is going to do is it's going to say, 709 00:36:23,370 --> 00:36:26,070 when you run the animation, go from being 710 00:36:26,070 --> 00:36:30,450 right next to the left side of the screen to being about 50 711 00:36:30,450 --> 00:36:33,280 away from the left side of the screen. 712 00:36:33,280 --> 00:36:37,627 So I can go ahead and rerun this, and we see 713 00:36:37,627 --> 00:36:39,210 that's the animation that takes place. 714 00:36:39,210 --> 00:36:44,430 It goes from the left all the way back up to about halfway across the screen. 715 00:36:44,430 --> 00:36:48,060 Refresh the page, and it goes ahead and does the exact same thing. 716 00:36:48,060 --> 00:36:51,380 And it turns out we don't just need to specify a beginning point and an end 717 00:36:51,380 --> 00:36:52,680 point for an animation. 718 00:36:52,680 --> 00:36:56,310 We can specify various different keyframes for different points 719 00:36:56,310 --> 00:36:58,530 within the animation that we would like to capture, 720 00:36:58,530 --> 00:37:00,572 something like at the beginning of the animation, 721 00:37:00,572 --> 00:37:02,280 have this set of CSS properties. 722 00:37:02,280 --> 00:37:05,580 Maybe halfway through the animation, have a different set of CSS properties, 723 00:37:05,580 --> 00:37:09,042 and then at the very end, have yet another set of CSS properties. 724 00:37:09,042 --> 00:37:11,250 So I could say something like-- if I want the heading 725 00:37:11,250 --> 00:37:15,510 not just to move from left to right, but also to move back again, I can say, 726 00:37:15,510 --> 00:37:19,170 at the beginning, at the 0% point, when you're 0% of the way 727 00:37:19,170 --> 00:37:23,460 through the animation, you should be 0% away from the left-hand side. 728 00:37:23,460 --> 00:37:25,890 When you're 50% of the way through the animation, 729 00:37:25,890 --> 00:37:28,553 you should be 50% away from the left-hand side, 730 00:37:28,553 --> 00:37:31,470 and then when you're done with the animation, 100% of the way through, 731 00:37:31,470 --> 00:37:35,490 let's go back to 0% away from the left-hand side. 732 00:37:35,490 --> 00:37:39,540 I now have three keyframes, beginning of the animation, middle of the animation, 733 00:37:39,540 --> 00:37:41,730 back to the beginning of the animation again. 734 00:37:41,730 --> 00:37:45,277 And the effect of this is if I refresh the page, we go to the right, 735 00:37:45,277 --> 00:37:46,110 and then we go back. 736 00:37:46,110 --> 00:37:49,753 We're able to move one direction and then move back. 737 00:37:49,753 --> 00:37:52,920 And there are other properties we can use to manipulate these animations, as 738 00:37:52,920 --> 00:37:53,430 well. 739 00:37:53,430 --> 00:37:56,670 I can set the animation iteration count, for example, 740 00:37:56,670 --> 00:38:00,870 to 2 to mean, rather than just do the animation once and then stop, 741 00:38:00,870 --> 00:38:03,826 do the animation twice and then stop. 742 00:38:03,826 --> 00:38:04,440 So I refresh. 743 00:38:04,440 --> 00:38:06,450 It goes to the right, and then it goes left. 744 00:38:06,450 --> 00:38:08,192 And then it repeats that a second time. 745 00:38:08,192 --> 00:38:09,900 And it turns out, if you really want, you 746 00:38:09,900 --> 00:38:14,110 can set this to infinite to mean never stop performing that animation. 747 00:38:14,110 --> 00:38:17,340 It's consistently going to have this heading move to the right 748 00:38:17,340 --> 00:38:20,760 and then move left, according to those keyframes that I've specified. 749 00:38:20,760 --> 00:38:23,010 And so if you ever see things moving around on a page, 750 00:38:23,010 --> 00:38:25,780 interactive in some way, there are a number of ways to do it. 751 00:38:25,780 --> 00:38:28,210 You can animate things using JavaScript, for example, 752 00:38:28,210 --> 00:38:31,470 but there are many cases where CSS alone is pretty good at just 753 00:38:31,470 --> 00:38:33,780 creating these types of animations. 754 00:38:33,780 --> 00:38:36,420 And while this animation right now is just running forever, 755 00:38:36,420 --> 00:38:41,230 we could use JavaScript in order to control that animation, as well. 756 00:38:41,230 --> 00:38:44,310 So let's see an example of what that would look like. 757 00:38:44,310 --> 00:38:45,420 I'll go back here. 758 00:38:45,420 --> 00:38:49,140 In the body of the page, in addition to a heading that says "Welcome!" 759 00:38:49,140 --> 00:38:54,870 I'll go ahead and add a button that just says, click here, for example. 760 00:38:54,870 --> 00:38:58,820 And now what I'll do is add a little bit of JavaScript. 761 00:38:58,820 --> 00:39:01,470 I'm going to add some JavaScript so that the button can now 762 00:39:01,470 --> 00:39:06,630 control the animation, decide when the animation is going to start and stop. 763 00:39:06,630 --> 00:39:10,200 And so what we'll do inside of the script is to first say, 764 00:39:10,200 --> 00:39:14,260 document.addEventListener DOMContentLoaded, 765 00:39:14,260 --> 00:39:18,180 meaning wait until the DOM is done loading, as we've done before. 766 00:39:18,180 --> 00:39:23,610 And let me now get that h1 element, document.querySelector h1. 767 00:39:23,610 --> 00:39:26,230 768 00:39:26,230 --> 00:39:31,420 And initially, I'm going to set its style.animationPlayState 769 00:39:31,420 --> 00:39:34,660 equal to paused. 770 00:39:34,660 --> 00:39:37,750 So animation placed it as a property of the style that 771 00:39:37,750 --> 00:39:40,690 lets me decide if the animation is playing or paused, 772 00:39:40,690 --> 00:39:42,430 and I can control that using JavaScript. 773 00:39:42,430 --> 00:39:45,610 Rather than just say, run infinitely forever, I can say, 774 00:39:45,610 --> 00:39:47,740 the animation-play-state should start out 775 00:39:47,740 --> 00:39:51,760 as paused by first getting the h1 element then modifying 776 00:39:51,760 --> 00:39:55,960 the animation-play-state property of that particular element. 777 00:39:55,960 --> 00:40:00,670 But now what I'd like to happen is anytime someone clicks on the button, 778 00:40:00,670 --> 00:40:02,800 I want to change the animation-play-state. 779 00:40:02,800 --> 00:40:06,280 So I'm going to say, document.querySelector button, meaning 780 00:40:06,280 --> 00:40:09,850 get that button, and when someone clicks on the button, 781 00:40:09,850 --> 00:40:18,140 let's run this function, where if the current animation-play-state is paused, 782 00:40:18,140 --> 00:40:24,280 we'll then go ahead and set animation-play-state equal to running. 783 00:40:24,280 --> 00:40:26,600 And otherwise, if it's already running, then 784 00:40:26,600 --> 00:40:32,600 let's go ahead and set the animation-play-state equal to paused. 785 00:40:32,600 --> 00:40:35,000 So all in all, what this function is going to do 786 00:40:35,000 --> 00:40:37,790 is it's going to get me the heading, pause this initially, 787 00:40:37,790 --> 00:40:40,580 and every time the button is clicked, run this function, where 788 00:40:40,580 --> 00:40:44,230 the function says, if we're paused, go ahead and start running the animation. 789 00:40:44,230 --> 00:40:46,640 Otherwise, go ahead and pause the animation 790 00:40:46,640 --> 00:40:50,850 by modifying that animation-play-state property of the heading. 791 00:40:50,850 --> 00:40:54,080 So now if I refresh this page, right now we have "Welcome!" plus a button 792 00:40:54,080 --> 00:40:55,110 that says, "Click Here!" 793 00:40:55,110 --> 00:40:56,610 And initially, everything is paused. 794 00:40:56,610 --> 00:40:58,190 There's no animation happening. 795 00:40:58,190 --> 00:41:00,910 But I click here, and that begins the animation, which 796 00:41:00,910 --> 00:41:04,820 would go on indefinitely until I decide that I want to stop it, at which point 797 00:41:04,820 --> 00:41:07,470 I click it again, and the animation pauses. 798 00:41:07,470 --> 00:41:12,430 And I can control when to start and when to pause that animation, as well. 799 00:41:12,430 --> 00:41:14,330 And so this can be helpful and nice when you 800 00:41:14,330 --> 00:41:16,622 want to create something a little bit more interactive, 801 00:41:16,622 --> 00:41:19,310 something animated on the page, but this is especially helpful 802 00:41:19,310 --> 00:41:23,880 because it means that you can gradually change CSS properties over time. 803 00:41:23,880 --> 00:41:25,880 Rather than just immediately change something, 804 00:41:25,880 --> 00:41:27,950 you have the ability to animate something, 805 00:41:27,950 --> 00:41:29,730 to make it work a little bit better. 806 00:41:29,730 --> 00:41:31,700 So let's take a look at an example of how 807 00:41:31,700 --> 00:41:34,130 you might put that idea into practice. 808 00:41:34,130 --> 00:41:38,840 Let's go back to our posts example, where we had this infinite scrolling 809 00:41:38,840 --> 00:41:42,620 list of posts, but imagine now that we want the ability to hide posts 810 00:41:42,620 --> 00:41:44,010 when we're done with them. 811 00:41:44,010 --> 00:41:47,270 So I've prepared an example called hide, which 812 00:41:47,270 --> 00:41:50,610 is very similar to what we had before. 813 00:41:50,610 --> 00:41:53,630 But this time I've just added one extra button, 814 00:41:53,630 --> 00:41:56,658 and the button says, "Hide," on every single div. 815 00:41:56,658 --> 00:41:58,700 Right now, clicking the Hide button does nothing. 816 00:41:58,700 --> 00:42:00,825 We'll go ahead and implement that in just a moment. 817 00:42:00,825 --> 00:42:03,410 But first, to see how this worked, if you go into hide, 818 00:42:03,410 --> 00:42:06,590 go into the index.html template. 819 00:42:06,590 --> 00:42:10,550 The only change that's been made here is what happens when I add a new post. 820 00:42:10,550 --> 00:42:12,500 Recall, again, that what this application does 821 00:42:12,500 --> 00:42:15,710 is it loads posts from a server, and then when it gets to those posts, 822 00:42:15,710 --> 00:42:19,330 it loops over each of the individual posts, which is just a string of text. 823 00:42:19,330 --> 00:42:23,960 And it adds that string of text inside of an element onto the page it via this 824 00:42:23,960 --> 00:42:25,970 add post function. 825 00:42:25,970 --> 00:42:28,130 And what the add post function is going to do here 826 00:42:28,130 --> 00:42:32,433 is first create a new element, create a div in which to store that post, 827 00:42:32,433 --> 00:42:35,600 give it a class name, because that's how we're going to animate it, and then 828 00:42:35,600 --> 00:42:40,190 set its inner HTML equal to the contents of the post, something like post 829 00:42:40,190 --> 00:42:42,650 number one, post number two, post number three, 830 00:42:42,650 --> 00:42:46,030 and then add a button that just says, "Hide." 831 00:42:46,030 --> 00:42:49,138 And then we're going to go ahead and add that to the DOM, as well. 832 00:42:49,138 --> 00:42:50,930 So that's what add post is now going to do. 833 00:42:50,930 --> 00:42:54,710 We're generating some HTML using this JavaScript code 834 00:42:54,710 --> 00:42:56,960 and then adding that HTML to the page. 835 00:42:56,960 --> 00:42:58,970 And now what we're adding is a div that has not 836 00:42:58,970 --> 00:43:01,520 only the contents of the post as text, but is also 837 00:43:01,520 --> 00:43:05,090 going to give us access to a button that ultimately, we hope, 838 00:43:05,090 --> 00:43:08,370 is going to let us hide that post, as well. 839 00:43:08,370 --> 00:43:11,720 So how do we actually get the hiding of the post to work? 840 00:43:11,720 --> 00:43:14,210 Well, what we want to do is somehow detect 841 00:43:14,210 --> 00:43:17,300 when the user clicks on one of those Hide buttons. 842 00:43:17,300 --> 00:43:19,320 So there's a number of ways we could do this, 843 00:43:19,320 --> 00:43:23,270 but one way is just to listen for anytime anyone 844 00:43:23,270 --> 00:43:28,160 clicks on the document as a whole. 845 00:43:28,160 --> 00:43:32,450 Anytime anyone clicks on the document, I might like to ask something like, 846 00:43:32,450 --> 00:43:34,530 what did they actually click on? 847 00:43:34,530 --> 00:43:36,530 And it turns out that with most event listeners, 848 00:43:36,530 --> 00:43:38,930 the function the event listener takes in can 849 00:43:38,930 --> 00:43:42,350 take as an optional argument the event itself, which 850 00:43:42,350 --> 00:43:46,340 is a JavaScript object that contains information about the event that 851 00:43:46,340 --> 00:43:49,340 happened, like the click event, or the scroll event, or the keydown 852 00:43:49,340 --> 00:43:51,510 event, or the keyup event, for example. 853 00:43:51,510 --> 00:43:56,570 And one of the properties you get access to is event.target, which is like, 854 00:43:56,570 --> 00:43:58,470 what was the target of the event? 855 00:43:58,470 --> 00:44:01,530 In this case, what was the thing that was actually clicked on? 856 00:44:01,530 --> 00:44:06,020 And I'll go ahead and save event.target inside of a variable called 857 00:44:06,020 --> 00:44:09,650 element, where the idea now is that whatever gets clicked on, that is 858 00:44:09,650 --> 00:44:10,760 the event's target. 859 00:44:10,760 --> 00:44:12,740 We're going to save that inside of element. 860 00:44:12,740 --> 00:44:15,200 And what I want to know is, is element-- 861 00:44:15,200 --> 00:44:16,790 is that one of the Hide buttons? 862 00:44:16,790 --> 00:44:18,290 I want to know, is it a Hide button? 863 00:44:18,290 --> 00:44:21,428 I could have also attached an event listener to each of the hide buttons. 864 00:44:21,428 --> 00:44:23,220 This is just an alternative way of doing it 865 00:44:23,220 --> 00:44:25,310 that I'm showing you for sake of demonstration, 866 00:44:25,310 --> 00:44:27,620 where we say when we click anywhere in the document, 867 00:44:27,620 --> 00:44:31,110 figure out what was clicked on, and save it inside of this variable. 868 00:44:31,110 --> 00:44:35,150 And if it's a Hide button, then it's going to have a class of hide, 869 00:44:35,150 --> 00:44:39,700 because I gave every Hide button a class of hide. 870 00:44:39,700 --> 00:44:47,133 And so what I can say is, if element.className equals hide, well, 871 00:44:47,133 --> 00:44:50,050 that means that what was clicked on is something with a class of hide. 872 00:44:50,050 --> 00:44:53,030 We can assume that it is, in fact, a Hide button. 873 00:44:53,030 --> 00:44:56,950 And then what I want to do is I can do something like element.remove 874 00:44:56,950 --> 00:45:00,320 to say, go ahead and get rid of that element. 875 00:45:00,320 --> 00:45:01,870 So now what does this do? 876 00:45:01,870 --> 00:45:04,017 If I refresh the page, let's try it. 877 00:45:04,017 --> 00:45:05,350 Post number one-- if I hide it-- 878 00:45:05,350 --> 00:45:07,572 I want to hide post number one. 879 00:45:07,572 --> 00:45:08,530 That didn't quite work. 880 00:45:08,530 --> 00:45:09,250 It was close. 881 00:45:09,250 --> 00:45:11,320 It got rid of the Hide button, but I didn't 882 00:45:11,320 --> 00:45:12,778 want to get rid of the Hide button. 883 00:45:12,778 --> 00:45:14,470 I wanted to get rid of the whole post. 884 00:45:14,470 --> 00:45:18,610 So what's going on here is it seems to be that if the element's class name is 885 00:45:18,610 --> 00:45:20,980 hide, meaning I clicked on a Hide button, 886 00:45:20,980 --> 00:45:23,890 element.remove just removes that element. 887 00:45:23,890 --> 00:45:26,410 It removes the Hide button, but it doesn't 888 00:45:26,410 --> 00:45:28,610 remove the post that contains it. 889 00:45:28,610 --> 00:45:31,870 And if you think about this in terms of the DOM, the post is a div, 890 00:45:31,870 --> 00:45:35,410 and its child element is the button, this Hide button. 891 00:45:35,410 --> 00:45:39,220 And so you remove the button, but it doesn't also remove the post, as well. 892 00:45:39,220 --> 00:45:41,080 If you want to remove the post, as well, you 893 00:45:41,080 --> 00:45:44,310 need to remove not the element, but the element's parent. 894 00:45:44,310 --> 00:45:46,930 And in JavaScript, it turns out there's a way to do that, too. 895 00:45:46,930 --> 00:45:52,630 Rather than element.remove, I can say element.parentElement.remove to say, 896 00:45:52,630 --> 00:45:56,450 take the element, get its parent, and remove that. 897 00:45:56,450 --> 00:45:58,940 So now I refresh the page. 898 00:45:58,940 --> 00:46:00,310 Now I see post one. 899 00:46:00,310 --> 00:46:01,330 I want to hide it. 900 00:46:01,330 --> 00:46:04,675 I hide post one, and now I see post two. 901 00:46:04,675 --> 00:46:05,800 And post one has gone away. 902 00:46:05,800 --> 00:46:08,540 If I want to hide post three, I hide post 3. 903 00:46:08,540 --> 00:46:09,400 Now post 3 is gone. 904 00:46:09,400 --> 00:46:12,460 Now I go straight from post two to post four. 905 00:46:12,460 --> 00:46:16,930 So this works, but it's also not immediately obvious what's going on. 906 00:46:16,930 --> 00:46:19,600 Because all of the posts are the exact same height, when 907 00:46:19,600 --> 00:46:22,780 I get rid of post one and three, it's not immediately obvious to the eye 908 00:46:22,780 --> 00:46:25,480 that they've gone away, because post two and four-- 909 00:46:25,480 --> 00:46:26,980 they look almost exactly the same. 910 00:46:26,980 --> 00:46:30,320 You really have to be paying attention to know that the hiding worked. 911 00:46:30,320 --> 00:46:32,980 And so this can be a time where animation can actually 912 00:46:32,980 --> 00:46:34,550 be quite helpful. 913 00:46:34,550 --> 00:46:38,260 So what I can do is say something like, let's go ahead 914 00:46:38,260 --> 00:46:43,650 and give this post an animation associated with every post. 915 00:46:43,650 --> 00:46:46,470 We'll give it an animation name called hide, 916 00:46:46,470 --> 00:46:49,720 an animation duration of two seconds-- we'll say it'll take you two seconds 917 00:46:49,720 --> 00:46:51,160 in order to hide-- 918 00:46:51,160 --> 00:46:53,150 and an animation fill mode of forwards. 919 00:46:53,150 --> 00:46:55,090 I want to go forwards with the animation. 920 00:46:55,090 --> 00:47:00,897 And initially, I'll give the post an animation-play-state of paused, meaning 921 00:47:00,897 --> 00:47:03,730 initially, I don't want the animation to be running, because I don't 922 00:47:03,730 --> 00:47:05,460 want to hide all the posts immediately. 923 00:47:05,460 --> 00:47:06,970 Pause this animation. 924 00:47:06,970 --> 00:47:09,220 Later we'll go ahead and run the animation 925 00:47:09,220 --> 00:47:12,520 in order to actually hide the post. 926 00:47:12,520 --> 00:47:16,840 Then I need to define what does it actually mean to hide the post. 927 00:47:16,840 --> 00:47:19,980 And I'll say, well, at the 0% mark, what does it mean? 928 00:47:19,980 --> 00:47:22,000 Let's give yourselves an opacity of 1. 929 00:47:22,000 --> 00:47:25,120 Opacity is a CSS property that just controls how opaque 930 00:47:25,120 --> 00:47:28,550 or how transparent an HTML element happens to be. 931 00:47:28,550 --> 00:47:31,580 And at the end, 100% of the way done with the animation, 932 00:47:31,580 --> 00:47:33,760 we'll set opacity to 0. 933 00:47:33,760 --> 00:47:36,040 So initially, we can fully see the element. 934 00:47:36,040 --> 00:47:38,770 At the end, the element is totally transparent. 935 00:47:38,770 --> 00:47:43,490 And now what I need to do is actually trigger this to happen somehow. 936 00:47:43,490 --> 00:47:47,120 So this is probably going to happen inside of my event listener, 937 00:47:47,120 --> 00:47:50,170 where instead of removing the element right away, 938 00:47:50,170 --> 00:47:54,880 let me just take the parent element and set its animation-play-state 939 00:47:54,880 --> 00:48:01,090 equal to running, for example, meaning when I click the Hide button, 940 00:48:01,090 --> 00:48:03,520 go ahead and run the animation that will change 941 00:48:03,520 --> 00:48:08,590 the opacity from 1 to 0 over the course of a couple of seconds. 942 00:48:08,590 --> 00:48:11,920 And then, if I really want to, I can add another event listener to say, 943 00:48:11,920 --> 00:48:15,510 take the parent element, add event listener. 944 00:48:15,510 --> 00:48:19,210 There is an event called animationend, which 945 00:48:19,210 --> 00:48:21,820 happens when the animation is over. 946 00:48:21,820 --> 00:48:24,440 And then I can say, when the animation is over, 947 00:48:24,440 --> 00:48:29,410 we'll then go ahead and remove the element. 948 00:48:29,410 --> 00:48:31,377 So all in all, rather than just immediately 949 00:48:31,377 --> 00:48:33,460 remove the element when I click on the button that 950 00:48:33,460 --> 00:48:36,850 says "Hide," what I'd like to do is say, if you click on a button 951 00:48:36,850 --> 00:48:40,030 and the button is Hide, go ahead and get the parent element, not 952 00:48:40,030 --> 00:48:42,340 the Hide button, but the post itself. 953 00:48:42,340 --> 00:48:46,450 Set its animation-play-state to running, meaning run the hide animation, 954 00:48:46,450 --> 00:48:50,170 and then add an event listener to the parent, to that post of the whole, 955 00:48:50,170 --> 00:48:54,340 to say, when the animation is over, go ahead and remove that entire post 956 00:48:54,340 --> 00:48:56,800 from the DOM altogether. 957 00:48:56,800 --> 00:48:59,860 So what is the effect of all of this now, of having this animation 958 00:48:59,860 --> 00:49:01,700 and running it? 959 00:49:01,700 --> 00:49:04,760 Well, now, if I refresh the page, I see all these posts. 960 00:49:04,760 --> 00:49:07,670 If I try and hide post number two, for example, you'll 961 00:49:07,670 --> 00:49:11,820 see that the opacity changes, and then it slowly disappears. 962 00:49:11,820 --> 00:49:13,880 And then only after it's totally transparent, 963 00:49:13,880 --> 00:49:15,270 the post disappears entirely. 964 00:49:15,270 --> 00:49:17,360 So I can say, hide post number four. 965 00:49:17,360 --> 00:49:20,812 It disappears, and then post number five jumps up to fill its place. 966 00:49:20,812 --> 00:49:22,520 And I can do that for any of these posts, 967 00:49:22,520 --> 00:49:25,970 triggering the animation when I click on the Hide button. 968 00:49:25,970 --> 00:49:28,790 And so this is part of the value of what animation can do 969 00:49:28,790 --> 00:49:31,310 is to be able to make our user interfaces a little more 970 00:49:31,310 --> 00:49:33,200 pleasant from the perspective of the user 971 00:49:33,200 --> 00:49:36,660 by not immediately getting rid of a post, but by having a nice fade-out 972 00:49:36,660 --> 00:49:38,420 so it disappears nicely. 973 00:49:38,420 --> 00:49:40,880 Now, even this is not perfect animation-wise. 974 00:49:40,880 --> 00:49:44,720 One thing you might notice is that it jumps up as soon as the post is gone. 975 00:49:44,720 --> 00:49:47,090 If I hide post number three, I hide it, it 976 00:49:47,090 --> 00:49:51,410 disappears, and post five jumps up very abruptly in order to fill its place. 977 00:49:51,410 --> 00:49:55,160 What I might like is to be a little bit clever, to somehow shrink 978 00:49:55,160 --> 00:49:59,720 the size of the post after it's gone so that the post doesn't jump into place, 979 00:49:59,720 --> 00:50:02,332 but it slides a little bit more naturally into place. 980 00:50:02,332 --> 00:50:04,790 And so there's some additional things I can play with here. 981 00:50:04,790 --> 00:50:10,410 Maybe I want to say, let me make this animation a multiple part animation. 982 00:50:10,410 --> 00:50:14,360 So here, instead of just from 0% to 100%, setting the opacity from 1 983 00:50:14,360 --> 00:50:18,740 to 0, maybe in the first 75% of the animation that 984 00:50:18,740 --> 00:50:22,040 will take care of reducing the opacity, going down from 1 all the way down 985 00:50:22,040 --> 00:50:22,910 to 0. 986 00:50:22,910 --> 00:50:28,940 But in the last 25% of the animation, we'll still end with an opacity of 0, 987 00:50:28,940 --> 00:50:33,370 but anything that creates vertical space I want to reduce down to 0. 988 00:50:33,370 --> 00:50:35,750 So the height should be 0 pixels. 989 00:50:35,750 --> 00:50:39,210 The line height, which is how high the text should also be 0 pixels, 990 00:50:39,210 --> 00:50:41,717 and any padding I want to go away. 991 00:50:41,717 --> 00:50:44,300 It turns out I've added some margin to the bottom of the post. 992 00:50:44,300 --> 00:50:46,200 I want to make that go away, as well. 993 00:50:46,200 --> 00:50:49,790 So I want to get all of those to 0 from whatever their initial values happened 994 00:50:49,790 --> 00:50:53,630 to be, that initially, the height is, like, 100% of what the height could be, 995 00:50:53,630 --> 00:50:56,570 likewise, for line height, 100% of the parent. 996 00:50:56,570 --> 00:50:58,850 Initially, I have, like, 20 pixels of padding 997 00:50:58,850 --> 00:51:01,390 and a margin at the bottom of 10 pixels. 998 00:51:01,390 --> 00:51:07,070 And I want all of that to still be true 75% of the way through the animation, 999 00:51:07,070 --> 00:51:09,813 but it's only in the last 25% of the animation 1000 00:51:09,813 --> 00:51:12,230 that I want to set all of these vertical height properties 1001 00:51:12,230 --> 00:51:14,897 down to 0, when I remove all the height, remove the line height, 1002 00:51:14,897 --> 00:51:16,070 remove all the padding. 1003 00:51:16,070 --> 00:51:20,060 And the effect of this as will have an animation now where for the first 75% 1004 00:51:20,060 --> 00:51:23,150 of the animation, the only thing that changes is the opacity. . 1005 00:51:23,150 --> 00:51:28,100 The opacity goes from 1, fully visible, to 0, fully transparent. 1006 00:51:28,100 --> 00:51:30,780 And then in the last 25% of the animation, 1007 00:51:30,780 --> 00:51:32,330 the post is already transparent. 1008 00:51:32,330 --> 00:51:33,740 You can't see it. 1009 00:51:33,740 --> 00:51:36,410 But it's still taking up physical space on the page, 1010 00:51:36,410 --> 00:51:38,870 but we're going to now reduce the height of that post 1011 00:51:38,870 --> 00:51:42,360 so that now you won't be able to see it at all. 1012 00:51:42,360 --> 00:51:45,950 So now, if I refresh this page, here, again, are all the posts, 1013 00:51:45,950 --> 00:51:48,260 but now, if I click Hide on a particular post, 1014 00:51:48,260 --> 00:51:50,030 we'll see that it first fades out. 1015 00:51:50,030 --> 00:51:52,220 And then its height shrinks so that the next post 1016 00:51:52,220 --> 00:51:54,110 slides very nicely into place. 1017 00:51:54,110 --> 00:51:57,020 I can do that again, hide the post, transparent, 1018 00:51:57,020 --> 00:51:58,700 and then it slides into place. 1019 00:51:58,700 --> 00:52:02,720 And this, again, is just an application of this idea of CSS animation, 1020 00:52:02,720 --> 00:52:06,140 using properties of animation to make our interfaces a little bit 1021 00:52:06,140 --> 00:52:08,450 nicer to use, a little bit clearer, visually, 1022 00:52:08,450 --> 00:52:11,630 to the user that one post has gone away, and the rest of the posts 1023 00:52:11,630 --> 00:52:15,810 have now scrolled up in order to take their place. 1024 00:52:15,810 --> 00:52:18,080 So now we've been able to use JavaScript to create 1025 00:52:18,080 --> 00:52:19,580 a lot of nice user interfaces. 1026 00:52:19,580 --> 00:52:21,800 We've been able to create single-page applications, 1027 00:52:21,800 --> 00:52:25,250 to create infinite scrolling, to be able to create some animations, as well 1028 00:52:25,250 --> 00:52:27,367 and use JavaScript to be able to control them. 1029 00:52:27,367 --> 00:52:29,450 But one thing you might be realizing at this point 1030 00:52:29,450 --> 00:52:32,460 is that our applications are starting to get fairly complicated. 1031 00:52:32,460 --> 00:52:34,970 There's a lot of JavaScript code needed to manipulate 1032 00:52:34,970 --> 00:52:37,700 a lot of different parts of our application at the same time. 1033 00:52:37,700 --> 00:52:40,700 And you can imagine that as web pages start to get more complex, 1034 00:52:40,700 --> 00:52:43,873 and as you want to start making them more interactive and more dynamic, 1035 00:52:43,873 --> 00:52:46,790 there's going to be a lot of JavaScript code required in order to keep 1036 00:52:46,790 --> 00:52:49,700 everything in sync, in order to make sure that all of the elements 1037 00:52:49,700 --> 00:52:52,410 are updated when they should, so on and so forth. 1038 00:52:52,410 --> 00:52:55,160 And it's for that reason that in recent years, a lot of JavaScript 1039 00:52:55,160 --> 00:52:58,430 has now turned to some JavaScript libraries or frameworks that 1040 00:52:58,430 --> 00:53:01,010 allow to more efficiently and more effectively 1041 00:53:01,010 --> 00:53:05,150 create user interfaces that are more interactive and more reactive. 1042 00:53:05,150 --> 00:53:08,540 And one of the most popular of these is a framework known as React. 1043 00:53:08,540 --> 00:53:10,760 React as a JavaScript library that is going 1044 00:53:10,760 --> 00:53:14,330 to enable us to be able to design user interfaces that 1045 00:53:14,330 --> 00:53:17,360 are very interactive, where the content of the web page updates 1046 00:53:17,360 --> 00:53:20,120 automatically based on some underlying state. 1047 00:53:20,120 --> 00:53:23,090 And what we'll do now is take a look at a brief taste of React 1048 00:53:23,090 --> 00:53:26,270 to get a sense for how frameworks like it can actually work 1049 00:53:26,270 --> 00:53:29,720 and can help us in designing some interactive and useful interfaces 1050 00:53:29,720 --> 00:53:32,100 for users to be able to interact with. 1051 00:53:32,100 --> 00:53:35,900 React is ultimately based on this idea of declarative programming, 1052 00:53:35,900 --> 00:53:37,848 a particular style of programming which is 1053 00:53:37,848 --> 00:53:40,640 different from the types of programming you might be familiar with, 1054 00:53:40,640 --> 00:53:44,390 more classical programming styles like imperative programming. 1055 00:53:44,390 --> 00:53:47,780 In imperative programming, you generally give the computer commands, 1056 00:53:47,780 --> 00:53:49,500 tell the computer what to do. 1057 00:53:49,500 --> 00:53:52,400 For example, if we had that counter program from before 1058 00:53:52,400 --> 00:53:55,520 and we wanted to update the counter from one number to another number, 1059 00:53:55,520 --> 00:53:58,480 in the view, the HTML that the user sees, 1060 00:53:58,480 --> 00:54:00,410 we would include something like a heading 1061 00:54:00,410 --> 00:54:02,610 that just has the 0 inside of it. 1062 00:54:02,610 --> 00:54:05,160 And then the logic in imperative programming 1063 00:54:05,160 --> 00:54:06,960 would take something like this form. 1064 00:54:06,960 --> 00:54:10,440 It would be like, first, document.querySelector h1 1065 00:54:10,440 --> 00:54:14,580 to get that each h1 tag, get it it's inner HTML, parseInt. 1066 00:54:14,580 --> 00:54:16,920 We'll take the string and convert it into an integer. 1067 00:54:16,920 --> 00:54:20,490 And we can save that inside of a variable called num, for example. 1068 00:54:20,490 --> 00:54:22,500 And then after that, if I want to increase it, 1069 00:54:22,500 --> 00:54:26,520 I would take this variable num and just add 1 to it, num plus equals 1, 1070 00:54:26,520 --> 00:54:27,587 add 1 to it. 1071 00:54:27,587 --> 00:54:29,670 And then if I want to update this heading in order 1072 00:54:29,670 --> 00:54:32,340 to replace the 0 with a 1, for example, well, 1073 00:54:32,340 --> 00:54:35,400 then I would need to say, document.querySelector h1, set 1074 00:54:35,400 --> 00:54:39,330 the inner HTML equal to that number, for instance, in order to say, 1075 00:54:39,330 --> 00:54:40,380 num is now 1. 1076 00:54:40,380 --> 00:54:43,540 Go ahead and replace that in the view. 1077 00:54:43,540 --> 00:54:46,800 But this is a fair amount of code to do something fairly simple, 1078 00:54:46,800 --> 00:54:48,302 just increase a number by 1. 1079 00:54:48,302 --> 00:54:50,010 And the reason why is because we have had 1080 00:54:50,010 --> 00:54:52,470 to be very explicit about what instructions we're 1081 00:54:52,470 --> 00:54:53,730 giving to the web browser. 1082 00:54:53,730 --> 00:54:55,495 We're saying, first, grab the h1. 1083 00:54:55,495 --> 00:54:57,120 Figure out what number is inside of it. 1084 00:54:57,120 --> 00:55:01,250 Add 1 to that number, and then replace it inside of this tag. 1085 00:55:01,250 --> 00:55:03,870 What declarative program is going to allow us to do 1086 00:55:03,870 --> 00:55:07,020 is it's going to allow us to just describe what state should 1087 00:55:07,020 --> 00:55:09,270 be displayed on the page in what form. 1088 00:55:09,270 --> 00:55:12,830 In declarative programming, in our view, the HTML-like code 1089 00:55:12,830 --> 00:55:14,580 that we're going to be writing, we're just 1090 00:55:14,580 --> 00:55:19,290 going to say something like, h1 and then in curly braces, num to mean, 1091 00:55:19,290 --> 00:55:21,010 fill in the number here. 1092 00:55:21,010 --> 00:55:23,760 And this is what the React syntax is going to look like. 1093 00:55:23,760 --> 00:55:27,480 And then the logic code, if we want to increment that number by 1, 1094 00:55:27,480 --> 00:55:31,890 is we just need to say, num plus equals 1, add 1 to the number, 1095 00:55:31,890 --> 00:55:34,498 and the effect of that is that since we have declared 1096 00:55:34,498 --> 00:55:37,540 that inside of this heading it should be whatever the value of the number 1097 00:55:37,540 --> 00:55:40,050 is, when we increment the value of number, 1098 00:55:40,050 --> 00:55:43,740 React is effectively just going to update the view so 1099 00:55:43,740 --> 00:55:45,753 that the number updates, as well. 1100 00:55:45,753 --> 00:55:48,170 And so this will be some of the power that React gives us. 1101 00:55:48,170 --> 00:55:51,390 React lets us divide our application into a whole bunch 1102 00:55:51,390 --> 00:55:54,003 of different components, where a component is something 1103 00:55:54,003 --> 00:55:56,670 like this thing here that is keeping track of some sort of count 1104 00:55:56,670 --> 00:55:59,040 along with a button that might manipulate it and then 1105 00:55:59,040 --> 00:56:02,550 make that component based on some underlying state, some underlying 1106 00:56:02,550 --> 00:56:05,460 variables that represent the state of the application, 1107 00:56:05,460 --> 00:56:07,230 something like the current number. 1108 00:56:07,230 --> 00:56:08,978 And then we can manipulate that state. 1109 00:56:08,978 --> 00:56:10,770 And when we manipulate the state, that will 1110 00:56:10,770 --> 00:56:13,020 have an impact on what the user actually sees, 1111 00:56:13,020 --> 00:56:17,400 and React will handle the process of updating that user interface for us. 1112 00:56:17,400 --> 00:56:20,220 There are a number of ways to get react to working on our web page, 1113 00:56:20,220 --> 00:56:23,760 but the simplest is probably just to include these three JavaScript 1114 00:56:23,760 --> 00:56:27,310 packages inside of our web page. 1115 00:56:27,310 --> 00:56:29,185 So we're first going to include React itself, 1116 00:56:29,185 --> 00:56:31,977 which is going to be the library that's going to allow us to define 1117 00:56:31,977 --> 00:56:33,690 these components and how they behave. 1118 00:56:33,690 --> 00:56:36,210 Then is ReactDOM, a special package that's 1119 00:56:36,210 --> 00:56:38,970 going to allow us to take react components 1120 00:56:38,970 --> 00:56:42,810 and insert them into the DOM, the Document Object Model, that represents 1121 00:56:42,810 --> 00:56:44,770 the structure of the entire page. 1122 00:56:44,770 --> 00:56:47,040 And then finally, Babel is going to be a package 1123 00:56:47,040 --> 00:56:49,620 that we're going to use in order to translate code 1124 00:56:49,620 --> 00:56:51,330 from one language to another. 1125 00:56:51,330 --> 00:56:53,890 It turns out that when we're writing React code, 1126 00:56:53,890 --> 00:56:56,340 we're not actually going to be writing JavaScript. 1127 00:56:56,340 --> 00:57:00,600 We're going to be writing in an extension to JavaScript known as JSX, 1128 00:57:00,600 --> 00:57:03,210 and JSX is going to be an extension of JavaScript that 1129 00:57:03,210 --> 00:57:06,210 looks a lot like JavaScript, but has some additional features. 1130 00:57:06,210 --> 00:57:09,180 In particular, it has the ability to effectively allow 1131 00:57:09,180 --> 00:57:12,615 us to represent HTML inside of our JavaScript code 1132 00:57:12,615 --> 00:57:14,490 in a way that's much easier to read, and it's 1133 00:57:14,490 --> 00:57:16,830 going to be convenient for us to deal with. 1134 00:57:16,830 --> 00:57:20,320 Browsers, on the other hand, don't understand JSX automatically, 1135 00:57:20,320 --> 00:57:22,380 so what we're going to use is a tool like Babel 1136 00:57:22,380 --> 00:57:25,740 to convert that JSX code into plain JavaScript 1137 00:57:25,740 --> 00:57:29,250 that our web browsers are ultimately going to be able to understand. 1138 00:57:29,250 --> 00:57:32,500 The best way to get a feel for this kind of thing is just to see it in action. 1139 00:57:32,500 --> 00:57:35,430 So I'll go ahead and create a couple of React applications 1140 00:57:35,430 --> 00:57:38,100 just to get a sense for how it is that you can use React 1141 00:57:38,100 --> 00:57:40,740 in your own applications, as well. 1142 00:57:40,740 --> 00:57:43,142 So I'm now going to take a look at react.html, 1143 00:57:43,142 --> 00:57:46,260 which just contains the basic structure for an HTML page, 1144 00:57:46,260 --> 00:57:50,460 that so far, all it's doing is including those three JavaScript packages we 1145 00:57:50,460 --> 00:57:53,370 talked about a moment ago by using these scripts tags to say, 1146 00:57:53,370 --> 00:57:59,590 I would like to include those JavaScript files inside of this web page, as well. 1147 00:57:59,590 --> 00:58:05,423 Now, inside the body of this HTML page, I'll just have a div whose ID is app, 1148 00:58:05,423 --> 00:58:06,840 and it's going to be an empty div. 1149 00:58:06,840 --> 00:58:09,132 It's not going to have anything inside of it initially, 1150 00:58:09,132 --> 00:58:10,923 because what we're ultimately going to have 1151 00:58:10,923 --> 00:58:13,140 happen is we're going to have React put something, 1152 00:58:13,140 --> 00:58:16,050 in particular, put what React calls a component 1153 00:58:16,050 --> 00:58:19,167 inside of that part of the body. 1154 00:58:19,167 --> 00:58:21,000 So now here comes some JavaScript, and we're 1155 00:58:21,000 --> 00:58:22,950 going to put this inside of script tags. 1156 00:58:22,950 --> 00:58:25,830 But because this isn't strictly speaking going to be JavaScript-- 1157 00:58:25,830 --> 00:58:29,040 it's going to be an extension to JavaScript called JSX-- 1158 00:58:29,040 --> 00:58:31,050 I'm going to add an attribute to the script tag 1159 00:58:31,050 --> 00:58:36,300 to say its type is equal to text/babel to mean Babel should translate 1160 00:58:36,300 --> 00:58:40,380 this code from JSX to plain JavaScript that the web browser is 1161 00:58:40,380 --> 00:58:41,490 able to understand. 1162 00:58:41,490 --> 00:58:43,480 Ultimately, this is going to take some time, 1163 00:58:43,480 --> 00:58:46,752 and in practice, you probably want to do this compilation before users end up 1164 00:58:46,752 --> 00:58:49,710 using the page, but for now, this will make our lives a little bit more 1165 00:58:49,710 --> 00:58:51,050 convenient. 1166 00:58:51,050 --> 00:58:55,440 And what we need to do inside of here now is define a React component, 1167 00:58:55,440 --> 00:58:58,080 and all a component is just something on the web page 1168 00:58:58,080 --> 00:59:00,420 that has some view, something the users can see, 1169 00:59:00,420 --> 00:59:02,440 when the component gets rendered to the screen 1170 00:59:02,440 --> 00:59:05,890 and maybe has some underlying properties in state that we can manipulate, 1171 00:59:05,890 --> 00:59:06,918 as well. 1172 00:59:06,918 --> 00:59:08,710 And it turns out that every React component 1173 00:59:08,710 --> 00:59:11,077 is organized into a JavaScript class. 1174 00:59:11,077 --> 00:59:12,910 In the same way that Python had classes when 1175 00:59:12,910 --> 00:59:15,460 we were talking about object-oriented programming, 1176 00:59:15,460 --> 00:59:18,580 JavaScript, too, has classes that we can create that, in this case, 1177 00:59:18,580 --> 00:59:21,478 are going to represent React components. 1178 00:59:21,478 --> 00:59:24,520 So here, I'm going to create a new class that I'm just going to call App, 1179 00:59:24,520 --> 00:59:26,380 but you can call it anything you want. 1180 00:59:26,380 --> 00:59:29,450 And it's going to extend React.Component, 1181 00:59:29,450 --> 00:59:32,050 meaning I'm creating a new class called App, 1182 00:59:32,050 --> 00:59:35,110 and this app is going to be a React component. 1183 00:59:35,110 --> 00:59:40,150 And every React component needs a function or a method called render, 1184 00:59:40,150 --> 00:59:44,140 and what render is going to do is return what HTML should display 1185 00:59:44,140 --> 00:59:46,070 when you look at this component. 1186 00:59:46,070 --> 00:59:48,100 So here I'm going to return, and now this 1187 00:59:48,100 --> 00:59:50,830 is where the JavaScript JSX part comes in. 1188 00:59:50,830 --> 00:59:53,380 Rather than just include JavaScript here, 1189 00:59:53,380 --> 00:59:58,210 I can actually include HTML-like syntax as what I return. 1190 00:59:58,210 --> 01:00:04,540 So I can return something like a div that says, "Hello!" 1191 01:00:04,540 --> 01:00:05,920 for example. 1192 01:00:05,920 --> 01:00:08,440 So when I render the app component, what's 1193 01:00:08,440 --> 01:00:12,267 going to display on this page is a div that is just going to say, "Hello!" 1194 01:00:12,267 --> 01:00:14,350 That's what this entire class called App is doing. 1195 01:00:14,350 --> 01:00:17,960 It is a React component, and when I render the React component, 1196 01:00:17,960 --> 01:00:22,390 we are going to return a div that just says, "Hello!" 1197 01:00:22,390 --> 01:00:26,330 And then the last step is to say, now that I have this component, 1198 01:00:26,330 --> 01:00:28,120 let's go ahead and render it into the DOM. 1199 01:00:28,120 --> 01:00:30,440 Let's render it into the page. 1200 01:00:30,440 --> 01:00:34,520 And to do that, I call ReactDOM.render and say, 1201 01:00:34,520 --> 01:00:41,230 I would like to put the App component into document.querySelector 1202 01:00:41,230 --> 01:00:44,690 app, the element whose ID is app. 1203 01:00:44,690 --> 01:00:46,600 So here is that element whose ID is app. 1204 01:00:46,600 --> 01:00:49,150 And what I'm saying is in that part of the page, 1205 01:00:49,150 --> 01:00:52,690 go ahead and insert the app component, and the syntax 1206 01:00:52,690 --> 01:00:55,390 for creating a component kind of looks like the syntax 1207 01:00:55,390 --> 01:00:57,280 for creating an HTML element in the sense 1208 01:00:57,280 --> 01:00:58,990 that it has these angled brackets. 1209 01:00:58,990 --> 01:01:02,260 Effectively, I have created this app component, 1210 01:01:02,260 --> 01:01:05,540 and I would like to insert it into the page. 1211 01:01:05,540 --> 01:01:10,880 So now, if I open up react.html, here's what I see. 1212 01:01:10,880 --> 01:01:13,150 I see a div that, in this case, says "Hello!" 1213 01:01:13,150 --> 01:01:15,110 because that's what was inside of my component. 1214 01:01:15,110 --> 01:01:17,440 And if I change the component to say something else, 1215 01:01:17,440 --> 01:01:21,800 like if I added an h1 at the top of it that just said, "Welcome!" 1216 01:01:21,800 --> 01:01:26,013 for example, well, then now, when I refresh the page, 1217 01:01:26,013 --> 01:01:28,930 that's what the component now looks like, big h1 that says, "Welcome!" 1218 01:01:28,930 --> 01:01:33,430 Underneath it, it's got a line that just says, "Hello!" for example. 1219 01:01:33,430 --> 01:01:37,342 So that then is an instance of our very first React component, 1220 01:01:37,342 --> 01:01:39,550 but what's really powerful about React is the ability 1221 01:01:39,550 --> 01:01:41,470 to compose components inside of each other, 1222 01:01:41,470 --> 01:01:45,410 to have a component that is inside of another component, for example. 1223 01:01:45,410 --> 01:01:49,660 So let me define, now, another component that I'll call Hello, which 1224 01:01:49,660 --> 01:01:53,230 will extend React.Component. 1225 01:01:53,230 --> 01:01:55,960 And when I render the Hello component, what should happen? 1226 01:01:55,960 --> 01:01:59,770 Well, I'm going to return just an h1 that says, "Hello!" 1227 01:01:59,770 --> 01:02:02,810 1228 01:02:02,810 --> 01:02:05,510 So the Hello component, when I render it to the screen, 1229 01:02:05,510 --> 01:02:08,150 just displays a big heading that says, "Hello!" 1230 01:02:08,150 --> 01:02:12,770 And now, inside of my app, I can just render a Hello component, 1231 01:02:12,770 --> 01:02:14,900 and maybe I'll render a second Hello component. 1232 01:02:14,900 --> 01:02:17,180 And maybe I'll render a third Hello component. 1233 01:02:17,180 --> 01:02:22,400 I can reuse components as much as I want to say, passing in Hello, Hello, Hello. 1234 01:02:22,400 --> 01:02:26,210 And now when I refresh the page, I see three of those Hello components 1235 01:02:26,210 --> 01:02:27,510 appear on my screen. 1236 01:02:27,510 --> 01:02:30,200 And the reason why that happened is because up above, I 1237 01:02:30,200 --> 01:02:32,382 defined a component called Hello, and all 1238 01:02:32,382 --> 01:02:34,340 the Hello component does is when it is rendered 1239 01:02:34,340 --> 01:02:37,700 to the page, it displays a heading that says, "Hello!" 1240 01:02:37,700 --> 01:02:39,800 And then what my app is going to do is it is 1241 01:02:39,800 --> 01:02:42,440 going to have three Hello components. 1242 01:02:42,440 --> 01:02:46,070 Each one of which is going to be rendered as just Hello. 1243 01:02:46,070 --> 01:02:49,130 Now, these components aren't super interesting if they all look exactly 1244 01:02:49,130 --> 01:02:52,820 the same, and it's for that reason that these components can have additional 1245 01:02:52,820 --> 01:02:56,450 properties or attributes-- or in React terms, they call them props-- 1246 01:02:56,450 --> 01:02:57,710 associated with them. 1247 01:02:57,710 --> 01:03:00,980 Maybe instead of Hello, I would like to provide additional information, 1248 01:03:00,980 --> 01:03:05,060 like, say hello to Harry, or Ron, or Hermione, for example, 1249 01:03:05,060 --> 01:03:08,390 where I might want to say, much as you could with HTML, 1250 01:03:08,390 --> 01:03:11,330 provide attributes, in this case known as props, to hello, 1251 01:03:11,330 --> 01:03:16,700 where Hello name equals Harry, Hello name equals Ron, 1252 01:03:16,700 --> 01:03:20,060 Hello name equals Hermione. 1253 01:03:20,060 --> 01:03:25,040 It turns out that in React, if I take a React component, something like Hello, 1254 01:03:25,040 --> 01:03:30,160 and I pass it the equivalent of what looks like HTML arguments 1255 01:03:30,160 --> 01:03:32,870 that you can put as parameters to a particular HTML tag, 1256 01:03:32,870 --> 01:03:36,350 like attributes on an HTML element, that you can access 1257 01:03:36,350 --> 01:03:41,240 those attributes, otherwise known as props, inside of a React component, 1258 01:03:41,240 --> 01:03:42,830 that I can access Hello. 1259 01:03:42,830 --> 01:03:45,710 And then in order to substitute a variable inside of React, 1260 01:03:45,710 --> 01:03:50,030 we use curly braces, much as you do in Python, and I can say, this.props.name. 1261 01:03:50,030 --> 01:03:53,510 1262 01:03:53,510 --> 01:03:57,590 So now what's going on is that I have passed in as a property of each 1263 01:03:57,590 --> 01:04:00,680 of these Hello components a name, and in order 1264 01:04:00,680 --> 01:04:04,160 to access that name inside of this class, I can just plug is, 1265 01:04:04,160 --> 01:04:07,490 using these curly braces, this.props.name. 1266 01:04:07,490 --> 01:04:11,470 This, in this case, refers to the current object, the Hello object. 1267 01:04:11,470 --> 01:04:14,870 I access its properties, and I access the value 1268 01:04:14,870 --> 01:04:18,260 of the name property, which is Harry in the first case, then Ron, then 1269 01:04:18,260 --> 01:04:20,040 Hermione, for example. 1270 01:04:20,040 --> 01:04:23,810 And so now, all in all, when I've go ahead and open this page, what I see 1271 01:04:23,810 --> 01:04:27,808 is three different components, each parameterized by a different property. 1272 01:04:27,808 --> 01:04:28,850 One says, "Hello, Harry!" 1273 01:04:28,850 --> 01:04:29,808 One says, "Hello, Ron!" 1274 01:04:29,808 --> 01:04:30,980 One says, "Hello, Hermione!" 1275 01:04:30,980 --> 01:04:33,260 And I've been able to abstractly represent 1276 01:04:33,260 --> 01:04:35,960 that as just three hello components, each of which 1277 01:04:35,960 --> 01:04:38,600 has a different property for what name I would 1278 01:04:38,600 --> 01:04:41,580 like to provide to that component. 1279 01:04:41,580 --> 01:04:44,360 So this, then, is what these components can look like, 1280 01:04:44,360 --> 01:04:46,460 but where components start to get more powerful 1281 01:04:46,460 --> 01:04:50,640 is when we can begin to express state inside of those components, as well. 1282 01:04:50,640 --> 01:04:54,020 So let's go ahead and taking a look at an example of how we could do that. 1283 01:04:54,020 --> 01:04:58,790 I'll now go ahead and create a new file called counter.html, 1284 01:04:58,790 --> 01:05:02,083 and here we're going to reimplement that counter program from when we first 1285 01:05:02,083 --> 01:05:04,250 took a look at JavaScript, where you click a button, 1286 01:05:04,250 --> 01:05:06,380 and that's going to increment some sort of counter. 1287 01:05:06,380 --> 01:05:10,130 And before, we had to separately maintain a variable called counter, 1288 01:05:10,130 --> 01:05:13,010 and every time we update that variable, we had to then say, 1289 01:05:13,010 --> 01:05:16,080 also, manipulate the DOM in order to reflect those changes. 1290 01:05:16,080 --> 01:05:18,080 That's going to start to get tedious, especially 1291 01:05:18,080 --> 01:05:20,840 if we need to start making many different changes in response 1292 01:05:20,840 --> 01:05:21,770 to what's happening. 1293 01:05:21,770 --> 01:05:24,560 It'll be nicer to be able to declaratively just say, 1294 01:05:24,560 --> 01:05:28,220 what should be displayed on the screen is whatever the value of the variable 1295 01:05:28,220 --> 01:05:31,690 happens to be inside of the component's state. 1296 01:05:31,690 --> 01:05:34,010 And so we'll see how we can do that now. 1297 01:05:34,010 --> 01:05:36,770 I'll go ahead and just copy the same basic structure 1298 01:05:36,770 --> 01:05:40,160 from react.html inside of counter. 1299 01:05:40,160 --> 01:05:42,547 But we no longer need a Hello component. 1300 01:05:42,547 --> 01:05:44,630 We're just going to have a single component, which 1301 01:05:44,630 --> 01:05:47,030 is going to be this App component. 1302 01:05:47,030 --> 01:05:49,500 And by default, let's go ahead and render 1303 01:05:49,500 --> 01:05:56,483 an h1 that says 0 and a button that says, "Click Here" 1304 01:05:56,483 --> 01:05:57,400 that's going to count. 1305 01:05:57,400 --> 01:05:58,830 Or maybe, instead of "Click Here," we can instead 1306 01:05:58,830 --> 01:06:01,480 have it say, "Count," just to make it much more clear. 1307 01:06:01,480 --> 01:06:05,340 So now I have a counter that is going to first render this App component, 1308 01:06:05,340 --> 01:06:08,880 and all the App component is going to do is display a heading that says 0 1309 01:06:08,880 --> 01:06:11,740 and display a button that says, "Count." 1310 01:06:11,740 --> 01:06:16,620 So let me now open up counter.html, and here, then, is what I see, 1311 01:06:16,620 --> 01:06:19,140 number and then a button that says, "Count." 1312 01:06:19,140 --> 01:06:20,970 Of course, nothing does anything just yet. 1313 01:06:20,970 --> 01:06:22,700 That's going to be this next step. 1314 01:06:22,700 --> 01:06:26,160 And now the first step is going to be to say that I don't just 1315 01:06:26,160 --> 01:06:29,040 want to display 0 inside of this h1. 1316 01:06:29,040 --> 01:06:32,790 I really want to display whatever the value of some internal state 1317 01:06:32,790 --> 01:06:35,720 of this component happens to be. 1318 01:06:35,720 --> 01:06:37,570 And so how can I do that? 1319 01:06:37,570 --> 01:06:42,240 Well, the first thing I need to do is when I first create a new app, 1320 01:06:42,240 --> 01:06:44,850 I need to give it some internal state, and it turns out 1321 01:06:44,850 --> 01:06:48,630 that in React, when I create a new component, 1322 01:06:48,630 --> 01:06:51,300 it's going to call a function called the constructor 1323 01:06:51,300 --> 01:06:53,908 to make the new component, which takes as an argument 1324 01:06:53,908 --> 01:06:56,700 the props that were passed into it in case you want to do something 1325 01:06:56,700 --> 01:06:58,620 with the props. 1326 01:06:58,620 --> 01:07:01,200 And because this is an object-oriented programming language, 1327 01:07:01,200 --> 01:07:03,540 we need to start by saying, super props, just to say, 1328 01:07:03,540 --> 01:07:06,240 make sure that this all gets set up as a React component, 1329 01:07:06,240 --> 01:07:08,310 no need to worry too much about that line. 1330 01:07:08,310 --> 01:07:10,320 The interesting line will come next now. 1331 01:07:10,320 --> 01:07:12,420 Inside of the constructor, when we create 1332 01:07:12,420 --> 01:07:14,670 this component for the first time, I'm going 1333 01:07:14,670 --> 01:07:21,540 to set this.state equal to a JavaScript object that can contain whatever keys 1334 01:07:21,540 --> 01:07:23,140 and values I want. 1335 01:07:23,140 --> 01:07:26,340 So I can add any state that I want into this.state, anything that 1336 01:07:26,340 --> 01:07:28,080 is about the state of the component. 1337 01:07:28,080 --> 01:07:33,330 So for example, I can add a variable like count, which will be 0. 1338 01:07:33,330 --> 01:07:36,450 So initially, when I create this application for the first time, 1339 01:07:36,450 --> 01:07:39,510 it is going to have some sort of internal state, some variables that 1340 01:07:39,510 --> 01:07:43,230 is keeping track of, and it will have one property called count, 1341 01:07:43,230 --> 01:07:45,630 and its initial value will be 0. 1342 01:07:45,630 --> 01:07:50,160 And now, instead of displaying just 0 inside of this h1, 1343 01:07:50,160 --> 01:07:54,090 I want to display in curly braces so that I plug in a value here. 1344 01:07:54,090 --> 01:08:00,660 The value I want to plug in is this.state.count, where now I'm saying, 1345 01:08:00,660 --> 01:08:04,170 you look inside of your state, and whenever the count happens to be, 1346 01:08:04,170 --> 01:08:07,050 that should be what gets displayed, instead of the h1. 1347 01:08:07,050 --> 01:08:10,560 If the count ever changes, I don't need to manually then say, go ahead 1348 01:08:10,560 --> 01:08:11,820 and update the h1. 1349 01:08:11,820 --> 01:08:15,480 The h1 will update automatically based on whatever the state is, 1350 01:08:15,480 --> 01:08:18,100 and React is going to take care of that for me. 1351 01:08:18,100 --> 01:08:21,029 So if I look at the page now nothing, appears to have changed, 1352 01:08:21,029 --> 01:08:24,720 but the number that I see is based on the number inside the state. 1353 01:08:24,720 --> 01:08:28,680 If I change it to something else, for example, and refresh the page, 1354 01:08:28,680 --> 01:08:31,260 then what I see in the h1 is just a reflection 1355 01:08:31,260 --> 01:08:34,020 of what happens to be inside of the application state. 1356 01:08:34,020 --> 01:08:36,180 But we'll go ahead and start that state at 0, 1357 01:08:36,180 --> 01:08:39,520 which is why 0 is the first thing that you should see here. 1358 01:08:39,520 --> 01:08:42,130 Now what I want to happen is when the button is clicked, 1359 01:08:42,130 --> 01:08:44,340 I would like for some function to run. 1360 01:08:44,340 --> 01:08:46,770 So I can say, onClick-- 1361 01:08:46,770 --> 01:08:50,790 and react happens to use capital C click for a lot of these event handlers-- 1362 01:08:50,790 --> 01:08:53,580 and when you click, we'll go ahead and run 1363 01:08:53,580 --> 01:08:58,383 this.count, which will be a function that we'll write in just a moment. 1364 01:08:58,383 --> 01:09:00,300 And so let's go ahead and write that function. 1365 01:09:00,300 --> 01:09:01,990 Count is going to be a function. 1366 01:09:01,990 --> 01:09:04,620 We use arrow function notation here. 1367 01:09:04,620 --> 01:09:06,910 And what is the count function going to do? 1368 01:09:06,910 --> 01:09:08,700 Well, it's going to update the state. 1369 01:09:08,700 --> 01:09:10,050 And how do you update the state? 1370 01:09:10,050 --> 01:09:14,460 React gives you access to a function called this.setState. 1371 01:09:14,460 --> 01:09:17,130 And it can work in a couple of ways, but one way it can work 1372 01:09:17,130 --> 01:09:19,500 is it can take as its argument a function 1373 01:09:19,500 --> 01:09:22,380 from the old state to the new state. 1374 01:09:22,380 --> 01:09:25,350 So I can say, the old state we'll call state. 1375 01:09:25,350 --> 01:09:28,890 And then the new state is going to be what? 1376 01:09:28,890 --> 01:09:31,109 Well, the new state is going to have count 1377 01:09:31,109 --> 01:09:36,907 set to whatever state.count plus 1 is. 1378 01:09:36,907 --> 01:09:38,240 And so how does this logic work? 1379 01:09:38,240 --> 01:09:39,580 Let's take a look at it again. 1380 01:09:39,580 --> 01:09:41,590 Inside the render function, we're saying, 1381 01:09:41,590 --> 01:09:46,300 go ahead and render a heading that just displays this.state.count. 1382 01:09:46,300 --> 01:09:49,660 Look at the internal state of the component, get access to the count, 1383 01:09:49,660 --> 01:09:51,550 and that should be the big heading. 1384 01:09:51,550 --> 01:09:55,070 Then we have a button called count, and when you click on the button, 1385 01:09:55,070 --> 01:09:57,820 we're going to run the this.count function. 1386 01:09:57,820 --> 01:09:59,570 And the count function is down here. 1387 01:09:59,570 --> 01:10:00,530 It's a function. 1388 01:10:00,530 --> 01:10:01,780 And what does the function do? 1389 01:10:01,780 --> 01:10:03,730 The function is going to update the state. 1390 01:10:03,730 --> 01:10:08,410 This state takes the initial state and then generates 1391 01:10:08,410 --> 01:10:11,440 a new state where we're going to update the count 1392 01:10:11,440 --> 01:10:14,440 to be state.count, whatever the count used to be, 1393 01:10:14,440 --> 01:10:18,790 plus 1, adding 1 to whatever it was. 1394 01:10:18,790 --> 01:10:21,628 And now that's all we need to do. 1395 01:10:21,628 --> 01:10:22,420 I refresh the page. 1396 01:10:22,420 --> 01:10:23,700 It starts out as 0. 1397 01:10:23,700 --> 01:10:26,800 Every time I press Count, the count is going to update, 1398 01:10:26,800 --> 01:10:29,380 incrementing by one each time. 1399 01:10:29,380 --> 01:10:31,600 And again, the reason it does that is because I 1400 01:10:31,600 --> 01:10:35,350 don't need to say, update the h1 in order to reflect the new change. 1401 01:10:35,350 --> 01:10:37,810 Anytime the state changes, React is going 1402 01:10:37,810 --> 01:10:40,840 to handle updating what it is the component looks like because I'm 1403 01:10:40,840 --> 01:10:43,030 saying that when you render the component, 1404 01:10:43,030 --> 01:10:46,830 it should be based on the value of this.state.count. 1405 01:10:46,830 --> 01:10:48,580 And that's going to, then, enable us to be 1406 01:10:48,580 --> 01:10:54,040 able to much more easily modify what the page looks like just by updating 1407 01:10:54,040 --> 01:10:55,525 the internal state. 1408 01:10:55,525 --> 01:10:57,400 And if the state appeared in multiple places, 1409 01:10:57,400 --> 01:11:04,240 for example, if underneath here I said, the current count is this.state.count, 1410 01:11:04,240 --> 01:11:06,040 then I refresh the page. 1411 01:11:06,040 --> 01:11:07,490 It says, the current count to 0. 1412 01:11:07,490 --> 01:11:10,240 And every time I press Count, it's going to change in both places. 1413 01:11:10,240 --> 01:11:12,670 I don't have to manually go into two different places 1414 01:11:12,670 --> 01:11:14,503 and change what the value should be. 1415 01:11:14,503 --> 01:11:17,170 React is going to take care of the process of updating that user 1416 01:11:17,170 --> 01:11:23,210 interface for me anytime the underlying state of the application changes. 1417 01:11:23,210 --> 01:11:26,470 So now what we'll do is take all of this, and begin to put it together, 1418 01:11:26,470 --> 01:11:29,500 and build a more interesting, dynamic, interactive web page 1419 01:11:29,500 --> 01:11:32,260 using React and using state to be able to control 1420 01:11:32,260 --> 01:11:33,970 how the application is going to work. 1421 01:11:33,970 --> 01:11:37,120 And the application we'll build will be a bit of a game 1422 01:11:37,120 --> 01:11:40,030 where we'll ask users to solve addition problems. 1423 01:11:40,030 --> 01:11:41,605 We'll ask them what is 1 plus 1? 1424 01:11:41,605 --> 01:11:43,900 And they answer, and if they answer correctly, 1425 01:11:43,900 --> 01:11:46,210 we'll increase their score, for example, type of game 1426 01:11:46,210 --> 01:11:48,210 you might see on the internet that's really just 1427 01:11:48,210 --> 01:11:51,278 going to be some text field, some text that we're going to display, 1428 01:11:51,278 --> 01:11:54,320 but ultimately, some variables that we're going to need to keep track of. 1429 01:11:54,320 --> 01:11:57,028 And so we'll see an example of how we can put all of those pieces 1430 01:11:57,028 --> 01:12:01,180 together by taking advantage of React to leverage this declarative programming 1431 01:12:01,180 --> 01:12:02,700 style. 1432 01:12:02,700 --> 01:12:05,950 So in order to do this, I'll go ahead and create a new file. 1433 01:12:05,950 --> 01:12:07,545 We'll call it addition.html. 1434 01:12:07,545 --> 01:12:10,060 1435 01:12:10,060 --> 01:12:13,270 And we'll start it off with the same type of code that we had from before. 1436 01:12:13,270 --> 01:12:15,100 I'll copy it from counter, but then we'll 1437 01:12:15,100 --> 01:12:20,930 clear out the contents of the app component, 1438 01:12:20,930 --> 01:12:23,690 clear out what we're returning. 1439 01:12:23,690 --> 01:12:25,700 So now we just have an app. 1440 01:12:25,700 --> 01:12:29,103 And what state do we need to keep track of inside of this game? 1441 01:12:29,103 --> 01:12:31,770 Well, one thing we might now want to keep track of, for example, 1442 01:12:31,770 --> 01:12:33,440 is the current user's score. 1443 01:12:33,440 --> 01:12:37,370 So we'll go ahead and give them a score that initially is going to be 0. 1444 01:12:37,370 --> 01:12:40,170 And maybe on the page we'll display the user's score. 1445 01:12:40,170 --> 01:12:45,110 So maybe I'll say, in a div, your score is this.state.score. 1446 01:12:45,110 --> 01:12:47,477 1447 01:12:47,477 --> 01:12:49,810 So that's all this application is going to do right now. 1448 01:12:49,810 --> 01:12:51,280 It's going to display a score. 1449 01:12:51,280 --> 01:12:53,950 Initially, I set the score equal to 0, and when 1450 01:12:53,950 --> 01:12:56,925 I render this component, when it displays on the screen, 1451 01:12:56,925 --> 01:12:59,050 we're going to have a div that says, your score is. 1452 01:12:59,050 --> 01:13:03,070 And then we're going to plug in here in curly braces this.state.score. 1453 01:13:03,070 --> 01:13:06,640 It's going to get us whatever the score happens to be. 1454 01:13:06,640 --> 01:13:12,770 So I go ahead and go to addition.html, and here's what I see. 1455 01:13:12,770 --> 01:13:16,060 I see that the score, in this case, so happens to be 0. 1456 01:13:16,060 --> 01:13:20,743 So now what I'd like to do is display some sort of math problem 1457 01:13:20,743 --> 01:13:22,660 for the user to be able to solve, because this 1458 01:13:22,660 --> 01:13:24,440 is what I want this game to be about. 1459 01:13:24,440 --> 01:13:31,730 So I might display a div that just says something like, 1 plus 1, for example. 1460 01:13:31,730 --> 01:13:34,290 So we'll go ahead and refresh that. 1461 01:13:34,290 --> 01:13:35,560 There's a math problem. 1462 01:13:35,560 --> 01:13:39,800 And now I also want there to be a place where the user can type in a response, 1463 01:13:39,800 --> 01:13:40,690 for example. 1464 01:13:40,690 --> 01:13:43,528 I'll just use input field for now, refresh the page, 1465 01:13:43,528 --> 01:13:45,070 and this is what this now looks like. 1466 01:13:45,070 --> 01:13:49,720 We have some math equation, some input field, and then some score. 1467 01:13:49,720 --> 01:13:52,570 And now when we begin to design a react application, 1468 01:13:52,570 --> 01:13:54,430 the thing to start to think about is what 1469 01:13:54,430 --> 01:13:58,150 should be included inside of the state of the application, what things 1470 01:13:58,150 --> 01:14:00,248 could change in this application. 1471 01:14:00,248 --> 01:14:02,290 And just looking at this here, there are a couple 1472 01:14:02,290 --> 01:14:03,820 of things that are going to change. 1473 01:14:03,820 --> 01:14:05,950 One thing we already know is going to change is the score. 1474 01:14:05,950 --> 01:14:08,590 The score starts out at 0, but ultimately, the score is later 1475 01:14:08,590 --> 01:14:10,390 going to increase to something else. 1476 01:14:10,390 --> 01:14:13,210 What other state is being stored inside this application? 1477 01:14:13,210 --> 01:14:14,920 What other things are going to change? 1478 01:14:14,920 --> 01:14:17,580 Well, these two numbers are going to change, presumably, 1479 01:14:17,580 --> 01:14:20,080 that after I answer the first question, you'll probably want 1480 01:14:20,080 --> 01:14:22,010 to show me a different math problem. 1481 01:14:22,010 --> 01:14:25,130 And so this 1 and that 1 are probably going to change two other numbers, 1482 01:14:25,130 --> 01:14:28,210 so maybe those should be part of the state, as well. 1483 01:14:28,210 --> 01:14:33,870 So we can do that, too, by updating what we're storing inside of this.state. 1484 01:14:33,870 --> 01:14:37,060 Maybe I'll initially store inside my state 1485 01:14:37,060 --> 01:14:41,030 that num1 is going to be 1 and num2 is going to be one. 1486 01:14:41,030 --> 01:14:43,030 And these are going to represent the two numbers 1487 01:14:43,030 --> 01:14:45,340 that I would like to add together as the problem 1488 01:14:45,340 --> 01:14:48,800 that I display to the user who is playing my game, for example. 1489 01:14:48,800 --> 01:14:52,160 So down below now, instead of just saying 1 plus 1, 1490 01:14:52,160 --> 01:15:00,460 I'm going to say, this.state.num1 plus this.state.num2. 1491 01:15:00,460 --> 01:15:04,008 So now, rather than just literally using 1 and 1, I'm saying, 1492 01:15:04,008 --> 01:15:06,550 the numbers that should be displayed in this part of the page 1493 01:15:06,550 --> 01:15:08,750 are reflective of whatever is stored in the state. 1494 01:15:08,750 --> 01:15:10,750 And if the state changes what those numbers are, 1495 01:15:10,750 --> 01:15:13,100 then we should change those numbers, as well. 1496 01:15:13,100 --> 01:15:14,290 So now I refresh the page. 1497 01:15:14,290 --> 01:15:16,780 Nothing appears to have changed, but if I later 1498 01:15:16,780 --> 01:15:20,620 change what these two numbers are to different numbers, then the problem 1499 01:15:20,620 --> 01:15:23,040 changes, as well. 1500 01:15:23,040 --> 01:15:27,460 So I'm able to manipulate what appears on the screen based on the underlying 1501 01:15:27,460 --> 01:15:29,600 state of the application. 1502 01:15:29,600 --> 01:15:32,350 And it turns out there's at least one other part of this page that 1503 01:15:32,350 --> 01:15:34,270 could change, as well, and in particular, it's 1504 01:15:34,270 --> 01:15:36,160 not just the score and not just what these 1505 01:15:36,160 --> 01:15:38,950 values that are the two numbers that we're adding together. 1506 01:15:38,950 --> 01:15:41,595 But the contents of this text field you can also 1507 01:15:41,595 --> 01:15:42,970 consider to be part of the state. 1508 01:15:42,970 --> 01:15:45,630 It is something about the application that is going to change. 1509 01:15:45,630 --> 01:15:47,380 And in particular, it's something that I'm 1510 01:15:47,380 --> 01:15:49,720 going to care about knowing about, because later on, 1511 01:15:49,720 --> 01:15:52,523 when the user presses Enter in order to submit their answer, 1512 01:15:52,523 --> 01:15:54,940 I want to know what the value of what's been typed in here 1513 01:15:54,940 --> 01:15:59,450 is to be able to figure out if they answered the question correctly or not. 1514 01:15:59,450 --> 01:16:03,520 So what I can do is I can add to the state something 1515 01:16:03,520 --> 01:16:08,600 like the response, which initially will just be the empty string. 1516 01:16:08,600 --> 01:16:13,978 But then I can say, this input's value is going to be this.state.response. 1517 01:16:13,978 --> 01:16:16,458 1518 01:16:16,458 --> 01:16:18,250 And again, nothing appears to have changed, 1519 01:16:18,250 --> 01:16:21,520 but now I'm controlling whatever is inside this text field 1520 01:16:21,520 --> 01:16:24,880 based on whatever the value of this.state.response is. 1521 01:16:24,880 --> 01:16:27,070 If I sent a responds to something like "Hello!" 1522 01:16:27,070 --> 01:16:30,550 for example and then refresh the page, well, then "Hello!" 1523 01:16:30,550 --> 01:16:32,790 is going to show up inside of the input field. 1524 01:16:32,790 --> 01:16:36,550 It is part of the state, and as a result, it is reflected in the view 1525 01:16:36,550 --> 01:16:38,740 that users ultimately see. 1526 01:16:38,740 --> 01:16:40,170 So this seems reasonable. 1527 01:16:40,170 --> 01:16:41,230 I have two numbers. 1528 01:16:41,230 --> 01:16:44,500 I'm keeping track of a response, and I'm also keeping track of a score. 1529 01:16:44,500 --> 01:16:46,540 We can go ahead and try and play this game now. 1530 01:16:46,540 --> 01:16:47,760 I refresh the page. 1531 01:16:47,760 --> 01:16:51,050 It's saying, 1 plus 1, and now giving me an option to type in a result. 1532 01:16:51,050 --> 01:16:53,458 Let me see if I can type in the number 2. 1533 01:16:53,458 --> 01:16:55,750 And though you can't see it, I'm pressing the number 2, 1534 01:16:55,750 --> 01:16:58,360 but nothing's changing in the input field. 1535 01:16:58,360 --> 01:17:00,980 I'm typing the number 2, but nothing is happening. 1536 01:17:00,980 --> 01:17:02,590 So why might that be the case? 1537 01:17:02,590 --> 01:17:03,855 Well, React is very literal. 1538 01:17:03,855 --> 01:17:05,980 You tell it what you want, and it's going to do it. 1539 01:17:05,980 --> 01:17:08,860 And what we said is that the value of this input field 1540 01:17:08,860 --> 01:17:11,840 should be whatever this.state.response is. 1541 01:17:11,840 --> 01:17:15,790 And this.state.response is always going to be just the empty string. 1542 01:17:15,790 --> 01:17:16,840 It's going to be nothing. 1543 01:17:16,840 --> 01:17:19,990 So it doesn't matter what I type while this input field is selected. 1544 01:17:19,990 --> 01:17:22,510 No text is ever going to appear here, because I'm not 1545 01:17:22,510 --> 01:17:25,760 updating this.state.response. 1546 01:17:25,760 --> 01:17:27,640 So if I want this text field to work, I'm 1547 01:17:27,640 --> 01:17:31,180 going to need to update the response inside of the state 1548 01:17:31,180 --> 01:17:34,340 in order to reflect what the user has actually typed in. 1549 01:17:34,340 --> 01:17:35,920 So let's give this a try. 1550 01:17:35,920 --> 01:17:38,290 And the way I can do this is go back to this input 1551 01:17:38,290 --> 01:17:42,420 field whose value right now is this.state.response, 1552 01:17:42,420 --> 01:17:45,920 and I'm going to say, onChange. 1553 01:17:45,920 --> 01:17:48,160 Let's go ahead and run a function. 1554 01:17:48,160 --> 01:17:51,640 And we'll do this.updateResponse as the name of the function. 1555 01:17:51,640 --> 01:17:53,260 updateResponse is just a name I chose. 1556 01:17:53,260 --> 01:17:54,250 It's arbitrary. 1557 01:17:54,250 --> 01:17:57,600 But what I'm saying here is anytime the value in the input field changes, 1558 01:17:57,600 --> 01:17:59,350 anytime someone tries to type in something 1559 01:17:59,350 --> 01:18:04,160 new, go ahead and call the updateResponse function. 1560 01:18:04,160 --> 01:18:08,420 Let's go ahead and now write the updateResponse function. 1561 01:18:08,420 --> 01:18:11,860 And remember that event handlers can usually take the event itself 1562 01:18:11,860 --> 01:18:13,520 as an argument. 1563 01:18:13,520 --> 01:18:20,380 And this is going to be helpful, because event.target.value is going to contain 1564 01:18:20,380 --> 01:18:22,240 whatever it is the user typed in. 1565 01:18:22,240 --> 01:18:26,960 Event.target is the input field that I was typing into, and .value will get 1566 01:18:26,960 --> 01:18:29,380 at me what it is the user typed in. 1567 01:18:29,380 --> 01:18:33,610 And what I'd like to do is say, this.setState. 1568 01:18:33,610 --> 01:18:38,185 And here, all I want to do is set the response equal to event.target.value. 1569 01:18:38,185 --> 01:18:41,390 1570 01:18:41,390 --> 01:18:42,730 So what's going on here? 1571 01:18:42,730 --> 01:18:43,750 I have an input field. 1572 01:18:43,750 --> 01:18:46,780 Every time the input field changes, meaning every time I type something 1573 01:18:46,780 --> 01:18:50,020 into the input field, the onChange handler in React 1574 01:18:50,020 --> 01:18:52,640 says, go ahead and call this.updateResponse, 1575 01:18:52,640 --> 01:18:55,780 meaning update the response inside of the state. 1576 01:18:55,780 --> 01:18:59,200 Here, then, is the updateResponse function, and what it's going to do 1577 01:18:59,200 --> 01:19:03,490 is it's going to take the event, the onChange event, get its target-- 1578 01:19:03,490 --> 01:19:04,330 what changed? 1579 01:19:04,330 --> 01:19:05,650 It was the input field-- 1580 01:19:05,650 --> 01:19:06,730 and get at that value-- 1581 01:19:06,730 --> 01:19:09,220 what is the actual text that was typed into the input field 1582 01:19:09,220 --> 01:19:11,140 when I triggered this event-- 1583 01:19:11,140 --> 01:19:15,427 and go ahead and update the state, setting response equal to that. 1584 01:19:15,427 --> 01:19:17,260 Now, this time I didn't need to provide what 1585 01:19:17,260 --> 01:19:19,390 the prior state is, because the prior state isn't 1586 01:19:19,390 --> 01:19:20,870 going to influence this new state. 1587 01:19:20,870 --> 01:19:24,010 We're just going to replace response with whatever the value of what 1588 01:19:24,010 --> 01:19:26,700 was typed in actually is. 1589 01:19:26,700 --> 01:19:29,390 And so we can actually test us now. 1590 01:19:29,390 --> 01:19:32,360 I refreshed the page, and now I have an input field 1591 01:19:32,360 --> 01:19:37,487 where if I type something like 1234, then it's going to actually appear. 1592 01:19:37,487 --> 01:19:39,320 And how do I know that it's actually keeping 1593 01:19:39,320 --> 01:19:41,135 track of this inside of the response? 1594 01:19:41,135 --> 01:19:43,260 Well, I could try just displaying it on the screen. 1595 01:19:43,260 --> 01:19:46,760 I could add another div that says, "You have typed," 1596 01:19:46,760 --> 01:19:50,420 and then this.state.response. 1597 01:19:50,420 --> 01:19:53,960 That is going to just display on the screen what it is that you have typed. 1598 01:19:53,960 --> 01:19:56,630 It's going to say, this.state.response, no matter what 1599 01:19:56,630 --> 01:19:59,570 this.state.response happens to be. 1600 01:19:59,570 --> 01:20:03,060 So now, if I refresh the page, you have typed nothing so far. 1601 01:20:03,060 --> 01:20:07,010 But as I type in numbers, not only does the input field change, 1602 01:20:07,010 --> 01:20:09,080 but this line changes, as well, because this line 1603 01:20:09,080 --> 01:20:12,570 is dependent upon the value of this.state.response. 1604 01:20:12,570 --> 01:20:16,700 So it updates dynamically along with the rest of the page, as well. 1605 01:20:16,700 --> 01:20:20,752 If I delete everything here, then this field also goes away. 1606 01:20:20,752 --> 01:20:22,460 It turns out, I probably don't need this, 1607 01:20:22,460 --> 01:20:24,210 because the input field does enough for me 1608 01:20:24,210 --> 01:20:26,760 to know what it is that I have typed in. 1609 01:20:26,760 --> 01:20:29,390 So now what I'd like is some way of detecting 1610 01:20:29,390 --> 01:20:31,760 that I've entered the problem, I pressed Return, 1611 01:20:31,760 --> 01:20:34,740 and I'd like to see whether or not I got the answer right or not. 1612 01:20:34,740 --> 01:20:38,090 So in order to detect that, we'll go ahead and add another event handler 1613 01:20:38,090 --> 01:20:41,120 to this input field, onKeyPress. 1614 01:20:41,120 --> 01:20:45,540 We'll go ahead and run a function called this.inputKeyPress. 1615 01:20:45,540 --> 01:20:47,540 It can be called anything we want, but basically 1616 01:20:47,540 --> 01:20:50,660 what we're saying is in the input field, when you press a key, 1617 01:20:50,660 --> 01:20:53,507 run the inputKeyPress function. 1618 01:20:53,507 --> 01:20:55,340 And what the inputKeyPress function is going 1619 01:20:55,340 --> 01:20:59,210 to do is the first thing it wants to do is check, 1620 01:20:59,210 --> 01:21:02,330 is the key that was typed in the Enter key? 1621 01:21:02,330 --> 01:21:05,020 1622 01:21:05,020 --> 01:21:06,570 So what is going on here again? 1623 01:21:06,570 --> 01:21:10,110 Every time I press a key, regardless of what key it is, 1624 01:21:10,110 --> 01:21:12,240 it will call the inputKeyPress function. 1625 01:21:12,240 --> 01:21:14,910 But what we really care about is just a scenario where 1626 01:21:14,910 --> 01:21:18,780 the user presses the Enter key, in which case, inputKeyPress will be called. 1627 01:21:18,780 --> 01:21:22,810 And it turns out, with a KeyPress event, you can access event.key, 1628 01:21:22,810 --> 01:21:24,810 which is a property of that event that tells you 1629 01:21:24,810 --> 01:21:26,700 what key was actually pressed. 1630 01:21:26,700 --> 01:21:30,660 And if the Enter key was pressed, then we want to do something. 1631 01:21:30,660 --> 01:21:32,190 What might we want to do? 1632 01:21:32,190 --> 01:21:36,690 Well, we want to check to see if the answer is actually correct. 1633 01:21:36,690 --> 01:21:38,770 Well, how do we know what the answer is? 1634 01:21:38,770 --> 01:21:41,580 Well, the answer is whatever the user typed into the text field, 1635 01:21:41,580 --> 01:21:46,370 and we know that's stored in this.state.response. 1636 01:21:46,370 --> 01:21:50,010 Now, technically, since this.state.response might be a string, 1637 01:21:50,010 --> 01:21:52,320 we'll go ahead and convert this into an integer first. 1638 01:21:52,320 --> 01:21:56,010 So parseInt is a function in JavaScript that takes a string, 1639 01:21:56,010 --> 01:21:57,930 converts it into an integer. 1640 01:21:57,930 --> 01:22:02,350 And we'll store that inside of a variable called answer. 1641 01:22:02,350 --> 01:22:05,698 And now how do I know if they've correctly solved the addition problem? 1642 01:22:05,698 --> 01:22:07,490 Well, the two numbers that were being added 1643 01:22:07,490 --> 01:22:11,490 were this.state.num1 and this.state.num2. 1644 01:22:11,490 --> 01:22:15,180 So the question that I could ask as a condition is something like, 1645 01:22:15,180 --> 01:22:22,610 if answer is equal to this.state.num1 plus this.state.num2, 1646 01:22:22,610 --> 01:22:24,500 well, that means they got the question right. 1647 01:22:24,500 --> 01:22:27,830 So this means user got question right. 1648 01:22:27,830 --> 01:22:30,440 And then we can add an else case that is, 1649 01:22:30,440 --> 01:22:35,520 user got question wrong, for example, so two different scenarios, 1650 01:22:35,520 --> 01:22:38,150 one for when the user correctly answers the question, one 1651 01:22:38,150 --> 01:22:40,550 for when the user does not. 1652 01:22:40,550 --> 01:22:42,740 So then the question is, what should happen 1653 01:22:42,740 --> 01:22:44,630 when the user gets the question right? 1654 01:22:44,630 --> 01:22:49,220 Well, we want to update the state, so this.setState, 1655 01:22:49,220 --> 01:22:51,240 and we take the old state. 1656 01:22:51,240 --> 01:22:52,950 And what do we want to modify? 1657 01:22:52,950 --> 01:22:56,160 Well, we probably want to modify at least the score, setting 1658 01:22:56,160 --> 01:23:02,220 the score equal to state.score plus 1, increasing the value of the score by 1. 1659 01:23:02,220 --> 01:23:04,980 So the logic of this now is that we get the answer, whenever 1660 01:23:04,980 --> 01:23:06,690 it is the user typed in. 1661 01:23:06,690 --> 01:23:09,300 If the answer is equal to the sum of the two numbers 1662 01:23:09,300 --> 01:23:11,460 they were trying to add together, then we'll 1663 01:23:11,460 --> 01:23:17,580 go ahead and update the state, setting the score equal to the score plus 1. 1664 01:23:17,580 --> 01:23:19,270 So if I try this now, it says 1 plus 1. 1665 01:23:19,270 --> 01:23:23,950 If I type in an incorrect answer, press Return, nothing happens. 1666 01:23:23,950 --> 01:23:27,910 I type in the correct answer, press Return, and my score increases 1667 01:23:27,910 --> 01:23:31,130 from 0 to 1, exactly what I would expect it to do. 1668 01:23:31,130 --> 01:23:34,130 Now, there are a couple of things I also probably want to happen. 1669 01:23:34,130 --> 01:23:36,610 One is I should probably get a new question, otherwise, 1670 01:23:36,610 --> 01:23:39,910 if it just stays 1 plus 1 forever, I can just keep pressing return 1671 01:23:39,910 --> 01:23:43,360 and just keep making my score as high as I want it to go indefinitely. 1672 01:23:43,360 --> 01:23:47,140 So I probably want every time I press Return, give myself a new question 1673 01:23:47,140 --> 01:23:48,710 to answer. 1674 01:23:48,710 --> 01:23:51,760 And so to do that, what needs to change in the state? 1675 01:23:51,760 --> 01:23:56,740 Well, the state is keeping track of a couple of things, num1, num2, response, 1676 01:23:56,740 --> 01:23:57,850 and score. 1677 01:23:57,850 --> 01:23:59,410 We've updated score. 1678 01:23:59,410 --> 01:24:02,770 Now let's also update num1 and num2. 1679 01:24:02,770 --> 01:24:07,090 So I can say, if they get the question right, we update the score, 1680 01:24:07,090 --> 01:24:08,740 increasing it by 1. 1681 01:24:08,740 --> 01:24:13,700 And let's also set num1 equal to a random number. 1682 01:24:13,700 --> 01:24:18,340 So Math.random gets us a random number between 0 and 1. 1683 01:24:18,340 --> 01:24:22,300 If we multiply it by 10, that'll give us a random number up to 10. 1684 01:24:22,300 --> 01:24:25,867 And because this could be a real number, something after the decimal, 1685 01:24:25,867 --> 01:24:27,700 but I only want to deal with integers, we'll 1686 01:24:27,700 --> 01:24:30,520 go ahead and take the ceiling, Math.ceil, 1687 01:24:30,520 --> 01:24:35,380 to make sure we get a whole number, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10. 1688 01:24:35,380 --> 01:24:37,420 And we'll do the same thing for num2. 1689 01:24:37,420 --> 01:24:40,140 Go ahead and generate a random number. 1690 01:24:40,140 --> 01:24:43,260 And you'd only know this by looking at JavaScript's documentation. 1691 01:24:43,260 --> 01:24:47,020 They happen to have a function called Math.random and Math.ceil that 1692 01:24:47,020 --> 01:24:48,430 do what I want. 1693 01:24:48,430 --> 01:24:53,010 And now I'm updating the score and also updating the two numbers. 1694 01:24:53,010 --> 01:24:54,940 So we try again, refresh the page. 1695 01:24:54,940 --> 01:24:56,020 Score is 0. 1696 01:24:56,020 --> 01:24:59,590 I type in the correct answer, press Return, and my score changes, 1697 01:24:59,590 --> 01:25:01,330 and I get two new numbers. 1698 01:25:01,330 --> 01:25:03,550 I type in the correct answer, press Return. 1699 01:25:03,550 --> 01:25:05,740 The score changes, and I get two new numbers. 1700 01:25:05,740 --> 01:25:09,610 All of this is updating automatically because I am updating the state, 1701 01:25:09,610 --> 01:25:12,020 and then React is taking care of the process of saying, 1702 01:25:12,020 --> 01:25:13,280 the state has updated. 1703 01:25:13,280 --> 01:25:16,910 Let's now update the interface, as well. 1704 01:25:16,910 --> 01:25:20,140 The other change that might be a nice user interface optimization 1705 01:25:20,140 --> 01:25:22,090 is that after I press Return, you probably 1706 01:25:22,090 --> 01:25:24,890 want to clear out this input field for me. 1707 01:25:24,890 --> 01:25:28,570 And so in order to do that, we go ahead and set the response back 1708 01:25:28,570 --> 01:25:30,410 to the empty string. 1709 01:25:30,410 --> 01:25:32,750 So every time I get the correct answer, the answer 1710 01:25:32,750 --> 01:25:35,210 is equal to the sum of the two numbers I'm trying to add, 1711 01:25:35,210 --> 01:25:37,110 we'll increase the score by one. 1712 01:25:37,110 --> 01:25:39,770 We'll set num1 and num2 to new random numbers, 1713 01:25:39,770 --> 01:25:42,400 and we'll clear out the response. 1714 01:25:42,400 --> 01:25:46,500 And so now I type in the right answer, press Return, 1715 01:25:46,500 --> 01:25:48,277 score increases to new answers. 1716 01:25:48,277 --> 01:25:49,860 What if I type in something incorrect? 1717 01:25:49,860 --> 01:25:53,610 I type in something like 5, press Return. 1718 01:25:53,610 --> 01:25:55,120 Nothing happens at all. 1719 01:25:55,120 --> 01:25:58,140 And that's what I would expect, because user got the question wrong. 1720 01:25:58,140 --> 01:26:00,030 I don't change anything about the state. 1721 01:26:00,030 --> 01:26:02,363 But maybe I do want to change something about the state. 1722 01:26:02,363 --> 01:26:05,780 Maybe when you get a question wrong, I want to decrease your score by one. 1723 01:26:05,780 --> 01:26:07,950 So we could say, this.setState. 1724 01:26:07,950 --> 01:26:13,467 And this time, your score becomes state.score minus 1, 1725 01:26:13,467 --> 01:26:16,050 and for good measure, we'll also clear out the response field. 1726 01:26:16,050 --> 01:26:20,280 But we won't replace num1 and num2 to give the user another chance 1727 01:26:20,280 --> 01:26:23,000 to answer the same question. 1728 01:26:23,000 --> 01:26:25,770 So now I refresh the page, 1 plus 1. 1729 01:26:25,770 --> 01:26:27,210 I type in the answer. 1730 01:26:27,210 --> 01:26:28,540 I get it correct. 1731 01:26:28,540 --> 01:26:31,270 If I type in an incorrect answer, watch what happens. 1732 01:26:31,270 --> 01:26:34,680 My score decreases by one, and the input field clears out. 1733 01:26:34,680 --> 01:26:37,710 So I now have the opportunity to type in another problem. 1734 01:26:37,710 --> 01:26:41,673 Now I type in something else, something like 11, get it right. 1735 01:26:41,673 --> 01:26:43,590 I get it right, and every time I get it right, 1736 01:26:43,590 --> 01:26:47,770 the score increases, and the numbers change, as well. 1737 01:26:47,770 --> 01:26:51,240 And so this is the big idea of what we can begin to do with React. 1738 01:26:51,240 --> 01:26:54,690 Just by manipulating four pieces of state, this number 1739 01:26:54,690 --> 01:26:58,080 here, this number here, what's inside of the input field, 1740 01:26:58,080 --> 01:27:00,360 and what the score happens to be, we're able to create 1741 01:27:00,360 --> 01:27:03,030 a very interactive and dynamic web application, 1742 01:27:03,030 --> 01:27:06,630 where we're able to update the interface of what the user sees based 1743 01:27:06,630 --> 01:27:08,730 on the underlying state, based on what happens 1744 01:27:08,730 --> 01:27:10,470 to be going on inside of the application, 1745 01:27:10,470 --> 01:27:14,343 whether they got the question right or whether they got the question wrong. 1746 01:27:14,343 --> 01:27:16,260 And what nice things we can add now are really 1747 01:27:16,260 --> 01:27:19,093 just aesthetic changes, things to make this look a little bit nicer, 1748 01:27:19,093 --> 01:27:20,170 look a little better. 1749 01:27:20,170 --> 01:27:25,230 So I can add some style, just say, let's go to the style section of this page. 1750 01:27:25,230 --> 01:27:28,770 And maybe for the entire app, the div whose ID is app, 1751 01:27:28,770 --> 01:27:35,220 let's center all the text and maybe use a sans serif font. 1752 01:27:35,220 --> 01:27:37,472 Let's refresh that, just see what it looks like. 1753 01:27:37,472 --> 01:27:38,430 That looks pretty good. 1754 01:27:38,430 --> 01:27:41,560 I might like for this math problem to be a little bit bigger. 1755 01:27:41,560 --> 01:27:42,960 So how do I do that? 1756 01:27:42,960 --> 01:27:45,390 Well, here's what I'm rendering. 1757 01:27:45,390 --> 01:27:48,180 And this div is where the problem is, so I'll just 1758 01:27:48,180 --> 01:27:52,263 go ahead and give it an ID of problem. 1759 01:27:52,263 --> 01:27:54,180 And then I can, in the style section and page, 1760 01:27:54,180 --> 01:27:57,690 say, for the thing that has an ID of a problem, 1761 01:27:57,690 --> 01:28:01,155 go ahead and give it a font size of 72 pixels. 1762 01:28:01,155 --> 01:28:03,750 1763 01:28:03,750 --> 01:28:06,820 So now I refresh that, and this looks even better, 1764 01:28:06,820 --> 01:28:09,500 that now I see a big math problem up top and then an input field 1765 01:28:09,500 --> 01:28:10,750 where I can type something in. 1766 01:28:10,750 --> 01:28:12,790 I type in a number, press Return. 1767 01:28:12,790 --> 01:28:13,960 I get a new problem. 1768 01:28:13,960 --> 01:28:16,150 I type in something wrong, press Return. 1769 01:28:16,150 --> 01:28:18,430 My score goes down, and I have another opportunity 1770 01:28:18,430 --> 01:28:20,730 to be able to answer the question correctly. 1771 01:28:20,730 --> 01:28:23,302 And this seems to be working pretty well. 1772 01:28:23,302 --> 01:28:24,510 Now what might I like to add? 1773 01:28:24,510 --> 01:28:26,538 So it's entirely up to us now in terms of what 1774 01:28:26,538 --> 01:28:29,830 features we might want to add here, and using React, and leveraging those tools 1775 01:28:29,830 --> 01:28:31,060 to be able to do so. 1776 01:28:31,060 --> 01:28:33,160 Maybe I'd like for some way to win the game. 1777 01:28:33,160 --> 01:28:36,460 Like maybe once I get to 10 points, let's say the game should end, 1778 01:28:36,460 --> 01:28:39,440 and we can just say, we've won the game at this point. 1779 01:28:39,440 --> 01:28:41,630 How can we go about doing that? 1780 01:28:41,630 --> 01:28:46,720 Well, I'll go back to addition.html, and let's look at the render function. 1781 01:28:46,720 --> 01:28:50,260 Right now, the render function always returns just one thing. 1782 01:28:50,260 --> 01:28:55,600 It's going to always return the problem in input field and the score. 1783 01:28:55,600 --> 01:28:57,470 But maybe I can add some additional logic. 1784 01:28:57,470 --> 01:29:01,300 This is a JavaScript function, so I can add any JavaScript logic that I'd like. 1785 01:29:01,300 --> 01:29:05,110 I can say something like, if this.state.score 1786 01:29:05,110 --> 01:29:13,220 equals 10, then rather than return this thing, let's return something else. 1787 01:29:13,220 --> 01:29:21,700 Let's return something like a div, maybe, whose ID is winner, 1788 01:29:21,700 --> 01:29:25,820 and that div is going to say, you won. 1789 01:29:25,820 --> 01:29:29,940 And now I can say, for the div whose ID is winner, 1790 01:29:29,940 --> 01:29:35,610 let's set the font size to 72 pixel, and let's set the color to green, 1791 01:29:35,610 --> 01:29:38,640 for example. 1792 01:29:38,640 --> 01:29:43,130 So now if I refresh this page, I see this math equation. 1793 01:29:43,130 --> 01:29:50,230 If I answer it, answer, answer to go all the way up to 10 points-- 1794 01:29:50,230 --> 01:29:52,310 I have a score of 9 now, last question. 1795 01:29:52,310 --> 01:29:55,380 If I get the question correct, the score is going to update to 10, 1796 01:29:55,380 --> 01:29:58,400 and when I do answer the question, press Return, 1797 01:29:58,400 --> 01:30:01,290 the entire screen changes and now says, "You won!" 1798 01:30:01,290 --> 01:30:04,280 And again, the reason why it's doing that is because of this render 1799 01:30:04,280 --> 01:30:04,940 function here. 1800 01:30:04,940 --> 01:30:08,680 The render function determines what should be displayed to the user, 1801 01:30:08,680 --> 01:30:11,580 and renders based upon the value of the state. 1802 01:30:11,580 --> 01:30:12,860 But I can ask a question. 1803 01:30:12,860 --> 01:30:17,330 If this.state.score is equal to 10, then render something. 1804 01:30:17,330 --> 01:30:19,840 Otherwise, render something else, that in this case, 1805 01:30:19,840 --> 01:30:23,180 I am returning a div that just says, "You won!" for example. 1806 01:30:23,180 --> 01:30:27,050 And otherwise, I'm not going to end up inside of this if condition, 1807 01:30:27,050 --> 01:30:31,670 in which case, we just return this normal div that includes a place where 1808 01:30:31,670 --> 01:30:35,160 we have the problem, an input field where you can provide some information, 1809 01:30:35,160 --> 01:30:37,160 and then a div where you can display your score. 1810 01:30:37,160 --> 01:30:39,920 And all of this is just based upon that state, 1811 01:30:39,920 --> 01:30:42,080 and given the state of a particular component, 1812 01:30:42,080 --> 01:30:44,120 React knows how to render that component, how 1813 01:30:44,120 --> 01:30:48,260 to display it to the user so the user can see what that interface ultimately 1814 01:30:48,260 --> 01:30:49,190 looks like. 1815 01:30:49,190 --> 01:30:52,550 And React is just one of many libraries that do this type of thing. 1816 01:30:52,550 --> 01:30:55,760 Other popular ones include Angular and View, where all of these 1817 01:30:55,760 --> 01:30:57,920 are just these web frameworks that make it easier 1818 01:30:57,920 --> 01:31:01,280 to be able to create applications that are able to respond 1819 01:31:01,280 --> 01:31:03,585 to some underlying state so that you, the programmer, 1820 01:31:03,585 --> 01:31:05,960 don't have to worry about constantly having to manipulate 1821 01:31:05,960 --> 01:31:08,810 various different parts of the page, especially 1822 01:31:08,810 --> 01:31:11,148 as you imagine websites like Facebook or Twitter, 1823 01:31:11,148 --> 01:31:13,940 where there are many things happening on the page at the same time. 1824 01:31:13,940 --> 01:31:16,670 Every time a new tweet comes in, you might get a notification 1825 01:31:16,670 --> 01:31:19,620 and see a new post in your main area of your news feed. 1826 01:31:19,620 --> 01:31:22,970 So these are the types of things that you might want the application 1827 01:31:22,970 --> 01:31:25,010 to be able to more easily handle for you, 1828 01:31:25,010 --> 01:31:27,050 where you describe what the state is. 1829 01:31:27,050 --> 01:31:30,410 You describe what the page should look like based on that underlying state 1830 01:31:30,410 --> 01:31:32,990 and let the library, whether it's React or something else, 1831 01:31:32,990 --> 01:31:36,400 begin to handle the process of doing that for you. 1832 01:31:36,400 --> 01:31:38,960 And the world of user interfaces is changing pretty quickly, 1833 01:31:38,960 --> 01:31:42,110 that a lot changes in user interfaces in terms of the technologies 1834 01:31:42,110 --> 01:31:43,740 and the tools that are quite popular. 1835 01:31:43,740 --> 01:31:46,282 But they're really based on the same set of underlying ideas, 1836 01:31:46,282 --> 01:31:50,090 the idea that we can use JavaScript in order to manipulate what it is the user 1837 01:31:50,090 --> 01:31:52,610 sees on their page in order to detect what's 1838 01:31:52,610 --> 01:31:55,040 happening based on particular events, like scrolling 1839 01:31:55,040 --> 01:31:58,190 to the bottom of the page or typing something into an input field, 1840 01:31:58,190 --> 01:32:00,800 and then responding to those particular events 1841 01:32:00,800 --> 01:32:03,560 by providing some sort of function that gets called 1842 01:32:03,560 --> 01:32:05,570 anytime a particular event happens. 1843 01:32:05,570 --> 01:32:08,060 By mixing that in with other features, like the ability 1844 01:32:08,060 --> 01:32:12,530 to asynchronously request information from an external server or the ability 1845 01:32:12,530 --> 01:32:16,280 to do computations based on the values of the state, like we saw within React, 1846 01:32:16,280 --> 01:32:18,680 we have the ability to create very interesting, 1847 01:32:18,680 --> 01:32:22,370 engaging, dynamic user interfaces very, very quickly, all just 1848 01:32:22,370 --> 01:32:25,887 using the power of combining Python and JavaScript. 1849 01:32:25,887 --> 01:32:28,470 That was Web Programming with Python and JavaScript for today. 1850 01:32:28,470 --> 01:32:30,460 We'll see you next time. 1851 01:32:30,460 --> 01:32:31,000