1 00:00:00,000 --> 00:00:03,395 [MUSIC PLAYING] 2 00:00:03,395 --> 00:00:12,130 3 00:00:12,130 --> 00:00:12,830 BRIAN YU: OK. 4 00:00:12,830 --> 00:00:14,190 Welcome back to CS50 Beyond. 5 00:00:14,190 --> 00:00:15,740 Hope you're all staying warm. 6 00:00:15,740 --> 00:00:17,720 So we'll pick up where we left off, diving a little bit more 7 00:00:17,720 --> 00:00:18,430 into JavaScript. 8 00:00:18,430 --> 00:00:21,380 Goal of this afternoon is look at a couple other JavaScript features 9 00:00:21,380 --> 00:00:24,890 just to give some more exposure, show you what kinds of things do exist, 10 00:00:24,890 --> 00:00:27,410 and how you can use JavaScript to build user interfaces. 11 00:00:27,410 --> 00:00:29,701 And then we'll dive a little more into user interfaces. 12 00:00:29,701 --> 00:00:31,610 In particular, today, looking at animation, 13 00:00:31,610 --> 00:00:34,580 animation which we can create using both CSS and JavaScript just 14 00:00:34,580 --> 00:00:37,100 to liven up pages, make them a little bit more interactive, 15 00:00:37,100 --> 00:00:38,840 make them a little more aesthetically pleasing. 16 00:00:38,840 --> 00:00:40,220 And we'll get an opportunity to play around 17 00:00:40,220 --> 00:00:42,350 with the types of web applications we can create 18 00:00:42,350 --> 00:00:45,680 once we have the ability to draw shapes and create animations 19 00:00:45,680 --> 00:00:47,140 all across the screen. 20 00:00:47,140 --> 00:00:50,179 So we'll start by looking at one JavaScript feature, which 21 00:00:50,179 --> 00:00:52,970 a couple of people were asking me about earlier this morning, which 22 00:00:52,970 --> 00:00:54,950 is the idea of doing something repeatedly 23 00:00:54,950 --> 00:00:57,410 and recurringly in over a fixed interval. 24 00:00:57,410 --> 00:01:03,080 And so if we take a look at inside the interval.HTML, what we'll see 25 00:01:03,080 --> 00:01:06,860 is inside the body we have an H1 that has ID of counter that 26 00:01:06,860 --> 00:01:08,842 initially is just set to zero. 27 00:01:08,842 --> 00:01:12,050 And then we have, very similar to what we had before, a counter variable that 28 00:01:12,050 --> 00:01:14,840 equals zero and a function called count that increments 29 00:01:14,840 --> 00:01:17,070 the counter and then just updates the counters 30 00:01:17,070 --> 00:01:19,892 HTML to be whatever the new value of the counter is. 31 00:01:19,892 --> 00:01:22,100 But here's the interesting part, when the DOM content 32 00:01:22,100 --> 00:01:27,110 is loaded we run this function called set interval, count, and 1,000. 33 00:01:27,110 --> 00:01:30,530 So what this is basically saying is every 1,000 milliseconds, 34 00:01:30,530 --> 00:01:33,620 or every second, run the count function again. 35 00:01:33,620 --> 00:01:35,520 And the result of that is-- 36 00:01:35,520 --> 00:01:39,920 I can open up interval.HTML. 37 00:01:39,920 --> 00:01:42,245 And then without doing anything, every one second we're 38 00:01:42,245 --> 00:01:44,870 just going to increment that counter again and again and again. 39 00:01:44,870 --> 00:01:47,270 So you could do this type of thing to implement like a timer feature, 40 00:01:47,270 --> 00:01:47,990 for instance. 41 00:01:47,990 --> 00:01:50,630 So if you wanted to go back into the quiz application you made this morning 42 00:01:50,630 --> 00:01:52,670 and had a timer to see, OK, how quickly can you 43 00:01:52,670 --> 00:01:53,720 get through all of the questions? 44 00:01:53,720 --> 00:01:56,300 You could do something like this to keep track of a running timer 45 00:01:56,300 --> 00:01:59,258 as you go through the game in order to keep track of how long something 46 00:01:59,258 --> 00:02:00,470 is taking you, for instance. 47 00:02:00,470 --> 00:02:02,750 Or if you want for some action to take place 48 00:02:02,750 --> 00:02:04,700 every so often on your web application, you 49 00:02:04,700 --> 00:02:07,190 can use intervals to do that as well. 50 00:02:07,190 --> 00:02:10,910 Now, one thing you may have noticed is as you're working on your web pages 51 00:02:10,910 --> 00:02:14,300 using JavaScript, anytime you close the page and reopen it 52 00:02:14,300 --> 00:02:16,100 it's as if everything is starting afresh. 53 00:02:16,100 --> 00:02:19,460 If I were to close this page and reopen interval.HTML, for instance, 54 00:02:19,460 --> 00:02:20,390 I go back to zero. 55 00:02:20,390 --> 00:02:22,160 Or if you were doing your quiz application 56 00:02:22,160 --> 00:02:24,410 and you started on question zero and maybe you were halfway 57 00:02:24,410 --> 00:02:27,140 through your questions and you closed the page and reopened it, 58 00:02:27,140 --> 00:02:29,450 you'd be back at the very first question again. 59 00:02:29,450 --> 00:02:32,690 And so JavaScript, at least in later versions and in more modern browsers, 60 00:02:32,690 --> 00:02:34,850 also supports this idea of local storage. 61 00:02:34,850 --> 00:02:37,760 The idea that sometimes I want to take information and just 62 00:02:37,760 --> 00:02:41,510 store it in the browser such that next time I reload the page 63 00:02:41,510 --> 00:02:44,670 I can just draw any information from that local storage. 64 00:02:44,670 --> 00:02:46,620 And so I'll show you an example of that. 65 00:02:46,620 --> 00:02:48,311 It's in storage.HTML. 66 00:02:48,311 --> 00:02:50,060 And all of the examples for this afternoon 67 00:02:50,060 --> 00:02:53,018 are already on the course website, if you want to take a look at those. 68 00:02:53,018 --> 00:02:55,540 And here's what we're doing, the body is exactly the same as 69 00:02:55,540 --> 00:02:57,290 before, we just have some counter variable 70 00:02:57,290 --> 00:02:59,120 and a button that says click here. 71 00:02:59,120 --> 00:03:03,290 And here's the interesting logic, the first thing that I'm going to do is 72 00:03:03,290 --> 00:03:07,160 say, all right, if local storage.getitem counter-- 73 00:03:07,160 --> 00:03:09,770 so local storage you can think of as just like a key value 74 00:03:09,770 --> 00:03:12,860 store where I can store something at a particular key 75 00:03:12,860 --> 00:03:15,770 and then I can access the value for a particular key. 76 00:03:15,770 --> 00:03:19,460 So if I try and get the counter, but it doesn't exist-- the exclamation point 77 00:03:19,460 --> 00:03:21,710 just means not as in not there, then I'll 78 00:03:21,710 --> 00:03:23,360 go ahead and set the counter to zero. 79 00:03:23,360 --> 00:03:26,720 Local storage.setitem, set the counter to zero. 80 00:03:26,720 --> 00:03:29,600 And so this is distinct from a variable, whereas a variable will only 81 00:03:29,600 --> 00:03:32,712 exist for this page while it is open, while this function is running, 82 00:03:32,712 --> 00:03:34,670 something in local storage is going to persist. 83 00:03:34,670 --> 00:03:37,640 You can close the page, you can quit the browser, restart the browser, 84 00:03:37,640 --> 00:03:41,180 and something in local storage will continue to stay there. 85 00:03:41,180 --> 00:03:45,440 And so now what's happening when the DOM content is loaded, I take the counter 86 00:03:45,440 --> 00:03:50,270 and I set it's inner HTML to be whatever you get when you take local storage 87 00:03:50,270 --> 00:03:52,470 and get whatever is inside the counter. 88 00:03:52,470 --> 00:03:55,100 Which means that rather than just set it to zero by default, 89 00:03:55,100 --> 00:03:58,490 I'm saying check local storage, get the counter out of local storage, 90 00:03:58,490 --> 00:04:01,150 and make that the default value of the counter. 91 00:04:01,150 --> 00:04:04,340 Anytime the button is clicked, this part at least should look very similar. 92 00:04:04,340 --> 00:04:06,880 I take the counter, give it a variable that's 93 00:04:06,880 --> 00:04:09,560 set to whatever the counter currently is-- call it counter. 94 00:04:09,560 --> 00:04:11,510 Increase the value of the counter. 95 00:04:11,510 --> 00:04:13,300 And then I'm going to do two things. 96 00:04:13,300 --> 00:04:18,110 Thing number one, I update whatever is inside the HTML page, 97 00:04:18,110 --> 00:04:21,050 setting its value to be whatever the counter variable is. 98 00:04:21,050 --> 00:04:23,180 And then I update local storage as well. 99 00:04:23,180 --> 00:04:26,990 I'm saving whatever the current value of the counter is to local storage, 100 00:04:26,990 --> 00:04:31,070 such that next time I open up the page I can draw on that local storage 101 00:04:31,070 --> 00:04:33,140 and those values will still be there. 102 00:04:33,140 --> 00:04:37,050 And so the result of this is, if I open up storage.HTML, I see-- 103 00:04:37,050 --> 00:04:37,550 OK. 104 00:04:37,550 --> 00:04:39,050 I see the number zero there. 105 00:04:39,050 --> 00:04:41,665 And I click one, two, three, four, five, six, seven, eight. 106 00:04:41,665 --> 00:04:44,540 And once it's there, normally if I were to close the page, reopen it, 107 00:04:44,540 --> 00:04:45,840 I'd be back to zero. 108 00:04:45,840 --> 00:04:49,490 But now if I close the page and reopen it, I'm still with the number eight. 109 00:04:49,490 --> 00:04:51,800 It was able to save that state inside of local storage, 110 00:04:51,800 --> 00:04:55,490 such that the next time I open it up I can actually access those values. 111 00:04:55,490 --> 00:04:58,580 And so that could be a helpful tool as you go about building applications 112 00:04:58,580 --> 00:05:00,784 that maybe, for example, in your quiz application 113 00:05:00,784 --> 00:05:03,200 you want it such that it remembers what question you're on 114 00:05:03,200 --> 00:05:05,960 or it remembers your score, such that even if you close your page 115 00:05:05,960 --> 00:05:08,566 and reopen it later, you're still at that same place. 116 00:05:08,566 --> 00:05:10,440 And so you can consider that as something you 117 00:05:10,440 --> 00:05:12,900 may want to implement as well later on this afternoon 118 00:05:12,900 --> 00:05:14,380 when we get to project time. 119 00:05:14,380 --> 00:05:15,210 Questions. 120 00:05:15,210 --> 00:05:15,861 Yeah. 121 00:05:15,861 --> 00:05:26,525 AUDIENCE: What is the scope [INAUDIBLE] 122 00:05:26,525 --> 00:05:27,150 BRIAN YU: Sure. 123 00:05:27,150 --> 00:05:28,608 What is the scope of local storage? 124 00:05:28,608 --> 00:05:30,270 How wide does it go? 125 00:05:30,270 --> 00:05:33,750 When you deploy applications to the internet it's by the domain name. 126 00:05:33,750 --> 00:05:37,240 So something .COM, for instance, would have its own local storage. 127 00:05:37,240 --> 00:05:39,904 In the case of files, your file systems basically 128 00:05:39,904 --> 00:05:41,820 are all going to share the same local storage. 129 00:05:41,820 --> 00:05:44,778 And you can actually see the contents of what's inside of local storage 130 00:05:44,778 --> 00:05:45,450 if you want to. 131 00:05:45,450 --> 00:05:48,960 If I Control Click on Chrome, at least, go into the inspector. 132 00:05:48,960 --> 00:05:54,030 And if you go in to application, on the left hand side 133 00:05:54,030 --> 00:05:56,370 here you should see local storage. 134 00:05:56,370 --> 00:05:58,710 And if I look at what's there, I see, OK, 135 00:05:58,710 --> 00:06:00,760 the key counter has a value of eight, so that's 136 00:06:00,760 --> 00:06:02,760 what's currently stored inside my local storage. 137 00:06:02,760 --> 00:06:03,360 So you could see that. 138 00:06:03,360 --> 00:06:04,430 You could update it if I wanted. 139 00:06:04,430 --> 00:06:07,320 I want to make the counter a little bit higher, like 28, for example. 140 00:06:07,320 --> 00:06:10,650 I can close the page, open the page again, and, OK, my counter is updated. 141 00:06:10,650 --> 00:06:12,660 I've changed what's inside of local storage 142 00:06:12,660 --> 00:06:16,369 and the result is that I've changed what shows up on the page. 143 00:06:16,369 --> 00:06:16,910 Other things? 144 00:06:16,910 --> 00:06:20,010 145 00:06:20,010 --> 00:06:21,070 OK. 146 00:06:21,070 --> 00:06:23,530 So thus far, all of our JavaScript programs 147 00:06:23,530 --> 00:06:26,920 have only existed on the client side and they've only involved 148 00:06:26,920 --> 00:06:28,681 code running inside of the browser. 149 00:06:28,681 --> 00:06:31,180 Yesterday, of course, we were dealing with server side code, 150 00:06:31,180 --> 00:06:33,010 like flask applications whereby you could 151 00:06:33,010 --> 00:06:34,880 talk to and interact with a server. 152 00:06:34,880 --> 00:06:35,860 And so what we're going to do now is just 153 00:06:35,860 --> 00:06:38,651 show a brief example of trying to combine these two ideas together, 154 00:06:38,651 --> 00:06:43,390 of having a client side application that can talk to some web server or some web 155 00:06:43,390 --> 00:06:43,891 API. 156 00:06:43,891 --> 00:06:47,181 We'll talk a little bit more about APIs, or application programming interfaces, 157 00:06:47,181 --> 00:06:47,800 tomorrow. 158 00:06:47,800 --> 00:06:51,580 But let's do one brief example, that maybe I 159 00:06:51,580 --> 00:06:57,140 want to write a website in JavaScript that allows me to get exchange rates. 160 00:06:57,140 --> 00:06:59,896 I want to figure out, OK, one US dollar, how many euros is that? 161 00:06:59,896 --> 00:07:01,270 Or how many Japanese yen is that? 162 00:07:01,270 --> 00:07:01,770 For example. 163 00:07:01,770 --> 00:07:03,710 And I wanted to do that conversion. 164 00:07:03,710 --> 00:07:07,202 Now, I could look up currently what the conversion rate is and plug that 165 00:07:07,202 --> 00:07:09,160 into my JavaScript code, but, of course, that's 166 00:07:09,160 --> 00:07:11,920 not totally accurate because tomorrow the exchange rates are going to change 167 00:07:11,920 --> 00:07:14,336 or even in a couple hours the exchange rates might change. 168 00:07:14,336 --> 00:07:17,857 I would like some way of knowing for sure what the current exchange rate is. 169 00:07:17,857 --> 00:07:19,690 And there happens to be an API that actually 170 00:07:19,690 --> 00:07:21,650 allows you to do this pretty easily. 171 00:07:21,650 --> 00:07:23,170 It's called Exchange Rates API. 172 00:07:23,170 --> 00:07:25,300 And you'd only know this by sort of Googling and looking around. 173 00:07:25,300 --> 00:07:27,550 And there are different APIs that do different things. 174 00:07:27,550 --> 00:07:34,730 And if I type in API.exchangeratesapi.io/latest. 175 00:07:34,730 --> 00:07:37,720 And I got this just by reading the website's documentation. 176 00:07:37,720 --> 00:07:42,490 What that does for me is it gives me a big JavaScript object 177 00:07:42,490 --> 00:07:44,860 that looks rather complicated, but basically it's 178 00:07:44,860 --> 00:07:46,930 giving me a whole bunch of exchange rates. 179 00:07:46,930 --> 00:07:52,300 And it's telling me, OK, here is how many Canadian dollars 1.5117 is 180 00:07:52,300 --> 00:07:55,180 equal to what base currency, one euro. 181 00:07:55,180 --> 00:07:57,070 So it's giving me all these exchange rates 182 00:07:57,070 --> 00:07:59,080 that are potentially useful for me. 183 00:07:59,080 --> 00:08:01,970 But, of course, I would rather not compare against the euro. 184 00:08:01,970 --> 00:08:04,340 I probably, in this case, want to be able to say, OK, 185 00:08:04,340 --> 00:08:07,190 how many of a certain currency is one US dollar? 186 00:08:07,190 --> 00:08:08,330 For example. 187 00:08:08,330 --> 00:08:11,350 And so in this case, I'm going to say, OK, I'm 188 00:08:11,350 --> 00:08:15,420 going to provide a parameter to this API route and say, base equals USD. 189 00:08:15,420 --> 00:08:16,720 I want US dollars only. 190 00:08:16,720 --> 00:08:19,131 191 00:08:19,131 --> 00:08:19,630 Oh, sorry. 192 00:08:19,630 --> 00:08:20,710 Not ampersand. 193 00:08:20,710 --> 00:08:21,910 Question mark. 194 00:08:21,910 --> 00:08:23,407 Base equals USD. 195 00:08:23,407 --> 00:08:25,990 And what I get there is I get a whole bunch of exchange rates, 196 00:08:25,990 --> 00:08:28,990 but now the base-- 197 00:08:28,990 --> 00:08:30,726 the base currency is US dollars. 198 00:08:30,726 --> 00:08:33,100 So I get all these exchange rates in terms of US dollars. 199 00:08:33,100 --> 00:08:38,230 And, again, this I would only know by actually going to exchangeratesapi.io 200 00:08:38,230 --> 00:08:42,309 and you can read the documentation here for how 201 00:08:42,309 --> 00:08:45,590 you would go about getting the exchange rates for any particular thing. 202 00:08:45,590 --> 00:08:47,340 And instead of getting all the currencies, 203 00:08:47,340 --> 00:08:53,590 if I just wanted one currency, I would say, and symbols equals euros. 204 00:08:53,590 --> 00:09:01,060 And so there we get, OK, one US dollar is equal to 0.8801 euros, at least 205 00:09:01,060 --> 00:09:03,430 as of today and as of right now. 206 00:09:03,430 --> 00:09:07,180 So this is an API that's returning to me some JavaScript object. 207 00:09:07,180 --> 00:09:11,020 And I could use this information to be able to implement something 208 00:09:11,020 --> 00:09:13,950 like a currency conversion application. 209 00:09:13,950 --> 00:09:15,790 And so I'll show you an example of that now. 210 00:09:15,790 --> 00:09:19,282 I'll open up currency.HTML. 211 00:09:19,282 --> 00:09:21,490 So this is a very simple application that all it does 212 00:09:21,490 --> 00:09:24,406 is it has an input field where I can type in a currency, a button that 213 00:09:24,406 --> 00:09:25,900 says Get Exchange Rate. 214 00:09:25,900 --> 00:09:28,330 And so if I type in something like Euro, for example, 215 00:09:28,330 --> 00:09:31,180 and click Get Exchange Rate, it says, one US dollar 216 00:09:31,180 --> 00:09:34,090 is equal to that number of euros, for example. 217 00:09:34,090 --> 00:09:36,340 Or if I type in Japanese yen. 218 00:09:36,340 --> 00:09:37,690 And so Get Exchange Rate. 219 00:09:37,690 --> 00:09:41,020 One US dollar is equal to 109.66 Japanese yen. 220 00:09:41,020 --> 00:09:44,640 If I type in something that doesn't exist, like beyond is not a currency, 221 00:09:44,640 --> 00:09:46,164 OK, there was an error. 222 00:09:46,164 --> 00:09:47,080 So how does this work? 223 00:09:47,080 --> 00:09:49,550 What is the code that actually implements this? 224 00:09:49,550 --> 00:09:52,900 We'll open up currency.HTML to take a look. 225 00:09:52,900 --> 00:09:55,940 Inside the body of the page, the body is actually quite simple. 226 00:09:55,940 --> 00:09:59,200 I have a form that has an input field called currency where 227 00:09:59,200 --> 00:10:01,300 I can type in the currency that I want. 228 00:10:01,300 --> 00:10:03,607 And I have a button, a Submit button for the form that 229 00:10:03,607 --> 00:10:04,940 just says Get The Exchange Rate. 230 00:10:04,940 --> 00:10:06,760 And I'm going to click on that button. 231 00:10:06,760 --> 00:10:07,990 And then I have a line break. 232 00:10:07,990 --> 00:10:09,070 That's what BR is. 233 00:10:09,070 --> 00:10:11,722 And then a div that's currently empty, where eventually I'm 234 00:10:11,722 --> 00:10:13,930 going to put the result of this calculation, whatever 235 00:10:13,930 --> 00:10:17,110 the result of looking up the exchange rate is. 236 00:10:17,110 --> 00:10:19,840 Now, what is the JavaScript that's making that work? 237 00:10:19,840 --> 00:10:23,810 Well, when the form is submitted, so on Submit for the form 238 00:10:23,810 --> 00:10:27,130 I'm going to get the value of the input field for the currency 239 00:10:27,130 --> 00:10:30,270 and save that in a variable called currency. 240 00:10:30,270 --> 00:10:32,970 And then I'm going to use this function called fetch. 241 00:10:32,970 --> 00:10:36,650 And what fetch is going to do it it's just going to request-- 242 00:10:36,650 --> 00:10:41,100 make an HTTP request, request some URL and get me back the results. 243 00:10:41,100 --> 00:10:46,470 And here I'm getting the results of going to API.exchangeratesapi.io/latest 244 00:10:46,470 --> 00:10:50,460 specifying the base being US dollars, and what symbol do I want? 245 00:10:50,460 --> 00:10:55,200 I want whatever currency I'm trying to convert into as the currency. 246 00:10:55,200 --> 00:10:59,040 So this is me making what's called an AJAX request, an asynchronous request 247 00:10:59,040 --> 00:11:03,090 where I'm requesting from some other URL, some other website not my own 248 00:11:03,090 --> 00:11:04,050 for some data. 249 00:11:04,050 --> 00:11:06,600 And in particular, I'd like data about the exchange rate, 250 00:11:06,600 --> 00:11:09,339 and then I'm going to get that back and do something with it. 251 00:11:09,339 --> 00:11:10,880 Before I go on, questions about this? 252 00:11:10,880 --> 00:11:12,400 I saw some yellow and red faces. 253 00:11:12,400 --> 00:11:16,694 So I'll pause for questions if there are any. 254 00:11:16,694 --> 00:11:17,194 Yeah. 255 00:11:17,194 --> 00:11:18,661 AUDIENCE: [INAUDIBLE]. 256 00:11:18,661 --> 00:11:26,000 257 00:11:26,000 --> 00:11:28,510 BRIAN YU: So the currency variable is going 258 00:11:28,510 --> 00:11:32,290 to be equal to whatever it is that I typed it, so like EUR for euros 259 00:11:32,290 --> 00:11:34,030 is what I typed into the text field. 260 00:11:34,030 --> 00:11:37,630 And then I'm taking that currency variable and plugging it into the URL, 261 00:11:37,630 --> 00:11:41,290 because if you look at the URL that I was using on the exchange rates API, 262 00:11:41,290 --> 00:11:44,080 up at the top I said, OK, base is going to be US dollars 263 00:11:44,080 --> 00:11:46,600 and the symbol is whatever I want to convert into. 264 00:11:46,600 --> 00:11:49,840 So I'm just plugging something into that spot in the URL, such 265 00:11:49,840 --> 00:11:52,760 that I can get a different exchange rate based on whatever I type in. 266 00:11:52,760 --> 00:11:52,910 Yeah. 267 00:11:52,910 --> 00:11:55,326 SPEAKER 3: Do you need to worry about escaping that string 268 00:11:55,326 --> 00:11:57,134 that you're plugging in to the URL? 269 00:11:57,134 --> 00:11:59,550 BRIAN YU: Do you need to worry about escaping that string? 270 00:11:59,550 --> 00:12:00,049 Sure. 271 00:12:00,049 --> 00:12:02,760 Certainly there are security considerations 272 00:12:02,760 --> 00:12:05,160 you might add here to check it to make sure. 273 00:12:05,160 --> 00:12:07,170 This is something we'll talk a little bit more about later in the week 274 00:12:07,170 --> 00:12:09,840 when we start talking about security in particular with regards to web 275 00:12:09,840 --> 00:12:10,170 requests. 276 00:12:10,170 --> 00:12:11,211 But, yeah, good thinking. 277 00:12:11,211 --> 00:12:13,619 278 00:12:13,619 --> 00:12:14,160 Other things. 279 00:12:14,160 --> 00:12:14,807 Yeah. 280 00:12:14,807 --> 00:12:16,298 AUDIENCE: [INAUDIBLE]. 281 00:12:16,298 --> 00:12:19,280 282 00:12:19,280 --> 00:12:22,449 BRIAN YU: If you're using JQuery and you do $.get, 283 00:12:22,449 --> 00:12:23,990 that'll behave in a very similar way. 284 00:12:23,990 --> 00:12:26,150 There are many ways of achieving the same general effect. 285 00:12:26,150 --> 00:12:28,420 Fetch just happens to be one of the more modern ways of doing so. 286 00:12:28,420 --> 00:12:30,211 But yeah, there are many ways in JavaScript 287 00:12:30,211 --> 00:12:34,480 to make an outgoing HTTP request. 288 00:12:34,480 --> 00:12:37,030 This syntax of .then don't worry about too much. 289 00:12:37,030 --> 00:12:39,190 This has to do with JavaScript promises. 290 00:12:39,190 --> 00:12:42,273 But the basic idea, or at least the idea that you should be getting across 291 00:12:42,273 --> 00:12:44,920 is, OK, I'm going to request this information from the server, 292 00:12:44,920 --> 00:12:49,330 then take the response and convert it to JSON, JavaScript Object Notation, 293 00:12:49,330 --> 00:12:51,700 until I get back a JavaScript object. 294 00:12:51,700 --> 00:12:57,220 And then with the resulting data, where is the actual exchange rate stored? 295 00:12:57,220 --> 00:13:01,470 Well, it's in a key called rates, and then this is the value. 296 00:13:01,470 --> 00:13:03,580 So I have to go into the key called rates 297 00:13:03,580 --> 00:13:07,030 and then go into a key called whatever the name of the currency 298 00:13:07,030 --> 00:13:10,450 is, and the value there is going to be the exchange 299 00:13:10,450 --> 00:13:13,100 rate, at least for this particular API. 300 00:13:13,100 --> 00:13:16,030 And so I'm going to set my-- the contents I'm going to fill 301 00:13:16,030 --> 00:13:19,910 in to my page to be one US dollar is equal to-- 302 00:13:19,910 --> 00:13:23,440 here is where I'm going to actually plug-in the currency exchange rate. 303 00:13:23,440 --> 00:13:27,730 So I go into the data, the object that came back, go into the rates key 304 00:13:27,730 --> 00:13:31,030 and then index into it and say, OK, get me the currency key. 305 00:13:31,030 --> 00:13:33,790 And that's going to get me the number of the exchange rate. 306 00:13:33,790 --> 00:13:36,010 And then just fill in the currency there, 307 00:13:36,010 --> 00:13:38,980 so it says this is equal to this number of euros or this number of yen, 308 00:13:38,980 --> 00:13:40,420 for example. 309 00:13:40,420 --> 00:13:46,780 And then just fill that into the result section of the page. 310 00:13:46,780 --> 00:13:50,450 The catch here is very similar to Python's Try Except syntax 311 00:13:50,450 --> 00:13:53,200 of like, try something, and if something goes wrong, do something. 312 00:13:53,200 --> 00:13:56,740 Catch just means, if anywhere along this path there was some sort of error, 313 00:13:56,740 --> 00:14:00,310 then go ahead and just include in the results section there was an error. 314 00:14:00,310 --> 00:14:02,470 That'll happen if I can't find the right key 315 00:14:02,470 --> 00:14:04,564 or if the request doesn't work for some reason. 316 00:14:04,564 --> 00:14:05,980 That's what will end up happening. 317 00:14:05,980 --> 00:14:06,582 Yeah. 318 00:14:06,582 --> 00:14:08,842 AUDIENCE: So it's not based on [INAUDIBLE].. 319 00:14:08,842 --> 00:14:11,555 320 00:14:11,555 --> 00:14:14,405 Based on [INAUDIBLE]. 321 00:14:14,405 --> 00:14:19,825 From the line above and fetch just goes by the chain of [INAUDIBLE].. 322 00:14:19,825 --> 00:14:20,450 BRIAN YU: Yeah. 323 00:14:20,450 --> 00:14:22,850 JavaScript is not indentation based, unlike Python. 324 00:14:22,850 --> 00:14:25,497 So the indentation in JavaScript is just aesthetic. 325 00:14:25,497 --> 00:14:27,830 It helps to make things clearer, but it's not necessary. 326 00:14:27,830 --> 00:14:30,800 The way that these are linked together is via these dots. 327 00:14:30,800 --> 00:14:33,510 So in reality these are all just being chained together. 328 00:14:33,510 --> 00:14:35,480 And this is a common syntax in JavaScript 329 00:14:35,480 --> 00:14:37,771 that you'll often see, that things get chained together 330 00:14:37,771 --> 00:14:40,430 one function being called after another function after another. 331 00:14:40,430 --> 00:14:42,138 We'll see another example of this when we 332 00:14:42,138 --> 00:14:45,330 get to animation as well, of this chaining of functions after each other. 333 00:14:45,330 --> 00:14:46,456 Yeah. 334 00:14:46,456 --> 00:14:47,920 AUDIENCE: [INAUDIBLE]. 335 00:14:47,920 --> 00:14:52,800 336 00:14:52,800 --> 00:14:55,728 To have a constant content [INAUDIBLE]. 337 00:14:55,728 --> 00:15:02,392 338 00:15:02,392 --> 00:15:04,600 BRIAN YU: You could certainly eliminate the variable. 339 00:15:04,600 --> 00:15:06,590 I did it this way just so it would fit on one screen 340 00:15:06,590 --> 00:15:08,260 so you all could see it more easily. 341 00:15:08,260 --> 00:15:08,901 Yeah. 342 00:15:08,901 --> 00:15:11,657 AUDIENCE: [INAUDIBLE] data [INAUDIBLE]? 343 00:15:11,657 --> 00:15:12,240 BRIAN YU: Yes. 344 00:15:12,240 --> 00:15:14,422 This word response and this word data, these 345 00:15:14,422 --> 00:15:15,880 are just arguments to the function. 346 00:15:15,880 --> 00:15:18,360 And so they could be called anything you want to call them. 347 00:15:18,360 --> 00:15:18,790 Yeah. 348 00:15:18,790 --> 00:15:19,415 AUDIENCE: Yeah. 349 00:15:19,415 --> 00:15:23,011 I'm just a little confused about what is response and what is data 350 00:15:23,011 --> 00:15:24,800 and what exactly do they pull? 351 00:15:24,800 --> 00:15:25,700 BRIAN YU: Yeah. 352 00:15:25,700 --> 00:15:29,220 So response, in this case, is a special JavaScript object 353 00:15:29,220 --> 00:15:32,760 that represents an HTTP response just to some web request. 354 00:15:32,760 --> 00:15:36,900 And so an HTTP response happens to have a function called .Json, 355 00:15:36,900 --> 00:15:40,620 which takes that HTTP response, converts it to a JavaScript object, 356 00:15:40,620 --> 00:15:43,620 just keys and values like we were doing with the questions this morning, 357 00:15:43,620 --> 00:15:45,300 and returns that object. 358 00:15:45,300 --> 00:15:48,799 Of course, not all HTTP responses can be turned into objects, 359 00:15:48,799 --> 00:15:51,090 so there's a chance that something will go wrong there, 360 00:15:51,090 --> 00:15:54,370 which is what the catch here is for in case something happens to go wrong. 361 00:15:54,370 --> 00:15:58,050 So we take the HTTP response, convert it into an object, 362 00:15:58,050 --> 00:16:01,500 and then data is just going to be that JavaScript object. 363 00:16:01,500 --> 00:16:06,070 It's just going to be literally this, the curly brace rates and then 364 00:16:06,070 --> 00:16:07,320 what the base is, for example. 365 00:16:07,320 --> 00:16:10,314 AUDIENCE: And how does data know that what it's taking in as input 366 00:16:10,314 --> 00:16:12,522 is response.Json? 367 00:16:12,522 --> 00:16:14,730 BRIAN YU: How does data know that what it's taking in 368 00:16:14,730 --> 00:16:16,230 is a result of response.Json? 369 00:16:16,230 --> 00:16:18,420 That's what this chaining .then is. 370 00:16:18,420 --> 00:16:21,502 So when you chain the .thens together, it's one thing after another. 371 00:16:21,502 --> 00:16:24,210 I wouldn't worry too much about the specifics of the syntax here. 372 00:16:24,210 --> 00:16:27,741 You can take a look at the example later as well for more examples of that. 373 00:16:27,741 --> 00:16:28,240 Yeah. 374 00:16:28,240 --> 00:16:29,136 AUDIENCE: Just to make sure. 375 00:16:29,136 --> 00:16:31,824 Does that have to be [? response and ?] [? data? ?] Or we can just 376 00:16:31,824 --> 00:16:32,280 [? take it in whatever? ?] 377 00:16:32,280 --> 00:16:32,821 BRIAN YU: No. 378 00:16:32,821 --> 00:16:34,500 Response and data are arbitrary names. 379 00:16:34,500 --> 00:16:35,458 They could be anything. 380 00:16:35,458 --> 00:16:39,000 381 00:16:39,000 --> 00:16:39,750 OK. 382 00:16:39,750 --> 00:16:42,750 So those are just some other JavaScript features, the idea of intervals, 383 00:16:42,750 --> 00:16:46,272 the idea of local storage, the idea of AJAX requests to get additional data. 384 00:16:46,272 --> 00:16:49,230 So now let's turn our attention a little bit, change gears a little bit 385 00:16:49,230 --> 00:16:50,580 to talking about user interfaces. 386 00:16:50,580 --> 00:16:53,288 We'll talk about user interfaces, how to make them more engaging, 387 00:16:53,288 --> 00:16:56,100 the types of features you'll often see in modern user interfaces. 388 00:16:56,100 --> 00:16:59,862 And we'll start by a little bit of discussion about a window. 389 00:16:59,862 --> 00:17:02,070 And so here is what a browser window might look like. 390 00:17:02,070 --> 00:17:05,550 You've got the menu bar along the top and then 391 00:17:05,550 --> 00:17:07,500 you've got the entire contents of the page. 392 00:17:07,500 --> 00:17:11,700 And there are certain attributes you can access about the window in JavaScript. 393 00:17:11,700 --> 00:17:14,160 If you say window.innerwidth what you'll get 394 00:17:14,160 --> 00:17:17,751 is a number of pixels equal to how wide the current page is. 395 00:17:17,751 --> 00:17:19,500 So you shrink the page, you grow the page, 396 00:17:19,500 --> 00:17:21,630 that will change window.innerwidth. 397 00:17:21,630 --> 00:17:26,211 And likewise, window.innerheight is how many pixels tall the page is. 398 00:17:26,211 --> 00:17:29,460 And so we saw this a little bit when we were dealing with media queries in CSS 399 00:17:29,460 --> 00:17:31,169 when we wanted to say, OK, if the page is 400 00:17:31,169 --> 00:17:34,501 smaller than a certain number of pixels, then do something slightly differently. 401 00:17:34,501 --> 00:17:36,240 But that's inner width and inner height. 402 00:17:36,240 --> 00:17:38,280 Then there are also some other variables that we 403 00:17:38,280 --> 00:17:42,360 can access about the current state of the user's experience on the page. 404 00:17:42,360 --> 00:17:46,235 The entire page is probably bigger than what's visible on the window, 405 00:17:46,235 --> 00:17:48,360 because there might be stuff above it, stuff below. 406 00:17:48,360 --> 00:17:51,710 You would scroll up and scroll down in order to see. 407 00:17:51,710 --> 00:17:56,250 Window.scrollY is a value that represents how far in the Y 408 00:17:56,250 --> 00:17:59,310 direction, the vertical direction, have you scrolled so far. 409 00:17:59,310 --> 00:18:02,430 So if you're at the very top of the page, window.scrollY is zero. 410 00:18:02,430 --> 00:18:06,270 If you scroll down 50 pixels, window.scrollY is 50. 411 00:18:06,270 --> 00:18:09,090 And finally, one other value that might be interesting to know, 412 00:18:09,090 --> 00:18:14,130 document.body.offsetheight just refers to the entire height 413 00:18:14,130 --> 00:18:17,850 of the document, not just the visible area, but from top of the document 414 00:18:17,850 --> 00:18:20,730 to the bottom of the web document, how many pixels is it? 415 00:18:20,730 --> 00:18:22,890 How many pixels would you have to scroll to get 416 00:18:22,890 --> 00:18:25,990 all the way from the top to the bottom? 417 00:18:25,990 --> 00:18:27,790 So a couple of interesting values there. 418 00:18:27,790 --> 00:18:30,390 And so now, interesting question, what would you 419 00:18:30,390 --> 00:18:33,150 write in code if you wanted to check to see 420 00:18:33,150 --> 00:18:34,665 if you were at the bottom of a page? 421 00:18:34,665 --> 00:18:38,440 422 00:18:38,440 --> 00:18:40,767 What would the expression look like if you 423 00:18:40,767 --> 00:18:42,850 wanted to see if you were at the bottom of a page? 424 00:18:42,850 --> 00:18:44,860 Take a few moments to think about it. 425 00:18:44,860 --> 00:18:47,854 And then we'll see if anyone has a guess. 426 00:18:47,854 --> 00:18:50,170 AUDIENCE: [INAUDIBLE]. 427 00:18:50,170 --> 00:18:52,570 BRIAN YU: Document.body.offsetheight refers 428 00:18:52,570 --> 00:18:56,020 to the entire height of the web page, not just the visible part 429 00:18:56,020 --> 00:18:58,210 on the window, it's from the very top of the page 430 00:18:58,210 --> 00:19:01,043 all the way to the bottom of the page, which you might theoretically 431 00:19:01,043 --> 00:19:05,240 need to scroll through, but it's the entire height of the document. 432 00:19:05,240 --> 00:19:05,740 OK. 433 00:19:05,740 --> 00:19:07,590 How would you find out if you're at the bottom of the page? 434 00:19:07,590 --> 00:19:08,642 Yeah. 435 00:19:08,642 --> 00:19:11,974 AUDIENCE: Window.scrollY plus window.innerheight [INAUDIBLE] 436 00:19:11,974 --> 00:19:14,155 document.body.offsetheight. 437 00:19:14,155 --> 00:19:14,780 BRIAN YU: Yeah. 438 00:19:14,780 --> 00:19:18,860 So long is window.scrollY and window.innerheight are 439 00:19:18,860 --> 00:19:21,077 as tall as document.body.offsetheight. 440 00:19:21,077 --> 00:19:23,660 That's how you would know if you're at the bottom of the page, 441 00:19:23,660 --> 00:19:27,230 because the amount that you scrolled by plus the height of the window 442 00:19:27,230 --> 00:19:29,910 would take you all the way to the bottom of the page. 443 00:19:29,910 --> 00:19:32,930 And so we could actually use this in a brief example. 444 00:19:32,930 --> 00:19:35,330 Let's open up scroll.HTML. 445 00:19:35,330 --> 00:19:38,210 And whereby in the body of scroll.HTML I just 446 00:19:38,210 --> 00:19:40,700 have a lot of paragraphs, paragraph one, two, three, four, 447 00:19:40,700 --> 00:19:42,959 all the way down to paragraph 100. 448 00:19:42,959 --> 00:19:45,500 So I just have 100 paragraphs that just have numbers in them. 449 00:19:45,500 --> 00:19:47,300 Nothing all that exciting. 450 00:19:47,300 --> 00:19:50,720 But here inside my JavaScript I've got some code. 451 00:19:50,720 --> 00:19:53,420 Window.onscroll, so this is another event handler. 452 00:19:53,420 --> 00:19:56,090 Whenever the window is scrolled, run some code. 453 00:19:56,090 --> 00:20:00,410 And if window.innerheight plus window.scrollY 454 00:20:00,410 --> 00:20:03,890 is at least as tall as the document.body.offsetheight, 455 00:20:03,890 --> 00:20:07,690 then go ahead and change the style of the body of the page 456 00:20:07,690 --> 00:20:11,940 to green, and otherwise, change it to white. 457 00:20:11,940 --> 00:20:16,866 In other words, if I hit the bottom of the page, turn the page green. 458 00:20:16,866 --> 00:20:20,610 So I'll show you that code. 459 00:20:20,610 --> 00:20:24,240 As soon as I hit the bottom of the page, scrollY plus innerheight 460 00:20:24,240 --> 00:20:26,320 is equal to the total height of the document. 461 00:20:26,320 --> 00:20:29,480 I'm going to change the background of the page to be green. 462 00:20:29,480 --> 00:20:32,100 And so open up scroll.HTML. 463 00:20:32,100 --> 00:20:34,290 I see I have all these paragraphs. 464 00:20:34,290 --> 00:20:37,170 And if I scroll down all the way to the bottom, paragraph number 100, 465 00:20:37,170 --> 00:20:38,504 the page is white right now. 466 00:20:38,504 --> 00:20:40,920 And as soon as I hit the bottom, OK, the page turns green. 467 00:20:40,920 --> 00:20:42,270 I scroll up, it's white. 468 00:20:42,270 --> 00:20:44,436 Hit the bottom, the page turns green. 469 00:20:44,436 --> 00:20:46,810 So I'm able to detect when I'm at the bottom of the page. 470 00:20:46,810 --> 00:20:48,240 And now, why might that be useful? 471 00:20:48,240 --> 00:20:50,031 In what context, in an application would it 472 00:20:50,031 --> 00:20:52,450 be good to know if you're at the bottom of a web page? 473 00:20:52,450 --> 00:20:54,300 Why do we care? 474 00:20:54,300 --> 00:20:55,119 Yeah. 475 00:20:55,119 --> 00:20:57,160 AUDIENCE: Well, a lot of news sites nowadays when 476 00:20:57,160 --> 00:20:59,400 you get to the bottom it shows the next story. 477 00:20:59,400 --> 00:20:59,640 BRIAN YU: Yeah. 478 00:20:59,640 --> 00:21:02,056 A lot of news sites nowadays when you scroll to the bottom 479 00:21:02,056 --> 00:21:06,660 you get the next story or we'll get sort of this dynamic loading 480 00:21:06,660 --> 00:21:10,460 where when you get to the end of the page, it'll load the next set of posts 481 00:21:10,460 --> 00:21:12,290 or the next set of articles, for instance, 482 00:21:12,290 --> 00:21:15,480 so that you can keep scrolling infinitely, this infinite scroll idea. 483 00:21:15,480 --> 00:21:18,540 And so we can use this notion to actually implement infinite scroll. 484 00:21:18,540 --> 00:21:20,290 I won't show you all of the code, but I'll 485 00:21:20,290 --> 00:21:22,200 show you the relevant portions of it. 486 00:21:22,200 --> 00:21:26,400 If we go in to the post zero example. 487 00:21:26,400 --> 00:21:32,430 What I have here is a flask application where in application.pi I basically 488 00:21:32,430 --> 00:21:36,632 just have a route that's going to-- called slash post where you can specify 489 00:21:36,632 --> 00:21:39,090 the start post that you want and the end post that you want 490 00:21:39,090 --> 00:21:43,410 and it will return to you a JSON object that's containing all of those posts. 491 00:21:43,410 --> 00:21:47,820 And in index.HTML, here's the interesting code. 492 00:21:47,820 --> 00:21:52,060 We're going to start with a body that just has an empty set of posts. 493 00:21:52,060 --> 00:21:56,170 And we're going to-- 494 00:21:56,170 --> 00:21:58,400 whenever we scroll the page-- 495 00:21:58,400 --> 00:22:02,020 so first, when DOM content loaded, when we first load the page, 496 00:22:02,020 --> 00:22:06,010 call the load function to load the first 20 posts, for example. 497 00:22:06,010 --> 00:22:09,490 And then when the window is scrolled, if the inner height plus scrollY 498 00:22:09,490 --> 00:22:13,250 is at least document.body.offsetheight, same equation as we were using before. 499 00:22:13,250 --> 00:22:15,460 In other words, if we've hit the bottom of the page, 500 00:22:15,460 --> 00:22:17,716 then go ahead and load the next set of posts. 501 00:22:17,716 --> 00:22:20,340 And all load is doing-- and you can take a look at this later-- 502 00:22:20,340 --> 00:22:23,170 is it's calculating what the start and end post number should be. 503 00:22:23,170 --> 00:22:25,961 And then it's making a fetch request, just fetching from the server 504 00:22:25,961 --> 00:22:29,350 just like we saw a moment ago trying to get the next set of posts. 505 00:22:29,350 --> 00:22:31,360 But the relevant part, at least for now, is just 506 00:22:31,360 --> 00:22:34,030 to understand these couple of lines here, 507 00:22:34,030 --> 00:22:36,820 that when the window is scrolled, if it is the case that we've 508 00:22:36,820 --> 00:22:42,850 hit the bottom of the page, then go ahead and load the next set of posts. 509 00:22:42,850 --> 00:22:46,300 And so I'll go ahead and go flask run here. 510 00:22:46,300 --> 00:22:48,400 We'll load up this page. 511 00:22:48,400 --> 00:22:49,810 We get a whole bunch of posts. 512 00:22:49,810 --> 00:22:52,440 I notice I'm almost about to hit the bottom. 513 00:22:52,440 --> 00:22:54,190 And when I hit the bottom, post number 20, 514 00:22:54,190 --> 00:22:56,820 there's a moment's pause, but, OK, then the next set of post loads. 515 00:22:56,820 --> 00:22:59,320 I scroll to the bottom again, and, OK, the next set of post loads. 516 00:22:59,320 --> 00:23:00,250 And I can do this infinitely. 517 00:23:00,250 --> 00:23:02,980 I can continue to scroll and continue to get a new set of posts 518 00:23:02,980 --> 00:23:06,620 because every time I hit the bottom of the page, the next set loads. 519 00:23:06,620 --> 00:23:08,830 And so this ability to know where I am on the page 520 00:23:08,830 --> 00:23:10,840 can allow for things like infinite scroll 521 00:23:10,840 --> 00:23:13,120 and the implementation of features like it. 522 00:23:13,120 --> 00:23:13,910 Questions. 523 00:23:13,910 --> 00:23:14,990 Yeah. 524 00:23:14,990 --> 00:23:16,370 AUDIENCE: [INAUDIBLE]. 525 00:23:16,370 --> 00:23:19,130 526 00:23:19,130 --> 00:23:24,250 If it was on the top of the page as well [INAUDIBLE].. 527 00:23:24,250 --> 00:23:30,240 BRIAN YU: If I'm at the top of the page, then the document.body.offsetheight, 528 00:23:30,240 --> 00:23:32,740 the body of the document is going to be the entire document, 529 00:23:32,740 --> 00:23:35,170 but the window.innerheight, the height of the window 530 00:23:35,170 --> 00:23:37,150 is only going to be a small portion of that. 531 00:23:37,150 --> 00:23:40,360 And scrollY will be zero, because I won't have scrolled at all. 532 00:23:40,360 --> 00:23:42,640 And so the total height is going to be much less 533 00:23:42,640 --> 00:23:45,400 than the total height of the document. 534 00:23:45,400 --> 00:23:50,980 So if you go back to this image, if I'm at the top of the page, 535 00:23:50,980 --> 00:23:53,724 if you add scrollY, which is zero with the inner height, 536 00:23:53,724 --> 00:23:56,140 it's going to be substantially less than the offset height 537 00:23:56,140 --> 00:23:59,310 if it's a tall document. 538 00:23:59,310 --> 00:24:01,140 Other things. 539 00:24:01,140 --> 00:24:02,086 Yeah. 540 00:24:02,086 --> 00:24:04,960 AUDIENCE: Why [? is it ?] [? greater ?] [? than ?] [? or equal to? ?] 541 00:24:04,960 --> 00:24:07,930 BRIAN YU: Greater than or equal to just to be able to handle browser case where 542 00:24:07,930 --> 00:24:10,720 sometimes you can do a little bit of scrolling past the bottom of the page, 543 00:24:10,720 --> 00:24:11,240 for example. 544 00:24:11,240 --> 00:24:16,550 545 00:24:16,550 --> 00:24:18,591 Other things. 546 00:24:18,591 --> 00:24:19,090 OK. 547 00:24:19,090 --> 00:24:21,550 And with end, if you're curious about what the load function is doing, 548 00:24:21,550 --> 00:24:24,070 it's basically making a request, and for each post 549 00:24:24,070 --> 00:24:26,530 that comes back, running this add post function. 550 00:24:26,530 --> 00:24:31,120 All add post is doing is it's creating a new div, giving it a class name, 551 00:24:31,120 --> 00:24:34,360 and then adding it to the DOM, just appending it 552 00:24:34,360 --> 00:24:37,330 to the section of the page that is dedicated to all the posts. 553 00:24:37,330 --> 00:24:42,310 And the result of that is we get this infinite scroll-like feature. 554 00:24:42,310 --> 00:24:44,620 With a little bit of additional work, we can actually 555 00:24:44,620 --> 00:24:47,650 use it to allow users to hide posts as well. 556 00:24:47,650 --> 00:24:49,060 So I'll show you-- 557 00:24:49,060 --> 00:24:51,380 we'll go into post one. 558 00:24:51,380 --> 00:24:55,610 And the only difference in post one is in index.HTML, 559 00:24:55,610 --> 00:24:58,640 if you look down at the add post function, 560 00:24:58,640 --> 00:25:00,950 in addition to creating a div, I'm also just creating 561 00:25:00,950 --> 00:25:04,340 a button called Hide that's going to hide the post. 562 00:25:04,340 --> 00:25:08,544 And when you click the Hide button it's going to remove the post altogether. 563 00:25:08,544 --> 00:25:10,710 And so I'll let you look at that code in more detail 564 00:25:10,710 --> 00:25:12,530 if it's something you're curious about. 565 00:25:12,530 --> 00:25:13,820 It's online. 566 00:25:13,820 --> 00:25:16,400 But now what we have is we have infinite scrolling posts. 567 00:25:16,400 --> 00:25:19,330 But if I want to, I can click the Hide button next to post 16 568 00:25:19,330 --> 00:25:23,860 and it goes away, just goes straight from 15 to 17, for example. 569 00:25:23,860 --> 00:25:25,970 Those are just more examples of what it is 570 00:25:25,970 --> 00:25:32,140 that you can do by taking advantage of the features that JavaScript offers. 571 00:25:32,140 --> 00:25:35,230 Questions about anything we've talked about so far? 572 00:25:35,230 --> 00:25:36,560 Yeah. 573 00:25:36,560 --> 00:25:37,996 AUDIENCE: As far as-- 574 00:25:37,996 --> 00:25:39,715 would you mind going back to the code? 575 00:25:39,715 --> 00:25:40,590 BRIAN YU: Which code? 576 00:25:40,590 --> 00:25:42,415 AUDIENCE: The [INAUDIBLE]. 577 00:25:42,415 --> 00:25:43,040 BRIAN YU: Yeah. 578 00:25:43,040 --> 00:25:50,400 579 00:25:50,400 --> 00:25:53,060 AUDIENCE: As far as the constant variables throughout, 580 00:25:53,060 --> 00:25:57,120 is there any advantages [INAUDIBLE] accidental changes? 581 00:25:57,120 --> 00:25:59,372 Like, what if you just didn't [INAUDIBLE]?? 582 00:25:59,372 --> 00:26:02,330 BRIAN YU: They could all be let variables instead of constant variables 583 00:26:02,330 --> 00:26:03,950 and it would work just fine in this case. 584 00:26:03,950 --> 00:26:05,630 Constant is just there as a security measure 585 00:26:05,630 --> 00:26:07,713 basically, to make sure that nothing gets changed. 586 00:26:07,713 --> 00:26:10,770 587 00:26:10,770 --> 00:26:11,270 OK. 588 00:26:11,270 --> 00:26:12,644 Let's do a bit of a change gears. 589 00:26:12,644 --> 00:26:15,920 Still on the topic of user interfaces and user experience. 590 00:26:15,920 --> 00:26:19,670 And let's try creating a new HTML page. 591 00:26:19,670 --> 00:26:20,960 I'll call it index.HTML. 592 00:26:20,960 --> 00:26:24,960 593 00:26:24,960 --> 00:26:27,530 It's going to have a header, title, hello. 594 00:26:27,530 --> 00:26:34,379 And in the body of the pager we're just going to say, welcome, again. 595 00:26:34,379 --> 00:26:36,920 Now what I'm going to do is I'm going to add some style code. 596 00:26:36,920 --> 00:26:39,260 But first let's look at the page, make sure it looks OK. 597 00:26:39,260 --> 00:26:41,250 Open up index.HTML. 598 00:26:41,250 --> 00:26:41,750 All right. 599 00:26:41,750 --> 00:26:44,180 Welcome looks fine. 600 00:26:44,180 --> 00:26:47,510 But now what I'm going to do is I'm going to add some style code. 601 00:26:47,510 --> 00:26:50,950 And in particular, I'm going to add some CSS animation, some CSS 602 00:26:50,950 --> 00:26:52,910 code that is going to allow me to animate 603 00:26:52,910 --> 00:26:54,890 what it is that's on the screen. 604 00:26:54,890 --> 00:26:56,630 And to do this I'm going to call-- 605 00:26:56,630 --> 00:27:00,650 use a special syntax called At Key Frames. 606 00:27:00,650 --> 00:27:03,110 So I'm going to define the name of an animation. 607 00:27:03,110 --> 00:27:06,140 And the name of this animation I'm going to call Grow, 608 00:27:06,140 --> 00:27:11,750 because we're going to grow the size of our heading, is what we're going to do. 609 00:27:11,750 --> 00:27:15,110 And to do this we define two keys, from and to. 610 00:27:15,110 --> 00:27:18,080 From is what the style is like at the beginning, 611 00:27:18,080 --> 00:27:20,579 and two is what the style is like at the end. 612 00:27:20,579 --> 00:27:22,370 And what I'd like to say is, when something 613 00:27:22,370 --> 00:27:27,890 grows it should go from having a font size of 20 pixels 614 00:27:27,890 --> 00:27:32,630 to having a font size of 100 pixels. 615 00:27:32,630 --> 00:27:34,370 So here I've defined an animation. 616 00:27:34,370 --> 00:27:37,880 At Key Frames Grow we're going to grow from something with a font size of 20 617 00:27:37,880 --> 00:27:40,580 to something with a font size of 100. 618 00:27:40,580 --> 00:27:47,300 And now for any H1, any heading, I'm going to say animation name is Grow. 619 00:27:47,300 --> 00:27:50,360 In other words, you should apply the Grow animation. 620 00:27:50,360 --> 00:27:52,610 And I'll add a couple other CSS properties. 621 00:27:52,610 --> 00:27:56,660 Animation film mode forwards is just going 622 00:27:56,660 --> 00:28:00,620 to say, once you get to where you're going, once you get to 100 pixels 623 00:28:00,620 --> 00:28:04,370 at the end of the Grow animation, stop there, and just retain 624 00:28:04,370 --> 00:28:06,170 that style state. 625 00:28:06,170 --> 00:28:09,410 And then finally, you say, OK, how long should this animation take? 626 00:28:09,410 --> 00:28:14,060 We'll say animation-duration, two seconds. 627 00:28:14,060 --> 00:28:15,940 So I've defined an animation called Grow. 628 00:28:15,940 --> 00:28:17,200 Could've been called anything. 629 00:28:17,200 --> 00:28:18,533 What does the Grow animation do? 630 00:28:18,533 --> 00:28:21,310 It goes from a font size of 20 to a font size of 100. 631 00:28:21,310 --> 00:28:23,230 And then I said for any heading, go ahead 632 00:28:23,230 --> 00:28:26,350 and use the Grow animation go forwards and it 633 00:28:26,350 --> 00:28:28,930 should take two seconds to do so. 634 00:28:28,930 --> 00:28:32,690 So now I refresh index.HTML and you get that animation. 635 00:28:32,690 --> 00:28:36,260 You refresh the page, it goes from 20 pixels to 100 pixels. 636 00:28:36,260 --> 00:28:40,192 I've been able to create something a little bit more dynamic. 637 00:28:40,192 --> 00:28:41,900 Questions about that and what I just did? 638 00:28:41,900 --> 00:28:42,551 Yeah. 639 00:28:42,551 --> 00:28:44,685 AUDIENCE: Can you explain what key frames is again? 640 00:28:44,685 --> 00:28:45,310 BRIAN YU: Yeah. 641 00:28:45,310 --> 00:28:48,010 Key frames is just defining what the-- 642 00:28:48,010 --> 00:28:50,230 we'll call, what the key frames of the animation are. 643 00:28:50,230 --> 00:28:54,340 In other words, what are the points in the animation at which the element 644 00:28:54,340 --> 00:28:55,675 should have a particular style? 645 00:28:55,675 --> 00:28:58,300 And here I'm saying at the beginning of the animation it should 646 00:28:58,300 --> 00:29:01,330 have a font size of 20 and at the end of the animation it 647 00:29:01,330 --> 00:29:02,622 should have a font size of 100. 648 00:29:02,622 --> 00:29:05,080 The beginning of the animation and the end of the animation 649 00:29:05,080 --> 00:29:06,580 are what we'll call the key frames. 650 00:29:06,580 --> 00:29:10,360 And the browser is going to do the heavy lifting of figuring out 651 00:29:10,360 --> 00:29:14,210 how to actually change the element from the from state to the to state. 652 00:29:14,210 --> 00:29:14,710 Yeah. 653 00:29:14,710 --> 00:29:17,120 AUDIENCE: [INAUDIBLE]. 654 00:29:17,120 --> 00:29:19,760 BRIAN YU: You could have multiple properties inside of to. 655 00:29:19,760 --> 00:29:23,170 So you could have multiple things that are happening inside of this animation. 656 00:29:23,170 --> 00:29:25,540 And font size is not the only thing you could do. 657 00:29:25,540 --> 00:29:31,480 I could say, for example, left 0%, meaning start 0% away 658 00:29:31,480 --> 00:29:35,830 from the left hand side and go to 50% away from the left hand side, 659 00:29:35,830 --> 00:29:38,780 like 50% of the window away from the left side. 660 00:29:38,780 --> 00:29:42,970 And if I reload that, the effect of that is, OK, we get-- well, 661 00:29:42,970 --> 00:29:44,560 that didn't work. 662 00:29:44,560 --> 00:29:49,060 From left 0%-- oh, what I need to do is-- 663 00:29:49,060 --> 00:29:50,810 based on the way that CSS lines things up, 664 00:29:50,810 --> 00:29:53,900 I need to say that the heading has a relative positioning, meaning 665 00:29:53,900 --> 00:29:57,950 it can change relative to the rest of the page. 666 00:29:57,950 --> 00:29:59,460 And I think this should work. 667 00:29:59,460 --> 00:29:59,960 OK. 668 00:29:59,960 --> 00:30:01,130 Great. 669 00:30:01,130 --> 00:30:05,697 So it started at the left hand side, ended 50% of the way across the window. 670 00:30:05,697 --> 00:30:06,530 Show you that again. 671 00:30:06,530 --> 00:30:09,840 Starts on the left, moves 50% across the way. 672 00:30:09,840 --> 00:30:10,340 Questions. 673 00:30:10,340 --> 00:30:10,490 Yeah. 674 00:30:10,490 --> 00:30:12,100 AUDIENCE: Do you have like a middle step though? 675 00:30:12,100 --> 00:30:12,440 BRIAN YU: Yeah. 676 00:30:12,440 --> 00:30:13,481 I can give a middle step. 677 00:30:13,481 --> 00:30:14,420 Absolutely. 678 00:30:14,420 --> 00:30:16,580 Instead of from and to, I might say, when 679 00:30:16,580 --> 00:30:20,960 you're 0% of the way done with the animation be 0% from the left, 680 00:30:20,960 --> 00:30:25,130 when I'm 50% of the way through the animation be 50% from the left, 681 00:30:25,130 --> 00:30:28,410 and when you're 100% of the way through done with the animation, 682 00:30:28,410 --> 00:30:29,984 let's go back to 0%. 683 00:30:29,984 --> 00:30:31,400 So what's this going to look like? 684 00:30:31,400 --> 00:30:33,930 685 00:30:33,930 --> 00:30:34,431 Yeah. 686 00:30:34,431 --> 00:30:34,930 OK. 687 00:30:34,930 --> 00:30:36,660 Someone's-- people are making the motion. 688 00:30:36,660 --> 00:30:37,480 We'll show it. 689 00:30:37,480 --> 00:30:40,850 Starts to the left, goes to the right, goes back to the left. 690 00:30:40,850 --> 00:30:41,870 Can refresh that. 691 00:30:41,870 --> 00:30:45,000 Goes to the right, goes back to the left. 692 00:30:45,000 --> 00:30:50,420 If I want it to happen multiple times there's animation iteration count. 693 00:30:50,420 --> 00:30:53,397 I can say, animation iteration count two, for example. 694 00:30:53,397 --> 00:30:55,730 And now I refresh the page, it goes there, it goes back, 695 00:30:55,730 --> 00:30:57,290 and then it happens again. 696 00:30:57,290 --> 00:30:58,649 Happens twice. 697 00:30:58,649 --> 00:31:01,690 You can even say animation iteration-- you guys are having fun with this. 698 00:31:01,690 --> 00:31:05,420 So we'll change it to infinite. 699 00:31:05,420 --> 00:31:08,000 And now you know you can just let it go and it will just 700 00:31:08,000 --> 00:31:09,710 go back and forth forever. 701 00:31:09,710 --> 00:31:11,520 So we've got these CSS animations running. 702 00:31:11,520 --> 00:31:12,020 Yeah. 703 00:31:12,020 --> 00:31:13,346 AUDIENCE: Why is not jumping? 704 00:31:13,346 --> 00:31:15,806 Because you're not telling it like the why. 705 00:31:15,806 --> 00:31:18,266 You're just specifying the beginning and the end, 706 00:31:18,266 --> 00:31:20,726 so why would it just not start here and end there. 707 00:31:20,726 --> 00:31:22,694 [INAUDIBLE] colors. 708 00:31:22,694 --> 00:31:25,745 [INAUDIBLE] 709 00:31:25,745 --> 00:31:26,370 BRIAN YU: Yeah. 710 00:31:26,370 --> 00:31:26,953 Good question. 711 00:31:26,953 --> 00:31:28,110 So why is it not jumping? 712 00:31:28,110 --> 00:31:31,410 Why is it smoothly sliding from one side to another when all I'm saying 713 00:31:31,410 --> 00:31:35,250 is, at 0% do this, at 50% do that, at 100% do that? 714 00:31:35,250 --> 00:31:36,960 This is what CSS animation is all about. 715 00:31:36,960 --> 00:31:40,129 You define the key frames, the key points in the animation where 716 00:31:40,129 --> 00:31:42,420 you want it to be doing something, and then the browser 717 00:31:42,420 --> 00:31:45,810 fills in the rest of it, figuring out what the intermediate positions need 718 00:31:45,810 --> 00:31:49,230 to be in order to get from the first key frame to the next key frame. 719 00:31:49,230 --> 00:31:53,570 You can certainly do this with color if you wanted to change this to-- 720 00:31:53,570 --> 00:31:58,410 we'll change this to 100% left, 50% will go back to from and to, 721 00:31:58,410 --> 00:32:00,240 though you don't necessarily need to. 722 00:32:00,240 --> 00:32:05,270 I could say, OK, start with a color of red and go to-- 723 00:32:05,270 --> 00:32:06,720 I should add semicolons here. 724 00:32:06,720 --> 00:32:10,140 And go to a color of blue. 725 00:32:10,140 --> 00:32:13,270 And let me get rid of the iteration count. 726 00:32:13,270 --> 00:32:15,670 We'll just do it once. 727 00:32:15,670 --> 00:32:19,870 Now, if I refresh the page it goes from red to blue. 728 00:32:19,870 --> 00:32:22,790 From red to blue. 729 00:32:22,790 --> 00:32:23,894 Yeah. 730 00:32:23,894 --> 00:32:25,742 AUDIENCE: [INAUDIBLE] function. 731 00:32:25,742 --> 00:32:27,590 You can change linear versus exponential. 732 00:32:27,590 --> 00:32:28,173 BRIAN YU: Yes. 733 00:32:28,173 --> 00:32:29,290 You can change-- 734 00:32:29,290 --> 00:32:32,100 You can start to get fancier about how you go about doing that. 735 00:32:32,100 --> 00:32:33,266 AUDIENCE: One more question. 736 00:32:33,266 --> 00:32:36,990 Which is faster, CSS or jQuery animations? 737 00:32:36,990 --> 00:32:37,990 BRIAN YU: Good question. 738 00:32:37,990 --> 00:32:41,160 Which is faster, CSS or jQuery animations? 739 00:32:41,160 --> 00:32:43,900 jQuery is probably going to be slower, though I'm not actually 740 00:32:43,900 --> 00:32:45,700 100% sure about that. 741 00:32:45,700 --> 00:32:46,375 Yeah. 742 00:32:46,375 --> 00:32:50,335 AUDIENCE: How would you-- if you were to do-- say you wanted to [INAUDIBLE] 743 00:32:50,335 --> 00:32:51,820 and then do the color. 744 00:32:51,820 --> 00:32:56,522 Would the formatting be different than if you wanted 745 00:32:56,522 --> 00:32:59,247 to [INAUDIBLE] and to do [INAUDIBLE]? 746 00:32:59,247 --> 00:32:59,830 BRIAN YU: Yes. 747 00:32:59,830 --> 00:33:03,000 So what I could do if I wanted to do like, first move and then change 748 00:33:03,000 --> 00:33:06,930 the color, is I'd say, OK, at 0% I want it to be on the left hand side 749 00:33:06,930 --> 00:33:12,300 and I want the color to be red, at 50% I want it to be left 50% 750 00:33:12,300 --> 00:33:17,220 and I want the color to still be red, and at 100% 751 00:33:17,220 --> 00:33:19,860 I want the color to be blue, for example. 752 00:33:19,860 --> 00:33:23,610 Where now it will move and then it'll change color. 753 00:33:23,610 --> 00:33:28,020 So you can define the intermediate key frames however you like. 754 00:33:28,020 --> 00:33:30,313 Questions about any of that. 755 00:33:30,313 --> 00:33:32,080 AUDIENCE: Can you show the code again? 756 00:33:32,080 --> 00:33:32,340 BRIAN YU: What? 757 00:33:32,340 --> 00:33:33,000 The code? 758 00:33:33,000 --> 00:33:33,500 Yeah. 759 00:33:33,500 --> 00:33:36,194 760 00:33:36,194 --> 00:33:37,360 So those are the key frames. 761 00:33:37,360 --> 00:33:42,210 762 00:33:42,210 --> 00:33:46,590 AUDIENCE: What happens if you do 99% and then [INAUDIBLE]?? 763 00:33:46,590 --> 00:33:48,580 BRIAN YU: 99%? 764 00:33:48,580 --> 00:33:51,879 Why do you want it 99%? 765 00:33:51,879 --> 00:33:52,420 AUDIENCE: No. 766 00:33:52,420 --> 00:33:53,842 I mean, [INAUDIBLE]. 767 00:33:53,842 --> 00:33:57,532 768 00:33:57,532 --> 00:33:58,240 BRIAN YU: Oh, no. 769 00:33:58,240 --> 00:33:58,865 That shouldn't. 770 00:33:58,865 --> 00:34:01,406 You can experiment with this all you'd like if you'd like to. 771 00:34:01,406 --> 00:34:03,250 You just need to create an HTML page and you 772 00:34:03,250 --> 00:34:04,940 can do whatever key frames you'd like to play around with. 773 00:34:04,940 --> 00:34:05,510 Yeah. 774 00:34:05,510 --> 00:34:08,319 AUDIENCE: [INAUDIBLE] left 50%. 775 00:34:08,319 --> 00:34:08,860 BRIAN YU: No. 776 00:34:08,860 --> 00:34:11,080 Some of this might be redundant that you can take out, for instance. 777 00:34:11,080 --> 00:34:11,579 Yeah. 778 00:34:11,579 --> 00:34:13,780 AUDIENCE: What is the meaning of the key frames? 779 00:34:13,780 --> 00:34:15,988 BRIAN YU: The key frames are just getting at the idea 780 00:34:15,988 --> 00:34:18,520 that rather than specifying what the state of the style 781 00:34:18,520 --> 00:34:21,940 should be at every single point at every single frame of the animation, 782 00:34:21,940 --> 00:34:24,760 I'm just specifying it at a couple of key frames 783 00:34:24,760 --> 00:34:27,070 and then the browser is going to fill in the rest 784 00:34:27,070 --> 00:34:30,489 to figure out how it should transition from one thing to the next. 785 00:34:30,489 --> 00:34:31,117 Yeah. 786 00:34:31,117 --> 00:34:33,417 AUDIENCE: So if you wanted it to basically make 787 00:34:33,417 --> 00:34:36,375 it appear and disappear and appear [INAUDIBLE] in the middle, basically 788 00:34:36,375 --> 00:34:37,920 no transition in between. 789 00:34:37,920 --> 00:34:41,936 Would you basically show it, hide it, show it on the middle, 790 00:34:41,936 --> 00:34:42,697 and then hide it? 791 00:34:42,697 --> 00:34:44,530 BRIAN YU: If you didn't want the transition, 792 00:34:44,530 --> 00:34:46,320 you probably don't need CSS animation. 793 00:34:46,320 --> 00:34:49,116 You could probably just use JavaScript to say, wait five seconds 794 00:34:49,116 --> 00:34:50,199 and then change the color. 795 00:34:50,199 --> 00:34:52,659 And then it would just change color, for example. 796 00:34:52,659 --> 00:34:53,247 Yeah. 797 00:34:53,247 --> 00:34:56,257 AUDIENCE: Is the CSS [INAUDIBLE]. 798 00:34:56,257 --> 00:34:57,195 BRIAN YU: Yeah. 799 00:34:57,195 --> 00:35:02,620 AUDIENCE: Is that referencing-- how does it know that we have an animation? 800 00:35:02,620 --> 00:35:03,730 [INAUDIBLE] 801 00:35:03,730 --> 00:35:05,920 BRIAN YU: When you say animation name Grow, 802 00:35:05,920 --> 00:35:09,040 it's referencing this grow, just some animation 803 00:35:09,040 --> 00:35:11,290 that I've defined that is called Grow, for example. 804 00:35:11,290 --> 00:35:13,827 AUDIENCE: It just knows that Grow is an animation. 805 00:35:13,827 --> 00:35:14,410 BRIAN YU: Yes. 806 00:35:14,410 --> 00:35:17,210 The at key frames basically tells it what it is. 807 00:35:17,210 --> 00:35:17,920 Yeah. 808 00:35:17,920 --> 00:35:19,390 Good question. 809 00:35:19,390 --> 00:35:20,660 So we can actually use this. 810 00:35:20,660 --> 00:35:22,780 This is not just all for just like fun and games. 811 00:35:22,780 --> 00:35:24,530 We can see what we can do with the heading 812 00:35:24,530 --> 00:35:27,020 and get it to slide back and forth and change color. 813 00:35:27,020 --> 00:35:29,750 We can go in to-- 814 00:35:29,750 --> 00:35:31,455 let's look at post to now. 815 00:35:31,455 --> 00:35:34,330 And the only difference I've made in post two as opposed to post one, 816 00:35:34,330 --> 00:35:37,960 remember this was our auto-infinite scroll for posts-- 817 00:35:37,960 --> 00:35:43,690 if I go into index.HTML, I've added this Hide key frame 818 00:35:43,690 --> 00:35:47,044 that we can use to basically hide a post if we don't want it to be there. 819 00:35:47,044 --> 00:35:49,460 So remember before when we were hitting hide on each post, 820 00:35:49,460 --> 00:35:51,168 it would just sort of go away immediately 821 00:35:51,168 --> 00:35:53,560 and the next one would immediately be in its place. 822 00:35:53,560 --> 00:35:55,900 We can define a key frame called hide that goes 823 00:35:55,900 --> 00:35:58,780 from an opacity of one, meaning totally visible, 824 00:35:58,780 --> 00:36:02,140 to an opacity of zero, which means totally invisible, 825 00:36:02,140 --> 00:36:07,120 and we can give any post an animation name of Hide, 826 00:36:07,120 --> 00:36:11,270 and we can use JavaScript to trigger when we want that animation to begin. 827 00:36:11,270 --> 00:36:14,020 And so if I say flask run here. 828 00:36:14,020 --> 00:36:15,380 Open up flask. 829 00:36:15,380 --> 00:36:15,880 All right. 830 00:36:15,880 --> 00:36:16,380 Great. 831 00:36:16,380 --> 00:36:17,830 Here is our auto completing post. 832 00:36:17,830 --> 00:36:20,980 And now if I wanted to hide post three I click Hide. 833 00:36:20,980 --> 00:36:23,210 And then over the course of some time it fades out 834 00:36:23,210 --> 00:36:26,140 and then the next post jumps in to fill its place. 835 00:36:26,140 --> 00:36:27,040 We hide. 836 00:36:27,040 --> 00:36:28,240 It fades out. 837 00:36:28,240 --> 00:36:29,380 And the next post jumps in. 838 00:36:29,380 --> 00:36:31,480 And this user interface still isn't amazing. 839 00:36:31,480 --> 00:36:33,820 What would we like to change? 840 00:36:33,820 --> 00:36:34,320 Yeah. 841 00:36:34,320 --> 00:36:36,990 It would be nice if it would slide up as opposed to just jumping up. 842 00:36:36,990 --> 00:36:38,640 And so if we take a look at post three. 843 00:36:38,640 --> 00:36:43,520 844 00:36:43,520 --> 00:36:45,940 And if we look at index.HTML. 845 00:36:45,940 --> 00:36:48,700 These key frames are a little fancier, but the idea here 846 00:36:48,700 --> 00:36:51,610 is at 0% we'll start at full opacity. 847 00:36:51,610 --> 00:36:56,140 When we're 75% of the way done with the animation the opacity will be zero, 848 00:36:56,140 --> 00:36:57,730 will fade out completely. 849 00:36:57,730 --> 00:37:01,390 And then will go from a height of 100% to-- when 850 00:37:01,390 --> 00:37:03,974 we're totally done with the animation the height will be zero. 851 00:37:03,974 --> 00:37:06,181 And when we go from a large height to a small height, 852 00:37:06,181 --> 00:37:09,310 when we fill in that transition, the result will be the height will shrink. 853 00:37:09,310 --> 00:37:13,646 And so if we say flask run now, open up this. 854 00:37:13,646 --> 00:37:14,770 We've got all of our posts. 855 00:37:14,770 --> 00:37:17,530 And if I want to hide post number three, I click Hide. 856 00:37:17,530 --> 00:37:18,530 It fades out. 857 00:37:18,530 --> 00:37:22,580 And then the next one slides in as the first size shrinks. 858 00:37:22,580 --> 00:37:24,100 Show you that again. 859 00:37:24,100 --> 00:37:26,410 Fades out and then it shrinks. 860 00:37:26,410 --> 00:37:30,620 So using CSS animation we're able to create these interactive, nicer 861 00:37:30,620 --> 00:37:33,040 and more aesthetically pleasing user interfaces just 862 00:37:33,040 --> 00:37:35,260 by taking advantage of these key frames and deciding 863 00:37:35,260 --> 00:37:37,510 when things are going to start and stop and how things 864 00:37:37,510 --> 00:37:41,740 transition from one thing to the other. 865 00:37:41,740 --> 00:37:43,030 Questions. 866 00:37:43,030 --> 00:37:45,774 What questions do you have? 867 00:37:45,774 --> 00:37:46,730 Yeah. 868 00:37:46,730 --> 00:37:48,880 AUDIENCE: Are those positions relative? 869 00:37:48,880 --> 00:37:51,615 Or are they using [INAUDIBLE]? 870 00:37:51,615 --> 00:37:53,240 BRIAN YU: This is relative positioning. 871 00:37:53,240 --> 00:37:56,020 Yeah. 872 00:37:56,020 --> 00:37:57,200 OK. 873 00:37:57,200 --> 00:37:58,430 So that's CSS animation. 874 00:37:58,430 --> 00:37:58,620 Yeah. 875 00:37:58,620 --> 00:37:59,120 Question. 876 00:37:59,120 --> 00:38:02,750 AUDIENCE: What if you wanted to give a post multiple animations? 877 00:38:02,750 --> 00:38:06,020 BRIAN YU: If you wanted to give a post multiple animations, you can do that. 878 00:38:06,020 --> 00:38:07,850 It'll be easier with some more JavaScript. 879 00:38:07,850 --> 00:38:11,300 And we're about to go to JavaScript based animations in just a second. 880 00:38:11,300 --> 00:38:12,900 Yeah. 881 00:38:12,900 --> 00:38:16,720 AUDIENCE: So we just set the size of where the document [INAUDIBLE] 882 00:38:16,720 --> 00:38:28,740 zero [INAUDIBLE] run the animation [INAUDIBLE] will that be [INAUDIBLE] 883 00:38:28,740 --> 00:38:29,670 zero? 884 00:38:29,670 --> 00:38:31,170 Or [INAUDIBLE] actually [INAUDIBLE]? 885 00:38:31,170 --> 00:38:32,370 BRIAN YU: I believe this code will actually 886 00:38:32,370 --> 00:38:34,328 remove the element after the animation is over, 887 00:38:34,328 --> 00:38:37,730 so you wouldn't have to worry about that. 888 00:38:37,730 --> 00:38:38,510 OK. 889 00:38:38,510 --> 00:38:40,940 Let's try something a little bit different. 890 00:38:40,940 --> 00:38:42,176 Yeah. 891 00:38:42,176 --> 00:38:46,658 AUDIENCE: So this is just all the visual stuff, right? 892 00:38:46,658 --> 00:38:52,640 The existence of the animation [INAUDIBLE] great accessibility? 893 00:38:52,640 --> 00:38:55,750 BRIAN YU: So good question about accessibility. 894 00:38:55,750 --> 00:38:57,400 There are certain things that-- 895 00:38:57,400 --> 00:39:00,130 element-- attributes that you should be adding to HTML 896 00:39:00,130 --> 00:39:03,460 elements for accessibility reasons. 897 00:39:03,460 --> 00:39:05,516 In particular on images and such, but in general, 898 00:39:05,516 --> 00:39:07,390 so long as you're following those guidelines, 899 00:39:07,390 --> 00:39:09,098 you can still have animations on the page 900 00:39:09,098 --> 00:39:11,020 and accessibility should still be OK. 901 00:39:11,020 --> 00:39:15,510 We can chat about specific use cases if you have them in mind too. 902 00:39:15,510 --> 00:39:17,250 All right. 903 00:39:17,250 --> 00:39:23,670 Let's go ahead and open up index.HTML. 904 00:39:23,670 --> 00:39:26,610 And let me get rid of the style code for now. 905 00:39:26,610 --> 00:39:29,470 906 00:39:29,470 --> 00:39:30,190 All right. 907 00:39:30,190 --> 00:39:33,100 What I'm going to do now is inside the body of the page 908 00:39:33,100 --> 00:39:36,130 introduce SVGs, or scalable vector graphics. 909 00:39:36,130 --> 00:39:38,740 And vector graphics you can think of as just graphics 910 00:39:38,740 --> 00:39:41,470 that you can, at least in the context of web pages, are 911 00:39:41,470 --> 00:39:43,480 shapes that you can add to your page in order 912 00:39:43,480 --> 00:39:46,570 to create for some more interactive user interfaces, 913 00:39:46,570 --> 00:39:50,840 allow for some user experiences that we weren't able to have before. 914 00:39:50,840 --> 00:39:52,160 So here I'm going to say-- 915 00:39:52,160 --> 00:39:55,200 SVG is going to be an element-- 916 00:39:55,200 --> 00:40:01,450 its style is going to have a width of 100% and a height of 800 pixels. 917 00:40:01,450 --> 00:40:04,270 In other words, what I'm doing here is creating 918 00:40:04,270 --> 00:40:08,740 an SVG canvas, just an 800 pixel tall canvas on which 919 00:40:08,740 --> 00:40:12,320 I can draw shapes, at least for now. 920 00:40:12,320 --> 00:40:16,150 So inside of this canvas I'm going to say, all right, let's create a circle. 921 00:40:16,150 --> 00:40:18,670 And a circle has some attributes. 922 00:40:18,670 --> 00:40:20,490 It has a center x-coordinate. 923 00:40:20,490 --> 00:40:21,490 So where is it centered? 924 00:40:21,490 --> 00:40:23,830 We'll say center x-coordinate is going to be 200. 925 00:40:23,830 --> 00:40:25,240 It has a center y-coordinate. 926 00:40:25,240 --> 00:40:26,680 We'll say also 200. 927 00:40:26,680 --> 00:40:27,700 It has a radius. 928 00:40:27,700 --> 00:40:29,972 We'll say 50 pixels, at least for now. 929 00:40:29,972 --> 00:40:31,180 And we can add styling to it. 930 00:40:31,180 --> 00:40:31,680 Right? 931 00:40:31,680 --> 00:40:35,710 I can say, all right, the fill color of this circle should be blue. 932 00:40:35,710 --> 00:40:38,379 933 00:40:38,379 --> 00:40:41,170 So what I've done here is I've created an SVG canvas, a place where 934 00:40:41,170 --> 00:40:44,840 I can draw shapes, it's 800 pixels tall, it fills up the full width of the page. 935 00:40:44,840 --> 00:40:49,330 And I'm going to draw a circle at location 200, 200 with a radius of 50 936 00:40:49,330 --> 00:40:51,090 and it should be blue. 937 00:40:51,090 --> 00:40:53,495 So I open up index.HTML. 938 00:40:53,495 --> 00:40:58,060 And OK, I have a page and just a blue circle, as you might expect. 939 00:40:58,060 --> 00:41:00,900 So this is a vector graphic. 940 00:41:00,900 --> 00:41:04,562 Questions about that before we dive into more. 941 00:41:04,562 --> 00:41:07,270 You could certainly do all these vector graphics entirely by hand 942 00:41:07,270 --> 00:41:09,220 just by specifying where you want things, 943 00:41:09,220 --> 00:41:11,150 but there are libraries that are able to help with this. 944 00:41:11,150 --> 00:41:12,760 A library we're going to use at least for today 945 00:41:12,760 --> 00:41:15,070 is called D3, something you may be familiar with. 946 00:41:15,070 --> 00:41:17,500 It's actually quite good, especially for analyzing data 947 00:41:17,500 --> 00:41:20,140 and for data visualization, so it's quite powerful. 948 00:41:20,140 --> 00:41:22,810 We're not even going to use most of those capabilities today. 949 00:41:22,810 --> 00:41:26,132 We're just going to use it for interacting with vector graphics 950 00:41:26,132 --> 00:41:28,090 in order to draw things on the screen, but know 951 00:41:28,090 --> 00:41:30,256 that it's far more powerful than what we're actually 952 00:41:30,256 --> 00:41:32,530 going to get a chance to look at today. 953 00:41:32,530 --> 00:41:37,090 And so we'll go ahead and go in to circleone.HTML, 954 00:41:37,090 --> 00:41:39,790 if you're following along with the source code examples. 955 00:41:39,790 --> 00:41:45,290 And in circleone.HTML I first included a script, not a script that I've written, 956 00:41:45,290 --> 00:41:47,054 but I'm including D3's JavaScript. 957 00:41:47,054 --> 00:41:49,720 This is just a JavaScript library that's going to make it easier 958 00:41:49,720 --> 00:41:52,000 for us to draw these shapes. 959 00:41:52,000 --> 00:41:56,950 And inside the body of our application here's an SVG canvas. 960 00:41:56,950 --> 00:42:02,350 It has an ID called SVG and it's going to take up the full width of the page. 961 00:42:02,350 --> 00:42:04,104 It's going to be 800 pixels tall. 962 00:42:04,104 --> 00:42:06,520 And then here is the JavaScript code that makes this work. 963 00:42:06,520 --> 00:42:10,080 This is the JavaScript equivalent of what it is that we just did. 964 00:42:10,080 --> 00:42:14,050 And we're first using a function called D3.select, 965 00:42:14,050 --> 00:42:17,890 which is just going to use D3 to select the SVG container, 966 00:42:17,890 --> 00:42:20,396 storing it in a variable called SVG, and then we're 967 00:42:20,396 --> 00:42:22,270 going to programmatically add a circle to it. 968 00:42:22,270 --> 00:42:24,820 Instead of just writing it hard-coded into the HTML, 969 00:42:24,820 --> 00:42:27,490 we're going to say SVG.appendcircle. 970 00:42:27,490 --> 00:42:29,320 And here we see that chaining idea again. 971 00:42:29,320 --> 00:42:31,750 This chaining of function after function after function. 972 00:42:31,750 --> 00:42:35,680 These dots are all just chained functions being applied to each other. 973 00:42:35,680 --> 00:42:38,890 So we're saying take that circle and give it this attribute, 974 00:42:38,890 --> 00:42:40,960 give it the center x attribute of 200. 975 00:42:40,960 --> 00:42:42,920 Put it at x location 200. 976 00:42:42,920 --> 00:42:44,860 Take the y attribute, put it at 200. 977 00:42:44,860 --> 00:42:46,750 Give it a radius of 90 pixels. 978 00:42:46,750 --> 00:42:49,090 Fill it with the color green, for example. 979 00:42:49,090 --> 00:42:50,500 And so you can add CSS. 980 00:42:50,500 --> 00:42:53,800 Instead of using attribute, using .style to add CSS properties, 981 00:42:53,800 --> 00:42:55,600 like the fill color, for example. 982 00:42:55,600 --> 00:43:00,680 And the result of this is if I open up circleone.HTML, 983 00:43:00,680 --> 00:43:02,172 I get a big green circle. 984 00:43:02,172 --> 00:43:03,880 Basically the same as before, but now I'm 985 00:43:03,880 --> 00:43:08,260 using this D3 library that's going to make things a little bit easier. 986 00:43:08,260 --> 00:43:11,090 Questions about anything so far before I go on? 987 00:43:11,090 --> 00:43:11,590 Yeah? 988 00:43:11,590 --> 00:43:16,300 AUDIENCE: [INAUDIBLE] circle is supposed to be 100% [INAUDIBLE] 989 00:43:16,300 --> 00:43:19,870 BRIAN YU: The SVG itself has a width of 100. 990 00:43:19,870 --> 00:43:22,480 So the canvas on which I'm drawing takes up the entire width, 991 00:43:22,480 --> 00:43:25,900 but the canvas is white, so it's just in the background of the page. 992 00:43:25,900 --> 00:43:28,810 The circle itself only has a radius of 90. 993 00:43:28,810 --> 00:43:32,140 And so it's going to have a radius of 90 pixels, is what I specified there. 994 00:43:32,140 --> 00:43:34,680 995 00:43:34,680 --> 00:43:35,180 Yeah. 996 00:43:35,180 --> 00:43:36,096 AUDIENCE: [INAUDIBLE]. 997 00:43:36,096 --> 00:43:38,457 998 00:43:38,457 --> 00:43:39,040 BRIAN YU: Yes. 999 00:43:39,040 --> 00:43:41,956 You can do combinations of any of the things that we're talking about. 1000 00:43:41,956 --> 00:43:44,430 1001 00:43:44,430 --> 00:43:44,930 OK. 1002 00:43:44,930 --> 00:43:46,305 Just to show you one other shape. 1003 00:43:46,305 --> 00:43:48,530 I'll show you rect.HTML for a rectangle. 1004 00:43:48,530 --> 00:43:49,587 It's very similar. 1005 00:43:49,587 --> 00:43:52,670 Instead of specifying CX and CY for the center x-coordinate and the center 1006 00:43:52,670 --> 00:43:55,970 y-coordinate and an R for radius, I specify an x-coordinate, 1007 00:43:55,970 --> 00:43:59,360 a y-coordinate, a width, and a height, and that lets 1008 00:43:59,360 --> 00:44:01,870 you draw a rectangle wherever you want. 1009 00:44:01,870 --> 00:44:03,470 So open up rect.HTML. 1010 00:44:03,470 --> 00:44:08,210 And OK, we get a big blue rectangle. 1011 00:44:08,210 --> 00:44:10,420 Questions. 1012 00:44:10,420 --> 00:44:10,920 All right. 1013 00:44:10,920 --> 00:44:12,960 So so far these shapes don't move, so let's go ahead 1014 00:44:12,960 --> 00:44:14,070 and add some animation to them. 1015 00:44:14,070 --> 00:44:15,970 Much as we did before with CSS, but now using 1016 00:44:15,970 --> 00:44:19,770 D3 to be able to create transitions as things move from one state 1017 00:44:19,770 --> 00:44:21,290 to another state. 1018 00:44:21,290 --> 00:44:25,350 So we'll open up circletwo.HTML. 1019 00:44:25,350 --> 00:44:28,560 And then circletwo.HTML, it starts basically the same way. 1020 00:44:28,560 --> 00:44:32,850 I create a circle located at 200, 200 with a radius of 50. 1021 00:44:32,850 --> 00:44:35,640 And we're going to fill it in with the color blue, 1022 00:44:35,640 --> 00:44:37,890 but then I'm going to apply a transition to it. 1023 00:44:37,890 --> 00:44:39,424 I'm going to say c.transition. 1024 00:44:39,424 --> 00:44:40,590 C is the name of the circle. 1025 00:44:40,590 --> 00:44:43,260 I just saved it inside of a variable. 1026 00:44:43,260 --> 00:44:48,770 And this transition is going to have a duration of 1,000 milliseconds, 1027 00:44:48,770 --> 00:44:49,896 or one second. 1028 00:44:49,896 --> 00:44:51,020 And what's going to happen? 1029 00:44:51,020 --> 00:44:54,440 I'm changing the x and the y attributes of the circle, 1030 00:44:54,440 --> 00:44:58,970 moving it from 200, 200 to 500, 500. 1031 00:44:58,970 --> 00:45:00,380 And I'm also changing its style. 1032 00:45:00,380 --> 00:45:03,120 I'm changing its style from blue to red. 1033 00:45:03,120 --> 00:45:06,440 And much in the same way that CSS allowed me to define key frames 1034 00:45:06,440 --> 00:45:09,654 and then CSS took care of the rest of figuring out how to transition things 1035 00:45:09,654 --> 00:45:10,820 from one state to the other. 1036 00:45:10,820 --> 00:45:13,062 D3 is going to do the same thing with the idea being 1037 00:45:13,062 --> 00:45:15,020 that we're going to apply a transition and it's 1038 00:45:15,020 --> 00:45:17,840 going to smoothly move from one position to another position, 1039 00:45:17,840 --> 00:45:19,940 from one color to another color. 1040 00:45:19,940 --> 00:45:23,120 Where by now I can open up circletwo.HTML. 1041 00:45:23,120 --> 00:45:26,765 And OK, the blue circle moves and it also changes color. 1042 00:45:26,765 --> 00:45:28,265 Refresh it again, so you can see it. 1043 00:45:28,265 --> 00:45:32,100 It moves and it changes color. 1044 00:45:32,100 --> 00:45:33,450 Questions about that. 1045 00:45:33,450 --> 00:45:34,922 Show you the code again. 1046 00:45:34,922 --> 00:45:37,880 This is in circletwo.HTML, if you're following along with the examples. 1047 00:45:37,880 --> 00:45:41,950 1048 00:45:41,950 --> 00:45:43,800 Do one more simple example. 1049 00:45:43,800 --> 00:45:45,320 We'll open up circlethree.HTML. 1050 00:45:45,320 --> 00:45:48,340 1051 00:45:48,340 --> 00:45:53,620 And now we're going to add a transition. 1052 00:45:53,620 --> 00:45:56,607 And this transition is going to change the x position. 1053 00:45:56,607 --> 00:45:58,690 So the duration is going to be 1,000 milliseconds. 1054 00:45:58,690 --> 00:46:00,398 We're also going to add a delay, which is 1055 00:46:00,398 --> 00:46:03,357 like how long it's going to take before the transition actually starts. 1056 00:46:03,357 --> 00:46:06,106 But you can also add event listeners to this, much in the same way 1057 00:46:06,106 --> 00:46:08,320 that you can add event listeners to other elements. 1058 00:46:08,320 --> 00:46:12,350 So I can say, take this circle, and on click, in other words, 1059 00:46:12,350 --> 00:46:17,050 when this circle is clicked on, then go ahead and run this function. 1060 00:46:17,050 --> 00:46:21,160 D3.selectthis is just a fancy way of saying, 1061 00:46:21,160 --> 00:46:24,340 get this object, this circle in particular, 1062 00:46:24,340 --> 00:46:27,970 and apply another transition to it that lasts three seconds that 1063 00:46:27,970 --> 00:46:29,937 changes its style to red. 1064 00:46:29,937 --> 00:46:32,020 So a lot of this, when you see this chaining, just 1065 00:46:32,020 --> 00:46:34,630 think of it as do this thing, and then do this thing, and then do this thing, 1066 00:46:34,630 --> 00:46:36,796 or think of it as chaining these all things together 1067 00:46:36,796 --> 00:46:38,050 into one big transition. 1068 00:46:38,050 --> 00:46:40,300 We're doing a transition on the circle that 1069 00:46:40,300 --> 00:46:42,397 is going to set the x attribute to 500. 1070 00:46:42,397 --> 00:46:44,230 And then when the circle is clicked on we're 1071 00:46:44,230 --> 00:46:46,750 going to apply another transition that's going to change 1072 00:46:46,750 --> 00:46:50,540 the fill color of the circle to be red. 1073 00:46:50,540 --> 00:46:53,520 So we open up circlethree.HTML. 1074 00:46:53,520 --> 00:46:54,650 We have a blue circle. 1075 00:46:54,650 --> 00:46:55,910 After one second it moves. 1076 00:46:55,910 --> 00:46:57,150 I didn't do anything. 1077 00:46:57,150 --> 00:46:59,390 But now if I go over it and I click, then 1078 00:46:59,390 --> 00:47:02,330 over the course of a couple of seconds the circle changes color. 1079 00:47:02,330 --> 00:47:05,375 Able to do animations in response to particular events. 1080 00:47:05,375 --> 00:47:07,900 1081 00:47:07,900 --> 00:47:10,500 What questions do you have? 1082 00:47:10,500 --> 00:47:12,360 Yeah. 1083 00:47:12,360 --> 00:47:16,510 AUDIENCE: On the code [INAUDIBLE] D3.selectthis, 1084 00:47:16,510 --> 00:47:17,896 why did you have to do that? 1085 00:47:17,896 --> 00:47:20,720 Couldn't you just do c.transition? 1086 00:47:20,720 --> 00:47:21,720 BRIAN YU: Good question. 1087 00:47:21,720 --> 00:47:24,554 Why did I need D3.selectthis instead of just c. 1088 00:47:24,554 --> 00:47:26,970 I probably could have done just c in this case-- actually, 1089 00:47:26,970 --> 00:47:29,780 let's try just to make sure. 1090 00:47:29,780 --> 00:47:32,315 Here and then click. 1091 00:47:32,315 --> 00:47:33,940 And then, yeah, that'll work just fine. 1092 00:47:33,940 --> 00:47:36,190 So in this case, you can get away with that. 1093 00:47:36,190 --> 00:47:38,890 In some more complex examples when they're not necessarily 1094 00:47:38,890 --> 00:47:40,780 referring to the same variable name, maybe 1095 00:47:40,780 --> 00:47:43,360 when applying animations to a list of potential things, 1096 00:47:43,360 --> 00:47:45,370 then D3.selectthis is helpful for getting 1097 00:47:45,370 --> 00:47:47,089 the thing that triggered the event. 1098 00:47:47,089 --> 00:47:48,880 And so I'm showing it to you for that sake, 1099 00:47:48,880 --> 00:47:50,920 so that you know how to use it in future cases. 1100 00:47:50,920 --> 00:47:55,735 But yeah, in this case, c.transition would've worked just fine. 1101 00:47:55,735 --> 00:47:57,214 Yeah. 1102 00:47:57,214 --> 00:48:03,623 AUDIENCE: So you [? divide ?] [INAUDIBLE] demo and then [INAUDIBLE] 1103 00:48:03,623 --> 00:48:07,987 so are you [INAUDIBLE]? 1104 00:48:07,987 --> 00:48:08,570 BRIAN YU: Yes. 1105 00:48:08,570 --> 00:48:12,779 We are constrained to whatever width and height the SVG canvas is. 1106 00:48:12,779 --> 00:48:14,570 And if we try and draw something beyond it, 1107 00:48:14,570 --> 00:48:19,932 we're not going to see it because it's outside the bounds of that container. 1108 00:48:19,932 --> 00:48:23,140 So using all these tools we can actually begin to build some interesting user 1109 00:48:23,140 --> 00:48:23,980 interfaces. 1110 00:48:23,980 --> 00:48:26,890 I'll show you one that I built that I thought was kind of fun. 1111 00:48:26,890 --> 00:48:29,370 It's called stoplight.HTML. 1112 00:48:29,370 --> 00:48:31,990 And it just looks something like this. 1113 00:48:31,990 --> 00:48:35,127 All this is so far is a black rectangle and three gray circles, 1114 00:48:35,127 --> 00:48:37,960 something you could create just by figuring out where the pixels go. 1115 00:48:37,960 --> 00:48:40,970 And when you click on the circles the colors change. 1116 00:48:40,970 --> 00:48:41,470 Right? 1117 00:48:41,470 --> 00:48:44,500 You click on the different circles and the colors change 1118 00:48:44,500 --> 00:48:46,520 much as a stoplight would, for example. 1119 00:48:46,520 --> 00:48:47,020 Yeah. 1120 00:48:47,020 --> 00:48:47,520 Question. 1121 00:48:47,520 --> 00:48:48,858 AUDIENCE: [INAUDIBLE]. 1122 00:48:48,858 --> 00:48:51,834 1123 00:48:51,834 --> 00:48:55,802 You have a transition where it moves out of the area and then back in. 1124 00:48:55,802 --> 00:48:59,217 Does it look like the circle [? was ?] hiding and then it comes back? 1125 00:48:59,217 --> 00:48:59,800 BRIAN YU: Yes. 1126 00:48:59,800 --> 00:49:02,110 If it's outside and it moves back in, it still exists, 1127 00:49:02,110 --> 00:49:04,750 it's just not in the visible area of the content of the page. 1128 00:49:04,750 --> 00:49:05,380 That's correct. 1129 00:49:05,380 --> 00:49:09,030 So there are interesting things you can do with that if you would like to. 1130 00:49:09,030 --> 00:49:09,530 Yeah. 1131 00:49:09,530 --> 00:49:13,450 AUDIENCE: If you were to shrink the size of your browser window, what 1132 00:49:13,450 --> 00:49:14,930 would happen to your stoplight? 1133 00:49:14,930 --> 00:49:15,930 BRIAN YU: Good question. 1134 00:49:15,930 --> 00:49:18,240 What happens if I shrink the size of the browser window? 1135 00:49:18,240 --> 00:49:20,240 Well, this browser window doesn't happen to go-- 1136 00:49:20,240 --> 00:49:24,810 let's see if I can simulate this on a mobile device. 1137 00:49:24,810 --> 00:49:27,000 Oh, well, this is just shrinking the viewport, 1138 00:49:27,000 --> 00:49:30,146 as we talked about two days ago. 1139 00:49:30,146 --> 00:49:32,770 Long story short, it's not going to work great on this example, 1140 00:49:32,770 --> 00:49:36,070 but you might get a situation where the animation does get cut off. 1141 00:49:36,070 --> 00:49:37,660 And so that might be a situation where if you really 1142 00:49:37,660 --> 00:49:39,409 want to think about mobile responsiveness, 1143 00:49:39,409 --> 00:49:42,757 you want to think about dynamically computing where pixels should be based 1144 00:49:42,757 --> 00:49:45,340 upon the size of the screen, for example, or at least assuming 1145 00:49:45,340 --> 00:49:48,006 that something will at least always be of at least a fixed width 1146 00:49:48,006 --> 00:49:51,160 and then being able to add positioning in that sense. 1147 00:49:51,160 --> 00:49:54,349 1148 00:49:54,349 --> 00:49:54,890 Other things. 1149 00:49:54,890 --> 00:49:56,604 So I'll show you the code for this. 1150 00:49:56,604 --> 00:49:58,520 We won't go into detail in it, but just so you 1151 00:49:58,520 --> 00:50:00,590 can get a chance to see it and feel free to look at it in more detail 1152 00:50:00,590 --> 00:50:01,520 if you'd like. 1153 00:50:01,520 --> 00:50:03,950 All that's happening is we get the canvas, 1154 00:50:03,950 --> 00:50:06,740 we add a rectangle to it, that's the big black rectangle, 1155 00:50:06,740 --> 00:50:08,630 we go ahead and add a red circle to it, that 1156 00:50:08,630 --> 00:50:11,030 at first is going to be styled as just gray, we 1157 00:50:11,030 --> 00:50:15,560 add a yellow circle to it that's also gray, a green circle that's also gray. 1158 00:50:15,560 --> 00:50:19,430 And basically-- and there are certainly better ways to design this. 1159 00:50:19,430 --> 00:50:22,876 When each of the buttons are clicked we take the corresponding color, 1160 00:50:22,876 --> 00:50:25,250 go ahead and fill it in with whatever color it should be, 1161 00:50:25,250 --> 00:50:29,060 and take the other circles and fill them in as gray instead of whatever color 1162 00:50:29,060 --> 00:50:31,320 they were before. 1163 00:50:31,320 --> 00:50:33,420 And so this is all just using the tools that we've 1164 00:50:33,420 --> 00:50:36,948 seen already in order to build some more interesting user interfaces. 1165 00:50:36,948 --> 00:50:39,576 1166 00:50:39,576 --> 00:50:40,860 So OK. 1167 00:50:40,860 --> 00:50:44,850 Let's try and do something a little more interesting now. 1168 00:50:44,850 --> 00:50:45,932 We'll go to the desktop. 1169 00:50:45,932 --> 00:50:48,390 I'm going to-- and this is the part where if you'd like to, 1170 00:50:48,390 --> 00:50:51,270 feel free to try and follow along by writing in the HTML yourself. 1171 00:50:51,270 --> 00:50:54,520 This is going to help lead into what's eventually going to be this afternoon's 1172 00:50:54,520 --> 00:50:55,810 project, if you would like to. 1173 00:50:55,810 --> 00:50:58,010 So go ahead and create a file called draw.HTML. 1174 00:50:58,010 --> 00:51:01,430 1175 00:51:01,430 --> 00:51:08,840 And inside of draw.HTML we're going to start with just the basic HTML page. 1176 00:51:08,840 --> 00:51:12,080 The title is just going to be draw. 1177 00:51:12,080 --> 00:51:14,770 We're going to need to include D3. 1178 00:51:14,770 --> 00:51:18,620 So if you go into any of the other source code examples 1179 00:51:18,620 --> 00:51:23,330 you can just copy the script length for D3. 1180 00:51:23,330 --> 00:51:26,420 And go ahead and copy that into the header of the page. 1181 00:51:26,420 --> 00:51:30,170 Doesn't matter where in the header it is, so long as it's there. 1182 00:51:30,170 --> 00:51:33,680 Inside the body of the page we'll go ahead 1183 00:51:33,680 --> 00:51:39,152 and create an SVG that has an ID of SVG, so that we can refer to it later. 1184 00:51:39,152 --> 00:51:41,180 Its style is going to be width 100%. 1185 00:51:41,180 --> 00:51:44,000 It's going to take up the full width of the window. 1186 00:51:44,000 --> 00:51:46,520 And it's going to have a height of 800 pixels, 1187 00:51:46,520 --> 00:51:49,429 just sort of arbitrarily chosen to most likely be tall enough, 1188 00:51:49,429 --> 00:51:50,720 but could be whatever you want. 1189 00:51:50,720 --> 00:51:54,390 1190 00:51:54,390 --> 00:51:57,277 And now let's go ahead and write some JavaScript. 1191 00:51:57,277 --> 00:52:00,140 1192 00:52:00,140 --> 00:52:04,452 Const SVG equals D3.select SVG. 1193 00:52:04,452 --> 00:52:07,410 This is the same thing that we've been doing in all of the SVG examples 1194 00:52:07,410 --> 00:52:09,980 thus far, whereby we're basically selecting the canvas 1195 00:52:09,980 --> 00:52:14,120 and storing it inside of a variable called SVG. 1196 00:52:14,120 --> 00:52:16,350 But now I'm going to define a function. 1197 00:52:16,350 --> 00:52:18,980 And this function is going to be called draw point. 1198 00:52:18,980 --> 00:52:21,440 And what draw point is going to do is it's just 1199 00:52:21,440 --> 00:52:25,340 going to draw a point on the screen. 1200 00:52:25,340 --> 00:52:26,026 And OK. 1201 00:52:26,026 --> 00:52:27,650 So first of all, I need to figure out-- 1202 00:52:27,650 --> 00:52:31,010 I want to draw a point wherever the mouse is-- wherever the mouse is, 1203 00:52:31,010 --> 00:52:31,520 for example. 1204 00:52:31,520 --> 00:52:34,040 So I need to know where the mouse currently is. 1205 00:52:34,040 --> 00:52:39,170 And so in D3, the way to get that is to say D3.mouse 1206 00:52:39,170 --> 00:52:40,880 and then in parentheses, this. 1207 00:52:40,880 --> 00:52:45,450 So take the event and figure out where the mouse is for this particular event. 1208 00:52:45,450 --> 00:52:50,090 And we're going to save that in a variable called cords, or coordinates, 1209 00:52:50,090 --> 00:52:52,560 for example. 1210 00:52:52,560 --> 00:52:56,010 And so that variable is going to store wherever the mouse currently 1211 00:52:56,010 --> 00:52:58,090 is at this moment. 1212 00:52:58,090 --> 00:53:02,210 And now I'm going to say SVG.appendcircle. 1213 00:53:02,210 --> 00:53:05,290 So add a circle to the canvas. 1214 00:53:05,290 --> 00:53:11,240 And the attribute cx, what is the center x-coordinate of this circle? 1215 00:53:11,240 --> 00:53:14,330 Well, it's just going to be cords zero. 1216 00:53:14,330 --> 00:53:17,160 Coordinates [INAUDIBLE] like an array of an xy pair. 1217 00:53:17,160 --> 00:53:19,100 So cords zero is just going to say, what is 1218 00:53:19,100 --> 00:53:22,130 the x-position of the mouse right now? 1219 00:53:22,130 --> 00:53:26,000 And that should be the center x-coordinate of this circle. 1220 00:53:26,000 --> 00:53:29,870 And likewise, cy, the center y-coordinate should be what? 1221 00:53:29,870 --> 00:53:34,298 1222 00:53:34,298 --> 00:53:35,290 AUDIENCE: Cords one. 1223 00:53:35,290 --> 00:53:36,180 BRIAN YU: Cords one. 1224 00:53:36,180 --> 00:53:37,350 Great. 1225 00:53:37,350 --> 00:53:40,360 So I'm creating a new circle and setting it's x and y coordinates 1226 00:53:40,360 --> 00:53:43,712 to be the x and y coordinates of the mouse. 1227 00:53:43,712 --> 00:53:45,045 We'll go and give this a radius. 1228 00:53:45,045 --> 00:53:47,982 We'll give it a radius of 5, for instance. 1229 00:53:47,982 --> 00:53:50,190 And we'll go ahead and give it some style properties. 1230 00:53:50,190 --> 00:53:52,228 Fill, we'll just say, black for now. 1231 00:53:52,228 --> 00:53:54,710 1232 00:53:54,710 --> 00:53:55,210 All right. 1233 00:53:55,210 --> 00:53:56,724 So I've created a circle. 1234 00:53:56,724 --> 00:53:58,700 AUDIENCE: Close the SVG-- 1235 00:53:58,700 --> 00:54:00,680 BRIAN YU: Close the SVG-- 1236 00:54:00,680 --> 00:54:04,310 the slash here is self-closing. 1237 00:54:04,310 --> 00:54:09,026 I mean, you could do this and this, which I guess helps the color scheming, 1238 00:54:09,026 --> 00:54:10,400 but technically we don't need to. 1239 00:54:10,400 --> 00:54:14,310 1240 00:54:14,310 --> 00:54:14,810 Circle. 1241 00:54:14,810 --> 00:54:17,900 We set the x and y coordinates at the radius of the fill color. 1242 00:54:17,900 --> 00:54:20,220 And that's it for this draw point function. 1243 00:54:20,220 --> 00:54:22,761 All we're going to do is figure out where the mouse currently 1244 00:54:22,761 --> 00:54:24,980 is and then we're going to add a circle to the screen 1245 00:54:24,980 --> 00:54:27,537 at that particular location. 1246 00:54:27,537 --> 00:54:29,120 Questions about what we did just then? 1247 00:54:29,120 --> 00:54:32,921 1248 00:54:32,921 --> 00:54:33,420 Yeah. 1249 00:54:33,420 --> 00:54:37,600 AUDIENCE: Can you just quickly say again the .attribute [INAUDIBLE].. 1250 00:54:37,600 --> 00:54:39,347 Just go through-- 1251 00:54:39,347 --> 00:54:39,930 BRIAN YU: Yep. 1252 00:54:39,930 --> 00:54:41,910 The .attribute section? 1253 00:54:41,910 --> 00:54:42,570 AUDIENCE: Yeah. 1254 00:54:42,570 --> 00:54:47,490 BRIAN YU: So SVG.appendcircle says take the SVG canvas and add a circle to it. 1255 00:54:47,490 --> 00:54:51,030 And then I'm going to take that circle and modify its attributes. 1256 00:54:51,030 --> 00:54:54,810 And so the circle needs to know where on the canvas it should go. 1257 00:54:54,810 --> 00:54:57,150 And so we're saying, set the x-coordinate of the circle 1258 00:54:57,150 --> 00:55:00,861 to be whatever cords zero, the x-coordinate of wherever the mouse is. 1259 00:55:00,861 --> 00:55:03,360 Same thing goes for the y-coordinate of the circle, wherever 1260 00:55:03,360 --> 00:55:05,220 the y-coordinate of the mouse is. 1261 00:55:05,220 --> 00:55:10,170 Set the radius of the circle to be five and then fill the circle in all black. 1262 00:55:10,170 --> 00:55:12,940 1263 00:55:12,940 --> 00:55:17,060 And then, now here comes the interesting part, 1264 00:55:17,060 --> 00:55:18,750 we're going to add an event listener. 1265 00:55:18,750 --> 00:55:20,970 SVG.on. 1266 00:55:20,970 --> 00:55:25,590 And the event that we're going to listen for is the mouse move event. 1267 00:55:25,590 --> 00:55:28,600 Whenever the mouse moves, we're going to run a function. 1268 00:55:28,600 --> 00:55:33,510 And the function we're going to run is the draw point function. 1269 00:55:33,510 --> 00:55:35,430 So we have our SVG canvas. 1270 00:55:35,430 --> 00:55:38,400 Anytime the mouse moves, we're going to call the draw point function. 1271 00:55:38,400 --> 00:55:40,800 And the draw point function is going to figure out where the mouse currently 1272 00:55:40,800 --> 00:55:43,080 is, save it in a variable called coordinates, 1273 00:55:43,080 --> 00:55:48,600 and then add a circle to the screen that has those coordinates. 1274 00:55:48,600 --> 00:55:53,460 And so assuming we did everything right, if we now open up draw.HTML, 1275 00:55:53,460 --> 00:55:56,370 we see a dot right underneath where my mouse is. 1276 00:55:56,370 --> 00:56:00,960 And if I move the mouse we'll see that little dots keep getting drawn. 1277 00:56:00,960 --> 00:56:04,380 Now, if I move the mouse quickly you'll see that it's not a perfect line. 1278 00:56:04,380 --> 00:56:06,270 Reason for that is that the browser only is 1279 00:56:06,270 --> 00:56:08,499 able to fire events every so many milliseconds. 1280 00:56:08,499 --> 00:56:10,290 And so if I move my mouse too quickly, it's 1281 00:56:10,290 --> 00:56:13,140 just not able to fire all the intermediary events in between. 1282 00:56:13,140 --> 00:56:16,410 But the idea now is I can move my mouse around, 1283 00:56:16,410 --> 00:56:18,930 and as I do so, the dots sort of follow. 1284 00:56:18,930 --> 00:56:21,772 So I'm able to trace out whatever it is that I'm drawing. 1285 00:56:21,772 --> 00:56:24,277 1286 00:56:24,277 --> 00:56:25,860 So this is all the code that did that. 1287 00:56:25,860 --> 00:56:28,620 It's 24 lines of code and we're able to create 1288 00:56:28,620 --> 00:56:30,610 that effect of drawing on the screen. 1289 00:56:30,610 --> 00:56:31,270 Yeah. 1290 00:56:31,270 --> 00:56:34,700 AUDIENCE: In the last statement you had where you were moving the mouse around, 1291 00:56:34,700 --> 00:56:36,170 is there an overflow limit? 1292 00:56:36,170 --> 00:56:38,456 Like, if you create too many dots, is that 1293 00:56:38,456 --> 00:56:40,580 going to crash the system or something? 1294 00:56:40,580 --> 00:56:42,620 BRIAN YU: If you create too many dots, is it going to crash the system? 1295 00:56:42,620 --> 00:56:44,690 Certainly, the browser does have a memory limit, 1296 00:56:44,690 --> 00:56:46,490 but these are pretty small circles that don't 1297 00:56:46,490 --> 00:56:48,406 have a whole lot of data associated with them, 1298 00:56:48,406 --> 00:56:50,573 and modern browsers can handle pretty big web pages, 1299 00:56:50,573 --> 00:56:53,739 so probably not something that we have to worry too much about at least now. 1300 00:56:53,739 --> 00:56:54,240 Yeah. 1301 00:56:54,240 --> 00:56:54,865 AUDIENCE: Yeah. 1302 00:56:54,865 --> 00:56:58,619 I'm confused about why you used const instead of let, because, aren't you 1303 00:56:58,619 --> 00:57:00,680 changing that value every time you [INAUDIBLE]?? 1304 00:57:00,680 --> 00:57:01,490 BRIAN YU: Yeah. 1305 00:57:01,490 --> 00:57:03,069 Why const instead of let here? 1306 00:57:03,069 --> 00:57:05,610 Because the mouse is moving, so the coordinates are changing, 1307 00:57:05,610 --> 00:57:08,602 because any one time I call the draw point function, 1308 00:57:08,602 --> 00:57:09,810 the coordinates don't change. 1309 00:57:09,810 --> 00:57:12,060 And so I'm never resetting coordinates later in the function. 1310 00:57:12,060 --> 00:57:14,180 And so it's fine to use const here instead of let. 1311 00:57:14,180 --> 00:57:16,769 1312 00:57:16,769 --> 00:57:17,310 Other things. 1313 00:57:17,310 --> 00:57:17,961 Yeah. 1314 00:57:17,961 --> 00:57:20,672 AUDIENCE: [INAUDIBLE]. 1315 00:57:20,672 --> 00:57:23,630 BRIAN YU: Is there a way to make the dots actually complete each other? 1316 00:57:23,630 --> 00:57:24,130 Yes. 1317 00:57:24,130 --> 00:57:26,580 We'll talk about that in a couple of minutes. 1318 00:57:26,580 --> 00:57:29,320 But yes, you can. 1319 00:57:29,320 --> 00:57:31,490 So all right. 1320 00:57:31,490 --> 00:57:34,340 Mouse move is an event that we can use to say, all right, when 1321 00:57:34,340 --> 00:57:37,580 the mouse is moving, anytime the mouse moves, let's do something. 1322 00:57:37,580 --> 00:57:39,040 There are other events too. 1323 00:57:39,040 --> 00:57:42,890 There is mouse down and mouse up to mean when I'm clicking 1324 00:57:42,890 --> 00:57:44,060 and when I'm not clicking. 1325 00:57:44,060 --> 00:57:47,150 And maybe that's something I'd like to do, because right now I'm drawing, 1326 00:57:47,150 --> 00:57:49,770 and I'm literally drawing anytime the mouse is moving, 1327 00:57:49,770 --> 00:57:52,910 and so there's no way to stop drawing, for example. 1328 00:57:52,910 --> 00:57:57,170 What I'd like to do is when the mouse is down, then I should be drawing, 1329 00:57:57,170 --> 00:58:00,850 but when I lift up the mouse, then don't worry about it. 1330 00:58:00,850 --> 00:58:03,250 So how would I do that? 1331 00:58:03,250 --> 00:58:05,260 What variable do I now need? 1332 00:58:05,260 --> 00:58:07,000 What type of variable should I add here? 1333 00:58:07,000 --> 00:58:09,700 1334 00:58:09,700 --> 00:58:12,041 Any thoughts as to how to go about designing this? 1335 00:58:12,041 --> 00:58:12,540 Yeah. 1336 00:58:12,540 --> 00:58:14,535 AUDIENCE: [INAUDIBLE]. 1337 00:58:14,535 --> 00:58:15,160 BRIAN YU: Yeah. 1338 00:58:15,160 --> 00:58:18,190 Some Boolean variable-- yes, no, true, false, that's keeping track of, 1339 00:58:18,190 --> 00:58:20,410 should I actually be drawing right now? 1340 00:58:20,410 --> 00:58:24,214 And so we'll just call it let drawing equal-- 1341 00:58:24,214 --> 00:58:27,130 and we'll start off by false, because by default, until you click down 1342 00:58:27,130 --> 00:58:28,720 for the first time, we don't want to actually 1343 00:58:28,720 --> 00:58:31,075 be drawing on the screen using let instead of const 1344 00:58:31,075 --> 00:58:32,783 because this is a variable that I'm going 1345 00:58:32,783 --> 00:58:35,530 to be changing pretty frequently as I click down and click up. 1346 00:58:35,530 --> 00:58:37,530 And now the idea here is going to be-- 1347 00:58:37,530 --> 00:58:40,340 all right, SVG on mouse down. 1348 00:58:40,340 --> 00:58:43,030 In other words, when I click, then let's go ahead 1349 00:58:43,030 --> 00:58:47,535 and run this function, whereby I'll say drawing equals true. 1350 00:58:47,535 --> 00:58:52,690 I actually do want to start drawing now when I click down. 1351 00:58:52,690 --> 00:59:01,215 And SVG on mouse up, let's go ahead and say drawing equals false. 1352 00:59:01,215 --> 00:59:03,840 So I defined a variable called drawing that's keeping track of, 1353 00:59:03,840 --> 00:59:05,370 should I be drawing right now? 1354 00:59:05,370 --> 00:59:09,270 When the mouse goes down, when I click the mouse down, drawing is set to true. 1355 00:59:09,270 --> 00:59:13,606 As soon as I lift my mouse up, drawing is set to false. 1356 00:59:13,606 --> 00:59:14,480 Questions about that. 1357 00:59:14,480 --> 00:59:17,446 1358 00:59:17,446 --> 00:59:18,320 What's the last step? 1359 00:59:18,320 --> 00:59:19,070 What am I missing? 1360 00:59:19,070 --> 00:59:21,830 1361 00:59:21,830 --> 00:59:22,330 Yeah. 1362 00:59:22,330 --> 00:59:25,434 AUDIENCE: [INAUDIBLE]. 1363 00:59:25,434 --> 00:59:26,100 BRIAN YU: Great. 1364 00:59:26,100 --> 00:59:27,974 An if statement inside of the function that's 1365 00:59:27,974 --> 00:59:30,420 actually doing the drawing that basically says, 1366 00:59:30,420 --> 00:59:33,510 if not drawing, or in other words, if drawing is false, 1367 00:59:33,510 --> 00:59:35,580 if I shouldn't be drawing right now, well, 1368 00:59:35,580 --> 00:59:39,570 then just go ahead and return, ignore the rest of the function, 1369 00:59:39,570 --> 00:59:41,640 just exit the function now, because if I'm not 1370 00:59:41,640 --> 00:59:43,560 supposed to be drawing right now, then I don't 1371 00:59:43,560 --> 00:59:46,060 want to actually calculate the coordinates or add the circle 1372 00:59:46,060 --> 00:59:48,550 or do any of that. 1373 00:59:48,550 --> 00:59:51,300 So now, again, assuming we did everything right, refresh the page. 1374 00:59:51,300 --> 00:59:53,508 I move the mouse around and, OK, nothing's happening, 1375 00:59:53,508 --> 00:59:54,430 nothing's being drawn. 1376 00:59:54,430 --> 00:59:57,430 But if I hold down the mouse and try and draw something, 1377 00:59:57,430 --> 01:00:00,250 OK, now I'm able to actually draw on the screen. 1378 01:00:00,250 --> 01:00:03,830 1379 01:00:03,830 --> 01:00:04,730 Questions about that. 1380 01:00:04,730 --> 01:00:09,510 1381 01:00:09,510 --> 01:00:10,010 Yeah. 1382 01:00:10,010 --> 01:00:15,290 AUDIENCE: [INAUDIBLE] what is again that you're doing on line 18 with D3 mouse? 1383 01:00:15,290 --> 01:00:17,300 BRIAN YU: D3.mousethis, you can just think of-- 1384 01:00:17,300 --> 01:00:20,360 this refers to like the current event, the event of clicking. 1385 01:00:20,360 --> 01:00:23,510 And D3.mousethis is just the special D3 function 1386 01:00:23,510 --> 01:00:26,482 that's going to say, for this click event, where was the mouse? 1387 01:00:26,482 --> 01:00:28,940 In other words, what were the coordinates of that position? 1388 01:00:28,940 --> 01:00:30,920 And so we can use that to give us information 1389 01:00:30,920 --> 01:00:32,930 about where to actually draw the circle, because we 1390 01:00:32,930 --> 01:00:35,263 want to draw the circle wherever the mouse currently is. 1391 01:00:35,263 --> 01:00:38,950 1392 01:00:38,950 --> 01:00:41,060 Other things. 1393 01:00:41,060 --> 01:00:41,560 All right. 1394 01:00:41,560 --> 01:00:43,851 So you have a couple options for the afternoon project. 1395 01:00:43,851 --> 01:00:45,942 I'll introduce it before we all set you free. 1396 01:00:45,942 --> 01:00:47,650 One option is, if you would like to, feel 1397 01:00:47,650 --> 01:00:49,270 free to keep working on the quiz application. 1398 01:00:49,270 --> 01:00:51,970 If you didn't quite finish it, feel free to keep working on it if you want to. 1399 01:00:51,970 --> 01:00:54,400 Feel free to think about adding other features. 1400 01:00:54,400 --> 01:00:57,656 We talked about like saving where you are in the game, for instance. 1401 01:00:57,656 --> 01:00:59,530 We talked about the ability of adding a timer 1402 01:00:59,530 --> 01:01:02,571 to it, for instance, using some of the things that we talked about today. 1403 01:01:02,571 --> 01:01:05,414 Or if you would like to, expand upon this draw example. 1404 01:01:05,414 --> 01:01:07,580 You can either use what you've just been working on. 1405 01:01:07,580 --> 01:01:09,130 If you look at draw-- 1406 01:01:09,130 --> 01:01:12,130 I think it's drawone.HTML in the source code examples, 1407 01:01:12,130 --> 01:01:14,170 you can find basically exactly this. 1408 01:01:14,170 --> 01:01:17,770 But here's some things that you could try to add that you should potentially 1409 01:01:17,770 --> 01:01:19,660 try if you're interested. 1410 01:01:19,660 --> 01:01:22,480 Let's go ahead and go into draw-- 1411 01:01:22,480 --> 01:01:23,582 draw.HTML. 1412 01:01:23,582 --> 01:01:25,540 Here's what a finished product might look like. 1413 01:01:25,540 --> 01:01:28,581 And this is not all that much more complicated than what we already have, 1414 01:01:28,581 --> 01:01:30,130 whereby you can specify a color. 1415 01:01:30,130 --> 01:01:31,960 Like, OK, let's draw on red. 1416 01:01:31,960 --> 01:01:34,440 And stroke width, OK, let's draw on eight-- 1417 01:01:34,440 --> 01:01:36,020 in stroke width of eight. 1418 01:01:36,020 --> 01:01:38,230 And you can draw-- 1419 01:01:38,230 --> 01:01:40,190 you can draw whatever shapes you want. 1420 01:01:40,190 --> 01:01:42,460 Change the color. 1421 01:01:42,460 --> 01:01:45,600 Change the stroke width. 1422 01:01:45,600 --> 01:01:46,380 Draw more. 1423 01:01:46,380 --> 01:01:48,810 If you want to you can erase the screen. 1424 01:01:48,810 --> 01:01:49,577 Draw again. 1425 01:01:49,577 --> 01:01:51,660 And so think about the types of features you might 1426 01:01:51,660 --> 01:01:53,201 want to add in order to support this. 1427 01:01:53,201 --> 01:01:55,320 Now, this does, in fact, support the idea of, OK, 1428 01:01:55,320 --> 01:01:57,196 even if I move the mouse quickly, we're still 1429 01:01:57,196 --> 01:01:59,236 able to get the idea of things that are connected 1430 01:01:59,236 --> 01:02:00,780 instead of independent circles. 1431 01:02:00,780 --> 01:02:03,120 And the way that I'm doing this currently that you can try to do, 1432 01:02:03,120 --> 01:02:05,161 it's the recommended way to do this, is that when 1433 01:02:05,161 --> 01:02:07,770 you draw two points next to each other in the same one, 1434 01:02:07,770 --> 01:02:09,240 just draw a line in between them. 1435 01:02:09,240 --> 01:02:10,470 Usually they'll be pretty close together. 1436 01:02:10,470 --> 01:02:12,840 And if you draw a line in between them, the result of it 1437 01:02:12,840 --> 01:02:15,240 is that you're going to ultimately get something 1438 01:02:15,240 --> 01:02:17,665 that looks smooth instead of something that just looks 1439 01:02:17,665 --> 01:02:19,290 like a whole bunch of independent dots. 1440 01:02:19,290 --> 01:02:21,440 So you can think about adding that if you'd like to. 1441 01:02:21,440 --> 01:02:22,890 You can think about adding a dropdown that 1442 01:02:22,890 --> 01:02:24,930 allows you to choose a color, a dropdown that 1443 01:02:24,930 --> 01:02:26,160 allows you to choose a stroke width. 1444 01:02:26,160 --> 01:02:27,780 And ultimately you can think about the components 1445 01:02:27,780 --> 01:02:29,154 that are actually making this up. 1446 01:02:29,154 --> 01:02:31,590 This is just a select menu that you know how to create. 1447 01:02:31,590 --> 01:02:34,920 And you know how to, in JavaScript, try and query for a particular element, 1448 01:02:34,920 --> 01:02:37,530 like a form input, get it its value, and then 1449 01:02:37,530 --> 01:02:39,720 use its value inside of other code. 1450 01:02:39,720 --> 01:02:42,600 And the SVG code we've been working with D3 is just JavaScript. 1451 01:02:42,600 --> 01:02:46,380 So any JavaScript code you were able to write before you can use inside of D3 1452 01:02:46,380 --> 01:02:47,320 as well. 1453 01:02:47,320 --> 01:02:49,666 And so we'll go ahead and let you work on your projects. 1454 01:02:49,666 --> 01:02:52,290 Feel free to work on either the quiz or the drawing application 1455 01:02:52,290 --> 01:02:54,914 where you can support different colors, different line weights, 1456 01:02:54,914 --> 01:02:57,416 clearing the board, connecting the lines, and smooth lines, 1457 01:02:57,416 --> 01:02:59,040 or other features if you would like to. 1458 01:02:59,040 --> 01:03:02,260 And we'll go ahead and say, why don't-- 1459 01:03:02,260 --> 01:03:03,990 I forget what we've been doing. 1460 01:03:03,990 --> 01:03:08,880 Why don't you all go to room 136, and you all go to room 212, 1461 01:03:08,880 --> 01:03:11,750 and you can stay in the middle? 1462 01:03:11,750 --> 01:03:12,480 All right. 1463 01:03:12,480 --> 01:03:15,510 And we'll reconvene tomorrow at 10:00 AM in order 1464 01:03:15,510 --> 01:03:17,380 to talk more about SQL and databases. 1465 01:03:17,380 --> 01:03:19,400 And we'll pick up from there. 1466 01:03:19,400 --> 01:03:20,292