1 00:00:00,000 --> 00:00:00,400 2 00:00:00,400 --> 00:00:01,816 ANTON ULYANOV: All right, awesome. 3 00:00:01,816 --> 00:00:05,990 So hey, everyone, joining us both in person and from the great beyond. 4 00:00:05,990 --> 00:00:06,530 I'm Anton. 5 00:00:06,530 --> 00:00:09,290 I'm a senior at Harvard in Mather House. 6 00:00:09,290 --> 00:00:12,860 And this is a CS50 seminar about building interactive websites 7 00:00:12,860 --> 00:00:14,870 with Bootstrap and jQuery. 8 00:00:14,870 --> 00:00:17,780 So we saw a little bit about how to use Bootstrap 9 00:00:17,780 --> 00:00:20,717 and jQuery to make our websites beautiful. 10 00:00:20,717 --> 00:00:23,300 And now we're going to see a little bit about how to also make 11 00:00:23,300 --> 00:00:25,640 those beautiful websites interactive. 12 00:00:25,640 --> 00:00:29,450 So just to kind of set the topic for today, 13 00:00:29,450 --> 00:00:33,554 we're going to start with three or four disclaimers. 14 00:00:33,554 --> 00:00:35,720 And you'll see what I mean by that in just a second. 15 00:00:35,720 --> 00:00:37,580 We'll do a quick review of Bootstrap. 16 00:00:37,580 --> 00:00:39,455 Hopefully, you've seen a little bit about how 17 00:00:39,455 --> 00:00:41,660 it works from doing this CS50 psets, but we'll 18 00:00:41,660 --> 00:00:44,510 cover kind of a few of the basics in more detail 19 00:00:44,510 --> 00:00:46,880 to set the context for the rest of the conversation. 20 00:00:46,880 --> 00:00:49,580 Then we will actually see how to make our websites interactive 21 00:00:49,580 --> 00:00:52,400 with no JavaScript at all, just HTML. 22 00:00:52,400 --> 00:00:54,770 And you can already add interactivity to your websites. 23 00:00:54,770 --> 00:00:58,220 And then we'll add on jQuery and see how we can combine that with our Bootstrap 24 00:00:58,220 --> 00:01:00,980 code to make our websites even better. 25 00:01:00,980 --> 00:01:02,970 So for those of you kind of here in person, 26 00:01:02,970 --> 00:01:06,580 I'm more than happy to answer questions whenever they come up. 27 00:01:06,580 --> 00:01:10,172 OK, so to start us off, as I promised, a few disclaimers-- 28 00:01:10,172 --> 00:01:13,130 so first, we're only going to be talking about the front-end framework. 29 00:01:13,130 --> 00:01:17,420 So we're going to be talking about HTML with Bootstrap and JavaScript 30 00:01:17,420 --> 00:01:19,940 and jQuery. 31 00:01:19,940 --> 00:01:22,580 This means that a lot of stuff we do will not work in the sense 32 00:01:22,580 --> 00:01:25,920 that you won't be able to register users for your website or anything like that. 33 00:01:25,920 --> 00:01:28,010 But the beauty of this is that these frameworks are really independent, 34 00:01:28,010 --> 00:01:30,980 and you can build it on with any back-end framework you want. 35 00:01:30,980 --> 00:01:33,590 So you can use Flask with Python, as we saw in class. 36 00:01:33,590 --> 00:01:35,630 You can use any back-end of your choosing. 37 00:01:35,630 --> 00:01:37,640 And this will work just fine. 38 00:01:37,640 --> 00:01:40,730 This is also going to be largely a quick look just at what's 39 00:01:40,730 --> 00:01:43,425 possible with Bootstrap and jQuery. 40 00:01:43,425 --> 00:01:45,800 So we're going to use simplified examples throughout just 41 00:01:45,800 --> 00:01:47,690 to illustrate some of the main points. 42 00:01:47,690 --> 00:01:51,530 And of course, we're going to gloss over some of the more nitty gritty syntax. 43 00:01:51,530 --> 00:01:53,840 The advantage of that, though, is that there is always 44 00:01:53,840 --> 00:01:55,490 a lot of support online. 45 00:01:55,490 --> 00:01:59,150 So the Bootstrap and jQuery documentation are both very thorough. 46 00:01:59,150 --> 00:02:02,570 And being the two most popular libraries used online for this type of stuff, 47 00:02:02,570 --> 00:02:04,170 there are so many examples everywhere. 48 00:02:04,170 --> 00:02:05,930 Pretty much anything you can think of, someone 49 00:02:05,930 --> 00:02:08,930 has already implemented either and Bootstrap or in Bootstrap and jQuery. 50 00:02:08,930 --> 00:02:11,480 And you can find all those examples online. 51 00:02:11,480 --> 00:02:14,900 Also, if you're interested in learning a little bit more just about Bootstrap, 52 00:02:14,900 --> 00:02:18,020 there was a CS50 seminar I think a couple of years ago by one of the TFs 53 00:02:18,020 --> 00:02:18,799 from Yale. 54 00:02:18,799 --> 00:02:20,840 So you can definitely take a look at that online. 55 00:02:20,840 --> 00:02:23,360 And that will kind of give a much more thorough introduction 56 00:02:23,360 --> 00:02:26,568 to Bootstrap as a whole, whereas here we're just going to cover enough of it, 57 00:02:26,568 --> 00:02:30,620 essentially, to get our feed running and start talking about that with jQuery 58 00:02:30,620 --> 00:02:31,670 as well. 59 00:02:31,670 --> 00:02:36,300 OK, we're going use, as you see, a bunch of code examples in the seminar. 60 00:02:36,300 --> 00:02:39,260 There's a coding sandbox with CS50. 61 00:02:39,260 --> 00:02:42,230 So you can access that there and play around with all the examples. 62 00:02:42,230 --> 00:02:44,140 They're all there for you. 63 00:02:44,140 --> 00:02:49,120 Awesome, OK, so with that, let's chat a little bit about Bootstrap. 64 00:02:49,120 --> 00:02:50,750 All right, so what is Bootstrap? 65 00:02:50,750 --> 00:02:52,700 Why bother with it in the first place? 66 00:02:52,700 --> 00:02:57,380 Essentially, because as you saw in the kind of last couple of problem sets, 67 00:02:57,380 --> 00:03:00,530 Bootstrap makes things look very beautiful very easily, right, 68 00:03:00,530 --> 00:03:04,020 with very little involvement on your part. 69 00:03:04,020 --> 00:03:06,650 So to go from here to here, all I did was just 70 00:03:06,650 --> 00:03:13,220 include the Bootstrap CSS files, link them into the head of the HTML file. 71 00:03:13,220 --> 00:03:16,610 And you can go from something that looks like this to a beautiful website 72 00:03:16,610 --> 00:03:21,950 with different layouts for your content, dynamic fonts, resizing, 73 00:03:21,950 --> 00:03:23,090 all of the good stuff-- 74 00:03:23,090 --> 00:03:27,110 so a very easy way to go from something that has all the content 75 00:03:27,110 --> 00:03:29,510 you need to something that looks the way you want it to. 76 00:03:29,510 --> 00:03:31,343 One other kind of neat thing about Bootstrap 77 00:03:31,343 --> 00:03:34,040 is that it was really built to be a mobile-first framework. 78 00:03:34,040 --> 00:03:36,623 And what that means is that there's been a lot of thought that 79 00:03:36,623 --> 00:03:39,650 goes into making sure that your content re-sizes automatically if you're 80 00:03:39,650 --> 00:03:41,577 on a phone versus on a laptop. 81 00:03:41,577 --> 00:03:43,910 There's been a lot of thought that goes into making sure 82 00:03:43,910 --> 00:03:46,640 that all the layouts look good, regardless of the screen size 83 00:03:46,640 --> 00:03:48,840 you're on or the resolution that you're on. 84 00:03:48,840 --> 00:03:52,250 So hopefully, kind of just with these two images 85 00:03:52,250 --> 00:03:55,640 and also with what you've seen in class so far, a lot of good reason 86 00:03:55,640 --> 00:03:59,360 to use Bootstrap-- and we'll see how we can use it most effectively here. 87 00:03:59,360 --> 00:04:00,620 OK, so how to get started? 88 00:04:00,620 --> 00:04:04,940 As I said, literally, to go from this to this, all I had to do 89 00:04:04,940 --> 00:04:08,960 was include a few URLs in the head of my HTML file. 90 00:04:08,960 --> 00:04:11,990 So bootstrap is a collection of CSS elements. 91 00:04:11,990 --> 00:04:14,300 That's the first style sheet that we're adding in-- 92 00:04:14,300 --> 00:04:19,579 just compiled Bootstrap code, a bunch of CSS classes. 93 00:04:19,579 --> 00:04:21,800 We're also seeing a lot of JavaScript. 94 00:04:21,800 --> 00:04:25,016 For the interactivity, Bootstrap relies on jQuery and JavaScript 95 00:04:25,016 --> 00:04:25,640 under the hood. 96 00:04:25,640 --> 00:04:27,510 So you need to include those as well. 97 00:04:27,510 --> 00:04:30,140 And then finally, there's this little meta tag at the end. 98 00:04:30,140 --> 00:04:34,190 This meta tag essentially is telling Bootstrap and the browser what type 99 00:04:34,190 --> 00:04:35,310 of device you're on. 100 00:04:35,310 --> 00:04:36,500 Right, as we mentioned, a lot of stuff is 101 00:04:36,500 --> 00:04:38,510 built to rescale automatically depending on whether you're 102 00:04:38,510 --> 00:04:39,740 on a phone or a laptop. 103 00:04:39,740 --> 00:04:41,490 That's what this meta tag is saying there. 104 00:04:41,490 --> 00:04:44,690 It's essentially giving the CSS and the JavaScript information 105 00:04:44,690 --> 00:04:47,570 about your device, how big the browser is, 106 00:04:47,570 --> 00:04:50,840 and then that will allow it to rescale automatically. 107 00:04:50,840 --> 00:04:56,720 OK, so let's chat through a little bit of the basics of Bootstrap. 108 00:04:56,720 --> 00:04:59,540 And then we'll start talking about much more kind of concrete stuff 109 00:04:59,540 --> 00:05:02,090 in terms of how we can actually build interactive websites. 110 00:05:02,090 --> 00:05:06,500 So Bootstrap uses CSS classes to style all of the elements. 111 00:05:06,500 --> 00:05:09,470 And essentially, what that means is that you have normal HTML tags, 112 00:05:09,470 --> 00:05:10,430 as you've always seen. 113 00:05:10,430 --> 00:05:14,240 I'm not sure if nav was one that we ran into, but tags like paragraph, 114 00:05:14,240 --> 00:05:16,160 div, all the usual ones. 115 00:05:16,160 --> 00:05:20,300 And Bootstrap just adds styling on top of that with the Bootstrap classes. 116 00:05:20,300 --> 00:05:22,460 So you can go online to the Bootstrap documentation 117 00:05:22,460 --> 00:05:24,680 and see all of the different classes and what 118 00:05:24,680 --> 00:05:27,888 all of the different stylings that will be applied, depending on what classes 119 00:05:27,888 --> 00:05:28,790 you use. 120 00:05:28,790 --> 00:05:31,206 Also, I'm not sure if this is something we've seen before, 121 00:05:31,206 --> 00:05:33,150 but essentially we can chain classes together. 122 00:05:33,150 --> 00:05:33,650 Right? 123 00:05:33,650 --> 00:05:36,140 Just separating them out with a spacebar, 124 00:05:36,140 --> 00:05:39,490 that would give us multiple classes applied to the same element. 125 00:05:39,490 --> 00:05:41,834 OK, so that's how we style things. 126 00:05:41,834 --> 00:05:43,250 And then how do we lay things out? 127 00:05:43,250 --> 00:05:45,110 Bootstrap just relies on a grid. 128 00:05:45,110 --> 00:05:49,040 So you have one container that wraps around all of your content. 129 00:05:49,040 --> 00:05:53,150 And that container can either take up a certain amount of width on the screen 130 00:05:53,150 --> 00:05:55,460 or just fill the entire screen, regardless 131 00:05:55,460 --> 00:05:57,920 of what the user's device is. 132 00:05:57,920 --> 00:06:00,170 Inside of that container, you have rows that 133 00:06:00,170 --> 00:06:04,490 break the container horizontally and then columns, up to 12 of them, 134 00:06:04,490 --> 00:06:05,750 that create that grid for you. 135 00:06:05,750 --> 00:06:08,600 Inside of each row, you can have up to 12 columns. 136 00:06:08,600 --> 00:06:15,140 So thinking back to this image here, what do we see on the right? 137 00:06:15,140 --> 00:06:18,690 Essentially, something that very likely looks like this-- 138 00:06:18,690 --> 00:06:19,880 we have a container. 139 00:06:19,880 --> 00:06:22,490 We have a row inside of that container and a bunch of columns. 140 00:06:22,490 --> 00:06:26,000 All right, here we just have two columns, but, of course, 141 00:06:26,000 --> 00:06:27,560 we could always make more. 142 00:06:27,560 --> 00:06:31,460 So in fact, this is the HTML code styled with Bootstrap 143 00:06:31,460 --> 00:06:36,680 that goes into making that set of boxes with headings and buttons on the right. 144 00:06:36,680 --> 00:06:40,750 We have three divs that are columns. 145 00:06:40,750 --> 00:06:42,140 They're styled to be columns. 146 00:06:42,140 --> 00:06:44,690 And then this md-4 is just specifying that we 147 00:06:44,690 --> 00:06:47,750 want the columns to be of medium width and that they 148 00:06:47,750 --> 00:06:49,999 should take up 4 of the 12 columns. 149 00:06:49,999 --> 00:06:51,290 All right, remember we have 12. 150 00:06:51,290 --> 00:06:54,020 And so each of these columns is taking up four of those. 151 00:06:54,020 --> 00:06:55,850 If you don't specify a number at the end, 152 00:06:55,850 --> 00:06:58,160 it'll just divide right by the number of columns 153 00:06:58,160 --> 00:07:00,240 you have, and they'll scale automatically, 154 00:07:00,240 --> 00:07:03,320 which is why here, when we just had two, they would just take up 155 00:07:03,320 --> 00:07:06,350 half of the screen each if we don't specify six and six 156 00:07:06,350 --> 00:07:08,070 or something like that. 157 00:07:08,070 --> 00:07:14,462 OK, so fairly easily, we can get to a lot of good looking stuff. 158 00:07:14,462 --> 00:07:17,170 And remember kind of one of the core things I wanted to emphasize 159 00:07:17,170 --> 00:07:20,290 is that this is very accessible because you're just using the exact same HTML 160 00:07:20,290 --> 00:07:21,780 elements you've always been using. 161 00:07:21,780 --> 00:07:25,870 All right, this is only a mix of divs, headings, and paragraphs. 162 00:07:25,870 --> 00:07:29,710 And we get that same website that we've kind of always known, but now 163 00:07:29,710 --> 00:07:31,780 in a much more beautiful context. 164 00:07:31,780 --> 00:07:37,560 So to see this more concretely, we can-- 165 00:07:37,560 --> 00:07:42,160 so I recreated this website with just the quick HTML. 166 00:07:42,160 --> 00:07:46,210 All we have is a navigation bar-- that's that nav bar on the top-- 167 00:07:46,210 --> 00:07:50,230 with a mix of a for links and buttons. 168 00:07:50,230 --> 00:07:54,850 And then we have the familiar stuff we've seen, 169 00:07:54,850 --> 00:07:57,910 just a bunch of divs, some of which are classed as jumbotron, 170 00:07:57,910 --> 00:07:59,740 which is that big Hello, world! thing. 171 00:07:59,740 --> 00:08:01,900 We see our container div. 172 00:08:01,900 --> 00:08:04,730 And then we see our row and our columns. 173 00:08:04,730 --> 00:08:09,460 So using just the normal HTML elements, we've recreate the exact same thing 174 00:08:09,460 --> 00:08:12,000 just by applying the Bootstrap classes. 175 00:08:12,000 --> 00:08:18,010 And just to show what I mean by making things beautiful by resizing them, 176 00:08:18,010 --> 00:08:21,070 so if we extend out our browser window, notice 177 00:08:21,070 --> 00:08:23,410 what happens as we shrink down the browser window. 178 00:08:23,410 --> 00:08:27,344 Perhaps, we're a user moving from their laptop to a phone device. 179 00:08:27,344 --> 00:08:28,510 We make the windows smaller. 180 00:08:28,510 --> 00:08:31,810 The content wraps around within all of the paragraphs automatically. 181 00:08:31,810 --> 00:08:34,370 It gets bunched up a little bit closer together. 182 00:08:34,370 --> 00:08:37,200 And then once we're past a certain minimum width, 183 00:08:37,200 --> 00:08:39,549 we're going to see the nav bar collapse down 184 00:08:39,549 --> 00:08:43,419 to just one button on the top right just like you would see on a cell phone. 185 00:08:43,419 --> 00:08:46,630 And we can then click on that to open up the navigation bar. 186 00:08:46,630 --> 00:08:48,980 All of that implemented automatically. 187 00:08:48,980 --> 00:08:53,050 We also see our three columns collapse down into just one column 188 00:08:53,050 --> 00:08:54,890 where they're stacked on top of each other, 189 00:08:54,890 --> 00:08:57,020 just like we would see on a mobile phone, so 190 00:08:57,020 --> 00:09:01,180 a really nice kind of mobile-first framework in that sense. 191 00:09:01,180 --> 00:09:06,610 OK, so we have seen some of the basics. 192 00:09:06,610 --> 00:09:10,370 We just style things using classes, and we lay things out onto a grid. 193 00:09:10,370 --> 00:09:14,470 So let's talk about how these classes actually work. 194 00:09:14,470 --> 00:09:16,750 Essentially, Bootstrap just has some pre-built 195 00:09:16,750 --> 00:09:19,840 what's called components, which are different class stylings that you 196 00:09:19,840 --> 00:09:22,070 can apply to various HTML elements. 197 00:09:22,070 --> 00:09:24,130 For example, you might style your header tags 198 00:09:24,130 --> 00:09:27,160 or your paragraph tags with different forms of text. 199 00:09:27,160 --> 00:09:30,400 You might style forms using the two classes here-- 200 00:09:30,400 --> 00:09:35,530 form group and form control. 201 00:09:35,530 --> 00:09:39,490 You might style buttons using the class button and button primary there 202 00:09:39,490 --> 00:09:40,610 at the end. 203 00:09:40,610 --> 00:09:44,050 So we're just applying classes to HTML elements. 204 00:09:44,050 --> 00:09:46,840 And here we see what makes the form go from just 205 00:09:46,840 --> 00:09:49,362 a normal HTML form to a Bootstrap form. 206 00:09:49,362 --> 00:09:51,070 The only difference is just those classes 207 00:09:51,070 --> 00:09:53,110 and then linking in that style sheet. 208 00:09:53,110 --> 00:09:57,710 OK, so in this seminar, we're going to talk about two components of Bootstrap. 209 00:09:57,710 --> 00:10:01,425 Remember components are just stylings applied to normal HTML elements. 210 00:10:01,425 --> 00:10:03,800 We're going to talk about specifically alerts and modals. 211 00:10:03,800 --> 00:10:06,140 And we're going to see how we can first create those and then make 212 00:10:06,140 --> 00:10:08,390 them interactive for us by just using Bootstrap 213 00:10:08,390 --> 00:10:10,790 and then by combining in the JavaScript. 214 00:10:10,790 --> 00:10:12,410 OK, so what are alerts? 215 00:10:12,410 --> 00:10:15,197 If you looked at the staff solution of the CS50 finance pset 216 00:10:15,197 --> 00:10:17,780 when you registered, you probably saw this blue kind of banner 217 00:10:17,780 --> 00:10:19,640 across the top that said registered. 218 00:10:19,640 --> 00:10:20,960 That's a Bootstrap alert. 219 00:10:20,960 --> 00:10:23,870 It's just a div where you emphasize the content inside of that div 220 00:10:23,870 --> 00:10:26,870 by changing the background color, making the font a little bit prettier. 221 00:10:26,870 --> 00:10:31,190 All you do, you just create a normal div and then set its class to be an alert. 222 00:10:31,190 --> 00:10:34,020 All right, so using the alert class here, 223 00:10:34,020 --> 00:10:37,970 and then specifying alert-primary, remember chaining the classes, 224 00:10:37,970 --> 00:10:40,850 we can create a blue alert, rather than just a normal one, which 225 00:10:40,850 --> 00:10:43,220 is what that primary styling is adding. 226 00:10:43,220 --> 00:10:45,244 So we can customize that. 227 00:10:45,244 --> 00:10:48,410 We can change it to alert-danger, which creates a red alert, maybe something 228 00:10:48,410 --> 00:10:50,451 where a user has done something wrong, or they're 229 00:10:50,451 --> 00:10:53,510 trying to do an action that causes an error. 230 00:10:53,510 --> 00:10:57,230 And we can also create tags inside of the alerts. 231 00:10:57,230 --> 00:11:00,590 And if we use the alert-link class on a tag inside of an alert, 232 00:11:00,590 --> 00:11:03,320 that'll make that link match the formatting of that alert. 233 00:11:03,320 --> 00:11:05,780 So normally, links would be blue with an underline. 234 00:11:05,780 --> 00:11:07,850 Using alert-link will make the formatting 235 00:11:07,850 --> 00:11:11,940 on that link match whatever the formatting of the alert is. 236 00:11:11,940 --> 00:11:16,380 OK, the second component to talk about is modals. 237 00:11:16,380 --> 00:11:18,540 So modals in Bootstrap are divs. 238 00:11:18,540 --> 00:11:21,870 They're content that sits above the normal, the rest of the page, 239 00:11:21,870 --> 00:11:25,650 and kind of floats on top of it, blocks off whatever you might be seeing there. 240 00:11:25,650 --> 00:11:27,510 All right, a common example of this might 241 00:11:27,510 --> 00:11:30,416 be some kind of confirmation dialog. 242 00:11:30,416 --> 00:11:33,540 In the CS50 finance pset, maybe one of the special features you implemented 243 00:11:33,540 --> 00:11:35,400 was, before a user sells a stock, you asked 244 00:11:35,400 --> 00:11:37,230 them to confirm that they want to sell. 245 00:11:37,230 --> 00:11:38,820 You pop up a little modal. 246 00:11:38,820 --> 00:11:41,900 You say are you sure you want to sell-- yes or cancel. 247 00:11:41,900 --> 00:11:46,240 A modal, again, just a div where we apply certain stylings-- 248 00:11:46,240 --> 00:11:52,770 so a modal really consists of a header, a body, and a modal footer. 249 00:11:52,770 --> 00:11:54,720 So the header is just the title there. 250 00:11:54,720 --> 00:11:57,630 The body is whatever content you want include inside of the modal. 251 00:11:57,630 --> 00:12:00,630 And then the footer here would have the two buttons there for Close 252 00:12:00,630 --> 00:12:02,750 and Save Changes. 253 00:12:02,750 --> 00:12:06,471 OK, let's see how that actually looks. 254 00:12:06,471 --> 00:12:08,220 Let's see how that looks in a code example 255 00:12:08,220 --> 00:12:11,820 before we see how we can make these two alerts and modals interactive. 256 00:12:11,820 --> 00:12:18,030 So jumping back to our sandbox and restarting our terminal, 257 00:12:18,030 --> 00:12:20,400 so here I've used our normal Flask back-end 258 00:12:20,400 --> 00:12:22,710 that we would have used in Python with CS50. 259 00:12:22,710 --> 00:12:26,100 Of course, you can use whatever back-end you find most convenient because this 260 00:12:26,100 --> 00:12:27,810 is just the front-end. 261 00:12:27,810 --> 00:12:35,470 OK, so let's just go to our static alert and see what that looks like. 262 00:12:35,470 --> 00:12:37,770 So we see a bunch of different alerts here. 263 00:12:37,770 --> 00:12:39,330 And how did we implement them? 264 00:12:39,330 --> 00:12:45,130 With the HTML, once we get into the body, I have my container. 265 00:12:45,130 --> 00:12:47,500 Inside of it, I have a heading for static alerts. 266 00:12:47,500 --> 00:12:50,410 hr is just a horizontal line underneath that. 267 00:12:50,410 --> 00:12:52,630 And then each alert is just a div that has 268 00:12:52,630 --> 00:12:54,640 a different class applied to it, which gives us 269 00:12:54,640 --> 00:12:58,030 the blue alert versus the secondary gray alert versus the green, the red, 270 00:12:58,030 --> 00:12:59,080 and so on-- 271 00:12:59,080 --> 00:13:01,760 so just divs with different stylings. 272 00:13:01,760 --> 00:13:05,800 OK, and then the modal, we won't go through the code 273 00:13:05,800 --> 00:13:09,430 right now because the modal kind of is inherently interactive. 274 00:13:09,430 --> 00:13:11,050 But how might the modal look? 275 00:13:11,050 --> 00:13:14,140 We might click a button that says Launch Modal or something like that. 276 00:13:14,140 --> 00:13:16,600 And then we would see the modal header up there 277 00:13:16,600 --> 00:13:20,830 where it says my modal, the modal body, the content, and then the footer that 278 00:13:20,830 --> 00:13:22,540 has the Close button inside of it. 279 00:13:22,540 --> 00:13:26,170 So the modal, kind of a preview of the type of interactivity 280 00:13:26,170 --> 00:13:30,250 that we can create very, very easily within Bootstrap. 281 00:13:30,250 --> 00:13:34,820 OK, so first, as promised, we can recreate that modal 282 00:13:34,820 --> 00:13:36,694 without using any JavaScript whatsoever. 283 00:13:36,694 --> 00:13:38,360 What we just saw, you can click buttons. 284 00:13:38,360 --> 00:13:40,130 You can make things pop up and go away-- 285 00:13:40,130 --> 00:13:45,470 no JavaScript at all, just the same HTML with probably under 20 characters 286 00:13:45,470 --> 00:13:47,980 of additional typing written out. 287 00:13:47,980 --> 00:13:49,880 OK, how do we do that? 288 00:13:49,880 --> 00:13:53,930 With something called data dash something attributes. 289 00:13:53,930 --> 00:14:01,400 So data attributes are a new feature in HTML5, the latest version of HTML. 290 00:14:01,400 --> 00:14:03,140 What happens there? 291 00:14:03,140 --> 00:14:07,040 Essentially, sometimes, we might want to associate additional information 292 00:14:07,040 --> 00:14:09,187 about a certain HTML element. 293 00:14:09,187 --> 00:14:11,270 And we don't really have any good place to put it. 294 00:14:11,270 --> 00:14:11,770 Right? 295 00:14:11,770 --> 00:14:14,630 With HTML elements, what we've seen so far are IDs and classes. 296 00:14:14,630 --> 00:14:16,546 Remember IDs are supposed to be unique, and we 297 00:14:16,546 --> 00:14:19,460 might want to refer to them in our CSS or something like that. 298 00:14:19,460 --> 00:14:21,470 Classes, of course, we don't want to store data 299 00:14:21,470 --> 00:14:22,999 about our content in the class. 300 00:14:22,999 --> 00:14:25,790 The class is something that's supposed to be used for CSS stylings. 301 00:14:25,790 --> 00:14:27,090 So what can we do? 302 00:14:27,090 --> 00:14:29,110 We can add data attributes. 303 00:14:29,110 --> 00:14:32,840 And these attributes can be essentially data dash anything-- whatever you want, 304 00:14:32,840 --> 00:14:35,280 my favorite parameter, whatever it is. 305 00:14:35,280 --> 00:14:37,740 And then you can put some kind of string inside of it. 306 00:14:37,740 --> 00:14:39,865 And then when you're referencing that HTML element, 307 00:14:39,865 --> 00:14:42,120 you can get back the data that's inside of there. 308 00:14:42,120 --> 00:14:46,100 So for example, here, we might have the inventory for a restaurant. 309 00:14:46,100 --> 00:14:48,530 So they have potatoes, carrots, and eggplants. 310 00:14:48,530 --> 00:14:50,780 And maybe each of those have some kind of product code 311 00:14:50,780 --> 00:14:53,030 when they're trying to reorder from a vendor. 312 00:14:53,030 --> 00:14:58,340 So we can say data-product_id and specify a string, product_id, 313 00:14:58,340 --> 00:15:00,950 for each of the elements inside of that list. 314 00:15:00,950 --> 00:15:05,120 And then if we're processing that list in our Python or with our JavaScript, 315 00:15:05,120 --> 00:15:10,620 we can get back those strings, the 1001, 1121, and 0615. 316 00:15:10,620 --> 00:15:15,170 We can get those back by referring to the data-product_id attribute 317 00:15:15,170 --> 00:15:17,360 of that HTML element. 318 00:15:17,360 --> 00:15:20,510 OK, so how do we do that? 319 00:15:20,510 --> 00:15:22,420 And why does that matter for Bootstrap? 320 00:15:22,420 --> 00:15:25,130 In Bootstrap, these data dash attributes are 321 00:15:25,130 --> 00:15:27,290 used to add the interactivity to components 322 00:15:27,290 --> 00:15:30,649 without kind of any additional effort required on the part of the user. 323 00:15:30,649 --> 00:15:33,440 So essentially, on the back-end, there's a lot of JavaScript that's 324 00:15:33,440 --> 00:15:35,180 implemented for you in Bootstrap. 325 00:15:35,180 --> 00:15:39,080 And when it sees that there's some kind of data attribute on an HTML element, 326 00:15:39,080 --> 00:15:41,520 it knows what to do for you. 327 00:15:41,520 --> 00:15:43,690 So for example, we can enable dismissing an alert. 328 00:15:43,690 --> 00:15:44,189 Right? 329 00:15:44,189 --> 00:15:47,540 We see this little cross on the bottom right here. 330 00:15:47,540 --> 00:15:49,190 How do we enable that? 331 00:15:49,190 --> 00:15:52,542 All we do, first, remember we style it in the same way 332 00:15:52,542 --> 00:15:53,750 as we would our normal alert. 333 00:15:53,750 --> 00:15:55,220 We just add a bunch of classes. 334 00:15:55,220 --> 00:15:58,670 And all of these classes, you can just find in the Bootstrap documentation. 335 00:15:58,670 --> 00:16:01,130 But what makes it a special alert? 336 00:16:01,130 --> 00:16:04,220 This data-dismiss="alert". 337 00:16:04,220 --> 00:16:05,550 What is that saying? 338 00:16:05,550 --> 00:16:08,600 It's saying, when the user clicks on this button, 339 00:16:08,600 --> 00:16:10,010 you should dismiss something. 340 00:16:10,010 --> 00:16:11,870 And what should you dismiss? 341 00:16:11,870 --> 00:16:16,530 The element with the tag alert on it or the alert element. 342 00:16:16,530 --> 00:16:20,630 OK, so again, kind of just to quickly recap, on the back-end, 343 00:16:20,630 --> 00:16:23,430 there's a lot of JavaScript that is implemented for you. 344 00:16:23,430 --> 00:16:26,035 And when you have this data-dismiss attribute, 345 00:16:26,035 --> 00:16:28,910 what the JavaScript is seeing is it's seeing you clicked on a button. 346 00:16:28,910 --> 00:16:30,860 And this button is supposed to dismiss something 347 00:16:30,860 --> 00:16:32,735 because the attribute is called data-dismiss, 348 00:16:32,735 --> 00:16:34,310 and it's present on the button. 349 00:16:34,310 --> 00:16:37,680 What is it dismissing the element with the alert. 350 00:16:37,680 --> 00:16:38,297 Yeah? 351 00:16:38,297 --> 00:16:41,424 AUDIENCE: The same thing we made with a [INAUDIBLE].. 352 00:16:41,424 --> 00:16:42,590 ANTON ULYANOV: Yes, exactly. 353 00:16:42,590 --> 00:16:45,860 So you can absolutely do the same thing with JavaScript. 354 00:16:45,860 --> 00:16:48,710 And that's, to an extent, what we're going to see in the second half 355 00:16:48,710 --> 00:16:51,167 with jQuery simplifying the JavaScript we need. 356 00:16:51,167 --> 00:16:54,500 But for people that are less comfortable with JavaScript, you can do all of this 357 00:16:54,500 --> 00:16:56,660 just with the HTML. 358 00:16:56,660 --> 00:16:59,330 OK, and we can see the exact same thing in modals-- 359 00:16:59,330 --> 00:17:01,879 modals a little bit more complicated, a little bit more code. 360 00:17:01,879 --> 00:17:03,920 But again, remember modal is just a bunch of divs 361 00:17:03,920 --> 00:17:05,930 where one div defines the header. 362 00:17:05,930 --> 00:17:07,490 A div defines the body. 363 00:17:07,490 --> 00:17:10,099 And a div defines the footer. 364 00:17:10,099 --> 00:17:11,490 So what is different about this? 365 00:17:11,490 --> 00:17:14,310 We've added one more line of code from our previous modal, 366 00:17:14,310 --> 00:17:16,849 which is the button. 367 00:17:16,849 --> 00:17:19,639 So with the button, we have a data toggle, 368 00:17:19,639 --> 00:17:21,680 which is saying that, when the button is clicked, 369 00:17:21,680 --> 00:17:24,589 we should be toggling something on versus off. 370 00:17:24,589 --> 00:17:25,670 What are we toggling? 371 00:17:25,670 --> 00:17:27,770 The modal that's on the page. 372 00:17:27,770 --> 00:17:31,695 The data target is telling us which modal we actually want to toggle. 373 00:17:31,695 --> 00:17:34,820 So essentially, data-toggle="modal" is saying what are we going to toggle-- 374 00:17:34,820 --> 00:17:37,190 a modal, some element of type modal. 375 00:17:37,190 --> 00:17:40,400 And then the data-target is saying which modal would we want to turn on-- 376 00:17:40,400 --> 00:17:43,520 the div with ID "#exampleModal." 377 00:17:43,520 --> 00:17:45,620 So what type of-- 378 00:17:45,620 --> 00:17:48,200 kind of what is the string inside of data-target? 379 00:17:48,200 --> 00:17:51,860 The sharp "#exampleModal"-- it's just a normal CSS selector Right? 380 00:17:51,860 --> 00:17:53,930 We can use sharp some ID. 381 00:17:53,930 --> 00:17:56,000 We can use dot some class. 382 00:17:56,000 --> 00:18:00,140 If we just use the naked string with no sharp or dot in front of it, 383 00:18:00,140 --> 00:18:02,490 it'll just select the HTML tag. 384 00:18:02,490 --> 00:18:03,260 All right, yeah? 385 00:18:03,260 --> 00:18:05,340 AUDIENCE: Are modals limited to one button? 386 00:18:05,340 --> 00:18:07,885 Or can you have like a yes or no or confirm? 387 00:18:07,885 --> 00:18:11,010 ANTON ULYANOV: No, you can have-- right, so inside of them-- good question. 388 00:18:11,010 --> 00:18:13,556 The question was are modals limited to one type of button. 389 00:18:13,556 --> 00:18:16,430 Inside of the modal, you can have whatever content you would normally 390 00:18:16,430 --> 00:18:17,690 have inside of an HTML page. 391 00:18:17,690 --> 00:18:19,810 So you can definitely have multiple buttons here, 392 00:18:19,810 --> 00:18:22,550 as we'll see actually in just a little bit. 393 00:18:22,550 --> 00:18:25,010 You can have a form inside of a modal. 394 00:18:25,010 --> 00:18:27,200 Whatever content, you know, is most interesting, 395 00:18:27,200 --> 00:18:30,730 you can put inside of it because it's just a bunch of HTML code. 396 00:18:30,730 --> 00:18:37,479 OK, so what does this modal look like on an actual website? 397 00:18:37,479 --> 00:18:39,770 Just like that, right, so we can have multiple buttons. 398 00:18:39,770 --> 00:18:41,120 In fact, just in this modal alone, we actually 399 00:18:41,120 --> 00:18:43,953 have three buttons, right, because the little cross on the top right 400 00:18:43,953 --> 00:18:45,650 is also a button in and of itself. 401 00:18:45,650 --> 00:18:51,350 OK, so let's jump back to our code examples 402 00:18:51,350 --> 00:18:54,800 and just see this in a little bit more detail. 403 00:18:54,800 --> 00:19:01,210 OK, so going back here, let's first look at our interactive alert. 404 00:19:01,210 --> 00:19:10,460 So let's restart Flask and open up our interactive alert and go to that page 405 00:19:10,460 --> 00:19:10,960 here. 406 00:19:10,960 --> 00:19:13,940 407 00:19:13,940 --> 00:19:15,860 So now we see an alert. 408 00:19:15,860 --> 00:19:18,950 And we know it's an interactive alert because it has the little X. 409 00:19:18,950 --> 00:19:22,070 And you can click the X and dismiss the alert. 410 00:19:22,070 --> 00:19:24,345 If we refresh the page, what happens? 411 00:19:24,345 --> 00:19:25,220 The alert comes back. 412 00:19:25,220 --> 00:19:25,340 Right? 413 00:19:25,340 --> 00:19:28,040 And again, we can just keep redoing this as much as we need. 414 00:19:28,040 --> 00:19:30,470 OK, what is different? 415 00:19:30,470 --> 00:19:33,740 Just like we saw on the slides, all we needed to do 416 00:19:33,740 --> 00:19:38,450 was add this button of class close, which styles it as the little cross 417 00:19:38,450 --> 00:19:39,980 in the far right of the alert. 418 00:19:39,980 --> 00:19:44,300 And we have a data-dismiss="alert" attribute, which is saying that, 419 00:19:44,300 --> 00:19:46,730 when that button is clicked, we want to dismiss something. 420 00:19:46,730 --> 00:19:47,870 What do we want to dismiss? 421 00:19:47,870 --> 00:19:50,160 The alert that's on the page. 422 00:19:50,160 --> 00:19:52,910 And again, maybe if we had multiple alerts or something like that, 423 00:19:52,910 --> 00:19:55,610 we could add the data-target attribute to specify which 424 00:19:55,610 --> 00:19:57,820 alert we actually want to dismiss. 425 00:19:57,820 --> 00:20:00,140 OK, now let's jump back to our example of the modal 426 00:20:00,140 --> 00:20:04,410 now that we understand a little bit better how this interactivity works. 427 00:20:04,410 --> 00:20:06,350 So in our modal example, we have a button. 428 00:20:06,350 --> 00:20:08,550 We can click on it to launch a modal. 429 00:20:08,550 --> 00:20:10,350 It pops over our screen. 430 00:20:10,350 --> 00:20:12,826 If we click on the cross, our modal leaves. 431 00:20:12,826 --> 00:20:13,950 And we can launch it again. 432 00:20:13,950 --> 00:20:16,850 We can click on the Close button also to close our modal. 433 00:20:16,850 --> 00:20:18,890 In fact, the way that modals are implemented, 434 00:20:18,890 --> 00:20:22,070 it's listening for clicks anywhere kind of outside of the modal content 435 00:20:22,070 --> 00:20:22,980 as well. 436 00:20:22,980 --> 00:20:26,188 So if you just click elsewhere on the page, intuitively, as you would expect, 437 00:20:26,188 --> 00:20:27,640 the modal would also close then. 438 00:20:27,640 --> 00:20:29,730 OK, how are we doing this? 439 00:20:29,730 --> 00:20:32,120 Let's jump down to the body of our page. 440 00:20:32,120 --> 00:20:37,149 So just like we saw in the slide content, we have a data-toggle="modal" 441 00:20:37,149 --> 00:20:39,440 attribute, which is saying, when the button is clicked, 442 00:20:39,440 --> 00:20:41,120 toggle something of type modal. 443 00:20:41,120 --> 00:20:42,050 Which modal? 444 00:20:42,050 --> 00:20:46,370 The modal specified by data-target with ID "#exampleModal". 445 00:20:46,370 --> 00:20:49,122 OK, then we have our modal. 446 00:20:49,122 --> 00:20:51,080 And inside of it, a couple of things to focus-- 447 00:20:51,080 --> 00:20:54,050 first, this little cross in the top right of our modal 448 00:20:54,050 --> 00:20:56,930 when we launch it, the cross in the top right here, 449 00:20:56,930 --> 00:20:59,690 that's this button right here, which has the class 450 00:20:59,690 --> 00:21:01,172 close, which styles it as a cross. 451 00:21:01,172 --> 00:21:02,630 And what happens when you click it? 452 00:21:02,630 --> 00:21:06,479 You dismiss the data of type modal. 453 00:21:06,479 --> 00:21:08,270 And then again at the bottom in the footer, 454 00:21:08,270 --> 00:21:10,610 we have another button that says Close. 455 00:21:10,610 --> 00:21:14,750 Here we've styled it to be a button that's gray with button secondary. 456 00:21:14,750 --> 00:21:16,820 And what is happening when you click that button? 457 00:21:16,820 --> 00:21:20,060 You dismiss the element of type modal again. 458 00:21:20,060 --> 00:21:23,652 So no JavaScript involved on your part, but kind 459 00:21:23,652 --> 00:21:26,169 of recall that what's happening underneath the hood 460 00:21:26,169 --> 00:21:28,460 is that there is a lot of JavaScript that's prewritten, 461 00:21:28,460 --> 00:21:31,769 and it's just listening for when you click on certain elements. 462 00:21:31,769 --> 00:21:33,560 When you click on them, it's trying to read 463 00:21:33,560 --> 00:21:36,435 what attributes they have if they have any of these special data dash 464 00:21:36,435 --> 00:21:37,766 attributes. 465 00:21:37,766 --> 00:21:39,890 And if they do, then it's responding appropriately. 466 00:21:39,890 --> 00:21:42,102 So all running in JavaScript underneath the hood, 467 00:21:42,102 --> 00:21:44,060 but you're not seeing that because you can just 468 00:21:44,060 --> 00:21:47,551 use the data attributes to pass in the commands that you want to run. 469 00:21:47,551 --> 00:21:48,050 Yeah? 470 00:21:48,050 --> 00:21:53,390 AUDIENCE: We saw in lecture that if the user deactivated JavaScript then 471 00:21:53,390 --> 00:21:54,877 certain things wouldn't work. 472 00:21:54,877 --> 00:21:56,210 Does that apply to this as well? 473 00:21:56,210 --> 00:21:57,410 ANTON ULYANOV: Yes, exactly right. 474 00:21:57,410 --> 00:21:59,618 So the question was what happens if the user disables 475 00:21:59,618 --> 00:22:01,430 JavaScript or something like that. 476 00:22:01,430 --> 00:22:04,159 Recall the Bootstrap kind of relies under the hood on JavaScript 477 00:22:04,159 --> 00:22:05,450 to animate all of these things. 478 00:22:05,450 --> 00:22:10,050 And up top when we're linking in, right, we're linking in the CSS style sheet, 479 00:22:10,050 --> 00:22:13,830 but then also three different JavaScript libraries. 480 00:22:13,830 --> 00:22:16,210 So if the user disables JavaScript, this wouldn't work. 481 00:22:16,210 --> 00:22:17,597 Exactly. 482 00:22:17,597 --> 00:22:19,430 What JavaScript libraries are we linking in? 483 00:22:19,430 --> 00:22:22,138 We're linking in jQuery that we're going to work with just a sec. 484 00:22:22,138 --> 00:22:26,286 Popper.js is an additional library of prewritten functions 485 00:22:26,286 --> 00:22:27,410 that are used in Bootstrap. 486 00:22:27,410 --> 00:22:29,910 And then Bootstrap has prewritten a bunch of JavaScript code 487 00:22:29,910 --> 00:22:33,620 again to make this stuff work, which is this third one down here. 488 00:22:33,620 --> 00:22:38,660 OK, so we see how this can work without any additional interaction 489 00:22:38,660 --> 00:22:39,360 on our behalf. 490 00:22:39,360 --> 00:22:39,860 Right? 491 00:22:39,860 --> 00:22:44,000 We just specify the data attributes, say what we want to dismiss 492 00:22:44,000 --> 00:22:46,250 or what we want to toggle on or off, and then 493 00:22:46,250 --> 00:22:49,927 it kind of just weirdly, magically kind of just works, which is great. 494 00:22:49,927 --> 00:22:52,260 I certainly encourage you all to use that whether you're 495 00:22:52,260 --> 00:22:54,320 thinking about final projects or something like that. 496 00:22:54,320 --> 00:22:56,861 But we can certainly make this a little bit more interesting. 497 00:22:56,861 --> 00:22:57,960 And how can we do that? 498 00:22:57,960 --> 00:23:01,043 How can we get beyond just the basic functionality that's provided for us? 499 00:23:01,043 --> 00:23:04,040 That's where the jQuery and the JavaScript would come in. 500 00:23:04,040 --> 00:23:09,610 OK, so very quick recap of jQuery and what's happening-- jQuery 501 00:23:09,610 --> 00:23:10,610 is a JavaScript library. 502 00:23:10,610 --> 00:23:12,920 It makes programming in JavaScript a lot easier. 503 00:23:12,920 --> 00:23:16,220 They're kind of branding is, "Write less, do more." 504 00:23:16,220 --> 00:23:19,331 And we're going to see that reflected in their syntax in just a sec. 505 00:23:19,331 --> 00:23:21,080 jQuery is especially popular when it comes 506 00:23:21,080 --> 00:23:25,370 to manipulating elements of the DOM, the Document Object Model. 507 00:23:25,370 --> 00:23:27,390 So Bootstrap interactivity, as I mentioned, 508 00:23:27,390 --> 00:23:30,290 is already implemented with JavaScript and jQuery under the hood. 509 00:23:30,290 --> 00:23:32,570 So right now, we're going to first uncover, see 510 00:23:32,570 --> 00:23:35,960 how we can just recreate what happens in Bootstrap with JavaScript and jQuery. 511 00:23:35,960 --> 00:23:38,960 And they're going to see how we can expand on that and make our elements 512 00:23:38,960 --> 00:23:40,550 even more interactive. 513 00:23:40,550 --> 00:23:41,720 OK, how do we use jQuery? 514 00:23:41,720 --> 00:23:44,930 We just link it in the head. 515 00:23:44,930 --> 00:23:48,230 The previous code chunk from Bootstrap already has all of that. 516 00:23:48,230 --> 00:23:51,260 So if you just link in everything that was on the Bootstrap slide, 517 00:23:51,260 --> 00:23:54,050 you'll have all this functionality for you. 518 00:23:54,050 --> 00:23:56,850 OK, and how does jQuery work? 519 00:23:56,850 --> 00:23:58,440 It's a very simple syntax. 520 00:23:58,440 --> 00:24:01,920 It's $selector.action. 521 00:24:01,920 --> 00:24:05,850 So the dollar sign, just a reference to the fact that you're using jQuery. 522 00:24:05,850 --> 00:24:10,980 Selector is something like #id or .class or something like that. 523 00:24:10,980 --> 00:24:13,440 It selects an element from the HTML. 524 00:24:13,440 --> 00:24:16,990 And then action is the action that's being applied to that element. 525 00:24:16,990 --> 00:24:22,020 So for example, if we say something like $("#test").hide(), 526 00:24:22,020 --> 00:24:26,920 we'll select the element with ID test in our HTML page and hide it. 527 00:24:26,920 --> 00:24:31,380 .hide is a function that will remove that from display. 528 00:24:31,380 --> 00:24:36,330 So you can imagine maybe there's something like some kind of online game 529 00:24:36,330 --> 00:24:39,270 where there are a bunch of things popping up like the punch 530 00:24:39,270 --> 00:24:40,680 down the mole game. 531 00:24:40,680 --> 00:24:44,470 You might click on those, and they'll be hidden from the display for you. 532 00:24:44,470 --> 00:24:48,110 OK, so again, the selectors in jQuery-- just like the CSS selectors 533 00:24:48,110 --> 00:24:50,810 we've already seen-- #id, .class. 534 00:24:50,810 --> 00:24:55,610 And then if you just use the naked selector, that'll choose by HTML tag. 535 00:24:55,610 --> 00:25:02,140 So something like $"key" would select all of the paragraph tags on that page. 536 00:25:02,140 --> 00:25:07,420 OK, but jQuery is useful not just for applying actions to events 537 00:25:07,420 --> 00:25:09,530 kind of linearly, line by line. 538 00:25:09,530 --> 00:25:11,680 We can also listen for certain things to happen 539 00:25:11,680 --> 00:25:14,030 and then have a response to that. 540 00:25:14,030 --> 00:25:18,970 So for example, with .click, click is not the action that is being applied 541 00:25:18,970 --> 00:25:20,140 onto the paragraph. 542 00:25:20,140 --> 00:25:22,630 It's listening for someone to click on the paragraph 543 00:25:22,630 --> 00:25:24,830 and then submitting your response to it. 544 00:25:24,830 --> 00:25:29,860 So in this case, what's happening when someone clicks on a paragraph? 545 00:25:29,860 --> 00:25:31,500 We just have the naked selector there. 546 00:25:31,500 --> 00:25:35,720 So that's just something with the HTML p tag. 547 00:25:35,720 --> 00:25:39,370 jQuery is responding to that and is changing the text of the element that 548 00:25:39,370 --> 00:25:42,940 got clicked on, which is being selected with $(this), 549 00:25:42,940 --> 00:25:47,020 and changing that to "contents have changed." 550 00:25:47,020 --> 00:25:49,150 OK, this is essentially the interactivity 551 00:25:49,150 --> 00:25:52,630 that we're going to see that's useful in Bootstrap 552 00:25:52,630 --> 00:25:54,280 and how we're going to combine the two. 553 00:25:54,280 --> 00:25:57,470 554 00:25:57,470 --> 00:25:59,620 So let's integrate jQuery with Bootstrap. 555 00:25:59,620 --> 00:26:04,330 First, let's just recreate dynamically closing alerts with that little button. 556 00:26:04,330 --> 00:26:07,270 So Bootstrap interactivity basically provides you 557 00:26:07,270 --> 00:26:11,520 with kind of custom jQuery functions and jQuery listeners 558 00:26:11,520 --> 00:26:14,530 that you can use and then respond to appropriately. 559 00:26:14,530 --> 00:26:17,360 So recreating kind of what we've already seen, 560 00:26:17,360 --> 00:26:20,110 let's just say we have a test alert, right, just a div 561 00:26:20,110 --> 00:26:22,460 with the alert styling being applied onto it. 562 00:26:22,460 --> 00:26:26,230 And let's say below that, separately, we have a button with some styling applied 563 00:26:26,230 --> 00:26:28,030 to it to make the button look nice. 564 00:26:28,030 --> 00:26:32,230 And what's going to happen below that with our script? 565 00:26:32,230 --> 00:26:35,470 So the script says $("#close_alert"). 566 00:26:35,470 --> 00:26:38,600 That means select the element with ID close_alert, 567 00:26:38,600 --> 00:26:41,030 which is that button we have below. 568 00:26:41,030 --> 00:26:44,150 .on means that, rather than taking some action directly, 569 00:26:44,150 --> 00:26:46,830 we're listening for some kind of event to happen. 570 00:26:46,830 --> 00:26:51,330 So we have . on("click"), which just means the function after that is going 571 00:26:51,330 --> 00:26:54,290 to run when the button is clicked, so when the user interacts with 572 00:26:54,290 --> 00:26:55,370 the button. 573 00:26:55,370 --> 00:26:57,270 When that's clicked, what's going to happen? 574 00:26:57,270 --> 00:27:00,080 We're going to select the element with class alert, which 575 00:27:00,080 --> 00:27:02,270 we can see right up here. 576 00:27:02,270 --> 00:27:04,490 And we're going to close it. 577 00:27:04,490 --> 00:27:08,120 What's special between jQuery and Bootstrap 578 00:27:08,120 --> 00:27:10,340 is this part down here at the bottom where 579 00:27:10,340 --> 00:27:13,790 we're able to close the alert that's a special function that Bootstrap 580 00:27:13,790 --> 00:27:16,130 has written for us with JavaScript. 581 00:27:16,130 --> 00:27:21,000 OK, so let's see this with our jQuery alert. 582 00:27:21,000 --> 00:27:22,540 And again, we will restart Flask. 583 00:27:22,540 --> 00:27:27,630 584 00:27:27,630 --> 00:27:31,530 OK, so let's jump to our jQuery alert. 585 00:27:31,530 --> 00:27:33,930 Right here, note there's no kind of interactivity 586 00:27:33,930 --> 00:27:35,490 built into the alert itself. 587 00:27:35,490 --> 00:27:38,917 We're just trying to recreate it using JavaScript and HTML alone. 588 00:27:38,917 --> 00:27:39,750 OK, so what happens? 589 00:27:39,750 --> 00:27:42,690 We can click on the button, and we'll close the alert 590 00:27:42,690 --> 00:27:46,270 just as if we had clicked on the button inside of the alert with data-toggle. 591 00:27:46,270 --> 00:27:49,880 Again, we can refresh and see that same behavior. 592 00:27:49,880 --> 00:27:52,210 So what's happening? 593 00:27:52,210 --> 00:27:57,600 As promised, right, when a user clicks on the button with ID close_alert, 594 00:27:57,600 --> 00:28:01,300 the function after that is going to run that's being listened for. 595 00:28:01,300 --> 00:28:04,590 And it's going to close the alert, as we see here. 596 00:28:04,590 --> 00:28:08,230 OK, so this is great, kind of neat that we were able to do this ourselves 597 00:28:08,230 --> 00:28:11,890 without relying on the magic of Bootstrap with the data-toggle 598 00:28:11,890 --> 00:28:15,899 and stuff like that attributes, but not especially useful. 599 00:28:15,899 --> 00:28:18,190 In fact, I would say it kind of looks worse because you 600 00:28:18,190 --> 00:28:19,300 have to have the separate button. 601 00:28:19,300 --> 00:28:19,800 Right? 602 00:28:19,800 --> 00:28:22,000 Why would we ever want to do this? 603 00:28:22,000 --> 00:28:26,610 Because now that we have this jQuery separated out from the Bootstrap-- 604 00:28:26,610 --> 00:28:28,870 right, remember this script here, this code in jQuery, 605 00:28:28,870 --> 00:28:30,740 can be whatever we want it to be. 606 00:28:30,740 --> 00:28:33,580 So whereas before with the data dash attributes 607 00:28:33,580 --> 00:28:37,030 we were just bound to the behavior that was built into Bootstrap for us, now 608 00:28:37,030 --> 00:28:42,610 we can really do whatever we want with the same selection, event listeners, 609 00:28:42,610 --> 00:28:44,210 and functions. 610 00:28:44,210 --> 00:28:45,470 What do we mean by that? 611 00:28:45,470 --> 00:28:50,119 So let's say that, rather than just trying to close an alert, 612 00:28:50,119 --> 00:28:52,660 we're actually going to try to dynamically change the content 613 00:28:52,660 --> 00:28:55,326 inside of the alert or inside of the modal, all right, something 614 00:28:55,326 --> 00:28:58,070 that we can't do with just Bootstrap alone. 615 00:28:58,070 --> 00:29:00,169 First, quickly, let's recap. 616 00:29:00,169 --> 00:29:01,210 Why is this bootstrapped? 617 00:29:01,210 --> 00:29:03,959 Because we have the class styling applied to it that's making them 618 00:29:03,959 --> 00:29:04,810 Bootstrap alerts. 619 00:29:04,810 --> 00:29:06,100 And why is it closing? 620 00:29:06,100 --> 00:29:08,140 Because we've written this jQuery function here. 621 00:29:08,140 --> 00:29:17,870 OK, so to add interactivity into our Bootstrap, let's create a modal. 622 00:29:17,870 --> 00:29:21,589 But rather than just using data-toggle, data-dismiss, all of that 623 00:29:21,589 --> 00:29:23,380 to open and close our modal, let's actually 624 00:29:23,380 --> 00:29:27,850 change the content inside of the modal, depending on how the user opens it. 625 00:29:27,850 --> 00:29:30,550 So just like we have multiple buttons inside of the modal, 626 00:29:30,550 --> 00:29:34,027 we can also launch the same modal from two different locations. 627 00:29:34,027 --> 00:29:35,360 All right, how would we do that? 628 00:29:35,360 --> 00:29:38,857 We just set the same data-target from two different buttons. 629 00:29:38,857 --> 00:29:42,190 So regardless of whether the user clicks on this top button or the bottom button 630 00:29:42,190 --> 00:29:45,130 there in the code, will open up the same modal. 631 00:29:45,130 --> 00:29:48,730 But we will know which button the user clicked on 632 00:29:48,730 --> 00:29:53,954 because we have this additional data-myfavoriteparameter attribute. 633 00:29:53,954 --> 00:29:55,870 This is the use case we're talking about where 634 00:29:55,870 --> 00:29:59,860 storing additional information about which specific button the user clicked 635 00:29:59,860 --> 00:30:03,800 or special information about the HTML attribute is useful. 636 00:30:03,800 --> 00:30:07,330 So let's create a modal that allows us to provide feedback 637 00:30:07,330 --> 00:30:10,330 for either Brian or Veronica, depending on which button we clicked. 638 00:30:10,330 --> 00:30:12,902 And this is something we might see in the Q score system. 639 00:30:12,902 --> 00:30:15,610 Later on at the end of the semester, you have to provide feedback 640 00:30:15,610 --> 00:30:17,162 for different CS50 staff members. 641 00:30:17,162 --> 00:30:19,120 We can just have a button for each staff member 642 00:30:19,120 --> 00:30:22,411 that will allow you to provide feedback for that person or something like that. 643 00:30:22,411 --> 00:30:24,967 OK, so we have two buttons here, identical buttons, 644 00:30:24,967 --> 00:30:26,800 the only thing that's different between them 645 00:30:26,800 --> 00:30:29,560 is data-myfavoriteparameter, which is allowing 646 00:30:29,560 --> 00:30:31,914 us to store a little bit of additional information, 647 00:30:31,914 --> 00:30:34,330 specifically which of the two buttons the user clicked on, 648 00:30:34,330 --> 00:30:37,630 whether it's the Brian button or the Veronica button. 649 00:30:37,630 --> 00:30:40,250 OK, now let's go to our modal. 650 00:30:40,250 --> 00:30:44,260 Our modal here looks exactly the same as it has before. 651 00:30:44,260 --> 00:30:48,460 Again, a lot of code, but really what it is just a header that has a title in it 652 00:30:48,460 --> 00:30:49,559 called New Feedback. 653 00:30:49,559 --> 00:30:52,600 It's some body content that doesn't have anything inside of it right now. 654 00:30:52,600 --> 00:30:55,510 And then it's a footer that has two buttons, either Close or Submit 655 00:30:55,510 --> 00:30:56,680 Feedback. 656 00:30:56,680 --> 00:31:00,790 Note that we have the little data-dismiss="modal" 657 00:31:00,790 --> 00:31:02,900 attribute on the Close button. 658 00:31:02,900 --> 00:31:05,110 So we already know that, when we click on Close, 659 00:31:05,110 --> 00:31:07,010 the modal is just going to close for us. 660 00:31:07,010 --> 00:31:07,509 Right? 661 00:31:07,509 --> 00:31:10,257 We're relying on the earlier data dash interactivity 662 00:31:10,257 --> 00:31:12,340 that we learned with Bootstrap because we're lazy, 663 00:31:12,340 --> 00:31:14,570 and we don't want to write out all of the jQuery just 664 00:31:14,570 --> 00:31:16,991 to recreate the behavior that we already have for us. 665 00:31:16,991 --> 00:31:18,490 We want to rely on that when we can. 666 00:31:18,490 --> 00:31:22,120 And then when we need to extend, that's where we can use the jQuery. 667 00:31:22,120 --> 00:31:24,460 OK, so we have a modal. 668 00:31:24,460 --> 00:31:25,210 We have buttons. 669 00:31:25,210 --> 00:31:26,918 These buttons will both open up the modal 670 00:31:26,918 --> 00:31:30,130 because the same data target attribute is present in both of the buttons. 671 00:31:30,130 --> 00:31:31,850 How do we actually make this interactive? 672 00:31:31,850 --> 00:31:32,350 Right? 673 00:31:32,350 --> 00:31:36,310 How do we pass in the data that we got about which button 674 00:31:36,310 --> 00:31:40,820 the user clicked on to somehow change the content inside of this modal? 675 00:31:40,820 --> 00:31:43,050 That's where jQuery comes in. 676 00:31:43,050 --> 00:31:46,100 So we want to change this title attribute 677 00:31:46,100 --> 00:31:50,190 and specify which person we're providing feedback for. 678 00:31:50,190 --> 00:31:54,980 OK, so in our jQuery, recall that we can use listeners and then 679 00:31:54,980 --> 00:31:57,200 respond to those listeners. 680 00:31:57,200 --> 00:32:01,500 And then based on what happened, we can dynamically react to that. 681 00:32:01,500 --> 00:32:05,360 So here we have a listener for #exampleModal. 682 00:32:05,360 --> 00:32:09,200 #exampleModal is the ID of the modal that is being activated. 683 00:32:09,200 --> 00:32:14,120 And on show.bs.modal is where Bootstrap is coming in and helping us out. 684 00:32:14,120 --> 00:32:16,820 That's a custom event, which will get triggered 685 00:32:16,820 --> 00:32:19,430 when the modal is shown from Bootstrap. 686 00:32:19,430 --> 00:32:23,210 So again, show.bs.modal is where the Bootstrap 687 00:32:23,210 --> 00:32:24,980 is integrating with the jQuery. 688 00:32:24,980 --> 00:32:29,450 Someone wrote show.bs.modal as a function that will fire off 689 00:32:29,450 --> 00:32:33,110 when the modal is shown from Bootstrap. 690 00:32:33,110 --> 00:32:36,600 So when that happens, let's respond to that modal being shown. 691 00:32:36,600 --> 00:32:37,100 Right? 692 00:32:37,100 --> 00:32:40,277 Whenever this event triggers, we know that our modal just popped up. 693 00:32:40,277 --> 00:32:42,110 The user just clicked on one of the buttons. 694 00:32:42,110 --> 00:32:43,760 What can we do? 695 00:32:43,760 --> 00:32:46,820 So first, let's extract information about which button 696 00:32:46,820 --> 00:32:50,390 the user clicked to actually show us that modal. 697 00:32:50,390 --> 00:32:51,590 How can we do that? 698 00:32:51,590 --> 00:32:55,910 With this event.relatedTarget selector, this 699 00:32:55,910 --> 00:32:59,180 is a custom selector just like #exampleModal. 700 00:32:59,180 --> 00:33:02,450 But in this case, we're kind of making a self reference 701 00:33:02,450 --> 00:33:04,010 to the event that just happened. 702 00:33:04,010 --> 00:33:07,280 So we're selecting the thing that launched the modal, essentially, 703 00:33:07,280 --> 00:33:09,620 with this event.relatedTarget. 704 00:33:09,620 --> 00:33:12,980 This is just giving us whichever button launched the modal. 705 00:33:12,980 --> 00:33:14,060 What do we want to do? 706 00:33:14,060 --> 00:33:15,520 We want to pull out of it. 707 00:33:15,520 --> 00:33:16,520 Remember the data- dash. 708 00:33:16,520 --> 00:33:18,800 So we want to pull out of it the data that 709 00:33:18,800 --> 00:33:22,730 was stored in data-myfavoriteparameter. 710 00:33:22,730 --> 00:33:26,930 So recall that myfavoriteparameter varied between Brian and Veronica, 711 00:33:26,930 --> 00:33:28,850 depending on which button the user clicked. 712 00:33:28,850 --> 00:33:33,170 So on this first line here, we're going to go back, look at the HTML code, 713 00:33:33,170 --> 00:33:35,360 pull out the button that was used to launch 714 00:33:35,360 --> 00:33:38,090 the modal through event.relatedTarget. 715 00:33:38,090 --> 00:33:40,490 And inside of the variable recipient, we're 716 00:33:40,490 --> 00:33:43,370 going to store either the string Brian or the string Veronica, 717 00:33:43,370 --> 00:33:46,440 depending on which of the two buttons the user clicked on. 718 00:33:46,440 --> 00:33:49,421 OK, now let's actually update the modal. 719 00:33:49,421 --> 00:33:49,920 Right? 720 00:33:49,920 --> 00:33:52,230 Remember that we're trying to change the title of our modal. 721 00:33:52,230 --> 00:33:53,940 So rather than just saying New Feedback, we 722 00:33:53,940 --> 00:33:55,650 want this to dynamically change depending 723 00:33:55,650 --> 00:33:58,040 on which button the user had clicked. 724 00:33:58,040 --> 00:34:00,110 OK, let's select the modal. 725 00:34:00,110 --> 00:34:04,220 Again, this is a special selector that just selects the current HTML element. 726 00:34:04,220 --> 00:34:06,020 How do we know what this is? 727 00:34:06,020 --> 00:34:10,730 It refers to whatever was up here, so the modal with id #exampleModal. 728 00:34:10,730 --> 00:34:18,020 OK, inside of the modal, we can find an element with class modal-title. 729 00:34:18,020 --> 00:34:20,019 We see that element up here. 730 00:34:20,019 --> 00:34:21,560 It's whatever we're trying to select. 731 00:34:21,560 --> 00:34:24,530 So we found it inside of the modal. 732 00:34:24,530 --> 00:34:27,679 And then we can set the text inside of it to something different with 733 00:34:27,679 --> 00:34:28,889 the .text function. 734 00:34:28,889 --> 00:34:32,060 The .text function just replaces the text inside of some kind of HTML 735 00:34:32,060 --> 00:34:33,139 element. 736 00:34:33,139 --> 00:34:36,080 We want to replace it with "New Feedback for" 737 00:34:36,080 --> 00:34:38,027 and then put in our recipient dynamically. 738 00:34:38,027 --> 00:34:39,860 So what do we expect is going to happen now? 739 00:34:39,860 --> 00:34:41,280 If we click on the Brian button, we're going 740 00:34:41,280 --> 00:34:43,139 to have to provide new feedback for Brian. 741 00:34:43,139 --> 00:34:47,239 If we click on Veronica, we're going to provide new feedback for Veronica. 742 00:34:47,239 --> 00:34:55,380 OK, let's see this in action now with our jQuery modal, new and improved. 743 00:34:55,380 --> 00:35:01,460 744 00:35:01,460 --> 00:35:05,700 OK, and let's go to jQuery modal. 745 00:35:05,700 --> 00:35:11,710 So we see we have the two buttons that we had written in our code before. 746 00:35:11,710 --> 00:35:16,770 Those are down here, just two buttons, one for Brian, one for Veronica. 747 00:35:16,770 --> 00:35:19,280 What happens when we click on Feedback for Brian? 748 00:35:19,280 --> 00:35:23,690 We get a new modal that pops up, and it actually says New Feedback for Brian. 749 00:35:23,690 --> 00:35:26,170 So using the custom jQuery that we just wrote, 750 00:35:26,170 --> 00:35:32,880 we're able to bring together the HTML and this new interactive modal. 751 00:35:32,880 --> 00:35:33,380 Right? 752 00:35:33,380 --> 00:35:35,840 We're able to make our interactivity customized 753 00:35:35,840 --> 00:35:39,830 and not just rely on the built-in data-toggle, data-dismiss functions 754 00:35:39,830 --> 00:35:42,169 that are prewritten for us in bootstrap. 755 00:35:42,169 --> 00:35:43,460 So why is this actually useful? 756 00:35:43,460 --> 00:35:44,960 All right, of course, kind of it's cute to write 757 00:35:44,960 --> 00:35:47,240 New Feedback for Brian, New Feedback for Veronica, 758 00:35:47,240 --> 00:35:49,740 which we see would happen if we did this. 759 00:35:49,740 --> 00:35:50,270 Right? 760 00:35:50,270 --> 00:35:52,310 But for example, something we might do is 761 00:35:52,310 --> 00:35:54,680 we might have a form inside of the modal where 762 00:35:54,680 --> 00:35:58,610 we pre-fill one of the inputs using this exact same setup here. 763 00:35:58,610 --> 00:36:01,070 Then when the user submits that form, that content 764 00:36:01,070 --> 00:36:04,370 will get passed into our back-end, into our Flask and our Python, 765 00:36:04,370 --> 00:36:06,710 and then we can deal with it more dynamically there. 766 00:36:06,710 --> 00:36:09,835 So this essentially allows us to keep passing information onwards in a very 767 00:36:09,835 --> 00:36:13,370 interactive way and make our beautiful websites much more interactive, much 768 00:36:13,370 --> 00:36:16,160 more customized, depending on what the user is doing. 769 00:36:16,160 --> 00:36:19,726 So for example, now if the user clicked the button Submit Feedback, 770 00:36:19,726 --> 00:36:22,100 and we had implemented this a little bit more thoroughly, 771 00:36:22,100 --> 00:36:24,260 we could have passed through the value of Veronica 772 00:36:24,260 --> 00:36:27,420 without the user having to type anything else additionally inside. 773 00:36:27,420 --> 00:36:27,920 Why? 774 00:36:27,920 --> 00:36:30,680 Because we know, again, how the user actually got here, right, 775 00:36:30,680 --> 00:36:31,970 with the Veronica button. 776 00:36:31,970 --> 00:36:35,000 So we can keep passing that information on without the user 777 00:36:35,000 --> 00:36:38,600 having to provide us that information at every single step again. 778 00:36:38,600 --> 00:36:40,230 OK, awesome. 779 00:36:40,230 --> 00:36:44,595 So again, our usual stuff about modals is still present here. 780 00:36:44,595 --> 00:36:47,400 All right, we have the Close button, the Submit Feedback button. 781 00:36:47,400 --> 00:36:49,380 Because we're only focusing on the front-end, 782 00:36:49,380 --> 00:36:51,280 Submit Feedback won't actually do anything. 783 00:36:51,280 --> 00:36:52,950 It's just a button that we can press. 784 00:36:52,950 --> 00:36:56,994 But if we close, we'll see the modal get closed out. 785 00:36:56,994 --> 00:37:01,400 OK, that brings us to the end of kind of the structured portion 786 00:37:01,400 --> 00:37:02,990 of our conversation. 787 00:37:02,990 --> 00:37:08,720 As we wrap up, just wanted to touch on 2 or 2 and 1/2 really good resources 788 00:37:08,720 --> 00:37:10,580 to learn more about this if you want. 789 00:37:10,580 --> 00:37:14,096 So the place where you can learn everything 790 00:37:14,096 --> 00:37:15,970 you want to know about Bootstrap, in addition 791 00:37:15,970 --> 00:37:17,928 Claire's awesome seminar from a couple of years 792 00:37:17,928 --> 00:37:20,520 ago, is just in the Bootstrap documentation. 793 00:37:20,520 --> 00:37:24,910 So if you go to Documentation, you can go to Components. 794 00:37:24,910 --> 00:37:27,280 And then you can see everything you can implement 795 00:37:27,280 --> 00:37:30,310 in Bootstrap-- alerts, badges, breadcrumbs, buttons, all 796 00:37:30,310 --> 00:37:31,510 different sorts of things. 797 00:37:31,510 --> 00:37:33,940 If you just click on one of those, you will 798 00:37:33,940 --> 00:37:36,310 see what different stylings you can apply 799 00:37:36,310 --> 00:37:38,210 and what that will actually look like. 800 00:37:38,210 --> 00:37:41,919 So essentially, this documentation is a massive repository of classes 801 00:37:41,919 --> 00:37:44,210 that you can apply to different elements to style them. 802 00:37:44,210 --> 00:37:46,570 All right, so if you want a yellow button, 803 00:37:46,570 --> 00:37:49,164 you'll set it to be btn, which would make it look pretty. 804 00:37:49,164 --> 00:37:52,330 And then you'll set it to btn-warning, which will fill it inside with yellow 805 00:37:52,330 --> 00:37:55,580 and make sure that the text is appropriate because we don't want, 806 00:37:55,580 --> 00:37:57,890 for example, white on yellow text. 807 00:37:57,890 --> 00:38:00,070 OK, two additional resources that I think 808 00:38:00,070 --> 00:38:02,260 were very, very helpful with this-- 809 00:38:02,260 --> 00:38:05,710 first, the Bootstrap 4 Tutorial on W3Schools, 810 00:38:05,710 --> 00:38:09,227 you can get all of the examples, all of the content. 811 00:38:09,227 --> 00:38:12,310 And this would show you how to implement that with much more interactivity 812 00:38:12,310 --> 00:38:14,440 than just the Bootstrap documentation. 813 00:38:14,440 --> 00:38:16,900 And then the jQuery tutorial-- all right, essentially, 814 00:38:16,900 --> 00:38:21,370 kind of all we're doing is writing jQuery, but in a special way 815 00:38:21,370 --> 00:38:24,190 that allows us to reference the HTML elements and the Bootstrap 816 00:38:24,190 --> 00:38:25,490 that we had before. 817 00:38:25,490 --> 00:38:31,840 So two really great tutorials in terms of Bootstrap 4 and jQuery on W3Schools. 818 00:38:31,840 --> 00:38:35,170 And then if you just want references for Bootstrap specifically, 819 00:38:35,170 --> 00:38:38,700 you can always go back to the Bootstrap documentation. 820 00:38:38,700 --> 00:38:39,374 OK, awesome. 821 00:38:39,374 --> 00:38:40,540 So I think that wraps us up. 822 00:38:40,540 --> 00:38:43,902 Of course, happy to chat about any questions, 823 00:38:43,902 --> 00:38:45,610 how to see this kind of more in practice, 824 00:38:45,610 --> 00:38:47,860 how this might apply to final projects. 825 00:38:47,860 --> 00:38:50,370 If not, thanks so much for coming.