1 00:00:00,000 --> 00:00:02,000 [Seminar] [JavaScript Frameworks: Why and How?] 2 00:00:02,000 --> 00:00:04,000 [Kevin Schmid] [Harvard University] 3 00:00:04,000 --> 00:00:06,960 [This is CS50.] [CS50.TV] 4 00:00:06,960 --> 00:00:10,630 >> Hi, everybody. Welcome to the JavaScript Frameworks seminar. 5 00:00:10,630 --> 00:00:14,910 My name is Kevin, and today I'm going to be talking about JavaScript frameworks, 6 00:00:14,910 --> 00:00:20,400 and the goal of this seminar is not to get you to, say, master a particular framework per se 7 00:00:20,400 --> 00:00:23,810 but to give you a broad introduction to a couple of frameworks 8 00:00:23,810 --> 00:00:27,150 and show why we would ever want to use a framework. 9 00:00:27,150 --> 00:00:31,060 >> Before I do that, I'll provide a little background in JavaScript, 10 00:00:31,060 --> 00:00:33,750 and then we'll take it from there. 11 00:00:33,750 --> 00:00:36,270 We're going to start by implementing a to-do list. 12 00:00:36,270 --> 00:00:39,330 Here's our task list for today. 13 00:00:39,330 --> 00:00:41,990 It's kind of funny. We have to implement a to-do list in JavaScript. 14 00:00:41,990 --> 00:00:45,110 This is what it's going to look like, so that's our first goal. 15 00:00:45,110 --> 00:00:47,160 We're not going to use a framework to do that. 16 00:00:47,160 --> 00:00:51,930 We're going to code JavaScript and get the to-do list to work. 17 00:00:51,930 --> 00:00:54,370 Then we're going to improve the design without using a framework. 18 00:00:54,370 --> 00:00:57,190 We're going to discuss various things we can do with just JavaScript alone 19 00:00:57,190 --> 00:01:00,650 to make our to-do list a little more well designed. 20 00:01:00,650 --> 00:01:02,490 Then we're going to throw in some jQuery, 21 00:01:02,490 --> 00:01:05,030 and then we're going to look at the same to-do list, 22 00:01:05,030 --> 00:01:07,170 just implemented in different frameworks, and we'll discuss 23 00:01:07,170 --> 00:01:09,280 the pros and cons along the way. 24 00:01:09,280 --> 00:01:12,040 >> Let's start implementing that to-do list. 25 00:01:12,040 --> 00:01:14,270 Let's say we're given this HTML. 26 00:01:14,270 --> 00:01:16,620 I'm going to make this a little smaller. 27 00:01:16,620 --> 00:01:19,300 As you can see, I have a little header that says Todo 28 00:01:19,300 --> 00:01:21,740 and a little box where I can enter a description of a todo 29 00:01:21,740 --> 00:01:26,990 and then a new item button, so let's try to enter a new todo to this list. 30 00:01:26,990 --> 00:01:31,000 Give a JavaScript frameworks seminar, 31 00:01:31,000 --> 00:01:33,090 and I'm to hit new item. 32 00:01:33,090 --> 00:01:35,730 I get this JavaScript alert that says implement me. 33 00:01:35,730 --> 00:01:37,560 We've got to implement it. 34 00:01:37,560 --> 00:01:41,490 Let's check out the code for this, both the HTML and the JavaScript. 35 00:01:41,490 --> 00:01:43,260 Here's our HTML. 36 00:01:43,260 --> 00:01:45,500 As you can see here, here's our little Todos header. 37 00:01:45,500 --> 00:01:47,620 That was that bold thing at the top, 38 00:01:47,620 --> 00:01:50,690 and then we have the input box with the placeholder, 39 00:01:50,690 --> 00:01:59,460 and then there's a certain attribute of this button that calls this function addTodo. 40 00:01:59,460 --> 00:02:05,460 Does anybody want to guess what that on click is signifying? 41 00:02:05,460 --> 00:02:07,390 [Student inaudible response] 42 00:02:07,390 --> 00:02:09,289 Good, the on click is sort of like an event, 43 00:02:09,289 --> 00:02:12,120 like clicking the mouse is just an event, and what we're doing 44 00:02:12,120 --> 00:02:16,890 is we're tying the event of clicking this button to execute that function. 45 00:02:16,890 --> 00:02:21,700 AddTodo is this event handler for clicking that button. 46 00:02:21,700 --> 00:02:25,010 >> As you can see, when I click the new item button 47 00:02:25,010 --> 00:02:29,940 the on click event gets fired, and this function gets called. 48 00:02:29,940 --> 00:02:33,170 Let's look at function. 49 00:02:33,170 --> 00:02:36,260 As you can see, here's my JavaScript code so far. 50 00:02:36,260 --> 00:02:41,280 What I have at the top is a global data structure for my to-do list. 51 00:02:41,280 --> 00:02:44,060 It looks like an array. It's just an empty array. 52 00:02:44,060 --> 00:02:47,100 And then I have the addTodo function that we saw earlier, 53 00:02:47,100 --> 00:02:50,740 and the only line of code in there is this alert. 54 00:02:50,740 --> 00:02:55,730 It alerts implement me, and then I have 2 tasks at hand. 55 00:02:55,730 --> 00:02:58,790 I have to add the todo to that global data structure, 56 00:02:58,790 --> 00:03:01,860 and then I want to draw out the to-do list. 57 00:03:01,860 --> 00:03:06,360 Nothing too fancy just yet, but JavaScript you may be unfamiliar with, 58 00:03:06,360 --> 00:03:12,370 so I'm going to go slow and review the fundamentals of JavaScript in that way. 59 00:03:12,370 --> 00:03:15,490 >> Let's give this a shot. 60 00:03:15,490 --> 00:03:21,130 Let's say the user enters something in this box. 61 00:03:21,130 --> 00:03:23,360 I just typed something in here, text. 62 00:03:23,360 --> 00:03:27,620 How do I sort of access that text through JavaScript? 63 00:03:27,620 --> 00:03:32,500 Remember that JavaScript, one of its fundamental features is that it gives us 64 00:03:32,500 --> 00:03:34,670 this programmatic access to the DOM. 65 00:03:34,670 --> 00:03:40,670 It allows us to access elements and their properties of this actual HTML. 66 00:03:40,670 --> 00:03:43,430 The way we do that with bare bones JavaScript 67 00:03:43,430 --> 00:03:51,360 is we can actually use a function in JavaScript called getElementByID. 68 00:03:51,360 --> 00:03:55,140 I want to store the text that's typed there in some variable, 69 00:03:55,140 --> 00:03:58,350 so I'm going to say a new variable called new_todo, 70 00:03:58,350 --> 00:04:01,980 and I'm going to get that element. 71 00:04:01,980 --> 00:04:06,330 This is a function, .getElementByID. 72 00:04:06,330 --> 00:04:11,580 And now I'm getting an element by ID, so I need the ID of that text box, 73 00:04:11,580 --> 00:04:15,860 so I've given it the ID new_todo_description. 74 00:04:15,860 --> 00:04:18,399 That's how I'm going to get an element. 75 00:04:18,399 --> 00:04:23,880 That's my argument to this function, to specify which ID to get. 76 00:04:23,880 --> 00:04:28,110 And so that's an element in HTML, and it has properties. 77 00:04:28,110 --> 00:04:30,650 You've seen these. They're attributes. 78 00:04:30,650 --> 00:04:37,090 The attribute of the text element that stores the user's input is called value. 79 00:04:37,090 --> 00:04:40,860 I saved the value of that text box now in this variable called new_todo. 80 00:04:40,860 --> 00:04:45,040 Now I have programmatic access to this variable, which is kind of cool 81 00:04:45,040 --> 00:04:49,200 because now what I can do is I can add it to my to-do list. 82 00:04:49,200 --> 00:04:52,870 >> The way we would do this in JavaScript—and don't worry if you're unfamiliar with this, 83 00:04:52,870 --> 00:04:57,010 but just going through it is todos.push 84 00:04:57,010 --> 00:05:00,130 because that's the name of my global data structure up here, 85 00:05:00,130 --> 00:05:04,450 and I'm going to push new_todo. 86 00:05:04,450 --> 00:05:09,120 This is great because now I have added it to my JavaScript 87 00:05:09,120 --> 00:05:11,280 representation of that to-do list. 88 00:05:11,280 --> 00:05:15,170 But now how do I get it back to the HTML? 89 00:05:15,170 --> 00:05:18,560 I have to find a way to sort of push it back. 90 00:05:18,560 --> 00:05:21,830 In other words, I kind of have to draw this. 91 00:05:21,830 --> 00:05:26,060 What we're going to do is we're going to draw the to-do list. 92 00:05:26,060 --> 00:05:29,270 I need to update other HTML on that page, 93 00:05:29,270 --> 00:05:32,040 and as you can see, I've left this little container here, 94 00:05:32,040 --> 00:05:36,840 this divider of the page whose ID is todos, 95 00:05:36,840 --> 00:05:40,870 and I'm going to put the to-do list there. 96 00:05:40,870 --> 00:05:47,240 First I'm going to clear it out because, say, there was an old to-do list there. 97 00:05:47,240 --> 00:05:49,560 I'm getting that element by ID again, 98 00:05:49,560 --> 00:05:54,530 and I'm accessing the inner HTML of that element, 99 00:05:54,530 --> 00:05:58,010 and I'm going to clear that. 100 00:05:58,010 --> 00:06:05,510 If we left this code as is, we'd see a blank nothing there, 101 00:06:05,510 --> 00:06:10,410 and now I want to start rendering my new to-do list. 102 00:06:10,410 --> 00:06:12,870 I'm basically going to wipe out my to-do list. 103 00:06:12,870 --> 00:06:18,180 >> Now the inner HTML inside of that todos div is completely clear, 104 00:06:18,180 --> 00:06:20,060 and now I need to start adding my list. 105 00:06:20,060 --> 00:06:23,890 The first thing I want to add back is the unordered list tag, 106 00:06:23,890 --> 00:06:33,890 which basically denotes that this is the start of an unordered list. 107 00:06:33,890 --> 00:06:39,770 Now for every element in my todos array I want to print it out inside of that HTML. 108 00:06:39,770 --> 00:06:43,710 I want to append it on to the bottom of this list. 109 00:06:43,710 --> 00:06:49,040 Just like in C, I can use a for loop, and I'm going to start at the beginning of my list 110 00:06:49,040 --> 00:06:54,140 at element 0, and I'm going to go all the way to the length of the list. 111 00:06:54,140 --> 00:07:01,100 We can actually get the length of an array in JavaScript using the length property. 112 00:07:01,100 --> 00:07:03,420 Basically I'm going to do something very similar inside of here 113 00:07:03,420 --> 00:07:05,600 to print out that element. 114 00:07:05,600 --> 00:07:12,970 I can again access the todos div, the inner HTML property of that, 115 00:07:12,970 --> 00:07:17,560 and I'm going to add on this new list item, and that's going to be surrounded by 116 00:07:17,560 --> 00:07:25,390 this li tag, and I'm going to concatenate with the + operator, 117 00:07:25,390 --> 00:07:28,040 and that's the ith element of my todos array, 118 00:07:28,040 --> 00:07:32,380 and then I'm going to close that tag. 119 00:07:32,380 --> 00:07:36,240 Now for every element we'll add a new list entry. 120 00:07:36,240 --> 00:07:48,700 And then all we really need to do is close off that tag. 121 00:07:48,700 --> 00:07:52,820 I just need to close off that unordered list tag. 122 00:07:52,820 --> 00:07:55,490 >> Do you get a feel for how that works? 123 00:07:55,490 --> 00:07:57,700 This opens the entire list. 124 00:07:57,700 --> 00:08:01,080 This adds individual elements from the todos list to the list, 125 00:08:01,080 --> 00:08:05,470 and then that closes the entire list, and this is my addTodo function. 126 00:08:05,470 --> 00:08:09,590 I basically begin by getting the todo from the text box. 127 00:08:09,590 --> 00:08:18,950 I add that to the todos array, and then I re-render the to-do list. 128 00:08:18,950 --> 00:08:21,520 Now I can add items to my list. 129 00:08:21,520 --> 00:08:24,620 This is kind of exciting because in just a few lines of code 130 00:08:24,620 --> 00:08:28,240 we've basically made a to-do list where we can add items. 131 00:08:28,240 --> 00:08:30,050 Great. 132 00:08:30,050 --> 00:08:34,480 That's kind of a basic introduction to JavaScript. 133 00:08:34,480 --> 00:08:36,179 Don't worry too much about the syntax for now, 134 00:08:36,179 --> 00:08:38,130 but think about this conceptually. 135 00:08:38,130 --> 00:08:40,539 We had some HTML. 136 00:08:40,539 --> 00:08:45,310 We had a text box on the page that basically allowed users to input a to-do item to add. 137 00:08:45,310 --> 00:08:49,210 And then we used JavaScript to fetch that todo from that text box. 138 00:08:49,210 --> 00:08:52,830 We stored that inside a JavaScript array, which is basically like 139 00:08:52,830 --> 00:08:56,010 our programmatic representation of that to-do list, 140 00:08:56,010 --> 00:08:59,060 and then we printed it out. 141 00:08:59,060 --> 00:09:02,690 This is todos.js. 142 00:09:02,690 --> 00:09:07,620 >> This is kind of cool, but how can we take this further? 143 00:09:07,620 --> 00:09:11,350 Well, as you can see, this is not like a complete to-do list. 144 00:09:11,350 --> 00:09:15,100 For example, I can't mark any of these items as incomplete, 145 00:09:15,100 --> 00:09:19,920 like if I wanted to reprioritize the items or delete items. 146 00:09:19,920 --> 00:09:23,150 This is okay, but we can take this further. 147 00:09:23,150 --> 00:09:29,280 I'm not going to talk too much about adding extra features, 148 00:09:29,280 --> 00:09:32,800 but we could take that further. 149 00:09:32,800 --> 00:09:35,970 Let's talk about adding one more feature to this to-do list, 150 00:09:35,970 --> 00:09:40,370 which is going to be being able to check an individual to-do item 151 00:09:40,370 --> 00:09:44,780 and have it be crossed out, so basically saying I've done this. 152 00:09:44,780 --> 00:09:50,240 Let's look at some code that could accomplish that. 153 00:09:50,240 --> 00:09:52,740 Notice what I've done at the top is I've added 154 00:09:52,740 --> 00:09:57,620 a new global array called complete. 155 00:09:57,620 --> 00:10:02,890 I'm basically using this to store whether the items on the to-do list 156 00:10:02,890 --> 00:10:06,560 are complete or not. 157 00:10:06,560 --> 00:10:08,470 This is one way to do this. 158 00:10:08,470 --> 00:10:13,750 If I look at the implementation of this, the display, 159 00:10:13,750 --> 00:10:21,120 basically if I enter a todo and I press this toggle button 160 00:10:21,120 --> 00:10:25,040 it crosses out, so every item on this list has either a complete 161 00:10:25,040 --> 00:10:31,050 or incomplete state, and I'm using another array to represent that. 162 00:10:31,050 --> 00:10:33,730 >> Basically for every todo in that todos array 163 00:10:33,730 --> 00:10:37,110 there's an item in the complete array that basically indicates 164 00:10:37,110 --> 00:10:39,060 whether that is complete or not. 165 00:10:39,060 --> 00:10:41,640 I've had to make pretty minimal changes to this code, 166 00:10:41,640 --> 00:10:44,470 so here's our addTodo function. 167 00:10:44,470 --> 00:10:48,530 Notice that here I'm pushing it onto the array, 168 00:10:48,530 --> 00:10:51,300 and then I'm pushing a 0 to that complete array, 169 00:10:51,300 --> 00:10:57,090 basically in parallel with that new todo push to say 170 00:10:57,090 --> 00:11:00,430 I'm adding this item, and it's coupled with this value, 171 00:11:00,430 --> 00:11:02,810 which means that it's incomplete. 172 00:11:02,810 --> 00:11:04,970 And then I'm redrawing the to-do list. 173 00:11:04,970 --> 00:11:09,220 Now, notice I've added this drawTodoList function. 174 00:11:09,220 --> 00:11:11,760 This takes a lot of the code we had before, 175 00:11:11,760 --> 00:11:15,320 basically clears out the box and then draws the new to-do list. 176 00:11:15,320 --> 00:11:19,620 But notice that inside of this for loop we're doing a little more now. 177 00:11:19,620 --> 00:11:25,000 We're basically checking whether the item corresponding to the ith todo here 178 00:11:25,000 --> 00:11:30,220 is complete, and we're behaving differently in these 2 circumstances. 179 00:11:30,220 --> 00:11:32,790 If it's complete, we're adding this del tag, 180 00:11:32,790 --> 00:11:35,360 which is basically the way you can get that strike through effect 181 00:11:35,360 --> 00:11:38,190 crossing out the to-do list if it's complete, 182 00:11:38,190 --> 00:11:42,200 and if it's not, we're not including it. 183 00:11:42,200 --> 00:11:45,030 And so that kind of takes care of that, 184 00:11:45,030 --> 00:11:49,140 >> and that's one way to accomplish this. 185 00:11:49,140 --> 00:11:53,420 And then notice when the user clicks one of these 186 00:11:53,420 --> 00:11:56,780 we toggle the completion status of it. 187 00:11:56,780 --> 00:12:02,170 When the user clicks, we'll reverse whether it's been completed or not, 188 00:12:02,170 --> 00:12:04,540 and then we'll redraw it. 189 00:12:04,540 --> 00:12:06,190 This kind of works. 190 00:12:06,190 --> 00:12:09,860 We have these functions that carry out their own tasks, 191 00:12:09,860 --> 00:12:11,730 and this is okay. 192 00:12:11,730 --> 00:12:14,110 Is there anything we could do better about this, though? 193 00:12:14,110 --> 00:12:18,700 Notice we have these 2 global arrays. 194 00:12:18,700 --> 00:12:23,550 If this was C, and we had 2 arrays that kind of represented 195 00:12:23,550 --> 00:12:25,800 data that was sort of related in some way 196 00:12:25,800 --> 00:12:30,140 what would we use in C to combine these 2 fields 197 00:12:30,140 --> 00:12:35,420 into something that encapsulates both pieces of information? 198 00:12:35,420 --> 00:12:37,600 Anybody want to make a suggestion? 199 00:12:37,600 --> 00:12:39,450 [Student inaudible response] 200 00:12:39,450 --> 00:12:42,340 >> Exactly, so we could use some kind of struct, 201 00:12:42,340 --> 00:12:44,960 and if you think back to, say, pset 3, 202 00:12:44,960 --> 00:12:47,350 remember we had dictionary, and then we had whether the word 203 00:12:47,350 --> 00:12:50,230 was in the dictionary, and all that information was put together 204 00:12:50,230 --> 00:12:52,420 inside of some data structure. 205 00:12:52,420 --> 00:12:56,390 One thing I can do with this code to avoid having these 2 different arrays 206 00:12:56,390 --> 00:13:01,760 for similar pieces of information is I can combine them into a JavaScript object. 207 00:13:01,760 --> 00:13:07,150 Let's take a look at that. 208 00:13:07,150 --> 00:13:11,740 Notice I only have one array at the top now 209 00:13:11,740 --> 00:13:17,650 and what I've done is—and this is just the JavaScript syntax for sort of 210 00:13:17,650 --> 00:13:21,350 creating a literal version of an object, 211 00:13:21,350 --> 00:13:24,670 and notice there are 2 properties, so we have the todo, 212 00:13:24,670 --> 00:13:29,660 and it's kept together with whether it's complete or incomplete. 213 00:13:29,660 --> 00:13:31,000 This is very similar code. 214 00:13:31,000 --> 00:13:35,310 We're using the JavaScript objects. 215 00:13:35,310 --> 00:13:38,600 This kind of improves things. 216 00:13:38,600 --> 00:13:43,850 Like now, all these fields of related information are kept together. 217 00:13:43,850 --> 00:13:46,410 When we go to print it out, we can access the fields. 218 00:13:46,410 --> 00:13:49,060 >> Notice how we're doing todos[i].complete 219 00:13:49,060 --> 00:13:52,880 instead of checking the complete array separately, 220 00:13:52,880 --> 00:13:56,560 and notice when we want to get the to-do string we're getting the to-do property 221 00:13:56,560 --> 00:13:58,750 of that todo, so this kind of makes sense because 222 00:13:58,750 --> 00:14:01,660 every item has these intrinsic properties about it. 223 00:14:01,660 --> 00:14:05,650 It has a todo, and it has whether it's complete or not. 224 00:14:05,650 --> 00:14:11,540 Not too many changes there functionally, just added some more to the code. 225 00:14:11,540 --> 00:14:13,430 This is an improvement on some fronts, right? 226 00:14:13,430 --> 00:14:16,030 I mean, we factored out the design a bit. 227 00:14:16,030 --> 00:14:20,350 Now we have objects to basically encapsulate this data. 228 00:14:20,350 --> 00:14:27,130 Is there anything more we could do from here in terms of JavaScript? 229 00:14:27,130 --> 00:14:31,810 Like notice that this code right here 230 00:14:31,810 --> 00:14:34,760 for getting the inner HTML of a div 231 00:14:34,760 --> 00:14:40,520 is a little, I guess, long. 232 00:14:40,520 --> 00:14:45,100 There's document.getElementByID("todos").innerHTML. 233 00:14:45,100 --> 00:14:48,400 One thing we could do to make this code look a little friendlier 234 00:14:48,400 --> 00:14:51,450 so I wouldn't have to keep scrolling left and right, back and forth, 235 00:14:51,450 --> 00:14:58,480 is I could use a library like jQuery. 236 00:14:58,480 --> 00:15:02,710 >> Let's check out Seminar 2, 237 00:15:02,710 --> 00:15:05,880 and this is the same code, but it's done with jQuery. 238 00:15:05,880 --> 00:15:08,790 You may not be too familiar with jQuery, 239 00:15:08,790 --> 00:15:11,510 but just know that jQuery is sort of a library for JavaScript 240 00:15:11,510 --> 00:15:15,910 that makes it easier to do things like access individual elements of the DOM. 241 00:15:15,910 --> 00:15:21,280 Here instead of saying document.getElementByID("todos").innerHTML 242 00:15:21,280 --> 00:15:25,210 I can use the much cleaner way in jQuery, 243 00:15:25,210 --> 00:15:28,490 which is just to use selectors. 244 00:15:28,490 --> 00:15:31,300 As you can see, this code did get a little cleaner, 245 00:15:31,300 --> 00:15:35,770 very similar functionally, but that's the idea. 246 00:15:35,770 --> 00:15:37,980 We've seen a couple of things so far, 247 00:15:37,980 --> 00:15:42,010 so we started with just raw JavaScript implementation. 248 00:15:42,010 --> 00:15:45,370 We added new features and showed how we can improve it with 249 00:15:45,370 --> 00:15:49,090 just what we have in JavaScript. 250 00:15:49,090 --> 00:15:53,300 >> Does anybody see any difficulties with this design? 251 00:15:53,300 --> 00:16:01,090 Namely, I guess—or not necessarily difficulties but let's say 252 00:16:01,090 --> 00:16:04,830 we weren't doing a to-do list project, and tomorrow we decided 253 00:16:04,830 --> 00:16:10,320 we wanted to make a grocery list or a shopping list project. 254 00:16:10,320 --> 00:16:14,150 A lot of these features are very similar. 255 00:16:14,150 --> 00:16:19,080 A lot of the things we want to get out of JavaScript are very common, 256 00:16:19,080 --> 00:16:23,820 and this underscores the need for some kind of way of 257 00:16:23,820 --> 00:16:25,670 making this easier to do. 258 00:16:25,670 --> 00:16:30,400 I had to build up all of this HTML access, all this DOM access, 259 00:16:30,400 --> 00:16:35,530 like I'm going to represent the to-do list with this model. 260 00:16:35,530 --> 00:16:39,130 And notice I'm responsible as the JavaScript developer 261 00:16:39,130 --> 00:16:42,890 for keeping the HTML and JavaScript that I have in sync. 262 00:16:42,890 --> 00:16:48,040 Nothing automatically made that JavaScript representation 263 00:16:48,040 --> 00:16:51,590 or the to-do list get pushed out to HTML. 264 00:16:51,590 --> 00:16:54,000 Nothing enforced that except for me. 265 00:16:54,000 --> 00:16:56,880 I had to write the draw to-do list function. 266 00:16:56,880 --> 00:17:01,650 And that may not be—I mean, it's reasonable to do that, 267 00:17:01,650 --> 00:17:03,670 but it may be tedious sometimes. 268 00:17:03,670 --> 00:17:08,190 If you have a larger project, that could be difficult. 269 00:17:08,190 --> 00:17:10,720 >> Frameworks, one of the purposes of frameworks 270 00:17:10,720 --> 00:17:14,060 is to simplify that process and sort of factor out 271 00:17:14,060 --> 00:17:16,950 these common—I guess you could say—design patterns 272 00:17:16,950 --> 00:17:20,700 that people generally have some kind of way of representing data, 273 00:17:20,700 --> 00:17:25,599 whether that's a friends list, whether that's map information 274 00:17:25,599 --> 00:17:27,280 or something or a to-do list. 275 00:17:27,280 --> 00:17:30,660 Some people have generally a way of representing information, 276 00:17:30,660 --> 00:17:33,650 and they generally need to keep that information sort of in sync 277 00:17:33,650 --> 00:17:36,520 between what the user sees in some kind of view, 278 00:17:36,520 --> 00:17:39,850 speaking in terms of like the model view controller that you saw in lecture, 279 00:17:39,850 --> 00:17:45,400 and then the model, which in this case is this JavaScript array. 280 00:17:45,400 --> 00:17:49,020 Frameworks give us a way to solve that problem. 281 00:17:49,020 --> 00:17:53,080 Now let's take a look at the implementation of this to-do list 282 00:17:53,080 --> 00:18:02,360 in a framework called angularjs. 283 00:18:02,360 --> 00:18:04,650 This is it. Notice it fits on a slide. 284 00:18:04,650 --> 00:18:07,330 I don't have to scroll to the left and right. 285 00:18:07,330 --> 00:18:10,460 That probably isn't a great reason to recommend using a framework, 286 00:18:10,460 --> 00:18:20,120 but notice am I ever accessing individual HTML elements here? 287 00:18:20,120 --> 00:18:22,400 Am I ever going into the DOM? 288 00:18:22,400 --> 00:18:26,120 Do you see any document.getElementByID or something like that? 289 00:18:26,120 --> 00:18:29,870 No, that's gone. 290 00:18:29,870 --> 00:18:35,590 >> Angular helps us keep the DOM and our JavaScript representation of something 291 00:18:35,590 --> 00:18:40,430 kind of in sync, so if it's not in the js file, 292 00:18:40,430 --> 00:18:46,790 if there's no way of programmatically getting to all that HTML content 293 00:18:46,790 --> 00:18:51,800 from the JavaScript how are we keeping this in sync? 294 00:18:51,800 --> 00:18:58,160 If it's not in the .js file, it's got to be in HTML, right? 295 00:18:58,160 --> 00:19:01,910 This is the new version of the HTML file, 296 00:19:01,910 --> 00:19:04,660 and notice we've added a lot here. 297 00:19:04,660 --> 00:19:11,110 Notice there's these new attributes that say ng-click and ng-repeat. 298 00:19:11,110 --> 00:19:15,650 Angular's approach to solving this problem of difficulties in design 299 00:19:15,650 --> 00:19:19,130 is to basically make HTML much more powerful. 300 00:19:19,130 --> 00:19:24,420 Angular is a way of allowing you to make HTML somewhat more expressive. 301 00:19:24,420 --> 00:19:30,520 For example, I can say that I'm going to tie or bind this text box 302 00:19:30,520 --> 00:19:35,080 to a variable within my Angular JavaScript code. 303 00:19:35,080 --> 00:19:37,030 This ng-model does just that. 304 00:19:37,030 --> 00:19:41,550 That basically says that the item inside of this text box, 305 00:19:41,550 --> 00:19:45,000 just associate that with the variable new_todo_description 306 00:19:45,000 --> 00:19:47,870 within the JavaScript code. 307 00:19:47,870 --> 00:19:51,600 That's very powerful because I don't have to explicitly go to 308 00:19:51,600 --> 00:19:53,310 the DOM to get that information. 309 00:19:53,310 --> 00:19:56,250 I don't have to say document.getElementByID. 310 00:19:56,250 --> 00:19:58,750 I don't have to use jQueries like DOM access. 311 00:19:58,750 --> 00:20:03,280 I can associate it with a variable, and then when I change that variable 312 00:20:03,280 --> 00:20:07,400 within JavaScript it's kept in sync with the HTML, 313 00:20:07,400 --> 00:20:11,640 so that simplifies the process of having to go back and forth between the two. 314 00:20:11,640 --> 00:20:18,260 Does that make sense? 315 00:20:18,260 --> 00:20:22,060 >> And notice there's no HTML access code. 316 00:20:22,060 --> 00:20:27,760 We've just made HTML more powerful, 317 00:20:27,760 --> 00:20:32,070 and now, for example, we can do things like this, 318 00:20:32,070 --> 00:20:38,610 like when you click on this, call this function within the scope of todos.js, 319 00:20:38,610 --> 00:20:43,410 and we could do that before, but there are other things, like this ng-model, 320 00:20:43,410 --> 00:20:47,020 and notice this ng-repeat. 321 00:20:47,020 --> 00:20:51,520 What do you think this does? 322 00:20:51,520 --> 00:20:54,390 Here's our unordered list from before. 323 00:20:54,390 --> 00:20:56,470 We have the ul tags, 324 00:20:56,470 --> 00:21:03,710 but am I ever rendering that list inside of the JavaScript code? 325 00:21:03,710 --> 00:21:09,280 I'm not ever explicitly rendering that list. 326 00:21:09,280 --> 00:21:11,580 How does this work? 327 00:21:11,580 --> 00:21:16,410 Well, the way Angular accomplishes this is this is called a repeater. 328 00:21:16,410 --> 00:21:22,760 Basically this says that I want to print this HTML 329 00:21:22,760 --> 00:21:26,240 for every todo inside of my todos array. 330 00:21:26,240 --> 00:21:31,850 Inside of todos.jr there is a todos array right here, 331 00:21:31,850 --> 00:21:37,910 and this will tell Angular go through that array, and for every element you see 332 00:21:37,910 --> 00:21:41,390 I want you to print this HTML. 333 00:21:41,390 --> 00:21:44,620 This is kind of awesome because I can just do this 334 00:21:44,620 --> 00:21:47,760 without having to write a for loop, 335 00:21:47,760 --> 00:21:52,250 which for a to-do list that was only 30 lines of code 336 00:21:52,250 --> 00:21:54,700 may not be the most beneficial thing, 337 00:21:54,700 --> 00:22:01,240 but if you have a large project, this could get very convenient. 338 00:22:01,240 --> 00:22:06,100 >> This is one solution to this problem, making HTML more powerful, 339 00:22:06,100 --> 00:22:10,820 and that allows us to keep JavaScript and HTML in sync. 340 00:22:10,820 --> 00:22:13,220 There are other possible ways to solve this problem, 341 00:22:13,220 --> 00:22:15,320 and not every framework does this. 342 00:22:15,320 --> 00:22:17,720 Not every framework works along these lines. 343 00:22:17,720 --> 00:22:19,490 Some frameworks have different approaches, 344 00:22:19,490 --> 00:22:23,310 and you may find that you enjoy coding in one framework over the other. 345 00:22:23,310 --> 00:22:26,160 Let's look at one more. 346 00:22:26,160 --> 00:22:30,060 This is the to-do list coded up in a framework called Backbone. 347 00:22:30,060 --> 00:22:33,250 I'm going to go through this quickly. 348 00:22:33,250 --> 00:22:38,300 I'll start with the HTML before we go there. 349 00:22:38,300 --> 00:22:40,290 One second. 350 00:22:40,290 --> 00:22:43,950 Starting with the HTML, as you notice, our HTML is very similar 351 00:22:43,950 --> 00:22:50,000 to what it was before, so not too much new on that front. 352 00:22:50,000 --> 00:22:55,410 But our js file is a little different. 353 00:22:55,410 --> 00:23:00,360 Backbone kind of has this idea, or builds on the idea 354 00:23:00,360 --> 00:23:04,750 that a lot of what we do with, say, our JavaScript projects 355 00:23:04,750 --> 00:23:09,110 is think about models and collections of these models. 356 00:23:09,110 --> 00:23:12,510 This could be, for example, a photo and collections of photos, 357 00:23:12,510 --> 00:23:16,230 or the idea of a friend and collections of friends. 358 00:23:16,230 --> 00:23:20,700 And oftentimes when we're programming JavaScript applications 359 00:23:20,700 --> 00:23:25,340 we'll sort of represent the idea of having a collection of friends 360 00:23:25,340 --> 00:23:29,500 somehow in JavaScript, and Backbone gives us this layer 361 00:23:29,500 --> 00:23:33,040 on top of JavaScript's existing arrays and objects 362 00:23:33,040 --> 00:23:38,300 to do more powerful things with that more easily. 363 00:23:38,300 --> 00:23:41,870 >> Here I've defined a to-do model, 364 00:23:41,870 --> 00:23:44,630 and you don't have to worry too much about the syntax, 365 00:23:44,630 --> 00:23:48,730 but notice that what's one of the properties of this? 366 00:23:48,730 --> 00:23:53,190 It has a default field. 367 00:23:53,190 --> 00:23:56,640 Backbone allows me to specify already off the bat 368 00:23:56,640 --> 00:24:00,190 any new to-do that I create is going to have these defaults. 369 00:24:00,190 --> 00:24:04,100 Now I can customize this, but being able to specify the defaults 370 00:24:04,100 --> 00:24:07,220 is nice, and it's kind of convenient because this is not something that's like 371 00:24:07,220 --> 00:24:10,430 inherent in JavaScript, and now I don't have to explicitly 372 00:24:10,430 --> 00:24:12,430 say that the todos are incomplete. 373 00:24:12,430 --> 00:24:19,190 I can say right off the bat that todos are going to be marked as incomplete. 374 00:24:19,190 --> 00:24:21,300 Notice then what is this? 375 00:24:21,300 --> 00:24:25,520 Now I have a to-do list, and that's a collection. 376 00:24:25,520 --> 00:24:30,960 Notice the field associated with that says model todo. 377 00:24:30,960 --> 00:24:33,390 This is my way of telling Backbone that 378 00:24:33,390 --> 00:24:37,350 I'm going to be thinking about a collection of these individual todos. 379 00:24:37,350 --> 00:24:42,140 This is basically the model structure for my program. 380 00:24:42,140 --> 00:24:44,980 Here I have this idea of a collection, 381 00:24:44,980 --> 00:24:48,960 and basically the items contained in that collection are all going to be these todos, 382 00:24:48,960 --> 00:24:51,910 and that is very natural in this sense 383 00:24:51,910 --> 00:24:59,890 because I do have todos, and I have them in a collection. 384 00:24:59,890 --> 00:25:02,940 >> Let's look at a little more of this. 385 00:25:02,940 --> 00:25:05,900 Here is a Backbone view. 386 00:25:05,900 --> 00:25:08,890 The other thing that Backbone says is that 387 00:25:08,890 --> 00:25:14,660 a lot of the models that you're thinking about or even collections 388 00:25:14,660 --> 00:25:19,150 are going to need to have some way of being displayed. 389 00:25:19,150 --> 00:25:21,900 We need to render that to-do list, 390 00:25:21,900 --> 00:25:25,460 and wouldn't it be nice if we could provide for each model 391 00:25:25,460 --> 00:25:28,390 or associate with each model this view 392 00:25:28,390 --> 00:25:34,020 that allows us to I guess connect the two together? 393 00:25:34,020 --> 00:25:38,320 Whereas before we had to use a for loop that would run through 394 00:25:38,320 --> 00:25:41,130 every todo in our list and then print it out here 395 00:25:41,130 --> 00:25:44,650 we can basically connect it with this model. 396 00:25:44,650 --> 00:25:47,550 This is a to-do view. 397 00:25:47,550 --> 00:25:50,550 This is associated with the todo we found earlier. 398 00:25:50,550 --> 00:25:54,940 Now every todo is displayable or renderable 399 00:25:54,940 --> 00:25:56,960 by this to-do view. 400 00:25:56,960 --> 00:25:59,440 Notice some of the fields. 401 00:25:59,440 --> 00:26:05,880 What do you think this tagName is, tagName: li? 402 00:26:05,880 --> 00:26:09,790 Remember from before when we wanted to render a todo 403 00:26:09,790 --> 00:26:16,700 we would have to explicitly pair our todos with this li tag. 404 00:26:16,700 --> 00:26:21,080 Now we're saying that where this todo is going to live 405 00:26:21,080 --> 00:26:25,250 is going to be inside of an li tag. 406 00:26:25,250 --> 00:26:31,440 And now we're also associating events with our todos. 407 00:26:31,440 --> 00:26:34,320 >> Every todo has this one event. 408 00:26:34,320 --> 00:26:38,480 If you click pretty much the toggle button, that's what I'm saying there, 409 00:26:38,480 --> 00:26:43,080 then basically mark the todo as the opposite of what it was before 410 00:26:43,080 --> 00:26:45,890 and then re-render the application. 411 00:26:45,890 --> 00:26:47,810 This is kind of similar to the code before. 412 00:26:47,810 --> 00:26:50,730 Remember when we marked it as either the opposite or— 413 00:26:50,730 --> 00:26:52,410 and then we re-rendered it. 414 00:26:52,410 --> 00:26:57,750 But notice now this event used to be something that was in the HTML. 415 00:26:57,750 --> 00:26:59,640 It was sitting there. 416 00:26:59,640 --> 00:27:01,410 The button had an on click. 417 00:27:01,410 --> 00:27:05,310 When you click the button, it kind of does the stuff to 418 00:27:05,310 --> 00:27:07,210 set up that todo to be incomplete. 419 00:27:07,210 --> 00:27:11,180 Here we've associated that event of clicking that toggle button 420 00:27:11,180 --> 00:27:15,830 and reversing whether it's on or off with this view. 421 00:27:15,830 --> 00:27:20,480 >> This is a nice way of setting up this event so that it's very tightly bound 422 00:27:20,480 --> 00:27:26,980 to this view, and so notice this one more. 423 00:27:26,980 --> 00:27:31,050 I have this render method, and we don't have to go through the details. 424 00:27:31,050 --> 00:27:33,650 It's kind of similar to what we had before, 425 00:27:33,650 --> 00:27:36,070 but notice I'm not looping through anything. 426 00:27:36,070 --> 00:27:40,700 I'm not printing that ul tag that's sort of saying I'm going to print all of the elements. 427 00:27:40,700 --> 00:27:46,610 I'm providing the functionality for rendering this one to-do item. 428 00:27:46,610 --> 00:27:49,400 This is a very powerful concept because basically 429 00:27:49,400 --> 00:27:53,600 our to-do list consists of all these todos, and if we can basically specify 430 00:27:53,600 --> 00:27:56,890 the way to render one of those todos 431 00:27:56,890 --> 00:28:04,230 then we can have our powerful backbone per se render all of the todos 432 00:28:04,230 --> 00:28:07,760 by calling the render method on the individual todos. 433 00:28:07,760 --> 00:28:14,180 This is a concept that is useful here. 434 00:28:14,180 --> 00:28:18,160 Now a good question to ask is how is this application being put together? 435 00:28:18,160 --> 00:28:21,200 Because we have the ability to render one todo, 436 00:28:21,200 --> 00:28:23,860 but how do we get the idea of multiple todos? 437 00:28:23,860 --> 00:28:25,100 >> Let's take a look at that. 438 00:28:25,100 --> 00:28:27,100 This is the last part. 439 00:28:27,100 --> 00:28:29,740 Notice we have a to-do list view here, 440 00:28:29,740 --> 00:28:34,440 and notice it's also a view. 441 00:28:34,440 --> 00:28:36,970 And to go over a couple of things, 442 00:28:36,970 --> 00:28:45,280 this initialize method will be called when we first create this to-do list. 443 00:28:45,280 --> 00:28:52,630 As you can see, it's like creating the to-do list and associating it with this view. 444 00:28:52,630 --> 00:28:57,860 And then I added the functions here so basically when you add an item— 445 00:28:57,860 --> 00:29:01,440 this is similar to the addItem method we saw before— 446 00:29:01,440 --> 00:29:07,430 I'm going to create a new todo object, and notice I'm actually calling 447 00:29:07,430 --> 00:29:13,080 this new todo method, so this is provided by Backbone, 448 00:29:13,080 --> 00:29:16,010 and I can pass in my properties here. 449 00:29:16,010 --> 00:29:23,710 And now every todo that I create using this will get that functionality that we saw before. 450 00:29:23,710 --> 00:29:28,140 Notice I'm clearing out the text box before—a small little detail— 451 00:29:28,140 --> 00:29:32,900 and then I'm adding this collection. 452 00:29:32,900 --> 00:29:37,630 >> This almost seems weird because before we just had to do that todos.push, 453 00:29:37,630 --> 00:29:43,310 and then we were done, and this may seem more complicated for this particular project, 454 00:29:43,310 --> 00:29:46,980 and you may find that Backbone or even Angular or any other framework 455 00:29:46,980 --> 00:29:50,790 doesn't suit your particular project, but I think it's important to think about 456 00:29:50,790 --> 00:29:54,100 what this means on a larger scale for larger projects, 457 00:29:54,100 --> 00:29:56,610 because if we had a larger project where we were representing 458 00:29:56,610 --> 00:30:00,860 some really complex collection, something deeper than just a to-do list, 459 00:30:00,860 --> 00:30:04,490 let's say a friends list or something like that, this could come in handy 460 00:30:04,490 --> 00:30:09,620 because we could organize our code in a really convenient way, 461 00:30:09,620 --> 00:30:12,550 in a way that would make it easier for somebody else 462 00:30:12,550 --> 00:30:16,820 who wanted to pick up a project to build upon. 463 00:30:16,820 --> 00:30:21,450 You can see that this provides a lot of structure. 464 00:30:21,450 --> 00:30:26,580 And then I'm calling render on this addItem. 465 00:30:26,580 --> 00:30:31,050 Render, as you can see, and you don't have to grasp this full syntax, 466 00:30:31,050 --> 00:30:37,790 but basically for each model it's going to call the individual render method. 467 00:30:37,790 --> 00:30:41,500 That's sort of where this comes from. 468 00:30:41,500 --> 00:30:44,140 Let's just specify how to render the individual todos, 469 00:30:44,140 --> 00:30:47,310 and then let's glue them together as a whole. 470 00:30:47,310 --> 00:30:49,810 But this provides a way of abstraction, 471 00:30:49,810 --> 00:30:55,470 because I could change the way I decide to render the individual todos, 472 00:30:55,470 --> 00:30:57,940 and I wouldn't have to change any of this code. 473 00:30:57,940 --> 00:31:00,700 That's kind of cool. 474 00:31:00,700 --> 00:31:08,540 >> Does anybody have any questions about JavaScript frameworks? 475 00:31:08,540 --> 00:31:14,310 [Student inaudible question] 476 00:31:14,310 --> 00:31:16,050 Oh, sure, that's a great question. 477 00:31:16,050 --> 00:31:19,080 The question was how did I include the frameworks? 478 00:31:19,080 --> 00:31:22,970 Most JavaScript frameworks are basically just js files 479 00:31:22,970 --> 00:31:25,740 that you can include at the top of your code. 480 00:31:25,740 --> 00:31:29,830 Notice in the head portion of my HTML I have all these script tags, 481 00:31:29,830 --> 00:31:34,250 and the final script tag is the code that we've written. 482 00:31:34,250 --> 00:31:38,820 And then the 3 framework codes are just also script tags. 483 00:31:38,820 --> 00:31:42,110 I'm including them from what's called a CDN, 484 00:31:42,110 --> 00:31:46,200 which allows me to get it from somebody else at this point 485 00:31:46,200 --> 00:31:57,930 but every framework has this—you can pretty much find the content 486 00:31:57,930 --> 00:32:03,540 for a particular JavaScript library available on some CDN or something like that, 487 00:32:03,540 --> 00:32:05,570 and then you can include these script tags. 488 00:32:05,570 --> 00:32:07,600 Does that make sense? 489 00:32:07,600 --> 00:32:09,500 Cool. 490 00:32:09,500 --> 00:32:11,730 >> Those are 2 different approaches. 491 00:32:11,730 --> 00:32:14,640 Those are not the only approaches to solving this problem. 492 00:32:14,640 --> 00:32:17,080 There are many different things that 493 00:32:17,080 --> 00:32:19,490 somebody could do, and there are many frameworks out there. 494 00:32:19,490 --> 00:32:23,300 Angular and Backbone do not tell the whole story. 495 00:32:23,300 --> 00:32:26,370 Good luck with your final projects, and thank you very much. 496 00:32:31,960 --> 00:32:35,000 [CS50.TV]